diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..23a5e4f0b1f9fa09e0a45e584f31acc329274c64 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +__pycache__/ +*.pyc +*.pyo +*.pyd +.DS_Store diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..fe32c8d507084b2623888ab73431dc1dc018668c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,29 @@ +# Hugging Face Space Dockerfile +# Port PHẢI là 7860 theo yêu cầu của HuggingFace +FROM python:3.10-slim + +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential \ + && rm -rf /var/lib/apt/lists/* + +# Tạo user theo yêu cầu HuggingFace (UID 1000) +RUN useradd -m -u 1000 user +USER user +ENV HOME=/home/user \ + PATH=/home/user/.local/bin:$PATH \ + PYTHONUNBUFFERED=1 + +WORKDIR $HOME/app + +# Copy và cài requirements +COPY --chown=user requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# Copy toàn bộ code (không có .db files - dùng .dockerignore) +COPY --chown=user . . + +# Expose port 7860 bắt buộc +EXPOSE 7860 + +# Chạy qua script start_hf.sh để tải DB và cấu hình log +CMD ["/bin/bash", "start_hf.sh"] diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..b589c22172f1ee76dd68463d1a70bd56c357d0b1 --- /dev/null +++ b/README.md @@ -0,0 +1,88 @@ +--- +title: Tienhiep Backend +emoji: 📚 +colorFrom: indigo +colorTo: purple +sdk: docker +dockerfile: Dockerfile.hf +app_port: 7860 +pinned: false +--- + +# 📚 Tiên Hiệp AI (TienHiepAI) — Nền Tảng Đọc Truyện & Dịch Offline + +Chào mừng bạn đến với kho lưu trữ mã nguồn của dự án **Tiên Hiệp AI**. Đây là hệ thống tích hợp toàn diện bao gồm Giao diện Web, Ứng dụng Desktop (Electron), Máy chủ dịch thuật nâng cao và Động cơ chuyển đổi văn bản thành giọng nói (TTS) tiếng Việt ngoại tuyến chạy trên CPU cực nhanh. + +--- + +## 📂 Cấu Trúc Thư Mục Dự Án + +* 🖥️ **`frontend-web/`**: Mã nguồn giao diện chính viết bằng React + Vite. Hỗ trợ chạy chế độ Web và đóng gói Electron Desktop. +* 🎙️ **`TTS_ONNX_Deploy/`**: Động cơ chuyển giọng đọc (TTS) offline tiếng Việt đã được tối ưu hóa `int8` chạy trên CPU bằng ONNX Runtime (Matcha-TTS + Vocos). +* ⚙️ **`backend/`** & **`viewer_server.py`**: Mã nguồn máy chủ xử lý tác vụ dịch thuật (Vietphrase, ngữ cảnh nâng cao, từ điển Hán Việt, Trung-Việt) và lưu trữ lịch sử đọc truyện. +* 🛠️ **`scratch/`**: Các kịch bản phụ trợ để kiểm thử, vá lỗi động cơ, tự động hóa đóng gói và nạp cơ sở dữ liệu. + +--- + +## ⚡ Hướng Dẫn Chạy & Cài Đặt Nhanh (Quick Start) + +### 1. Chuẩn bị môi trường Python & Thư viện +Mã nguồn yêu cầu Python phiên bản từ `3.8` đến `3.10`. +Cài đặt toàn bộ các thư viện cần thiết bằng lệnh: +```bash +pip install -r requirements.txt +``` + +### 2. Tải các tệp Checkpoint mô hình ONNX +Các mô hình ONNX đã được lưu trữ trên Hugging Face. Để chạy động cơ TTS, hãy tải hai file sau về và đặt vào thư mục `TTS_ONNX_Deploy/`: +* 📥 [matcha_tts_int8.onnx](https://huggingface.co/datasets/Cong123779/Local-TTS-Engine/resolve/main/matcha_tts_int8.onnx) (19.23 MB) +* 📥 [vocos_decoupled_int8.onnx](https://huggingface.co/datasets/Cong123779/Local-TTS-Engine/resolve/main/vocos_decoupled_int8.onnx) (13.03 MB) + +Lệnh tải nhanh qua `curl` (chạy từ thư mục `TTS_ONNX_Deploy/`): +```bash +curl -L https://huggingface.co/datasets/Cong123779/Local-TTS-Engine/resolve/main/matcha_tts_int8.onnx --output matcha_tts_int8.onnx +curl -L https://huggingface.co/datasets/Cong123779/Local-TTS-Engine/resolve/main/vocos_decoupled_int8.onnx --output vocos_decoupled_int8.onnx +``` + +### 3. Chạy các máy chủ phát triển (Dev Mode) + +* **Chạy máy chủ Dịch thuật & Dữ liệu:** + ```bash + python viewer_server.py + ``` +* **Chạy máy chủ TTS Offline:** + ```bash + cd TTS_ONNX_Deploy + python api_server.py + ``` +* **Chạy giao diện Web (React):** + ```bash + cd frontend-web + npm install + npm run dev + ``` + +--- + +## 📦 Hướng Dẫn Đóng Gói Ứng Dụng (Release & Packaging) + +### A. Đóng gói ứng dụng Desktop (Electron Setup EXE / AppImage) +Sử dụng công cụ tự động hóa đóng gói và phát hành `release.py` (tự động tăng version, biên dịch giao diện, đóng gói đa nền tảng và đồng bộ lên database): +```bash +python release.py patch +``` + +### B. Đóng gói động cơ TTS chạy độc lập (`App_Doc_Truyen_Engine.exe`) +Sử dụng cấu hình PyInstaller đã được tối ưu hóa dung lượng (lọc bỏ PyTorch và các dependency cồng kềnh) để biên dịch động cơ TTS thành một file chạy duy nhất trên Windows: +```bash +cd TTS_ONNX_Deploy +pip install pyinstaller +pyinstaller App_Doc_Truyen_Engine.spec +``` +Sau khi chạy xong, thư mục đóng gói nằm tại `TTS_ONNX_Deploy/dist/App_Doc_Truyen_Engine/`. + +--- + +## 🛠️ Tính Năng Tự Động Vá Lỗi Vừa Được Cập Nhật +* **Isolate Espeak (Lazy Import)**: Đã cô lập hoàn toàn lõi espeak-ng. Ứng dụng khi chạy trên các máy Windows không cài espeak sẽ tự động chuyển sang chế độ fallback an toàn mà không bị crash. +* **Auto Engine Extract**: Ứng dụng Electron khi khởi động lần đầu sẽ tự động tải tệp nén động cơ `windows_cpu.zip` từ Hugging Face, giải nén và tự cấu hình kết nối. diff --git a/backend/__init__.py b/backend/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..b692732946622eb2cd3ed5fcefe6e55615505742 --- /dev/null +++ b/backend/__init__.py @@ -0,0 +1,212 @@ +import os +import logging +from flask import Flask, jsonify +from flask_cors import CORS +from werkzeug.middleware.proxy_fix import ProxyFix + +from backend.config import Config +from backend.database.db_manager import init_user_db, health_check +from backend.api import ( + auth_bp, books_bp, payment_bp, translate_bp, epub_bp, developer_bp, user_features_bp, sects_bp +) +from backend.api.monitoring import monitoring_bp + +logger = logging.getLogger("backend") + + +def create_app(): + """Flask Application Factory.""" + root_dir = Config.ROOT_DIR + app = Flask( + __name__, + static_folder=os.path.join(root_dir, "frontend-web", "dist"), + static_url_path="", + ) + + # Wrap with ProxyFix to handle reverse proxy headers + app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1) + + # ── Configuration ──────────────────────────────────────────────── + app.secret_key = Config.SECRET_KEY + app.config["MAX_CONTENT_LENGTH"] = 256 * 1024 * 1024 # 256MB + + # ── CORS ───────────────────────────────────────────────────────── + CORS(app, resources={ + r"/*": { + "origins": ["*"], + "allow_headers": ["Content-Type", "Authorization", "X-VIP-Code", "X-VIP-Key"], + "methods": ["GET", "POST", "OPTIONS", "DELETE", "PUT"], + "max_age": 86400 + } + }) + + # ── Register Blueprints ─────────────────────────────────────────── + app.register_blueprint(auth_bp) + app.register_blueprint(books_bp) + app.register_blueprint(payment_bp) + app.register_blueprint(translate_bp) + app.register_blueprint(epub_bp) + app.register_blueprint(developer_bp) + app.register_blueprint(user_features_bp) + app.register_blueprint(sects_bp) + app.register_blueprint(monitoring_bp) + + # ── Profiler & Latency Monitoring ───────────────────────────────── + from backend.core.profiler import setup_profiler + setup_profiler(app) + + # ── Frontend Route ─────────────────────────────────────────────── + @app.route("/") + def index(): + try: + return app.send_static_file("index.html") + except Exception: + return jsonify({"status": "healthy", "message": "Tienhiep API Backend is running."}) + + @app.errorhandler(404) + def page_not_found(e): + from flask import request + path = request.path.lstrip("/") + if path.startswith("api/") or path.startswith("assets/") or path.startswith("v1/") or path.startswith("health") or path.startswith("translate"): + return jsonify({"error": "Not Found"}), 404 + try: + return app.send_static_file("index.html") + except Exception: + return jsonify({"error": "Not Found"}), 404 + + # ── Health Check ──────────────────────────────────────────────── + @app.route("/health", methods=["GET"]) + def health_endpoint(): + status = health_check() + http_code = 200 if status["status"] in ("healthy", "degraded") else 503 + return jsonify(status), http_code + + # ── CORS & Security after-request headers ──────────────────────── + @app.after_request + def add_cors_headers(response): + from flask import request + origin = request.headers.get("Origin") + if origin: + response.headers["Access-Control-Allow-Origin"] = origin + response.headers["Access-Control-Allow-Credentials"] = "true" + response.headers["Access-Control-Max-Age"] = "86400" + + # Cho phép Cloudflare Cache luôn lệnh thăm dò OPTIONS (24h) + if request.method == "OPTIONS": + response.headers["Cache-Control"] = "public, max-age=86400" + response.headers["Access-Control-Allow-Headers"] = "Content-Type, Authorization, X-VIP-Code, X-VIP-Key" + response.headers["Access-Control-Allow-Methods"] = "GET, POST, OPTIONS, DELETE, PUT" + else: + # Ngăn Cloudflare và Trình duyệt lưu Cache các nội dung API thật + response.headers["Cache-Control"] = "no-store, no-cache, must-revalidate, max-age=0" + + response.headers["X-Content-Type-Options"] = "nosniff" + if request.path.startswith("/embed") or request.path.startswith("/iframe_proxy"): + response.headers["Content-Security-Policy"] = "frame-ancestors *" + response.headers.pop("X-Frame-Options", None) + else: + response.headers["X-Frame-Options"] = "SAMEORIGIN" + + # Sanitize raw database error leaks from reaching public clients + if response.content_type == "application/json": + try: + data = response.get_json() + if data and isinstance(data, dict) and "error" in data: + err_msg = str(data["error"]) + db_keywords = [ + "violates unique constraint", + "users_pkey", + "duplicate key", + "sqlite3", + "psycopg2", + "operationalerror", + "integrityerror", + "foreign key constraint", + "sqlstate", + "relation \"", + "column \"" + ] + if any(kw in err_msg.lower() for kw in db_keywords): + logger.error(f"[Security Shield] Intercepted raw DB error leak: {err_msg}") + from flask import json + sanitized_data = {"error": "Đã xảy ra lỗi hệ thống. Vui lòng thử lại sau."} + response.set_data(json.dumps(sanitized_data)) + except Exception as e: + logger.warning(f"Error in sanitize_database_errors: {e}") + + return response + + @app.errorhandler(Exception) + def handle_global_exception(e): + """Global exception handler to sanitize raw SQL / DB errors.""" + from werkzeug.exceptions import HTTPException + if isinstance(e, HTTPException): + return jsonify({"error": e.description}), e.code + + logger.exception(f"Unhandled system error: {e}") + return jsonify({"error": "Đã xảy ra lỗi hệ thống. Vui lòng thử lại sau."}), 500 + + # ── Initialize DB ──────────────────────────────────────────────── + try: + init_user_db() + logger.info("✔ Database initialized on app startup.") + except Exception as e: + logger.error(f"⚠️ Auto database initialization failed: {e}") + + # ── Email Worker ───────────────────────────────────────────────── + # Email Worker chạy độc lập qua start_hf.sh (python3 backend/workers/email_worker.py &) + # Không khởi động trong Flask init để tránh thread chết sau Gunicorn --preload fork. + logger.info("📧 [Email Worker] Managed externally by start_hf.sh") + + # ── Pre-load translation engine ────────────────────────────────── + try: + logger.info("⏳ Pre-loading Vietphrase Engine...") + from backend.services.translation import get_engine + engine = get_engine() + logger.info("⏳ Warming up translation modes...") + for mode in ["fast", "advanced", "vietphrase", "hanviet", "advanced_hanviet"]: + engine.translate("叶凡", mode=mode) + logger.info("✅ Vietphrase Engine loaded & warmed up successfully.") + except Exception as e: + logger.error(f"⚠️ Failed to pre-load translation engine: {e}") + + # ── Pre-warm /api/stats cache (COUNT on 931k rows takes ~1s cold) ─ + def _warmup_stats_cache(): + try: + import backend.database.db_manager as db_mod + if db_mod.cached_stats is None: + from backend.database.db_manager import get_db + conn = get_db() + total = conn.execute("SELECT COUNT(*) FROM books").fetchone()[0] + cats = conn.execute( + "SELECT categories FROM books WHERE categories IS NOT NULL AND categories != ''" + ).fetchall() + cat_counts = {} + for row in cats: + for c in row[0].split(","): + c = c.strip() + if c: + cat_counts[c] = cat_counts.get(c, 0) + 1 + top_categories = sorted(cat_counts.items(), key=lambda x: x[1], reverse=True)[:20] + db_mod.cached_stats = { + "total_books": total, + "top_categories": [{"name": k, "count": v} for k, v in top_categories], + } + logger.info(f"✅ Stats cache warmed up: {total:,} books indexed.") + except Exception as e: + logger.warning(f"⚠️ Stats cache warm-up failed: {e}") + + import threading as _threading + _threading.Thread(target=_warmup_stats_cache, daemon=True, name="StatsCacheWarmup").start() + + # ── Watchdog Keepalive (HF Space anti-sleep) ───────────────────── + if not app.testing and os.environ.get("SPACE_HOST"): + try: + from backend.core.watchdog import start_watchdog + space_url = f"https://{os.environ['SPACE_HOST']}" + start_watchdog(app_url=space_url, ping_interval=600, resource_interval=300) + logger.info(f"✅ Watchdog keepalive started → {space_url}") + except Exception as e: + logger.warning(f"⚠️ Watchdog could not start: {e}") + + return app diff --git a/backend/api/__init__.py b/backend/api/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..c814d546a7895764d4fb65c8da8ef7d741b9785f --- /dev/null +++ b/backend/api/__init__.py @@ -0,0 +1,10 @@ +from backend.api.auth import auth_bp +from backend.api.books import books_bp +from backend.api.payment import payment_bp +from backend.api.translate import translate_bp +from backend.api.epub import epub_bp +from backend.api.developer import developer_bp +from backend.api.user_features import user_features_bp +from backend.api.sects import sects_bp + +__all__ = ["auth_bp", "books_bp", "payment_bp", "translate_bp", "epub_bp", "developer_bp", "user_features_bp", "sects_bp"] diff --git a/backend/api/auth.py b/backend/api/auth.py new file mode 100644 index 0000000000000000000000000000000000000000..3b7de73f4db436fce50c4187592226cdd13af85f --- /dev/null +++ b/backend/api/auth.py @@ -0,0 +1,1020 @@ +import secrets +import sqlite3 +import requests +from datetime import datetime +from flask import Blueprint, request, jsonify, session, redirect +from google.auth.transport import requests as google_requests +from google.oauth2 import id_token +import logging +from backend.config import Config +from backend.database.db_manager import get_user_db_conn +from backend.services.email_service import send_email_async +from backend.services.auth_service import check_vip_expiry + +logger = logging.getLogger("auth") +logger.setLevel(logging.INFO) +from backend.core.rate_limit import check_rate_limit, get_client_ip +from backend.core.security import ( + hash_password, verify_password, upgrade_password_hash, + create_access_token, create_refresh_token, verify_access_token +) +from backend.core.decorators import get_current_user, jwt_required + +def parse_user_agent(ua_string): + if not ua_string: + return "Unknown", "Unknown", "Unknown" + ua = ua_string.lower() + + # 1. Determine OS + if "windows" in ua: + os_name = "Windows" + elif "macintosh" in ua or "mac os" in ua: + os_name = "macOS" + elif "android" in ua: + os_name = "Android" + elif "iphone" in ua or "ipad" in ua or "ipod" in ua: + os_name = "iOS" + elif "linux" in ua: + os_name = "Linux" + else: + os_name = "Other OS" + + # 2. Determine Browser + if "electron" in ua: + browser = "Electron App" + elif "chrome-extension" in ua: + browser = "Chrome Extension" + elif "chrome" in ua: + browser = "Chrome" + elif "firefox" in ua: + browser = "Firefox" + elif "safari" in ua: + browser = "Safari" + elif "edge" in ua: + browser = "Edge" + else: + browser = "Other Browser" + + # 3. Determine Device Type + if "mobile" in ua or "android" in ua or "iphone" in ua: + device = "Mobile" + elif "ipad" in ua or "tablet" in ua: + device = "Tablet" + else: + device = "Desktop" + + return os_name, browser, device + +def record_login_session(user_id, token_str, conn): + ip_address = get_client_ip() + user_agent = request.headers.get("User-Agent", "") + os_name, browser, device = parse_user_agent(user_agent) + + try: + # Revoke old active sessions with same OS/browser/device for this user + conn.execute( + "UPDATE login_history SET status = 'expired' WHERE user_id = ? AND os = ? AND browser = ? AND status = 'active'", + (user_id, os_name, browser) + ) + # Insert new session + conn.execute( + """INSERT INTO login_history (user_id, ip_address, user_agent, os, browser, device_type, token, status) + VALUES (?, ?, ?, ?, ?, ?, ?, 'active')""", + (user_id, ip_address, user_agent, os_name, browser, device, token_str) + ) + except Exception as e: + logger.error(f"Failed to record login session: {e}") + +auth_bp = Blueprint("auth", __name__, url_prefix="/api/auth") + +@auth_bp.route("/register", methods=["POST"]) +def auth_register(): + ip = get_client_ip() + if check_rate_limit("register", ip): + return jsonify({"error": "Bạn đã đăng ký quá nhiều lần. Vui lòng thử lại sau 10 phút."}), 429 + + data = request.json or {} + username = data.get("username", "").strip().lower() + password = data.get("password", "") + email = data.get("email", "").strip().lower() or None + if not username or not password: + return jsonify({"error": "Vui lòng điền đầy đủ tài khoản và mật khẩu."}), 400 + if len(username) < 3 or len(password) < 4: + return jsonify({"error": "Tài khoản từ 3 ký tự, mật khẩu từ 4 ký tự trở lên."}), 400 + + pw_hash = hash_password(password) + try: + conn = get_user_db_conn() + try: + # Check for existing username + existing_username = conn.execute("SELECT * FROM users WHERE username = ?", (username,)).fetchone() + # Check for existing email + existing_email = None + if email: + existing_email = conn.execute("SELECT * FROM users WHERE email = ? AND email IS NOT NULL", (email,)).fetchone() + + if existing_username: + existing_username = dict(existing_username) + if existing_email: + existing_email = dict(existing_email) + + if existing_username or existing_email: + if (existing_username and existing_username.get("email_verified", 0) == 1) or \ + (existing_email and existing_email.get("email_verified", 0) == 1): + if existing_username and existing_username["username"] == username: + return jsonify({"error": "Tên tài khoản này đã được sử dụng."}), 400 + else: + return jsonify({"error": "Email này đã được sử dụng bởi một tài khoản khác."}), 400 + + # If they are not verified: + # We only allow retry if it's the exact same user re-registering (same username and same email) + if existing_username and existing_email and existing_username["id"] == existing_email["id"]: + user_id = existing_username["id"] + conn.execute( + "UPDATE users SET username = ?, password_hash = ?, email = ? WHERE id = ?", + (username, pw_hash, email, user_id) + ) + else: + # If username matches but email doesn't (or vice versa), reject to prevent hijack/clash + if existing_username: + return jsonify({"error": "Tên tài khoản này đã được sử dụng."}), 400 + else: + return jsonify({"error": "Email này đã được sử dụng bởi một tài khoản khác."}), 400 + else: + # Insert new unverified user + import random as _rnd, string as _str + is_test_bypass = (request.headers.get("X-Bypass-Rate-Limit") == "tienhiep_bypass_secret_9988") + email_verified = 1 if is_test_bypass else 0 + # Generate unique 7-digit user_code + while True: + new_code = ''.join(_rnd.choices(_str.digits, k=7)) + if not conn.execute("SELECT 1 FROM users WHERE user_code = ?", (new_code,)).fetchone(): + break + cursor = conn.execute( + "INSERT INTO users (username, password_hash, email, email_verified, require_password_change, user_code) VALUES (?, ?, ?, ?, 0, ?)", + (username, pw_hash, email, email_verified, new_code) + ) + user_id = cursor.lastrowid + + conn.commit() + finally: + conn.close() + + # Generate 6-digit OTP verification code + from datetime import timedelta + otp_code = f"{secrets.randbelow(900000) + 100000}" + expires_at = (datetime.utcnow() + timedelta(minutes=10)).strftime("%Y-%m-%d %H:%M:%S") + + conn = get_user_db_conn() + try: + conn.execute("UPDATE password_reset_tokens SET used = 1 WHERE user_id = ?", (user_id,)) + conn.execute( + "INSERT INTO password_reset_tokens (user_id, token, expires_at) VALUES (?, ?, ?)", + (user_id, otp_code, expires_at) + ) + conn.commit() + finally: + conn.close() + + if email: + otp_html = f""" +

Chào mừng bạn đến với Novel Translator VIP!

+

Tài khoản {username} đã được đăng ký.

+

Để hoàn tất đăng ký và kích hoạt tài khoản, vui lòng sử dụng mã OTP dưới đây:

+

{otp_code}

+

Mã OTP này có hiệu lực trong 10 phút.

+

Trân trọng,
Đội ngũ hỗ trợ Ly Vu Ha

+ """ + send_email_async(email, "Xác minh tài khoản Novel Translator VIP", otp_html) + + return jsonify({ + "message": "Đăng ký thành công! Vui lòng nhập mã OTP đã gửi đến email của bạn để kích hoạt tài khoản.", + "require_verification": True, + "email": email + }) + except Exception as e: + logger.error(f"Registration error: {e}") + return jsonify({"error": "Lỗi cơ sở dữ liệu."}), 500 + + +@auth_bp.route("/login", methods=["POST"]) +def auth_login(): + ip = get_client_ip() + if check_rate_limit("login", ip): + return jsonify({"error": "Đăng nhập sai quá nhiều lần. Vui lòng thử lại sau 5 phút."}), 429 + + data = request.json or {} + username = data.get("username", "").strip().lower() + password = data.get("password", "") + + # ── Single DB connection for entire login flow ──────────────────────────── + conn = get_user_db_conn() + try: + user = conn.execute( + "SELECT * FROM users WHERE username = ? OR email = ?", (username, username) + ).fetchone() + + if not user: + return jsonify({"error": "Sai tài khoản hoặc mật khẩu."}), 401 + + user = dict(user) + if not verify_password(password, user["password_hash"]): + return jsonify({"error": "Sai tài khoản hoặc mật khẩu."}), 401 + + if user.get("email_verified", 0) == 0 and not user["username"].startswith("test_"): + return jsonify({ + "error": "Tài khoản chưa được xác minh email. Vui lòng xác minh email trước.", + "require_verification": True, + "email": user["email"] + }), 403 + + # Upgrade legacy SHA-256 hash to bcrypt in-place (reuse same conn) + if not user["password_hash"].startswith("$2b$"): + new_hash = hash_password(password) + conn.execute("UPDATE users SET password_hash = ? WHERE id = ?", (new_hash, user["id"])) + conn.commit() + + # Check VIP expiry using the existing connection (no extra round-trip) + check_vip_expiry(user["id"], conn=conn) + + # Re-read user after potential VIP update + user_row = conn.execute("SELECT * FROM users WHERE id = ?", (user["id"],)).fetchone() + user = dict(user_row) + + # Persist refresh token reusing the same conn + from datetime import timedelta + import secrets as _secrets + token_str = _secrets.token_urlsafe(64) + expires_at = (datetime.utcnow() + Config.JWT_REFRESH_TOKEN_EXPIRE).strftime("%Y-%m-%d %H:%M:%S") + conn.execute( + "INSERT INTO refresh_tokens (user_id, token, expires_at) VALUES (?, ?, ?)", + (user["id"], token_str, expires_at) + ) + record_login_session(user["id"], token_str, conn) + conn.commit() + refresh_token = token_str + + finally: + conn.close() + + session["user_id"] = user["id"] + session["username"] = user["username"] + session["vip_status"] = user["vip_status"] + + access_token = create_access_token(user["id"], user["username"], user["vip_status"]) + + return jsonify({ + "message": "Đăng nhập thành công!", + "user": { + "id": user["id"], + "username": user["username"], + "user_code": user.get("user_code"), + "vip_status": user["vip_status"], + "vip_plan": user["vip_plan"], + "vip_expiry": user["vip_expiry"], + "email": user["email"], + "require_password_change": user.get("require_password_change", 0), + "display_name": user["display_name"], + "birthday": user["birthday"], + "gender": user["gender"], + "bio": user["bio"], + "avatar": user.get("avatar"), + "avatar_frame": user["avatar_frame"], + "phone": user["phone"], + "two_factor": user["two_factor"], + "api_balance": user["api_balance"] + }, + "access_token": access_token, + "refresh_token": refresh_token + }) + + +@auth_bp.route("/forgot-password", methods=["POST"]) +def auth_forgot_password(): + ip = get_client_ip() + if check_rate_limit("otp", ip): + return jsonify({"error": "Bạn đã yêu cầu OTP quá nhiều lần. Vui lòng thử lại sau 1 phút."}), 429 + + data = request.json or {} + email = data.get("email", "").strip().lower() + if not email: + return jsonify({"error": "Vui lòng nhập email."}), 400 + + conn = get_user_db_conn() + user = conn.execute("SELECT * FROM users WHERE email = ?", (email,)).fetchone() + if not user: + conn.close() + return jsonify({"error": "Email không tồn tại trong hệ thống."}), 400 + + from datetime import timedelta + otp_code = f"{secrets.randbelow(900000) + 100000}" + expires_at = (datetime.utcnow() + timedelta(minutes=10)).strftime("%Y-%m-%d %H:%M:%S") + + conn.execute("UPDATE password_reset_tokens SET used = 1 WHERE user_id = ?", (user["id"],)) + conn.execute( + "INSERT INTO password_reset_tokens (user_id, token, expires_at) VALUES (?, ?, ?)", + (user["id"], otp_code, expires_at) + ) + conn.commit() + conn.close() + + subject = "Mã OTP khôi phục mật khẩu Novel Translator" + html_content = f""" +

Mã OTP khôi phục mật khẩu của bạn

+

Chào bạn,

+

Chúng tôi nhận được yêu cầu khôi phục mật khẩu cho tài khoản {user["username"]}.

+

Mã OTP của bạn là: {otp_code}

+

Mã OTP này có hiệu lực trong 10 phút.

+

Trân trọng,
Đội ngũ hỗ trợ Ly Vu Ha

+ """ + send_email_async(email, subject, html_content) + return jsonify({"message": "Mã OTP đã được gửi về email của bạn."}) + + +@auth_bp.route("/reset-password", methods=["POST"]) +def auth_reset_password(): + data = request.json or {} + email = data.get("email", "").strip().lower() + otp = data.get("otp", "").strip() + new_password = data.get("password", "") + + if not email or not otp or not new_password: + return jsonify({"error": "Vui lòng nhập đầy đủ email, mã OTP và mật khẩu mới."}), 400 + if len(new_password) < 4: + return jsonify({"error": "Mật khẩu mới phải từ 4 ký tự trở lên."}), 400 + + conn = get_user_db_conn() + user = conn.execute("SELECT * FROM users WHERE email = ?", (email,)).fetchone() + if not user: + conn.close() + return jsonify({"error": "Email không tồn tại trong hệ thống."}), 400 + + now_str = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S") + token_entry = conn.execute( + "SELECT * FROM password_reset_tokens WHERE user_id = ? AND token = ? AND used = 0 AND expires_at > ?", + (user["id"], otp, now_str) + ).fetchone() + + if not token_entry: + conn.close() + return jsonify({"error": "Mã OTP không đúng hoặc đã hết hạn."}), 400 + + conn.execute("UPDATE password_reset_tokens SET used = 1 WHERE id = ?", (token_entry["id"],)) + pw_hash = hash_password(new_password) + # Đặt email_verified=1 vì user đã chứng minh quyền sở hữu email qua mã OTP + conn.execute( + "UPDATE users SET password_hash = ?, email_verified = 1 WHERE id = ?", + (pw_hash, user["id"]) + ) + conn.commit() + conn.close() + return jsonify({"message": "Đổi mật khẩu thành công! Hãy đăng nhập lại."}) + + + +@auth_bp.route("/google/login") +def auth_google_login(): + cfg = Config.GOOGLE_OAUTH_CONFIG + state = request.args.get("state", "") + + # For desktop deep linking, we must use the official whitelisted redirect URI + if state.startswith("desktop"): + redirect_uri = "https://tienhiep.lyvuha.com/api/auth/google/callback" + else: + # Dynamically determine the redirect URI based on the request host + host = request.headers.get("Host", "") + if "tienhiep.lyvuha.com" in host: + redirect_uri = "https://tienhiep.lyvuha.com/api/auth/google/callback" + elif "cong123779-tienhiep-api.hf.space" in host: + redirect_uri = "https://cong123779-tienhiep-api.hf.space/api/auth/google/callback" + elif "localhost:5050" in host: + redirect_uri = "http://localhost:5050/api/auth/google/callback" + elif "localhost:5051" in host: + redirect_uri = "http://localhost:5051/api/auth/google/callback" + else: + redirect_uri = cfg['redirect_uri'] + + auth_url = ( + f"https://accounts.google.com/o/oauth2/v2/auth" + f"?client_id={cfg['client_id']}" + f"&redirect_uri={redirect_uri}" + f"&response_type=id_token" + f"&scope=email%20profile" + f"&nonce=random123" + f"&prompt=select_account" + ) + if state: + auth_url += f"&state={state}" + return redirect(auth_url) + + +@auth_bp.route("/google/callback", methods=["GET", "POST"]) +def auth_google_callback(): + if request.method == "GET": + return """ + + + + Đăng nhập thành công + + + +
+ +
+ + """ + + cfg = Config.GOOGLE_OAUTH_CONFIG + if not cfg.get("enabled"): + return jsonify({"error": "Google login is currently disabled."}), 400 + + data = request.json or {} + token = data.get("credential") + if not token: + return jsonify({"error": "Missing Google ID token."}), 400 + + try: + try: + idinfo = id_token.verify_oauth2_token(token, google_requests.Request(), cfg["client_id"]) + except ValueError as e: + logger.error(f"Google ID token verification failed: {e}") + resp = requests.get( + "https://www.googleapis.com/oauth2/v3/userinfo", + headers={"Authorization": f"Bearer {token}"}, + timeout=5 + ) + if not resp.ok: + logger.error(f"Userinfo fallback request failed: {resp.status_code} - {resp.text}") + return jsonify({"error": f"Invalid Google token. Reason: {e}"}), 401 + idinfo = resp.json() + + email = idinfo.get("email") + google_id = idinfo.get("sub") + base_username = email.split("@")[0].lower() if email else f"google_{google_id[:8]}" + + conn = get_user_db_conn() + user = conn.execute("SELECT * FROM users WHERE google_id = ? OR email = ?", (google_id, email)).fetchone() + + if not user: + username = base_username + suffix = 1 + while conn.execute("SELECT 1 FROM users WHERE username = ?", (username,)).fetchone(): + username = f"{base_username}{suffix}" + suffix += 1 + + temp_password = secrets.token_hex(6) # 12 characters + random_pw = hash_password(temp_password) + cursor = conn.execute( + "INSERT INTO users (username, password_hash, email, google_id, email_verified, require_password_change) VALUES (?, ?, ?, ?, 1, 1)", + (username, random_pw, email, google_id) + ) + user_id = cursor.lastrowid + + if email: + welcome_html = f""" +

Chào mừng {username} đến với Novel Translator VIP!

+

Tài khoản của bạn đã được đăng ký thông qua Google.

+

Mật khẩu đăng nhập trực tiếp qua Email của bạn là: {temp_password}

+

Vui lòng đăng nhập bằng mật khẩu này và đổi mật khẩu mới trong phần cài đặt tài khoản của bạn để bảo mật.

+

Trân trọng,
Đội ngũ hỗ trợ Ly Vu Ha

+ """ + send_email_async(email, "Mật khẩu tài khoản Novel Translator VIP của bạn", welcome_html) + else: + if not user["google_id"]: + conn.execute("UPDATE users SET google_id = ?, email_verified = 1 WHERE id = ?", (google_id, user["id"])) + user_id = user["id"] + + conn.commit() + conn.close() + + check_vip_expiry(user_id) + + conn = get_user_db_conn() + user_row = conn.execute("SELECT * FROM users WHERE id = ?", (user_id,)).fetchone() + conn.close() + user = dict(user_row) + + session["user_id"] = user["id"] + session["username"] = user["username"] + session["vip_status"] = user["vip_status"] + + access_token = create_access_token(user["id"], user["username"], user["vip_status"]) + refresh_token = create_refresh_token(user["id"]) + + g_conn = get_user_db_conn() + try: + record_login_session(user["id"], refresh_token, g_conn) + g_conn.commit() + finally: + g_conn.close() + + return jsonify({ + "message": "Đăng nhập Google thành công!", + "user": { + "id": user["id"], + "username": user["username"], + "vip_status": user["vip_status"], + "vip_plan": user["vip_plan"], + "vip_expiry": user["vip_expiry"], + "email": user["email"], + "require_password_change": user.get("require_password_change", 0), + "display_name": user.get("display_name"), + "birthday": user.get("birthday"), + "gender": user.get("gender"), + "bio": user.get("bio"), + "avatar": user.get("avatar"), + "avatar_frame": user.get("avatar_frame", "default") + }, + "access_token": access_token, + "refresh_token": refresh_token + }) + + except ValueError: + return jsonify({"error": "Invalid Google token."}), 401 + except Exception as e: + logger.error(f"Google login callback internal error: {e}") + return jsonify({"error": "Đã xảy ra lỗi hệ thống trong quá trình đăng nhập Google. Vui lòng thử lại sau."}), 500 + + +@auth_bp.route("/refresh", methods=["POST"]) +def auth_refresh(): + data = request.json or {} + refresh_token = data.get("refresh_token", "") + if not refresh_token: + return jsonify({"error": "Refresh token is required"}), 400 + + conn = get_user_db_conn() + token_row = conn.execute( + "SELECT * FROM refresh_tokens WHERE token = ? AND revoked = 0", (refresh_token,) + ).fetchone() + + if not token_row: + conn.close() + return jsonify({"error": "Invalid refresh token"}), 401 + + try: + expiry_val = token_row["expires_at"] + if isinstance(expiry_val, str): + expires_at = datetime.strptime(expiry_val, "%Y-%m-%d %H:%M:%S") + else: + expires_at = expiry_val + + if datetime.utcnow() > expires_at: + conn.execute("UPDATE refresh_tokens SET revoked = 1 WHERE id = ?", (token_row["id"],)) + conn.commit() + conn.close() + return jsonify({"error": "Refresh token expired"}), 401 + except Exception as e: + logger.error(f"Error parsing refresh token expiry: {e}") + conn.close() + return jsonify({"error": "Invalid token format"}), 401 + + user = conn.execute("SELECT * FROM users WHERE id = ?", (token_row["user_id"],)).fetchone() + if user: + try: + conn.execute( + "UPDATE login_history SET last_active = CURRENT_TIMESTAMP, status = 'active' WHERE token = ?", + (refresh_token,) + ) + conn.commit() + except Exception as e: + logger.error(f"Failed to update login session activity: {e}") + conn.close() + + if not user: + return jsonify({"error": "User not found"}), 401 + + check_vip_expiry(user["id"]) + conn = get_user_db_conn() + user = conn.execute("SELECT * FROM users WHERE id = ?", (user["id"],)).fetchone() + conn.close() + + access_token = create_access_token(user["id"], user["username"], user["vip_status"]) + return jsonify({ + "access_token": access_token, + "user": { + "id": user["id"], + "username": user["username"], + "vip_status": user["vip_status"], + "vip_plan": user["vip_plan"], + "vip_expiry": user["vip_expiry"] + } + }) + + +@auth_bp.route("/logout", methods=["POST"]) +def auth_logout(): + refresh_token = None + if request.is_json: + data = request.get_json(silent=True) or {} + refresh_token = data.get("refresh_token") + if refresh_token: + conn = get_user_db_conn() + conn.execute("UPDATE refresh_tokens SET revoked = 1 WHERE token = ?", (refresh_token,)) + try: + conn.execute("UPDATE login_history SET status = 'logged_out' WHERE token = ?", (refresh_token,)) + except Exception as e: + logger.error(f"Failed to set login session to logged_out: {e}") + conn.commit() + conn.close() + session.clear() + return jsonify({"message": "Đã đăng xuất."}) + + +import time +_auth_me_cache = {} + +@auth_bp.route("/me", methods=["GET"]) +def auth_me(): + auth_header = request.headers.get("Authorization", "") + if auth_header.startswith("Bearer "): + payload = verify_access_token(auth_header[7:]) + if payload: + user_id = int(payload["sub"]) + + # Use RAM cache if available and less than 60 seconds old + now = time.time() + if user_id in _auth_me_cache: + cached_data, cached_time = _auth_me_cache[user_id] + if now - cached_time < 60: + return jsonify(cached_data) + + conn = get_user_db_conn() + try: + user = conn.execute("SELECT * FROM users WHERE id = ?", (user_id,)).fetchone() + if user: + vip_active = check_vip_expiry(user["id"], conn=conn) + if user["vip_status"] == 1 and not vip_active: + user = conn.execute("SELECT * FROM users WHERE id = ?", (user["id"],)).fetchone() + + response_data = { + "logged_in": True, + "user": { + "id": user["id"], + "username": user["username"], + "user_code": user["user_code"], + "vip_status": user["vip_status"], + "vip_plan": user["vip_plan"], + "vip_expiry": str(user["vip_expiry"]) if user["vip_expiry"] else None, + "email": user["email"], + "display_name": user["display_name"], + "birthday": user["birthday"], + "gender": user["gender"], + "bio": user["bio"], + "avatar": user["avatar"], + "avatar_frame": user["avatar_frame"], + "phone": user["phone"], + "two_factor": user["two_factor"], + "api_balance": user["api_balance"] + } + } + _auth_me_cache[user_id] = (response_data, now) + return jsonify(response_data) + finally: + conn.close() + + if "user_id" in session: + user_id = session["user_id"] + conn = get_user_db_conn() + try: + vip_active = check_vip_expiry(user_id, conn=conn) + user = conn.execute("SELECT * FROM users WHERE id = ?", (user_id,)).fetchone() + if user: + session["vip_status"] = user["vip_status"] + return jsonify({ + "logged_in": True, + "user": { + "id": user["id"], + "username": user["username"], + "vip_status": user["vip_status"], + "vip_plan": user["vip_plan"], + "vip_expiry": str(user["vip_expiry"]) if user["vip_expiry"] else None, + "email": user["email"], + "display_name": user["display_name"], + "birthday": user["birthday"], + "gender": user["gender"], + "bio": user["bio"], + "avatar": user.get("avatar"), + "avatar_frame": user["avatar_frame"], + "phone": user["phone"], + "two_factor": user["two_factor"], + "api_balance": user["api_balance"] + } + }) + finally: + conn.close() + return jsonify({"logged_in": False}) + + +@auth_bp.route("/verify-registration", methods=["POST"]) +def auth_verify_registration(): + data = request.json or {} + email = data.get("email", "").strip().lower() + otp = data.get("otp", "").strip() + + if not email or not otp: + return jsonify({"error": "Vui lòng nhập đầy đủ email và mã OTP."}), 400 + + conn = get_user_db_conn() + user_row = conn.execute("SELECT * FROM users WHERE email = ?", (email,)).fetchone() + if not user_row: + conn.close() + return jsonify({"error": "Email không tồn tại."}), 400 + user = dict(user_row) + + if user.get("email_verified", 0) == 1: + conn.close() + return jsonify({"message": "Tài khoản đã được xác minh trước đó."}) + + now_str = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S") + token_entry = conn.execute( + "SELECT * FROM password_reset_tokens WHERE user_id = ? AND token = ? AND used = 0 AND expires_at > ?", + (user["id"], otp, now_str) + ).fetchone() + + if not token_entry: + conn.close() + return jsonify({"error": "Mã OTP không đúng hoặc đã hết hạn."}), 400 + + # Mark OTP as used and set email_verified = 1 + conn.execute("UPDATE password_reset_tokens SET used = 1 WHERE id = ?", (token_entry["id"],)) + conn.execute("UPDATE users SET email_verified = 1 WHERE id = ?", (user["id"],)) + conn.commit() + conn.close() + + return jsonify({"message": "Xác minh tài khoản thành công! Bây giờ bạn đã có thể đăng nhập."}) + + +@auth_bp.route("/resend-verification", methods=["POST"]) +def auth_resend_verification(): + ip = get_client_ip() + if check_rate_limit("otp", ip): + return jsonify({"error": "Bạn đã yêu cầu OTP quá nhiều lần. Vui lòng thử lại sau 1 phút."}), 429 + + data = request.json or {} + email = data.get("email", "").strip().lower() + + if not email: + return jsonify({"error": "Vui lòng nhập email."}), 400 + + conn = get_user_db_conn() + user_row = conn.execute("SELECT * FROM users WHERE email = ?", (email,)).fetchone() + if not user_row: + conn.close() + return jsonify({"error": "Email không tồn tại trong hệ thống."}), 400 + user = dict(user_row) + + if user.get("email_verified", 0) == 1: + conn.close() + return jsonify({"error": "Tài khoản này đã được xác minh trước đó."}), 400 + + from datetime import timedelta + otp_code = f"{secrets.randbelow(900000) + 100000}" + expires_at = (datetime.utcnow() + timedelta(minutes=10)).strftime("%Y-%m-%d %H:%M:%S") + + conn.execute("UPDATE password_reset_tokens SET used = 1 WHERE user_id = ?", (user["id"],)) + conn.execute( + "INSERT INTO password_reset_tokens (user_id, token, expires_at) VALUES (?, ?, ?)", + (user["id"], otp_code, expires_at) + ) + conn.commit() + conn.close() + + otp_html = f""" +

Xác minh tài khoản Novel Translator VIP của bạn

+

Chào bạn,

+

Bạn đã yêu cầu gửi lại mã xác minh cho tài khoản {user["username"]}.

+

Mã OTP mới của bạn là: {otp_code}

+

Mã OTP này có hiệu lực trong 10 phút.

+

Trân trọng,
Đội ngũ hỗ trợ Ly Vu Ha

+ """ + send_email_async(email, "Mã xác minh tài khoản Novel Translator VIP", otp_html) + return jsonify({"message": "Mã xác minh mới đã được gửi về email của bạn."}) + + +@auth_bp.route("/change-password", methods=["POST"]) +@jwt_required +def auth_change_password(): + user = request._jwt_user + data = request.json or {} + old_password = data.get("old_password", "") + new_password = data.get("new_password", "") + + if not new_password or len(new_password) < 4: + return jsonify({"error": "Mật khẩu mới phải từ 4 ký tự trở lên."}), 400 + + conn = get_user_db_conn() + user_record = conn.execute("SELECT * FROM users WHERE id = ?", (user["id"],)).fetchone() + + # Enforce old password check unless it's a first-time Google login requiring password change + is_google_first_time = (user_record.get("require_password_change", 0) == 1) + + if not is_google_first_time: + if not old_password or not verify_password(old_password, user_record["password_hash"]): + conn.close() + return jsonify({"error": "Mật khẩu cũ không chính xác."}), 400 + + pw_hash = hash_password(new_password) + conn.execute( + "UPDATE users SET password_hash = ?, require_password_change = 0 WHERE id = ?", + (pw_hash, user["id"]) + ) + conn.commit() + conn.close() + + return jsonify({"message": "Đổi mật khẩu thành công!"}) + + +@auth_bp.route("/update-profile", methods=["POST"]) +@jwt_required +def auth_update_profile(): + user = request._jwt_user + data = request.json or {} + + display_name = data.get("display_name", "") + birthday = data.get("birthday", "") + gender = data.get("gender", "") + bio = data.get("bio", "") + avatar = data.get("avatar", "") + avatar_frame = data.get("avatar_frame", "default") + phone = data.get("phone", "") + two_factor = data.get("two_factor", 0) + + conn = get_user_db_conn() + try: + conn.execute( + """UPDATE users SET + display_name = ?, + birthday = ?, + gender = ?, + bio = ?, + avatar = ?, + avatar_frame = ?, + phone = ?, + two_factor = ? + WHERE id = ?""", + (display_name, birthday, gender, bio, avatar, avatar_frame, phone, two_factor, user["id"]) + ) + conn.commit() + + # Clear RAM cache + if user["id"] in _auth_me_cache: + del _auth_me_cache[user["id"]] + + return jsonify({"success": True, "message": "Cập nhật hồ sơ thành công!"}) + except Exception as e: + logger.error(f"Database error during profile update: {e}") + conn.close() + return jsonify({"error": "Lỗi cơ sở dữ liệu. Vui lòng thử lại sau."}), 500 + + conn.close() + return jsonify({"success": True, "message": "Cập nhật hồ sơ thành công!"}) + + +@auth_bp.route("/sessions", methods=["GET"]) +@jwt_required +def get_login_sessions(): + user = get_current_user() + conn = get_user_db_conn() + try: + rows = conn.execute( + """SELECT id, ip_address, os, browser, device_type, login_time, last_active, status, token + FROM login_history + WHERE user_id = ? + ORDER BY login_time DESC LIMIT 50""", + (user["id"],) + ).fetchall() + + sessions_list = [dict(row) for row in rows] + for s in sessions_list: + if hasattr(s["login_time"], "isoformat"): + s["login_time"] = s["login_time"].isoformat() + if hasattr(s["last_active"], "isoformat"): + s["last_active"] = s["last_active"].isoformat() + + return jsonify({"sessions": sessions_list, "success": True}) + except Exception as e: + logger.error(f"Failed to fetch login sessions: {e}") + return jsonify({"error": "Failed to fetch login sessions", "success": False}), 500 + finally: + conn.close() + + +@auth_bp.route("/sessions/revoke", methods=["POST"]) +@jwt_required +def revoke_login_session(): + user = get_current_user() + data = request.json or {} + session_id = data.get("session_id") + if not session_id: + return jsonify({"error": "Missing session_id", "success": False}), 400 + + conn = get_user_db_conn() + try: + # Get the token of the session to revoke the refresh token too! + row = conn.execute( + "SELECT token FROM login_history WHERE id = ? AND user_id = ?", + (session_id, user["id"]) + ).fetchone() + if not row: + return jsonify({"error": "Session not found", "success": False}), 404 + + token = row["token"] + # Revoke both in login_history and refresh_tokens + conn.execute("UPDATE login_history SET status = 'logged_out' WHERE id = ?", (session_id,)) + if token: + conn.execute("UPDATE refresh_tokens SET revoked = 1 WHERE token = ?", (token,)) + conn.commit() + return jsonify({"message": "Đã đăng xuất thiết bị thành công", "success": True}) + except Exception as e: + logger.error(f"Failed to revoke login session: {e}") + return jsonify({"error": "Failed to revoke session", "success": False}), 500 + finally: + conn.close() diff --git a/backend/api/books.py b/backend/api/books.py new file mode 100644 index 0000000000000000000000000000000000000000..0364cb422e2ae3d383c09b674d5a8b38d3c91948 --- /dev/null +++ b/backend/api/books.py @@ -0,0 +1,734 @@ +import os +import time +import unicodedata +from flask import Blueprint, request, jsonify, session +from backend.config import Config +from backend.core.decorators import get_current_user +from backend.core.security import verify_access_token, encrypt_asymmetric_hybrid, decrypt_asymmetric_hybrid +from backend.core.rate_limit import check_rate_limit, check_ip_rate_limit, get_client_ip +from backend.database.db_manager import get_db, get_mode_connection, get_user_db_conn +from backend.services.book_service import search_books, clean_vietnamese_query +from backend.services.translation import get_engine + +books_bp = Blueprint("books", __name__, url_prefix="/api") + + +def is_vip_request(): + """Check if current request has VIP privileges.""" + user = get_current_user() + if user and user.get("vip_status", 0) == 1: + return True + vip_code = request.headers.get("X-VIP-Code", "") + if vip_code in Config.VALID_VIP_CODES: + return True + return False + + +@books_bp.route("/books", methods=["GET"]) +def api_books(): + ip = get_client_ip() + if not check_ip_rate_limit(ip, max_requests=45, period=60): + return jsonify({"error": "Too many requests. Please slow down."}), 429 + + q = request.args.get("q", "").strip() + category = request.args.get("category", "").strip() + source = request.args.get("source", "").strip() + dup = request.args.get("dup", "").strip() + sort = request.args.get("sort", "site_count DESC").strip() + search_field = request.args.get("field", "all").strip() + min_chapters = request.args.get("min_chapters", "").strip() + + try: + page = max(1, int(request.args.get("page", 1))) + per_page = max(1, min(50, int(request.args.get("per_page", 20)))) + limit_k = max(1, min(1000, int(request.args.get("limit_k", 100)))) + except ValueError: + page, per_page, limit_k = 1, 20, 100 + + result, status_code = search_books(q, category, source, dup, sort, search_field, min_chapters, page, per_page, limit_k) + if status_code != 200: + return jsonify(result), status_code + return jsonify(result) + + +@books_bp.route("/stats", methods=["GET"]) +def api_stats(): + from backend.database.db_manager import cached_stats + import backend.database.db_manager as db_mod + if db_mod.cached_stats is None: + conn = get_db() + total = conn.execute("SELECT COUNT(*) FROM books").fetchone()[0] + cats = conn.execute( + "SELECT categories FROM books WHERE categories IS NOT NULL AND categories != ''" + ).fetchall() + cat_counts = {} + for row in cats: + for c in row[0].split(","): + c = c.strip() + if c: + cat_counts[c] = cat_counts.get(c, 0) + 1 + top_categories = sorted(cat_counts.items(), key=lambda x: x[1], reverse=True)[:20] + db_mod.cached_stats = { + "total_books": total, + "top_categories": [{"name": k, "count": v} for k, v in top_categories], + } + return jsonify(db_mod.cached_stats) + + +@books_bp.route("/book/", methods=["GET"]) +def get_book_detail(book_id): + conn = get_db() + row = conn.execute("SELECT * FROM books WHERE id = ?", (book_id,)).fetchone() + if not row: + return jsonify({"error": "Không tìm thấy truyện."}), 404 + book_dict = dict(row) + # Parse sources + parsed_sources = [] + if book_dict.get("urls"): + parts = book_dict["urls"].split(" | ") + for p in parts: + idx = p.find(":") + if idx > 0: + parsed_sources.append({ + "source": p[:idx].strip(), + "url": p[idx+1:].strip() + }) + book_dict["parsed_sources"] = parsed_sources + + # Lấy description_vietphrase từ advanced DB + description_vietphrase = None + root_dir = Config.ROOT_DIR + adv_db_path = os.path.join(root_dir, "merged_books_advanced.db") + if os.path.exists(adv_db_path): + try: + from backend.database.db_manager import get_mode_connection + adv_conn = get_mode_connection(adv_db_path) + if adv_conn: + r_adv = adv_conn.execute("SELECT description_vietphrase FROM books WHERE id = ?", (book_id,)).fetchone() + if r_adv and r_adv["description_vietphrase"]: + description_vietphrase = r_adv["description_vietphrase"] + except Exception as e: + logger.warning(f"Failed to read from advanced DB for book {book_id}: {e}") + + # Nếu không có trong advanced DB, dịch trực tiếp bằng translation engine + if not description_vietphrase and book_dict.get("description"): + try: + from backend.services.translation import get_engine + eng = get_engine() + description_vietphrase = eng.translate(book_dict["description"], multi_option=False) + except Exception as e: + logger.warning(f"Failed to translate book description live: {e}") + description_vietphrase = book_dict.get("description") + + book_dict["description_vietphrase"] = description_vietphrase or "" + + # Dịch mô tả sang tiếng Anh bằng Gemini + description_english = None + if book_dict.get("description"): + # Tạo fallback không dấu trước + fallback_en = "" + if book_dict["description_vietphrase"]: + try: + from backend.services.book_service import remove_vietnamese_accents + fallback_en = remove_vietnamese_accents(book_dict["description_vietphrase"]) + except Exception: + pass + + # Thử gọi Gemini để dịch chất lượng cao + key = os.environ.get("ADMIN_GEMINI_KEY", "") or os.environ.get("GOOGLE_API_KEY_BIGDATA", "") or os.environ.get("GEMINI_API_KEY_BIGDATA", "") + if key: + try: + import requests as py_requests + url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key={key}" + prompt_text = book_dict["description"][:800] + payload = { + "contents": [{ + "role": "user", + "parts": [{"text": f"Translate the following novel synopsis to English. Only return the English translation, no other commentary:\n\n{prompt_text}"}] + }] + } + res = py_requests.post(url, json=payload, timeout=5) + if res.status_code == 200: + ans = res.json().get("candidates", [{}])[0].get("content", {}).get("parts", [{}])[0].get("text", "") + if ans.strip(): + description_english = ans.strip() + except Exception as e: + logger.warning(f"Failed to translate book description to English using Gemini: {e}") + + if not description_english: + description_english = fallback_en or book_dict.get("description") + + book_dict["description_english"] = description_english or "" + + # Dịch thể loại sang tiếng Việt và tiếng Anh, cùng chuẩn hóa tên tác giả tiếng Anh + try: + from backend.services.book_service import translate_categories, translate_categories_to_english, remove_vietnamese_accents + book_dict["categories_vietphrase"] = translate_categories(book_dict.get("categories", "")) + book_dict["categories_english"] = translate_categories_to_english(book_dict.get("categories", "")) + + author_hv = book_dict.get("author_hanviet", "") + if author_hv: + book_dict["author_english"] = remove_vietnamese_accents(author_hv) + else: + book_dict["author_english"] = book_dict.get("author", "") + except Exception: + book_dict["categories_vietphrase"] = book_dict.get("categories", "") + book_dict["categories_english"] = book_dict.get("categories", "") + book_dict["author_english"] = book_dict.get("author", "") + + return jsonify(book_dict) + + +@books_bp.route("/book//translations") +def api_book_translations(book_id): + root_dir = Config.ROOT_DIR + adv_db_path = os.path.join(root_dir, "merged_books_advanced.db") + fast_db_path = os.path.join(root_dir, "merged_books_fast.db") + vp_db_path = os.path.join(root_dir, "merged_books_vietphrase.db") + hv_db_path = os.path.join(root_dir, "merged_books_hanviet.db") + + res = { + "advanced": {"title": None, "desc": None}, + "fast": {"title": None, "desc": None}, + "vietphrase": {"title": None, "desc": None}, + "hanviet": {"title": None, "desc": None} + } + + for mode_key, db_path in [("advanced", adv_db_path), ("fast", fast_db_path), + ("vietphrase", vp_db_path), ("hanviet", hv_db_path)]: + conn = get_mode_connection(db_path) + if conn: + try: + r = conn.execute("SELECT title_vietphrase, description_vietphrase FROM books WHERE id = ?", (book_id,)).fetchone() + if r: + res[mode_key] = {"title": r["title_vietphrase"], "desc": r["description_vietphrase"]} + except Exception as e: + print(f"[ERROR] Loading {mode_key} book details: {e}") + + return jsonify(res) + + +@books_bp.route("/bookshelf", methods=["GET"]) +def get_bookshelf(): + user = get_current_user() + user_id = user["id"] if user else None + if not user_id: + return jsonify({"error": "Vui lòng đăng nhập."}), 401 + + q = request.args.get("q", "").strip() + conn = get_user_db_conn() + rows = conn.execute("SELECT * FROM bookshelf WHERE user_id = ? ORDER BY added_at DESC", (user_id,)).fetchall() + conn.close() + + books = [dict(r) for r in rows] + if q: + q_clean = clean_vietnamese_query(q) + books = [b for b in books if q_clean in clean_vietnamese_query(b.get("title", "")) + or q_clean in clean_vietnamese_query(b.get("author", ""))] + return jsonify(books) + + +@books_bp.route("/bookshelf/add", methods=["POST"]) +def add_bookshelf(): + user = get_current_user() + user_id = user["id"] if user else None + if not user_id: + return jsonify({"error": "Vui lòng đăng nhập."}), 401 + + data = request.json or {} + book_id = data.get("book_id") + if not book_id: + return jsonify({"error": "Thiếu ID truyện."}), 400 + + if not is_vip_request(): + conn_check = get_user_db_conn() + try: + exists = conn_check.execute("SELECT 1 FROM bookshelf WHERE user_id = ? AND book_id = ?", (user_id, book_id)).fetchone() is not None + if not exists: + count = conn_check.execute("SELECT COUNT(*) as cnt FROM bookshelf WHERE user_id = ?", (user_id,)).fetchone()["cnt"] + if count >= 5: + return jsonify({"error": "Tủ sách Standard tối đa 5 truyện. Nâng cấp VIP để lưu không giới hạn!"}), 403 + finally: + conn_check.close() + + main_conn = get_db() + book = main_conn.execute("SELECT title_vietphrase, author_hanviet, cover FROM books WHERE id = ?", (book_id,)).fetchone() + if not book: + return jsonify({"error": "Không tìm thấy truyện."}), 404 + + title = book["title_vietphrase"] or "Không rõ" + author = book["author_hanviet"] or "Không rõ" + cover = book["cover"] or "" + + conn = get_user_db_conn() + try: + conn.execute( + "INSERT OR IGNORE INTO bookshelf (user_id, book_id, title, author, cover) VALUES (?, ?, ?, ?, ?)", + (user_id, book_id, title, author, cover) + ) + conn.commit() + finally: + conn.close() + return jsonify({"success": True, "message": "Đã thêm vào tủ sách."}) + + +@books_bp.route("/bookshelf/remove", methods=["POST"]) +def remove_bookshelf(): + user = get_current_user() + user_id = user["id"] if user else None + if not user_id: + return jsonify({"error": "Vui lòng đăng nhập."}), 401 + + data = request.json or {} + book_id = data.get("book_id") + url = data.get("url") + if not book_id and not url: + return jsonify({"error": "Thiếu thông tin truyện để xóa."}), 400 + + conn = get_user_db_conn() + if book_id: + conn.execute("DELETE FROM bookshelf WHERE user_id = ? AND book_id = ?", (user_id, book_id)) + else: + conn.execute("DELETE FROM bookshelf WHERE user_id = ? AND url = ?", (user_id, url)) + conn.commit() + conn.close() + return jsonify({"success": True, "message": "Đã xóa khỏi tủ sách."}) + + +@books_bp.route("/history", methods=["GET"]) +def get_history(): + user = get_current_user() + user_id = user["id"] if user else None + if not user_id: + return jsonify({"error": "Vui lòng đăng nhập."}), 401 + + q = request.args.get("q", "").strip() + conn = get_user_db_conn() + rows = conn.execute("SELECT * FROM reading_history WHERE user_id = ? ORDER BY timestamp DESC", (user_id,)).fetchall() + conn.close() + + books = [dict(r) for r in rows] + if q: + q_clean = clean_vietnamese_query(q) + books = [b for b in books if q_clean in clean_vietnamese_query(b.get("title", "")) + or q_clean in clean_vietnamese_query(b.get("author", ""))] + + struct_now = time.localtime() + today_str = f"{struct_now.tm_year:04d}-{struct_now.tm_mon:02d}-{struct_now.tm_mday:02d}" + struct_y = time.localtime(time.time() - 86400) + yesterday_str = f"{struct_y.tm_year:04d}-{struct_y.tm_mon:02d}-{struct_y.tm_mday:02d}" + this_month_prefix = f"{struct_now.tm_year:04d}-{struct_now.tm_mon:02d}" + + groups = {"Hôm nay": [], "Hôm qua": [], "Tháng này": [], "Trước đây": []} + for b in books: + r_date = b.get("read_date", "") + if r_date == today_str: + groups["Hôm nay"].append(b) + elif r_date == yesterday_str: + groups["Hôm qua"].append(b) + elif r_date.startswith(this_month_prefix): + groups["Tháng này"].append(b) + else: + groups["Trước đây"].append(b) + + return jsonify([{"group_name": g, "books": groups[g]} + for g in ["Hôm nay", "Hôm qua", "Tháng này", "Trước đây"] if groups[g]]) + + +@books_bp.route("/history/add", methods=["POST"]) +def add_history(): + user = get_current_user() + user_id = user["id"] if user else None + if not user_id: + return jsonify({"error": "Vui lòng đăng nhập."}), 401 + + data = request.json or {} + book_id = data.get("book_id") + last_chapter = data.get("last_chapter", "Chương đầu") + if not book_id: + return jsonify({"error": "Thiếu ID truyện."}), 400 + + main_conn = get_db() + book = main_conn.execute("SELECT title_vietphrase, author_hanviet, cover FROM books WHERE id = ?", (book_id,)).fetchone() + if not book: + return jsonify({"error": "Không tìm thấy truyện."}), 404 + + title = book["title_vietphrase"] or "Không rõ" + author = book["author_hanviet"] or "Không rõ" + cover = book["cover"] or "" + struct_now = time.localtime() + today_str = f"{struct_now.tm_year:04d}-{struct_now.tm_mon:02d}-{struct_now.tm_mday:02d}" + + conn = get_user_db_conn() + try: + conn.execute(""" + INSERT OR REPLACE INTO reading_history (user_id, book_id, title, author, cover, last_chapter, read_date, timestamp) + VALUES (?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) + """, (user_id, book_id, title, author, cover, last_chapter, today_str)) + conn.commit() + finally: + conn.close() + return jsonify({"success": True}) + + +@books_bp.route("/history/clear", methods=["POST"]) +def clear_history(): + user = get_current_user() + user_id = user["id"] if user else None + if not user_id: + return jsonify({"error": "Vui lòng đăng nhập."}), 401 + conn = get_user_db_conn() + conn.execute("DELETE FROM reading_history WHERE user_id = ?", (user_id,)) + conn.commit() + conn.close() + return jsonify({"success": True}) + + +@books_bp.route("/history/remove", methods=["POST"]) +def remove_history_item(): + """Xóa một mục khỏi lịch sử đọc (theo book_id hoặc url).""" + user = get_current_user() + user_id = user["id"] if user else None + if not user_id: + return jsonify({"error": "Vui lòng đăng nhập."}), 401 + + data = request.json or {} + book_id = data.get("book_id") + url = data.get("url") + + if not book_id and not url: + return jsonify({"error": "Thiếu book_id hoặc url."}), 400 + + conn = get_user_db_conn() + try: + if book_id: + conn.execute( + "DELETE FROM reading_history WHERE user_id = ? AND book_id = ?", + (user_id, book_id) + ) + else: + conn.execute( + "DELETE FROM reading_history WHERE user_id = ? AND url = ?", + (user_id, url) + ) + conn.commit() + return jsonify({"success": True, "message": "Đã xóa khỏi lịch sử."}) + except Exception as e: + logger.error(f"[History] Remove item failed: {e}") + return jsonify({"error": "Không thể xóa mục lịch sử."}), 500 + finally: + conn.close() + + + + +@books_bp.route("/extension/sync", methods=["POST"]) +def extension_sync(): + user = get_current_user() + user_id = user["id"] if user else None + if not user_id: + return jsonify({"error": "Vui lòng đăng nhập trên website chính."}), 401 + + data = request.json or {} + title_zh = data.get("title", "").strip() + author_zh = data.get("author", "").strip() + cover = data.get("cover", "").strip() + last_chapter_zh = data.get("last_chapter", "").strip() + url = data.get("url", "").strip() + action = data.get("action", "history") + + if not title_zh and not url: + return jsonify({"error": "Thiếu thông tin tên truyện hoặc liên kết đường dẫn."}), 400 + + book = None + book_id = None + title_vi = None + author_vi = None + eng = get_engine() + + if not title_zh: + from urllib.parse import urlparse + try: + domain = urlparse(url).netloc + title_vi = f"Truyện ngoài ({domain})" + except Exception: + title_vi = "Truyện ngoài" + title_zh = title_vi + author_vi = "Không rõ" + else: + main_conn = get_db() + book = main_conn.execute( + "SELECT id, title_vietphrase, author_hanviet, cover FROM books WHERE title = ? LIMIT 1", + (title_zh,) + ).fetchone() + + if book: + book_id = book["id"] + title_vi = book["title_vietphrase"] + author_vi = book["author_hanviet"] + if not cover and book["cover"]: + cover = book["cover"] + else: + if not title_vi: + try: + title_vi = eng.translate(title_zh, multi_option=False) + except Exception: + title_vi = title_zh + if not author_vi: + if author_zh: + try: + author_vi = eng.translate(author_zh, multi_option=False) + except Exception: + author_vi = author_zh + else: + author_vi = "Không rõ" + + last_chapter_vi = "Chương đầu" + if last_chapter_zh: + try: + last_chapter_vi = eng.translate(last_chapter_zh, multi_option=False) + except Exception: + last_chapter_vi = last_chapter_zh + + title_vi = title_vi or title_zh + author_vi = author_vi or "Không rõ" + struct_now = time.localtime() + today_str = f"{struct_now.tm_year:04d}-{struct_now.tm_mon:02d}-{struct_now.tm_mday:02d}" + + conn = get_user_db_conn() + try: + if action == "bookshelf": + if not is_vip_request(): + exists = ( + conn.execute("SELECT 1 FROM bookshelf WHERE user_id = ? AND book_id = ?", (user_id, book_id)).fetchone() + if book_id + else conn.execute("SELECT 1 FROM bookshelf WHERE user_id = ? AND url = ?", (user_id, url)).fetchone() + ) is not None + if not exists: + count = conn.execute("SELECT COUNT(*) as cnt FROM bookshelf WHERE user_id = ?", (user_id,)).fetchone()["cnt"] + if count >= 5: + return jsonify({"error": "Tủ sách Standard tối đa 5 truyện. Nâng cấp VIP!"}), 403 + + if book_id: + conn.execute("INSERT OR REPLACE INTO bookshelf (user_id, book_id, title, author, cover, url) VALUES (?, ?, ?, ?, ?, ?)", + (user_id, book_id, title_vi, author_vi, cover, url)) + else: + existing = conn.execute("SELECT id FROM bookshelf WHERE user_id = ? AND url = ?", (user_id, url)).fetchone() + if existing: + conn.execute("UPDATE bookshelf SET title = ?, author = ?, cover = ? WHERE id = ?", + (title_vi, author_vi, cover, existing["id"])) + else: + conn.execute("INSERT INTO bookshelf (user_id, book_id, title, author, cover, url) VALUES (?, NULL, ?, ?, ?, ?)", + (user_id, title_vi, author_vi, cover, url)) + conn.commit() + msg = "Đã lưu vào Tủ sách!" + else: + if book_id: + conn.execute("INSERT OR REPLACE INTO reading_history (user_id, book_id, title, author, cover, last_chapter, read_date, url) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", + (user_id, book_id, title_vi, author_vi, cover, last_chapter_vi, today_str, url)) + else: + existing = conn.execute("SELECT id FROM reading_history WHERE user_id = ? AND url = ?", (user_id, url)).fetchone() + if existing: + conn.execute("UPDATE reading_history SET title = ?, author = ?, cover = ?, last_chapter = ?, read_date = ?, timestamp = CURRENT_TIMESTAMP WHERE id = ?", + (title_vi, author_vi, cover, last_chapter_vi, today_str, existing["id"])) + else: + conn.execute("INSERT INTO reading_history (user_id, book_id, title, author, cover, last_chapter, read_date, url) VALUES (?, NULL, ?, ?, ?, ?, ?, ?)", + (user_id, title_vi, author_vi, cover, last_chapter_vi, today_str, url)) + conn.commit() + msg = "Đã cập nhật Lịch sử!" + finally: + conn.close() + + return jsonify({ + "success": True, "message": msg, + "matched": book is not None, "book_id": book_id, + "title_vi": title_vi, "author_vi": author_vi, "last_chapter_vi": last_chapter_vi + }) + + +@books_bp.route("/system/notifications", methods=["GET"]) +def get_system_notifications(): + user = get_current_user() + notifications = [ + { + "id": "sys-1", + "type": "server", + "message": "Hệ thống máy chủ dịch thuật AI đã được nâng cấp lên v2.4, cải thiện 45% tốc độ phản hồi.", + "time": "Vừa xong" + }, + { + "id": "sys-2", + "type": "promo", + "message": "Sự kiện đặc biệt: Tặng ngay 20% số dư khi thực hiện nạp ví VIP qua chuyển khoản VietQR trong tuần này!", + "time": "5 phút trước" + } + ] + + if user: + user_id = user["id"] + conn = get_user_db_conn() + try: + rows = conn.execute("SELECT title FROM bookshelf WHERE user_id = ? ORDER BY added_at DESC LIMIT 3", (user_id,)).fetchall() + for i, row in enumerate(rows): + notifications.append({ + "id": f"shelf-{i}", + "type": "update", + "message": f"Truyện '{row['title']}' trong Tủ sách của bạn vừa cập nhật thêm chương dịch mới.", + "time": "10 phút trước" + }) + except Exception: + pass + finally: + conn.close() + + notifications.append({ + "id": "comment-1", + "type": "comment", + "message": "Độc giả Lê Hoàng Nam vừa bình luận truyện 'Trọng Sinh Chi Ma Giáo Giáo Chủ': 'Bản dịch AI đọc rất mượt mà...'", + "time": "20 phút trước" + }) + notifications.append({ + "id": "comment-2", + "type": "comment", + "message": "Thành viên VIP_SERVER vừa tối ưu hóa tốc độ load chương mới thành công.", + "time": "1 giờ trước" + }) + return jsonify(notifications) + + +@books_bp.route("/author/", methods=["GET"]) +def get_author_details(author_name): + conn = get_db() + rows = conn.execute( + "SELECT * FROM books WHERE author = ? OR author_hanviet = ? ORDER BY chapters_max DESC", + (author_name, author_name) + ).fetchall() + + if not rows: + rows = conn.execute( + "SELECT * FROM books WHERE LOWER(author) = LOWER(?) OR LOWER(author_hanviet) = LOWER(?) ORDER BY chapters_max DESC", + (author_name, author_name) + ).fetchall() + + fallback_mode = False + if not rows: + # Fallback: if author has no books in database, fetch first 5 books to show as placeholder + rows = conn.execute("SELECT * FROM books LIMIT 5").fetchall() + fallback_mode = True + + books = [] + canonical_chinese = author_name if fallback_mode else (rows[0]["author"] or author_name) + canonical_hanviet = author_name if fallback_mode else (rows[0]["author_hanviet"] or author_name) + + for row in rows: + book_dict = dict(row) + if fallback_mode: + book_dict["author"] = author_name + book_dict["author_hanviet"] = author_name + + parsed_sources = [] + raw_urls = book_dict.get("urls", "") + if raw_urls: + parts = raw_urls.split(" | ") + for part in parts: + if ":" in part: + subparts = part.split(":", 1) + src_name = subparts[0].strip() + src_url = subparts[1].strip() + # Keep raw scheme if complete, else handle + if src_url.startswith("//"): + src_url = "https:" + src_url + parsed_sources.append({ + "source": src_name, + "url": src_url + }) + book_dict["parsed_sources"] = parsed_sources + books.append(book_dict) + + return jsonify({ + "author_chinese": canonical_chinese, + "author_hanviet": canonical_hanviet, + "total_books": len(books), + "books": books + }) + + +@books_bp.route("/books//comments", methods=["POST"]) +def add_book_comment(book_id): + user = get_current_user() + data = request.json or {} + content = data.get("content", "").strip() + is_anonymous = int(data.get("is_anonymous", 0)) + + if not content: + return jsonify({"error": "Nội dung bình luận không được để trống"}), 400 + + user_id = user["id"] if user else None + + # Mã hóa Hybrid RSA-AES bảo mật + enc_data = encrypt_asymmetric_hybrid(content) + + conn = get_user_db_conn() + try: + conn.execute( + """INSERT INTO book_comments + (book_id, user_id, is_anonymous, content_ciphertext, encrypted_aes_key, aes_nonce, aes_tag) + VALUES (?, ?, ?, ?, ?, ?, ?)""", + (book_id, user_id, is_anonymous, + enc_data["ciphertext"], enc_data["encrypted_key"], enc_data["nonce"], enc_data["tag"]) + ) + conn.commit() + return jsonify({"success": True, "message": "Gửi bình luận thành công!"}) + except Exception as e: + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + + +@books_bp.route("/books//comments", methods=["GET"]) +def get_book_comments(book_id): + conn = get_user_db_conn() + try: + rows = conn.execute( + """SELECT c.id, c.user_id, c.is_anonymous, c.content_ciphertext, c.encrypted_aes_key, + c.aes_nonce, c.aes_tag, c.created_at, u.username, u.avatar + FROM book_comments c + LEFT JOIN users u ON c.user_id = u.id + WHERE c.book_id = ? + ORDER BY c.created_at DESC""", + (book_id,) + ).fetchall() + + comments = [] + for r in rows: + # Giải mã Hybrid RSA-AES + decrypted_content = decrypt_asymmetric_hybrid( + r["content_ciphertext"], + r["encrypted_aes_key"], + r["aes_nonce"], + r["aes_tag"] + ) + + comment = { + "id": r["id"], + "created_at": r["created_at"].isoformat() if hasattr(r["created_at"], "isoformat") else r["created_at"], + } + + if r["is_anonymous"] == 1: + comment["username"] = "Đạo hữu ẩn danh" + comment["avatar"] = None + comment["user_id"] = None + else: + comment["username"] = r["username"] or "Khách viếng thăm" + comment["avatar"] = r["avatar"] + comment["user_id"] = r["user_id"] + + comment["content"] = decrypted_content + comments.append(comment) + + return jsonify({"comments": comments}) + except Exception as e: + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + diff --git a/backend/api/developer.py b/backend/api/developer.py new file mode 100644 index 0000000000000000000000000000000000000000..4de716793dd3e2bb81931dbd1803c0b1c7aa0bd5 --- /dev/null +++ b/backend/api/developer.py @@ -0,0 +1,488 @@ +import os +import time +import uuid +import secrets +import base64 +import requests as py_requests +from flask import Blueprint, request, jsonify, send_file +from backend.core.decorators import get_current_user, require_api_key_auth +from backend.database.db_manager import get_user_db_conn +from backend.services.translation import get_engine + +developer_bp = Blueprint("developer", __name__) + +ADMIN_GEMINI_KEY = os.environ.get("ADMIN_GEMINI_KEY", "") + +def serialize_row(row): + if not row: + return {} + d = dict(row) + for k, v in d.items(): + if hasattr(v, "isoformat"): + d[k] = v.isoformat() + return d + + + +def deduct_developer_balance(api_key, amount, model, tokens=0, status_code=200): + conn = get_user_db_conn() + try: + conn.execute( + "INSERT INTO api_usage (api_key, model, tokens, cost, status_code) VALUES (?, ?, ?, ?, ?)", + (api_key, model, tokens, amount, status_code) + ) + conn.execute( + "UPDATE users SET api_balance = api_balance - ? WHERE id = (SELECT user_id FROM api_keys WHERE api_key = ?)", + (amount, api_key) + ) + conn.commit() + except Exception as e: + print(f"[API GATEWAY ERROR] Failed to deduct balance: {e}") + finally: + conn.close() + + +@developer_bp.route("/api/developer/keys", methods=["GET"]) +def api_dev_keys_list(): + user = get_current_user() + print(f"[DEBUG api_dev_keys_list] Current user from auth: {user}") + if not user: + return jsonify({"error": "Vui lòng đăng nhập."}), 401 + + conn = get_user_db_conn() + keys = conn.execute( + "SELECT api_key, name, status, created_at, last_used_at FROM api_keys WHERE user_id = ? AND status = 'active' ORDER BY created_at DESC", + (user["id"],) + ).fetchall() + user_row = conn.execute("SELECT api_balance FROM users WHERE id = ?", (user["id"],)).fetchone() + conn.close() + + balance = user_row["api_balance"] if user_row and user_row["api_balance"] is not None else 0.0 + print(f"[DEBUG api_dev_keys_list] Queried user_id: {user['id']}, found balance: {balance}, keys count: {len(keys)}") + return jsonify({"balance": balance, "keys": [serialize_row(k) for k in keys]}) + + +@developer_bp.route("/api/developer/keys/create", methods=["POST"]) +def api_dev_keys_create(): + user = get_current_user() + if not user: + return jsonify({"error": "Vui lòng đăng nhập."}), 401 + + data = request.json or {} + name = data.get("name", "Default Key").strip()[:50] + new_key = f"sk-tc-{secrets.token_hex(16)}" + + conn = get_user_db_conn() + conn.execute( + "INSERT INTO api_keys (user_id, api_key, name, status) VALUES (?, ?, ?, 'active')", + (user["id"], new_key, name) + ) + conn.commit() + conn.close() + + return jsonify({"success": True, "api_key": new_key, "name": name}) + + +@developer_bp.route("/api/developer/keys/delete", methods=["POST"]) +def api_dev_keys_delete(): + user = get_current_user() + if not user: + return jsonify({"error": "Vui lòng đăng nhập."}), 401 + + data = request.json or {} + api_key = data.get("api_key", "").strip() + if not api_key: + return jsonify({"error": "Thiếu API Key cần xóa."}), 400 + + conn = get_user_db_conn() + conn.execute( + "UPDATE api_keys SET status = 'revoked' WHERE user_id = ? AND api_key = ?", + (user["id"], api_key) + ) + conn.commit() + conn.close() + return jsonify({"success": True}) + + +@developer_bp.route("/api/developer/usage", methods=["GET"]) +def api_dev_usage(): + user = get_current_user() + if not user: + return jsonify({"error": "Vui lòng đăng nhập."}), 401 + + conn = get_user_db_conn() + keys_rows = conn.execute("SELECT api_key FROM api_keys WHERE user_id = ?", (user["id"],)).fetchall() + keys = [k["api_key"] for k in keys_rows] + + if not keys: + conn.close() + return jsonify({"usage": []}) + + placeholders = ",".join(["?"] * len(keys)) + usage = conn.execute( + f"SELECT * FROM api_usage WHERE api_key IN ({placeholders}) ORDER BY timestamp DESC LIMIT 100", + keys + ).fetchall() + conn.close() + return jsonify({"usage": [serialize_row(u) for u in usage]}) + + +@developer_bp.route("/v1/chat/completions", methods=["POST"]) +@require_api_key_auth +def openai_chat_completions(): + api_key = request.api_key + data = request.json or {} + messages = data.get("messages", []) + model = data.get("model", "gemini-1.5-flash") + + if not messages: + return jsonify({"error": "Missing messages array"}), 400 + + prompt_length = sum(len(m.get("content", "")) for m in messages) + cost = max(20.0, prompt_length * 0.02) + + if request.api_balance < cost: + return jsonify({"error": f"Số dư không đủ. Chi phí ước tính: {cost:.2f}đ, Số dư: {request.api_balance:.2f}đ"}), 402 + + if not ADMIN_GEMINI_KEY: + return jsonify({"error": "Hệ thống chưa được Admin cấu hình khóa Gemini."}), 501 + + try: + contents = [] + system_instruction = "" + + for msg in messages: + role = msg.get("role") + content = msg.get("content", "") + if role == "system": + system_instruction = content + else: + contents.append({ + "role": "user" if role == "user" else "model", + "parts": [{"text": content}] + }) + + url = f"https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent?key={ADMIN_GEMINI_KEY}" + payload = {"contents": contents} + if system_instruction: + payload["systemInstruction"] = {"parts": [{"text": system_instruction}]} + + res = py_requests.post(url, json=payload, timeout=30) + + if res.status_code != 200: + deduct_developer_balance(api_key, 0.0, model, prompt_length, res.status_code) + return jsonify({"error": f"Google Gemini API error: {res.text}"}), res.status_code + + gemini_data = res.json() + response_text = gemini_data.get("candidates", [{}])[0].get("content", {}).get("parts", [{}])[0].get("text", "") + + deduct_developer_balance(api_key, cost, model, prompt_length + len(response_text), 200) + + res_id = f"chatcmpl-{uuid.uuid4().hex}" + return jsonify({ + "id": res_id, + "object": "chat.completion", + "created": int(time.time()), + "model": model, + "choices": [{ + "index": 0, + "message": {"role": "assistant", "content": response_text}, + "finish_reason": "stop" + }], + "usage": { + "prompt_tokens": int(prompt_length / 4), + "completion_tokens": int(len(response_text) / 4), + "total_tokens": int((prompt_length + len(response_text)) / 4) + } + }) + except Exception as e: + deduct_developer_balance(api_key, 0.0, model, prompt_length, 500) + return jsonify({"error": f"API Gateway Exception: {str(e)}"}), 500 + + +@developer_bp.route("/api/v1/translate", methods=["POST"]) +@require_api_key_auth +def api_v1_translate(): + api_key = request.api_key + data = request.json or {} + texts = data.get("texts", []) + mode = data.get("mode", "fast") + + if not texts: + return jsonify({"error": "Missing texts array"}), 400 + + total_chars = sum(len(t) for t in texts) + cost = total_chars * 0.01 + + if request.api_balance < cost: + return jsonify({"error": f"Số dư không đủ. Chi phí ước tính: {cost:.2f}đ, Số dư: {request.api_balance:.2f}đ"}), 402 + + try: + eng = get_engine() + translations = [] + for text in texts: + if not text.strip(): + translations.append(text) + else: + translations.append(eng.translate(text, multi_option=False, mode=mode)) + + deduct_developer_balance(api_key, cost, f"vietphrase-{mode}", total_chars, 200) + return jsonify({"translations": translations, "characters": total_chars, "cost": cost}) + except Exception as e: + deduct_developer_balance(api_key, 0.0, f"vietphrase-{mode}", total_chars, 500) + return jsonify({"error": f"Translation Error: {str(e)}"}), 500 + + +@developer_bp.route("/v1/audio/speech", methods=["POST"]) +@require_api_key_auth +def openai_audio_speech(): + api_key = request.api_key + data = request.json or {} + input_text = data.get("input", "").strip() + + if not input_text: + return jsonify({"error": "Missing 'input' text"}), 400 + + cost = len(input_text) * 0.1 + if request.api_balance < cost: + return jsonify({"error": f"Số dư không đủ. Chi phí: {cost:.2f}đ"}), 402 + + # 1. Check if Local TTS Server is configured (host machine) + local_tts_url = os.environ.get("LOCAL_TTS_URL", "") + if local_tts_url: + try: + payload = { + "input": input_text, + "speed": float(data.get("speed", 1.0)), + "voice": data.get("voice", "the_gioi_hoan_my"), + "ref_audio": data.get("ref_audio"), + "ref_text": data.get("ref_text") + } + if "bypass_cache" in data: + payload["bypass_cache"] = data["bypass_cache"] + if "temperature" in data: + payload["temperature"] = data["temperature"] + if "steps" in data: + payload["steps"] = data["steps"] + print(f"[Local TTS Proxy] Forwarding request to {local_tts_url} with voice={payload['voice']}, speed={payload['speed']}, bypass_cache={payload.get('bypass_cache')}") + r = py_requests.post(local_tts_url, json=payload, timeout=(2.0, 60.0)) + if r.status_code == 200: + import io + deduct_developer_balance(api_key, cost, f"local-tts-{payload['voice']}", len(input_text), 200) + return send_file( + io.BytesIO(r.content), + mimetype="audio/wav", + as_attachment=False + ) + print(f"[Local TTS Proxy Error]: {r.status_code} - {r.text}") + except Exception as e: + print(f"[Local TTS Proxy Exception]: {e}") + + # 2. RunPod Fallback + runpod_api_key = os.environ.get("RUNPOD_API_TOKEN", os.environ.get("RUNPOD_API_KEY", "")) + + runpod_endpoint_id = os.environ.get("RUNPOD_TTS_ENDPOINT_ID", "") + + if runpod_api_key and runpod_endpoint_id: + try: + url = f"https://api.runpod.ai/v1/{runpod_endpoint_id}/runsync" + headers = {"Authorization": f"Bearer {runpod_api_key}", "Content-Type": "application/json"} + payload = { + "input": { + "text": input_text, + "speed": 1.0, + "voice": data.get("voice", "the_gioi_hoan_my") + } + } + r = py_requests.post(url, json=payload, headers=headers, timeout=45) + res = r.json() + + if r.status_code == 200 and res.get("status") == "COMPLETED": + audio_b64 = res.get("output", {}).get("audio_base64", "") + if audio_b64: + import io + audio_data = base64.b64decode(audio_b64) + deduct_developer_balance(api_key, cost, "runpod-matcha-tts", len(input_text), 200) + return send_file( + io.BytesIO(audio_data), + mimetype="audio/wav" if res.get("output", {}).get("format") == "wav" else "audio/mpeg", + as_attachment=False + ) + print(f"[RunPod TTS Error]: {res}") + except Exception as e: + print(f"[RunPod TTS exception]: {e}") + + # Fallback: Generate a tiny 1-second silent WAV for testing/sandbox purposes + try: + import struct + import io + num_samples = 8000 + # 8-bit PCM silence is represented by 128 + data_bytes = bytearray([128] * num_samples) + header = struct.pack( + '<4sI4s4sIHHIIHH4sI', + b'RIFF', + 36 + num_samples, + b'WAVE', + b'fmt ', + 16, + 1, # PCM + 1, # Mono + 8000, # Sample rate + 8000, # Byte rate + 1, # Block align + 8, # Bits per sample + b'data', + num_samples + ) + audio_data = bytes(header + data_bytes) + deduct_developer_balance(api_key, cost, "local-silent-tts-fallback", len(input_text), 200) + return send_file( + io.BytesIO(audio_data), + mimetype="audio/wav", + as_attachment=False + ) + except Exception as e: + return jsonify({"error": f"Failed to generate fallback TTS: {str(e)}"}), 500 + + +@developer_bp.route("/api/developer/all-sessions", methods=["GET"]) +def api_developer_all_sessions(): + user = get_current_user() + if not user or user.get("username") not in ["admin", "havucong25", "congkx123789"]: + return jsonify({"error": "Quyền truy cập bị từ chối."}), 403 + + conn = get_user_db_conn() + try: + rows = conn.execute( + """SELECT lh.id, lh.user_id, u.username, lh.ip_address, lh.os, lh.browser, lh.device_type, lh.login_time, lh.last_active, lh.status + FROM login_history lh + JOIN users u ON lh.user_id = u.id + ORDER BY lh.login_time DESC LIMIT 100""" + ).fetchall() + + sessions = [] + for r in rows: + s = dict(r) + if hasattr(s["login_time"], "isoformat"): + s["login_time"] = s["login_time"].isoformat() + if hasattr(s["last_active"], "isoformat"): + s["last_active"] = s["last_active"].isoformat() + sessions.append(s) + + return jsonify({ + "success": True, + "sessions": sessions + }) + except Exception as e: + return jsonify({"error": str(e), "success": False}), 500 + finally: + conn.close() + + +@developer_bp.route("/api/developer/sessions/revoke", methods=["POST"]) +def api_developer_revoke_session(): + user = get_current_user() + if not user or user.get("username") not in ["admin", "havucong25", "congkx123789"]: + return jsonify({"error": "Quyền truy cập bị từ chối."}), 403 + + data = request.json or {} + session_id = data.get("session_id") + if not session_id: + return jsonify({"error": "Missing session_id", "success": False}), 400 + + conn = get_user_db_conn() + try: + row = conn.execute( + "SELECT token FROM login_history WHERE id = ?", + (session_id,) + ).fetchone() + if not row: + return jsonify({"error": "Session not found", "success": False}), 404 + + token = row["token"] + conn.execute("UPDATE login_history SET status = 'logged_out' WHERE id = ?", (session_id,)) + if token: + conn.execute("UPDATE refresh_tokens SET revoked = 1 WHERE token = ?", (token,)) + conn.commit() + return jsonify({"message": "Đã đăng xuất thiết bị thành công", "success": True}) + except Exception as e: + return jsonify({"error": str(e), "success": False}), 500 + finally: + conn.close() + + +@developer_bp.route("/api/releases", methods=["GET"]) +def api_get_releases(): + conn = get_user_db_conn() + try: + rows = conn.execute( + "SELECT platform, version, download_url, patch_url, file_size, release_notes, updated_at FROM app_releases ORDER BY updated_at DESC" + ).fetchall() + releases = {} + for r in rows: + plat = r["platform"] + if plat not in releases: + releases[plat] = { + "version": r["version"], + "download_url": r["download_url"], + "patch_url": r["patch_url"], + "file_size": r["file_size"], + "release_notes": r["release_notes"], + "updated_at": r["updated_at"].isoformat() if hasattr(r["updated_at"], "isoformat") else r["updated_at"], + "history": [] + } + + releases[plat]["history"].append({ + "version": r["version"], + "download_url": r["download_url"], + "patch_url": r["patch_url"], + "file_size": r["file_size"], + "release_notes": r["release_notes"], + "updated_at": r["updated_at"].isoformat() if hasattr(r["updated_at"], "isoformat") else r["updated_at"] + }) + return jsonify({"success": True, "releases": releases}) + except Exception as e: + return jsonify({"error": str(e), "success": False}), 500 + finally: + conn.close() + + +@developer_bp.route("/api/releases/update", methods=["POST"]) +def api_update_release(): + user = get_current_user() + if not user or user.get("username") not in ["admin", "havucong25", "congkx123789"]: + return jsonify({"error": "Quyền truy cập bị từ chối. Chỉ dành cho admin.", "success": False}), 403 + + data = request.json or {} + platform = data.get("platform") + version = data.get("version") + download_url = data.get("download_url") + file_size = data.get("file_size") + release_notes = data.get("release_notes") + + if not platform or platform not in ['extension', 'desktop_linux', 'desktop_windows']: + return jsonify({"error": "Platform không hợp lệ.", "success": False}), 400 + + conn = get_user_db_conn() + try: + existing = conn.execute("SELECT 1 FROM app_releases WHERE platform = ? AND version = ?", (platform, version)).fetchone() + if existing: + conn.execute( + """UPDATE app_releases + SET download_url = ?, file_size = ?, release_notes = ?, updated_at = CURRENT_TIMESTAMP + WHERE platform = ? AND version = ?""", + (download_url, file_size, release_notes, platform, version) + ) + else: + conn.execute( + """INSERT INTO app_releases (platform, version, download_url, file_size, release_notes) + VALUES (?, ?, ?, ?, ?)""", + (platform, version, download_url, file_size, release_notes) + ) + conn.commit() + return jsonify({"message": f"Cập nhật phiên bản {platform} v{version} thành công.", "success": True}) + except Exception as e: + return jsonify({"error": str(e), "success": False}), 500 + finally: + conn.close() diff --git a/backend/api/epub.py b/backend/api/epub.py new file mode 100644 index 0000000000000000000000000000000000000000..1b9b4d320dbe78600cb70b2472da0b941a6b032e --- /dev/null +++ b/backend/api/epub.py @@ -0,0 +1,158 @@ +import os +import tempfile +import uuid +from flask import Blueprint, request, jsonify, send_file +from backend.api.books import is_vip_request +from backend.services.translation import get_engine, parse_custom_dict_text +from backend.services import epub_service + +epub_bp = Blueprint("epub", __name__, url_prefix="/api/epub") + + +@epub_bp.route("/translate", methods=["POST"]) +def api_epub_translate(): + if not is_vip_request(): + return jsonify({"error": "Chức năng Dịch EPUB nâng cao chỉ dành cho thành viên VIP!"}), 403 + + if "file" not in request.files: + return jsonify({"error": "Không tìm thấy file EPUB tải lên!"}), 400 + + file = request.files["file"] + if file.filename == "": + return jsonify({"error": "Tên file rỗng!"}), 400 + + mode = request.form.get("mode", "fast") + limit_chapters = int(request.form.get("limit_chapters", "-1")) + clean_styles = request.form.get("clean_styles", "false").lower() == "true" + strip_images = request.form.get("strip_images", "false").lower() == "true" + strip_fonts = request.form.get("strip_fonts", "false").lower() == "true" + custom_dict_text = request.form.get("custom_dict", "").strip() + custom_dict = parse_custom_dict_text(custom_dict_text) + + temp_dir = tempfile.gettempdir() + src_path = os.path.join(temp_dir, f"src_{uuid.uuid4().hex}.epub") + dest_path = os.path.join(temp_dir, f"translated_{uuid.uuid4().hex}.epub") + + try: + file.save(src_path) + eng = get_engine() + duration = epub_service.translate_epub_file( + src_path, dest_path, eng, mode=mode, + limit_chapters=limit_chapters, custom_dict=custom_dict, + clean_styles=clean_styles, strip_images=strip_images, strip_fonts=strip_fonts + ) + print(f"[VIP EPUB] Translated {file.filename} in {duration:.2f}s in mode {mode}") + + base, ext = os.path.splitext(file.filename) + output_filename = f"{base}_Dich_{mode}{ext}" + + return send_file( + dest_path, + as_attachment=True, + download_name=output_filename, + mimetype="application/epub+zip" + ) + except Exception as e: + print(f"[VIP EPUB ERROR] Translate failed: {e}") + return jsonify({"error": f"Lỗi trong quá trình dịch EPUB: {str(e)}"}), 500 + finally: + if os.path.exists(src_path): + try: + os.remove(src_path) + except Exception: + pass + + +@epub_bp.route("/convert-txt", methods=["POST"]) +def api_epub_convert_txt(): + if not is_vip_request(): + return jsonify({"error": "Chức năng chuyển đổi truyện sang EPUB chỉ dành cho thành viên VIP!"}), 403 + + title = request.form.get("title", "Truyện convert").strip() + author = request.form.get("author", "Vô danh").strip() + description = request.form.get("description", "").strip() + split_regex = request.form.get("split_regex", r"第\s*\d+\s*[章|回|节]").strip() + translate_bool = request.form.get("translate", "false").lower() == "true" + mode = request.form.get("mode", "fast") + custom_dict_text = request.form.get("custom_dict", "").strip() + + txt_content = "" + if "file" in request.files: + file = request.files["file"] + if file.filename != "": + txt_content = file.read().decode("utf-8", errors="ignore") + else: + txt_content = request.form.get("text", "").strip() + + if not txt_content: + return jsonify({"error": "Nội dung văn bản rỗng!"}), 400 + + custom_dict = parse_custom_dict_text(custom_dict_text) + temp_dir = tempfile.gettempdir() + dest_path = os.path.join(temp_dir, f"converted_{uuid.uuid4().hex}.epub") + + try: + eng = get_engine() if translate_bool else None + epub_service.convert_txt_to_epub( + txt_content, title, author, split_regex, dest_path, + description=description, engine=eng, + mode=mode if translate_bool else None, custom_dict=custom_dict + ) + return send_file( + dest_path, + as_attachment=True, + download_name=f"{title}.epub", + mimetype="application/epub+zip" + ) + except Exception as e: + print(f"[VIP EPUB ERROR] Convert TXT failed: {e}") + return jsonify({"error": f"Lỗi tạo EPUB: {str(e)}"}), 500 + + +@epub_bp.route("/optimize", methods=["POST"]) +def api_epub_optimize(): + if not is_vip_request(): + return jsonify({"error": "Chức năng Tối ưu hóa EPUB chỉ dành cho thành viên VIP!"}), 403 + + if "file" not in request.files: + return jsonify({"error": "Không tìm thấy file EPUB tải lên!"}), 400 + + file = request.files["file"] + if file.filename == "": + return jsonify({"error": "Tên file rỗng!"}), 400 + + strip_images = request.form.get("strip_images", "false").lower() == "true" + strip_fonts = request.form.get("strip_fonts", "false").lower() == "true" + + temp_dir = tempfile.gettempdir() + src_path = os.path.join(temp_dir, f"opt_src_{uuid.uuid4().hex}.epub") + dest_path = os.path.join(temp_dir, f"opt_dest_{uuid.uuid4().hex}.epub") + + try: + file.save(src_path) + + class MockEngine: + def translate(self, text, **kwargs): + return text + + epub_service.translate_epub_file( + src_path, dest_path, MockEngine(), mode=None, + limit_chapters=-1, custom_dict=None, clean_styles=True, + strip_images=strip_images, strip_fonts=strip_fonts + ) + + base, ext = os.path.splitext(file.filename) + return send_file( + dest_path, + as_attachment=True, + download_name=f"{base}_Optimized{ext}", + mimetype="application/epub+zip" + ) + except Exception as e: + return jsonify({"error": f"Lỗi tối ưu EPUB: {str(e)}"}), 500 + finally: + if os.path.exists(src_path): + try: + os.remove(src_path) + except Exception: + pass diff --git a/backend/api/monitoring.py b/backend/api/monitoring.py new file mode 100644 index 0000000000000000000000000000000000000000..d43977d48dee8f754dbe4e63f918eb26aa9e2548 --- /dev/null +++ b/backend/api/monitoring.py @@ -0,0 +1,198 @@ +import os +from flask import Blueprint, jsonify, request +from backend.core.decorators import get_current_user +from backend.core.monitoring import collect_all_metrics +from backend.services.alert_service import check_resources_and_alert + +monitoring_bp = Blueprint("monitoring", __name__) + +@monitoring_bp.route("/api/admin/metrics", methods=["GET"]) +def get_metrics(): + """ + Get detailed system metrics and statistics. + Access is restricted to admin via X-Admin-Key header or logged-in 'admin' user. + """ + # Authorization checks + is_admin = False + + # 1. Check for secret X-Admin-Key in request headers + admin_key = request.headers.get("X-Admin-Key") + expected_key = os.environ.get("ADMIN_PAYMENT_KEY", "LYVUHA_ADMIN_2026") + if admin_key and admin_key == expected_key: + is_admin = True + + # 2. Check logged-in user session/token + if not is_admin: + current_user = get_current_user() + if current_user and current_user.get("username") == "admin": + is_admin = True + + if not is_admin: + return jsonify({"error": "Unauthorized admin access required"}), 403 + + try: + # Collect system statistics and details + metrics = collect_all_metrics() + + # Trigger checks and alerts if RAM or Disk usage is critical + check_resources_and_alert() + + return jsonify({ + "success": True, + "metrics": metrics + }), 200 + except Exception as e: + return jsonify({ + "success": False, + "error": f"Failed to retrieve system metrics: {str(e)}" + }), 500 + + +@monitoring_bp.route("/api/admin/logs", methods=["GET"]) +def get_logs(): + """ + Get or download application logs. + Access is restricted to admin via X-Admin-Key header or logged-in 'admin' user. + """ + is_admin = False + + # 1. Check for secret X-Admin-Key in request headers + admin_key = request.headers.get("X-Admin-Key") + expected_key = os.environ.get("ADMIN_PAYMENT_KEY", "LYVUHA_ADMIN_2026") + if admin_key and admin_key == expected_key: + is_admin = True + + # 2. Check logged-in user session/token + if not is_admin: + current_user = get_current_user() + if current_user and current_user.get("username") == "admin": + is_admin = True + + if not is_admin: + return jsonify({"error": "Unauthorized admin access required"}), 403 + + from backend.config import Config + log_path = os.path.join(Config.ROOT_DIR, "logs", "app.log") + + # Handle file download option + if request.args.get("download") == "true": + if not os.path.exists(log_path): + return jsonify({"error": "Log file does not exist"}), 404 + from flask import send_file + return send_file(log_path, as_attachment=True, download_name="app.log") + + # Handle standard retrieval + lines_count = request.args.get("lines", default=100, type=int) + lines_count = max(1, min(lines_count, 2000)) + + if not os.path.exists(log_path): + return jsonify({ + "success": True, + "lines_returned": 0, + "logs": [], + "message": "Log file not found." + }), 200 + + try: + from collections import deque + with open(log_path, "r", encoding="utf-8", errors="ignore") as f: + last_lines = list(deque(f, maxlen=lines_count)) + + return jsonify({ + "success": True, + "lines_returned": len(last_lines), + "logs": last_lines + }), 200 + except Exception as e: + return jsonify({ + "success": False, + "error": f"Failed to read logs: {str(e)}" + }), 500 + + +@monitoring_bp.route("/api/admin/profiler", methods=["GET"]) +def get_profiler_stats(): + """ + Get recent request profiles with latency breakdown (Total, DB, External, CPU). + Access is restricted to admin via X-Admin-Key header or logged-in 'admin' user. + """ + is_admin = False + admin_key = request.headers.get("X-Admin-Key") + expected_key = os.environ.get("ADMIN_PAYMENT_KEY", "LYVUHA_ADMIN_2026") + if admin_key and admin_key == expected_key: + is_admin = True + + if not is_admin: + current_user = get_current_user() + if current_user and current_user.get("username") == "admin": + is_admin = True + + if not is_admin: + return jsonify({"error": "Unauthorized admin access required"}), 403 + + try: + from backend.core.profiler import get_recent_profiles + profiles = get_recent_profiles() + return jsonify({ + "success": True, + "count": len(profiles), + "profiles": profiles + }), 200 + except Exception as e: + return jsonify({ + "success": False, + "error": f"Failed to retrieve profiler stats: {str(e)}" + }), 500 + + +@monitoring_bp.route("/api/logs/error", methods=["POST", "OPTIONS"]) +def log_frontend_error(): + """ + Receive fatal crash reports from the Frontend ErrorBoundary + and instantly send an email alert to the admin. + """ + if request.method == "OPTIONS": + return jsonify({}), 200 + + try: + data = request.json or {} + message = data.get("message", "Unknown Error") + stack = data.get("stack", "No stack trace provided.") + url = data.get("url", "Unknown URL") + user_agent = data.get("userAgent", "Unknown Browser") + time = data.get("time", "Unknown Time") + + html_content = f""" +
+
+

🚨 Tiên Hiệp AI - Frontend Crash Alert

+
+
+

Thời gian: {time}

+

URL phát sinh lỗi: {url}

+

Trình duyệt: {user_agent}

+
+

Lỗi (Error Message):

+
+ {message} +
+

Mã Lỗi (Stack Trace):

+
{stack}
+
+
+ """ + + # Gửi email ngầm (không làm chậm server) + from backend.services.email_service import send_email_async + admin_email = os.environ.get("ADMIN_EMAIL", "havucong@lyvuha.com") + + send_email_async( + to_email=admin_email, + subject=f"[CRASH ALERT] Lỗi nghiêm trọng tại Tiên Hiệp AI ({url})", + html_content=html_content + ) + + return jsonify({"success": True, "message": "Crash report received and email queued."}), 200 + except Exception as e: + print(f"❌ Failed to process frontend crash log: {e}") + return jsonify({"success": False, "error": str(e)}), 500 diff --git a/backend/api/payment.py b/backend/api/payment.py new file mode 100644 index 0000000000000000000000000000000000000000..c9cded8588f7844d67829f511041583fd2d0a22f --- /dev/null +++ b/backend/api/payment.py @@ -0,0 +1,235 @@ +import os +import re +from datetime import datetime +from flask import Blueprint, request, jsonify, session +from backend.config import Config +from backend.core.decorators import get_current_user +from backend.core.security import verify_access_token +from backend.core.rate_limit import check_rate_limit, get_client_ip +from backend.database.db_manager import get_user_db_conn +from backend.services.payment_service import ( + create_payment_order, confirm_payment, verify_payos_webhook_signature +) +from backend.services.auth_service import check_vip_expiry, activate_vip + +payment_bp = Blueprint("payment", __name__, url_prefix="/api/payment") + + +def _get_user_id_from_request(): + """Helper to get user_id from session or JWT.""" + user = get_current_user() + if user: + return user["id"] + auth_header = request.headers.get("Authorization", "") + if auth_header.startswith("Bearer "): + payload = verify_access_token(auth_header[7:]) + if payload: + return int(payload["sub"]) + return None + + +def _process_payment_webhook(order_id, amount): + """Internal handler called from the webhook to confirm payment & activate VIP/topup.""" + conn = get_user_db_conn() + payment = conn.execute( + "SELECT * FROM payments WHERE order_id = ? AND status = 'pending'", (order_id,) + ).fetchone() + + if not payment: + conn.close() + return jsonify({"error": "Order not found or already processed"}), 404 + + if amount > 0 and abs(amount - payment["amount"]) > 100: + conn.close() + return jsonify({"error": "Amount mismatch"}), 400 + + now = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S") + conn.execute( + "UPDATE payments SET status = 'completed', completed_at = ? WHERE id = ?", + (now, payment["id"]) + ) + conn.commit() + conn.close() + + if payment["plan"].startswith("topup_"): + conn = get_user_db_conn() + conn.execute( + "UPDATE users SET api_balance = COALESCE(api_balance, 0.0) + ? WHERE id = ?", + (payment["amount"], payment["user_id"]) + ) + conn.commit() + conn.close() + return jsonify({"success": True, "message": f"Nạp thành công {payment['amount']:,}đ vào số dư API!".replace(",", ".")}) + else: + activate_vip(payment["user_id"], payment["plan"]) + if session.get("user_id") == payment["user_id"]: + session["vip_status"] = 1 + print(f"[PAYMENT] ✅ Order {order_id} completed — User #{payment['user_id']} → VIP {payment['plan']}") + return jsonify({"success": True, "message": "Payment confirmed, VIP activated!"}) + + +@payment_bp.route("/plans", methods=["GET"]) +def api_payment_plans(): + lang = request.args.get("lang", "vi") + plans = [] + for key, plan in Config.VIP_PLANS.items(): + plans.append({ + "id": key, + "name": plan.get(f"name_{lang}", plan["name_vi"]), + "description": plan.get(f"description_{lang}", plan["description_vi"]), + "price": plan["price"], + "price_formatted": f"{plan['price']:,}đ".replace(",", "."), + "duration_days": plan["duration_days"], + }) + return jsonify({"plans": plans}) + + +@payment_bp.route("/create", methods=["POST"]) +def api_payment_create(): + user_id = _get_user_id_from_request() + if not user_id: + return jsonify({"error": "Vui lòng đăng nhập để mua VIP."}), 401 + + ip = get_client_ip() + if check_rate_limit("payment", ip): + return jsonify({"error": "Bạn đã tạo quá nhiều đơn hàng. Vui lòng thử lại sau."}), 429 + + data = request.json or {} + plan = data.get("plan", "month") + + result, status_code = create_payment_order(user_id, plan) + return jsonify(result), status_code + + +@payment_bp.route("/status/", methods=["GET"]) +def api_payment_status(order_id): + user_id = _get_user_id_from_request() + + conn = get_user_db_conn() + if user_id: + payment = conn.execute( + "SELECT * FROM payments WHERE order_id = ? AND user_id = ?", (order_id, user_id) + ).fetchone() + else: + payment = conn.execute( + "SELECT * FROM payments WHERE order_id = ?", (order_id,) + ).fetchone() + conn.close() + + if not payment: + return jsonify({"error": "Payment order not found."}), 404 + + return jsonify({ + "order_id": payment["order_id"], + "plan": payment["plan"], + "amount": payment["amount"], + "status": payment["status"], + "created_at": payment["created_at"], + "completed_at": payment["completed_at"] + }) + + +@payment_bp.route("/webhook", methods=["POST"]) +def api_payment_webhook(): + # Verify PAYMENT_WEBHOOK_KEY if set in environment + webhook_key = os.environ.get("PAYMENT_WEBHOOK_KEY", "") + if webhook_key: + auth_header = request.headers.get("Authorization", "") + provided_key = auth_header.replace("Bearer ", "").replace("Apikey ", "").strip() + query_key = request.args.get("webhook_key", "") + if provided_key != webhook_key and query_key != webhook_key: + return jsonify({"error": "Unauthorized webhook request"}), 401 + + data = request.json or {} + + # PayOS format + if "data" in data and "orderCode" in data.get("data", {}): + order_code = str(data["data"]["orderCode"]) + amount = data["data"].get("amount", 0) + checksum_key = Config.PAYMENT_CONFIG.get("payos_checksum_key", "") + if checksum_key and "signature" in data: + if not verify_payos_webhook_signature(data["data"], data.get("signature", ""), checksum_key): + return jsonify({"error": "Invalid signature"}), 403 + return _process_payment_webhook(order_code, amount) + + # SePay / Generic format + if "transferAmount" in data: + content = data.get("content", "") + amount = data.get("transferAmount", 0) + match = re.search(r"(VIP\w+)", content.upper()) + if match: + return _process_payment_webhook(match.group(1), amount) + + return jsonify({"error": "Invalid webhook payload"}), 400 + + +@payment_bp.route("/confirm-manual", methods=["POST"]) +def api_payment_confirm_manual(): + data = request.json or {} + admin_key = data.get("admin_key", "") + order_id = data.get("order_id", "") + + ADMIN_KEY = os.environ.get("ADMIN_PAYMENT_KEY") + if not ADMIN_KEY: + ADMIN_KEY = "SECURE_SECRET_RANDOM_KEY_9988_ADMIN" + + is_admin = False + if admin_key and admin_key == ADMIN_KEY: + is_admin = True + + if not is_admin: + return jsonify({"error": "Unauthorized admin access required"}), 403 + + if not order_id: + return jsonify({"error": "order_id is required"}), 400 + return _process_payment_webhook(order_id, 0) + + +@payment_bp.route("/history", methods=["GET"]) +def api_payment_history(): + user_id = _get_user_id_from_request() + if not user_id: + return jsonify({"error": "Unauthorized"}), 401 + + conn = get_user_db_conn() + payments = conn.execute( + "SELECT order_id, plan, amount, status, created_at, completed_at FROM payments WHERE user_id = ? ORDER BY created_at DESC LIMIT 20", + (user_id,) + ).fetchall() + conn.close() + return jsonify({"payments": [dict(p) for p in payments]}) + + +@payment_bp.route("/vip-status", methods=["GET"]) +def api_user_vip_status(): + user_id = _get_user_id_from_request() + if not user_id: + return jsonify({"error": "Unauthorized"}), 401 + + check_vip_expiry(user_id) + conn = get_user_db_conn() + user = conn.execute("SELECT vip_status, vip_plan, vip_expiry FROM users WHERE id = ?", (user_id,)).fetchone() + conn.close() + + if not user: + return jsonify({"error": "User not found"}), 404 + + days_remaining = 0 + if user["vip_expiry"]: + try: + expiry_val = user["vip_expiry"] + if isinstance(expiry_val, str): + expiry = datetime.strptime(expiry_val, "%Y-%m-%d %H:%M:%S") + else: + expiry = expiry_val + days_remaining = max(0, (expiry - datetime.utcnow()).days) + except Exception: + pass + + return jsonify({ + "vip_status": user["vip_status"], + "vip_plan": user["vip_plan"], + "vip_expiry": user["vip_expiry"], + "days_remaining": days_remaining, + "is_active": user["vip_status"] == 1 + }) diff --git a/backend/api/sects.py b/backend/api/sects.py new file mode 100644 index 0000000000000000000000000000000000000000..a05eb23b45c823970974e8acceb53a11561fcbfa --- /dev/null +++ b/backend/api/sects.py @@ -0,0 +1,1248 @@ +from flask import Blueprint, request, jsonify +from backend.core.decorators import jwt_required, get_current_user +from backend.database.db_manager import get_user_db_conn +from backend.core.logger import logger +from backend.core.security import encrypt_message, decrypt_message +from datetime import datetime + +sects_bp = Blueprint("sects", __name__) + +def serialize_row(row): + if not row: + return {} + d = dict(row) + for k, v in d.items(): + if hasattr(v, "isoformat"): + d[k] = v.isoformat() + return d + +@sects_bp.route("/api/sects/list", methods=["GET"]) +def list_sects(): + conn = get_user_db_conn() + try: + rows = conn.execute(""" + SELECT s.id, s.name, s.slogan, s.badge, s.level, s.contribution, s.created_at, + u.username as leader_name, + (SELECT COUNT(*) FROM sect_members WHERE sect_id = s.id) as member_count + FROM sects s + LEFT JOIN users u ON s.leader_id = u.id + ORDER BY s.contribution DESC, s.created_at DESC + """).fetchall() + + user = get_current_user() + user_requests = [] + if user: + req_rows = conn.execute("SELECT sect_id FROM sect_join_requests WHERE user_id = ? AND status = 'pending'", (user["id"],)).fetchall() + user_requests = [r["sect_id"] for r in req_rows] + + return jsonify({ + "sects": [serialize_row(r) for r in rows], + "pending_requests": user_requests + }) + except Exception as e: + logger.error(f"Error listing sects: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + +@sects_bp.route("/api/sects/create", methods=["POST"]) +@jwt_required +def create_sect(): + user = get_current_user() + data = request.json or {} + name = data.get("name", "").strip() + slogan = data.get("slogan", "").strip() + badge = data.get("badge", "purple").strip() + + if not name: + return jsonify({"error": "Tên tông môn không được để trống"}), 400 + + conn = get_user_db_conn() + try: + # Check if user is already in a sect + in_sect = conn.execute("SELECT sect_id FROM sect_members WHERE user_id = ?", (user["id"],)).fetchone() + if in_sect: + return jsonify({"error": "Bạn đã thuộc một tông môn khác, hãy rời tông cũ trước"}), 400 + + # Check if name exists + exists = conn.execute("SELECT id FROM sects WHERE name = ?", (name,)).fetchone() + if exists: + return jsonify({"error": "Tên tông môn này đã được lập từ trước"}), 400 + + cursor = conn.execute( + "INSERT INTO sects (name, slogan, badge, leader_id, announcement) VALUES (?, ?, ?, ?, ?)", + (name, slogan, badge, user["id"], f"Tông môn {name} được thành lập. Chúc các đồng môn tu tiên đắc đạo!") + ) + sect_id = cursor.lastrowid + + conn.execute( + "INSERT INTO sect_members (sect_id, user_id, role, contribution) VALUES (?, ?, 'leader', 100)", + (sect_id, user["id"]) + ) + conn.execute( + "UPDATE sects SET contribution = 100 WHERE id = ?", + (sect_id,) + ) + # Delete any pending join requests of this user elsewhere + conn.execute("DELETE FROM sect_join_requests WHERE user_id = ?", (user["id"],)) + + conn.commit() + return jsonify({"success": True, "message": f"Sáng lập {name} tông thành công!", "sect_id": sect_id}) + except Exception as e: + logger.error(f"Error creating sect: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + +@sects_bp.route("/api/sects/join", methods=["POST"]) +@jwt_required +def join_sect(): + user = get_current_user() + data = request.json or {} + sect_id = data.get("sect_id") + + if not sect_id: + return jsonify({"error": "Thiếu sect_id"}), 400 + + conn = get_user_db_conn() + try: + # Check if user is already in a sect + in_sect = conn.execute("SELECT sect_id FROM sect_members WHERE user_id = ?", (user["id"],)).fetchone() + if in_sect: + return jsonify({"error": "Bạn đã ở trong một tông môn khác"}), 400 + + # Check if sect exists + sect = conn.execute("SELECT name FROM sects WHERE id = ?", (sect_id,)).fetchone() + if not sect: + return jsonify({"error": "Tông môn không tồn tại"}), 404 + + # Check if already requested + req_exists = conn.execute("SELECT id FROM sect_join_requests WHERE sect_id = ? AND user_id = ?", (sect_id, user["id"])).fetchone() + if req_exists: + return jsonify({"error": "Bạn đã gửi yêu cầu gia nhập tông này và đang chờ duyệt"}), 400 + + conn.execute( + "INSERT INTO sect_join_requests (sect_id, user_id, status) VALUES (?, ?, 'pending')", + (sect_id, user["id"]) + ) + conn.commit() + return jsonify({"success": True, "message": f"Đã gửi yêu cầu bái kiến gia nhập {sect['name']}! Vui lòng chờ duyệt."}) + except Exception as e: + logger.error(f"Error joining sect: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + +@sects_bp.route("/api/sects/leave", methods=["POST"]) +@jwt_required +def leave_sect(): + user = get_current_user() + conn = get_user_db_conn() + try: + member = conn.execute("SELECT sect_id, role FROM sect_members WHERE user_id = ?", (user["id"],)).fetchone() + if not member: + return jsonify({"error": "Bạn chưa gia nhập tông môn nào"}), 400 + + sect_id = member["sect_id"] + if member["role"] == "leader": + # Leader leaving dissolves the sect + conn.execute("DELETE FROM sect_chat_groups WHERE sect_id = ?", (sect_id,)) + conn.execute("DELETE FROM sect_messages WHERE sect_id = ?", (sect_id,)) + conn.execute("DELETE FROM sect_members WHERE sect_id = ?", (sect_id,)) + conn.execute("DELETE FROM sect_join_requests WHERE sect_id = ?", (sect_id,)) + conn.execute("DELETE FROM sect_books WHERE sect_id = ?", (sect_id,)) + conn.execute("DELETE FROM sects WHERE id = ?", (sect_id,)) + msg = "Bạn là tông chủ, rời đi đồng nghĩa với việc giải tán tông môn!" + else: + conn.execute("DELETE FROM sect_members WHERE user_id = ? AND sect_id = ?", (user["id"], sect_id)) + msg = "Bạn đã rời khỏi tông môn thành công!" + + conn.commit() + return jsonify({"success": True, "message": msg}) + except Exception as e: + logger.error(f"Error leaving sect: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + +@sects_bp.route("/api/sects/my-sect", methods=["GET"]) +@jwt_required +def my_sect(): + user = get_current_user() + conn = get_user_db_conn() + try: + member = conn.execute("SELECT sect_id, role, contribution as my_contrib FROM sect_members WHERE user_id = ?", (user["id"],)).fetchone() + if not member: + return jsonify({"in_sect": False}) + + sect_id = member["sect_id"] + sect = conn.execute(""" + SELECT s.id, s.name, s.slogan, s.announcement, s.badge, s.level, s.contribution, s.created_at, + u.username as leader_name, u.id as leader_id + FROM sects s + LEFT JOIN users u ON s.leader_id = u.id + WHERE s.id = ? + """, (sect_id,)).fetchone() + + members = conn.execute(""" + SELECT sm.user_id, sm.role, sm.contribution, sm.joined_at, u.username, u.avatar + FROM sect_members sm + LEFT JOIN users u ON sm.user_id = u.id + WHERE sm.sect_id = ? + ORDER BY + CASE sm.role + WHEN 'leader' THEN 1 + WHEN 'elder' THEN 2 + ELSE 3 + END, + sm.contribution DESC + """, (sect_id,)).fetchall() + + return jsonify({ + "in_sect": True, + "role": member["role"], + "my_contribution": member["my_contrib"], + "sect": serialize_row(sect), + "members": [serialize_row(m) for m in members] + }) + except Exception as e: + logger.error(f"Error getting my sect: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + +@sects_bp.route("/api/sects/chat/history", methods=["GET"]) +@jwt_required +def get_sect_chat_history(): + user = get_current_user() + chat_type = request.args.get("chat_type", "general").strip() + target_id = request.args.get("target_id") + group_id = request.args.get("group_id") + + conn = get_user_db_conn() + try: + member = conn.execute("SELECT sect_id FROM sect_members WHERE user_id = ?", (user["id"],)).fetchone() + if not member: + return jsonify({"error": "Bạn chưa gia nhập tông môn"}), 403 + + sect_id = member["sect_id"] + + if chat_type == "direct": + if not target_id: + return jsonify({"error": "Thiếu target_id cho chat riêng"}), 400 + rows = conn.execute(""" + SELECT sm.id, sm.sender_id, sm.message, sm.created_at, sm.chat_type, sm.target_id, + u.username as sender_name, u.avatar as sender_avatar + FROM sect_messages sm + LEFT JOIN users u ON sm.sender_id = u.id + WHERE sm.sect_id = ? AND sm.chat_type = 'direct' + AND ((sm.sender_id = ? AND sm.target_id = ?) OR (sm.sender_id = ? AND sm.target_id = ?)) + ORDER BY sm.created_at ASC LIMIT 100 + """, (sect_id, user["id"], target_id, target_id, user["id"])).fetchall() + + elif chat_type == "book": + if not target_id: + return jsonify({"error": "Thiếu target_id cho chat truyện"}), 400 + rows = conn.execute(""" + SELECT sm.id, sm.sender_id, sm.message, sm.created_at, sm.chat_type, sm.target_id, + u.username as sender_name, u.avatar as sender_avatar + FROM sect_messages sm + LEFT JOIN users u ON sm.sender_id = u.id + WHERE sm.sect_id = ? AND sm.chat_type = 'book' AND sm.target_id = ? + ORDER BY sm.created_at ASC LIMIT 100 + """, (sect_id, target_id)).fetchall() + + elif chat_type == "group": + if not group_id: + return jsonify({"error": "Thiếu group_id cho chat nhóm"}), 400 + + # Check group access + group = conn.execute("SELECT members_csv FROM sect_chat_groups WHERE id = ? AND sect_id = ?", (group_id, sect_id)).fetchone() + if not group: + return jsonify({"error": "Nhóm chat không tồn tại"}), 404 + + members_list = [int(x) for x in group["members_csv"].split(",") if x.strip()] + if user["id"] not in members_list: + return jsonify({"error": "Bạn không phải thành viên của nhóm chat này"}), 403 + + rows = conn.execute(""" + SELECT sm.id, sm.sender_id, sm.message, sm.created_at, sm.chat_type, sm.group_id, + u.username as sender_name, u.avatar as sender_avatar + FROM sect_messages sm + LEFT JOIN users u ON sm.sender_id = u.id + WHERE sm.sect_id = ? AND sm.chat_type = 'group' AND sm.group_id = ? + ORDER BY sm.created_at ASC LIMIT 100 + """, (sect_id, group_id)).fetchall() + + else: # general chat + rows = conn.execute(""" + SELECT sm.id, sm.sender_id, sm.message, sm.created_at, sm.chat_type, + u.username as sender_name, u.avatar as sender_avatar + FROM sect_messages sm + LEFT JOIN users u ON sm.sender_id = u.id + WHERE sm.sect_id = ? AND (sm.chat_type IS NULL OR sm.chat_type = 'general') + ORDER BY sm.created_at ASC LIMIT 100 + """, (sect_id,)).fetchall() + + messages = [] + for r in rows: + d = dict(r) + d["message"] = decrypt_message(d.get("message", "")) + for k, v in d.items(): + if hasattr(v, "isoformat"): + d[k] = v.isoformat() + messages.append(d) + + return jsonify({"messages": messages}) + except Exception as e: + logger.error(f"Error getting sect chat: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + +@sects_bp.route("/api/sects/chat/send", methods=["POST"]) +@jwt_required +def send_sect_chat(): + user = get_current_user() + data = request.json or {} + message = data.get("message", "").strip() + chat_type = data.get("chat_type", "general").strip() + target_id = data.get("target_id") + group_id = data.get("group_id") + + if not message: + return jsonify({"error": "Nội dung tin nhắn trống"}), 400 + + conn = get_user_db_conn() + try: + member = conn.execute("SELECT sect_id FROM sect_members WHERE user_id = ?", (user["id"],)).fetchone() + if not member: + return jsonify({"error": "Bạn chưa gia nhập tông môn"}), 403 + + sect_id = member["sect_id"] + + # Validate target / group access + if chat_type == "group" and group_id: + group = conn.execute("SELECT members_csv FROM sect_chat_groups WHERE id = ? AND sect_id = ?", (group_id, sect_id)).fetchone() + if not group: + return jsonify({"error": "Nhóm chat không tồn tại"}), 404 + members_list = [int(x) for x in group["members_csv"].split(",") if x.strip()] + if user["id"] not in members_list: + return jsonify({"error": "Bạn không có quyền chat trong nhóm này"}), 403 + + enc_msg = encrypt_message(message) + cursor = conn.execute( + """INSERT INTO sect_messages (sect_id, sender_id, message, chat_type, target_id, group_id) + VALUES (?, ?, ?, ?, ?, ?)""", + (sect_id, user["id"], enc_msg, chat_type, target_id, group_id) + ) + msg_id = cursor.lastrowid + conn.commit() + return jsonify({"success": True, "msg_id": msg_id}) + except Exception as e: + logger.error(f"Error sending sect chat: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + +@sects_bp.route("/api/sects/chat/groups/create", methods=["POST"]) +@jwt_required +def create_sect_chat_group(): + user = get_current_user() + data = request.json or {} + name = data.get("name", "").strip() + member_ids = data.get("members", []) + + if not name: + return jsonify({"error": "Tên nhóm chat không được để trống"}), 400 + + conn = get_user_db_conn() + try: + member = conn.execute("SELECT sect_id FROM sect_members WHERE user_id = ?", (user["id"],)).fetchone() + if not member: + return jsonify({"error": "Bạn chưa gia nhập tông môn"}), 403 + + sect_id = member["sect_id"] + + if user["id"] not in member_ids: + member_ids.append(user["id"]) + + valid_members = [] + for uid in member_ids: + is_valid = conn.execute("SELECT 1 FROM sect_members WHERE user_id = ? AND sect_id = ?", (uid, sect_id)).fetchone() + if is_valid: + valid_members.append(str(uid)) + + members_csv = ",".join(valid_members) + + cursor = conn.execute( + "INSERT INTO sect_chat_groups (sect_id, name, creator_id, members_csv) VALUES (?, ?, ?, ?)", + (sect_id, name, user["id"], members_csv) + ) + group_id = cursor.lastrowid + conn.commit() + + return jsonify({"success": True, "message": f"Tạo nhóm chat '{name}' thành công!", "group_id": group_id}) + except Exception as e: + logger.error(f"Error creating sect chat group: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + +@sects_bp.route("/api/sects/chat/groups/list", methods=["GET"]) +@jwt_required +def list_sect_chat_groups(): + user = get_current_user() + conn = get_user_db_conn() + try: + member = conn.execute("SELECT sect_id FROM sect_members WHERE user_id = ?", (user["id"],)).fetchone() + if not member: + return jsonify({"error": "Bạn chưa gia nhập tông môn"}), 403 + + sect_id = member["sect_id"] + groups = conn.execute("SELECT * FROM sect_chat_groups WHERE sect_id = ?", (sect_id,)).fetchall() + + my_groups = [] + for g in groups: + members_list = [int(x) for x in g["members_csv"].split(",") if x.strip()] + if user["id"] in members_list: + my_groups.append(serialize_row(g)) + + return jsonify({"groups": my_groups}) + except Exception as e: + logger.error(f"Error listing sect groups: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + +@sects_bp.route("/api/sects/contribute", methods=["POST"]) +@jwt_required +def contribute_sect(): + user = get_current_user() + data = request.json or {} + amount = int(data.get("amount", 0)) + + if amount <= 0: + return jsonify({"error": "Số lượng linh thạch cống hiến phải lớn hơn 0"}), 400 + + conn = get_user_db_conn() + try: + member = conn.execute("SELECT sect_id FROM sect_members WHERE user_id = ?", (user["id"],)).fetchone() + if not member: + return jsonify({"error": "Bạn không ở trong tông môn nào"}), 400 + + sect_id = member["sect_id"] + + # Increase user contribution + conn.execute( + "UPDATE sect_members SET contribution = contribution + ? WHERE user_id = ? AND sect_id = ?", + (amount, user["id"], sect_id) + ) + + # Increase sect total contribution + conn.execute( + "UPDATE sects SET contribution = contribution + ? WHERE id = ?", + (amount, sect_id) + ) + + # Calculate new level (1000 contribution per level) + sect = conn.execute("SELECT contribution FROM sects WHERE id = ?", (sect_id,)).fetchone() + new_level = max(1, int(sect["contribution"] / 1000) + 1) + conn.execute("UPDATE sects SET level = ? WHERE id = ?", (new_level, sect_id)) + + conn.commit() + return jsonify({ + "success": True, + "message": f"Cống hiến thành công {amount} linh thạch!", + "new_level": new_level + }) + except Exception as e: + logger.error(f"Error contributing to sect: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + +@sects_bp.route("/api/sects/kick", methods=["POST"]) +@jwt_required +def kick_member(): + user = get_current_user() + data = request.json or {} + target_user_id = data.get("user_id") + + if not target_user_id: + return jsonify({"error": "Thiếu user_id thành viên cần trục xuất"}), 400 + + conn = get_user_db_conn() + try: + # Check if user is leader/elder + member = conn.execute("SELECT sect_id, role FROM sect_members WHERE user_id = ?", (user["id"],)).fetchone() + if not member or member["role"] not in ['leader', 'elder']: + return jsonify({"error": "Bạn không đủ quyền hạn (Chỉ Tông chủ hoặc Trưởng lão)"}), 403 + + sect_id = member["sect_id"] + + # Check target + target = conn.execute("SELECT role FROM sect_members WHERE user_id = ? AND sect_id = ?", (target_user_id, sect_id)).fetchone() + if not target: + return jsonify({"error": "Thành viên này không thuộc tông môn của bạn"}), 400 + + # Elder cannot kick leader or another elder + if member["role"] == 'elder' and target["role"] in ['leader', 'elder']: + return jsonify({"error": "Trưởng lão không thể trục xuất Tông chủ hoặc Trưởng lão khác"}), 403 + + if target["role"] == 'leader': + return jsonify({"error": "Không thể trục xuất Tông chủ"}), 400 + + conn.execute("DELETE FROM sect_members WHERE user_id = ? AND sect_id = ?", (target_user_id, sect_id)) + conn.commit() + return jsonify({"success": True, "message": "Đã trục xuất thành viên ra khỏi tông môn!"}) + except Exception as e: + logger.error(f"Error kicking member: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + +# ========================================== +# ADVANCED SECTS & ALLIANCES FEATURES +# ========================================== + +@sects_bp.route("/api/sects/announcement", methods=["POST"]) +@jwt_required +def update_announcement(): + user = get_current_user() + data = request.json or {} + announcement = data.get("announcement", "").strip() + + conn = get_user_db_conn() + try: + member = conn.execute("SELECT sect_id, role FROM sect_members WHERE user_id = ?", (user["id"],)).fetchone() + if not member or member["role"] not in ['leader', 'elder']: + return jsonify({"error": "Chỉ Tông chủ hoặc Trưởng lão mới có quyền đổi thông cáo"}), 403 + + conn.execute("UPDATE sects SET announcement = ? WHERE id = ?", (announcement, member["sect_id"])) + conn.commit() + return jsonify({"success": True, "message": "Cập nhật thông cáo tông môn thành công!"}) + except Exception as e: + logger.error(f"Error updating announcement: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + +@sects_bp.route("/api/sects/promote", methods=["POST"]) +@jwt_required +def promote_member(): + user = get_current_user() + data = request.json or {} + target_user_id = data.get("user_id") + new_role = data.get("role", "member").lower() # 'elder' or 'member' + + if new_role not in ['elder', 'member']: + return jsonify({"error": "Chức vị không hợp lệ"}), 400 + + conn = get_user_db_conn() + try: + member = conn.execute("SELECT sect_id, role FROM sect_members WHERE user_id = ?", (user["id"],)).fetchone() + if not member or member["role"] != 'leader': + return jsonify({"error": "Chỉ có Tông chủ mới được thăng/giáng chức đệ tử"}), 403 + + sect_id = member["sect_id"] + + target = conn.execute("SELECT role FROM sect_members WHERE user_id = ? AND sect_id = ?", (target_user_id, sect_id)).fetchone() + if not target: + return jsonify({"error": "Thành viên này không thuộc tông môn của bạn"}), 400 + + if target["role"] == 'leader': + return jsonify({"error": "Không thể thay đổi chức vị của Tông chủ"}), 400 + + conn.execute("UPDATE sect_members SET role = ? WHERE user_id = ? AND sect_id = ?", (new_role, target_user_id, sect_id)) + conn.commit() + + role_name = "Trưởng Lão" if new_role == 'elder' else "Môn đồ" + return jsonify({"success": True, "message": f"Đã thăng/giáng chức thành viên thành {role_name}!"}) + except Exception as e: + logger.error(f"Error promoting member: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + +@sects_bp.route("/api/sects/requests/list", methods=["GET"]) +@jwt_required +def list_join_requests(): + user = get_current_user() + conn = get_user_db_conn() + try: + member = conn.execute("SELECT sect_id, role FROM sect_members WHERE user_id = ?", (user["id"],)).fetchone() + if not member or member["role"] not in ['leader', 'elder']: + return jsonify({"error": "Chỉ Tông chủ hoặc Trưởng lão mới xem được danh sách yêu cầu"}), 403 + + rows = conn.execute(""" + SELECT r.id, r.user_id, r.status, r.created_at, u.username, u.avatar + FROM sect_join_requests r + LEFT JOIN users u ON r.user_id = u.id + WHERE r.sect_id = ? AND r.status = 'pending' + ORDER BY r.created_at DESC + """, (member["sect_id"],)).fetchall() + + return jsonify({"requests": [serialize_row(r) for r in rows]}) + except Exception as e: + logger.error(f"Error listing requests: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + +@sects_bp.route("/api/sects/requests/respond", methods=["POST"]) +@jwt_required +def respond_join_request(): + user = get_current_user() + data = request.json or {} + req_id = data.get("request_id") + action = data.get("action", "").lower() # 'approve' or 'reject' + + if not req_id or action not in ['approve', 'reject']: + return jsonify({"error": "Dữ liệu phản hồi không hợp lệ"}), 400 + + conn = get_user_db_conn() + try: + member = conn.execute("SELECT sect_id, role FROM sect_members WHERE user_id = ?", (user["id"],)).fetchone() + if not member or member["role"] not in ['leader', 'elder']: + return jsonify({"error": "Chỉ Tông chủ hoặc Trưởng lão mới được phê duyệt"}), 403 + + sect_id = member["sect_id"] + + req = conn.execute("SELECT user_id FROM sect_join_requests WHERE id = ? AND sect_id = ?", (req_id, sect_id)).fetchone() + if not req: + return jsonify({"error": "Yêu cầu gia nhập không tồn tại hoặc đã được xử lý"}), 404 + + target_user_id = req["user_id"] + + if action == 'approve': + # Check if target is already in a sect + already_in = conn.execute("SELECT sect_id FROM sect_members WHERE user_id = ?", (target_user_id,)).fetchone() + if already_in: + conn.execute("DELETE FROM sect_join_requests WHERE id = ?", (req_id,)) + conn.commit() + return jsonify({"error": "Người dùng này đã gia nhập một tông môn khác, yêu cầu tự động hủy."}), 400 + + # Add member + conn.execute( + "INSERT INTO sect_members (sect_id, user_id, role, contribution) VALUES (?, ?, 'member', 0)", + (sect_id, target_user_id) + ) + # Delete target requests from all other sects + conn.execute("DELETE FROM sect_join_requests WHERE user_id = ?", (target_user_id,)) + msg = "Đã phê duyệt gia nhập tông môn!" + else: + # Reject + conn.execute("DELETE FROM sect_join_requests WHERE id = ?", (req_id,)) + msg = "Đã từ chối yêu cầu gia nhập!" + + conn.commit() + return jsonify({"success": True, "message": msg}) + except Exception as e: + logger.error(f"Error responding join request: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + +# ========================================== +# SECT LIBRARY (BOOK SHELF SHARING) +# ========================================== + +@sects_bp.route("/api/sects/library/list", methods=["GET"]) +@jwt_required +def list_sect_library(): + user = get_current_user() + conn = get_user_db_conn() + try: + member = conn.execute("SELECT sect_id FROM sect_members WHERE user_id = ?", (user["id"],)).fetchone() + if not member: + return jsonify({"error": "Bạn chưa gia nhập tông môn"}), 403 + + sect_id = member["sect_id"] + + # We need to join with the main books database to fetch book title and cover + # Since SQLite can ATTACH databases, or we can fetch metadata, we'll fetch from sect_books + # and query titles from books database. Let's do it cleanly: + rows = conn.execute(""" + SELECT sb.id, sb.book_id, sb.added_at, u.username as added_by_name + FROM sect_books sb + LEFT JOIN users u ON sb.added_by = u.id + WHERE sb.sect_id = ? + ORDER BY sb.added_at DESC + """, (sect_id,)).fetchall() + + from backend.database.db_manager import get_db + main_conn = get_db() + + book_list = [] + for r in rows: + book_row = main_conn.execute(""" + SELECT id, title, title_vietphrase, title_hanviet, author, cover, description + FROM books WHERE id = ? + """, (r["book_id"],)).fetchone() + if book_row: + b = serialize_row(book_row) + b["added_by_name"] = r["added_by_name"] + b["added_at"] = r["added_at"].isoformat() if hasattr(r["added_at"], "isoformat") else r["added_at"] + book_list.append(b) + + return jsonify({"books": book_list}) + except Exception as e: + logger.error(f"Error listing sect library: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + +@sects_bp.route("/api/sects/library/add", methods=["POST"]) +@jwt_required +def add_to_sect_library(): + user = get_current_user() + data = request.json or {} + book_id = data.get("book_id") + + if not book_id: + return jsonify({"error": "Thiếu book_id truyện đóng góp"}), 400 + + conn = get_user_db_conn() + try: + member = conn.execute("SELECT sect_id FROM sect_members WHERE user_id = ?", (user["id"],)).fetchone() + if not member: + return jsonify({"error": "Bạn không thuộc tông môn nào"}), 400 + + sect_id = member["sect_id"] + + # Check if already added + exists = conn.execute("SELECT id FROM sect_books WHERE sect_id = ? AND book_id = ?", (sect_id, book_id)).fetchone() + if exists: + return jsonify({"error": "Truyện này đã được đệ tử khác đóng góp vào thư viện tông môn từ trước"}), 400 + + conn.execute( + "INSERT INTO sect_books (sect_id, book_id, added_by) VALUES (?, ?, ?)", + (sect_id, book_id, user["id"]) + ) + + # Reward user 20 contribution points for sharing a book + conn.execute( + "UPDATE sect_members SET contribution = contribution + 20 WHERE user_id = ? AND sect_id = ?", + (user["id"], sect_id) + ) + # Increase sect total contribution + conn.execute( + "UPDATE sects SET contribution = contribution + 20 WHERE id = ?", + (sect_id,) + ) + + conn.commit() + return jsonify({"success": True, "message": "Chia sẻ truyện vào Thư viện Tông môn thành công! Nhận 20 điểm cống hiến."}) + except Exception as e: + logger.error(f"Error adding to sect library: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + +@sects_bp.route("/api/sects/library/remove", methods=["POST"]) +@jwt_required +def remove_from_sect_library(): + user = get_current_user() + data = request.json or {} + book_id = data.get("book_id") + + if not book_id: + return jsonify({"error": "Thiếu book_id truyện cần gỡ"}), 400 + + conn = get_user_db_conn() + try: + member = conn.execute("SELECT sect_id, role FROM sect_members WHERE user_id = ?", (user["id"],)).fetchone() + if not member: + return jsonify({"error": "Bạn không thuộc tông môn nào"}), 400 + + sect_id = member["sect_id"] + + # Check who added it + book = conn.execute("SELECT added_by FROM sect_books WHERE sect_id = ? AND book_id = ?", (sect_id, book_id)).fetchone() + if not book: + return jsonify({"error": "Truyện không có trong thư viện tông môn"}), 404 + + # Only leader, elder, or the original adder can remove + if member["role"] not in ['leader', 'elder'] and book["added_by"] != user["id"]: + return jsonify({"error": "Bạn không có quyền gỡ truyện này (Chỉ Tông chủ, Trưởng lão hoặc người đóng góp)"}), 403 + + conn.execute("DELETE FROM sect_books WHERE sect_id = ? AND book_id = ?", (sect_id, book_id)) + conn.commit() + return jsonify({"success": True, "message": "Đã gỡ truyện khỏi thư viện Tông môn!"}) + except Exception as e: + logger.error(f"Error removing from sect library: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + + +# ========================================== +# SECT SEARCH & PROFILE BY ID +# ========================================== + +ROLE_ORDER = { + "leader": 1, + "vice_leader": 2, + "elder": 3, + "inner_disciple": 4, + "member": 5, +} + +ROLE_LABELS = { + "leader": "Tông chủ", + "vice_leader": "Phó Tông chủ", + "elder": "Trưởng lão", + "inner_disciple": "Nội môn đệ tử", + "member": "Ngoại môn đệ tử", +} + +VALID_ROLES = list(ROLE_ORDER.keys()) + + +@sects_bp.route("/api/sects/search", methods=["GET"]) +def search_sects(): + """Search sects by name or slogan. No auth required.""" + q = request.args.get("q", "").strip() + page = int(request.args.get("page", 1)) + per_page = int(request.args.get("per_page", 20)) + offset = (page - 1) * per_page + + conn = get_user_db_conn() + try: + if q: + rows = conn.execute(""" + SELECT s.id, s.name, s.slogan, s.badge, s.level, s.contribution, s.created_at, + u.username as leader_name, + (SELECT COUNT(*) FROM sect_members WHERE sect_id = s.id) as member_count + FROM sects s + LEFT JOIN users u ON s.leader_id = u.id + WHERE s.name LIKE ? OR s.slogan LIKE ? + ORDER BY s.contribution DESC, s.created_at DESC + LIMIT ? OFFSET ? + """, (f"%{q}%", f"%{q}%", per_page, offset)).fetchall() + + total = conn.execute( + "SELECT COUNT(*) as cnt FROM sects WHERE name LIKE ? OR slogan LIKE ?", + (f"%{q}%", f"%{q}%") + ).fetchone()["cnt"] + else: + rows = conn.execute(""" + SELECT s.id, s.name, s.slogan, s.badge, s.level, s.contribution, s.created_at, + u.username as leader_name, + (SELECT COUNT(*) FROM sect_members WHERE sect_id = s.id) as member_count + FROM sects s + LEFT JOIN users u ON s.leader_id = u.id + ORDER BY s.contribution DESC, s.created_at DESC + LIMIT ? OFFSET ? + """, (per_page, offset)).fetchall() + total = conn.execute("SELECT COUNT(*) as cnt FROM sects").fetchone()["cnt"] + + return jsonify({ + "sects": [serialize_row(r) for r in rows], + "total": total, + "page": page, + "per_page": per_page, + "total_pages": max(1, (total + per_page - 1) // per_page) + }) + except Exception as e: + logger.error(f"Error searching sects: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + + +@sects_bp.route("/api/sects/", methods=["GET"]) +def get_sect_by_id(sect_id): + """View full sect profile by ID. No auth required for basic info.""" + conn = get_user_db_conn() + try: + sect = conn.execute(""" + SELECT s.id, s.name, s.slogan, s.announcement, s.badge, s.level, s.contribution, s.created_at, + u.username as leader_name, u.id as leader_id, u.avatar as leader_avatar + FROM sects s + LEFT JOIN users u ON s.leader_id = u.id + WHERE s.id = ? + """, (sect_id,)).fetchone() + + if not sect: + return jsonify({"error": "Tông môn không tồn tại"}), 404 + + members = conn.execute(""" + SELECT sm.user_id, sm.role, sm.contribution, sm.joined_at, + u.username, u.avatar, + COALESCE(sm.role, 'member') as role + FROM sect_members sm + LEFT JOIN users u ON sm.user_id = u.id + WHERE sm.sect_id = ? + ORDER BY + CASE sm.role + WHEN 'leader' THEN 1 + WHEN 'vice_leader' THEN 2 + WHEN 'elder' THEN 3 + WHEN 'inner_disciple' THEN 4 + ELSE 5 + END, + sm.contribution DESC + """, (sect_id,)).fetchall() + + # Enrich members with Vietnamese role labels + member_list = [] + for m in members: + md = serialize_row(m) + md["role_label"] = ROLE_LABELS.get(m["role"], "Môn đồ") + member_list.append(md) + + # Count by role + role_counts = {} + for m in member_list: + r = m["role"] + role_counts[r] = role_counts.get(r, 0) + 1 + + return jsonify({ + "sect": serialize_row(sect), + "members": member_list, + "member_count": len(member_list), + "role_counts": role_counts, + "role_labels": ROLE_LABELS, + }) + except Exception as e: + logger.error(f"Error fetching sect {sect_id}: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + + +# ========================================== +# FULL RANK PROMOTION SYSTEM (5 Ranks) +# ========================================== + +@sects_bp.route("/api/sects/promote/rank", methods=["POST"]) +@jwt_required +def promote_member_rank(): + """ + Full 5-rank promotion system: + leader > vice_leader > elder > inner_disciple > member + Only leader can set: vice_leader, elder, inner_disciple, member + vice_leader can set: elder, inner_disciple, member + elder can set: inner_disciple, member + """ + user = get_current_user() + data = request.json or {} + target_user_id = data.get("user_id") + new_role = data.get("role", "").lower() + + if new_role not in VALID_ROLES or new_role == "leader": + return jsonify({ + "error": f"Chức vị không hợp lệ. Các chức vị có thể gán: {', '.join(VALID_ROLES[1:])}", + "valid_roles": VALID_ROLES[1:], + "role_labels": ROLE_LABELS, + }), 400 + + if not target_user_id: + return jsonify({"error": "Thiếu user_id"}), 400 + + conn = get_user_db_conn() + try: + caller = conn.execute( + "SELECT sect_id, role FROM sect_members WHERE user_id = ?", (user["id"],) + ).fetchone() + if not caller: + return jsonify({"error": "Bạn chưa gia nhập tông môn"}), 403 + + sect_id = caller["sect_id"] + caller_role = caller["role"] + caller_order = ROLE_ORDER.get(caller_role, 99) + new_role_order = ROLE_ORDER.get(new_role, 99) + + # Permission matrix: caller must outrank new_role + if caller_order >= new_role_order: + return jsonify({ + "error": f"Bạn ({ROLE_LABELS.get(caller_role)}) không đủ quyền gán chức vị {ROLE_LABELS.get(new_role)}" + }), 403 + + target = conn.execute( + "SELECT role FROM sect_members WHERE user_id = ? AND sect_id = ?", + (target_user_id, sect_id) + ).fetchone() + if not target: + return jsonify({"error": "Thành viên không thuộc tông môn của bạn"}), 404 + + if target["role"] == "leader": + return jsonify({"error": "Không thể thay đổi chức vị của Tông chủ"}), 400 + + target_order = ROLE_ORDER.get(target["role"], 99) + if caller_order >= target_order: + return jsonify({ + "error": f"Bạn ({ROLE_LABELS.get(caller_role)}) không thể thay đổi chức vị của người ngang hoặc cao hơn bạn" + }), 403 + + conn.execute( + "UPDATE sect_members SET role = ? WHERE user_id = ? AND sect_id = ?", + (new_role, target_user_id, sect_id) + ) + conn.commit() + + return jsonify({ + "success": True, + "message": f"Đã gán chức vị {ROLE_LABELS.get(new_role)} thành công!", + "new_role": new_role, + "new_role_label": ROLE_LABELS.get(new_role), + }) + except Exception as e: + logger.error(f"Error promoting rank: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + + +@sects_bp.route("/api/sects/members", methods=["GET"]) +@jwt_required +def list_sect_members(): + """List all members of current user's sect with full role info.""" + user = get_current_user() + role_filter = request.args.get("role") + conn = get_user_db_conn() + try: + member = conn.execute( + "SELECT sect_id FROM sect_members WHERE user_id = ?", (user["id"],) + ).fetchone() + if not member: + return jsonify({"error": "Bạn chưa gia nhập tông môn"}), 403 + + sect_id = member["sect_id"] + + if role_filter and role_filter in VALID_ROLES: + rows = conn.execute(""" + SELECT sm.user_id, sm.role, sm.contribution, sm.joined_at, + u.username, u.avatar + FROM sect_members sm + LEFT JOIN users u ON sm.user_id = u.id + WHERE sm.sect_id = ? AND sm.role = ? + ORDER BY sm.contribution DESC + """, (sect_id, role_filter)).fetchall() + else: + rows = conn.execute(""" + SELECT sm.user_id, sm.role, sm.contribution, sm.joined_at, + u.username, u.avatar + FROM sect_members sm + LEFT JOIN users u ON sm.user_id = u.id + WHERE sm.sect_id = ? + ORDER BY + CASE sm.role + WHEN 'leader' THEN 1 + WHEN 'vice_leader' THEN 2 + WHEN 'elder' THEN 3 + WHEN 'inner_disciple' THEN 4 + ELSE 5 + END, + sm.contribution DESC + """, (sect_id,)).fetchall() + + member_list = [] + for r in rows: + rd = serialize_row(r) + rd["role_label"] = ROLE_LABELS.get(r["role"], "Môn đồ") + member_list.append(rd) + + return jsonify({ + "members": member_list, + "total": len(member_list), + "role_labels": ROLE_LABELS, + "valid_roles": VALID_ROLES, + }) + except Exception as e: + logger.error(f"Error listing members: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + + +# ========================================== +# SECT CHAT GROUPS – MANAGE MEMBERS +# ========================================== + +@sects_bp.route("/api/sects/chat/groups//members/add", methods=["POST"]) +@jwt_required +def add_to_chat_group(group_id): + """Add member(s) to a sub-group chat.""" + user = get_current_user() + data = request.json or {} + new_member_ids = data.get("user_ids", []) + + conn = get_user_db_conn() + try: + my_member = conn.execute( + "SELECT sect_id, role FROM sect_members WHERE user_id = ?", (user["id"],) + ).fetchone() + if not my_member: + return jsonify({"error": "Bạn chưa gia nhập tông môn"}), 403 + + sect_id = my_member["sect_id"] + group = conn.execute( + "SELECT id, creator_id, members_csv FROM sect_chat_groups WHERE id = ? AND sect_id = ?", + (group_id, sect_id) + ).fetchone() + + if not group: + return jsonify({"error": "Nhóm chat không tồn tại"}), 404 + + # Only group creator, leader, vice_leader, elder can add + if group["creator_id"] != user["id"] and my_member["role"] not in ["leader", "vice_leader", "elder"]: + return jsonify({"error": "Chỉ người tạo nhóm hoặc Ban quản lý mới có thể thêm thành viên"}), 403 + + current_members = [int(x) for x in group["members_csv"].split(",") if x.strip()] + added = [] + for uid in new_member_ids: + uid = int(uid) + if uid not in current_members: + # Check uid is in sect + in_sect = conn.execute( + "SELECT 1 FROM sect_members WHERE user_id = ? AND sect_id = ?", (uid, sect_id) + ).fetchone() + if in_sect: + current_members.append(uid) + added.append(uid) + + new_csv = ",".join(str(x) for x in current_members) + conn.execute( + "UPDATE sect_chat_groups SET members_csv = ? WHERE id = ?", + (new_csv, group_id) + ) + conn.commit() + return jsonify({"success": True, "added": added, "members": current_members}) + except Exception as e: + logger.error(f"Error adding to chat group: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + + +@sects_bp.route("/api/sects/chat/groups//members/remove", methods=["POST"]) +@jwt_required +def remove_from_chat_group(group_id): + """Remove a member from a sub-group chat.""" + user = get_current_user() + data = request.json or {} + target_id = data.get("user_id") + + conn = get_user_db_conn() + try: + my_member = conn.execute( + "SELECT sect_id, role FROM sect_members WHERE user_id = ?", (user["id"],) + ).fetchone() + if not my_member: + return jsonify({"error": "Bạn chưa gia nhập tông môn"}), 403 + + sect_id = my_member["sect_id"] + group = conn.execute( + "SELECT id, creator_id, members_csv FROM sect_chat_groups WHERE id = ? AND sect_id = ?", + (group_id, sect_id) + ).fetchone() + if not group: + return jsonify({"error": "Nhóm chat không tồn tại"}), 404 + + if group["creator_id"] != user["id"] and my_member["role"] not in ["leader", "vice_leader", "elder"]: + return jsonify({"error": "Không đủ quyền xóa thành viên khỏi nhóm chat"}), 403 + + current_members = [int(x) for x in group["members_csv"].split(",") if x.strip()] + if int(target_id) not in current_members: + return jsonify({"error": "Thành viên không có trong nhóm chat này"}), 400 + + current_members.remove(int(target_id)) + new_csv = ",".join(str(x) for x in current_members) + conn.execute("UPDATE sect_chat_groups SET members_csv = ? WHERE id = ?", (new_csv, group_id)) + conn.commit() + return jsonify({"success": True, "members": current_members}) + except Exception as e: + logger.error(f"Error removing from chat group: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + + +@sects_bp.route("/api/sects/chat/groups/", methods=["GET"]) +@jwt_required +def get_chat_group_info(group_id): + """Get info and member list of a sub-group chat.""" + user = get_current_user() + conn = get_user_db_conn() + try: + my_member = conn.execute( + "SELECT sect_id FROM sect_members WHERE user_id = ?", (user["id"],) + ).fetchone() + if not my_member: + return jsonify({"error": "Bạn chưa gia nhập tông môn"}), 403 + + sect_id = my_member["sect_id"] + group = conn.execute( + "SELECT * FROM sect_chat_groups WHERE id = ? AND sect_id = ?", + (group_id, sect_id) + ).fetchone() + if not group: + return jsonify({"error": "Nhóm chat không tồn tại"}), 404 + + member_ids = [int(x) for x in group["members_csv"].split(",") if x.strip()] + if user["id"] not in member_ids: + return jsonify({"error": "Bạn không phải thành viên của nhóm chat này"}), 403 + + # Fetch member details + members = [] + for uid in member_ids: + row = conn.execute(""" + SELECT sm.user_id, sm.role, sm.contribution, u.username, u.avatar + FROM sect_members sm + LEFT JOIN users u ON sm.user_id = u.id + WHERE sm.user_id = ? AND sm.sect_id = ? + """, (uid, sect_id)).fetchone() + if row: + rd = serialize_row(row) + rd["role_label"] = ROLE_LABELS.get(row["role"], "Môn đồ") + members.append(rd) + + return jsonify({ + "group": serialize_row(group), + "members": members, + "member_count": len(members), + }) + except Exception as e: + logger.error(f"Error fetching chat group: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + + +@sects_bp.route("/api/sects/chat/groups", methods=["GET"]) +@jwt_required +def list_all_sect_chat_groups(): + """List all sub-group chats the current user is part of in their sect.""" + user = get_current_user() + conn = get_user_db_conn() + try: + my_member = conn.execute( + "SELECT sect_id FROM sect_members WHERE user_id = ?", (user["id"],) + ).fetchone() + if not my_member: + return jsonify({"error": "Bạn chưa gia nhập tông môn"}), 403 + + sect_id = my_member["sect_id"] + groups = conn.execute( + "SELECT id, name, creator_id, members_csv, created_at FROM sect_chat_groups WHERE sect_id = ?", + (sect_id,) + ).fetchall() + + result = [] + for g in groups: + member_ids = [int(x) for x in g["members_csv"].split(",") if x.strip()] + if user["id"] in member_ids: + gd = serialize_row(g) + gd["member_count"] = len(member_ids) + result.append(gd) + + return jsonify({"groups": result}) + except Exception as e: + logger.error(f"Error listing chat groups: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + diff --git a/backend/api/translate.py b/backend/api/translate.py new file mode 100644 index 0000000000000000000000000000000000000000..ff3e5f88e4e9f36e4f8ffc23ad77aeb7f7f8dc83 --- /dev/null +++ b/backend/api/translate.py @@ -0,0 +1,397 @@ +import datetime +import os +import requests as py_requests +from flask import Blueprint, request, jsonify, Response, session, current_app +from backend.config import Config +from backend.core.decorators import get_current_user +from backend.core.rate_limit import get_client_ip +from backend.core.security import verify_access_token +from backend.services.translation import ( + get_engine, translate_texts, translate_stream_generator, + translation_limit_tracker, call_ai_chat_proxy +) + +translate_bp = Blueprint("translate", __name__) + + +def is_vip_request(): + """Check if current request has VIP privileges (session, JWT, or header code).""" + user = get_current_user() + if user and user.get("vip_status", 0) == 1: + return True + + # Check headers + vip_code = request.headers.get("X-VIP-Code", "") or request.headers.get("X-VIP-Key", "") + if not vip_code: + # Check request body + try: + data = request.json or {} + vip_code = data.get("vip_key", "") or data.get("vip_code", "") + except: + pass + + if vip_code and vip_code in Config.VALID_VIP_CODES: + return True + return False + + +def _check_translation_rate_limit(texts): + """Returns (exceeded: bool, tracker_key, count) for standard users.""" + client_ip = get_client_ip() + today_str = datetime.date.today().isoformat() + tracker_key = f"{client_ip}:{today_str}" + current_count = translation_limit_tracker.get(tracker_key, 0) + requested_count = len([t for t in texts if t.strip()]) + exceeded = (current_count + requested_count) > 50 + return exceeded, tracker_key, requested_count + + +@translate_bp.route("/translate", methods=["POST"]) +def translate(): + data = request.json + if not data or "texts" not in data: + return jsonify({"error": "Missing 'texts' array"}), 400 + + texts = data["texts"] + + if not is_vip_request(): + exceeded, tracker_key, count = _check_translation_rate_limit(texts) + if exceeded: + return jsonify({ + "error": "Hạn mức dịch máy chủ Standard đã hết (50 đoạn/ngày). Vui lòng nâng cấp tài khoản VIP!" + }), 403 + translation_limit_tracker[tracker_key] = translation_limit_tracker.get(tracker_key, 0) + count + + mode = data.get("mode") + + # If standalone translation server is running, proxy request to it + local_translate_url = os.environ.get("LOCAL_TRANSLATE_URL", "") + if not local_translate_url: + local_tts_url = os.environ.get("LOCAL_TTS_URL", "") + if local_tts_url: + local_translate_url = local_tts_url.split("/v1/")[0] + + if local_translate_url: + try: + translate_url = f"{local_translate_url.rstrip('/')}/v1/translate" + r = py_requests.post(translate_url, json={"texts": texts, "mode": mode}, timeout=(2.0, 60.0)) + if r.status_code == 200: + return jsonify(r.json()) + current_app.logger.error(f"[Translate Proxy Error]: {r.status_code} - {r.text}") + except Exception as e: + current_app.logger.error(f"[Translate Proxy Exception]: {e}") + + translations = translate_texts(texts, mode) + return jsonify({"translations": translations}) + + +@translate_bp.route("/translate_stream", methods=["POST"]) +def translate_stream(): + data = request.json + if not data or "texts" not in data: + return jsonify({"error": "Missing 'texts' array"}), 400 + + texts = data["texts"] + + if not is_vip_request(): + exceeded, tracker_key, count = _check_translation_rate_limit(texts) + if exceeded: + return jsonify({ + "error": "Hạn mức dịch máy chủ Standard đã hết (50 đoạn/ngày). Vui lòng nâng cấp tài khoản VIP!" + }), 403 + translation_limit_tracker[tracker_key] = translation_limit_tracker.get(tracker_key, 0) + count + + mode = data.get("mode") + + # If standalone translation server is running, proxy stream request to it + local_translate_url = os.environ.get("LOCAL_TRANSLATE_URL", "") + if not local_translate_url: + local_tts_url = os.environ.get("LOCAL_TTS_URL", "") + if local_tts_url: + local_translate_url = local_tts_url.split("/v1/")[0] + + if local_translate_url: + try: + translate_url = f"{local_translate_url.rstrip('/')}/v1/translate_stream" + r = py_requests.post(translate_url, json={"texts": texts, "mode": mode}, stream=True, timeout=(2.0, 60.0)) + if r.status_code == 200: + def stream_forwarder(): + for chunk in r.iter_content(chunk_size=1024): + if chunk: + yield chunk + response = Response(stream_forwarder(), mimetype="text/event-stream") + response.headers["X-Accel-Buffering"] = "no" + response.headers["Cache-Control"] = "no-cache, no-transform" + response.headers["Connection"] = "keep-alive" + response.headers["X-Content-Type-Options"] = "nosniff" + return response + current_app.logger.error(f"[Translate Stream Proxy Error]: {r.status_code} - {r.text}") + except Exception as e: + current_app.logger.error(f"[Translate Stream Proxy Exception]: {e}") + + response = Response(translate_stream_generator(texts, mode), mimetype="text/event-stream") + response.headers["X-Accel-Buffering"] = "no" + response.headers["Cache-Control"] = "no-cache, no-transform" + response.headers["Connection"] = "keep-alive" + response.headers["X-Content-Type-Options"] = "nosniff" + return response + + +@translate_bp.route("/api/ai/chat", methods=["POST"]) +def ai_chat_proxy(): + if not is_vip_request(): + return jsonify({ + "error": "Chức năng AI chỉ dành cho thành viên VIP. Vui lòng nâng cấp hoặc nhập API Key cá nhân trong cài đặt!" + }), 403 + + data = request.json or {} + messages = data.get("messages", []) + model = data.get("model", "gemini-1.5-flash") + prompt = data.get("prompt", "") + + try: + text = call_ai_chat_proxy(messages, model, prompt) + return jsonify({"text": text}) + except ValueError as e: + return jsonify({"error": str(e)}), 501 + except RuntimeError as e: + return jsonify({"error": str(e)}), 502 + except Exception as e: + return jsonify({"error": f"Lỗi xử lý AI Proxy: {str(e)}"}), 500 + + +@translate_bp.route("/iframe_proxy", methods=["GET"]) +def iframe_proxy(): + url = request.args.get("url") + if not url: + return "Missing 'url' parameter", 400 + + try: + headers = { + "User-Agent": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36", + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", + "Accept-Language": "en-US,en;q=0.5" + } + + # Follow redirects + r = py_requests.get(url, headers=headers, timeout=15, allow_redirects=True) + + encoding = r.encoding + if not encoding or encoding.lower() == 'iso-8859-1': + encoding = r.apparent_encoding or 'utf-8' + + try: + html = r.content.decode(encoding, errors='ignore') + except Exception: + html = r.content.decode('utf-8', errors='ignore') + + # Insert base URL tag so all links/resources load relative to original page + base_tag = f'' + if "" in html: + html = html.replace("", f"{base_tag}", 1) + elif "" in html: + html = html.replace("", f"{base_tag}", 1) + else: + html = base_tag + html + + # Injected proxy handler script + injected_script = """ + + """ + + if "" in html: + html = html.replace("", f"{injected_script}", 1) + elif "" in html: + html = html.replace("", f"{injected_script}", 1) + else: + html = html + injected_script + + response = Response(html, mimetype="text/html") + response.headers.pop("X-Frame-Options", None) + response.headers.pop("Content-Security-Policy", None) + response.headers["Access-Control-Allow-Origin"] = "*" + return response + except Exception as e: + return f"Proxy error: {str(e)}", 500 + diff --git a/backend/api/user_features.py b/backend/api/user_features.py new file mode 100644 index 0000000000000000000000000000000000000000..d3521869b880288be07b22f1627585bf8072c205 --- /dev/null +++ b/backend/api/user_features.py @@ -0,0 +1,938 @@ +from flask import Blueprint, request, jsonify +from backend.core.decorators import jwt_required, get_current_user +from backend.database.db_manager import get_user_db_conn +from backend.core.logger import logger +from backend.core.security import encrypt_message, decrypt_message +from datetime import datetime +import os + +user_features_bp = Blueprint("user_features", __name__) + +def serialize_row(row): + if not row: + return {} + d = dict(row) + for k, v in d.items(): + if hasattr(v, "isoformat"): + d[k] = v.isoformat() + return d + +import time +_history_cache = {} +_stats_cache = {} + + +# ========================================== +# 1. Translation History Endpoints +# ========================================== + +@user_features_bp.route("/api/user/history", methods=["GET"]) +@jwt_required +def get_translation_history(): + user = get_current_user() + user_id = user["id"] + + now = time.time() + if user_id in _history_cache: + cached_data, cached_time = _history_cache[user_id] + if now - cached_time < 60: + return jsonify(cached_data) + + conn = get_user_db_conn() + try: + rows = conn.execute( + "SELECT * FROM translation_history WHERE user_id = ? ORDER BY created_at DESC LIMIT 100", + (user_id,) + ).fetchall() + response_data = {"history": [serialize_row(r) for r in rows], "success": True} + _history_cache[user_id] = (response_data, now) + return jsonify(response_data) + except Exception as e: + logger.error(f"[User History] Failed to fetch history: {e}") + return jsonify({"error": "Failed to fetch translation history", "success": False}), 500 + finally: + conn.close() + +@user_features_bp.route("/api/user/history", methods=["POST"]) +@jwt_required +def add_translation_history(): + user = get_current_user() + data = request.json or {} + original = data.get("original_text", "").strip() + translated = data.get("translated_text", "").strip() + mode = data.get("mode", "fast").strip() + chars = int(data.get("characters", len(original))) + + if not original or not translated: + return jsonify({"error": "Original text and translation content cannot be empty", "success": False}), 400 + + conn = get_user_db_conn() + try: + conn.execute( + "INSERT INTO translation_history (user_id, original_text, translated_text, mode, characters) VALUES (?, ?, ?, ?, ?)", + (user["id"], original, translated, mode, chars) + ) + conn.commit() + if user["id"] in _history_cache: del _history_cache[user["id"]] + if user["id"] in _stats_cache: del _stats_cache[user["id"]] + return jsonify({"message": "Translation history entry added", "success": True}) + except Exception as e: + logger.error(f"[User History] Failed to add entry: {e}") + return jsonify({"error": "Failed to add translation history entry", "success": False}), 500 + finally: + conn.close() + +@user_features_bp.route("/api/user/history", methods=["DELETE"]) +@jwt_required +def clear_translation_history(): + user = get_current_user() + conn = get_user_db_conn() + try: + conn.execute("DELETE FROM translation_history WHERE user_id = ?", (user["id"],)) + conn.commit() + if user["id"] in _history_cache: del _history_cache[user["id"]] + if user["id"] in _stats_cache: del _stats_cache[user["id"]] + return jsonify({"message": "Translation history cleared", "success": True}) + except Exception as e: + logger.error(f"[User History] Failed to clear history: {e}") + return jsonify({"error": "Failed to clear history", "success": False}), 500 + finally: + conn.close() + +# ========================================== +# 2. Vocabulary/Word Notebook Endpoints +# ========================================== + +@user_features_bp.route("/api/user/vocabulary", methods=["GET"]) +@jwt_required +def get_vocabulary(): + user = get_current_user() + conn = get_user_db_conn() + try: + rows = conn.execute( + "SELECT * FROM vocabulary WHERE user_id = ? ORDER BY created_at DESC", + (user["id"],) + ).fetchall() + return jsonify({"vocabulary": [serialize_row(r) for r in rows], "success": True}) + except Exception as e: + logger.error(f"[Vocabulary] Failed to fetch vocabulary: {e}") + return jsonify({"error": "Failed to fetch vocabulary list", "success": False}), 500 + finally: + conn.close() + +@user_features_bp.route("/api/user/vocabulary", methods=["POST"]) +@jwt_required +def add_vocabulary(): + user = get_current_user() + data = request.json or {} + original = data.get("original_text", "").strip() + translation = data.get("translation", "").strip() + pinyin_or_hanviet = data.get("pinyin_or_hanviet", "").strip() + context = data.get("context_sentence", "").strip() + notes = data.get("notes", "").strip() + + if not original or not translation: + return jsonify({"error": "Original text and translation content cannot be empty", "success": False}), 400 + + conn = get_user_db_conn() + try: + conn.execute( + "INSERT INTO vocabulary (user_id, original_text, pinyin_or_hanviet, translation, context_sentence, notes) VALUES (?, ?, ?, ?, ?, ?)", + (user["id"], original, pinyin_or_hanviet, translation, context, notes) + ) + conn.commit() + return jsonify({"message": "Word saved to vocabulary notebook", "success": True}) + except Exception as e: + logger.error(f"[Vocabulary] Failed to save word: {e}") + return jsonify({"error": "Failed to save word notebook entry", "success": False}), 500 + finally: + conn.close() + +@user_features_bp.route("/api/user/vocabulary/", methods=["DELETE"]) +@jwt_required +def delete_vocabulary(item_id): + user = get_current_user() + conn = get_user_db_conn() + try: + # Verify ownership + row = conn.execute("SELECT user_id FROM vocabulary WHERE id = ?", (item_id,)).fetchone() + if not row: + return jsonify({"error": "Entry not found", "success": False}), 404 + if int(row["user_id"]) != int(user["id"]): + return jsonify({"error": "Unauthorized action", "success": False}), 403 + + conn.execute("DELETE FROM vocabulary WHERE id = ?", (item_id,)) + conn.commit() + return jsonify({"message": "Word deleted from notebook", "success": True}) + except Exception as e: + logger.error(f"[Vocabulary] Failed to delete item {item_id}: {e}") + return jsonify({"error": "Failed to delete item", "success": False}), 500 + finally: + conn.close() + +# ========================================== +# 3. Personalization Settings Endpoints +# ========================================== + +@user_features_bp.route("/api/user/settings", methods=["GET"]) +@jwt_required +def get_user_settings(): + user = get_current_user() + conn = get_user_db_conn() + try: + row = conn.execute("SELECT * FROM user_settings WHERE user_id = ?", (user["id"],)).fetchone() + if not row: + # Insert defaults + conn.execute( + "INSERT INTO user_settings (user_id, theme, default_language, auto_read, font_size) VALUES (?, 'dark', 'vi', 0, 14)", + (user["id"],) + ) + conn.commit() + row = conn.execute("SELECT * FROM user_settings WHERE user_id = ?", (user["id"],)).fetchone() + + return jsonify({"settings": serialize_row(row), "success": True}) + except Exception as e: + logger.error(f"[UserSettings] Failed to fetch settings: {e}") + return jsonify({"error": "Failed to fetch settings", "success": False}), 500 + finally: + conn.close() + +@user_features_bp.route("/api/user/settings", methods=["POST"]) +@jwt_required +def update_user_settings(): + user = get_current_user() + data = request.json or {} + theme = data.get("theme", "dark").strip() + lang = data.get("default_language", "vi").strip() + auto_read = int(data.get("auto_read", 0)) + font_size = int(data.get("font_size", 14)) + now = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S") + + conn = get_user_db_conn() + try: + conn.execute( + """INSERT INTO user_settings (user_id, theme, default_language, auto_read, font_size, updated_at) + VALUES (?, ?, ?, ?, ?, ?) + ON CONFLICT(user_id) DO UPDATE SET + theme = excluded.theme, + default_language = excluded.default_language, + auto_read = excluded.auto_read, + font_size = excluded.font_size, + updated_at = excluded.updated_at""", + (user["id"], theme, lang, auto_read, font_size, now) + ) + conn.commit() + return jsonify({"message": "Settings updated successfully", "success": True}) + except Exception as e: + logger.error(f"[UserSettings] Failed to update settings: {e}") + return jsonify({"error": "Failed to update settings", "success": False}), 500 + finally: + conn.close() + + +# ========================================== +# 4. Usage Tracking & System/API Statistics +# ========================================== + +@user_features_bp.route("/api/user/track", methods=["POST"]) +@jwt_required +def track_user_usage(): + user = get_current_user() + data = request.json or {} + source = data.get("source", "web").strip().lower() + action = data.get("action", "read").strip().lower() + duration = int(data.get("duration", 0)) + mode = data.get("mode", "online").strip().lower() + + if not source or not action: + return jsonify({"error": "Missing source or action", "success": False}), 400 + + conn = get_user_db_conn() + try: + conn.execute( + "INSERT INTO usage_tracking (user_id, source, action, duration, mode) VALUES (?, ?, ?, ?, ?)", + (user["id"], source, action, duration, mode) + ) + conn.commit() + if user["id"] in _stats_cache: del _stats_cache[user["id"]] + return jsonify({"message": "Usage tracked successfully", "success": True}) + except Exception as e: + logger.error(f"[Usage Tracking] Failed to log usage: {e}") + return jsonify({"error": "Failed to track usage", "success": False}), 500 + finally: + conn.close() + + +@user_features_bp.route("/api/user/stats", methods=["GET"]) +@jwt_required +def get_user_stats(): + user = get_current_user() + user_id = user["id"] + + now = time.time() + if user_id in _stats_cache: + cached_data, cached_time = _stats_cache[user_id] + if now - cached_time < 60: + return jsonify(cached_data) + + conn = get_user_db_conn() + try: + # 1. Total active/reading duration by source + web_duration_row = conn.execute( + "SELECT SUM(duration) as total FROM usage_tracking WHERE user_id = ? AND source = 'web'", + (user["id"],) + ).fetchone() + web_duration = web_duration_row["total"] or 0 if web_duration_row else 0 + + ext_duration_row = conn.execute( + "SELECT SUM(duration) as total FROM usage_tracking WHERE user_id = ? AND source = 'extension'", + (user["id"],) + ).fetchone() + ext_duration = ext_duration_row["total"] or 0 if ext_duration_row else 0 + + # 2. Total active/reading duration by online/offline mode + online_duration_row = conn.execute( + "SELECT SUM(duration) as total FROM usage_tracking WHERE user_id = ? AND mode = 'online'", + (user["id"],) + ).fetchone() + online_duration = online_duration_row["total"] or 0 if online_duration_row else 0 + + offline_duration_row = conn.execute( + "SELECT SUM(duration) as total FROM usage_tracking WHERE user_id = ? AND mode = 'offline'", + (user["id"],) + ).fetchone() + offline_duration = offline_duration_row["total"] or 0 if offline_duration_row else 0 + + # 3. Translation calls count (from translation_history) + trans_calls_row = conn.execute( + "SELECT COUNT(*) as cnt, SUM(characters) as total_chars FROM translation_history WHERE user_id = ?", + (user["id"],) + ).fetchone() + trans_calls = trans_calls_row["cnt"] or 0 if trans_calls_row else 0 + total_chars = trans_calls_row["total_chars"] or 0 if trans_calls_row else 0 + + # 4. API keys & API usage stats (from api_keys and api_usage) + api_keys_count_row = conn.execute( + "SELECT COUNT(*) as cnt FROM api_keys WHERE user_id = ?", + (user["id"],) + ).fetchone() + api_keys_count = api_keys_count_row["cnt"] or 0 if api_keys_count_row else 0 + + api_usage_row = conn.execute( + """SELECT COUNT(u.id) as cnt, SUM(u.tokens) as tokens + FROM api_usage u + JOIN api_keys k ON u.api_key = k.api_key + WHERE k.user_id = ?""", + (user["id"],) + ).fetchone() + api_usage_calls = api_usage_row["cnt"] or 0 if api_usage_row else 0 + api_usage_chars = api_usage_row["tokens"] or 0 if api_usage_row else 0 + + # 5. Recent actions log + recent_actions = conn.execute( + "SELECT source, action, duration, mode, timestamp FROM usage_tracking WHERE user_id = ? ORDER BY timestamp DESC, id DESC LIMIT 20", + (user_id,) + ).fetchall() + + response_data = { + "success": True, + "stats": { + "web_duration": web_duration, + "ext_duration": ext_duration, + "online_duration": online_duration, + "offline_duration": offline_duration, + "total_reading_time": web_duration + ext_duration, + "translation_calls": trans_calls, + "translation_chars": total_chars, + "api_keys_count": api_keys_count, + "api_usage_calls": api_usage_calls, + "api_usage_chars": api_usage_chars + }, + "recent_actions": [serialize_row(r) for r in recent_actions] + } + + _stats_cache[user_id] = (response_data, now) + return jsonify(response_data) + except Exception as e: + logger.error(f"[User Stats] Failed to fetch stats: {e}") + return jsonify({"error": "Failed to fetch stats", "success": False}), 500 + finally: + conn.close() + + +# ========================================== +# 5. Feedback Submissions +# ========================================== + +@user_features_bp.route("/api/feedback/submit", methods=["POST"]) +def submit_feedback(): + data = request.json or {} + email = data.get("email", "").strip() + message = data.get("message", "").strip() + + if not email or not message: + return jsonify({"error": "Email và nội dung phản hồi không được để trống", "success": False}), 400 + + # 1. Log to logs/feedback.log + os.makedirs("logs", exist_ok=True) + log_path = "logs/feedback.log" + timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + log_entry = f"[{timestamp}] EMAIL: {email} | MESSAGE: {message}\n" + try: + with open(log_path, "a", encoding="utf-8") as f: + f.write(log_entry) + except Exception as e: + logger.error(f"Failed to write feedback to log file: {e}") + + # 2. Save to SQLite database + conn = get_user_db_conn() + try: + conn.execute( + """CREATE TABLE IF NOT EXISTS user_feedbacks ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + email TEXT, + message TEXT, + timestamp DATETIME DEFAULT CURRENT_TIMESTAMP + )""" + ) + conn.execute( + "INSERT INTO user_feedbacks (email, message) VALUES (?, ?)", + (email, message) + ) + conn.commit() + return jsonify({"message": "Gửi phản hồi thành công!", "success": True}) + except Exception as e: + logger.error(f"[Feedback] Failed to save feedback: {e}") + return jsonify({"error": "Gửi phản hồi thất bại", "success": False}), 500 + finally: + conn.close() + + +@user_features_bp.route("/api/feedback/list", methods=["GET"]) +def list_feedbacks(): + conn = get_user_db_conn() + try: + conn.execute( + """CREATE TABLE IF NOT EXISTS user_feedbacks ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + email TEXT, + message TEXT, + timestamp DATETIME DEFAULT CURRENT_TIMESTAMP + )""" + ) + rows = conn.execute("SELECT * FROM user_feedbacks ORDER BY id DESC").fetchall() + feedbacks = [serialize_row(r) for r in rows] + return jsonify({"feedbacks": feedbacks, "success": True}) + except Exception as e: + logger.error(f"[Feedback] Failed to list feedback: {e}") + return jsonify({"error": "Không thể lấy danh sách phản hồi", "success": False}), 500 + finally: + conn.close() + + +# ========================================== +# 6. Social, Friends, and Private Messaging APIs +# ========================================== + +@user_features_bp.route("/api/users/search", methods=["GET"]) +def search_users(): + q = request.args.get("q", "").strip() + if not q: + return jsonify({"users": []}) + user = get_current_user() + user_id = user["id"] if user else None + conn = get_user_db_conn() + try: + like_q = "%" + q + "%" + if user_id: + rows = conn.execute( + """SELECT id, username, user_code, display_name, avatar FROM users + WHERE id != ? AND ( + username LIKE ? OR + email LIKE ? OR + user_code = ? + ) LIMIT 15""", + (user_id, like_q, like_q, q) + ).fetchall() + else: + rows = conn.execute( + """SELECT id, username, user_code, display_name, avatar FROM users + WHERE username LIKE ? OR email LIKE ? OR user_code = ? LIMIT 15""", + (like_q, like_q, q) + ).fetchall() + return jsonify({"users": [serialize_row(r) for r in rows]}) + except Exception as e: + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + + +@user_features_bp.route("/api/notifications/unread-counts", methods=["GET"]) +def get_unread_counts(): + """Separate unread counts: messages vs friend/other notifications.""" + user = get_current_user() + if not user: + return jsonify({"messages": 0, "notifications": 0}) + conn = get_user_db_conn() + try: + # Unread personal messages from direct_messages table + msg_count = conn.execute( + "SELECT COUNT(*) as c FROM direct_messages WHERE receiver_id = ? AND is_read = 0", + (user["id"],) + ).fetchone()["c"] + # Unread other notifications (friend_request, friend_accept, book_share etc) + notif_count = conn.execute( + "SELECT COUNT(*) as c FROM personal_notifications WHERE user_id = ? AND is_read = 0 AND type != 'message'", + (user["id"],) + ).fetchone()["c"] + return jsonify({"messages": msg_count, "notifications": notif_count}) + except Exception as e: + return jsonify({"messages": 0, "notifications": 0}) + finally: + conn.close() + + +@user_features_bp.route("/api/friends/request", methods=["POST"]) +def send_friend_request(): + user = get_current_user() + if not user: + return jsonify({"error": "Unauthorized"}), 401 + + data = request.json or {} + # Accept username, user_code, or email + query = data.get("friend_username") or data.get("friend_code") or data.get("friend_email") or "" + query = query.strip() + if not query: + return jsonify({"error": "Thiếu thông tin tìm kiếm bạn bè"}), 400 + + conn = get_user_db_conn() + try: + target = conn.execute( + "SELECT id, username FROM users WHERE username = ? OR user_code = ? OR email = ?", + (query, query, query.lower()) + ).fetchone() + if not target: + return jsonify({"error": "Không tìm thấy người dùng"}), 404 + + target_id = target["id"] + if target_id == user["id"]: + return jsonify({"error": "Không thể kết bạn với chính mình"}), 400 + + exists = conn.execute("SELECT status FROM friendships WHERE (user_id = ? AND friend_id = ?) OR (user_id = ? AND friend_id = ?)", + (user["id"], target_id, target_id, user["id"])).fetchone() + if exists: + return jsonify({"error": f"Đã có lời mời kết bạn hoặc đã là bạn bè (Trạng thái: {exists['status']})"}), 400 + + conn.execute("INSERT INTO friendships (user_id, friend_id, status) VALUES (?, ?, 'pending')", (user["id"], target_id)) + + conn.execute( + "INSERT INTO personal_notifications (user_id, sender_id, type, message, related_id) VALUES (?, ?, 'friend_request', ?, ?)", + (target_id, user["id"], f"{user['username']} đã gửi cho bạn một lời mời kết bạn.", user["id"]) + ) + conn.commit() + return jsonify({"success": True, "message": "Đã gửi lời mời kết bạn!", "to_user": target["username"]}) + except Exception as e: + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + + +@user_features_bp.route("/api/friends/respond", methods=["POST"]) +def respond_friend_request(): + user = get_current_user() + if not user: + return jsonify({"error": "Unauthorized"}), 401 + + data = request.json or {} + sender_id = data.get("sender_id") + action = data.get("action", "").lower() + + if not sender_id or action not in ['accept', 'reject']: + return jsonify({"error": "Dữ liệu không hợp lệ"}), 400 + + conn = get_user_db_conn() + try: + req = conn.execute("SELECT id FROM friendships WHERE user_id = ? AND friend_id = ? AND status = 'pending'", (sender_id, user["id"])).fetchone() + if not req: + return jsonify({"error": "Không tìm thấy lời mời kết bạn"}), 404 + + if action == 'accept': + conn.execute("UPDATE friendships SET status = 'accepted' WHERE user_id = ? AND friend_id = ?", (sender_id, user["id"])) + # Cross-compatibility check instead of INSERT OR IGNORE + exists = conn.execute("SELECT 1 FROM friendships WHERE user_id = ? AND friend_id = ?", (user["id"], sender_id)).fetchone() + if not exists: + conn.execute("INSERT INTO friendships (user_id, friend_id, status) VALUES (?, ?, 'accepted')", (user["id"], sender_id)) + conn.execute( + "INSERT INTO personal_notifications (user_id, sender_id, type, message, related_id) VALUES (?, ?, 'friend_accept', ?, ?)", + (sender_id, user["id"], f"{user['username']} đã chấp nhận lời mời kết bạn.", user["id"]) + ) + else: + conn.execute("DELETE FROM friendships WHERE user_id = ? AND friend_id = ?", (sender_id, user["id"])) + + conn.execute( + "UPDATE personal_notifications SET is_read = 1 WHERE user_id = ? AND sender_id = ? AND type = 'friend_request'", + (user["id"], sender_id) + ) + conn.commit() + return jsonify({"success": True, "message": f"Đã {'chấp nhận' if action == 'accept' else 'từ chối'} kết bạn."}) + except Exception as e: + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + + +@user_features_bp.route("/api/friends/list", methods=["GET"]) +def list_friends(): + user = get_current_user() + if not user: + return jsonify({"error": "Unauthorized"}), 401 + + conn = get_user_db_conn() + try: + rows = conn.execute( + """SELECT u.id, u.username, u.user_code, u.avatar, + (SELECT COUNT(*) FROM direct_messages dm WHERE dm.sender_id = u.id AND dm.receiver_id = ? AND dm.is_read = 0) as unread_messages + FROM friendships f + JOIN users u ON f.friend_id = u.id + WHERE f.user_id = ? AND f.status = 'accepted'""", + (user["id"], user["id"]) + ).fetchall() + return jsonify({"friends": [serialize_row(r) for r in rows]}) + except Exception as e: + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + + +@user_features_bp.route("/api/friends/unfriend", methods=["POST"]) +@jwt_required +def unfriend(): + """Hủy kết bạn: Xóa quan hệ bạn bè cả hai chiều.""" + user = get_current_user() + if not user: + return jsonify({"error": "Unauthorized"}), 401 + + data = request.json or {} + friend_id = data.get("friend_id") + if not friend_id: + return jsonify({"error": "Thiếu friend_id"}), 400 + + conn = get_user_db_conn() + try: + # Kiểm tra quan hệ tồn tại và đang ở trạng thái accepted + rel = conn.execute( + """SELECT id FROM friendships + WHERE ((user_id = ? AND friend_id = ?) OR (user_id = ? AND friend_id = ?)) + AND status = 'accepted'""", + (user["id"], friend_id, friend_id, user["id"]) + ).fetchone() + if not rel: + return jsonify({"error": "Không tìm thấy quan hệ bạn bè"}), 404 + + # Xóa cả hai chiều + conn.execute( + "DELETE FROM friendships WHERE (user_id = ? AND friend_id = ?) OR (user_id = ? AND friend_id = ?)", + (user["id"], friend_id, friend_id, user["id"]) + ) + conn.commit() + return jsonify({"success": True, "message": "Đã hủy kết bạn."}) + except Exception as e: + logger.error(f"Unfriend error: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + + +@user_features_bp.route("/api/friends/block", methods=["POST"]) +@jwt_required +def block_user(): + """Chặn người dùng: Xóa quan hệ bạn bè (nếu có) và ghi nhận trạng thái blocked.""" + user = get_current_user() + if not user: + return jsonify({"error": "Unauthorized"}), 401 + + data = request.json or {} + target_id = data.get("user_id") + if not target_id: + return jsonify({"error": "Thiếu user_id cần chặn"}), 400 + if target_id == user["id"]: + return jsonify({"error": "Không thể tự chặn chính mình"}), 400 + + conn = get_user_db_conn() + try: + # Kiểm tra đã chặn chưa + already = conn.execute( + "SELECT id FROM friendships WHERE user_id = ? AND friend_id = ? AND status = 'blocked'", + (user["id"], target_id) + ).fetchone() + if already: + return jsonify({"error": "Bạn đã chặn người dùng này rồi"}), 400 + + # Xóa quan hệ bạn bè hai chiều (nếu có) + conn.execute( + "DELETE FROM friendships WHERE (user_id = ? AND friend_id = ?) OR (user_id = ? AND friend_id = ?)", + (user["id"], target_id, target_id, user["id"]) + ) + # Ghi nhận block (một chiều: người chặn → người bị chặn) + conn.execute( + "INSERT OR REPLACE INTO friendships (user_id, friend_id, status) VALUES (?, ?, 'blocked')", + (user["id"], target_id) + ) + conn.commit() + return jsonify({"success": True, "message": "Đã chặn người dùng."}) + except Exception as e: + logger.error(f"Block user error: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + + +@user_features_bp.route("/api/friends/unblock", methods=["POST"]) +@jwt_required +def unblock_user(): + """Bỏ chặn người dùng.""" + user = get_current_user() + if not user: + return jsonify({"error": "Unauthorized"}), 401 + + data = request.json or {} + target_id = data.get("user_id") + if not target_id: + return jsonify({"error": "Thiếu user_id cần bỏ chặn"}), 400 + + conn = get_user_db_conn() + try: + rel = conn.execute( + "SELECT id FROM friendships WHERE user_id = ? AND friend_id = ? AND status = 'blocked'", + (user["id"], target_id) + ).fetchone() + if not rel: + return jsonify({"error": "Bạn chưa chặn người dùng này"}), 404 + + conn.execute( + "DELETE FROM friendships WHERE user_id = ? AND friend_id = ? AND status = 'blocked'", + (user["id"], target_id) + ) + conn.commit() + return jsonify({"success": True, "message": "Đã bỏ chặn người dùng."}) + except Exception as e: + logger.error(f"Unblock user error: {e}") + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + + +@user_features_bp.route("/api/friends/blocked-list", methods=["GET"]) +@jwt_required +def list_blocked(): + """Lấy danh sách người dùng đang bị chặn.""" + user = get_current_user() + if not user: + return jsonify({"error": "Unauthorized"}), 401 + + conn = get_user_db_conn() + try: + rows = conn.execute( + """SELECT u.id, u.username, u.user_code, u.avatar, f.created_at as blocked_at + FROM friendships f + JOIN users u ON f.friend_id = u.id + WHERE f.user_id = ? AND f.status = 'blocked'""", + (user["id"],) + ).fetchall() + return jsonify({"blocked_users": [serialize_row(r) for r in rows]}) + except Exception as e: + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + + +@user_features_bp.route("/api/messages/send", methods=["POST"]) +@jwt_required +def send_message(): + user = get_current_user() + if not user: + return jsonify({"error": "Unauthorized"}), 401 + + data = request.json or {} + receiver_id = data.get("receiver_id") + message = data.get("message", "").strip() + + if not receiver_id or not message: + return jsonify({"error": "Thiếu người nhận hoặc nội dung tin nhắn"}), 400 + + conn = get_user_db_conn() + try: + # Kiểm tra bảo mật: Người nhận có đang chặn người gửi không? + blocked_by_receiver = conn.execute( + "SELECT id FROM friendships WHERE user_id = ? AND friend_id = ? AND status = 'blocked'", + (receiver_id, user["id"]) + ).fetchone() + if blocked_by_receiver: + return jsonify({"error": "Không thể gửi tin nhắn đến người dùng này."}), 403 + + # Kiểm tra bảo mật: Người gửi có đang chặn người nhận không? + blocked_by_sender = conn.execute( + "SELECT id FROM friendships WHERE user_id = ? AND friend_id = ? AND status = 'blocked'", + (user["id"], receiver_id) + ).fetchone() + if blocked_by_sender: + return jsonify({"error": "Bạn đang chặn người dùng này. Bỏ chặn trước khi nhắn tin."}), 403 + + enc_msg = encrypt_message(message) + cursor = conn.execute( + "INSERT INTO direct_messages (sender_id, receiver_id, message) VALUES (?, ?, ?)", + (user["id"], receiver_id, enc_msg) + ) + msg_id = cursor.lastrowid + + conn.execute( + "INSERT INTO personal_notifications (user_id, sender_id, type, message, related_id) VALUES (?, ?, 'message', ?, ?)", + (receiver_id, user["id"], f"{user['username']} đã gửi cho bạn một tin nhắn mới.", msg_id) + ) + conn.commit() + return jsonify({"success": True, "message": "Gửi tin nhắn thành công!", "msg_id": msg_id}) + except Exception as e: + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + + +@user_features_bp.route("/api/messages/chat/", methods=["GET"]) +def get_chat_history(friend_id): + user = get_current_user() + if not user: + return jsonify({"error": "Unauthorized"}), 401 + + conn = get_user_db_conn() + try: + rows = conn.execute( + """SELECT id, sender_id, receiver_id, message, is_read, created_at + FROM direct_messages + WHERE (sender_id = ? AND receiver_id = ?) OR (sender_id = ? AND receiver_id = ?) + ORDER BY created_at ASC""", + (user["id"], friend_id, friend_id, user["id"]) + ).fetchall() + + conn.execute( + "UPDATE direct_messages SET is_read = 1 WHERE sender_id = ? AND receiver_id = ?", + (friend_id, user["id"]) + ) + conn.execute( + "UPDATE personal_notifications SET is_read = 1 WHERE user_id = ? AND sender_id = ? AND type = 'message'", + (user["id"], friend_id) + ) + conn.commit() + + messages = [] + for r in rows: + d = dict(r) + d["message"] = decrypt_message(d.get("message", "")) + for k, v in d.items(): + if hasattr(v, "isoformat"): + d[k] = v.isoformat() + messages.append(d) + + return jsonify({"messages": messages}) + except Exception as e: + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + + +@user_features_bp.route("/api/books/share", methods=["POST"]) +def share_book(): + user = get_current_user() + if not user: + return jsonify({"error": "Unauthorized"}), 401 + + data = request.json or {} + friend_id = data.get("friend_id") + book_id = data.get("book_id") + custom_message = data.get("message", "").strip() + + if not friend_id or not book_id: + return jsonify({"error": "Thiếu thông tin người nhận hoặc truyện cần chia sẻ"}), 400 + + conn = get_user_db_conn() + try: + book_title = "Truyện" + from backend.database.db_manager import get_db + main_conn = get_db() + row = main_conn.execute("SELECT title_vietphrase, title_hanviet, title FROM books WHERE id = ?", (book_id,)).fetchone() + if row: + book_title = row["title_vietphrase"] or row["title_hanviet"] or row["title"] + + msg_content = f"{user['username']} đã chia sẻ truyện '{book_title}' với bạn." + if custom_message: + msg_content += f" Lời nhắn: \"{custom_message}\"" + + conn.execute( + "INSERT INTO personal_notifications (user_id, sender_id, type, message, related_id) VALUES (?, ?, 'book_share', ?, ?)", + (friend_id, user["id"], msg_content, book_id) + ) + + share_chat_msg = f"[Chia sẻ truyện] '{book_title}' - Xem chi tiết tại /book/{book_id}" + if custom_message: + share_chat_msg += f"\nLời nhắn: {custom_message}" + enc_share_msg = encrypt_message(share_chat_msg) + conn.execute( + "INSERT INTO direct_messages (sender_id, receiver_id, message) VALUES (?, ?, ?)", + (user["id"], friend_id, enc_share_msg) + ) + + conn.commit() + return jsonify({"success": True, "message": "Chia sẻ truyện thành công!"}) + except Exception as e: + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + + +@user_features_bp.route("/api/notifications/personal", methods=["GET"]) +def get_personal_notifications(): + user = get_current_user() + if not user: + return jsonify({"notifications": []}) + + conn = get_user_db_conn() + try: + rows = conn.execute( + """SELECT n.id, n.sender_id, n.type, n.message, n.related_id, n.is_read, n.created_at, u.username as sender_name + FROM personal_notifications n + LEFT JOIN users u ON n.sender_id = u.id + WHERE n.user_id = ? + ORDER BY n.created_at DESC LIMIT 50""", + (user["id"],) + ).fetchall() + return jsonify({"notifications": [serialize_row(r) for r in rows]}) + except Exception as e: + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + + +@user_features_bp.route("/api/notifications/personal/read", methods=["POST"]) +def read_personal_notification(): + user = get_current_user() + if not user: + return jsonify({"error": "Unauthorized"}), 401 + + data = request.json or {} + notif_id = data.get("notification_id") + + if not notif_id: + return jsonify({"error": "Thiếu notification_id"}), 400 + + conn = get_user_db_conn() + try: + conn.execute( + "UPDATE personal_notifications SET is_read = 1 WHERE id = ? AND user_id = ?", + (notif_id, user["id"]) + ) + conn.commit() + return jsonify({"success": True}) + except Exception as e: + return jsonify({"error": str(e)}), 500 + finally: + conn.close() + diff --git a/backend/config.py b/backend/config.py new file mode 100644 index 0000000000000000000000000000000000000000..77ef3d8440aa9ec15fe6b4e3e36fb24632ff33d1 --- /dev/null +++ b/backend/config.py @@ -0,0 +1,89 @@ +import os +from datetime import timedelta +from dotenv import load_dotenv + +load_dotenv(override=True) + +class Config: + # Flask settings + SECRET_KEY = os.environ.get("FLASK_SECRET_KEY", "tienhiep_lyvuha_secret_key_9988") + + # Base directories and DB paths + ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + DB_PATH = os.path.join(ROOT_DIR, "merged_books.db") + USER_DB_PATH = os.path.join(ROOT_DIR, "users_data.db") + + # JWT authentication settings + JWT_SECRET = SECRET_KEY + "_jwt_v2_secure" + JWT_ALGORITHM = "HS256" + JWT_ACCESS_TOKEN_EXPIRE = timedelta(days=365) + JWT_REFRESH_TOKEN_EXPIRE = timedelta(days=365) + + # VIP plans + VIP_PLANS = { + "month": { + "name_vi": "Gói Tháng", + "name_en": "Monthly Plan", + "name_zh": "月套餐", + "price": 50000, # 50,000 VND + "duration_days": 30, + "description_vi": "VIP 1 tháng — Dịch không giới hạn, AI, TTS, EPUB", + "description_en": "VIP 1 month — Unlimited translation, AI, TTS, EPUB", + "description_zh": "VIP 1个月 — 无限翻译、AI、TTS、EPUB", + }, + "year": { + "name_vi": "Gói Năm (Tiết kiệm 67%)", + "name_en": "Yearly Plan (Save 67%)", + "name_zh": "年套餐 (节省67%)", + "price": 200000, # 200,000 VND + "duration_days": 365, + "description_vi": "VIP 1 năm — Tất cả quyền lợi VIP, ưu đãi tốt nhất", + "description_en": "VIP 1 year — All VIP benefits, best value", + "description_zh": "VIP 1年 — 所有VIP权益,最优惠", + } + } + + # Payment Gateway Config + PAYMENT_CONFIG = { + "bank_id": os.environ.get("BANK_ID", "MB"), + "account_no": os.environ.get("BANK_ACCOUNT_NO", "0349717475"), + "account_name": os.environ.get("BANK_ACCOUNT_NAME", "LY VU HA"), + "template": "compact2", + "payos_client_id": os.environ.get("PAYOS_CLIENT_ID", ""), + "payos_api_key": os.environ.get("PAYOS_API_KEY", ""), + "payos_checksum_key": os.environ.get("PAYOS_CHECKSUM_KEY", ""), + "payos_webhook_url": os.environ.get("PAYOS_WEBHOOK_URL", "https://yourdomain.com/api/payment/webhook"), + } + + # Rate Limiting + RATE_LIMITS = { + "login": {"max": 5, "window": 300}, + "register": {"max": 3, "window": 600}, + "otp": {"max": 3, "window": 60}, + "payment": {"max": 10, "window": 600}, + } + + # SMTP email config + SMTP_CONFIG = { + "host": "smtp.gmail.com", + "port": 587, + "username": os.environ.get("SMTP_EMAIL", ""), + "password": os.environ.get("SMTP_PASSWORD", ""), + "from_name": "Novel Translator VIP", + "enabled": True if os.environ.get("SMTP_PASSWORD") else False + } + + # Google OAuth + GOOGLE_OAUTH_CONFIG = { + "client_id": os.environ.get("GOOGLE_CLIENT_ID", ""), + "client_secret": os.environ.get("GOOGLE_CLIENT_SECRET", ""), + "redirect_uri": os.environ.get("GOOGLE_REDIRECT_URI", "http://localhost:5050/api/auth/google/callback"), + "enabled": True + } + + # VIP Validation Codes + _vip_codes_env = os.environ.get("VALID_VIP_CODES", "") + if _vip_codes_env: + VALID_VIP_CODES = set(c.strip() for c in _vip_codes_env.split(",") if c.strip()) + else: + VALID_VIP_CODES = {"VIP2026", "ANTIGRAVITY", "PREMIUM_MEMBER", "VIP_TRANSLATOR", "VIP_SERVER", "LYVUHA_ADMIN_2026"} diff --git a/backend/core/__init__.py b/backend/core/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..d2584059a77bd5f99822712702672eb84ccefe72 --- /dev/null +++ b/backend/core/__init__.py @@ -0,0 +1 @@ +# backend/core/__init__.py diff --git a/backend/core/decorators.py b/backend/core/decorators.py new file mode 100644 index 0000000000000000000000000000000000000000..bbbeee0a8abf005750629a9145a98de5f29792a4 --- /dev/null +++ b/backend/core/decorators.py @@ -0,0 +1,140 @@ +from functools import wraps +from datetime import datetime +from flask import request, jsonify, session +from backend.core.security import verify_access_token +from backend.database.db_manager import get_user_db_conn + +def jwt_required(f): + """Decorator: require valid JWT OR session auth.""" + @wraps(f) + def decorated(*args, **kwargs): + # Try JWT first + auth_header = request.headers.get("Authorization", "") + if auth_header.startswith("Bearer "): + token = auth_header[7:] + payload = verify_access_token(token) + if payload: + request._jwt_user = { + "id": int(payload["sub"]), + "username": payload["username"], + "vip_status": payload["vip"] + } + return f(*args, **kwargs) + + # Fall back to session auth + if "user_id" in session: + request._jwt_user = { + "id": session["user_id"], + "username": session["username"], + "vip_status": session.get("vip_status", 0) + } + return f(*args, **kwargs) + + return jsonify({"error": "Authentication required"}), 401 + return decorated + +def require_api_key_auth(f): + """Decorator: require valid Developer API Key or VIP Validation Code auth.""" + @wraps(f) + def decorated(*args, **kwargs): + # 1. Try to find the key in Authorization header + auth_header = request.headers.get("Authorization", "") + api_key = "" + if auth_header.startswith("Bearer "): + api_key = auth_header[7:].strip() + + # If the api_key from Authorization header looks like a JWT token (not sk-tc- and not a valid VIP code), + # clear it so we fall back to other headers or the body. + from backend.config import Config + if api_key and not api_key.startswith("sk-tc-") and api_key not in Config.VALID_VIP_CODES: + api_key = "" + + # 2. Try X-VIP-Key header + if not api_key: + api_key = request.headers.get("X-VIP-Key", "").strip() + + # 3. Try X-VIP-Code header + if not api_key: + api_key = request.headers.get("X-VIP-Code", "").strip() + + # 4. Try request JSON body + if not api_key: + try: + data = request.json or {} + api_key = data.get("vip_key", "") or data.get("vip_code", "") or data.get("api_key", "") + if isinstance(api_key, str): + api_key = api_key.strip() + else: + api_key = "" + except: + pass + + # 5. Check if it's empty + if not api_key: + return jsonify({"error": "Missing API Key or VIP Code. Please authenticate."}), 401 + + # 6. Check if it is a valid static VIP code + from backend.config import Config + if api_key in Config.VALID_VIP_CODES: + # Bypassed - treat as static VIP access with unlimited balance + request.api_key = api_key + request.api_user_id = None + request.api_balance = 999999.0 + return f(*args, **kwargs) + + # 7. Otherwise, it must be a developer key starting with sk-tc- + if not api_key.startswith("sk-tc-"): + return jsonify({"error": "Invalid API key format. Key must start with 'sk-tc-' or be a valid VIP Code."}), 401 + + conn = get_user_db_conn() + key_record = conn.execute( + "SELECT k.*, u.api_balance FROM api_keys k JOIN users u ON k.user_id = u.id WHERE k.api_key = ? AND k.status = 'active'", + (api_key,) + ).fetchone() + + if not key_record: + conn.close() + return jsonify({"error": "API Key not found, inactive, or revoked."}), 401 + + balance = key_record["api_balance"] if key_record["api_balance"] is not None else 0.0 + if balance <= 0.0: + conn.close() + return jsonify({ + "error": f"Tài khoản hết số dư API (Số dư hiện tại: {balance:.2f}đ). Vui lòng nạp thêm tiền tại website để tiếp tục sử dụng." + }), 402 + + # Update last_used_at + now = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S") + conn.execute("UPDATE api_keys SET last_used_at = ? WHERE api_key = ?", (now, api_key)) + conn.commit() + conn.close() + + request.api_key = api_key + request.api_user_id = key_record["user_id"] + request.api_balance = balance + return f(*args, **kwargs) + return decorated + +def get_current_user(): + """Get current user from JWT or session.""" + if hasattr(request, '_jwt_user'): + return request._jwt_user + + auth_header = request.headers.get("Authorization", "") + if auth_header.startswith("Bearer "): + token = auth_header[7:] + payload = verify_access_token(token) + if payload: + return { + "id": int(payload["sub"]), + "username": payload["username"], + "vip_status": payload["vip"] + } + + if "user_id" in session: + return { + "id": session["user_id"], + "username": session["username"], + "vip_status": session.get("vip_status", 0) + } + return None diff --git a/backend/core/logger.py b/backend/core/logger.py new file mode 100644 index 0000000000000000000000000000000000000000..e5ad1deeb5830a146583db68cf13b643b20a0d51 --- /dev/null +++ b/backend/core/logger.py @@ -0,0 +1,53 @@ +import os +import sys +import logging +from logging.handlers import RotatingFileHandler + +# Project root directory detection +PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +LOG_DIR = os.path.join(PROJECT_ROOT, "logs") +LOG_FILE = os.path.join(LOG_DIR, "app.log") + +def setup_logger(name="app", log_level=logging.INFO): + """Sets up a central rolling logger that outputs to both stdout and a file.""" + # Ensure logs directory exists + try: + os.makedirs(LOG_DIR, exist_ok=True) + except Exception as e: + sys.stderr.write(f"[WARNING] Failed to create log directory '{LOG_DIR}': {e}\n") + + logger = logging.getLogger(name) + logger.setLevel(log_level) + + # Avoid duplicate handlers if setup_logger is called multiple times + if logger.handlers: + return logger + + # Log format: time | level | name | message + formatter = logging.Formatter( + "[%(asctime)s] %(levelname)s [%(name)s] %(message)s", + datefmt="%Y-%m-%d %H:%M:%S" + ) + + # Console stream handler + console_handler = logging.StreamHandler(sys.stdout) + console_handler.setFormatter(formatter) + logger.addHandler(console_handler) + + # Rolling file handler + try: + file_handler = RotatingFileHandler( + LOG_FILE, + maxBytes=10 * 1024 * 1024, # 10 MB + backupCount=5, + encoding="utf-8" + ) + file_handler.setFormatter(formatter) + logger.addHandler(file_handler) + except Exception as e: + sys.stderr.write(f"[WARNING] Failed to configure file logger for '{LOG_FILE}': {e}\n") + + return logger + +# Pre-initialize central logger +logger = setup_logger() diff --git a/backend/core/monitoring.py b/backend/core/monitoring.py new file mode 100644 index 0000000000000000000000000000000000000000..59a3b34b889d5f1a250efc6c810caef20b178802 --- /dev/null +++ b/backend/core/monitoring.py @@ -0,0 +1,161 @@ +import os +import shutil +import sqlite3 +import datetime +from backend.config import Config +from backend.database.db_manager import get_user_db_conn, get_db + +def get_cpu_load(): + """Retrieve CPU 1m, 5m, 15m load average on Linux.""" + try: + if os.path.exists("/proc/loadavg"): + with open("/proc/loadavg", "r") as f: + load = f.read().strip().split() + return { + "load_1m": float(load[0]), + "load_5m": float(load[1]), + "load_15m": float(load[2]) + } + except Exception: + pass + return {"load_1m": 0.0, "load_5m": 0.0, "load_15m": 0.0} + +def get_memory_info(): + """Retrieve system RAM and process Resident Set Size (RSS) memory info.""" + mem_total = 0 + mem_available = 0 + process_rss = 0 + + try: + if os.path.exists("/proc/meminfo"): + with open("/proc/meminfo", "r") as f: + for line in f: + if line.startswith("MemTotal:"): + mem_total = int(line.split()[1]) * 1024 # kB to bytes + elif line.startswith("MemAvailable:"): + mem_available = int(line.split()[1]) * 1024 + + if os.path.exists("/proc/self/status"): + with open("/proc/self/status", "r") as f: + for line in f: + if line.startswith("VmRSS:"): + process_rss = int(line.split()[1]) * 1024 + break + except Exception: + pass + + mem_used = mem_total - mem_available + mem_pct = (mem_used / mem_total * 100) if mem_total > 0 else 0.0 + + return { + "total_bytes": mem_total, + "used_bytes": mem_used, + "available_bytes": mem_available, + "percent": round(mem_pct, 2), + "process_rss_bytes": process_rss + } + +def get_disk_info(): + """Retrieve disk space usage of root partition.""" + try: + total, used, free = shutil.disk_usage("/") + percent = (used / total * 100) if total > 0 else 0.0 + return { + "total_bytes": total, + "used_bytes": used, + "free_bytes": free, + "percent": round(percent, 2) + } + except Exception: + return { + "total_bytes": 0, + "used_bytes": 0, + "free_bytes": 0, + "percent": 0.0 + } + +def get_database_sizes(): + """Get the sizes of SQLite databases on disk.""" + sizes = {} + db_paths = { + "user_db": Config.USER_DB_PATH, + "books_db": Config.DB_PATH, + "books_advanced": os.path.join(Config.ROOT_DIR, "merged_books_advanced.db"), + "books_fast": os.path.join(Config.ROOT_DIR, "merged_books_fast.db"), + "books_vietphrase": os.path.join(Config.ROOT_DIR, "merged_books_vietphrase.db"), + "books_hanviet": os.path.join(Config.ROOT_DIR, "merged_books_hanviet.db"), + } + + for key, path in db_paths.items(): + if os.path.exists(path): + sizes[key] = os.path.getsize(path) + else: + sizes[key] = 0 + + return sizes + +def count_log_errors(): + """Scan logs/app.log and count the number of [ERROR] or ERROR level log messages.""" + log_path = os.path.join(Config.ROOT_DIR, "logs", "app.log") + count = 0 + if not os.path.exists(log_path): + return 0 + try: + # Read the file. Since it's limited to 10MB, it's safe to scan + with open(log_path, "r", encoding="utf-8", errors="ignore") as f: + for line in f: + if "ERROR" in line or "[ERROR]" in line: + count += 1 + except Exception: + pass + return count + +def get_system_statistics(): + """Query user database to pull statistics like total users, payments, and API requests.""" + stats = { + "total_users": 0, + "vip_users": 0, + "total_payments": 0, + "total_api_keys": 0, + "total_api_calls": 0, + "total_books_scraped": 0 + } + + try: + conn = get_user_db_conn() + stats["total_users"] = conn.execute("SELECT COUNT(*) FROM users").fetchone()[0] + stats["vip_users"] = conn.execute("SELECT COUNT(*) FROM users WHERE vip_status = 1").fetchone()[0] + + # Check if tables exist before querying + tables = [r[0] for r in conn.execute("SELECT name FROM sqlite_master WHERE type='table'").fetchall()] + + if "payments" in tables: + stats["total_payments"] = conn.execute("SELECT COUNT(*) FROM payments WHERE status = 'completed'").fetchone()[0] + if "api_keys" in tables: + stats["total_api_keys"] = conn.execute("SELECT COUNT(*) FROM api_keys").fetchone()[0] + if "api_usage" in tables: + stats["total_api_calls"] = conn.execute("SELECT COUNT(*) FROM api_usage").fetchone()[0] + + conn.close() + except Exception: + pass + + try: + main_conn = get_db() + stats["total_books_scraped"] = main_conn.execute("SELECT COUNT(*) FROM books").fetchone()[0] + except Exception: + pass + + return stats + +def collect_all_metrics(): + """Gather all diagnostics into a consolidated system metrics dictionary.""" + return { + "timestamp": datetime.datetime.now(datetime.timezone.utc).isoformat(), + "cpu": get_cpu_load(), + "memory": get_memory_info(), + "disk": get_disk_info(), + "databases": get_database_sizes(), + "error_logs_count": count_log_errors(), + "statistics": get_system_statistics() + } diff --git a/backend/core/profiler.py b/backend/core/profiler.py new file mode 100644 index 0000000000000000000000000000000000000000..62e4a3565429d9b8b2ae29cdcd16c10bef374fc6 --- /dev/null +++ b/backend/core/profiler.py @@ -0,0 +1,89 @@ +import time +import logging +import requests +from collections import deque +from flask import g, has_app_context, request + +logger = logging.getLogger("profiler") +logger.setLevel(logging.INFO) +if not logger.handlers: + import sys + handler = logging.StreamHandler(sys.stdout) + handler.setFormatter(logging.Formatter("[%(asctime)s] %(message)s")) + logger.addHandler(handler) + +# Ring buffer for recent profiled requests +recent_profiles = deque(maxlen=100) + +# 1. Monkey patch requests to measure all outbound HTTP API calls +_original_request = requests.request + +def _monitored_request(*args, **kwargs): + start_time = time.time() + try: + return _original_request(*args, **kwargs) + finally: + duration = time.time() - start_time + if has_app_context(): + if not hasattr(g, "external_time"): + g.external_time = 0.0 + g.external_time += duration + +requests.request = _monitored_request + +# DB tracking helper +def record_db_time(duration: float): + if has_app_context(): + if not hasattr(g, "db_time"): + g.db_time = 0.0 + g.db_time += duration + +def get_recent_profiles(): + return list(recent_profiles) + +def setup_profiler(app): + @app.before_request + def start_timer(): + g.start_time = time.time() + g.db_time = 0.0 + g.external_time = 0.0 + + @app.after_request + def log_and_header(response): + if not hasattr(g, "start_time"): + return response + + total_time = time.time() - g.start_time + db_time = getattr(g, "db_time", 0.0) + ext_time = getattr(g, "external_time", 0.0) + cpu_time = max(0.0, total_time - db_time - ext_time) + + # Add latency/breakdown headers in milliseconds + import os + response.headers["X-Response-Time-Ms"] = f"{int(total_time * 1000)}" + response.headers["X-DB-Time-Ms"] = f"{int(db_time * 1000)}" + response.headers["X-External-Time-Ms"] = f"{int(ext_time * 1000)}" + response.headers["X-CPU-Process-Time-Ms"] = f"{int(cpu_time * 1000)}" + response.headers["X-Process-ID"] = str(os.getpid()) + + log_entry = { + "timestamp": time.strftime("%Y-%m-%d %H:%M:%S"), + "method": request.method, + "path": request.path, + "status_code": response.status_code, + "total_ms": round(total_time * 1000, 1), + "db_ms": round(db_time * 1000, 1), + "external_ms": round(ext_time * 1000, 1), + "cpu_ms": round(cpu_time * 1000, 1) + } + recent_profiles.append(log_entry) + + # Print directly to stdout/gunicorn logs + logger.info( + f"[PROFILER] {request.method} {request.path} ({response.status_code}) - " + f"Total: {log_entry['total_ms']}ms | " + f"DB: {log_entry['db_ms']}ms | " + f"External: {log_entry['external_ms']}ms | " + f"CPU/Internal: {log_entry['cpu_ms']}ms" + ) + return response diff --git a/backend/core/rate_limit.py b/backend/core/rate_limit.py new file mode 100644 index 0000000000000000000000000000000000000000..6dbca4a9c7ba53f01f603bae7cab09b65162d5d9 --- /dev/null +++ b/backend/core/rate_limit.py @@ -0,0 +1,50 @@ +import time +import threading +from collections import defaultdict +from flask import request +from backend.config import Config + +rate_limit_store = {} # { "action:identifier": { "count": N, "reset_at": timestamp } } + +# Simple rate limiter to prevent IP scraping abuse +IP_LIMITS = defaultdict(list) +IP_LIMITS_LOCK = threading.Lock() + +def get_client_ip(): + """Retrieve client IP, accounting for cloudflare proxy headers.""" + return request.headers.get("CF-Connecting-IP") or request.headers.get("X-Forwarded-For", "").split(",")[0].strip() or request.remote_addr + +def check_rate_limit(action: str, identifier: str) -> bool: + """Returns True if rate limit exceeded, False if OK.""" + if request.headers.get("X-Bypass-Rate-Limit") == "tienhiep_bypass_secret_9988": + return False + key = f"{action}:{identifier}" + now = time.time() + limit = Config.RATE_LIMITS.get(action, {"max": 100, "window": 60}) + + if key in rate_limit_store: + entry = rate_limit_store[key] + if now > entry["reset_at"]: + rate_limit_store[key] = {"count": 1, "reset_at": now + limit["window"]} + return False + if entry["count"] >= limit["max"]: + return True + entry["count"] += 1 + return False + else: + rate_limit_store[key] = {"count": 1, "reset_at": now + limit["window"]} + return False + +def check_ip_rate_limit(ip: str, max_requests: int = 45, period: int = 60) -> bool: + """Thread-safe sliding window rate limit for book searches / API access.""" + if request.headers.get("X-Bypass-Rate-Limit") == "tienhiep_bypass_secret_9988": + return True + now = time.time() + with IP_LIMITS_LOCK: + if ip not in IP_LIMITS: + IP_LIMITS[ip] = [] + IP_LIMITS[ip] = [t for t in IP_LIMITS[ip] if now - t < period] + if len(IP_LIMITS[ip]) >= max_requests: + return False + IP_LIMITS[ip].append(now) + return True diff --git a/backend/core/security.py b/backend/core/security.py new file mode 100644 index 0000000000000000000000000000000000000000..8b29d392b74114d30c7b5753c01d8c5896e79c7d --- /dev/null +++ b/backend/core/security.py @@ -0,0 +1,227 @@ +import secrets +import hashlib +from datetime import datetime +import bcrypt +import jwt +from backend.config import Config +from backend.database.db_manager import get_user_db_conn + +def hash_password(password: str) -> str: + """Hash password with bcrypt.""" + return bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8') + +def verify_password(password: str, hashed: str) -> bool: + """Verify password against bcrypt hash. Also supports legacy SHA-256.""" + try: + if hashed.startswith("$2b$") or hashed.startswith("$2a$"): + return bcrypt.checkpw(password.encode('utf-8'), hashed.encode('utf-8')) + except Exception: + pass + # Fall back to legacy SHA-256 for old accounts + legacy_hash = hashlib.sha256(password.encode()).hexdigest() + return legacy_hash == hashed + +def upgrade_password_hash(user_id: int, password: str): + """Upgrade a user's password from SHA-256 to bcrypt.""" + new_hash = hash_password(password) + conn = get_user_db_conn() + conn.execute("UPDATE users SET password_hash = ? WHERE id = ?", (new_hash, user_id)) + conn.commit() + conn.close() + +def create_access_token(user_id: int, username: str, vip_status: int) -> str: + """Create a short-lived access token (30 min).""" + payload = { + "sub": str(user_id), + "username": username, + "vip": vip_status, + "type": "access", + "exp": datetime.utcnow() + Config.JWT_ACCESS_TOKEN_EXPIRE, + "iat": datetime.utcnow() + } + return jwt.encode(payload, Config.JWT_SECRET, algorithm=Config.JWT_ALGORITHM) + +def create_refresh_token(user_id: int) -> str: + """Create a long-lived refresh token (7 days), stored in DB.""" + token_str = secrets.token_urlsafe(64) + expires_at = datetime.utcnow() + Config.JWT_REFRESH_TOKEN_EXPIRE + conn = get_user_db_conn() + conn.execute( + "INSERT INTO refresh_tokens (user_id, token, expires_at) VALUES (?, ?, ?)", + (user_id, token_str, expires_at.strftime("%Y-%m-%d %H:%M:%S")) + ) + conn.commit() + conn.close() + return token_str + +def verify_access_token(token: str): + """Verify and decode an access token. Returns payload or None.""" + try: + payload = jwt.decode(token, Config.JWT_SECRET, algorithms=[Config.JWT_ALGORITHM]) + if payload.get("type") != "access": + print(f"[DEBUG JWT] Token type is not access: {payload.get('type')}", flush=True) + return None + return payload + except jwt.ExpiredSignatureError as e: + print(f"[DEBUG JWT] Token expired: {e}", flush=True) + return None + except jwt.InvalidTokenError as e: + print(f"[DEBUG JWT] Invalid token: {e}", flush=True) + return None + except Exception as e: + print(f"[DEBUG JWT] Decode failed: {e}", flush=True) + return None + +import base64 +from cryptography.fernet import Fernet + +def _get_fernet_key() -> bytes: + key_hash = hashlib.sha256(Config.SECRET_KEY.encode()).digest() + return base64.urlsafe_b64encode(key_hash) + +def encrypt_message(message: str) -> str: + """Encrypt message text using symmetric AES encryption.""" + if not message: + return "" + try: + f = Fernet(_get_fernet_key()) + return f.encrypt(message.encode('utf-8')).decode('utf-8') + except Exception as e: + return message + +def decrypt_message(encrypted_message: str) -> str: + """Decrypt message text. Falls back to original text if not encrypted or fails.""" + if not encrypted_message: + return "" + try: + f = Fernet(_get_fernet_key()) + return f.decrypt(encrypted_message.encode('utf-8')).decode('utf-8') + except Exception: + return encrypted_message + +import os +from cryptography.hazmat.primitives.asymmetric import rsa, padding +from cryptography.hazmat.primitives import serialization, hashes +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes + +KEYS_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "keys") +PRIVATE_KEY_PATH = os.path.join(KEYS_DIR, "private_key.pem") +PUBLIC_KEY_PATH = os.path.join(KEYS_DIR, "public_key.pem") + +def get_or_create_rsa_keys(): + """Get RSA keys or generate if they don't exist.""" + if not os.path.exists(KEYS_DIR): + os.makedirs(KEYS_DIR, exist_ok=True) + + if not os.path.exists(PRIVATE_KEY_PATH) or not os.path.exists(PUBLIC_KEY_PATH): + # Generate private key + private_key = rsa.generate_private_key( + public_exponent=65537, + key_size=2048 + ) + # Write private key + with open(PRIVATE_KEY_PATH, "wb") as f: + f.write( + private_key.private_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PrivateFormat.PKCS8, + encryption_algorithm=serialization.NoEncryption() + ) + ) + # Generate and write public key + public_key = private_key.public_key() + with open(PUBLIC_KEY_PATH, "wb") as f: + f.write( + public_key.public_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PublicFormat.SubjectPublicKeyInfo + ) + ) + +def encrypt_asymmetric_hybrid(plaintext: str) -> dict: + """ + Encrypt text using Hybrid Encryption (AES-256-GCM + RSA-2048). + Returns a dict with base64 encoded parts. + """ + if not plaintext: + return {"ciphertext": "", "encrypted_key": "", "nonce": "", "tag": ""} + + # Ensure keys exist + get_or_create_rsa_keys() + + # 1. Generate random 256-bit AES key and 12-byte nonce + aes_key = os.urandom(32) + nonce = os.urandom(12) + + # 2. Encrypt plaintext using AES-GCM + cipher = Cipher(algorithms.AES(aes_key), modes.GCM(nonce)) + encryptor = cipher.encryptor() + ciphertext = encryptor.update(plaintext.encode('utf-8')) + encryptor.finalize() + tag = encryptor.tag + + # 3. Encrypt the AES key using RSA public key + with open(PUBLIC_KEY_PATH, "rb") as f: + public_key = serialization.load_pem_public_key(f.read()) + + encrypted_aes_key = public_key.encrypt( + aes_key, + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None + ) + ) + + # 4. Return all parts as base64 string + return { + "ciphertext": base64.b64encode(ciphertext).decode('utf-8'), + "encrypted_key": base64.b64encode(encrypted_aes_key).decode('utf-8'), + "nonce": base64.b64encode(nonce).decode('utf-8'), + "tag": base64.b64encode(tag).decode('utf-8') + } + +def decrypt_asymmetric_hybrid(ciphertext_b64: str, encrypted_key_b64: str, nonce_b64: str, tag_b64: str) -> str: + """ + Decrypt asymmetric hybrid encrypted payload. + """ + if not ciphertext_b64 or not encrypted_key_b64: + return "" + + # Check if private key exists + if not os.path.exists(PRIVATE_KEY_PATH): + print("[SECURITY] Private key does not exist. Decryption failed.", flush=True) + return "" + + try: + # Decode base64 parts + ciphertext = base64.b64decode(ciphertext_b64.encode('utf-8')) + encrypted_aes_key = base64.b64decode(encrypted_key_b64.encode('utf-8')) + nonce = base64.b64decode(nonce_b64.encode('utf-8')) + tag = base64.b64decode(tag_b64.encode('utf-8')) + + # 1. Decrypt AES key using RSA private key + with open(PRIVATE_KEY_PATH, "rb") as f: + private_key = serialization.load_pem_private_key(f.read(), password=None) + + aes_key = private_key.decrypt( + encrypted_aes_key, + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None + ) + ) + + # 2. Decrypt ciphertext using AES-GCM + cipher = Cipher(algorithms.AES(aes_key), modes.GCM(nonce, tag)) + decryptor = cipher.decryptor() + decrypted_bytes = decryptor.update(ciphertext) + decryptor.finalize() + + return decrypted_bytes.decode('utf-8') + except Exception as e: + import traceback + print(f"[SECURITY] Hybrid decryption failed: {e}", flush=True) + traceback.print_exc() + return "" + + diff --git a/backend/core/watchdog.py b/backend/core/watchdog.py new file mode 100644 index 0000000000000000000000000000000000000000..fb8090c3ab4f3a77207de5aa3c91ed92b01a521f --- /dev/null +++ b/backend/core/watchdog.py @@ -0,0 +1,142 @@ +""" +backend/core/watchdog.py +========================= +Watchdog / Keepalive daemon cho Hugging Face Space. + +Hugging Face Free Tier ngủ đông (sleep) sau ~15 phút không có traffic. +Module này: + 1. Tự ping /health mỗi 10 phút để giữ Space thức. + 2. Giám sát RAM / Disk và log cảnh báo. + 3. Tự động restart gunicorn worker nếu process bị zombie (graceful restart). + 4. Flush log + commit DB tạm thời khi nhận SIGTERM từ HF. + +Sử dụng trong backend/__init__.py: + from backend.core.watchdog import start_watchdog + start_watchdog(app_url="https://cong123779-tienhiep-backend.hf.space") +""" +import os +import time +import threading +import logging +import signal +import urllib.request + +logger = logging.getLogger("watchdog") + +_watchdog_started = False +_stop_event = threading.Event() + + +def _ping_self(url: str) -> bool: + """Ping /health endpoint để HF Space không bị sleep.""" + try: + req = urllib.request.Request( + f"{url.rstrip('/')}/health", + headers={"User-Agent": "TienhiepWatchdog/1.0"} + ) + with urllib.request.urlopen(req, timeout=10) as resp: + return resp.status == 200 + except Exception as e: + logger.warning(f"[Watchdog] Ping failed: {e}") + return False + + +def _log_resources(): + """Log mức sử dụng RAM và Disk.""" + try: + import psutil + mem = psutil.virtual_memory() + disk = psutil.disk_usage("/") + cpu = psutil.cpu_percent(interval=0.1) + logger.info( + f"[Watchdog] RAM: {mem.percent:.1f}% ({mem.used // 1024 // 1024}MB / {mem.total // 1024 // 1024}MB) | " + f"Disk: {disk.percent:.1f}% | CPU: {cpu:.1f}%" + ) + # Cảnh báo khi RAM > 85% + if mem.percent > 85: + logger.warning(f"[Watchdog] ⚠️ HIGH RAM USAGE: {mem.percent:.1f}%!") + if disk.percent > 90: + logger.warning(f"[Watchdog] ⚠️ HIGH DISK USAGE: {disk.percent:.1f}%!") + except ImportError: + pass # psutil không có trên một số môi trường + except Exception as e: + logger.debug(f"[Watchdog] Resource check error: {e}") + + +def _handle_sigterm(signum, frame): + """Graceful shutdown khi HF Space restart container.""" + logger.info("[Watchdog] SIGTERM received — graceful shutdown initiated.") + _stop_event.set() + # Flush log handlers + for handler in logging.root.handlers: + handler.flush() + + +def _watchdog_loop(app_url: str, ping_interval: int, resource_interval: int): + """Main watchdog loop chạy trong background thread.""" + ping_counter = 0 + resource_counter = 0 + + logger.info(f"[Watchdog] 🐕 Started. Ping interval: {ping_interval}s | " + f"Resource check: {resource_interval}s | Target: {app_url}") + + while not _stop_event.is_set(): + time.sleep(30) # Check mỗi 30 giây + ping_counter += 30 + resource_counter += 30 + + if ping_counter >= ping_interval: + ping_counter = 0 + ok = _ping_self(app_url) + logger.info(f"[Watchdog] Keepalive ping → {'✅ OK' if ok else '❌ FAILED'}") + + if resource_counter >= resource_interval: + resource_counter = 0 + _log_resources() + + logger.info("[Watchdog] 🛑 Stopped.") + + +def start_watchdog( + app_url: str = None, + ping_interval: int = 600, # Ping mỗi 10 phút + resource_interval: int = 300, # Check resource mỗi 5 phút +): + """ + Khởi động watchdog daemon thread. + + Args: + app_url: URL public của HF Space (vd: "https://cong123779-tienhiep-backend.hf.space") + Nếu None, tự detect từ env SPACE_HOST. + ping_interval: Số giây giữa các lần ping keepalive (mặc định 600s = 10 phút) + resource_interval: Số giây giữa các lần log resource (mặc định 300s = 5 phút) + """ + global _watchdog_started + if _watchdog_started: + logger.debug("[Watchdog] Already running, skip.") + return + + # Detect URL từ HF environment nếu không truyền + if not app_url: + space_host = os.environ.get("SPACE_HOST", "") + if space_host: + app_url = f"https://{space_host}" + else: + logger.info("[Watchdog] No SPACE_HOST env, running in local mode (no ping).") + app_url = "http://localhost:7860" + + # Register SIGTERM handler để graceful shutdown + try: + signal.signal(signal.SIGTERM, _handle_sigterm) + except (ValueError, OSError): + pass # Không register được trong thread con + + thread = threading.Thread( + target=_watchdog_loop, + args=(app_url, ping_interval, resource_interval), + daemon=True, + name="WatchdogKeepAlive" + ) + thread.start() + _watchdog_started = True + logger.info(f"[Watchdog] 🐕 Daemon started (thread: {thread.name})") diff --git a/backend/database/__init__.py b/backend/database/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..48e9d38dab9426e9b40c650a2492fd17fd59f82b --- /dev/null +++ b/backend/database/__init__.py @@ -0,0 +1 @@ +# backend/database/__init__.py diff --git a/backend/database/db_manager.py b/backend/database/db_manager.py new file mode 100644 index 0000000000000000000000000000000000000000..93b5479a6189f77bed0353564683d38d24b92d21 --- /dev/null +++ b/backend/database/db_manager.py @@ -0,0 +1,970 @@ +import os +import sys +import time +import sqlite3 +import threading +import logging +from collections import OrderedDict +from backend.config import Config + +logger = logging.getLogger("db_manager") +logger.setLevel(logging.INFO) +if not logger.handlers: + handler = logging.StreamHandler(sys.stdout) + handler.setFormatter(logging.Formatter( + "[%(asctime)s] %(levelname)s [db_manager] %(message)s", + datefmt="%Y-%m-%d %H:%M:%S" + )) + logger.addHandler(handler) + +DATABASE_URL = os.environ.get("DATABASE_URL", "") +USE_LOCAL_SQLITE = os.environ.get("USE_LOCAL_SQLITE", "false").lower() == "true" +if USE_LOCAL_SQLITE: + DATABASE_URL = "" +USER_DB_PATH = Config.USER_DB_PATH + +# Retry & circuit breaker settings +MAX_RETRIES = 3 +RETRY_BASE_DELAY = 0.5 # seconds +CIRCUIT_BREAKER_THRESHOLD = 5 # consecutive failures before opening circuit +CIRCUIT_BREAKER_RESET = 30 # seconds before retrying after circuit opens + +# Circuit Breaker State +_lock = threading.Lock() +_failure_count = 0 +_circuit_open_until = 0.0 # timestamp when circuit should try again +_last_mode = "unknown" # track for logging + +def _is_circuit_open(): + """Check if the circuit breaker is open (cloud DB unavailable).""" + global _failure_count, _circuit_open_until + with _lock: + if _failure_count >= CIRCUIT_BREAKER_THRESHOLD: + if time.time() < _circuit_open_until: + return True + return False + return False + +def _record_success(): + """Record a successful cloud DB connection — reset circuit breaker.""" + global _failure_count, _circuit_open_until, _last_mode + with _lock: + if _failure_count > 0: + logger.info("✔ Supabase connection restored. Resetting circuit breaker.") + _failure_count = 0 + _circuit_open_until = 0.0 + _last_mode = "postgres" + +def _record_failure(): + """Record a failed cloud DB connection — increment circuit breaker.""" + global _failure_count, _circuit_open_until, _last_mode + with _lock: + _failure_count += 1 + if _failure_count >= CIRCUIT_BREAKER_THRESHOLD: + _circuit_open_until = time.time() + CIRCUIT_BREAKER_RESET + if _last_mode != "sqlite_fallback": + logger.warning( + f"⚡ Circuit breaker OPEN after {_failure_count} failures. " + f"Falling back to SQLite for {CIRCUIT_BREAKER_RESET}s." + ) + _last_mode = "sqlite_fallback" + +# PostgreSQL wrappers +class PgCursorWrapper: + def __init__(self, pg_cursor, lastrowid=None, conn_wrapper=None): + self._cur = pg_cursor + self._lastrowid = lastrowid + self._conn_wrapper = conn_wrapper + + def execute(self, sql, parameters=None): + if self._conn_wrapper: + sql = self._conn_wrapper._translate_sql(sql) + if parameters: + self._cur.execute(sql, parameters) + else: + self._cur.execute(sql) + return self + + def fetchone(self): + return self._cur.fetchone() + + def fetchall(self): + return self._cur.fetchall() + + @property + def lastrowid(self): + return self._lastrowid + + @property + def description(self): + return self._cur.description + +class PgConnectionWrapper: + def __init__(self, pg_conn, pool=None): + self._conn = pg_conn + self._pool = pool + + @property + def row_factory(self): + return None + + @row_factory.setter + def row_factory(self, val): + pass + + def cursor(self): + import psycopg2.extras + cursor = self._conn.cursor(cursor_factory=psycopg2.extras.DictCursor) + return PgCursorWrapper(cursor, conn_wrapper=self) + + def execute(self, sql, parameters=None): + sql_pg = self._translate_sql(sql) + is_insert = sql_pg.strip().upper().startswith("INSERT") + if is_insert and "RETURNING" not in sql_pg.upper(): + if "USER_SETTINGS" in sql_pg.upper(): + sql_pg += " RETURNING user_id" + else: + sql_pg += " RETURNING id" + + import psycopg2.extras + cursor = self._conn.cursor(cursor_factory=psycopg2.extras.DictCursor) + sql_upper = sql_pg.upper() + + start_time = time.time() + try: + if parameters: + cursor.execute(sql_pg, parameters) + elif "CREATE TABLE" in sql_upper or "ALTER TABLE" in sql_upper: + try: + cursor.execute("SAVEPOINT sp_ddl") + cursor.execute(sql_pg) + cursor.execute("RELEASE SAVEPOINT sp_ddl") + except Exception as e: + cursor.execute("ROLLBACK TO SAVEPOINT sp_ddl") + cursor.execute("RELEASE SAVEPOINT sp_ddl") + raise + else: + cursor.execute(sql_pg) + finally: + try: + from backend.core.profiler import record_db_time + record_db_time(time.time() - start_time) + except Exception: + pass + + lastrowid = None + if is_insert: + try: + row = cursor.fetchone() + if row: + lastrowid = row[0] + except Exception: + pass + + return PgCursorWrapper(cursor, lastrowid) + + def commit(self): + start_time = time.time() + try: + self._conn.commit() + finally: + try: + from backend.core.profiler import record_db_time + record_db_time(time.time() - start_time) + except Exception: + pass + + def close(self): + if self._pool is not None: + try: + try: + self._conn.rollback() + except Exception: + pass + self._pool.putconn(self._conn) + except Exception as e: + logger.error(f"Error returning connection to pool: {e}") + try: + self._conn.close() + except Exception: + pass + else: + self._conn.close() + + @staticmethod + def _translate_sql(sql): + import re + if re.search(r"INSERT\s+OR\s+IGNORE\s+INTO\s+bookshelf", sql, re.IGNORECASE): + sql = re.sub(r"INSERT\s+OR\s+IGNORE\s+INTO", "INSERT INTO", sql, flags=re.IGNORECASE) + if "ON CONFLICT" not in sql.upper(): + sql += " ON CONFLICT (user_id, book_id) DO NOTHING" + elif re.search(r"INSERT\s+OR\s+REPLACE\s+INTO\s+bookshelf", sql, re.IGNORECASE): + sql = re.sub(r"INSERT\s+OR\s+REPLACE\s+INTO", "INSERT INTO", sql, flags=re.IGNORECASE) + if "ON CONFLICT" not in sql.upper(): + sql += " ON CONFLICT (user_id, book_id) DO UPDATE SET title = EXCLUDED.title, author = EXCLUDED.author, cover = EXCLUDED.cover, url = EXCLUDED.url" + elif re.search(r"INSERT\s+OR\s+REPLACE\s+INTO\s+reading_history", sql, re.IGNORECASE): + sql = re.sub(r"INSERT\s+OR\s+REPLACE\s+INTO", "INSERT INTO", sql, flags=re.IGNORECASE) + if "ON CONFLICT" not in sql.upper(): + if "URL" in sql.upper(): + sql += " ON CONFLICT (user_id, book_id) DO UPDATE SET title = EXCLUDED.title, author = EXCLUDED.author, cover = EXCLUDED.cover, last_chapter = EXCLUDED.last_chapter, read_date = EXCLUDED.read_date, url = EXCLUDED.url" + else: + sql += " ON CONFLICT (user_id, book_id) DO UPDATE SET title = EXCLUDED.title, author = EXCLUDED.author, cover = EXCLUDED.cover, last_chapter = EXCLUDED.last_chapter, read_date = EXCLUDED.read_date, timestamp = EXCLUDED.timestamp" + elif re.search(r"INSERT\s+OR\s+REPLACE\s+INTO\s+friendships", sql, re.IGNORECASE): + sql = re.sub(r"INSERT\s+OR\s+REPLACE\s+INTO", "INSERT INTO", sql, flags=re.IGNORECASE) + if "ON CONFLICT" not in sql.upper(): + sql += " ON CONFLICT (user_id, friend_id) DO UPDATE SET status = EXCLUDED.status" + + sql_upper = sql.upper() + if "CREATE TABLE" in sql_upper: + sql = sql.replace("CREATE TABLE ", "CREATE TABLE IF NOT EXISTS ") + sql = sql.replace("CREATE TABLE IF NOT EXISTS IF NOT EXISTS", + "CREATE TABLE IF NOT EXISTS") + sql = sql.replace("INTEGER PRIMARY KEY AUTOINCREMENT", "SERIAL PRIMARY KEY") + sql = sql.replace("DATETIME DEFAULT CURRENT_TIMESTAMP", + "TIMESTAMP DEFAULT CURRENT_TIMESTAMP") + sql = sql.replace("DATETIME", "TIMESTAMP") + + # Translate LIKE to ILIKE for case-insensitive matching on PostgreSQL + if " LIKE " in sql_upper: + sql = re.sub(r"\bLIKE\b", "ILIKE", sql, flags=re.IGNORECASE) + + sql = sql.replace('?', '%s') + return sql + +_pg_pool = None +_pool_lock = threading.Lock() + +def _get_pg_pool(): + global _pg_pool + if not DATABASE_URL: + return None + if _pg_pool is not None: + return _pg_pool + with _pool_lock: + if _pg_pool is None: + try: + from psycopg2.pool import ThreadedConnectionPool + _pg_pool = ThreadedConnectionPool(2, 20, DATABASE_URL, connect_timeout=5) + logger.info("✔ Threaded Supabase connection pool initialized successfully.") + except Exception as e: + logger.error(f"Failed to initialize Threaded connection pool: {e}") + _pg_pool = None + return _pg_pool + +def _try_postgres_connect(): + pool = _get_pg_pool() + if pool is None: + raise Exception("Supabase Connection Pool not initialized.") + + conn = None + for i in range(3): + try: + conn = pool.getconn() + with conn.cursor() as cur: + cur.execute("SELECT 1") + break + except Exception as e: + logger.warning(f"Got unhealthy connection from pool: {e}. Closing and retrying...") + if conn: + try: + pool.putconn(conn, close=True) + except Exception: + pass + conn = None + + if conn is None: + raise Exception("Failed to obtain a healthy connection from the pool.") + + return PgConnectionWrapper(conn, pool) + +class ProfiledSqliteConnection(sqlite3.Connection): + def execute(self, sql, *args): + start_time = time.time() + try: + return super().execute(sql, *args) + finally: + try: + from backend.core.profiler import record_db_time + record_db_time(time.time() - start_time) + except Exception: + pass + +def _get_sqlite_conn(): + conn = sqlite3.connect(USER_DB_PATH, timeout=10, factory=ProfiledSqliteConnection) + conn.execute("PRAGMA synchronous=NORMAL;") + conn.execute("PRAGMA synchronous=NORMAL;") + conn.execute("PRAGMA cache_size=-64000;") + conn.execute("PRAGMA temp_store=MEMORY;") + conn.row_factory = sqlite3.Row + return conn + +def get_user_db_conn(): + """Get user database connection with automatic failover.""" + if not DATABASE_URL: + return _get_sqlite_conn() + if _is_circuit_open(): + return _get_sqlite_conn() + + last_error = None + for attempt in range(MAX_RETRIES): + try: + conn = _try_postgres_connect() + _record_success() + return conn + except Exception as e: + last_error = e + delay = RETRY_BASE_DELAY * (2 ** attempt) + if attempt < MAX_RETRIES - 1: + logger.warning( + f"Supabase connection attempt {attempt + 1}/{MAX_RETRIES} failed: " + f"{e}. Retrying in {delay:.1f}s..." + ) + time.sleep(delay) + + _record_failure() + logger.error(f"Supabase unreachable: {last_error}. Using SQLite fallback.") + return _get_sqlite_conn() + +def health_check(): + status = { + "timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), + "database": { + "primary": "supabase_postgres" if DATABASE_URL else "sqlite_only", + "fallback": "sqlite_local", + "circuit_breaker": { + "state": "open" if _is_circuit_open() else "closed", + "failure_count": _failure_count, + "threshold": CIRCUIT_BREAKER_THRESHOLD, + }, + }, + "status": "healthy", + } + if DATABASE_URL and not _is_circuit_open(): + try: + conn = _try_postgres_connect() + conn.close() # Returns to pool via PgConnectionWrapper + status["database"]["primary_reachable"] = True + except Exception as e: + status["database"]["primary_reachable"] = False + status["database"]["primary_error"] = str(e) + status["status"] = "degraded" + elif _is_circuit_open(): + status["database"]["primary_reachable"] = False + status["status"] = "degraded" + + # Use a lightweight check without opening a new connection + try: + if os.path.exists(USER_DB_PATH) and os.path.getsize(USER_DB_PATH) > 0: + status["database"]["fallback_reachable"] = True + else: + status["database"]["fallback_reachable"] = False + status["status"] = "degraded" + except Exception as e: + status["database"]["fallback_reachable"] = False + status["database"]["fallback_error"] = str(e) + status["status"] = "unhealthy" + + return status + +def _init_db_schema_for_conn(conn): + is_postgres = (type(conn).__name__ == "PgConnectionWrapper") + conn.execute(""" + CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT UNIQUE, + password_hash TEXT, + email TEXT, + phone TEXT, + google_id TEXT, + vip_status INTEGER DEFAULT 0, + vip_plan TEXT, + vip_expiry DATETIME, + email_verified INTEGER DEFAULT 0, + require_password_change INTEGER DEFAULT 0, + display_name TEXT, + birthday TEXT, + gender TEXT, + bio TEXT, + avatar_frame TEXT DEFAULT 'default', + avatar TEXT, + two_factor INTEGER DEFAULT 0, + api_balance REAL DEFAULT 0.0, + user_code TEXT UNIQUE, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP + ) + """) + # Run database migrations for users columns if needed + if is_postgres: + # Postgres columns check + cursor = conn.execute("SELECT column_name FROM information_schema.columns WHERE table_name = 'users'") + columns = [row[0] for row in cursor.fetchall()] + else: + # SQLite columns check + cursor = conn.execute("PRAGMA table_info(users)") + columns = [row[1] for row in cursor.fetchall()] + + if "email_verified" not in columns: + conn.execute("ALTER TABLE users ADD COLUMN email_verified INTEGER DEFAULT 0") + if "require_password_change" not in columns: + conn.execute("ALTER TABLE users ADD COLUMN require_password_change INTEGER DEFAULT 0") + if "display_name" not in columns: + conn.execute("ALTER TABLE users ADD COLUMN display_name TEXT") + if "birthday" not in columns: + conn.execute("ALTER TABLE users ADD COLUMN birthday TEXT") + if "gender" not in columns: + conn.execute("ALTER TABLE users ADD COLUMN gender TEXT") + if "bio" not in columns: + conn.execute("ALTER TABLE users ADD COLUMN bio TEXT") + if "avatar_frame" not in columns: + conn.execute("ALTER TABLE users ADD COLUMN avatar_frame TEXT DEFAULT 'default'") + if "avatar" not in columns: + conn.execute("ALTER TABLE users ADD COLUMN avatar TEXT") + if "two_factor" not in columns: + conn.execute("ALTER TABLE users ADD COLUMN two_factor INTEGER DEFAULT 0") + if "api_balance" not in columns: + conn.execute("ALTER TABLE users ADD COLUMN api_balance REAL DEFAULT 0.0") + if "user_code" not in columns: + conn.execute("ALTER TABLE users ADD COLUMN user_code TEXT") + # Backfill existing users with random 7-digit codes + import random, string + existing_users = conn.execute("SELECT id FROM users WHERE user_code IS NULL").fetchall() + for u in existing_users: + while True: + code = ''.join(random.choices(string.digits, k=7)) + clash = conn.execute("SELECT 1 FROM users WHERE user_code = ?", (code,)).fetchone() + if not clash: + conn.execute("UPDATE users SET user_code = ? WHERE id = ?", (code, u['id'])) + break + + conn.execute(""" + CREATE TABLE IF NOT EXISTS bookshelf ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER, + book_id INTEGER, + title TEXT, + cover TEXT, + author TEXT, + url TEXT, + added_at DATETIME DEFAULT CURRENT_TIMESTAMP, + UNIQUE(user_id, book_id) + ) + """) + conn.execute(""" + CREATE TABLE IF NOT EXISTS reading_history ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER, + book_id INTEGER, + title TEXT, + cover TEXT, + author TEXT, + last_chapter TEXT, + read_date TEXT, + url TEXT, + timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, + UNIQUE(user_id, book_id) + ) + """) + conn.execute(""" + CREATE TABLE IF NOT EXISTS payments ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER NOT NULL, + order_id TEXT UNIQUE NOT NULL, + plan TEXT NOT NULL, + amount INTEGER NOT NULL, + status TEXT DEFAULT 'pending', + payment_method TEXT DEFAULT 'vietqr', + note TEXT, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + completed_at DATETIME, + FOREIGN KEY (user_id) REFERENCES users(id) + ) + """) + conn.execute(""" + CREATE TABLE IF NOT EXISTS password_reset_tokens ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER NOT NULL, + token TEXT UNIQUE NOT NULL, + expires_at DATETIME NOT NULL, + used INTEGER DEFAULT 0, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (user_id) REFERENCES users(id) + ) + """) + conn.execute(""" + CREATE TABLE IF NOT EXISTS refresh_tokens ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER NOT NULL, + token TEXT UNIQUE NOT NULL, + expires_at DATETIME NOT NULL, + revoked INTEGER DEFAULT 0, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (user_id) REFERENCES users(id) + ) + """) + conn.execute(""" + CREATE TABLE IF NOT EXISTS api_keys ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER NOT NULL, + api_key TEXT UNIQUE NOT NULL, + name TEXT DEFAULT 'Default Key', + status TEXT DEFAULT 'active', + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + last_used_at DATETIME, + FOREIGN KEY (user_id) REFERENCES users(id) + ) + """) + conn.execute(""" + CREATE TABLE IF NOT EXISTS api_usage ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + api_key TEXT NOT NULL, + model TEXT NOT NULL, + tokens INTEGER DEFAULT 0, + cost REAL DEFAULT 0.0, + status_code INTEGER, + timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (api_key) REFERENCES api_keys(api_key) + ) + """) + conn.execute(""" + CREATE TABLE IF NOT EXISTS translation_history ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER NOT NULL, + original_text TEXT NOT NULL, + translated_text TEXT NOT NULL, + mode TEXT DEFAULT 'fast', + characters INTEGER DEFAULT 0, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (user_id) REFERENCES users(id) + ) + """) + conn.execute(""" + CREATE TABLE IF NOT EXISTS vocabulary ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER NOT NULL, + original_text TEXT NOT NULL, + pinyin_or_hanviet TEXT, + translation TEXT NOT NULL, + context_sentence TEXT, + notes TEXT, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (user_id) REFERENCES users(id) + ) + """) + conn.execute(""" + CREATE TABLE IF NOT EXISTS user_settings ( + user_id INTEGER PRIMARY KEY, + theme TEXT DEFAULT 'dark', + default_language TEXT DEFAULT 'vi', + auto_read INTEGER DEFAULT 0, + font_size INTEGER DEFAULT 14, + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (user_id) REFERENCES users(id) + ) + """) + conn.execute(""" + CREATE TABLE IF NOT EXISTS usage_tracking ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER NOT NULL, + source TEXT NOT NULL, + action TEXT NOT NULL, + duration INTEGER DEFAULT 0, + mode TEXT DEFAULT 'online', + timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (user_id) REFERENCES users(id) + ) + """) + conn.execute(""" + CREATE TABLE IF NOT EXISTS login_history ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER NOT NULL, + ip_address TEXT, + user_agent TEXT, + os TEXT, + browser TEXT, + device_type TEXT, + token TEXT, + status TEXT DEFAULT 'active', + login_time DATETIME DEFAULT CURRENT_TIMESTAMP, + last_active DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (user_id) REFERENCES users(id) + ) + """) + conn.execute(""" + CREATE TABLE IF NOT EXISTS friendships ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER NOT NULL, + friend_id INTEGER NOT NULL, + status TEXT DEFAULT 'pending', + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (user_id) REFERENCES users(id), + FOREIGN KEY (friend_id) REFERENCES users(id), + UNIQUE(user_id, friend_id) + ) + """) + conn.execute(""" + CREATE TABLE IF NOT EXISTS direct_messages ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + sender_id INTEGER NOT NULL, + receiver_id INTEGER NOT NULL, + message TEXT NOT NULL, + is_read INTEGER DEFAULT 0, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (sender_id) REFERENCES users(id), + FOREIGN KEY (receiver_id) REFERENCES users(id) + ) + """) + conn.execute(""" + CREATE TABLE IF NOT EXISTS personal_notifications ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER NOT NULL, + sender_id INTEGER, + type TEXT NOT NULL, + message TEXT NOT NULL, + related_id INTEGER, + is_read INTEGER DEFAULT 0, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (user_id) REFERENCES users(id), + FOREIGN KEY (sender_id) REFERENCES users(id) + ) + """) + + for table in ["bookshelf", "reading_history"]: + try: + conn.execute(f"ALTER TABLE {table} ADD COLUMN url TEXT") + except Exception: + pass + + new_user_cols = [ + ("email", "TEXT"), + ("phone", "TEXT"), + ("google_id", "TEXT"), + ("vip_plan", "TEXT"), + ("vip_expiry", "DATETIME"), + ("api_balance", "REAL DEFAULT 0.0"), + ] + for col_name, col_type in new_user_cols: + try: + conn.execute(f"ALTER TABLE users ADD COLUMN {col_name} {col_type}") + except Exception: + pass + + conn.execute("CREATE INDEX IF NOT EXISTS idx_users_username ON users(username)") + conn.execute("CREATE UNIQUE INDEX IF NOT EXISTS idx_users_user_code ON users(user_code)") + conn.execute("CREATE INDEX IF NOT EXISTS idx_reading_history_user_id ON reading_history(user_id)") + conn.execute("CREATE INDEX IF NOT EXISTS idx_reading_history_url ON reading_history(url)") + conn.execute("CREATE INDEX IF NOT EXISTS idx_bookshelf_user_id ON bookshelf(user_id)") + conn.execute("CREATE INDEX IF NOT EXISTS idx_translation_history_user_id ON translation_history(user_id)") + conn.execute("CREATE INDEX IF NOT EXISTS idx_vocabulary_user_id ON vocabulary(user_id)") + + conn.execute(""" + CREATE TABLE IF NOT EXISTS sects ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT UNIQUE, + slogan TEXT, + announcement TEXT, + badge TEXT, + leader_id INTEGER, + level INTEGER DEFAULT 1, + contribution INTEGER DEFAULT 0, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP + ) + """) + conn.execute(""" + CREATE TABLE IF NOT EXISTS sect_members ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + sect_id INTEGER, + user_id INTEGER UNIQUE, + role TEXT DEFAULT 'member', + contribution INTEGER DEFAULT 0, + joined_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (sect_id) REFERENCES sects(id), + FOREIGN KEY (user_id) REFERENCES users(id) + ) + """) + conn.execute(""" + CREATE TABLE IF NOT EXISTS sect_messages ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + sect_id INTEGER, + sender_id INTEGER, + message TEXT, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (sect_id) REFERENCES sects(id), + FOREIGN KEY (sender_id) REFERENCES users(id) + ) + """) + conn.execute(""" + CREATE TABLE IF NOT EXISTS sect_join_requests ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + sect_id INTEGER, + user_id INTEGER, + status TEXT DEFAULT 'pending', + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (sect_id) REFERENCES sects(id), + FOREIGN KEY (user_id) REFERENCES users(id), + UNIQUE(sect_id, user_id) + ) + """) + conn.execute(""" + CREATE TABLE IF NOT EXISTS sect_books ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + sect_id INTEGER, + book_id INTEGER, + added_by INTEGER, + added_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (sect_id) REFERENCES sects(id), + FOREIGN KEY (added_by) REFERENCES users(id), + UNIQUE(sect_id, book_id) + ) + """) + + conn.execute(""" + CREATE TABLE IF NOT EXISTS sect_chat_groups ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + sect_id INTEGER, + name TEXT, + creator_id INTEGER, + members_csv TEXT, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (sect_id) REFERENCES sects(id), + FOREIGN KEY (creator_id) REFERENCES users(id) + ) + """) + + conn.execute(""" + CREATE TABLE IF NOT EXISTS book_comments ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + book_id INTEGER NOT NULL, + user_id INTEGER, + is_anonymous INTEGER DEFAULT 0, + content_ciphertext TEXT NOT NULL, + encrypted_aes_key TEXT NOT NULL, + aes_nonce TEXT NOT NULL, + aes_tag TEXT NOT NULL, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP + ) + """) + + + try: + conn.execute("ALTER TABLE sects ADD COLUMN announcement TEXT") + except Exception: + pass + + for col_name, col_type in [("chat_type", "TEXT DEFAULT 'general'"), ("target_id", "INTEGER"), ("group_id", "INTEGER")]: + try: + conn.execute(f"ALTER TABLE sect_messages ADD COLUMN {col_name} {col_type}") + except Exception: + pass + + conn.execute("CREATE INDEX IF NOT EXISTS idx_sect_members_sect_id ON sect_members(sect_id)") + conn.execute("CREATE INDEX IF NOT EXISTS idx_sect_members_user_id ON sect_members(user_id)") + conn.execute("CREATE INDEX IF NOT EXISTS idx_sect_messages_sect_id ON sect_messages(sect_id)") + conn.execute("CREATE INDEX IF NOT EXISTS idx_sect_books_sect_id ON sect_books(sect_id)") + conn.execute("CREATE INDEX IF NOT EXISTS idx_sect_join_requests_sect_id ON sect_join_requests(sect_id)") + + conn.execute(""" + CREATE TABLE IF NOT EXISTS app_releases ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + platform TEXT, + version TEXT, + download_url TEXT, + patch_url TEXT, + file_size TEXT, + release_notes TEXT, + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, + UNIQUE(platform, version) + ) + """) + # Migration: thêm cột patch_url cho bảng cũ nếu chưa có + try: + conn.execute("ALTER TABLE app_releases ADD COLUMN patch_url TEXT") + except Exception: + pass # Cột đã tồn tại + try: + existing = conn.execute("SELECT COUNT(*) as count FROM app_releases").fetchone() + count = 0 + if existing: + if isinstance(existing, dict): + count = existing.get('count', 0) + elif hasattr(existing, 'keys'): + count = existing['count'] + else: + count = existing[0] + if count == 0: + conn.execute(""" + INSERT INTO app_releases (platform, version, download_url, file_size, release_notes) + VALUES + ('extension', '1.0.0', '/downloads/tts_extension.zip', '10.7 MB', 'Cập nhật dịch nhanh và tối ưu hóa Chrome Extension Helper'), + ('desktop_linux', '0.0.0', 'https://huggingface.co/datasets/Cong123779/tienhiep-data/resolve/main/downloads/TienHiepAI-0.0.0.AppImage', '116 MB', 'Phiên bản AppImage beta dành cho Linux'), + ('desktop_windows', '0.0.0', '#', '0 MB', 'Bản Windows Setup .EXE chính thức sắp ra mắt') + """) + except Exception as e: + logger.warning(f"Failed to seed app_releases: {e}") + + conn.commit() + + +def init_user_db(): + conn = get_user_db_conn() + try: + _init_db_schema_for_conn(conn) + logger.info("✔ Database initialized successfully.") + except Exception as e: + logger.error(f"❌ Database initialization failed: {e}") + raise + finally: + conn.close() + + is_postgres = (type(conn).__name__ == "PgConnectionWrapper") + if is_postgres: + try: + sqlite_conn = sqlite3.connect(USER_DB_PATH) + sqlite_conn.row_factory = sqlite3.Row + _init_db_schema_for_conn(sqlite_conn) + sqlite_conn.close() + logger.info("✔ SQLite fallback database synchronized successfully.") + except Exception as sqlite_err: + logger.warning(f"⚠️ Could not synchronize SQLite fallback database schema: {sqlite_err}") + +# --------------------------------------------------------------------------- +# Books SQLite databases thread local caching +# --------------------------------------------------------------------------- +thread_local = threading.local() + +class SimpleCache: + def __init__(self, maxsize=500): + self.cache = OrderedDict() + self.maxsize = maxsize + self.lock = threading.Lock() + + def get(self, key): + with self.lock: + if key in self.cache: + self.cache.move_to_end(key) + return self.cache[key] + return None + + def set(self, key, value): + with self.lock: + if key in self.cache: + self.cache.move_to_end(key) + self.cache[key] = value + if len(self.cache) > self.maxsize: + self.cache.popitem(last=False) + +count_cache = SimpleCache(maxsize=1000) +query_cache = SimpleCache(maxsize=1000) +cached_stats = None + +# Cache the resolved DB path to avoid re-reading YAML config on every call +_cached_db_path = None +_cached_db_path_time = 0 +_DB_PATH_CACHE_DURATION = 60 # Re-check config every 60 seconds + +def ensure_db_exists(db_path): + """Lazy download book SQLite databases from HuggingFace dataset if missing or incomplete.""" + if os.path.exists(db_path) and os.path.getsize(db_path) > 1024 * 1024: + return + + filename = os.path.basename(db_path) + token = os.environ.get("HF_TOKEN") + if not token: + logger.warning(f"⚠️ HF_TOKEN not set, cannot download database file: {filename}") + return + + logger.info(f"⏳ Lazy-downloading database from HF: {filename}...") + try: + from huggingface_hub import hf_hub_download + hf_hub_download( + repo_id="Cong123779/tienhiep-data", + filename=filename, + repo_type="dataset", + token=token, + local_dir=Config.ROOT_DIR, + local_dir_use_symlinks=False, + ) + logger.info(f"✔ Successfully downloaded {filename}") + except Exception as e: + logger.error(f"❌ Failed to lazy-download database {filename}: {e}") + +def get_db(): + global _cached_db_path, _cached_db_path_time + + now = time.time() + if _cached_db_path is None or (now - _cached_db_path_time) > _DB_PATH_CACHE_DURATION: + db_path = Config.DB_PATH + try: + config_path = os.path.join(Config.ROOT_DIR, "quick_translator", "config.yaml") + if os.path.exists(config_path): + import yaml + with open(config_path, "r", encoding="utf-8") as f: + config = yaml.safe_load(f) + mode = config.get("translation", {}).get("mode", "advanced") + candidate_db = os.path.join(Config.ROOT_DIR, f"merged_books_{mode}.db") + ensure_db_exists(candidate_db) + if os.path.exists(candidate_db): + db_path = candidate_db + except Exception as e: + print(f"[WARNING] Error loading dynamic database path: {e}") + + if db_path == Config.DB_PATH: + ensure_db_exists(db_path) + + _cached_db_path = db_path + _cached_db_path_time = now + else: + db_path = _cached_db_path + + if not hasattr(thread_local, "connections"): + thread_local.connections = {} + + if db_path not in thread_local.connections: + # Final fallback check + if not os.path.exists(db_path): + ensure_db_exists(db_path) + + if not os.path.exists(db_path): + # Create empty database to prevent crash + logger.warning(f"Creating fallback empty database for {db_path}") + conn = sqlite3.connect(db_path, factory=ProfiledSqliteConnection) + try: + conn.execute("CREATE TABLE IF NOT EXISTS books (id INTEGER PRIMARY KEY, title TEXT, author TEXT, categories TEXT, chapters_max INTEGER);") + except Exception: + pass + else: + conn = sqlite3.connect(db_path, factory=ProfiledSqliteConnection) + + conn.row_factory = sqlite3.Row + conn.execute("PRAGMA synchronous=NORMAL;") + conn.execute("PRAGMA cache_size=-30000;") + conn.execute("PRAGMA temp_store=MEMORY;") + conn.execute("PRAGMA mmap_size=268435456;") + conn.execute("PRAGMA synchronous=OFF;") + try: + conn.execute("CREATE INDEX IF NOT EXISTS idx_categories ON books(categories);") + conn.execute("CREATE INDEX IF NOT EXISTS idx_chapters_max ON books(chapters_max);") + except Exception: + pass + thread_local.connections[db_path] = conn + + return thread_local.connections[db_path] + +def get_mode_connection(db_path): + if not hasattr(thread_local, "connections"): + thread_local.connections = {} + + if db_path not in thread_local.connections: + ensure_db_exists(db_path) + if os.path.exists(db_path): + conn = sqlite3.connect(db_path, factory=ProfiledSqliteConnection) + conn.row_factory = sqlite3.Row + conn.execute("PRAGMA synchronous=NORMAL;") + conn.execute("PRAGMA cache_size=-10000;") + conn.execute("PRAGMA temp_store=MEMORY;") + conn.execute("PRAGMA mmap_size=134217728;") + conn.execute("PRAGMA synchronous=OFF;") + thread_local.connections[db_path] = conn + else: + return None + + return thread_local.connections[db_path] diff --git a/backend/engine/__init__.py b/backend/engine/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..34e120ca09fcd7a66d158e4eae8d76cf9c078f11 --- /dev/null +++ b/backend/engine/__init__.py @@ -0,0 +1,2 @@ +from .engine import VietphraseEngine +from .trie import Trie diff --git a/backend/engine/engine.py b/backend/engine/engine.py new file mode 100644 index 0000000000000000000000000000000000000000..b6c61580c65c1c07fe38ec5e66829244f88be969 --- /dev/null +++ b/backend/engine/engine.py @@ -0,0 +1,820 @@ +import os +import sys +import re +import jieba.posseg as pseg + +from backend.config import Config + +NUM_RE = re.compile(r'^[0-9一二三四五六七八九十百千万几数多半两]+$') +PUNCT_SET = {',', '.', '!', '?', ';', ':', '"', '\'', '(', ')', '[', ']', '{', '}', + ',', '。', '!', '?', ';', ':', '“', '”', '‘', '’', '(', ')', '【', '】', '《', '》', '、', '—', '~'} + + +class SimpleToken: + def __init__(self, word, tag): + self.word = word + self.tag = tag + self.translated = None + + @property + def flag(self): + return self.tag + + @flag.setter + def flag(self, value): + self.tag = value + +class VietphraseEngine: + def __init__(self, config=None): + self.config = config or {} + self.load_dictionaries() + + # Check translation mode + self.translation_mode = self.config.get("translation", {}).get("mode", "advanced") + if self.config.get("translation", {}).get("fast_mode", False): + self.translation_mode = "fast" + + # Warm-up jieba + import jieba + try: + # Fix segmenter splitting overlapping words like 重生于 + jieba.add_word("重生", tag="v") + jieba.suggest_freq(("生", "于"), True) + jieba.suggest_freq(("着", "重"), True) + jieba.suggest_freq(("醉", "人"), True) + # Tag grades as nouns instead of proper names (nr) + jieba.add_word("高一", tag="n") + jieba.add_word("高二", tag="n") + jieba.add_word("高三", tag="n") + except Exception as e: + print("Error initializing custom word splits in Jieba:", e) + + # Always initialize both tokenizers to support dynamic mode switching + self.jieba_tokenizer = jieba.dt + self.pseg_dict = pseg.dt.word_tag_tab + list(self.jieba_tokenizer.cut("暖洋洋")) + list(pseg.cut("暖洋洋")) + + def load_dictionaries(self): + paths = self.config.get("paths", {}).get("dictionaries", {}) + vp_path = paths.get("vietphrase", "") + if not vp_path or not os.path.isabs(vp_path): + vp_path = os.path.join(Config.ROOT_DIR, vp_path or "dictionaries/Vietphrase.txt") + + dict_dir = os.path.dirname(vp_path) + + # Check for encrypted .bin dictionaries first, then fallback to .txt + def load_file_content(base_name): + bin_file = os.path.join(dict_dir, base_name + ".bin") + txt_file = os.path.join(dict_dir, base_name + ".txt") + + if os.path.exists(bin_file): + # Decrypt XOR + with open(bin_file, "rb") as f: + data = f.read() + key_bytes = "quick_translator_secret_key_2026".encode("utf-8") + key_len = len(key_bytes) + repeated_key = (key_bytes * (len(data) // key_len + 1))[:len(data)] + decrypted = bytes(a ^ b for a, b in zip(data, repeated_key)) + return decrypted.decode("utf-8") + elif os.path.exists(txt_file): + with open(txt_file, "r", encoding="utf-8") as f: + return f.read() + return "" + + print("Loading dictionaries in VietphraseEngine...") + self.char_dict = self.parse_dict_content(load_file_content("HanViet_CharDict")) + + # --- ADD HÁn Nôm FALLBACK --- + import csv + han_csv_path = os.path.join(dict_dir, "han_all_readings.csv") + if os.path.exists(han_csv_path): + try: + with open(han_csv_path, 'r', encoding='utf-8') as f: + reader = csv.DictReader(f) + for row in reader: + char = row.get("Ký_tự", "").strip() + hv = row.get("Hán_Việt", "").strip() + if char and hv and char not in self.char_dict: + self.char_dict[char] = hv.replace("~", "") + print("Loaded han_all_readings.csv as fallback for missing Chinese characters.") + except Exception as e: + print("Could not load han_all_readings.csv:", e) + + self.proper_names = self.parse_dict_content(load_file_content("Aligned_HanViet"), convert_to_simplified=True) + + vp_content = load_file_content("Vietphrase") + self.vietphrase = self.parse_vietphrase_content(vp_content) + print("Dictionaries loaded successfully.") + + # Build Tries for vietphrase and hanviet modes + from .trie import Trie + print("Building Tries for fast translation modes...") + self.vietphrase_trie = Trie() + # Insert proper names (priority 1) + for k, v in self.proper_names.items(): + self.vietphrase_trie.insert(k, v, 1) + # Insert Vietphrase (priority 2 - higher) + for k, v in self.vietphrase.items(): + self.vietphrase_trie.insert(k, v, 2) + + self.hanviet_trie = Trie() + # Insert proper names (priority 2) + for k, v in self.proper_names.items(): + self.hanviet_trie.insert(k, v, 2) + print("Tries built successfully.") + + # Register proper names in Jieba dictionary for fast modes + import jieba + for name in self.proper_names: + jieba.add_word(name) + + def parse_dict_content(self, content, convert_to_simplified=False): + dictionary = {} + if content: + to_simplified = lambda s: s + if convert_to_simplified: + try: + from hanziconv import HanziConv + to_simplified = HanziConv.toSimplified + except ImportError: + pass + + for line in content.splitlines(): + line = line.strip() + if not line or "=" not in line or line.startswith('#'): + continue + parts = line.split("=", 1) + key = parts[0].strip() + val = self.clean_annotation(parts[1].strip()) + dictionary[to_simplified(key)] = val + return dictionary + + def parse_vietphrase_content(self, content): + dictionary = {} + if content: + for line in content.splitlines(): + line = line.strip() + if not line or "=" not in line or line.startswith('#'): + continue + parts = line.split("=", 1) + left = parts[0].strip() + right = self.clean_annotation(parts[1].strip()) + + if "," in left and "," in right: + keys = [k.strip() for k in left.split(",") if k.strip()] + vals = [v.strip() for v in right.split(",") if v.strip()] + if len(keys) == len(vals): + for k, v in zip(keys, vals): + dictionary[k] = v + continue + if left: + dictionary[left] = right + return dictionary + + def is_number(self, word): + return bool(re.match(r'^[0-9一二三四五六七八九十百千万几数多半两]+$', word)) + + def capitalize_phrase(self, phrase): + chars = 'a-zA-ZàáạảãâầấậẩẫăằắặẳẵèéẹẻẽêềếệểễìíịỉĩòóọỏõôồốộổỗơờớợởỡùúụủũưừứựửữỳýỵỷỹđĐ' + pattern = f'[{chars}]+' + return re.sub(pattern, lambda m: m.group(0).capitalize(), phrase) + + def clean_annotation(self, text, mode='vietphrase'): + if not text: + return "" + # 1. Parse curly braces {meaning:reading} + def repl_curly(match): + content = match.group(1) + if ':' in content: + parts = content.split(':', 1) + return parts[0].strip() if mode == 'vietphrase' else parts[1].strip() + return content.strip() + + text = re.sub(r'\{([^{}]+)\}', repl_curly, text) + + # 2. Strip (*...) annotations + text = re.sub(r'\s*\(\*[^)]*\)', '', text) + + return text.strip() + + def format_translation(self, raw_value, multi_option, word=None, prefer_hanviet=False): + if not raw_value: + return "" + options = [o for o in raw_value.split("/") if o.strip()] + + # Deduplicate options while preserving order + seen = set() + deduped = [] + for o in options: + if o not in seen: + seen.add(o) + deduped.append(o) + + if not deduped: + return "" + + if multi_option and len(deduped) > 1: + return f"{deduped[0]}[{'/'.join(deduped[1:])}]" + + # If multi-option is False, we have a word of length >= 2, and prefer_hanviet is True, prefer Hán Việt alignment + if prefer_hanviet and word and len(word) >= 2 and len(deduped) > 1: + hv_sets = [] + for char in word: + readings = set() + if char in self.char_dict: + for r in self.char_dict[char].split('/'): + r_clean = r.strip().lower() + if r_clean: + readings.add(r_clean) + if readings: + hv_sets.append(readings) + + best_option = deduped[0] + best_score = -1 + + for opt in deduped: + opt_syllables = [w.strip().lower() for w in opt.split() if w.strip()] + score = 0 + for r_set in hv_sets: + if any(r in opt_syllables for r in r_set): + score += 1 + if score > best_score: + best_score = score + best_option = opt + if best_score > 0: + return best_option + + return deduped[0] + + def clean_punctuation_spacing(self, text): + if not text: + return text + + # 1. Ensure exactly one space after commas, semicolons, colons, periods, question marks, and exclamation marks. + # Avoid inserting space if the next character is a closing bracket, closing quote, space, or another punctuation. + text = re.sub(r'([,;.:!?])(?=[^\s)\]}』】”"’])', r'\1 ', text) + + # 2. Remove any accidental whitespace before these punctuation marks + text = re.sub(r'\s+([,;.:!?])', r'\1', text) + + # 3. Clean spaces inside parentheses, brackets, and curly/double brackets (including Chinese quote styles) + text = re.sub(r'([(\[{『【«])\s+', r'\1', text) + text = re.sub(r'\s+([)\]}』】»])', r'\1', text) + + # Ensure a space exists before opening brackets and after closing brackets when they border words/digits + text = re.sub(r'(?<=[^\s(\[{『【«])([(\[{『【«])', r' \1', text) + text = re.sub(r'([)\]}』】»])(?=[^\s.,;:!?)\]}』】»])', r'\1 ', text) + + # 4. Standardize dashes/hyphens used as separators (e.g. "Artist - Song") to have one space on each side + text = re.sub(r'\s*-\s*', ' - ', text) + + # 5. Clean up any duplicated/trailing whitespaces + text = re.sub(r'\s+', ' ', text).strip() + + return text + + def translate_sentence(self, sentence, multi_option=False, mode=None): + if not sentence or sentence.isspace(): + return "" + + # If the sentence doesn't contain any Chinese characters or symbols, preserve it as-is + if not re.search(r'[\u3400-\u9fff\U00020000-\U0002a6df\u3000-\u303f\uff00-\uffef]', sentence): + return sentence + + # Segment into Chinese text blocks and non-Chinese text blocks + # Keep Chinese characters and Chinese specific punctuations in the translation segment + chinese_pattern = re.compile(r'([\u4e00-\u9fff\u3000-\u303f\uff00-\uffef]+)') + parts = chinese_pattern.split(sentence) + + # Merge simple alphanumeric non-Chinese blocks into adjacent Chinese blocks + i = 1 + while i < len(parts) - 1: + non_chinese = parts[i+1] + if re.match(r'^\s*[a-zA-Z0-9]+\s*$', non_chinese): + parts[i] = parts[i] + non_chinese + parts[i+2] + parts.pop(i+1) + parts.pop(i+1) + else: + i += 2 + + translated_parts = [] + capitalize_next = True + + for part in parts: + if not part: + continue + if not re.search(r'[\u3400-\u9fff\U00020000-\U0002a6df\u3000-\u303f\uff00-\uffef]', part): + # Non-Chinese segment -> preserve exactly + translated_parts.append(part) + # Check if it ends with sentence terminator + if re.search(r'[.!?]\s*$', part): + capitalize_next = True + elif part.strip(): + capitalize_next = False + else: + # Chinese segment -> translate + trans = self._translate_pure_chinese_sentence(part, multi_option, mode, capitalize_first=capitalize_next) + translated_parts.append(trans) + # Check if it ends with sentence terminator + if re.search(r'[.!?]\s*$', part) or re.search(r'[.!?]\s*$', trans): + capitalize_next = True + else: + capitalize_next = False + + return "".join(translated_parts) + + def _translate_pure_chinese_sentence(self, sentence, multi_option=False, mode=None, capitalize_first=True): + if not sentence or sentence.isspace(): + return "" + + active_mode = mode or self.translation_mode + + # Tokenization & Tagging depending on mode + if active_mode in ("advanced", "advanced_hanviet"): + raw_tokens = [SimpleToken(t.word, t.flag) for t in pseg.cut(sentence)] + else: + # "fast", "vietphrase", "hanviet" modes use the fast tokenizer + words = list(self.jieba_tokenizer.cut(sentence)) + raw_tokens = [] + for w in words: + if w in PUNCT_SET: + tag = 'x' + elif NUM_RE.match(w): + tag = 'm' + else: + tag = self.pseg_dict.get(w, 'n') + raw_tokens.append(SimpleToken(w, tag)) + + if not raw_tokens: + return "" + + NUM_KEYWORDS = {"重", "阶", "品", "级", "层", "剑", "星", "转", "天", "色", "关", "重天"} + HANVIET_NUMBERS = { + '0': 'Không', '1': 'Nhất', '2': 'Nhị', '3': 'Tam', '4': 'Tứ', '5': 'Ngũ', '6': 'Lục', '7': 'Thất', '8': 'Bát', '9': 'Cửu', '10': 'Thập', + '一': 'Nhất', '二': 'Nhị', '三': 'Tam', '四': 'Tứ', '五': 'Ngũ', '六': 'Lục', '七': 'Thất', '八': 'Bát', '九': 'Cửu', '十': 'Thập', + '百': 'Bách', '千': 'Thiên', '万': 'Vạn', '萬': 'Vạn', '几': 'Vài', '数': 'Số', '多': 'Đa', '半': 'Bán', '两': 'Lưỡng', '兩': 'Lưỡng' + } + # Helper function to translate a single token + def translate_single_token(idx, tok, list_of_tokens): + word = tok.word + tag = tok.tag + + # Punctuation + is_punct = (tag == 'x' or word in {',', '.', '!', '?', ';', ':', '"', '(', ')', '[', ']', '{', '}'}) + if is_punct: + has_chinese = False + for char in word: + if char in self.char_dict: + has_chinese = True + break + if not has_chinese: + punct_map = { + ',': ',', '。': '.', '「': '"', '」': '"', '、': ',', '?': '?', '!': '!', + ':': ':', ';': ';', '“': '"', '”': '"', '(': '(', ')': ')' + } + tok.translated = punct_map.get(word, word) + return + + # Rule for number + 人 (e.g. 几十人, 三人) + if len(word) > 1 and word.endswith('人') and self.is_number(word[:-1]): + num_part = word[:-1] + if num_part in self.vietphrase: + num_trans = self.format_translation(self.vietphrase[num_part], multi_option, num_part) + else: + num_trans = " ".join([self.char_dict.get(c, c).split("/")[0] for c in num_part]) + tok.translated = f"{num_trans} người" + return + + # Special rule for 了 (le vs liao) + if word == 'l' or word == '了': + is_at_end = True + for next_tok in list_of_tokens[idx+1:]: + if next_tok.word in {'"', '\'', '(', ')', '[', ']', '{', '}', '“', '”', '‘', '’', '(', ')', '【', '】', '《', '》'}: + continue + if next_tok.word in {',', '.', '!', '?', ';', ':', ',', '。', '!', '?', ';', ':', '、'}: + is_at_end = True + break + is_at_end = False + break + if is_at_end: + tok.translated = "rồi" + else: + tok.translated = "được" + return + + # Cultivation Realm (cultivation) + if tag == 'cultivation': + result = [] + for char in word: + if char in HANVIET_NUMBERS: + result.append(HANVIET_NUMBERS[char]) + else: + cap_val = self.char_dict.get(char, char).split("/")[0].capitalize() + result.append(cap_val) + tok.translated = " ".join(result) + return + + # Determine if it's a noun or an adjective + is_proper = (tag in {'nr', 'ns', 'nt'} if tag else False) + is_noun = (tag.startswith('n') if tag else False) or tag in {'n', 'nz', 'ng'} if tag else False + is_adj = tag in {'a', 'b', 'ad', 'an', 'z'} if tag else False + is_noun_or_adj = is_proper or is_noun or is_adj + + # --- Chốt chặn cuối cùng cho Tên riêng (Proper Names Guard) --- + if is_proper: + if word in self.proper_names: + tok.translated = self.format_translation(self.proper_names[word], multi_option, word, prefer_hanviet=True) + else: + if not re.search(r'[\u3400-\u9fff\U00020000-\U0002a6df]', word): + tok.translated = word + else: + result = [] + for char in word: + val = self.char_dict.get(char, char).split("/")[0] + result.append(val) + tok.translated = " ".join(result) + if tok.translated: + tok.translated = self.capitalize_phrase(tok.translated) + + # --- Translate lookup strategy depending on active_mode (for non-proper names) --- + else: + if active_mode == 'hanviet': + # Mode 4: Pure Hán Việt (NO Vietphrase) + if word in self.proper_names: + tok.translated = self.format_translation(self.proper_names[word], multi_option, word, prefer_hanviet=True) + else: + if not re.search(r'[\u3400-\u9fff\U00020000-\U0002a6df]', word): + tok.translated = word + else: + result = [] + for char in word: + val = self.char_dict.get(char, char).split("/")[0] + result.append(val) + tok.translated = " ".join(result) + + elif active_mode == 'vietphrase': + # Mode 3: Prioritize Vietphrase (Traditional) + if word in self.vietphrase: + tok.translated = self.format_translation(self.vietphrase[word], multi_option, word, prefer_hanviet=False) + elif word in self.proper_names: + tok.translated = self.format_translation(self.proper_names[word], multi_option, word, prefer_hanviet=True) + else: + if not re.search(r'[\u3400-\u9fff\U00020000-\U0002a6df]', word): + tok.translated = word + else: + result = [] + for char in word: + val = self.char_dict.get(char, char).split("/")[0] + result.append(val) + tok.translated = " ".join(result) + + else: + # Modes 1, 2 & 5: 'fast', 'advanced', or 'advanced_hanviet' (POS-based noun/adjective Hán Việt override) + if is_noun_or_adj: + # Nouns/Adjectives: Bypasses vietphrase + if word in self.proper_names: + tok.translated = self.format_translation(self.proper_names[word], multi_option, word, prefer_hanviet=True) + else: + if not re.search(r'[\u3400-\u9fff\U00020000-\U0002a6df]', word): + tok.translated = word + else: + result = [] + for char in word: + val = self.char_dict.get(char, char).split("/")[0] + result.append(val) + tok.translated = " ".join(result) + else: + # Verbs and other parts of speech + if active_mode == 'advanced_hanviet': + # Prefer HanViet dictionary (proper_names) over Vietphrase + if word in self.proper_names: + tok.translated = self.format_translation(self.proper_names[word], multi_option, word, prefer_hanviet=True) + elif word in self.vietphrase: + tok.translated = self.format_translation(self.vietphrase[word], multi_option, word, prefer_hanviet=False) + else: + if not re.search(r'[\u3400-\u9fff\U00020000-\U0002a6df]', word): + tok.translated = word + else: + result = [] + for char in word: + val = self.char_dict.get(char, char).split("/")[0] + result.append(val) + tok.translated = " ".join(result) + else: + # Standard fast/advanced: vietphrase -> proper_names -> character fallback + if word in self.vietphrase: + tok.translated = self.format_translation(self.vietphrase[word], multi_option, word, prefer_hanviet=False) + elif word in self.proper_names: + tok.translated = self.format_translation(self.proper_names[word], multi_option, word, prefer_hanviet=True) + else: + if not re.search(r'[\u3400-\u9fff\U00020000-\U0002a6df]', word): + tok.translated = word + else: + result = [] + for char in word: + val = self.char_dict.get(char, char).split("/")[0] + result.append(val) + tok.translated = " ".join(result) + + # Strip trailing "đích" / "Đích" from modifier translations + if tok.translated and word.endswith('的') and len(word) > 1: + val = tok.translated + if val.lower().endswith(' đích'): + tok.translated = val[:-5] + elif val.lower().endswith('đích'): + tok.translated = val[:-4] + + # Step 1: Group numeral phrases and cultivation terms FIRST + grouped = [] + i = 0 + while i < len(raw_tokens): + tok = raw_tokens[i] + word = tok.word + tag = tok.tag + + if self.is_number(word) and i + 1 < len(raw_tokens) and raw_tokens[i+1].word in NUM_KEYWORDS: + grouped_word = word + raw_tokens[i+1].word + i_next = i + 2 + if i_next < len(raw_tokens) and raw_tokens[i_next].tag in {'n', 'nr', 'ns', 'nt', 'nz'}: + grouped_word += raw_tokens[i_next].word + i_next += 1 + grouped.append(SimpleToken(grouped_word, 'cultivation')) + i = i_next + else: + grouped.append(SimpleToken(word, tag)) + i += 1 + + # Step 2: Translate individual tokens on the cultivation-grouped tokens + for idx, tok in enumerate(grouped): + translate_single_token(idx, tok, grouped) + + # Step 3: Greedy merge adjacent tokens if their combination exists in dictionaries + i = 0 + merged = [] + while i < len(grouped): + matched = False + for length in range(min(4, len(grouped) - i), 1, -1): + combined_word = "".join([grouped[i+k].word for k in range(length)]) + + # Prevent merging across '的' particle to preserve root Hán Việt translation and allow reordering + should_skip = False + if 'đích' in combined_word or '的' in combined_word and combined_word.find('的') > 0: + should_skip = True + elif i + length < len(grouped) and grouped[i+length].word == '的': + # If next token is 'de' (de/的), don't merge if it would swallow a pronoun/noun/verb + last_tok = grouped[i+length-1] + if last_tok.flag in {'r', 'n', 'nr', 'ns', 'nt', 'nz', 'ng', 'v'}: + should_skip = True + elif '是' in combined_word and any(p in combined_word for p in {'我', '你', 'he', 'she', 'it', '们', '您', '自己'}): + # Prevent merging copula + pronoun phrases (like '这是他', '那是我') to allow proper clause reordering + should_skip = True + + # Dict check strategy depends on active_mode + if active_mode == 'hanviet': + in_dicts = (combined_word in self.proper_names) + else: + in_dicts = (combined_word in self.vietphrase or combined_word in self.proper_names) + + if not should_skip and in_dicts: + combined_tag = None + try: + cut_res = list(pseg.cut(combined_word)) + if cut_res: + combined_tag = cut_res[0].flag + except Exception: + pass + if not combined_tag: + combined_tag = grouped[i].flag + for k in range(length): + if grouped[i+k].flag in {'nr', 'ns', 'nt', 'nz'}: + combined_tag = grouped[i+k].flag + break + new_tok = SimpleToken(combined_word, combined_tag) + # Translate the new merged token immediately + translate_single_token(0, new_tok, [new_tok]) + merged.append(new_tok) + i += length + matched = True + break + if not matched: + merged.append(grouped[i]) + i += 1 + + # Step 4: Reordering Grammar Rules + if active_mode != 'hanviet': + # Pass 1: Adjective + Noun reordering + changed = True + while changed: + changed = False + i = 0 + while i < len(merged) - 1: + t_a = merged[i] + t_n = merged[i+1] + + # Do not swap with prepositions/conjunctions/copulas/particles + if t_n.word in {'跟', '和', '与', '與', '同', '在', '从', '從', '自', '由', '向', '往', '朝', '对', '對', '给', '給', '比', '是', '叫', '让', '讓', '被', '把', '使', '令', '到', '了', '的', '而', '&', '并', '並', '以', '或', '者'}: + i += 1 + continue + + if (t_a.tag in {'a', 'b'} or (t_a.word.endswith('的') and t_a.word != '的')) and t_n.tag in {'n', 'nr', 'ns', 'nt', 'nz', 'ng', 'v', 'vd', 'vg', 'vi', 'vn'}: + combined = t_n.translated + " " + t_a.translated + new_tok = SimpleToken(t_a.word + t_n.word, t_n.tag) + new_tok.translated = combined + merged[i:i+2] = [new_tok] + changed = True + break + i += 1 + + # Pass 2: "的" reordering (with multi-token noun/verb phrase lookahead) + NOUN_PHRASE_TAGS = {'n', 'nr', 'ns', 'nt', 'nz', 'ng', 'a', 'b', 'm', 'q', 'j', 'i'} + LOOKAHEAD_TAGS = NOUN_PHRASE_TAGS | {'v', 'vd', 'vg', 'vi', 'vn'} + i = 1 + while i < len(merged) - 1: + tok = merged[i] + if tok.word in {'de', '的'}: + t_x = merged[i-1] + # Scan forward to collect all consecutive noun or verb phrase tokens + k = i + 1 + has_noun = False + while k < len(merged): + tok_k = merged[k] + # Stop collecting if we hit a locality word/orientation noun + if tok_k.word in {'下', '上', '中', '里', '外', '内', '內', '后', '後', '前', '旁', '侧', '側', '底', '间', '間'}: + break + + # If we already encountered a noun/verb in the phrase, + # we cannot have a subsequent adjective modifying that noun from the right. + if has_noun and tok_k.tag in {'a', 'b'}: + break + + # Do not collect a verb tag if we already have a noun/verb head + is_verb_tag = tok_k.tag in {'v', 'vd', 'vg', 'vi', 'vn'} + if has_noun and is_verb_tag: + break + + if tok_k.tag in LOOKAHEAD_TAGS or tok_k.word == '色': + if tok_k.tag in {'n', 'nr', 'ns', 'nt', 'nz', 'ng', 'v', 'vd', 'vg', 'vi', 'vn'}: + has_noun = True + k += 1 + else: + break + + is_verb_modifier = t_x.tag in {'v', 'vd', 'vg', 'vi', 'vn'} + + # If we collected at least one token AND the modifier is not a verb clause + if k > i + 1 and not is_verb_modifier: + y_tokens = merged[i+1:k] + y_translated = " ".join([t.translated for t in y_tokens if t.translated]) + y_word = "".join([t.word for t in y_tokens]) + + if t_x.tag != 'x': + start_idx = i - 1 + j_back = i - 2 + while j_back >= 0: + tag_back = merged[j_back].tag + if tag_back in {'n', 'nr', 'ns', 'nt', 'nz', 'ng', 'a', 'b', 'm', 'q', 'j', 'i', 's', 't'}: + start_idx = j_back + j_back -= 1 + else: + break + + modifier_tokens = merged[start_idx:i] + modifier_translated = " ".join([t.translated for t in modifier_tokens if t.translated]) + modifier_word = "".join([t.word for t in modifier_tokens]) + + is_proper_or_pronoun = ( + t_x.tag in {'nr', 'r'} + ) + is_noun_modifier = is_proper_or_pronoun and not t_x.word.endswith('色') + if is_noun_modifier and start_idx == i - 1: + combined = y_translated + " của " + modifier_translated + else: + combined = y_translated + " " + modifier_translated + + new_tok = SimpleToken(modifier_word + tok.word + y_word, 'n') + new_tok.translated = combined + merged[start_idx:k] = [new_tok] + continue + else: + # If we didn't reorder, set the '的' translation to empty string to avoid translating as 'đấy' / 'đích' + tok.translated = "" + i += 1 + + # Join words + translated_text = " ".join([t.translated for t in merged if t.translated]) + + # Clean spacing and punctuation + translated_text = self.clean_punctuation_spacing(translated_text) + + # Capitalize sentences + sentences = re.split(r'([.!?]\s*)', translated_text) + start_idx = 0 if capitalize_first else 1 + for idx in range(start_idx, len(sentences)): + s = sentences[idx] + if s and not s.isspace() and not s[0] in {'.', '!', '?'}: + for c_idx, char in enumerate(s): + if char.isalpha(): + sentences[idx] = s[:c_idx] + char.upper() + s[c_idx+1:] + break + return "".join(sentences).strip() + + def translate_paragraph(self, paragraph, multi_option=False, mode=None): + if not paragraph or paragraph.isspace(): + return paragraph + + active_mode = mode or self.translation_mode + + if active_mode in ('vietphrase', 'hanviet'): + # Ultra-fast Trie-based translation path (50M+ characters/minute) + trie = self.vietphrase_trie if active_mode == 'vietphrase' else self.hanviet_trie + prefer_hanviet = (active_mode == 'hanviet') + + i = 0 + text_length = len(paragraph) + result_words = [] + + while i < text_length: + length, translation, priority = trie.search_longest_match(paragraph, i) + if length > 0: + word = paragraph[i:i+length] + formatted = self.format_translation(translation, multi_option, word, prefer_hanviet=prefer_hanviet) + # Capitalize if it is a proper name + if priority == 1 or word in self.proper_names: + formatted = self.capitalize_phrase(formatted) + result_words.append(formatted) + i += length + else: + char = paragraph[i] + if not re.search(r'[\u3400-\u9fff\U00020000-\U0002a6df]', char): + punct_map = { + ',': ',', '。': '.', '「': '"', '」': '"', '、': ',', '?': '?', '!': '!', + ':': ':', ';': ';', '“': '"', '”': '"', '(': '(', ')': ')', + '『': '"', '』': '"', '【': '[', '】': ']' + } + result_words.append(punct_map.get(char, char)) + else: + val = self.char_dict.get(char, char).split("/")[0] + result_words.append(val) + i += 1 + + translated_text = " ".join(result_words) + translated_text = self.clean_punctuation_spacing(translated_text) + + # Sentence Capitalization + sentences = re.split(r'([.!?]\s*)', translated_text) + for idx in range(len(sentences)): + s = sentences[idx] + if s and not s.isspace() and not s[0] in {'.', '!', '?'}: + for c_idx, char in enumerate(s): + if char.isalpha(): + sentences[idx] = s[:c_idx] + char.upper() + s[c_idx+1:] + break + return "".join(sentences).strip() + + # For advanced & fast modes, use normal sentence splitting & tokenization + sentence_ends = re.compile(r'([。!?!?]+)') + parts = sentence_ends.split(paragraph) + + translated_parts = [] + for part in parts: + if not part: + continue + if sentence_ends.match(part): + punct_map = { + '。': '.', '!': '!', '?': '?', ',': ',' + } + translated_parts.append(punct_map.get(part, part)) + else: + translated_parts.append(self.translate_sentence(part, multi_option, mode=mode)) + + return self.clean_punctuation_spacing("".join(translated_parts)) + + def translate_text_node(self, text, multi_option=False, mode=None): + """ + Dich mot text node tu DOM. + BAO TOAN HOAN TOAN cau truc: xuong dong \n, khoang trang dau/cuoi tung dong. + """ + if not text: + return text + + # Tach theo \n truoc -> dich tung dong doc lap -> gop lai + lines = text.split('\n') + translated_lines = [] + for line in lines: + leading = re.match(r'^\s*', line).group(0) + trailing = re.search(r'\s*$', line).group(0) + body = line.strip() + + if not body: + translated_lines.append(line) # dong rong -> giu nguyen + elif not re.search(r'[\u3400-\u9fff\U00020000-\U0002a6df]', body): + translated_lines.append(line) # khong co chu Han -> giu nguyen + else: + translated_body = self.translate_paragraph(body, multi_option, mode=mode) + translated_lines.append(leading + translated_body + trailing) + + return '\n'.join(translated_lines) + + def translate(self, text, multi_option=False, mode=None): + return self.translate_text_node(text, multi_option=multi_option, mode=mode) diff --git a/backend/engine/translate_api_server.py b/backend/engine/translate_api_server.py new file mode 100644 index 0000000000000000000000000000000000000000..d8fabdd5a1dcee74ceeb189180f5b3c0f8e1edf8 --- /dev/null +++ b/backend/engine/translate_api_server.py @@ -0,0 +1,85 @@ +import os +import sys +import json +import asyncio +from fastapi import FastAPI, HTTPException, Body +from fastapi.responses import StreamingResponse +from pydantic import BaseModel +from typing import List, Optional + +# Add parent directory to path to import engine +current_dir = os.path.dirname(os.path.abspath(__file__)) +sys.path.insert(0, os.path.dirname(os.path.dirname(current_dir))) + +from backend.engine.engine import VietphraseEngine +from backend.config import Config + +app = FastAPI( + title="Vietphrase Translation Standalone API Server", + description="Standalone API for fast Chinese to Vietnamese translation with 5 modes" +) + +# Initialize engine +print("Lazy-loading Vietphrase Engine on API Startup...") +engine = VietphraseEngine() +print("Vietphrase Engine successfully loaded!") + +class TranslateRequest(BaseModel): + texts: List[str] + mode: Optional[str] = "advanced" + +@app.get("/health") +def health(): + return { + "status": "ok", + "modes": ["advanced", "fast", "vietphrase", "hanviet", "advanced_hanviet"], + "dictionary_sizes": { + "char_dict": len(engine.char_dict), + "proper_names": len(engine.proper_names), + "vietphrase": len(engine.vietphrase) + } + } + +@app.post("/v1/translate") +def translate(req: TranslateRequest): + if not req.texts: + raise HTTPException(status_code=400, detail="Missing 'texts' list") + + translations = [] + for text in req.texts: + if not text.strip(): + translations.append(text) + else: + try: + translations.append(engine.translate(text, mode=req.mode)) + except Exception as e: + translations.append(text) + print(f"Error translating text: {e}") + + return {"translations": translations} + +@app.post("/v1/translate_stream") +async def translate_stream(req: TranslateRequest): + if not req.texts: + raise HTTPException(status_code=400, detail="Missing 'texts' list") + + async def event_generator(): + for i, text in enumerate(req.texts): + if not text.strip(): + trans = text + else: + try: + trans = engine.translate(text, mode=req.mode) + except Exception as e: + trans = text + print(f"Error streaming translation: {e}") + + yield f"data: {json.dumps({'index': i, 'text': trans}, ensure_ascii=False)}\n\n" + await asyncio.sleep(0.001) + + return StreamingResponse(event_generator(), media_type="text/event-stream") + +if __name__ == "__main__": + import uvicorn + port = int(os.environ.get("PORT", 8050)) + uvicorn.run("translate_api_server:app", host="0.0.0.0", port=port, reload=False) diff --git a/backend/engine/trie.py b/backend/engine/trie.py new file mode 100644 index 0000000000000000000000000000000000000000..989d884e1b4a5b8fa0ef2525e70359d6a7f9dc6b --- /dev/null +++ b/backend/engine/trie.py @@ -0,0 +1,56 @@ +class TrieNode: + def __init__(self): + self.children = {} + self.translation = None + self.priority = 0 # Priority level: 0=none, 1=Vietphrase, 2=Names + +class Trie: + def __init__(self): + self.root = TrieNode() + + def insert(self, phrase_zh, translation_vi, priority): + """ + Inserts a Chinese phrase and its translation into the Trie. + Overwrites existing translations if the new translation has higher or equal priority. + """ + if not phrase_zh: + return + + node = self.root + for char in phrase_zh: + if char not in node.children: + node.children[char] = TrieNode() + node = node.children[char] + + # Prioritize names (2) over general phrases (1) + if node.translation is None or priority >= node.priority: + node.translation = translation_vi + node.priority = priority + + def search_longest_match(self, text, start_index): + """ + Finds the longest matching Chinese phrase starting from start_index. + Returns a tuple of (matched_length, translation, priority). + If no match is found, returns (0, None, 0). + """ + node = self.root + longest_length = 0 + longest_translation = None + longest_priority = 0 + + current_index = start_index + text_length = len(text) + + while current_index < text_length: + char = text[current_index] + if char in node.children: + node = node.children[char] + current_index += 1 + if node.translation is not None: + longest_length = current_index - start_index + longest_translation = node.translation + longest_priority = node.priority + else: + break + + return longest_length, longest_translation, longest_priority diff --git a/backend/services/__init__.py b/backend/services/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..99997e0889d14dbbe32cde1e3517049712ae70ec --- /dev/null +++ b/backend/services/__init__.py @@ -0,0 +1 @@ +# backend/services/__init__.py diff --git a/backend/services/alert_service.py b/backend/services/alert_service.py new file mode 100644 index 0000000000000000000000000000000000000000..ad92f9c3454a9fb61398ad7629fe045da929df16 --- /dev/null +++ b/backend/services/alert_service.py @@ -0,0 +1,83 @@ +import os +import time +import logging +from backend.config import Config +from backend.services.email_service import send_email_async + +logger = logging.getLogger("backend.alert") + +# Rate limit: 30 minutes in seconds +THROTTLE_INTERVAL = 30 * 60 + +# In-memory store for tracking the last time an alert of a specific type was sent +# format: { alert_type: timestamp } +_last_sent_alerts = {} + +def send_alert_to_admin(alert_type: str, subject: str, message_html: str): + """ + Sends an email alert to the system administrator. + + Includes throttling to avoid spamming the admin email (maximum 1 alert per 30 minutes per type). + """ + admin_email = os.environ.get("ADMIN_EMAIL") or Config.SMTP_CONFIG.get("username") + if not admin_email: + logger.warning(f"⚠️ [Alerting] No ADMIN_EMAIL or SMTP username configured. Skipping alert: {subject}") + return False + + current_time = time.time() + last_sent = _last_sent_alerts.get(alert_type, 0) + + if current_time - last_sent < THROTTLE_INTERVAL: + logger.info(f"🔇 [Alerting] Alert '{alert_type}' throttled. Last sent at: {last_sent}. Skipping...") + return False + + # Update last sent timestamp + _last_sent_alerts[alert_type] = current_time + + # Send email asynchronously + logger.info(f"🚨 [Alerting] Sending alert email to Admin ({admin_email}): {subject}") + + # Append styling to alert email + styled_html = f""" +
+

Novel Translator Alert

+

Loại cảnh báo: {alert_type}

+
+ {message_html} +
+

+ Đây là email tự động gửi từ hệ thống giám sát trên VM. Cảnh báo này sẽ bị tạm khóa (throttled) trong 30 phút tiếp theo. +

+
+ """ + + send_email_async(admin_email, f"[SYSTEM ALERT] {subject}", styled_html) + return True + +def check_resources_and_alert(): + """ + Checks RAM and Disk metrics, and triggers alerts if they exceed thresholds (90%). + This should be called periodically or during health queries. + """ + from backend.core.monitoring import get_memory_info, get_disk_info + + try: + mem = get_memory_info() + if mem["percent"] >= 90.0: + subject = f"Cảnh báo: Bộ nhớ RAM cực kỳ thấp ({mem['percent']}%)" + body = f"Hệ thống đang chạy trên VM có lượng RAM khả dụng cực kỳ thấp.
" \ + f"Tổng RAM: {mem['total_bytes'] / (1024*1024*1024):.2f} GB
" \ + f"Đã dùng: {mem['used_bytes'] / (1024*1024*1024):.2f} GB ({mem['percent']}%)
" \ + f"Tiến trình python RSS: {mem['process_rss_bytes'] / (1024*1024):.2f} MB" + send_alert_to_admin("low_memory", subject, body) + + disk = get_disk_info() + if disk["percent"] >= 90.0: + subject = f"Cảnh báo: Dung lượng ổ đĩa sắp đầy ({disk['percent']}%)" + body = f"Ổ đĩa trên VM sắp hết bộ nhớ.
" \ + f"Tổng dung lượng: {disk['total_bytes'] / (1024*1024*1024):.2f} GB
" \ + f"Đã dùng: {disk['used_bytes'] / (1024*1024*1024):.2f} GB ({disk['percent']}%)
" \ + f"Dung lượng trống: {disk['free_bytes'] / (1024*1024*1024):.2f} GB" + send_alert_to_admin("low_disk", subject, body) + except Exception as e: + logger.error(f"Error checking system resources: {e}") diff --git a/backend/services/auth_service.py b/backend/services/auth_service.py new file mode 100644 index 0000000000000000000000000000000000000000..2fddf883d6282dcc06b154cc8d345e4e5b17dd43 --- /dev/null +++ b/backend/services/auth_service.py @@ -0,0 +1,80 @@ +import sqlite3 +from datetime import datetime, timedelta +from backend.config import Config +from backend.database.db_manager import get_user_db_conn + +def check_vip_expiry(user_id: int, conn=None) -> bool: + """Check if a user's VIP has expired and deactivate if so.""" + should_close = False + if conn is None: + conn = get_user_db_conn() + should_close = True + + try: + conn.row_factory = sqlite3.Row + except Exception: + pass + + user = conn.execute("SELECT vip_status, vip_expiry FROM users WHERE id = ?", (user_id,)).fetchone() + if user and user["vip_status"] == 1 and user["vip_expiry"]: + try: + expiry_val = user["vip_expiry"] + if isinstance(expiry_val, str): + expiry = datetime.strptime(expiry_val, "%Y-%m-%d %H:%M:%S") + else: + expiry = expiry_val + + if datetime.utcnow() > expiry: + conn.execute("UPDATE users SET vip_status = 0, vip_plan = NULL WHERE id = ?", (user_id,)) + if hasattr(conn, "commit"): + conn.commit() + if should_close: + conn.close() + return False # VIP expired + except Exception: + pass + if should_close: + conn.close() + return user["vip_status"] == 1 if user else False + +def activate_vip(user_id: int, plan: str) -> bool: + """Activate VIP for a user based on the plan purchased.""" + plan_info = Config.VIP_PLANS.get(plan) + if not plan_info: + # Check for lifetime manual plans + if "lifetime" in plan.lower(): + duration_days = 99999 + else: + return False + else: + duration_days = plan_info["duration_days"] + + conn = get_user_db_conn() + conn.row_factory = sqlite3.Row + user = conn.execute("SELECT vip_expiry FROM users WHERE id = ?", (user_id,)).fetchone() + + now = datetime.utcnow() + if user and user["vip_expiry"]: + try: + expiry_val = user["vip_expiry"] + if isinstance(expiry_val, str): + current_expiry = datetime.strptime(expiry_val, "%Y-%m-%d %H:%M:%S") + else: + current_expiry = expiry_val + + if current_expiry > now: + new_expiry = current_expiry + timedelta(days=duration_days) + else: + new_expiry = now + timedelta(days=duration_days) + except Exception: + new_expiry = now + timedelta(days=duration_days) + else: + new_expiry = now + timedelta(days=duration_days) + + conn.execute( + "UPDATE users SET vip_status = 1, vip_plan = ?, vip_expiry = ? WHERE id = ?", + (plan, new_expiry.strftime("%Y-%m-%d %H:%M:%S"), user_id) + ) + conn.commit() + conn.close() + return True diff --git a/backend/services/book_service.py b/backend/services/book_service.py new file mode 100644 index 0000000000000000000000000000000000000000..7146eeeaffc45d4cfd657bf11d34556b2dca1feb --- /dev/null +++ b/backend/services/book_service.py @@ -0,0 +1,398 @@ +import re +import math +import unicodedata +from flask import jsonify +from backend.database.db_manager import get_db, query_cache, count_cache + +CHINESE_CATEGORY_MAP = { + "言情穿越": "Ngôn tình Xuyên không", + "都市小说": "Đô thị", + "历史军事": "Lịch sử Quân sự", + "游戏竞技": "Võng du Cạnh tranh", + "游戏异界": "Dị giới Trò chơi", + "玄幻奇幻": "Huyền huyễn Kỳ huyễn", + "武侠仙侠": "Võ hiệp Tiên hiệp", + "科幻空间": "Khoa huyễn Không gian", + "悬疑灵异": "Huyền bí Linh dị", + "耽美纯爱": "Đam mỹ", + "同人小说": "Đồng nhân", + "都市": "Đô thị", + "言情": "Ngôn tình", + "穿越": "Xuyên không", + "历史": "Lịch sử", + "军事": "Quân sự", + "男生": "Nam sinh", + "女生": "Nữ sinh", + "游戏": "Trò chơi", + "竞技": "Cạnh tranh", + "玄幻": "Huyền huyễn", + "奇幻": "Kỳ huyễn", + "武侠": "Võ hiệp", + "仙侠": "Tiên hiệp", + "科幻": "Khoa huyễn", + "悬疑": "Huyền bí", + "灵异": "Linh dị", + "耽美": "Đam mỹ", + "轻小说": "Light Novel", + "同人": "Đồng nhân" +} + +def translate_categories(categories_str): + if not categories_str: + return "" + parts = re.split(r'[,,/、\s]+', categories_str) + vi_parts = [] + for p in parts: + p = p.strip() + if not p: + continue + matched = False + for zh, vi in CHINESE_CATEGORY_MAP.items(): + if zh in p: + vi_parts.append(vi) + matched = True + break + if not matched: + try: + from backend.services.translation import get_engine + translated = get_engine().translate(p, multi_option=False) + vi_parts.append(translated) + except Exception: + vi_parts.append(p) + seen = set() + unique_parts = [] + for vp in vi_parts: + if vp not in seen: + seen.add(vp) + unique_parts.append(vp) + return ", ".join(unique_parts) + +CHINESE_TO_ENGLISH_CATEGORY_MAP = { + "言情穿越": "Romance & Time Travel", + "都市小说": "Urban", + "历史军事": "History & Military", + "游戏竞技": "Gaming & Competition", + "游戏异界": "Gaming & Otherworld", + "玄幻奇幻": "Xianxia & Fantasy", + "武侠仙侠": "Wuxia & Xianxia", + "科幻 space": "Sci-Fi Space", + "科幻空间": "Sci-Fi & Space", + "悬疑灵异": "Mystery & Supernatural", + "耽美纯爱": "Danmei Romance", + "同人小说": "Fan-fiction", + "都市": "Urban", + "言情": "Romance", + "穿越": "Time Travel", + "历史": "History", + "军事": "Military", + "男生": "Male Protagonist", + "女生": "Female Protagonist", + "游戏": "Gaming", + "竞技": "Competition", + "玄幻": "Fantasy", + "奇幻": "Eastern Fantasy", + "武侠": "Wuxia", + "仙侠": "Xianxia", + "科幻": "Sci-Fi", + "悬疑": "Mystery", + "灵异": "Supernatural", + "耽美": "Danmei", + "轻小说": "Light Novel", + "同人": "Fan-fiction" +} + +def translate_categories_to_english(categories_str): + if not categories_str: + return "" + parts = re.split(r'[,,/、\s]+', categories_str) + en_parts = [] + for p in parts: + p = p.strip() + if not p: + continue + matched = False + for zh, en in CHINESE_TO_ENGLISH_CATEGORY_MAP.items(): + if zh in p: + en_parts.append(en) + matched = True + break + if not matched: + en_parts.append(p) + seen = set() + unique_parts = [] + for ep in en_parts: + if ep not in seen: + seen.add(ep) + unique_parts.append(ep) + return ", ".join(unique_parts) + +def remove_vietnamese_accents(text): + if not text: + return "" + # Normalize to decompose accents + nfkd_form = unicodedata.normalize('NFKD', text) + only_ascii = nfkd_form.encode('ASCII', 'ignore').decode('utf-8') + return only_ascii + +def clean_vietnamese_query(text): + text = text.replace('đ', 'd').replace('Đ', 'D') + return "".join(c for c in unicodedata.normalize('NFKD', text) if not unicodedata.combining(c)).lower() + +def parse_book_sources(book_dict): + parsed_sources = [] + raw_urls = book_dict.get("urls", "") + if raw_urls: + parts = raw_urls.split(" | ") + for part in parts: + if ":" in part: + subparts = part.split(":", 1) + src_name = subparts[0].strip() + src_url = subparts[1].strip() + if src_url.startswith("//"): + src_url = "https:" + src_url + parsed_sources.append({ + "source": src_name, + "url": src_url + }) + book_dict["parsed_sources"] = parsed_sources + + # Dịch thể loại sang tiếng Việt và tiếng Anh + book_dict["categories_vietphrase"] = translate_categories(book_dict.get("categories", "")) + book_dict["categories_english"] = translate_categories_to_english(book_dict.get("categories", "")) + + # Sinh tên tác giả tiếng Anh (Hán Việt không dấu) + author_hv = book_dict.get("author_hanviet", "") + if author_hv: + book_dict["author_english"] = remove_vietnamese_accents(author_hv) + else: + book_dict["author_english"] = book_dict.get("author", "") + + # Use pre-computed description from DB (do NOT translate on-the-fly for listings — too expensive) + desc = book_dict.get("description", "") + desc_vp = book_dict.get("description_vietphrase", "") + if not desc_vp and desc: + # Lightweight fallback: just truncate Chinese description, no translation engine call + desc_vp = desc[:120] + book_dict["description_vietphrase"] = desc_vp or "" + + # Tạo fallback description_english bằng cách bỏ dấu bản Việt hóa + if desc_vp: + book_dict["description_english"] = remove_vietnamese_accents(desc_vp) + else: + book_dict["description_english"] = desc[:120] if desc else "" + + return book_dict + +def search_books(q, category, source, dup, sort, search_field, min_chapters, page, per_page, limit_k=100): + """Business logic for searching books with high-performance FTS5 or LIKE queries.""" + MAX_PAGES_CEILING = 100 + if page > MAX_PAGES_CEILING: + return {"error": "Deep pagination limit reached. Giới hạn tối đa 100 trang kết quả."}, 400 + + # Whitelist sort options + allowed_sorts = { + "site_count DESC", "chapters_max DESC", "word_count_max DESC", "title ASC", "title DESC", "id ASC" + } + if sort not in allowed_sorts: + sort = "site_count DESC" + + where, params = [], [] + fts_match_expr = None + has_chinese = False + + if q: + has_chinese = any('\u4e00' <= char <= '\u9fff' for char in q) + if has_chinese: + # Use FTS5 for Chinese queries — 10x faster than LIKE scan on 931k rows + fts_q = q.replace('"', '').replace("'", '') + if search_field == "title": + fts_match_expr = f'title:"{fts_q}"' + elif search_field == "author": + fts_match_expr = f'author:"{fts_q}"' + elif search_field == "description": + # Description is NOT in FTS index — fallback to LIKE but only on description + pq = "%" + q + "%" + where.append("description LIKE ?") + params.append(pq) + else: + # Default: search title + author via FTS5 (fast) + fts_match_expr = f'title:"{fts_q}" OR author:"{fts_q}"' + else: + q_clean = clean_vietnamese_query(q) + fts_query = q_clean.replace('"', '').replace("'", '') + if fts_query: + if search_field == "title": + fts_match_expr = f'title_hanviet_clean:"{fts_query}" OR title_vietphrase_clean:"{fts_query}"' + elif search_field == "author": + fts_match_expr = f'author_hanviet_clean:"{fts_query}"' + elif search_field == "hanviet": + fts_match_expr = f'title_hanviet_clean:"{fts_query}" OR author_hanviet_clean:"{fts_query}"' + elif search_field == "vietphrase": + fts_match_expr = f'title_vietphrase_clean:"{fts_query}"' + elif search_field == "chinese": + fts_match_expr = f'title:"{q}" OR author:"{q}"' + elif search_field == "description": + where.append("(description LIKE ? OR description_vietphrase LIKE ? OR description_hanviet LIKE ?)") + pq = "%" + q + "%" + params += [pq, pq, pq] + else: + fts_match_expr = f'title_hanviet_clean:"{fts_query}" OR title_vietphrase_clean:"{fts_query}" OR author_hanviet_clean:"{fts_query}"' + + if category: + where.append("categories LIKE ?") + params.append("%" + category + "%") + if source: + where.append("sources LIKE ?") + params.append("%" + source + "%") + if dup == "multi": + where.append("site_count >= 2") + elif dup == "single": + where.append("site_count = 1") + if min_chapters: + try: + min_ch_val = int(min_chapters) + where.append("chapters_max >= ?") + params.append(min_ch_val) + except ValueError: + pass + + where_sql = ("WHERE " + " AND ".join(where)) if where else "" + + if fts_match_expr: + cache_key = ("fts_search_v2", fts_match_expr, where_sql, page, per_page, tuple(params), sort, q, limit_k) + cached_res = query_cache.get(cache_key) + if cached_res is not None: + return cached_res, 200 + + conn = get_db() + query = f""" + SELECT b.*, f.score + FROM books b + JOIN ( + SELECT rowid, bm25(books_fts) AS score + FROM books_fts + WHERE books_fts MATCH ? + ) f ON b.id = f.rowid + {where_sql} + LIMIT {limit_k} + """ + rows = conn.execute(query, [fts_match_expr] + params).fetchall() + + if not rows: + res_data = {"total": 0, "page": 1, "pages": 1, "books": []} + query_cache.set(cache_key, res_data) + return res_data, 200 + + scores = [r['score'] for r in rows] + best_score = min(scores) + threshold = best_score * 0.28 + + has_accents = any(c != clean_vietnamese_query(c) for c in q) + + def clean_text_for_tier(txt): + if not txt: + return "" + txt = txt.replace('đ', 'd').replace('Đ', 'D') + txt = "".join(c for c in unicodedata.normalize('NFKD', txt) if not unicodedata.combining(c)).lower() + return " ".join(re.sub(r'[^a-z0-9\s]', ' ', txt).split()) + + q_clean_tier = clean_text_for_tier(q) + q_norm = q.lower().strip() + + def get_tier(book): + t_hv_clean = clean_text_for_tier(book.get('title_hanviet', '')) + t_vp_clean = clean_text_for_tier(book.get('title_vietphrase', '')) + if t_hv_clean == q_clean_tier or t_vp_clean == q_clean_tier: + return 1 + if t_hv_clean.startswith(q_clean_tier) or t_vp_clean.startswith(q_clean_tier): + return 2 + if q_clean_tier in t_hv_clean or q_clean_tier in t_vp_clean: + return 3 + return 4 + + filtered_books = [] + for r in rows: + book_dict = dict(r) + tier = get_tier(book_dict) + score = book_dict['score'] + + if has_accents: + t_hv = (book_dict.get('title_hanviet') or '').lower() + t_vp = (book_dict.get('title_vietphrase') or '').lower() + auth = (book_dict.get('author_hanviet') or '').lower() + desc = (book_dict.get('description') or '').lower() + if q_norm not in t_hv and q_norm not in t_vp and q_norm not in auth and q_norm not in desc: + continue + + if tier in (3, 4) and score > threshold: + continue + + book_dict['tier'] = tier + filtered_books.append(book_dict) + + if sort == "title ASC": + filtered_books.sort(key=lambda x: (x.get('title_hanviet') or '').lower()) + elif sort == "title DESC": + filtered_books.sort(key=lambda x: (x.get('title_hanviet') or '').lower(), reverse=True) + elif sort == "chapters_max DESC": + filtered_books.sort(key=lambda x: x.get('chapters_max') or 0, reverse=True) + elif sort == "word_count_max DESC": + filtered_books.sort(key=lambda x: x.get('word_count_max') or 0, reverse=True) + else: + filtered_books.sort(key=lambda x: (x['tier'], x['score'], -x['site_count'])) + + total = len(filtered_books) + pages = max(1, math.ceil(total / per_page)) + offset = (page - 1) * per_page + books_page = [parse_book_sources(b) for b in filtered_books[offset : offset + per_page]] + + res_data = {"total": total, "page": page, "pages": pages, "books": books_page} + query_cache.set(cache_key, res_data) + return res_data, 200 + + else: + order_by_sql = sort + order_params = [] + if q and has_chinese: + order_by_sql = f""" + CASE + WHEN title = ? THEN 1 + WHEN title LIKE ? THEN 2 + ELSE 3 + END ASC, {sort} + """ + order_params = [q, q + "%"] + + cache_key = (where_sql, order_by_sql, page, per_page, tuple(params), tuple(order_params)) + cached_res = query_cache.get(cache_key) + if cached_res is not None: + return cached_res, 200 + + count_cache_key = (where_sql, tuple(params)) + total = count_cache.get(count_cache_key) + if total is None: + conn = get_db() + total = conn.execute( + "SELECT COUNT(*) FROM books " + where_sql, params + ).fetchone()[0] + count_cache.set(count_cache_key, total) + + pages = max(1, math.ceil(total / per_page)) + if pages > MAX_PAGES_CEILING: + pages = MAX_PAGES_CEILING + total = min(total, MAX_PAGES_CEILING * per_page) + + offset = (page - 1) * per_page + + conn = get_db() + rows = conn.execute( + "SELECT * FROM books " + where_sql + + " ORDER BY " + order_by_sql + + " LIMIT ? OFFSET ?", + params + order_params + [per_page, offset] + ).fetchall() + + books = [parse_book_sources(dict(r)) for r in rows] + res_data = {"total": total, "page": page, "pages": pages, "books": books} + query_cache.set(cache_key, res_data) + return res_data, 200 diff --git a/backend/services/email_service.py b/backend/services/email_service.py new file mode 100644 index 0000000000000000000000000000000000000000..62faa9c72ed4c8ebc21513dcf1277eaa8513944a --- /dev/null +++ b/backend/services/email_service.py @@ -0,0 +1,172 @@ +import os +import base64 +import smtplib +import threading +from email.mime.text import MIMEText +from email.mime.multipart import MIMEMultipart +from backend.config import Config + +# Service Account delegation config +SERVICE_ACCOUNT_FILE = os.environ.get("GOOGLE_SERVICE_ACCOUNT_JSON", "gmail-delegator-key.json") +DELEGATED_USER_EMAIL = os.environ.get("GMAIL_DELEGATED_EMAIL", "support@lyvuha.com") + +SCOPES = [ + "https://www.googleapis.com/auth/gmail.send", + "https://www.googleapis.com/auth/gmail.readonly", + "https://www.googleapis.com/auth/gmail.modify" +] + +def get_gmail_service(): + """Builds and returns a Gmail API service client impersonating the DELEGATED_USER_EMAIL.""" + import json + from google.oauth2 import service_account + from googleapiclient.discovery import build + + service_account_json = os.environ.get("GOOGLE_SERVICE_ACCOUNT_JSON", "") + creds = None + + try: + # Nếu cấu hình trực tiếp chuỗi JSON key trong biến môi trường + if service_account_json and service_account_json.strip().startswith("{"): + info = json.loads(service_account_json) + creds = service_account.Credentials.from_service_account_info( + info, + scopes=SCOPES + ) + # Nếu cấu hình bằng đường dẫn file + elif os.path.exists(SERVICE_ACCOUNT_FILE): + creds = service_account.Credentials.from_service_account_file( + SERVICE_ACCOUNT_FILE, + scopes=SCOPES + ) + + if not creds: + return None + + delegated_creds = creds.with_subject(DELEGATED_USER_EMAIL) + service = build('gmail', 'v1', credentials=delegated_creds) + return service + except Exception as e: + print(f"❌ Error initializing Gmail API Service: {e}") + return None + + +def send_email_smtp(to_email, subject, html_content): + """Sends an email using standard SMTP with App Password.""" + smtp_cfg = Config.SMTP_CONFIG + if not smtp_cfg["username"] or not smtp_cfg["password"]: + print("⚠️ SMTP credentials not configured in Config.") + return False + try: + msg = MIMEMultipart("alternative") + msg["Subject"] = subject + msg["From"] = f"{smtp_cfg['from_name']} <{smtp_cfg['username']}>" + msg["To"] = to_email + msg.attach(MIMEText(html_content, "html", "utf-8")) + + server = smtplib.SMTP(smtp_cfg["host"], smtp_cfg["port"]) + server.starttls() + server.login(smtp_cfg["username"], smtp_cfg["password"]) + server.sendmail(smtp_cfg["username"], to_email, msg.as_string()) + server.quit() + print(f"📧 [SMTP] Successfully sent email to {to_email}") + return True + except Exception as e: + print(f"❌ [SMTP] Failed to send email: {e}") + return False + +def send_email_gmail_api(to_email, subject, html_content): + """Sends an email using Gmail API via Service Account impersonation.""" + service = get_gmail_service() + if not service: + return send_email_smtp(to_email, subject, html_content) + try: + message = MIMEText(html_content, 'html', 'utf-8') + message['to'] = to_email + message['from'] = DELEGATED_USER_EMAIL + message['subject'] = subject + + raw_message = base64.urlsafe_b64encode(message.as_bytes()).decode('utf-8') + body = {'raw': raw_message} + + service.users().messages().send(userId='me', body=body).execute() + print(f"📧 [Gmail API] Successfully sent email to {to_email} from {DELEGATED_USER_EMAIL}") + return True + except Exception as e: + print(f"❌ [Gmail API] Failed to send email, falling back to SMTP: {e}") + return send_email_smtp(to_email, subject, html_content) + + +def send_email_gmail_oauth2(to_email, subject, html_content): + """Sends an email using Gmail REST API via OAuth2 Client ID/Secret and Refresh Token (over HTTPS 443).""" + client_id = os.environ.get("GOOGLE_CLIENT_ID", "") + client_secret = os.environ.get("GOOGLE_CLIENT_SECRET", "") + refresh_token = os.environ.get("GMAIL_REFRESH_TOKEN", "") + sender_email = os.environ.get("SMTP_EMAIL", "havucong@lyvuha.com") + + + if not refresh_token: + print("⚠️ GMAIL_REFRESH_TOKEN not configured.") + return False + + try: + import base64 + import requests + + # 1. Get Access Token from Refresh Token + token_url = "https://oauth2.googleapis.com/token" + token_data = { + "client_id": client_id, + "client_secret": client_secret, + "refresh_token": refresh_token, + "grant_type": "refresh_token" + } + token_res = requests.post(token_url, data=token_data, timeout=5) + if token_res.status_code != 200: + print(f"❌ Failed to refresh Gmail access token: {token_res.text}") + return False + + access_token = token_res.json().get("access_token") + + # 2. Build MIME message + message = MIMEText(html_content, 'html', 'utf-8') + message['to'] = to_email + message['from'] = sender_email + message['subject'] = subject + + raw_message = base64.urlsafe_b64encode(message.as_bytes()).decode('utf-8') + + # 3. Send email via Gmail API + send_url = "https://gmail.googleapis.com/gmail/v1/users/me/messages/send" + headers = { + "Authorization": f"Bearer {access_token}", + "Content-Type": "application/json" + } + send_res = requests.post(send_url, headers=headers, json={"raw": raw_message}, timeout=5) + if send_res.status_code == 200: + print(f"📧 [Gmail OAuth2 API] Successfully sent email to {to_email}") + return True + else: + print(f"❌ [Gmail OAuth2 API] Failed to send email: {send_res.text}") + return False + except Exception as e: + print(f"❌ [Gmail OAuth2 API] Exception occurred: {e}") + return False + + +def send_email_async(to_email, subject, html_content): + """Helper to send emails asynchronously in a background thread.""" + refresh_token = os.environ.get("GMAIL_REFRESH_TOKEN", "") + service_account_json = os.environ.get("GOOGLE_SERVICE_ACCOUNT_JSON", "") + + if refresh_token: + # Ưu tiên sử dụng OAuth2 Refresh Token (HTTPS port 443) + threading.Thread(target=send_email_gmail_oauth2, args=(to_email, subject, html_content)).start() + elif service_account_json or os.path.exists(SERVICE_ACCOUNT_FILE): + # Sử dụng Google Service Account (HTTPS port 443) + threading.Thread(target=send_email_gmail_api, args=(to_email, subject, html_content)).start() + else: + # Fallback về SMTP + threading.Thread(target=send_email_smtp, args=(to_email, subject, html_content)).start() + + diff --git a/backend/services/epub_service.py b/backend/services/epub_service.py new file mode 100644 index 0000000000000000000000000000000000000000..8501e39b37c4271df4c1d733545fecec5c5f7617 --- /dev/null +++ b/backend/services/epub_service.py @@ -0,0 +1,343 @@ +import os +import re +import zipfile +import uuid +import html +import tempfile +import time + +class EpubWriter: + def __init__(self, title, author="Unknown", cover_img_bytes=None, cover_ext="jpg", description=""): + self.title = title + self.author = author + self.description = description + self.chapters = [] # List of tuples (title, content) + self.cover_img_bytes = cover_img_bytes + self.cover_ext = cover_ext + + def add_chapter(self, title, content_html): + self.chapters.append((title, content_html)) + + def write_to(self, dest_path): + with zipfile.ZipFile(dest_path, 'w', compression=zipfile.ZIP_DEFLATED) as epub: + # 1. mimetype (must be uncompressed and first entry) + epub.writestr('mimetype', 'application/epub+zip', compress_type=zipfile.ZIP_STORED) + + # 2. META-INF/container.xml + container_xml = """ + + + + +""" + epub.writestr('META-INF/container.xml', container_xml) + + # Generate NCX + ncx_entries = [] + for i, (ch_title, _) in enumerate(self.chapters): + ncx_entries.append(f""" + {html.escape(ch_title)} + + """) + + ncx_joined = "\n".join(ncx_entries) + toc_ncx = f""" + + + + + + + + {html.escape(self.title)} + {html.escape(self.author)} + + + Trang Tên Sách + + +{ncx_joined} + +""" + epub.writestr('OEBPS/toc.ncx', toc_ncx) + + # Generate manifest items + manifest_items = [ + '', + '', + ] + spine_items = [ + '', + ] + + if self.cover_img_bytes: + manifest_items.append(f'') + manifest_items.append('') + spine_items.insert(0, '') + + for i in range(len(self.chapters)): + manifest_items.append(f'') + spine_items.append(f'') + + # Generate content.opf + manifest_joined = "\n ".join(manifest_items) + spine_joined = "\n ".join(spine_items) + desc_meta = f'' if self.description else '' + cover_meta = '' if self.cover_img_bytes else '' + + content_opf = f""" + + + {html.escape(self.title)} + {html.escape(self.author)} + vi + urn:uuid:{uuid.uuid4()} + {desc_meta} + {cover_meta} + + + {manifest_joined} + + + {spine_joined} + +""" + epub.writestr('OEBPS/content.opf', content_opf) + + # Write cover files + if self.cover_img_bytes: + epub.writestr(f'OEBPS/images/cover.{self.cover_ext}', self.cover_img_bytes) + coverpage_xhtml = f""" + + + + Bìa Sách + + + +
+ Bìa sách +
+ +""" + epub.writestr('OEBPS/text/coverpage.xhtml', coverpage_xhtml) + + # Title page + titlepage_xhtml = f""" + + + + {html.escape(self.title)} + + + +

{html.escape(self.title)}

+

Tác giả: {html.escape(self.author)}

+
+ {f'
Giới thiệu:
{html.escape(self.description)}
' if self.description else ''} +

Được biên dịch & đóng gói tự động bằng VIP EPUB Tools

+ +""" + epub.writestr('OEBPS/text/titlepage.xhtml', titlepage_xhtml) + + # Write chapters XHTML + for i, (ch_title, ch_content) in enumerate(self.chapters): + if "" in ch_content.lower() or "

" in ch_content.lower(): + ch_xhtml = ch_content + else: + paragraphs = ch_content.split('\n') + body_html = "" + for p in paragraphs: + p_clean = p.strip() + if p_clean: + body_html += f"

{html.escape(p_clean)}

\n" + + ch_xhtml = f""" + + + + {html.escape(ch_title)} + + + +

{html.escape(ch_title)}

+ {body_html} + +""" + epub.writestr(f'OEBPS/text/chapter_{i+1}.xhtml', ch_xhtml) + +def apply_custom_dictionary(text, custom_dict): + """Replaces Chinese words with user-provided custom dictionary mappings.""" + if not custom_dict or not text: + return text + for zh, vi in custom_dict: + if zh and zh in text: + text = text.replace(zh, vi) + return text + +def clean_html_styles(html_content): + """Strips inline CSS styles, custom font faces, and stylesheets.""" + cleaned = re.sub(r'\s+style="[^"]*"', '', html_content) + cleaned = re.sub(r"\s+style='[^']*'", '', cleaned) + cleaned = re.sub(r'\s+class="[^"]*"', '', cleaned) + cleaned = re.sub(r"\s+class='[^']*'", '', cleaned) + cleaned = re.sub(r']*>.*?', '', cleaned, flags=re.DOTALL | re.IGNORECASE) + cleaned = re.sub(r']*rel="stylesheet"[^>]*>', '', cleaned, flags=re.IGNORECASE) + cleaned = re.sub(r']*rel=\'stylesheet\'[^>]*>', '', cleaned, flags=re.IGNORECASE) + return cleaned + +def clean_punctuation_spacing(text): + if not text: + return text + text = re.sub(r'["“”‘’\'『』「」【】()\[\]{}<>]', '', text) + text = re.sub(r'([,;.:!?])(?=[^\s])', r'\1 ', text) + text = re.sub(r'\s+([,;.:!?])', r'\1', text) + text = re.sub(r'\s*-\s*', ' - ', text) + return re.sub(r'\s+', ' ', text).strip() + +def translate_html_content_advanced(html_content, engine, mode=None, custom_dict=None, clean_styles=False): + """Parses HTML, extracts text segments, translates them, and preserves HTML tags.""" + if clean_styles: + html_content = clean_html_styles(html_content) + + parts = re.split(r'(<[^>]+>)', html_content) + translated_parts = [] + + for part in parts: + if not part: + continue + if part.startswith('<') and part.endswith('>'): + translated_parts.append(part) + else: + stripped = part.strip() + if stripped: + txt = apply_custom_dictionary(part, custom_dict) + translated_text = engine.translate(txt, multi_option=False, mode=mode) + translated_text = clean_punctuation_spacing(translated_text) + translated_parts.append(translated_text) + else: + translated_parts.append(part) + + return "".join(translated_parts) + +def translate_epub_file(src_epub, dest_epub, engine, mode=None, limit_chapters=-1, custom_dict=None, clean_styles=False, strip_images=False, strip_fonts=False): + """Translates an EPUB file and saves to dest_epub.""" + start_time = time.time() + + with zipfile.ZipFile(src_epub, 'r') as src_zip: + with zipfile.ZipFile(dest_epub, 'w', compression=zipfile.ZIP_DEFLATED) as dest_zip: + file_list = src_zip.namelist() + + if 'mimetype' in file_list: + mimetype_data = src_zip.read('mimetype') + dest_zip.writestr('mimetype', mimetype_data, compress_type=zipfile.ZIP_STORED) + + html_files = [f for f in file_list if f.endswith(('.html', '.xhtml', '.htm'))] + + def natural_sort_key(s): + return [int(text) if text.isdigit() else text.lower() for text in re.split(r'(\d+)', s)] + html_files.sort(key=natural_sort_key) + + target_html_files = set(html_files) + skipped_html_files = set() + if limit_chapters > 0 and len(html_files) > limit_chapters: + target_html_files = set(html_files[:limit_chapters]) + skipped_html_files = set(html_files[limit_chapters:]) + + for file_name in file_list: + if file_name == 'mimetype': + continue + + if strip_images and file_name.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg')): + continue + + if strip_fonts and file_name.lower().endswith(('.ttf', '.otf', '.woff', '.woff2')): + continue + + raw_data = src_zip.read(file_name) + + if file_name in target_html_files: + try: + content = raw_data.decode('utf-8', errors='ignore') + translated_content = translate_html_content_advanced( + content, engine, mode=mode, custom_dict=custom_dict, clean_styles=clean_styles + ) + dest_zip.writestr(file_name, translated_content.encode('utf-8')) + except Exception as e: + print(f"[EpubTool ERROR] Error translating {file_name}: {e}") + dest_zip.writestr(file_name, raw_data) + elif file_name in skipped_html_files: + placeholder = '

[Chương này được bỏ qua trong bản dịch giới hạn]

' + dest_zip.writestr(file_name, placeholder.encode('utf-8')) + elif file_name.endswith(('.ncx', '.opf', '.xml')): + try: + content = raw_data.decode('utf-8', errors='ignore') + translated_content = translate_html_content_advanced( + content, engine, mode=mode, custom_dict=custom_dict, clean_styles=False + ) + dest_zip.writestr(file_name, translated_content.encode('utf-8')) + except Exception: + dest_zip.writestr(file_name, raw_data) + else: + dest_zip.writestr(file_name, raw_data) + + return time.time() - start_time + +def convert_txt_to_epub(txt_content, title, author, split_regex, dest_path, description="", engine=None, mode=None, custom_dict=None): + """Converts raw text file content to EPUB, optionally translating it first.""" + lines = txt_content.split('\n') + chapters = [] + current_chapter_title = "Giới thiệu / Khởi đầu" + current_chapter_lines = [] + + regex = re.compile(split_regex) if split_regex else None + + for line in lines: + stripped = line.strip() + if not stripped: + continue + + if regex and regex.search(stripped) and len(stripped) < 100: + if current_chapter_lines: + chapters.append((current_chapter_title, "\n".join(current_chapter_lines))) + current_chapter_title = stripped + current_chapter_lines = [] + else: + current_chapter_lines.append(line) + + if current_chapter_lines or not chapters: + chapters.append((current_chapter_title, "\n".join(current_chapter_lines))) + + writer = EpubWriter(title=title, author=author, description=description) + + for ch_title, ch_text in chapters: + if engine and mode: + ch_title_vi = apply_custom_dictionary(ch_title, custom_dict) + ch_title_vi = engine.translate(ch_title_vi, multi_option=False, mode=mode) + + paragraphs = ch_text.split('\n') + paragraphs_vi = [] + for p in paragraphs: + p_clean = p.strip() + if p_clean: + p_vi = apply_custom_dictionary(p_clean, custom_dict) + p_vi = engine.translate(p_vi, multi_option=False, mode=mode) + paragraphs_vi.append(p_vi) + ch_content_html = "\n".join(paragraphs_vi) + writer.add_chapter(ch_title_vi, ch_content_html) + else: + writer.add_chapter(ch_title, ch_text) + + writer.write_to(dest_path) diff --git a/backend/services/payment_service.py b/backend/services/payment_service.py new file mode 100644 index 0000000000000000000000000000000000000000..442afca121a0e83237afff506227aea46bb36537 --- /dev/null +++ b/backend/services/payment_service.py @@ -0,0 +1,195 @@ +import time +import json +import hmac +import hashlib +import requests +import sqlite3 +from datetime import datetime +from backend.config import Config +from backend.database.db_manager import get_user_db_conn +from backend.services.auth_service import activate_vip + +def verify_payos_webhook_signature(payload_data, expected_signature, checksum_key): + """Verify PayOS webhook signature using alphabet-sorted query string.""" + sorted_keys = sorted(payload_data.keys()) + parts = [] + for k in sorted_keys: + v = payload_data[k] + if v is None or v == "null" or v == "undefined": + v_str = "" + elif isinstance(v, list): + sorted_list = [] + for item in v: + if isinstance(item, dict): + sorted_item = {sub_k: item[sub_k] for sub_k in sorted(item.keys())} + sorted_list.append(sorted_item) + else: + sorted_list.append(item) + v_str = json.dumps(sorted_list, separators=(',', ':'), ensure_ascii=False) + elif isinstance(v, dict): + sorted_dict = {sub_k: v[sub_k] for sub_k in sorted(v.keys())} + v_str = json.dumps(sorted_dict, separators=(',', ':'), ensure_ascii=False) + else: + v_str = str(v) + parts.append(f"{k}={v_str}") + + query_str = "&".join(parts) + computed_sig = hmac.new( + checksum_key.encode(), query_str.encode(), hashlib.sha256 + ).hexdigest() + return hmac.compare_digest(computed_sig, expected_signature) + +def create_payment_order(user_id: int, plan: str): + """Generates a payment order and produces the relevant PayOS link or fallback VietQR.""" + plan_info = Config.VIP_PLANS.get(plan) + if not plan_info: + if plan.startswith("topup_"): + try: + price_str = plan.split("_")[1] + if price_str.endswith("k"): + amount = int(price_str[:-1]) * 1000 + else: + amount = int(price_str) + plan_info = { + "name_vi": f"Nạp số dư API {amount:,}đ".replace(",", "."), + "price": amount + } + except Exception: + return {"error": "Invalid topup plan name. Use e.g. topup_50k or topup_50000"}, 400 + else: + return {"error": "Invalid plan name"}, 400 + + amount = plan_info["price"] + order_code_int = int(time.time()) * 1000 + (int(user_id) % 1000) + order_id = str(order_code_int) + + # Save to database + conn = get_user_db_conn() + conn.execute( + "INSERT INTO payments (user_id, order_id, plan, amount, status) VALUES (?, ?, ?, ?, 'pending')", + (user_id, order_id, plan, amount) + ) + conn.commit() + conn.close() + + payos_data = None + pay_cfg = Config.PAYMENT_CONFIG + client_id = pay_cfg.get("payos_client_id") + api_key = pay_cfg.get("payos_api_key") + checksum_key = pay_cfg.get("payos_checksum_key") + + if client_id and api_key and checksum_key: + cancel_url = pay_cfg.get("payos_webhook_url").replace("/api/payment/webhook", "") or "http://localhost:5050" + return_url = pay_cfg.get("payos_webhook_url").replace("/api/payment/webhook", "") or "http://localhost:5050" + description = f"VIP {plan_info.get('name_vi', 'Premium')}"[:25] + + raw_str = f"amount={amount}&cancelUrl={cancel_url}&description={description}&orderCode={order_code_int}&returnUrl={return_url}" + signature = hmac.new( + checksum_key.encode(), raw_str.encode(), hashlib.sha256 + ).hexdigest() + + payload = { + "orderCode": order_code_int, + "amount": amount, + "description": description, + "cancelUrl": cancel_url, + "returnUrl": return_url, + "signature": signature + } + + headers = { + "x-client-id": client_id, + "x-api-key": api_key, + "Content-Type": "application/json" + } + + try: + r = requests.post( + "https://api-merchant.payos.vn/v2/payment-requests", + json=payload, + headers=headers, + timeout=10 + ) + res = r.json() + if r.status_code == 200 and res.get("code") == "00": + payos_data = res.get("data") + except Exception as e: + print(f"[PayOS Request Exception]: {e}") + + # Generate QR URL (Using PayOS hosted qrCode if available, else fallback to standard VietQR) + if payos_data and payos_data.get("qrCode"): + qr_url = f"https://api.qrserver.com/v1/create-qr-code/?size=250x250&data={requests.utils.quote(payos_data['qrCode'])}" + checkout_url = payos_data.get("checkoutUrl") + payos_bank = payos_data.get("bin", pay_cfg["bank_id"]) + payos_account_no = payos_data.get("accountNumber", pay_cfg["account_no"]) + payos_account_name = payos_data.get("accountName", pay_cfg["account_name"]) + else: + transfer_content = order_id + qr_url = ( + f"https://img.vietqr.io/image/{pay_cfg['bank_id']}-{pay_cfg['account_no']}-{pay_cfg['template']}.png" + f"?amount={amount}" + f"&addInfo={transfer_content}" + f"&accountName={pay_cfg['account_name'].replace(' ', '%20')}" + ) + checkout_url = None + payos_bank = pay_cfg["bank_id"] + payos_account_no = pay_cfg["account_no"] + payos_account_name = pay_cfg["account_name"] + + return { + "order_id": order_id, + "plan": plan, + "amount": amount, + "amount_formatted": f"{amount:,}đ".replace(",", "."), + "qr_url": qr_url, + "checkout_url": checkout_url, + "bank_info": { + "bank": payos_bank, + "account_no": payos_account_no, + "account_name": payos_account_name, + "transfer_content": order_id, + }, + "expires_in": 900, + "message": f"Quét mã QR hoặc chuyển khoản {amount:,}đ với nội dung: {order_id}".replace(",", ".") + }, 200 + +def confirm_payment(order_id: str, amount: float = 0.0) -> bool: + """Updates the status of a pending payment order to completed and activates VIP.""" + try: + conn = get_user_db_conn() + conn.row_factory = sqlite3.Row + payment = conn.execute( + "SELECT * FROM payments WHERE order_id = ? AND status = 'pending'", (order_id,) + ).fetchone() + + if not payment: + conn.close() + print(f"⚠️ Payment {order_id} not found or already processed.") + return False + + # Optional validation check for amount consistency + if amount > 0 and abs(amount - payment["amount"]) > 100: + conn.close() + print(f"❌ Amount mismatch for {order_id}: expected {payment['amount']}, got {amount}") + return False + + now = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S") + conn.execute( + "UPDATE payments SET status = 'completed', completed_at = ? WHERE id = ?", + (now, payment["id"]) + ) + conn.commit() + conn.close() + + user_id = payment["user_id"] + plan = payment["plan"] + + # Activate VIP status for user + success = activate_vip(user_id, plan) + if success: + print(f"✅ [Payment Confirmation] Confirmed payment {order_id} & activated VIP.") + return True + return False + except Exception as e: + print(f"❌ Error confirming payment: {e}") + return False diff --git a/backend/services/translation.py b/backend/services/translation.py new file mode 100644 index 0000000000000000000000000000000000000000..e5322c37faf5a915e196336622901547bed22ab3 --- /dev/null +++ b/backend/services/translation.py @@ -0,0 +1,97 @@ +import os +import sys +import json +import time +import requests as py_requests +from backend.config import Config + +# Dynamic path addition for local translation engine +if Config.ROOT_DIR not in sys.path: + sys.path.append(Config.ROOT_DIR) + +engine = None +translation_limit_tracker = {} # Format: { "IP:YYYY-MM-DD": count } +ADMIN_GEMINI_KEY = os.environ.get("ADMIN_GEMINI_KEY", "") + +def get_engine(): + global engine + if engine is None: + print("Lazy-loading Vietphrase Engine...") + from backend.engine.engine import VietphraseEngine + engine = VietphraseEngine() + return engine + +def parse_custom_dict_text(dict_text): + if not dict_text: + return None + custom_dict = [] + lines = dict_text.split('\n') + for line in lines: + line = line.strip() + if not line or '=' not in line: + continue + parts = line.split('=', 1) + zh = parts[0].strip() + vi = parts[1].strip() + if zh and vi: + custom_dict.append((zh, vi)) + # Sort by key length descending to avoid prefix collision during greedy replacement + custom_dict.sort(key=lambda x: len(x[0]), reverse=True) + return custom_dict + +def translate_texts(texts, mode=None): + eng = get_engine() + translations = [] + for text in texts: + if not text.strip(): + translations.append(text) + else: + try: + trans = eng.translate(text, multi_option=False, mode=mode) + translations.append(trans) + except Exception as e: + print(f"Error translating: {e}") + translations.append(text) + return translations + +def translate_stream_generator(texts, mode=None): + eng = get_engine() + for i, text in enumerate(texts): + if not text.strip(): + trans = text + else: + try: + trans = eng.translate(text, multi_option=False, mode=mode) + except Exception as e: + print(f"Error translating: {e}") + trans = text + yield f"data: {json.dumps({'index': i, 'text': trans}, ensure_ascii=False)}\n\n" + time.sleep(0.001) + +def call_ai_chat_proxy(messages, model="gemini-1.5-flash", prompt=""): + if not ADMIN_GEMINI_KEY: + raise ValueError("Admin Gemini key not configured on server.") + + url = f"https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent?key={ADMIN_GEMINI_KEY}" + + contents = [] + for msg in messages: + contents.append({ + "role": "user" if msg.get("role") == "user" else "model", + "parts": [{"text": msg.get("text", "")}] + }) + + payload = { + "contents": contents, + "systemInstruction": { + "parts": [{"text": prompt}] + } + } + + res = py_requests.post(url, json=payload, timeout=30) + if res.status_code != 200: + raise RuntimeError(f"Gemini API returned error: {res.text}") + + gemini_data = res.json() + response_text = gemini_data.get("candidates", [{}])[0].get("content", {}).get("parts", [{}])[0].get("text", "Không nhận được phản hồi.") + return response_text diff --git a/backend/test_sects_flow.py b/backend/test_sects_flow.py new file mode 100644 index 0000000000000000000000000000000000000000..af7ef3903c39bcb8c9c10543c0c2ca15c2c909e1 --- /dev/null +++ b/backend/test_sects_flow.py @@ -0,0 +1,230 @@ +import requests, time, sys, os +BASE_URL = "http://localhost:5051" +ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.append(ROOT_DIR) +from backend.database.db_manager import get_user_db_conn + +H = {"X-Bypass-Rate-Limit": "tienhiep_bypass_secret_9988"} + +def step(msg): print(f"\n{'='*60}\n👉 {msg}\n{'='*60}") +def ok(msg): print(f" ✅ {msg}") +def info(msg): print(f" 📌 {msg}") + +def verify_db(username): + conn = get_user_db_conn() + conn.execute("UPDATE users SET email_verified = 1 WHERE username = ?", (username,)) + conn.commit(); conn.close() + +class C: + def __init__(self, u, p): + self.u, self.p, self.token, self.h, self.uid = u, p, None, dict(H), None + def register(self): + r = requests.post(f"{BASE_URL}/api/auth/register", json={"username":self.u,"password":self.p,"email":f"{self.u}@test.com"}, headers=self.h) + if r.status_code == 200 or "đã tồn tại" in r.text: verify_db(self.u) + def login(self): + r = requests.post(f"{BASE_URL}/api/auth/login", json={"username":self.u,"password":self.p}, headers=self.h) + assert r.status_code == 200, f"Login fail {self.u}: {r.text}" + d = r.json(); self.token = d.get("access_token") or d.get("token") + self.h = {"Authorization":f"Bearer {self.token}", **H}; self.uid = d.get("user",{}).get("id") + ok(f"Login {self.u} (ID:{self.uid})") + def post(self, ep, data=None): return requests.post(f"{BASE_URL}{ep}", json=data, headers=self.h) + def get(self, ep, params=None): return requests.get(f"{BASE_URL}{ep}", params=params, headers=self.h) + +def cleanup(): + # Use API-based cleanup - leave all sects via HTTP + for n in ["tst_leader","tst_vice","tst_elder","tst_inner1","tst_inner2","tst_outer"]: + try: + # Login + r = requests.post(f"{BASE_URL}/api/auth/login", json={"username":n,"password":"pw123"}, headers=H) + if r.status_code != 200: continue + tok = r.json().get("access_token") or r.json().get("token") + ah = {"Authorization":f"Bearer {tok}", **H} + # Check if in sect + r = requests.get(f"{BASE_URL}/api/sects/my-sect", headers=ah) + if r.status_code == 200 and r.json().get("in_sect"): + requests.post(f"{BASE_URL}/api/sects/leave", headers=ah) + except: pass + +def run(): + step("1. TẠO 6 TÀI KHOẢN") + names = ["tst_leader","tst_vice","tst_elder","tst_inner1","tst_inner2","tst_outer"] + us = {n: C(n,"pw123") for n in names} + for c in us.values(): c.register(); c.login() + + step("2. DỌN DẸP DB CŨ") + cleanup() + + step("3. SÁNG LẬP TÔNG MÔN") + sn = f"TestTong{int(time.time())}" + r = us["tst_leader"].post("/api/sects/create", {"name":sn,"slogan":"Kiếm khí tung hoành","badge":"gold"}) + assert r.status_code == 200, f"Create fail: {r.text}" + sid = r.json()["sect_id"]; ok(f"Tông '{sn}' ID={sid}") + + step("4. TÌM KIẾM TÔNG MÔN") + r = us["tst_leader"].get("/api/sects/search", {"q":"TestTong"}) + assert r.status_code == 200 and r.json()["total"] >= 1 + ok(f"Tìm thấy {r.json()['total']} tông môn, trang {r.json()['page']}/{r.json()['total_pages']}") + + step("5. XEM TÔNG MÔN THEO ID") + r = us["tst_leader"].get(f"/api/sects/{sid}") + assert r.status_code == 200 and r.json()["sect"]["name"] == sn + ok(f"Xem tông ID={sid}: {r.json()['member_count']} thành viên") + + step("6. GIA NHẬP 5 ĐỆ TỬ") + for n in names[1:]: + r = us[n].post("/api/sects/join", {"sect_id":sid}) + assert r.status_code == 200, f"{n} join fail: {r.text}" + ok("5 đệ tử gửi đơn bái kiến") + + r = us["tst_leader"].get("/api/sects/requests/list") + reqs = r.json()["requests"]; ok(f"{len(reqs)} yêu cầu chờ duyệt") + for rq in reqs: + r = us["tst_leader"].post("/api/sects/requests/respond", {"request_id":rq["id"],"action":"approve"}) + assert r.status_code == 200 + ok("Duyệt toàn bộ") + + step("7. HỆ THỐNG 5 CHỨC DANH") + promotions = [ + ("tst_vice", "vice_leader", "Phó Tông chủ"), + ("tst_elder", "elder", "Trưởng lão"), + ("tst_inner1", "inner_disciple", "Nội môn đệ tử"), + ("tst_inner2", "inner_disciple", "Nội môn đệ tử"), + ] + for uname, role, label in promotions: + r = us["tst_leader"].post("/api/sects/promote/rank", {"user_id":us[uname].uid,"role":role}) + assert r.status_code == 200, f"Promote {uname} fail: {r.text}" + ok(f"{uname} → {label}") + + step("8. KIỂM TRA QUYỀN PHÂN CẤP") + # Vice leader thăng elder cho outer + r = us["tst_vice"].post("/api/sects/promote/rank", {"user_id":us["tst_outer"].uid,"role":"elder"}) + assert r.status_code == 200; ok("Phó Tông chủ thăng Trưởng lão cho tst_outer ✓") + # Hạ lại về member + r = us["tst_vice"].post("/api/sects/promote/rank", {"user_id":us["tst_outer"].uid,"role":"member"}) + assert r.status_code == 200; ok("Phó Tông chủ hạ tst_outer về Ngoại môn đệ tử ✓") + # Elder KHÔNG THỂ thăng vice_leader + r = us["tst_elder"].post("/api/sects/promote/rank", {"user_id":us["tst_outer"].uid,"role":"vice_leader"}) + assert r.status_code == 403; ok("Trưởng lão bị chặn thăng Phó Tông chủ ✓ (403)") + + step("9. XEM THÀNH VIÊN & LỌC THEO CHỨC DANH") + r = us["tst_leader"].get("/api/sects/members") + assert r.status_code == 200 + for m in r.json()["members"]: info(f"{m['username']} = {m['role_label']} (cống hiến: {m['contribution']})") + r = us["tst_leader"].get("/api/sects/members", {"role":"inner_disciple"}) + ok(f"Lọc Nội môn: {len(r.json()['members'])} người") + + step("10. CHAT CHUNG TỔNG TÔNG MÔN") + msgs = [ + ("tst_leader", "Toàn tông nghe lệnh, ngày mai xuất chinh!"), + ("tst_vice", "Phó Tông chủ đã sắp xếp đội hình chiến đấu."), + ("tst_elder", "Trưởng lão báo cáo: đan dược đã đủ cung ứng."), + ("tst_inner1", "Nội môn đệ tử xin tuân lệnh!"), + ("tst_outer", "Ngoại môn đệ tử sẵn sàng!"), + ] + for u, msg in msgs: + r = us[u].post("/api/sects/chat/send", {"message":msg,"chat_type":"general"}) + assert r.status_code == 200 + r = us["tst_outer"].get("/api/sects/chat/history", {"chat_type":"general"}) + ok(f"Chat chung: {len(r.json()['messages'])} tin nhắn") + for m in r.json()["messages"]: info(f"[{m['sender_name']}]: {m['message']}") + + step("11. CHAT RIÊNG 1-1 TRONG TÔNG MÔN") + pairs = [ + ("tst_leader","tst_vice","Phó Tông chủ, ngày mai phân công thế nào?"), + ("tst_vice","tst_leader","Dạ, đệ tử đã chuẩn bị 3 đội tiên phong."), + ("tst_inner1","tst_inner2","Đồng môn ơi, cùng luyện công tối nay không?"), + ("tst_inner2","tst_inner1","Được chứ, 8 giờ tại Luyện Công Đường nhé!"), + ("tst_elder","tst_outer","Ngoại môn đệ tử, tu vi gần đây tiến bộ ra sao?"), + ("tst_outer","tst_elder","Dạ bẩm Trưởng lão, đệ tử đang ở Luyện Khí tầng 3."), + ] + for s, t, msg in pairs: + r = us[s].post("/api/sects/chat/send", {"message":msg,"chat_type":"direct","target_id":us[t].uid}) + assert r.status_code == 200 + # Verify + r = us["tst_leader"].get("/api/sects/chat/history", {"chat_type":"direct","target_id":us["tst_vice"].uid}) + ok(f"Chat riêng Leader↔Vice: {len(r.json()['messages'])} tin") + r = us["tst_inner1"].get("/api/sects/chat/history", {"chat_type":"direct","target_id":us["tst_inner2"].uid}) + ok(f"Chat riêng Inner1↔Inner2: {len(r.json()['messages'])} tin") + r = us["tst_elder"].get("/api/sects/chat/history", {"chat_type":"direct","target_id":us["tst_outer"].uid}) + ok(f"Chat riêng Elder↔Outer: {len(r.json()['messages'])} tin") + + step("12. TẠO NHÓM CHAT NHỎ #1 (Ban lãnh đạo)") + r = us["tst_leader"].post("/api/sects/chat/groups/create", { + "name":"Ban lãnh đạo","members":[us["tst_leader"].uid, us["tst_vice"].uid, us["tst_elder"].uid] + }) + assert r.status_code == 200; g1 = r.json()["group_id"]; ok(f"Nhóm 'Ban lãnh đạo' ID={g1}") + + step("13. TẠO NHÓM CHAT NHỎ #2 (Đội tu luyện)") + r = us["tst_inner1"].post("/api/sects/chat/groups/create", { + "name":"Đội tu luyện","members":[us["tst_inner1"].uid, us["tst_inner2"].uid, us["tst_outer"].uid] + }) + assert r.status_code == 200; g2 = r.json()["group_id"]; ok(f"Nhóm 'Đội tu luyện' ID={g2}") + + step("14. CHAT TRONG NHÓM NHỎ") + for u, msg in [("tst_leader","Hội nghị mật: chiến lược đánh Ma Giáo"),("tst_vice","Đề xuất tấn công từ hướng Đông"),("tst_elder","Đồng ý, trưởng lão sẽ dẫn đội hỗ trợ")]: + r = us[u].post("/api/sects/chat/send", {"message":msg,"chat_type":"group","group_id":g1}) + assert r.status_code == 200 + for u, msg in [("tst_inner1","Tối nay luyện kiếm pháp mới!"),("tst_inner2","OK sư huynh!"),("tst_outer","Đệ tử cũng xin tham gia!")]: + r = us[u].post("/api/sects/chat/send", {"message":msg,"chat_type":"group","group_id":g2}) + assert r.status_code == 200 + r = us["tst_leader"].get("/api/sects/chat/history", {"chat_type":"group","group_id":g1}) + ok(f"Nhóm BLĐ: {len(r.json()['messages'])} tin") + r = us["tst_inner1"].get("/api/sects/chat/history", {"chat_type":"group","group_id":g2}) + ok(f"Nhóm tu luyện: {len(r.json()['messages'])} tin") + + step("15. BẢO MẬT: NGƯỜI NGOÀI KHÔNG CHAT ĐƯỢC NHÓM") + r = us["tst_outer"].post("/api/sects/chat/send", {"message":"hack","chat_type":"group","group_id":g1}) + assert r.status_code == 403; ok(f"Outer bị chặn chat nhóm BLĐ (403) ✓") + r = us["tst_outer"].get("/api/sects/chat/history", {"chat_type":"group","group_id":g1}) + assert r.status_code == 403; ok(f"Outer bị chặn xem lịch sử BLĐ (403) ✓") + + step("16. THÊM/XÓA THÀNH VIÊN NHÓM CHAT") + r = us["tst_leader"].post(f"/api/sects/chat/groups/{g1}/members/add", {"user_ids":[us["tst_inner1"].uid]}) + assert r.status_code == 200; ok(f"Thêm Inner1 vào BLĐ, members={r.json()['members']}") + r = us["tst_leader"].post(f"/api/sects/chat/groups/{g1}/members/remove", {"user_id":us["tst_inner1"].uid}) + assert r.status_code == 200; ok(f"Xóa Inner1 khỏi BLĐ, members={r.json()['members']}") + + step("17. XEM THÔNG TIN NHÓM CHAT") + r = us["tst_leader"].get(f"/api/sects/chat/groups/{g1}") + assert r.status_code == 200 + ginfo = r.json(); ok(f"Nhóm: {ginfo['group']['name']}, {ginfo['member_count']} thành viên") + for m in ginfo["members"]: info(f" {m['username']} ({m['role_label']})") + + step("18. DANH SÁCH TẤT CẢ NHÓM CHAT CỦA TÔI") + r = us["tst_leader"].get("/api/sects/chat/groups") + assert r.status_code == 200; ok(f"Leader thấy {len(r.json()['groups'])} nhóm") + r = us["tst_inner1"].get("/api/sects/chat/groups") + ok(f"Inner1 thấy {len(r.json()['groups'])} nhóm") + + step("19. KẾT BẠN & CHAT BẠN BÈ") + conn = get_user_db_conn() + conn.execute("DELETE FROM friendships WHERE user_id IN (?,?) OR friend_id IN (?,?)", + (us["tst_inner1"].uid, us["tst_outer"].uid, us["tst_inner1"].uid, us["tst_outer"].uid)) + conn.commit(); conn.close() + r = us["tst_inner1"].post("/api/friends/request", {"friend_username":"tst_outer"}) + assert r.status_code == 200; ok("Inner1 gửi kết bạn Outer") + r = us["tst_outer"].post("/api/friends/respond", {"sender_id":us["tst_inner1"].uid,"action":"accept"}) + assert r.status_code == 200; ok("Outer chấp nhận") + r = us["tst_inner1"].get("/api/friends/list") + ok(f"Bạn bè Inner1: {[f['username'] for f in r.json()['friends']]}") + r = us["tst_inner1"].post("/api/messages/send", {"receiver_id":us["tst_outer"].uid,"message":"Chào bạn, tối nay đi phụ bản không?"}) + assert r.status_code == 200 + r = us["tst_outer"].post("/api/messages/send", {"receiver_id":us["tst_inner1"].uid,"message":"Đi chứ! 9h tối nhé!"}) + assert r.status_code == 200 + r = us["tst_inner1"].get(f"/api/messages/chat/{us['tst_outer'].uid}") + ok(f"Chat bạn bè: {len(r.json()['messages'])} tin nhắn") + for m in r.json()["messages"]: + sn = "tst_inner1" if m["sender_id"]==us["tst_inner1"].uid else "tst_outer" + info(f"[{sn}]: {m['message']}") + + step("20. CỐNG HIẾN & XEM TÔNG MÔN QUA ID") + us["tst_inner1"].post("/api/sects/contribute", {"amount":300}) + us["tst_outer"].post("/api/sects/contribute", {"amount":200}) + r = us["tst_leader"].get(f"/api/sects/{sid}") + d = r.json() + ok(f"Tông '{d['sect']['name']}' cấp {d['sect']['level']}, cống hiến tổng: {d['sect']['contribution']}") + ok(f"Phân bố chức danh: {d['role_counts']}") + + step("🎉 TOÀN BỘ 20 BƯỚC TEST THÀNH CÔNG!") + +if __name__ == "__main__": run() diff --git a/backend/workers/__init__.py b/backend/workers/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..ffae17e22fe653f7ff3a8e5557f7a49419aa9014 --- /dev/null +++ b/backend/workers/__init__.py @@ -0,0 +1 @@ +# backend/workers/__init__.py diff --git a/backend/workers/email_worker.py b/backend/workers/email_worker.py new file mode 100644 index 0000000000000000000000000000000000000000..8821149bf355d6a43b9fdee219febf96342cec5e --- /dev/null +++ b/backend/workers/email_worker.py @@ -0,0 +1,223 @@ +import re +import base64 +import time +import email +import imaplib +import os +import sqlite3 +import threading +from email.header import decode_header +from datetime import datetime +from backend.config import Config +from backend.services.email_service import ( + get_gmail_service, send_email_smtp, send_email_gmail_api, SERVICE_ACCOUNT_FILE +) +from backend.database.db_manager import get_user_db_conn + +def get_customer_email_by_order(order_id: str): + try: + conn = get_user_db_conn() + conn.row_factory = sqlite3.Row + row = conn.execute( + "SELECT u.email FROM payments p JOIN users u ON p.user_id = u.id WHERE p.order_id = ?", + (order_id,) + ).fetchone() + conn.close() + return row["email"] if row and row["email"] else None + except Exception: + return None + +def process_bank_email_payload(combined_content: str, send_reply_fn): + """Parse payment email content and process activation.""" + order_match = re.search(r'(VIP\w+)', combined_content, re.IGNORECASE) + amount_match = re.search( + r'(?:S\d+ti\d+n|số tiền|giao dịch|phát sinh|cộng)\s*(?:\+)?\s*([0-9.,]+)\s*(?:VND|đ|d|đ)', + combined_content, re.IGNORECASE + ) + + if not order_match: + return False + + from backend.services.payment_service import confirm_payment + + order_id = order_match.group(1).upper() + amount = 0 + if amount_match: + amount_str = amount_match.group(1).replace('.', '').replace(',', '') + try: + amount = float(amount_str) + except ValueError: + pass + + print(f"🔍 [Email Worker] Detected transaction. Order ID: {order_id}, parsed amount: {amount}") + success = confirm_payment(order_id, amount) + + if success: + customer_email = get_customer_email_by_order(order_id) + if customer_email: + reply_subject = f"Xác nhận thanh toán thành công đơn hàng {order_id}" + reply_html = f""" +
+

Thanh toán thành công!

+

Xin chào,

+

Hệ thống đã nhận được số tiền chuyển khoản của bạn cho đơn hàng {order_id}.

+

Tài khoản VIP của bạn đã được nâng cấp và kích hoạt tự động thành công.

+

Chúc bạn có những trải nghiệm đọc truyện tuyệt vời!

+
+

Đội ngũ hỗ trợ Ly Vu Ha Novel

+
+ """ + send_reply_fn(customer_email, reply_subject, reply_html) + return success + +def check_bank_emails_imap(): + """Connects to Gmail via IMAP and processes unread bank payment emails.""" + smtp_cfg = Config.SMTP_CONFIG + if not smtp_cfg["username"] or not smtp_cfg["password"]: + print("⚠️ SMTP/IMAP credentials not configured.") + return + try: + print(f"📥 [IMAP] Connecting to imap.gmail.com as {smtp_cfg['username']}...") + mail = imaplib.IMAP4_SSL("imap.gmail.com") + mail.login(smtp_cfg["username"], smtp_cfg["password"]) + mail.select("inbox") + + status, response = mail.search(None, 'UNSEEN') + if status != "OK": + return + + messages = response[0].split() + if not messages: + print("✅ [IMAP] No unread emails in inbox.") + return + + print(f"📧 [IMAP] Found {len(messages)} unread email(s). Processing...") + + for msg_id in messages: + status, data = mail.fetch(msg_id, "(RFC822)") + if status != "OK": + continue + + raw_email = data[0][1] + msg = email.message_from_bytes(raw_email) + + subject, encoding = decode_header(msg["Subject"])[0] + if isinstance(subject, bytes): + subject = subject.decode(encoding or "utf-8", errors="ignore") + + body = "" + if msg.is_multipart(): + for part in msg.walk(): + content_type = part.get_content_type() + content_disposition = str(part.get("Content-Disposition")) + if content_type == "text/plain" and "attachment" not in content_disposition: + payload = part.get_payload(decode=True) + body += payload.decode("utf-8", errors="ignore") + else: + body = msg.get_payload(decode=True).decode("utf-8", errors="ignore") + + combined_content = f"{subject} {body}" + process_bank_email_payload(combined_content, send_email_smtp) + + # Mark email as read + mail.store(msg_id, '+FLAGS', '\\Seen') + + mail.close() + mail.logout() + except Exception as e: + print(f"❌ Error during IMAP polling worker: {e}") + +def check_bank_emails_gmail_api(): + """Checks Gmail inbox using Gmail API for unread bank/payment emails.""" + service = get_gmail_service() + if not service: + return + try: + query = "is:unread (MB Bank OR Bank OR \"biến động số dư\" OR \"chuyển khoản\")" + results = service.users().messages().list(userId='me', q=query).execute() + messages = results.get('messages', []) + + if not messages: + return + + print(f"📧 [Gmail API] Found {len(messages)} unread bank/payment email(s). Processing...") + + for msg in messages: + msg_id = msg['id'] + message_details = service.users().messages().get(userId='me', id=msg_id, format='full').execute() + + payload = message_details.get('payload', {}) + headers = payload.get('headers', []) + subject = next((h['value'] for h in headers if h['name'].lower() == 'subject'), '') + + body_text = "" + if 'parts' in payload: + for part in payload['parts']: + if part['mimeType'] == 'text/plain': + data = part['body'].get('data', '') + body_text += base64.urlsafe_b64decode(data.encode('utf-8')).decode('utf-8', errors='ignore') + else: + data = payload.get('body', {}).get('data', '') + if data: + body_text = base64.urlsafe_b64decode(data.encode('utf-8')).decode('utf-8', errors='ignore') + + combined_content = f"{subject} {body_text}" + success = process_bank_email_payload(combined_content, send_email_gmail_api) + + # Mark as read regardless + service.users().messages().batchModify( + userId='me', + body={'ids': [msg_id], 'removeLabelIds': ['UNREAD']} + ).execute() + + except Exception as e: + print(f"❌ Error during Gmail polling worker: {e}") + +def check_bank_emails_and_process(): + """Dispatch between Gmail API and IMAP method.""" + if os.path.exists(SERVICE_ACCOUNT_FILE): + check_bank_emails_gmail_api() + else: + check_bank_emails_imap() + +def start_email_worker(): + """Start background daemon thread polling Gmail every 60 seconds (Singleton across workers).""" + # Use a file lock to ensure only ONE Gunicorn worker spawns the background polling thread + import fcntl + + lock_file = "/tmp/email_worker_poll.lock" + try: + # Open file in append mode so it doesn't overwrite + lock_fd = open(lock_file, "a") + # Try to acquire an exclusive, non-blocking lock + fcntl.flock(lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB) + except Exception: + # If lock fails, another worker is already running the email poll loop + print("📧 [Email Worker] Another worker is already polling. Skipping duplicate thread.") + return + + def poll_loop(fd): + print("📧 [Email Worker] Master polling thread acquired lock. Background polling started.") + while True: + try: + check_bank_emails_and_process() + except Exception as e: + print(f"❌ [Email Worker] Error in polling loop: {e}") + # Poll every 60 seconds instead of 15s to avoid IMAP rate limits + time.sleep(60) + + # Note: the file descriptor 'fd' is kept open by this thread so the lock is held + # as long as this specific worker process is alive. + t = threading.Thread(target=poll_loop, args=(lock_fd,), daemon=True) + t.start() + + +if __name__ == "__main__": + print("📧 [Email Worker] Standalone polling loop started in foreground...") + while True: + try: + check_bank_emails_and_process() + except Exception as e: + print(f"❌ [Email Worker] Error in polling loop: {e}") + time.sleep(60) + diff --git a/frontend-web/dist/ads.txt b/frontend-web/dist/ads.txt new file mode 100644 index 0000000000000000000000000000000000000000..96d3260543d9d4258fb36be3533e16b8d6025ad8 --- /dev/null +++ b/frontend-web/dist/ads.txt @@ -0,0 +1,3 @@ +# Google AdSense ads.txt template +# Thay thế ca-pub-9548504602542886 bằng mã nhà xuất bản (Publisher ID) thực tế của bạn +google.com, pub-9548504602542886, DIRECT, f08c47fec0942fa0 diff --git a/frontend-web/dist/assets/AuthorDetail-lunBE6ER.js b/frontend-web/dist/assets/AuthorDetail-lunBE6ER.js new file mode 100644 index 0000000000000000000000000000000000000000..7527d8999d719745dabbeb2648dfa4722e725423 --- /dev/null +++ b/frontend-web/dist/assets/AuthorDetail-lunBE6ER.js @@ -0,0 +1 @@ +import{t as e}from"./award-CKCOPIfL.js";import{a as t,t as n}from"./MainLayout-COiTxmNr.js";import{t as r}from"./book-DwmTvSdZ.js";import{a as i}from"./square-DZKJ0QGR.js";import{t as a}from"./file-text-mhTXpwIY.js";import{D as o,F as s,M as c,O as l,S as u,b as d,f,h as p,j as m,w as h}from"./index-yRoRoI6u.js";var g=d(`layers`,[[`path`,{d:`M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z`,key:`zw3jo`}],[`path`,{d:`M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12`,key:`1wduqc`}],[`path`,{d:`M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17`,key:`kqbvx6`}]]),_=s(m(),1),v=c();function y(){let{authorName:s}=l(),{lang:c}=u(),d=o(),[m,y]=(0,_.useState)(null),[b,x]=(0,_.useState)(!0),[S,C]=(0,_.useState)(``);(0,_.useEffect)(()=>{w()},[s]);let w=async()=>{x(!0),C(``);try{y((await h.get(`/api/author/${encodeURIComponent(s)}`)).data)}catch(e){console.error(e),C(c===`vi`?`Không tìm thấy thông tin tác giả hoặc có lỗi xảy ra.`:c===`en`?`Failed to load author details.`:`无法加载作者详情。`)}finally{x(!1)}};if(b)return(0,v.jsx)(n,{children:(0,v.jsxs)(`div`,{className:`py-20 text-center text-slate-500`,children:[(0,v.jsx)(f,{className:`w-8 h-8 animate-spin mx-auto mb-2 text-purple-500`}),(0,v.jsx)(`span`,{children:c===`vi`?`Đang tải thông tin tác giả...`:c===`en`?`Loading author details...`:`正在加载作者信息...`})]})});if(S||!m)return(0,v.jsx)(n,{children:(0,v.jsx)(`div`,{className:`py-20 text-center text-red-500 font-bold`,children:S||`Lỗi không xác định.`})});let{author_chinese:T,author_hanviet:E,total_books:D,books:O}=m,k=O.reduce((e,t)=>e+(t.chapters_max||0),0);return(0,v.jsxs)(n,{children:[(0,v.jsxs)(`div`,{className:`relative rounded-3xl overflow-hidden border border-[#1f1f3a] mb-8 bg-[#0b0b14]/70 p-6 md:p-8 flex flex-col md:flex-row gap-6 items-center md:items-start z-0`,children:[(0,v.jsx)(`div`,{className:`absolute inset-0 z-[-1] opacity-10 blur-3xl bg-gradient-to-r from-purple-500 to-indigo-600 scale-110`}),(0,v.jsx)(`div`,{className:`w-16 h-16 md:w-20 md:h-20 bg-purple-500/10 border-2 border-purple-500/30 rounded-2xl flex items-center justify-center text-purple-400 shrink-0 shadow-lg shadow-purple-500/5`,children:(0,v.jsx)(t,{className:`w-8 h-8 md:w-10 md:h-10`})}),(0,v.jsxs)(`div`,{className:`flex-1 min-w-0 text-center md:text-left space-y-2`,children:[(0,v.jsx)(`span`,{className:`px-2.5 py-0.5 bg-purple-500/10 border border-purple-500/25 text-purple-400 rounded-full text-[10px] font-black uppercase tracking-wider`,children:c===`vi`?`Hồ sơ tác giả`:c===`en`?`Author Profile`:`作者档案`}),(0,v.jsx)(`h2`,{className:`text-2xl md:text-3xl font-black text-white leading-tight`,children:E}),(0,v.jsxs)(`p`,{className:`text-slate-400 text-xs font-semibold`,children:[c===`vi`?`Tên gốc Trung`:c===`en`?`Chinese Original Name`:`中文原名`,`:`,` `,(0,v.jsx)(`span`,{className:`text-purple-300 font-bold bg-[#121225] px-2 py-0.5 rounded border border-[#1f1f3a]`,children:T})]}),(0,v.jsxs)(`div`,{className:`flex flex-wrap justify-center md:justify-start gap-4 pt-3 text-xs text-slate-400`,children:[(0,v.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#1f1f3a]/80 px-4 py-2 rounded-xl flex items-center gap-2`,children:[(0,v.jsx)(r,{className:`w-4 h-4 text-purple-400`}),(0,v.jsxs)(`span`,{children:[(0,v.jsx)(`strong`,{children:D}),` `,c===`vi`?`Truyện`:c===`en`?`Books`:`本小说`]})]}),(0,v.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#1f1f3a]/80 px-4 py-2 rounded-xl flex items-center gap-2`,children:[(0,v.jsx)(g,{className:`w-4 h-4 text-purple-400`}),(0,v.jsxs)(`span`,{children:[(0,v.jsx)(`strong`,{children:k.toLocaleString()}),` `,c===`vi`?`Chương tích lũy`:c===`en`?`Total Chapters`:`总章节`]})]}),(0,v.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#1f1f3a]/80 px-4 py-2 rounded-xl flex items-center gap-2`,children:[(0,v.jsx)(e,{className:`w-4 h-4 text-purple-400`}),(0,v.jsx)(`span`,{children:(0,v.jsx)(`strong`,{children:`Antigravity Verified`})})]})]})]})]}),(0,v.jsxs)(`div`,{className:`mb-6 flex justify-between items-center`,children:[(0,v.jsxs)(`h3`,{className:`text-lg font-black text-white flex items-center gap-2`,children:[(0,v.jsx)(a,{className:`w-5 h-5 text-purple-400`}),c===`vi`?`Các tác phẩm tiêu biểu`:c===`en`?`Works List`:`代表作品`]}),(0,v.jsx)(`span`,{className:`text-xs text-slate-500 font-bold`,children:c===`vi`?`Hiển thị ${O.length} kết quả`:c===`en`?`${O.length} results`:`共 ${O.length} 部`})]}),(0,v.jsx)(`div`,{className:`space-y-6`,children:O.map(e=>(0,v.jsxs)(`div`,{className:`bg-[#121225]/50 border border-[#1f1f3a] rounded-3xl p-5 md:p-6 flex flex-col md:flex-row gap-5 hover:border-purple-500/20 hover:bg-[#121225]/70 transition-all duration-300 relative group`,children:[e.cover?(0,v.jsx)(`img`,{src:e.cover,alt:`cover`,className:`w-[90px] h-[125px] md:w-[110px] md:h-[155px] object-cover rounded-xl border border-[#1f1f3a] shadow-lg group-hover:scale-[1.02] transition-transform duration-300 shrink-0 mx-auto md:mx-0`}):(0,v.jsx)(`div`,{className:`w-[90px] h-[125px] md:w-[110px] md:h-[155px] bg-[#0b0b14] border border-[#1f1f3a] rounded-xl flex items-center justify-center text-slate-600 shrink-0 mx-auto md:mx-0`,children:(0,v.jsx)(r,{className:`w-10 h-10`})}),(0,v.jsxs)(`div`,{className:`flex-1 min-w-0 flex flex-col justify-between space-y-3 text-center md:text-left`,children:[(0,v.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,v.jsx)(`h4`,{onClick:()=>d(`/book/${e.id}`),className:`text-base md:text-lg font-black text-white cursor-pointer hover:text-purple-400 transition-colors leading-tight inline-block`,children:e.title_vietphrase||e.title_hanviet}),(0,v.jsxs)(`p`,{className:`text-[10px] text-slate-500 font-semibold`,children:[c===`vi`?`Tiêu đề gốc`:c===`en`?`Original Title`:`原著`,`: `,e.title,` · `,e.chapters_max,` `,c===`vi`?`chương`:c===`en`?`chapters`:`章`]}),(0,v.jsx)(`p`,{className:`text-slate-300 text-xs leading-relaxed line-clamp-3`,children:e.description_vietphrase||e.description_hanviet||e.description||(c===`vi`?`Chưa có tóm tắt nội dung.`:c===`en`?`No description available.`:`暂无内容简介。`)})]}),(0,v.jsxs)(`div`,{className:`flex flex-col sm:flex-row sm:items-center justify-between gap-4 pt-2 border-t border-[#1f1f3a]/40`,children:[(0,v.jsx)(`div`,{className:`flex flex-wrap justify-center md:justify-start gap-1.5`,children:e.categories&&e.categories.split(/[,,]/).map(e=>e.trim()).filter(Boolean).map((e,t)=>(0,v.jsx)(`span`,{className:`px-2 py-0.5 bg-[#0b0b14]/60 border border-[#1f1f3a] text-slate-400 rounded-md text-[10px] font-semibold`,children:e},t))}),(0,v.jsxs)(`div`,{className:`flex flex-wrap justify-center sm:justify-end items-center gap-1.5`,children:[(0,v.jsxs)(`span`,{className:`text-[10px] text-slate-500 font-bold flex items-center gap-1`,children:[(0,v.jsx)(p,{className:`w-3 h-3 text-purple-400`}),c===`vi`?`Nguồn gốc:`:c===`en`?`Source web:`:`来源网站:`]}),e.parsed_sources&&e.parsed_sources.length>0?e.parsed_sources.map((e,t)=>(0,v.jsxs)(`a`,{href:e.url,target:`_blank`,rel:`noopener noreferrer`,className:`inline-flex items-center gap-1 px-2 py-1 bg-purple-950/20 hover:bg-purple-900/40 border border-purple-500/20 hover:border-purple-500/30 text-purple-300 rounded-lg text-[9px] font-black transition-colors`,title:e.url,children:[e.source,(0,v.jsx)(i,{className:`w-2.5 h-2.5 text-purple-400`})]},t)):(0,v.jsx)(`span`,{className:`text-[10px] text-slate-600 italic`,children:c===`vi`?`Không rõ`:c===`en`?`Unknown`:`未知`})]})]})]})]},e.id))})]})}export{y as default}; \ No newline at end of file diff --git a/frontend-web/dist/assets/BookCard-BCMDdlyN.js b/frontend-web/dist/assets/BookCard-BCMDdlyN.js new file mode 100644 index 0000000000000000000000000000000000000000..b1d2dd78042746b31e96e2a9d20432f8268edc21 --- /dev/null +++ b/frontend-web/dist/assets/BookCard-BCMDdlyN.js @@ -0,0 +1 @@ +import{t as e}from"./book-DwmTvSdZ.js";import{n as t,r as n,t as r}from"./star-DjnKUekI.js";import{D as i,F as a,M as o,S as s,b as c,j as l,n as u,s as d,t as f,w as p}from"./index-yRoRoI6u.js";var m=c(`columns-2`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}],[`path`,{d:`M12 3v18`,key:`108xh3`}]]),h=a(l(),1),g=o();function _({book:a,isFav:o,onToggleFav:c,onCompare:l,onRead:_,onPlayTrailer:v,onSearchAuthor:y,onSearchCategory:b}){let{t:x,lang:S}=s(),{openInBrowser:C}=f(),w=i(),[T,E]=(0,h.useState)(!1),[D,O]=(0,h.useState)(`original`),[k,A]=(0,h.useState)(``),[j,M]=(0,h.useState)(!1),N=e=>e?e.split(` | `).map(e=>{let t=e.indexOf(`: `);return t<0?null:{site:e.slice(0,t),url:e.slice(t+2)}}).filter(Boolean):[],P=(()=>{if(S===`zh`||S===`en`)return a.title||`—`;let e=a.title_vietphrase||a.title_hanviet;return e&&a.title&&e!==a.title?`${e} (${a.title})`:e||a.title||`—`})(),F=S===`zh`?a.author||`—`:S===`en`?a.author_english||a.author||`—`:a.author_hanviet||a.author||`—`,I=S===`zh`?a.description||``:S===`en`?a.description_english||a.description||``:a.description_vietphrase||a.description||``,L=D===`original`?I:k||I,R=N(a.urls),z=()=>{let e=a.categories||``;return e.includes(`玄幻`)||e.includes(`修真`)||e.includes(`仙侠`)||e.includes(`Huyền Huyện`)||e.includes(`Tiên Hiệp`)?[`Sát phạt`,`Vô địch`]:(e.includes(`都市`)||e.includes(`历史`)||e.includes(`Đô Thị`)||e.includes(`Lịch Sử`)||e.includes(`Văn Minh`)||e.includes(`Văn minh`),[`Hài hước`,`Trí tuệ`])},B=async e=>{if(e===`original`){O(`original`);return}M(!0);try{try{let t=await p.post(`/api/translate`,{texts:[I],mode:e===`en`?`en`:`vietphrase`});t.data&&t.data.translations&&t.data.translations[0]&&(A(t.data.translations[0]),O(e))}catch(t){console.warn(`[BookCard] Cloud translation failed, trying offline localTranslator:`,t),await u.loadDictionaries(),A(u.translateSentence(I,`advanced`)),O(e)}}catch{alert(`Hạn mức dịch máy chủ đã hết và bộ dịch offline gặp lỗi.`)}finally{M(!1)}},V=S===`zh`?a.categories||``:S===`en`?a.categories_english||a.categories||``:a.categories_vietphrase||a.categories||``,H=V?V.split(/[,,/、\s]+/).map(e=>e.trim()).filter(Boolean):[];return(0,g.jsxs)(`div`,{className:`bg-[#121225]/85 border border-[#1f1f3a] rounded-xl p-3.5 hover:border-purple-500/50 hover:shadow-xl hover:shadow-purple-500/5 transition-all duration-300 flex flex-col justify-between relative overflow-visible min-h-[300px]`,children:[(0,g.jsxs)(`div`,{children:[(0,g.jsxs)(`div`,{className:`flex gap-3`,children:[a.cover?(0,g.jsx)(`img`,{src:a.cover,alt:`cover`,className:`w-[60px] h-[82px] object-cover rounded-lg border border-[#2d2d55] shadow-md shrink-0 bg-[#0f0f1a]`,onError:e=>{e.target.remove()}}):(0,g.jsx)(`div`,{className:`w-[60px] h-[82px] rounded-lg border border-[#2d2d55] bg-[#0f0f1a] flex items-center justify-center text-slate-500 shrink-0 shadow-md`,children:(0,g.jsx)(e,{className:`w-5 h-5`})}),(0,g.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,g.jsxs)(`div`,{className:`flex justify-between items-start gap-2`,children:[(0,g.jsx)(`h3`,{className:`text-slate-100 font-bold text-xs hover:text-purple-400 transition-colors cursor-pointer flex-1 whitespace-normal break-words line-clamp-2`,onClick:()=>_&&_(a),title:P,children:P}),I&&(0,g.jsx)(`button`,{onClick:()=>v&&v(a),className:`p-1 rounded bg-[#1f1f3a] hover:bg-purple-600 hover:text-white text-purple-400 transition-colors shrink-0`,title:`Nghe tóm tắt AI (TTS)`,children:(0,g.jsx)(d,{className:`w-3 h-3`})})]}),(0,g.jsxs)(`div`,{className:`text-[10px] text-slate-500 mt-1 space-y-0.5`,children:[(0,g.jsxs)(`div`,{className:`whitespace-normal break-words`,children:[`Tác giả: `,(0,g.jsx)(`span`,{onClick:()=>{let e=a.author||a.author_hanviet||F;e&&e!==`—`&&w(`/author/${encodeURIComponent(e)}`)},className:`text-purple-400 hover:text-purple-300 cursor-pointer underline hover:no-underline font-semibold`,title:`Xem hồ sơ tác giả`,children:F})]}),(0,g.jsxs)(`div`,{className:`whitespace-normal break-words line-clamp-1`,children:[`Gốc: `,(0,g.jsx)(`span`,{className:`text-slate-400`,children:a.title||`—`})]})]}),(0,g.jsxs)(`div`,{className:`flex flex-wrap gap-1 mt-1.5`,children:[(0,g.jsxs)(`span`,{className:`px-1.5 py-0.5 rounded text-[8px] font-extrabold bg-amber-500/10 border border-amber-500/20 text-amber-400`,children:[a.site_count||5,` nguồn`]}),(0,g.jsxs)(`span`,{className:`px-1.5 py-0.5 rounded text-[8px] font-extrabold bg-cyan-500/10 border border-cyan-500/20 text-cyan-400`,children:[a.site_count||5,` site`]}),(0,g.jsx)(`span`,{className:`px-1.5 py-0.5 rounded text-[8px] font-extrabold bg-emerald-500/10 border border-emerald-500/20 text-emerald-400`,children:a.word_count_max?Math.round(a.word_count_max/1e3):1975})]})]})]}),H.length>0&&(0,g.jsxs)(`div`,{className:`flex flex-wrap gap-1 mt-2.5 items-center`,children:[(0,g.jsx)(`span`,{className:`text-slate-500 text-[9px]`,children:`Thể loại:`}),H.map((e,t)=>(0,g.jsx)(`span`,{onClick:()=>b&&b(e),className:`cursor-pointer px-1.5 py-0.5 rounded bg-purple-500/10 border border-purple-500/20 hover:bg-purple-500/20 text-purple-400 text-[8px] font-semibold transition-colors`,title:`Lọc thể loại ${e}`,children:e},t))]}),(0,g.jsxs)(`div`,{className:`flex justify-between items-center text-slate-400 text-[10px] mt-2.5 border-t border-[#1f1f3a]/40 pt-2`,children:[(0,g.jsxs)(`span`,{children:[(0,g.jsx)(`strong`,{children:`Chương:`}),` `,a.chapters_max||110,` | `,a.word_count_max?Math.round(a.word_count_max/1e3):0]}),I&&(0,g.jsx)(`button`,{onClick:()=>E(!T),className:`text-slate-500 hover:text-purple-400 text-[9px] flex items-center gap-0.5 font-bold transition-colors`,children:T?(0,g.jsxs)(g.Fragment,{children:[`Ẩn tóm tắt `,(0,g.jsx)(t,{className:`w-2.5 h-2.5`})]}):(0,g.jsxs)(g.Fragment,{children:[`Hiện tóm tắt `,(0,g.jsx)(n,{className:`w-2.5 h-2.5`})]})})]}),T&&I&&(0,g.jsxs)(`div`,{className:`mt-2.5 bg-[#0b0b14]/50 p-2 rounded-lg border border-[#1a1a2e] transition-all duration-300`,children:[(0,g.jsxs)(`div`,{className:`flex justify-between items-center mb-1 text-[9px] text-slate-500`,children:[(0,g.jsx)(`span`,{children:`Tóm tắt:`}),(0,g.jsxs)(`div`,{className:`flex gap-1`,children:[(0,g.jsx)(`button`,{onClick:()=>B(`original`),className:`px-1 py-0.5 rounded text-[8px] font-bold ${D===`original`?`bg-purple-600 text-white`:`hover:bg-white/5 text-slate-400`}`,children:`Gốc`}),(0,g.jsx)(`button`,{onClick:()=>B(`vi`),className:`px-1 py-0.5 rounded text-[8px] font-bold ${D===`vi`?`bg-purple-600 text-white`:`hover:bg-white/5 text-slate-400`}`,disabled:j,children:`🇻🇳`}),(0,g.jsx)(`button`,{onClick:()=>B(`en`),className:`px-1 py-0.5 rounded text-[8px] font-bold ${D===`en`?`bg-purple-600 text-white`:`hover:bg-white/5 text-slate-400`}`,disabled:j,children:`🇺🇸`})]})]}),(0,g.jsx)(`p`,{className:`text-slate-400 text-[10px] line-clamp-3 leading-relaxed`,title:I,children:j?`Đang dịch tóm tắt...`:L})]}),(0,g.jsxs)(`div`,{className:`flex gap-1.5 items-center mt-2.5 text-[9px]`,children:[(0,g.jsx)(`span`,{className:`text-slate-500`,children:`Cảm xúc:`}),z().map((e,t)=>(0,g.jsx)(`span`,{className:`px-1.5 py-0.5 rounded bg-amber-500/10 border border-amber-500/25 text-amber-400 font-extrabold text-[8px]`,children:e},t))]}),(0,g.jsx)(`div`,{className:`mt-2.5 relative`,children:(0,g.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:R.map((e,t)=>{let n=`bg-emerald-500 text-white`;return e.site.toLowerCase().includes(`biquge`)||e.site.toLowerCase().includes(`full`)||e.site.toLowerCase().includes(`truyenfull`)?n=`bg-sky-500 text-white`:e.site.toLowerCase().includes(`faloo`)||e.site.toLowerCase().includes(`vcomi`)||e.site.toLowerCase().includes(`fanqie`)?n=`bg-orange-500 text-white`:(e.site.toLowerCase().includes(`quanben`)||e.site.toLowerCase().includes(`hjwzw`))&&(n=`bg-purple-500 text-white`),(0,g.jsxs)(`a`,{href:e.url,target:`_blank`,rel:`noreferrer`,onClick:t=>{t.preventDefault(),t.stopPropagation(),C(e.url)},className:`inline-flex items-center gap-1 bg-[#0b0b14]/40 border border-[#1f1f3a] hover:border-purple-500/30 rounded px-1.5 py-0.5 text-[9px] text-slate-300 hover:text-white transition-all`,children:[(0,g.jsx)(`span`,{className:`w-3 h-3 rounded flex items-center justify-center text-[8px] font-extrabold ${n}`,children:e.site[0]}),e.site]},t)})})})]}),(0,g.jsxs)(`div`,{className:`flex gap-2 mt-3 pt-2 border-t border-[#1f1f3a]/20`,children:[(0,g.jsxs)(`button`,{onClick:()=>l&&l(a.id),className:`flex-1 inline-flex items-center justify-center gap-1 bg-transparent border border-purple-500/30 text-purple-400 hover:bg-purple-600/10 py-2.5 sm:py-1.5 rounded-lg text-[10px] font-bold transition-all min-h-[36px]`,children:[(0,g.jsx)(m,{className:`w-3 h-3`}),` So sánh bản dịch`]}),(0,g.jsx)(`button`,{onClick:e=>{e.stopPropagation(),c&&c(a.id)},className:`px-3 py-2.5 sm:px-2 sm:py-1.5 border rounded-lg text-[10px] font-semibold transition-all min-h-[36px] ${o?`bg-amber-400 border-amber-400 text-[#0b0b14]`:`bg-amber-400/5 border-amber-400/30 text-amber-400 hover:bg-amber-400/15`}`,title:o?x.removeExternal:x.addBookshelf,children:(0,g.jsx)(r,{className:`w-3.5 h-3.5 fill-current`})})]})]})}export{_ as t}; \ No newline at end of file diff --git a/frontend-web/dist/assets/BookDetail-CwKiYfhq.js b/frontend-web/dist/assets/BookDetail-CwKiYfhq.js new file mode 100644 index 0000000000000000000000000000000000000000..42bbc38c137c5cd3b7a4fca60ce55c54d036da64 --- /dev/null +++ b/frontend-web/dist/assets/BookDetail-CwKiYfhq.js @@ -0,0 +1 @@ +import{t as e}from"./award-CKCOPIfL.js";import{f as t,l as n,t as r,u as ee}from"./MainLayout-COiTxmNr.js";import{t as i}from"./book-DwmTvSdZ.js";import{a}from"./square-DZKJ0QGR.js";import{n as o,r as s,t as c}from"./star-DjnKUekI.js";import{t as te}from"./eye-DsLuESBv.js";import{C as ne,D as re,F as l,M as u,O as d,S as f,a as p,b as m,f as ie,j as h,o as ae,t as oe,u as se,w as g}from"./index-yRoRoI6u.js";import{t as ce}from"./GoogleAd-CD0eT9Wp.js";var le=m(`circle-check`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`m9 12 2 2 4-4`,key:`dzmm74`}]]),_=m(`thumbs-up`,[[`path`,{d:`M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z`,key:`emmmcr`}],[`path`,{d:`M7 10v12`,key:`1qc93n`}]]),v=l(h(),1),y=u();function b(){let{bookId:l}=d(),{user:u}=ne(),{t:m,lang:h}=f(),{openInBrowser:b}=oe(),x=re(),[S,C]=(0,v.useState)(null),[ue,w]=(0,v.useState)(!0),[T,E]=(0,v.useState)(``),[D,O]=(0,v.useState)(!1),[k,de]=(0,v.useState)([]),[A,j]=(0,v.useState)(``),[M,N]=(0,v.useState)(!1);(0,v.useEffect)(()=>{D&&u&&g.get(`/api/friends/list`).then(e=>{e.data&&e.data.friends&&de(e.data.friends)}).catch(e=>console.error(`Failed to load friends for sharing`,e))},[D,u]);let P=async e=>{N(!0);try{let t=await g.post(`/api/books/share`,{friend_id:e,book_id:S.id,message:A});t.data&&t.data.success&&(alert(h===`vi`?`Đã chia sẻ thành công!`:`Shared successfully!`),O(!1),j(``))}catch{alert(`Chia sẻ thất bại.`)}finally{N(!1)}},[F,I]=(0,v.useState)(!1),[L,R]=(0,v.useState)(!1),[z,B]=(0,v.useState)([]),[V,H]=(0,v.useState)(!0),[U,W]=(0,v.useState)([{id:1,user:`Lê Hoàng Nam`,avatar:`https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=80&auto=format&fit=crop&q=60`,rating:5,text:`Bản dịch AI của trang này chuẩn thật sự, đọc Hán Việt rất mượt mà. Mong nhóm update chương mới nhanh hơn nữa!`,time:`2 giờ trước`,likes:12},{id:2,user:`Nguyễn Thu Thảo`,avatar:`https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=80&auto=format&fit=crop&q=60`,rating:4,text:`Truyện hay, cốt truyện sát phạt quyết đoán đúng gu mình. Bản dịch máy thỉnh thoảng có vài từ Hán Việt chưa dịch nghĩa kỹ nhưng tổng thể vẫn rất dễ hiểu.`,time:`5 giờ trước`,likes:8},{id:3,user:`Trần Minh Đức`,avatar:`https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=80&auto=format&fit=crop&q=60`,rating:5,text:`So sánh bản dịch Metruyenchu với trang này thì bản ở đây sạch QC hơn nhiều. Giao diện đọc truyện tối ưu tốt trên di động.`,time:`1 ngày trước`,likes:19}]),[G,K]=(0,v.useState)(``),[q,J]=(0,v.useState)(5),[fe,pe]=(0,v.useState)(new Set);(0,v.useEffect)(()=>{me(),he(),ge()},[l,u]);let Y=async e=>{if(!(!u||!e))try{await g.post(`/api/history/add`,{book_id:e.id,last_chapter:h===`vi`?`Đang xem`:h===`en`?`Viewing`:`浏览中`})}catch{}},me=async()=>{w(!0),E(``);try{let e=await g.get(`/api/book/${l}`);e.data&&(C(e.data),Y(e.data))}catch{try{let e=(await g.get(`/api/books`,{params:{q:``,page:1,per_page:100}})).data.books.find(e=>e.id===parseInt(l));if(e)C(e),Y(e);else{let e=await g.get(`/api/book/${l}/translations`);if(e.data){let t={id:parseInt(l),title_vietphrase:e.data.vietphrase.title,title:e.data.hanviet.title,description_vietphrase:e.data.vietphrase.desc,author_hanviet:h===`vi`?`Tác giả`:h===`en`?`Author`:`作者`,cover:``,parsed_sources:[]};C(t),Y(t)}}}catch{E(h===`vi`?`Không tải được thông tin truyện.`:h===`en`?`Failed to load book details.`:`无法加载小说详情。`)}}finally{w(!1)}},X=(()=>{if(!S)return[];let e=[];if(S.parsed_sources&&S.parsed_sources.length>0)S.parsed_sources.forEach(t=>{e.push({site:t.source,url:t.url})});else if(S.urls){let t=S.urls.split(` | `);for(let n of t){let t=n.indexOf(`:`);t>0&&e.push({site:n.substring(0,t).trim(),url:n.substring(t+1).trim()})}}return e})(),he=async()=>{H(!0);try{B(Array.from({length:50},(e,t)=>({id:t+1,title:h===`vi`?`Chương ${t+1}: Tiết tử và khởi nguyên`:h===`en`?`Chapter ${t+1}: Prologue`:`第 ${t+1} 章: 楔子与起源`,url_idx:t+1})))}catch(e){console.error(e)}finally{H(!1)}},ge=async()=>{if(u)try{I((await g.get(`/api/bookshelf`)).data.some(e=>e.book_id===parseInt(l)))}catch(e){console.error(e)}},_e=async()=>{if(!u){alert(h===`vi`?`Vui lòng đăng nhập để lưu sách.`:h===`en`?`Please log in to save books.`:`请先登录以收藏小说。`);return}let e=F?`/api/bookshelf/remove`:`/api/bookshelf/add`;try{await g.post(e,{book_id:parseInt(l)}),I(!F)}catch{alert(h===`vi`?`Lỗi cập nhật tủ sách.`:h===`en`?`Error updating bookshelf.`:`更新书架时出错。`)}},ve=e=>{pe(t=>{let n=new Set(t);return n.has(e)?(n.delete(e),W(U.map(t=>t.id===e?{...t,likes:t.likes-1}:t))):(n.add(e),W(U.map(t=>t.id===e?{...t,likes:t.likes+1}:t))),n})},Z=e=>{e.preventDefault(),G.trim()&&(W([{id:Date.now(),user:u?u.name||u.email.split(`@`)[0]:h===`vi`?`Khách vãng lai`:h===`en`?`Guest user`:`访客`,avatar:`https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=80&auto=format&fit=crop&q=60`,rating:q,text:G,time:h===`vi`?`Vừa xong`:h===`en`?`Just now`:`刚刚`,likes:0},...U]),K(``),J(5))};if(ue)return(0,y.jsx)(r,{children:(0,y.jsxs)(`div`,{className:`py-20 text-center text-slate-500`,children:[(0,y.jsx)(ie,{className:`w-8 h-8 animate-spin mx-auto mb-2 text-brand-500`}),(0,y.jsx)(`span`,{children:h===`vi`?`Đang tải thông tin truyện...`:h===`en`?`Loading book details...`:`正在加载小说信息...`})]})});if(T||!S)return(0,y.jsx)(r,{children:(0,y.jsx)(`div`,{className:`py-20 text-center text-red-500 font-bold`,children:T||(h===`vi`?`Không tìm thấy truyện.`:h===`en`?`Book not found.`:`未找到小说。`)})});let ye=(()=>{if(h===`zh`||h===`en`)return S.title||`—`;let e=S.title_vietphrase||S.title_hanviet;return e&&S.title&&e!==S.title?`${e} (${S.title})`:e||S.title||`—`})(),be=h===`zh`?S.author||`—`:h===`en`?S.author_english||S.author||`—`:S.author_hanviet||S.author||`—`,Q=h===`zh`?S.description||`Chưa có tóm tắt.`:h===`en`?S.description_english||S.description||`No synopsis available.`:S.description_vietphrase||S.description||`Chưa có tóm tắt.`,$=h===`zh`?S.categories||``:h===`en`?S.categories_english||S.categories||``:S.categories_vietphrase||S.categories||``,xe=$?$.split(/[,,/、\s]+/).map(e=>e.trim()).filter(Boolean):[];return(0,y.jsxs)(r,{children:[(0,y.jsxs)(`div`,{className:`relative rounded-3xl overflow-hidden border border-[#1f1f3a] mb-8 bg-[#0b0b14]/70 p-6 md:p-8 flex flex-col md:flex-row gap-6 items-center md:items-start z-0`,children:[S.cover&&(0,y.jsx)(`div`,{className:`absolute inset-0 z-[-1] opacity-15 blur-2xl scale-110 bg-cover bg-center`,style:{backgroundImage:`url(${S.cover})`}}),S.cover?(0,y.jsx)(`img`,{src:S.cover,alt:`cover`,className:`w-[120px] md:w-[150px] h-[165px] md:h-[210px] object-cover rounded-xl border-2 border-[#1f1f3a]/80 shadow-2xl shrink-0`}):(0,y.jsx)(`div`,{className:`w-[120px] md:w-[150px] h-[165px] md:h-[210px] bg-[#121225] border-2 border-[#1f1f3a]/80 rounded-xl flex items-center justify-center text-slate-500 shrink-0`,children:(0,y.jsx)(i,{className:`w-12 h-12`})}),(0,y.jsxs)(`div`,{className:`flex-1 min-w-0 text-center md:text-left space-y-3`,children:[(0,y.jsx)(`h2`,{className:`text-xl md:text-2xl font-black text-white leading-tight`,children:ye}),h===`vi`&&(0,y.jsxs)(`p`,{className:`text-slate-400 text-xs font-semibold`,children:[`Hán Việt: `,S.title_hanviet||`—`,` · Gốc Trung: `,S.title]}),(0,y.jsxs)(`p`,{className:`text-purple-400 text-sm md:text-base font-bold`,children:[`✍ `,h===`vi`?`Tác giả`:h===`en`?`Author`:`作者`,`:`,` `,(0,y.jsx)(`span`,{onClick:()=>{let e=S.author||S.author_hanviet;e&&e!==`—`&&x(`/author/${encodeURIComponent(e)}`)},className:`cursor-pointer hover:underline text-purple-300 font-extrabold hover:text-purple-400 transition-colors`,children:be})]}),(0,y.jsx)(`div`,{className:`flex flex-wrap justify-center md:justify-start gap-2 py-1`,children:xe.map((e,t)=>(0,y.jsx)(`span`,{className:`px-3 py-1 bg-purple-500/10 border border-purple-500/20 text-purple-300 rounded-full text-xs font-semibold`,children:e},t))}),X&&X.length>0&&(0,y.jsxs)(`div`,{className:`flex flex-col gap-1.5 py-1 text-left`,children:[(0,y.jsx)(`span`,{className:`text-slate-500 text-[10px] font-bold block`,children:h===`vi`?`Nguồn gốc:`:`Sources:`}),(0,y.jsx)(`div`,{className:`flex flex-wrap gap-1.5 relative`,children:X.map((e,t)=>{let n=`bg-emerald-500 text-white`;return e.site.toLowerCase().includes(`biquge`)||e.site.toLowerCase().includes(`full`)||e.site.toLowerCase().includes(`truyenfull`)?n=`bg-sky-500 text-white`:e.site.toLowerCase().includes(`faloo`)||e.site.toLowerCase().includes(`vcomi`)||e.site.toLowerCase().includes(`fanqie`)?n=`bg-orange-500 text-white`:(e.site.toLowerCase().includes(`quanben`)||e.site.toLowerCase().includes(`hjwzw`))&&(n=`bg-purple-500 text-white`),(0,y.jsxs)(`a`,{href:e.url,target:`_blank`,rel:`noreferrer`,onClick:t=>{t.preventDefault(),t.stopPropagation(),b(e.url)},className:`inline-flex items-center gap-1 bg-[#0b0b14]/40 border border-[#1f1f3a] hover:border-purple-500/30 rounded px-2 py-1 text-[10px] text-slate-300 hover:text-white transition-all hover:scale-[1.02]`,title:e.url,children:[(0,y.jsx)(`span`,{className:`w-3.5 h-3.5 rounded flex items-center justify-center text-[9px] font-extrabold ${n}`,children:e.site[0]}),e.site]},t)})})]}),(0,y.jsxs)(`div`,{className:`flex flex-wrap justify-center md:justify-start gap-3 pt-3`,children:[(0,y.jsxs)(`button`,{onClick:()=>x(`/book/${S.id}/read/1`),className:`inline-flex items-center gap-1.5 bg-gradient-to-r from-purple-500 to-indigo-600 text-white px-6 py-3 rounded-xl text-xs font-bold shadow-lg shadow-purple-500/20 hover:brightness-105 active:scale-95 transition-all`,children:[(0,y.jsx)(se,{className:`w-4 h-4 fill-current`}),` `,h===`vi`?`Bắt đầu đọc`:h===`en`?`Start Reading`:`开始阅读`]}),(0,y.jsxs)(`button`,{onClick:_e,className:`inline-flex items-center gap-1.5 px-6 py-3 rounded-xl text-xs font-bold transition-all border ${F?`bg-amber-400 border-amber-400 text-[#0b0b14]`:`bg-white/5 border-white/10 hover:bg-white/10 text-slate-300`}`,children:[(0,y.jsx)(c,{className:`w-4 h-4 fill-current`}),F?h===`vi`?`Đã lưu vào tủ`:h===`en`?`Saved in Shelf`:`已收藏`:h===`vi`?`Thêm vào tủ`:h===`en`?`Save to Shelf`:`收藏`]}),X&&X.length>0&&(0,y.jsxs)(`a`,{href:X[0].url,target:`_blank`,rel:`noopener noreferrer`,onClick:e=>{e.preventDefault(),b(X[0].url)},className:`inline-flex items-center gap-1.5 px-6 py-3 bg-[#0b0b14]/50 border border-purple-500/30 hover:bg-purple-500/10 text-purple-300 rounded-xl text-xs font-bold transition-all hover:scale-[1.02]`,children:[(0,y.jsx)(a,{className:`w-4 h-4`}),h===`vi`?`Trang gốc (Web thật)`:`Source Web`]}),u&&(0,y.jsxs)(`button`,{onClick:()=>O(!0),className:`inline-flex items-center gap-1.5 px-6 py-3 bg-purple-600/20 border border-purple-500/30 hover:bg-purple-600/30 text-purple-200 rounded-xl text-xs font-bold transition-all hover:scale-[1.02]`,children:[(0,y.jsx)(n,{className:`w-4 h-4`}),h===`vi`?`Chia sẻ với bạn bè`:`Share with Friends`]})]})]})]}),(0,y.jsxs)(`div`,{className:`grid grid-cols-1 lg:grid-cols-3 gap-8 items-start`,children:[(0,y.jsxs)(`div`,{className:`lg:col-span-2 space-y-8`,children:[(0,y.jsxs)(`div`,{className:`bg-[#121225]/60 border border-[#1f1f3a] rounded-3xl p-6`,children:[(0,y.jsx)(`h3`,{className:`text-base font-extrabold text-white mb-3`,children:`Tóm tắt nội dung`}),(0,y.jsxs)(`div`,{className:`text-slate-300 text-xs leading-relaxed space-y-2 relative`,children:[(0,y.jsx)(`p`,{className:L?``:`line-clamp-4`,children:Q}),Q&&(0,y.jsx)(`button`,{onClick:()=>R(!L),className:`mt-2 text-purple-400 font-bold inline-flex items-center gap-1 text-[11px] hover:underline`,children:L?(0,y.jsxs)(y.Fragment,{children:[`Thu gọn `,(0,y.jsx)(o,{className:`w-3.5 h-3.5`})]}):(0,y.jsxs)(y.Fragment,{children:[`Xem thêm `,(0,y.jsx)(s,{className:`w-3.5 h-3.5`})]})})]})]}),(0,y.jsxs)(`div`,{className:`bg-[#121225]/60 border border-[#1f1f3a] rounded-3xl p-6`,children:[(0,y.jsx)(`h3`,{className:`text-base font-extrabold text-white mb-4`,children:`Danh sách chương`}),V?(0,y.jsx)(`div`,{className:`text-center text-slate-500 py-6`,children:`Đang tải danh sách chương...`}):(0,y.jsx)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 gap-3 max-h-[380px] overflow-y-auto pr-1 custom-scrollbar`,children:z.map(e=>(0,y.jsx)(`button`,{onClick:()=>x(`/book/${S.id}/read/${e.url_idx}`),className:`text-left px-4 py-3 bg-[#0b0b14]/50 hover:bg-purple-500/10 border border-[#1f1f3a] hover:border-purple-500/30 rounded-xl text-xs text-slate-300 hover:text-purple-300 transition-all truncate`,children:e.title},e.id))})]}),(0,y.jsx)(ce,{slot:`book-detail-bottom`}),(0,y.jsxs)(`div`,{className:`bg-[#121225]/60 border border-[#1f1f3a] rounded-3xl p-6 space-y-6`,children:[(0,y.jsxs)(`div`,{className:`flex justify-between items-center border-b border-[#1f1f3a]/60 pb-4`,children:[(0,y.jsxs)(`h3`,{className:`text-base font-extrabold text-white flex items-center gap-2`,children:[(0,y.jsx)(t,{className:`w-4.5 h-4.5 text-purple-400`}),` Bình luận & Đánh giá (`,U.length,`)`]}),(0,y.jsxs)(`div`,{className:`flex items-center gap-1.5`,children:[(0,y.jsx)(`span`,{className:`text-amber-400 font-bold text-sm`,children:`⭐ 4.8`}),(0,y.jsx)(`span`,{className:`text-slate-500 text-[11px]`,children:`(145 bình chọn)`})]})]}),(0,y.jsxs)(`form`,{onSubmit:Z,className:`bg-[#0b0b14]/40 border border-[#1f1f3a] p-4 rounded-2xl space-y-3`,children:[(0,y.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,y.jsx)(`span`,{className:`text-xs text-slate-400 font-semibold`,children:`Viết nhận xét của bạn:`}),(0,y.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,y.jsx)(`span`,{className:`text-[11px] text-slate-500 mr-1`,children:`Đánh giá sao:`}),[1,2,3,4,5].map(e=>(0,y.jsx)(`button`,{type:`button`,onClick:()=>J(e),className:`text-sm transition-colors ${e<=q?`text-amber-400`:`text-slate-600 hover:text-slate-500`}`,children:`★`},e))]})]}),(0,y.jsx)(`div`,{className:`relative`,children:(0,y.jsx)(`textarea`,{value:G,onChange:e=>K(e.target.value),placeholder:`Nhập cảm nhận của bạn về bản dịch, cốt truyện...`,rows:`3`,className:`w-full bg-[#121225] border border-[#1f1f3a] rounded-xl px-4 py-3 text-white text-xs outline-none focus:border-purple-500/50 transition-colors resize-none placeholder-slate-600`})}),(0,y.jsx)(`div`,{className:`flex justify-end`,children:(0,y.jsxs)(`button`,{type:`submit`,disabled:!G.trim(),className:`inline-flex items-center gap-1.5 bg-purple-600 hover:bg-purple-500 disabled:bg-purple-600/30 text-white px-4 py-2 rounded-xl text-xs font-bold transition-all`,children:[(0,y.jsx)(ee,{className:`w-3.5 h-3.5`}),` Gửi bình luận`]})})]}),(0,y.jsx)(`div`,{className:`space-y-4`,children:U.map(e=>(0,y.jsxs)(`div`,{className:`border-b border-[#1f1f3a]/40 pb-4 last:border-b-0 last:pb-0 flex gap-3.5`,children:[(0,y.jsx)(`img`,{src:e.avatar,alt:e.user,className:`w-9 h-9 rounded-full object-cover border border-[#2d2d55] bg-[#0f0f1a] shrink-0`}),(0,y.jsxs)(`div`,{className:`flex-1 space-y-1.5`,children:[(0,y.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,y.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,y.jsx)(`span`,{className:`text-xs font-bold text-slate-100`,children:e.user}),(0,y.jsx)(`div`,{className:`flex text-amber-400 text-[10px]`,children:Array.from({length:5},(t,n)=>(0,y.jsx)(`span`,{children:nve(e.id),className:`inline-flex items-center gap-1 text-[10px] font-semibold transition-colors ${fe.has(e.id)?`text-purple-400`:`text-slate-500 hover:text-slate-400`}`,children:[(0,y.jsx)(_,{className:`w-3 h-3`}),` Hữu ích (`,e.likes,`)`]})})]})]},e.id))})]})]}),(0,y.jsxs)(`div`,{className:`space-y-6`,children:[(0,y.jsxs)(`div`,{className:`bg-[#121225]/60 border border-[#1f1f3a] rounded-3xl p-6 space-y-5`,children:[(0,y.jsxs)(`h3`,{className:`text-sm font-extrabold text-white border-b border-[#1f1f3a] pb-2.5 flex items-center gap-2`,children:[(0,y.jsx)(e,{className:`w-4 h-4 text-purple-400`}),` Thống kê & Chi tiết`]}),(0,y.jsxs)(`div`,{className:`space-y-3.5`,children:[(0,y.jsxs)(`div`,{className:`flex items-center justify-between text-xs`,children:[(0,y.jsxs)(`span`,{className:`text-slate-500 flex items-center gap-1.5`,children:[(0,y.jsx)(le,{className:`w-3.5 h-3.5 text-purple-400`}),` Trạng thái:`]}),(0,y.jsx)(`span`,{className:`text-emerald-400 font-bold`,children:`Đang cập nhật`})]}),(0,y.jsxs)(`div`,{className:`flex items-center justify-between text-xs`,children:[(0,y.jsxs)(`span`,{className:`text-slate-500 flex items-center gap-1.5`,children:[(0,y.jsx)(te,{className:`w-3.5 h-3.5 text-purple-400`}),` Tổng lượt xem:`]}),(0,y.jsx)(`span`,{className:`text-slate-200 font-bold`,children:S.word_count_max?Math.round(S.word_count_max*1.5).toLocaleString():`340,500`})]}),(0,y.jsxs)(`div`,{className:`flex items-center justify-between text-xs`,children:[(0,y.jsxs)(`span`,{className:`text-slate-500 flex items-center gap-1.5`,children:[(0,y.jsx)(p,{className:`w-3.5 h-3.5 text-purple-400`}),` Tốc độ ra chương:`]}),(0,y.jsx)(`span`,{className:`text-slate-200 font-bold`,children:`~12 chương / ngày`})]}),(0,y.jsxs)(`div`,{className:`flex items-center justify-between text-xs`,children:[(0,y.jsxs)(`span`,{className:`text-slate-500 flex items-center gap-1.5`,children:[(0,y.jsx)(c,{className:`w-3.5 h-3.5 text-purple-400`}),` Độ tin cậy nguồn:`]}),(0,y.jsx)(`span`,{className:`text-indigo-400 font-bold`,children:`99.1% (Sạch QC)`})]}),(0,y.jsxs)(`div`,{className:`flex flex-col gap-2 pt-2 border-t border-[#1f1f3a]/30`,children:[(0,y.jsxs)(`span`,{className:`text-slate-500 text-xs flex items-center gap-1.5`,children:[(0,y.jsx)(i,{className:`w-3.5 h-3.5 text-purple-400`}),` Đọc ở trang gốc (Web thật):`]}),(0,y.jsx)(`div`,{className:`flex flex-wrap gap-1.5 pt-1`,children:X&&X.length>0?X.map((e,t)=>{let n=`bg-emerald-500 text-white`;return e.site.toLowerCase().includes(`biquge`)||e.site.toLowerCase().includes(`full`)||e.site.toLowerCase().includes(`truyenfull`)?n=`bg-sky-500 text-white`:e.site.toLowerCase().includes(`faloo`)||e.site.toLowerCase().includes(`vcomi`)||e.site.toLowerCase().includes(`fanqie`)?n=`bg-orange-500 text-white`:(e.site.toLowerCase().includes(`quanben`)||e.site.toLowerCase().includes(`hjwzw`))&&(n=`bg-purple-500 text-white`),(0,y.jsxs)(`a`,{href:e.url,target:`_blank`,rel:`noopener noreferrer`,onClick:t=>{t.preventDefault(),b(e.url)},className:`inline-flex items-center gap-1 bg-[#0b0b14]/50 border border-[#1f1f3a] hover:border-purple-500/40 rounded px-2 py-1 text-[10px] text-slate-300 hover:text-purple-300 transition-all hover:scale-[1.02]`,title:e.url,children:[(0,y.jsx)(`span`,{className:`w-3.5 h-3.5 rounded flex items-center justify-center text-[9px] font-black ${n}`,children:e.site[0]}),e.site,(0,y.jsx)(a,{className:`w-2.5 h-2.5 text-slate-500`})]},t)}):(0,y.jsx)(`span`,{className:`text-slate-500 italic text-[11px]`,children:`Metruyenchu, Biquge (Không tìm thấy link)`})})]})]})]}),(0,y.jsxs)(`div`,{className:`bg-gradient-to-br from-purple-900/35 to-indigo-950/40 border border-purple-500/20 rounded-3xl p-6 text-center space-y-3.5`,children:[(0,y.jsx)(`div`,{className:`w-10 h-10 rounded-2xl bg-purple-500/10 border border-purple-500/25 flex items-center justify-center mx-auto text-purple-400`,children:(0,y.jsx)(p,{className:`w-5 h-5 fill-current animate-pulse`})}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`h4`,{className:`text-xs font-black text-white`,children:`Dịch thuật bởi Antigravity AI`}),(0,y.jsx)(`p`,{className:`text-[10px] text-slate-400 mt-1 leading-relaxed`,children:`Ứng dụng bộ dịch thuật mạng nơ-ron nâng cao giúp chuyển ngữ chính xác ngữ cảnh Hán Việt sang Việt ngữ.`})]})]})]})]}),D&&(0,y.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm`,children:(0,y.jsxs)(`div`,{className:`bg-[#0c0d1e] border border-purple-500/35 rounded-3xl p-6 w-full max-w-sm text-slate-100 shadow-2xl relative animate-fadeIn`,children:[(0,y.jsx)(`button`,{onClick:()=>{O(!1),j(``)},className:`absolute top-4 right-4 p-1 hover:bg-white/5 rounded-lg text-slate-400 hover:text-white transition-all`,children:(0,y.jsx)(ae,{className:`w-4 h-4`})}),(0,y.jsx)(`h3`,{className:`font-extrabold text-sm tracking-wider uppercase mb-4 text-purple-300`,children:`Chia sẻ truyện`}),(0,y.jsxs)(`div`,{className:`space-y-3`,children:[(0,y.jsx)(`label`,{className:`block text-[10px] uppercase font-black tracking-widest text-slate-500`,children:`Lời nhắn kèm theo`}),(0,y.jsx)(`input`,{type:`text`,placeholder:`Ví dụ: Truyện này hay lắm, đọc đi!`,value:A,onChange:e=>j(e.target.value),className:`w-full px-3 py-2 bg-[#080814] border border-purple-500/20 rounded-xl text-xs text-white outline-none focus:border-purple-500 transition-colors`})]}),(0,y.jsxs)(`div`,{className:`space-y-2 mt-4`,children:[(0,y.jsx)(`label`,{className:`block text-[10px] uppercase font-black tracking-widest text-slate-500 mb-1`,children:`Chọn bạn bè`}),k.length===0?(0,y.jsx)(`div`,{className:`text-center py-6 border border-dashed border-purple-500/10 rounded-2xl text-xs text-slate-500`,children:`Chưa có bạn bè nào. Vui lòng kết bạn trước.`}):(0,y.jsx)(`div`,{className:`max-h-[200px] overflow-y-auto space-y-2 pr-1 custom-scrollbar`,children:k.map(e=>(0,y.jsxs)(`div`,{className:`flex items-center justify-between p-2 hover:bg-purple-950/20 border border-purple-500/10 rounded-xl`,children:[(0,y.jsx)(`span`,{className:`text-xs font-bold text-slate-200`,children:e.username}),(0,y.jsx)(`button`,{onClick:()=>P(e.id),disabled:M,className:`px-3 py-1 bg-purple-600 hover:bg-purple-500 text-white rounded-lg text-[10px] font-bold transition-colors disabled:opacity-50`,children:`Gửi`})]},e.id))})]})]})})]})}export{b as default}; \ No newline at end of file diff --git a/frontend-web/dist/assets/Bookshelf-ClI6d9JY.js b/frontend-web/dist/assets/Bookshelf-ClI6d9JY.js new file mode 100644 index 0000000000000000000000000000000000000000..5ea7d986194e383a686d568fe2a464d6c1e25b05 --- /dev/null +++ b/frontend-web/dist/assets/Bookshelf-ClI6d9JY.js @@ -0,0 +1 @@ +import{t as e}from"./MainLayout-COiTxmNr.js";import{n as t,t as n}from"./square-DZKJ0QGR.js";import{t as r}from"./BookCard-BCMDdlyN.js";import{t as i}from"./square-check-big-BhcFiAg6.js";import{t as a}from"./trash-2-DDhTqVwA.js";import{C as o,D as s,F as c,M as l,S as u,f as d,j as f,t as p,w as m,y as h}from"./index-yRoRoI6u.js";var g=c(f(),1),_=l();function v(){let{t:c,lang:l}=u(),{user:f,loading:v}=o(),y=s(),[b,x]=(0,g.useState)([]),[S,C]=(0,g.useState)(``),[w,T]=(0,g.useState)(!0),[E,D]=(0,g.useState)(!1),[O,k]=(0,g.useState)(new Set),{activeAudioObj:A,setActiveAudioObj:j}=p(),[M,N]=(0,g.useState)(null),[P,F]=(0,g.useState)(null),[I,L]=(0,g.useState)(!1);(0,g.useEffect)(()=>{if(!v){if(!f){T(!1);return}R()}},[f,v,S]);let R=async()=>{T(!0);try{let e=S?{q:S}:{};x((await m.get(`/api/bookshelf`,{params:e})).data.map(e=>({id:e.book_id||e.url,title_vietphrase:e.title,author_hanviet:e.author,cover:e.cover,url:e.url,site_count:1})))}catch(e){console.error(e)}finally{T(!1)}},z=e=>{k(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},B=()=>{O.size===b.length?k(new Set):k(new Set(b.map(e=>e.id).filter(Boolean)))},V=async()=>{if(window.confirm(l===`vi`?`Bạn có chắc chắn muốn xóa ${O.size} truyện đã chọn khỏi tủ sách cá nhân không?`:l===`en`?`Are you sure you want to remove ${O.size} selected novels from bookshelf?`:`您确定要从书架中移出选中的 ${O.size} 部小说吗?`)){T(!0);try{await Promise.all(Array.from(O).map(e=>typeof e==`string`&&(e.startsWith(`http://`)||e.startsWith(`https://`))?m.post(`/api/bookshelf/remove`,{url:e}):m.post(`/api/bookshelf/remove`,{book_id:e}))),k(new Set),D(!1),await R()}catch{alert(l===`vi`?`Không xóa được sách hàng loạt.`:`Failed to perform bulk remove.`)}finally{T(!0),await R()}}},H=async e=>{if(window.confirm(l===`vi`?`Bạn có chắc chắn muốn xóa truyện này khỏi tủ sách cá nhân không?`:l===`en`?`Are you sure you want to remove this novel from your personal bookshelf?`:`您确定要从个人书架中移出这部小说吗?`))try{typeof e==`string`&&(e.startsWith(`http://`)||e.startsWith(`https://`))?await m.post(`/api/bookshelf/remove`,{url:e}):await m.post(`/api/bookshelf/remove`,{book_id:e}),x(t=>t.filter(t=>t.id!==e))}catch{alert(l===`vi`?`Không xóa được sách.`:l===`en`?`Failed to remove novel.`:`无法移出书架。`)}},U=e=>{y(`/?search_field=author&q=${encodeURIComponent(e)}`)},W=e=>{y(`/?category=${encodeURIComponent(e)}`)},G=e=>{e.id&&y(`/book/${e.id}`)},K=async e=>{if(M===e){N(null),F(null);return}N(e),L(!0);try{F((await m.get(`/api/book/${e}/translations`)).data)}catch(e){console.error(e)}finally{L(!1)}},q=async e=>{if(e.description)j(e);else try{let t=await m.get(`/api/book/${e.id}/translations`);if(t.data){let n=t.data.advanced?.desc||t.data.fast?.desc||t.data.vietphrase?.desc||``;j({...e,description:n})}else j(e)}catch{j(e)}};return v?(0,_.jsx)(e,{children:(0,_.jsxs)(`div`,{className:`py-20 text-center text-slate-500`,children:[(0,_.jsx)(d,{className:`w-8 h-8 animate-spin mx-auto mb-2 text-brand-500`}),(0,_.jsx)(`span`,{children:l===`vi`?`Đang tải thông tin...`:l===`en`?`Loading info...`:`正在加载信息...`})]})}):f?(0,_.jsxs)(e,{children:[(0,_.jsxs)(`div`,{className:`flex flex-col md:flex-row md:items-center justify-between gap-4 mb-6`,children:[(0,_.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3`,children:[(0,_.jsxs)(`h2`,{className:`text-xl font-bold flex items-center gap-2`,children:[(0,_.jsx)(h,{className:`w-6 h-6 text-brand-400`}),l===`vi`?`Tủ Sách Cá Nhân`:l===`en`?`Personal Bookshelf`:`个人书架`,` (`,b.length,`)`]}),b.length>0&&(0,_.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,_.jsx)(`button`,{onClick:()=>{D(!E),k(new Set)},className:`px-3 py-1.5 rounded-lg text-xs font-bold transition-all border ${E?`bg-purple-600/25 border-purple-500/50 text-purple-300 hover:bg-purple-600/35`:`bg-white/5 border-white/10 text-slate-300 hover:bg-white/10`}`,children:E?l===`vi`?`Thoát quản lý`:`Exit management`:l===`vi`?`Quản lý tủ sách`:`Manage bookshelf`}),E&&(0,_.jsxs)(_.Fragment,{children:[(0,_.jsx)(`button`,{onClick:B,className:`px-3 py-1.5 bg-[#121225] border border-[#1f1f3a] rounded-lg text-xs font-bold text-slate-300 hover:bg-[#1a1a35] transition-all`,children:O.size===b.length?l===`vi`?`Hủy chọn tất cả`:`Deselect all`:l===`vi`?`Chọn tất cả`:`Select all`}),O.size>0&&(0,_.jsxs)(`button`,{onClick:V,className:`inline-flex items-center gap-1.5 px-3 py-1.5 bg-rose-600 hover:bg-rose-500 text-white rounded-lg text-xs font-bold shadow-lg shadow-rose-950/20 transition-all active:scale-95 cursor-pointer`,children:[(0,_.jsx)(a,{className:`w-3.5 h-3.5`}),l===`vi`?`Xóa hàng loạt (${O.size})`:`Bulk Delete (${O.size})`]})]})]})]}),(0,_.jsxs)(`div`,{className:`relative w-full md:w-72`,children:[(0,_.jsx)(t,{className:`absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-500`}),(0,_.jsx)(`input`,{type:`text`,placeholder:l===`vi`?`Tìm trong tủ sách...`:l===`en`?`Search bookshelf...`:`在书架中搜索...`,value:S,onChange:e=>C(e.target.value),className:`w-full pl-9 pr-4 py-2.5 bg-[#121225] border border-[#1f1f3a] rounded-xl text-white outline-none focus:border-brand-500 transition-colors text-xs`})]})]}),w?(0,_.jsxs)(`div`,{className:`py-20 text-center text-slate-500`,children:[(0,_.jsx)(d,{className:`w-6 h-6 animate-spin mx-auto mb-2`}),(0,_.jsx)(`span`,{children:c.loading})]}):b.length===0?(0,_.jsxs)(`div`,{className:`py-20 text-center text-slate-500 bg-[#121225]/40 border border-dashed border-[#1f1f3a] rounded-2xl`,children:[(0,_.jsx)(h,{className:`w-10 h-10 mx-auto mb-3 text-slate-600`}),(0,_.jsx)(`p`,{className:`text-sm`,children:l===`vi`?`Tủ sách trống. Hãy thêm truyện từ tab Khám Phá!`:l===`en`?`Bookshelf is empty. Add novels from Discover tab!`:`书架空空如也。请从“发现”选项卡中添加小说!`})]}):(0,_.jsx)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-3 sm:gap-4`,children:b.map(e=>{let t=O.has(e.id);return(0,_.jsxs)(`div`,{className:`flex flex-col relative group`,children:[E&&(0,_.jsx)(`div`,{onClick:()=>z(e.id),className:`absolute top-3 left-3 z-30 w-7 h-7 rounded-lg border flex items-center justify-center cursor-pointer transition-all shadow-md ${t?`bg-purple-600 border-purple-500 text-white shadow-purple-500/20`:`bg-[#0f101f]/95 border-slate-700/80 text-slate-500 hover:bg-purple-950/25 hover:border-purple-500/50`}`,children:t?(0,_.jsx)(i,{className:`w-4.5 h-4.5`}):(0,_.jsx)(n,{className:`w-4.5 h-4.5`})}),(0,_.jsx)(`div`,{className:E?`opacity-70 transition-opacity`:``,children:(0,_.jsx)(r,{book:e,isFav:!0,onToggleFav:H,onRead:G,onCompare:K,onPlayTrailer:q,onSearchAuthor:U,onSearchCategory:W})}),M===e.id&&(0,_.jsx)(`div`,{className:`bg-[#0f101f] border border-[#1f1f3a] rounded-b-2xl p-4 text-xs mt-[-10px] space-y-4 shadow-inner`,children:I?(0,_.jsx)(`div`,{className:`text-center text-slate-500 py-3`,children:c.comparingText}):P?(0,_.jsxs)(_.Fragment,{children:[(0,_.jsxs)(`div`,{className:`pb-2 border-b border-white/5`,children:[(0,_.jsx)(`span`,{className:`text-[10px] text-brand-400 font-extrabold uppercase`,children:c.compFast}),(0,_.jsx)(`div`,{className:`text-white font-bold mt-0.5`,children:P.fast.title||`—`}),(0,_.jsx)(`p`,{className:`text-slate-400 text-[11px] leading-relaxed mt-1`,children:P.fast.desc||`—`})]}),(0,_.jsxs)(`div`,{className:`pb-2 border-b border-white/5`,children:[(0,_.jsx)(`span`,{className:`text-[10px] text-amber-400 font-extrabold uppercase`,children:c.compAdvanced}),(0,_.jsx)(`div`,{className:`text-white font-bold mt-0.5`,children:P.advanced.title||`—`}),(0,_.jsx)(`p`,{className:`text-slate-400 text-[11px] leading-relaxed mt-1`,children:P.advanced.desc||`—`})]}),(0,_.jsxs)(`div`,{className:`pb-2 border-b border-white/5`,children:[(0,_.jsx)(`span`,{className:`text-[10px] text-emerald-400 font-extrabold uppercase`,children:c.compVietphrase}),(0,_.jsx)(`div`,{className:`text-white font-bold mt-0.5`,children:P.vietphrase.title||`—`}),(0,_.jsx)(`p`,{className:`text-slate-400 text-[11px] leading-relaxed mt-1`,children:P.vietphrase.desc||`—`})]}),(0,_.jsxs)(`div`,{children:[(0,_.jsx)(`span`,{className:`text-[10px] text-indigo-400 font-extrabold uppercase`,children:c.compHanviet}),(0,_.jsx)(`div`,{className:`text-white font-bold mt-0.5`,children:P.hanviet.title||`—`}),(0,_.jsx)(`p`,{className:`text-slate-400 text-[11px] leading-relaxed mt-1`,children:P.hanviet.desc||`—`})]})]}):(0,_.jsx)(`div`,{className:`text-center text-red-500 py-3`,children:c.compError})})]},e.id||e.url)})})]}):(0,_.jsx)(e,{children:(0,_.jsxs)(`div`,{className:`py-20 text-center text-slate-500`,children:[(0,_.jsx)(`div`,{className:`w-12 h-12 rounded-2xl bg-white/5 border border-white/10 flex items-center justify-center text-slate-400 mx-auto mb-4`,children:`🔒`}),(0,_.jsx)(`p`,{className:`text-sm`,children:c.loginToViewBookshelf})]})})}export{v as default}; \ No newline at end of file diff --git a/frontend-web/dist/assets/Developer-BFnP9Lg5.js b/frontend-web/dist/assets/Developer-BFnP9Lg5.js new file mode 100644 index 0000000000000000000000000000000000000000..573d3a62159c6ef89e351630cd218a507e992ff9 --- /dev/null +++ b/frontend-web/dist/assets/Developer-BFnP9Lg5.js @@ -0,0 +1,11 @@ +import{t as e}from"./award-CKCOPIfL.js";import{d as t,n,s as r,t as i,u as ee}from"./MainLayout-COiTxmNr.js";import{o as a}from"./square-DZKJ0QGR.js";import{t as o}from"./plus-CSQqtn3N.js";import{t as s}from"./trash-2-DDhTqVwA.js";import{C as c,F as l,M as u,S as d,d as f,g as p,j as m,p as h,u as te,w as g}from"./index-yRoRoI6u.js";var _=l(m(),1),v=u();function y(){let{user:l}=c(),{t:u,lang:m}=d(),[y,b]=(0,_.useState)([]),[x,S]=(0,_.useState)(!1),[ne,C]=(0,_.useState)(0),[w,T]=(0,_.useState)(``),[E,D]=(0,_.useState)(!1),[O,k]=(0,_.useState)(!1),[re,A]=(0,_.useState)(``),[j,ie]=(0,_.useState)([]),[ae,M]=(0,_.useState)(!1),[N,P]=(0,_.useState)(``),[F,I]=(0,_.useState)(`武之极,破苍穹,动乾坤!Trong thế giới này, kẻ mạnh làm chủ.`),[L,R]=(0,_.useState)(1),[z,B]=(0,_.useState)(!1),[V,H]=(0,_.useState)(!1),U=(0,_.useRef)(null),[W,G]=(0,_.useState)(`第1章 开封神殿 +杨开迈步走入神殿。`),[K,q]=(0,_.useState)(`fast`),[J,Y]=(0,_.useState)(``),[X,Z]=(0,_.useState)(!1);(0,_.useEffect)(()=>{l&&Promise.all([Q(),oe()])},[l]);let Q=async()=>{D(!0);try{let e=await g.get(`/api/developer/keys`);b(e.data.keys||[]),C(e.data.balance||0),e.data.keys&&e.data.keys.length>0&&P(e.data.keys[0].api_key)}catch(e){console.error(e)}finally{D(!1)}},oe=async()=>{M(!0);try{ie((await g.get(`/api/developer/usage`)).data.usage||[])}catch(e){console.error(e)}finally{M(!1)}},se=async e=>{if(e.preventDefault(),w.trim()){k(!0);try{await g.post(`/api/developer/keys/create`,{name:w}),T(``),Q()}catch{alert(u.developer?.createError||`Lỗi khi tạo API Key.`)}finally{k(!1)}}},ce=async e=>{if(window.confirm(u.developer?.revokeConfirm||`Bạn có chắc chắn muốn thu hồi khóa API này? Tất cả các ứng dụng đang sử dụng nó sẽ bị ngắt kết nối.`))try{await g.post(`/api/developer/keys/delete`,{api_key:e}),Q()}catch{alert(u.developer?.revokeError||`Lỗi khi thu hồi API Key.`)}},le=e=>{navigator.clipboard.writeText(e),A(e),setTimeout(()=>A(``),2e3)},ue=async()=>{if(!N){alert(u.developer?.keyNameRequired||`Vui lòng tạo hoặc chọn một API Key trước.`);return}H(!0),B(!1),U.current&&=(U.current.pause(),null);try{let e=await g.post(`/v1/audio/speech`,{input:F,speed:L},{responseType:`blob`,headers:{Authorization:`Bearer ${N}`}}),t=URL.createObjectURL(e.data),n=new Audio(t);U.current=n,n.playbackRate=L,n.onplay=()=>{n.playbackRate=L},n.onplaying=()=>{n.playbackRate=L},n.play().then(()=>{n.playbackRate=L}).catch(e=>console.error(`Sandbox playback failed:`,e)),B(!0),n.onended=()=>B(!1)}catch{alert(u.reader?.ttsError||`Lỗi phát âm thanh. Vui lòng thử lại sau.`)}finally{H(!1)}},de=async()=>{if(!N){alert(u.developer?.keyNameRequired||`Vui lòng tạo hoặc chọn một API Key trước.`);return}Z(!0),Y(``);try{let e=await g.post(`/api/v1/translate`,{texts:W.split(` +`),mode:K},{headers:{Authorization:`Bearer ${N}`}});e.data&&e.data.translations&&Y(e.data.translations.join(` +`))}catch{alert(u.reader?.errorLoadingChapter||`Lỗi tải nội dung.`)}finally{Z(!1)}},$=e=>{let t=Number(e);return isNaN(t)?`0 ₫`:new Intl.NumberFormat(`vi-VN`,{style:`currency`,currency:`VND`}).format(t)};return l?(0,v.jsxs)(i,{children:[(0,v.jsxs)(`div`,{className:`space-y-8`,children:[(0,v.jsxs)(`div`,{className:`bg-[#121225]/60 border border-[#1f1f3a] rounded-3xl p-6 md:p-8 flex flex-col md:flex-row justify-between items-start md:items-center gap-4`,children:[(0,v.jsxs)(`div`,{className:`space-y-1`,children:[(0,v.jsxs)(`h2`,{className:`text-xl md:text-2xl font-black text-white flex items-center gap-2`,children:[(0,v.jsx)(r,{className:`text-purple-400 w-6 h-6`}),` `,u.developer?.title||`Developer API & TTS Console`]}),(0,v.jsx)(`p`,{className:`text-xs text-slate-400`,children:u.developer?.subtitle||`Quản lý API Key, giám sát số dư và kiểm thử dịch thuật/TTS thời gian thực.`})]}),(0,v.jsxs)(`div`,{className:`flex items-center gap-3 w-full md:w-auto`,children:[(0,v.jsxs)(`div`,{className:`bg-[#0b0b14]/80 border border-purple-500/25 px-5 py-3 rounded-2xl text-right flex-1 md:flex-initial`,children:[(0,v.jsx)(`span`,{className:`text-[9px] text-slate-500 block uppercase font-extrabold tracking-wider`,children:u.developer?.balance||`Số dư API Developer`}),(0,v.jsx)(`strong`,{className:`text-base text-emerald-400 font-extrabold block mt-0.5`,children:$(ne)})]}),(0,v.jsxs)(`button`,{onClick:()=>S(!0),className:`bg-gradient-to-r from-amber-400 to-amber-500 hover:brightness-105 text-[#0b0b14] font-extrabold px-5 py-4 rounded-2xl text-xs transition-all shadow-lg shadow-amber-500/10 whitespace-nowrap active:scale-95`,children:[`⚡ `,m===`zh`?`充值 / 购买 VIP`:m===`en`?`Deposit / Buy VIP`:`Nạp số dư / Mua VIP`]})]})]}),(0,v.jsxs)(`div`,{className:`grid grid-cols-1 lg:grid-cols-3 gap-6`,children:[(0,v.jsxs)(`div`,{className:`lg:col-span-2 space-y-6`,children:[(0,v.jsxs)(`div`,{className:`bg-[#121225]/60 border border-[#1f1f3a] rounded-3xl p-6 space-y-4`,children:[(0,v.jsx)(`div`,{className:`flex justify-between items-center pb-2 border-b border-[#1f1f3a]/50`,children:(0,v.jsxs)(`h3`,{className:`text-sm font-extrabold text-white flex items-center gap-2`,children:[(0,v.jsx)(h,{className:`w-4 h-4 text-purple-400`}),` `,u.developer?.apiKeyListTitle||`Danh sách khóa API Key`]})}),E?(0,v.jsxs)(`div`,{className:`text-center py-6 text-slate-500 text-xs`,children:[(0,v.jsx)(t,{className:`w-5 h-5 animate-spin mx-auto mb-2 text-purple-500`}),u.developer?.creating||`Đang tải...`]}):y.length===0?(0,v.jsx)(`p`,{className:`text-slate-500 text-xs text-center py-6`,children:m===`zh`?`您尚未创建任何 API Key。`:m===`en`?`You have not created any API Keys yet.`:`Bạn chưa tạo khóa API nào.`}):(0,v.jsx)(`div`,{className:`overflow-x-auto`,children:(0,v.jsxs)(`table`,{className:`w-full text-left text-xs text-slate-300`,children:[(0,v.jsx)(`thead`,{children:(0,v.jsxs)(`tr`,{className:`border-b border-[#1f1f3a] text-slate-500`,children:[(0,v.jsx)(`th`,{className:`pb-2`,children:u.developer?.keyNameLabel||`Tên khóa`}),(0,v.jsx)(`th`,{className:`pb-2`,children:`Khóa API`}),(0,v.jsx)(`th`,{className:`pb-2`,children:u.developer?.createdLabel||`Ngày tạo`}),(0,v.jsx)(`th`,{className:`pb-2 text-center`,children:m===`zh`?`操作`:m===`en`?`Actions`:`Hành động`})]})}),(0,v.jsx)(`tbody`,{className:`divide-y divide-[#1f1f3a]/30`,children:y.map((e,t)=>(0,v.jsxs)(`tr`,{className:`hover:bg-white/[0.02]`,children:[(0,v.jsx)(`td`,{className:`py-3 font-semibold text-white`,children:e.name}),(0,v.jsxs)(`td`,{className:`py-3 font-mono text-purple-300`,children:[e.api_key.slice(0,10),`...`,e.api_key.slice(-6)]}),(0,v.jsx)(`td`,{className:`py-3 text-slate-500 text-[10px]`,children:new Date(e.created_at).toLocaleDateString(`vi-VN`)}),(0,v.jsx)(`td`,{className:`py-3 text-center`,children:(0,v.jsxs)(`div`,{className:`flex justify-center gap-2`,children:[(0,v.jsx)(`button`,{onClick:()=>le(e.api_key),className:`p-1.5 bg-[#0b0b14] border border-[#1f1f3a] hover:border-purple-500/50 rounded-lg text-slate-400 hover:text-white transition-all`,title:`Copy API Key`,children:re===e.api_key?(0,v.jsx)(a,{className:`w-3.5 h-3.5 text-emerald-400`}):(0,v.jsx)(p,{className:`w-3.5 h-3.5`})}),(0,v.jsx)(`button`,{onClick:()=>ce(e.api_key),className:`p-1.5 bg-red-500/10 border border-red-500/20 hover:bg-red-500/20 rounded-lg text-red-400 transition-all`,title:`Thu hồi`,children:(0,v.jsx)(s,{className:`w-3.5 h-3.5`})})]})})]},t))})]})}),(0,v.jsxs)(`form`,{onSubmit:se,className:`flex gap-2 border-t border-[#1f1f3a]/50 pt-4`,children:[(0,v.jsx)(`input`,{type:`text`,placeholder:u.developer?.keyNamePlaceholder||`Tên gợi nhớ`,value:w,onChange:e=>T(e.target.value),className:`flex-1 px-4 py-2.5 bg-[#0b0b14] border border-[#1f1f3a] rounded-xl text-xs text-white outline-none focus:border-purple-500 transition-colors`}),(0,v.jsxs)(`button`,{type:`submit`,disabled:O||!w.trim(),className:`bg-purple-600 hover:bg-purple-500 disabled:opacity-40 text-white font-bold px-4 py-2.5 rounded-xl text-xs flex items-center gap-1.5 transition-all`,children:[(0,v.jsx)(o,{className:`w-4 h-4`}),` `,u.developer?.createBtn||`Tạo khóa`]})]})]}),(0,v.jsxs)(`div`,{className:`bg-[#121225]/60 border border-[#1f1f3a] rounded-3xl p-6 space-y-6`,children:[(0,v.jsx)(`h3`,{className:`text-sm font-extrabold text-white flex items-center gap-2 border-b border-[#1f1f3a]/50 pb-2`,children:`⚡ API Sandbox & TTS Playground`}),(0,v.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-6`,children:[(0,v.jsxs)(`div`,{className:`space-y-4`,children:[(0,v.jsxs)(`div`,{className:`flex justify-between items-center`,children:[(0,v.jsx)(`h4`,{className:`text-xs font-bold text-slate-300`,children:`1. Text-to-Speech (TTS)`}),(0,v.jsx)(`span`,{className:`text-[9px] bg-purple-500/15 text-purple-400 px-2 py-0.5 rounded border border-purple-500/20 uppercase font-bold`,children:`RunPod AI`})]}),(0,v.jsx)(`textarea`,{rows:4,value:F,onChange:e=>I(e.target.value),placeholder:`Nhập văn bản cần phát audio...`,className:`w-full bg-[#0b0b14] border border-[#1f1f3a] rounded-xl p-3 text-xs text-slate-300 outline-none focus:border-purple-500`}),(0,v.jsxs)(`div`,{className:`grid grid-cols-2 gap-3`,children:[(0,v.jsxs)(`div`,{className:`space-y-1`,children:[(0,v.jsxs)(`label`,{className:`text-[10px] text-slate-400 font-bold block`,children:[u.reader?.speed||`Tốc độ`,` (`,L,`x):`]}),(0,v.jsx)(`input`,{type:`range`,min:`0.5`,max:`4.0`,step:`0.1`,value:L,onChange:e=>R(parseFloat(e.target.value)),className:`w-full accent-purple-500 bg-[#0b0b14]`})]}),(0,v.jsx)(`div`,{className:`space-y-1 flex items-end`,children:(0,v.jsxs)(`button`,{onClick:ue,disabled:V,className:`w-full bg-purple-600 hover:bg-purple-500 active:scale-95 disabled:opacity-40 text-white font-bold py-2.5 rounded-xl text-xs flex items-center justify-center gap-1.5 shadow-md transition-all`,children:[V?(0,v.jsx)(t,{className:`w-4 h-4 animate-spin`}):z?(0,v.jsx)(f,{className:`w-4 h-4`}):(0,v.jsx)(te,{className:`w-4 h-4 fill-current`}),z?m===`zh`?`正在播放...`:m===`en`?`Playing...`:`Đang phát...`:m===`zh`?`播放音频`:m===`en`?`Play Audio`:`Gửi & Phát Audio`]})})]})]}),(0,v.jsxs)(`div`,{className:`space-y-4`,children:[(0,v.jsxs)(`div`,{className:`flex justify-between items-center`,children:[(0,v.jsx)(`h4`,{className:`text-xs font-bold text-slate-300`,children:m===`zh`?`2. 中越翻译`:m===`en`?`2. Chinese-Vietnamese Translation`:`2. Dịch thuật Trung-Việt`}),(0,v.jsx)(`span`,{className:`text-[9px] bg-emerald-500/15 text-emerald-400 px-2 py-0.5 rounded border border-emerald-500/20 uppercase font-bold`,children:`Vietphrase`})]}),(0,v.jsx)(`textarea`,{rows:4,value:W,onChange:e=>G(e.target.value),placeholder:`Nhập văn bản tiếng Trung cần dịch...`,className:`w-full bg-[#0b0b14] border border-[#1f1f3a] rounded-xl p-3 text-xs text-slate-300 outline-none focus:border-purple-500`}),(0,v.jsxs)(`div`,{className:`grid grid-cols-2 gap-3`,children:[(0,v.jsxs)(`select`,{value:K,onChange:e=>q(e.target.value),className:`bg-[#0b0b14] border border-[#1f1f3a] text-xs font-semibold rounded-xl p-2.5 text-slate-300 outline-none cursor-pointer focus:border-purple-500`,children:[(0,v.jsx)(`option`,{value:`fast`,children:u.compFast}),(0,v.jsx)(`option`,{value:`vietphrase`,children:u.compVietphrase})]}),(0,v.jsxs)(`button`,{onClick:de,disabled:X,className:`w-full bg-emerald-600 hover:bg-emerald-500 active:scale-95 disabled:opacity-40 text-white font-bold py-2.5 rounded-xl text-xs flex items-center justify-center gap-1.5 shadow-md transition-all`,children:[X?(0,v.jsx)(t,{className:`w-4 h-4 animate-spin`}):(0,v.jsx)(ee,{className:`w-4 h-4`}),m===`zh`?`翻译`:m===`en`?`Translate`:`Dịch ngay`]})]})]})]}),J&&(0,v.jsxs)(`div`,{className:`bg-[#0b0b14] border border-[#1f1f3a] rounded-xl p-4 space-y-1.5 animate-in fade-in duration-200`,children:[(0,v.jsx)(`span`,{className:`text-[9px] text-slate-500 block uppercase font-extrabold tracking-wider`,children:m===`zh`?`翻译结果`:m===`en`?`Translation Result`:`Kết quả dịch`}),(0,v.jsx)(`p`,{className:`text-xs text-slate-200 whitespace-pre-line leading-relaxed`,children:J})]})]})]}),(0,v.jsxs)(`div`,{className:`space-y-6`,children:[(0,v.jsxs)(`div`,{className:`bg-[#121225]/60 border border-[#1f1f3a] rounded-3xl p-5 shadow-xl space-y-4`,children:[(0,v.jsxs)(`h3`,{className:`text-xs font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-amber-400 to-amber-200 flex items-center gap-1.5`,children:[(0,v.jsx)(r,{className:`w-4 h-4 text-amber-400`}),` `,u.developer?.apiDocsTitle||`Tài liệu tích hợp (cURL)`]}),(0,v.jsxs)(`div`,{className:`space-y-3.5`,children:[(0,v.jsxs)(`div`,{className:`space-y-1`,children:[(0,v.jsx)(`span`,{className:`text-[9px] text-slate-400 font-extrabold uppercase`,children:u.developer?.ttsEndpoint||`1. Chuyển Text thành Audio (OpenAI format)`}),(0,v.jsx)(`div`,{className:`bg-[#0b0b14] border border-white/5 p-3 rounded-xl relative`,children:(0,v.jsx)(`pre`,{className:`text-[10px] text-slate-300 font-mono overflow-x-auto whitespace-pre leading-relaxed select-all`,children:`curl -X POST http://localhost:5051/v1/audio/speech \\ + -H "Authorization: Bearer YOUR_API_KEY" \\ + -H "Content-Type: application/json" \\ + -d '{"input": "Nhập văn bản cần phát", "speed": 1.0}' \\ + --output audio.wav`})})]}),(0,v.jsxs)(`div`,{className:`space-y-1`,children:[(0,v.jsx)(`span`,{className:`text-[9px] text-slate-400 font-extrabold uppercase`,children:u.developer?.transEndpoint||`2. API Dịch Thuật Trung-Việt`}),(0,v.jsx)(`div`,{className:`bg-[#0b0b14] border border-white/5 p-3 rounded-xl relative`,children:(0,v.jsx)(`pre`,{className:`text-[10px] text-slate-300 font-mono overflow-x-auto whitespace-pre leading-relaxed select-all`,children:`curl -X POST http://localhost:5051/api/v1/translate \\ + -H "Authorization: Bearer YOUR_API_KEY" \\ + -H "Content-Type: application/json" \\ + -d '{"texts": ["第1章", "开封神殿"], "mode": "fast"}'`})})]})]})]}),(0,v.jsxs)(`div`,{className:`bg-[#121225]/60 border border-[#1f1f3a] rounded-3xl p-5 shadow-xl space-y-4`,children:[(0,v.jsxs)(`h3`,{className:`text-xs font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-brand-300 to-purple-300 flex items-center gap-1.5`,children:[(0,v.jsx)(e,{className:`w-4 h-4 text-brand-400`}),` `,u.developer?.apiUsageHistoryTitle||`Nhật ký cuộc gọi gần đây`]}),ae?(0,v.jsx)(`div`,{className:`text-center py-4 text-slate-500 text-xs`,children:`Đang tải...`}):j.length===0?(0,v.jsx)(`p`,{className:`text-slate-500 text-xs text-center py-4`,children:m===`zh`?`暂无接口调用记录。`:m===`en`?`No API usage records found.`:`Chưa có lịch sử cuộc gọi API nào.`}):(0,v.jsx)(`div`,{className:`space-y-3 max-h-[300px] overflow-y-auto`,children:j.slice(0,10).map((e,t)=>(0,v.jsxs)(`div`,{className:`border-b border-[#1f1f3a]/30 pb-2.5 last:border-0 last:pb-0 flex justify-between items-center text-[10px]`,children:[(0,v.jsxs)(`div`,{children:[(0,v.jsx)(`span`,{className:`text-white font-bold font-mono`,children:e.model}),(0,v.jsxs)(`span`,{className:`text-slate-500 block text-[9px] mt-0.5`,children:[new Date(e.timestamp).toLocaleTimeString(`vi-VN`),` · `,e.tokens,` `,m===`zh`?`字符`:m===`en`?`chars`:`kí tự`]})]}),(0,v.jsxs)(`div`,{className:`text-right`,children:[(0,v.jsx)(`span`,{className:`text-emerald-400 font-bold block`,children:e.cost===0?u.developer?.freeCost||`Miễn phí (VIP)`:$(e.cost)}),(0,v.jsx)(`span`,{className:`px-1 rounded text-[8px] font-bold ${e.status_code===200?`bg-emerald-500/15 text-emerald-400`:`bg-red-500/15 text-red-400`}`,children:e.status_code})]})]},t))})]})]})]})]}),(0,v.jsx)(n,{isOpen:x,onClose:()=>{S(!1),Q()}})]}):(0,v.jsx)(i,{children:(0,v.jsxs)(`div`,{className:`py-20 text-center text-slate-500 max-w-md mx-auto space-y-4`,children:[(0,v.jsx)(r,{className:`w-12 h-12 text-purple-400 mx-auto`}),(0,v.jsx)(`h2`,{className:`text-lg font-bold text-white`,children:`Developer API Console`}),(0,v.jsx)(`p`,{className:`text-xs text-slate-400 leading-relaxed`,children:`Vui lòng đăng nhập tài khoản để tiếp tục.`})]})})}export{y as default}; \ No newline at end of file diff --git a/frontend-web/dist/assets/Discover-BCmVIXus.js b/frontend-web/dist/assets/Discover-BCmVIXus.js new file mode 100644 index 0000000000000000000000000000000000000000..3f0fc33b1a94333a4f7bdbb9c26bca99987f8381 --- /dev/null +++ b/frontend-web/dist/assets/Discover-BCmVIXus.js @@ -0,0 +1 @@ +import{t as e}from"./award-CKCOPIfL.js";import{c as t,d as n,f as r,t as i,u as a,v as o}from"./MainLayout-COiTxmNr.js";import{t as s}from"./book-DwmTvSdZ.js";import{n as c}from"./square-DZKJ0QGR.js";import{t as l}from"./BookCard-BCMDdlyN.js";import{C as u,D as d,F as f,M as p,S as m,_ as h,b as g,j as _,k as ee,n as v,o as te,t as ne,v as re,w as y}from"./index-yRoRoI6u.js";import{t as ie}from"./GoogleAd-CD0eT9Wp.js";var ae=g(`funnel`,[[`path`,{d:`M10 20a1 1 0 0 0 .553.895l2 1A1 1 0 0 0 14 21v-7a2 2 0 0 1 .517-1.341L21.74 4.67A1 1 0 0 0 21 3H3a1 1 0 0 0-.742 1.67l7.225 7.989A2 2 0 0 1 10 14z`,key:`sc7q7i`}]]),oe=g(`shield-alert`,[[`path`,{d:`M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z`,key:`oel41y`}],[`path`,{d:`M12 8v4`,key:`1got3b`}],[`path`,{d:`M12 16h.01`,key:`1drbdi`}]]),se=g(`shuffle`,[[`path`,{d:`m18 14 4 4-4 4`,key:`10pe0f`}],[`path`,{d:`m18 2 4 4-4 4`,key:`pucp1d`}],[`path`,{d:`M2 18h1.973a4 4 0 0 0 3.3-1.7l5.454-8.6a4 4 0 0 1 3.3-1.7H22`,key:`1ailkh`}],[`path`,{d:`M2 6h1.972a4 4 0 0 1 3.6 2.2`,key:`km57vx`}],[`path`,{d:`M22 18h-6.041a4 4 0 0 1-3.3-1.8l-.359-.45`,key:`os18l9`}]]),b=f(_(),1),x=p();function ce({isOpen:e,onClose:r,onSelectBook:i}){let[c,l]=(0,b.useState)(``),[u,d]=(0,b.useState)(!1),[f,p]=(0,b.useState)(``),[m,h]=(0,b.useState)([]),[g,_]=(0,b.useState)(!1),ee=[`Main thông minh, IQ vô cực, đấu trí nghẹt thở`,`Tiên hiệp hài hước, cười bể bụng, main lầy lội`,`Sát phạt quyết đoán, độc hành, không thánh mẫu`,`Mạt thế xây dựng thế lực, không hậu cung`],v=e=>{l(e)};return e?(0,x.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/75 backdrop-blur-md`,children:(0,x.jsxs)(`div`,{className:`relative w-full max-w-2xl bg-gradient-to-b from-[#131327] to-[#0d0d1a] border border-[#2d2d6b]/80 rounded-3xl p-6 shadow-2xl overflow-hidden max-h-[85vh] flex flex-col`,children:[(0,x.jsx)(`div`,{className:`absolute -top-20 -left-20 w-40 h-40 bg-brand-500/10 rounded-full blur-3xl pointer-events-none`}),(0,x.jsx)(`div`,{className:`absolute -bottom-20 -right-20 w-40 h-40 bg-amber-500/10 rounded-full blur-3xl pointer-events-none`}),(0,x.jsxs)(`div`,{className:`flex justify-between items-center border-b border-white/5 pb-4 mb-4`,children:[(0,x.jsxs)(`div`,{className:`flex items-center gap-2.5`,children:[(0,x.jsx)(`div`,{className:`p-2 rounded-xl bg-gradient-to-r from-amber-500 to-amber-400 text-[#0b0b14] font-bold`,children:(0,x.jsx)(t,{className:`w-5 h-5 fill-current`})}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h3`,{className:`text-lg font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-amber-400 to-amber-200`,children:`TÌM KIẾM NÂNG CẤP AI`}),(0,x.jsx)(`p`,{className:`text-slate-400 text-xs mt-0.5`,children:`Tìm và gợi ý truyện thông minh theo cốt truyện, cảm xúc, tính cách nhân vật`})]})]}),(0,x.jsx)(`button`,{onClick:r,className:`p-1.5 hover:bg-white/5 rounded-lg text-slate-400 hover:text-white transition-colors`,children:(0,x.jsx)(te,{className:`w-6 h-6`})})]}),(0,x.jsxs)(`div`,{className:`flex-1 overflow-y-auto space-y-4 pr-1`,children:[(0,x.jsxs)(`div`,{className:`space-y-2`,children:[(0,x.jsx)(`span`,{className:`text-slate-500 text-xs font-bold uppercase tracking-wider block`,children:`Gợi ý câu hỏi AI:`}),(0,x.jsx)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-2`,children:ee.map((e,t)=>(0,x.jsxs)(`button`,{onClick:()=>v(e),className:`text-left text-xs bg-[#1a1a35]/60 hover:bg-[#1a1a35] border border-[#2d2d6b]/30 hover:border-brand-500/50 rounded-xl p-3 text-slate-300 hover:text-white transition-all`,children:[`💡 "`,e,`"`]},t))})]}),(0,x.jsxs)(`form`,{onSubmit:async e=>{if(e.preventDefault(),c.trim()){d(!0),p(``),h([]),_(!1);try{p((await y.post(`/api/ai/chat`,{prompt:`Bạn là trợ lý AI tìm kiếm truyện. Tìm các tác phẩm phù hợp với yêu cầu sau: "${c}". Hãy trả về lời khuyên ngắn gọn và một vài tên truyện gợi ý.`,model:`gemini-1.5-flash`})).data.text);let e=c.replace(/(main|truyện|tìm|có|yếu tố|không)/gi,``).trim(),t=await y.get(`/api/books`,{params:{q:e.split(` `)[0],per_page:3}});t.data&&t.data.books&&h(t.data.books.map(e=>({...e,matchScore:Math.floor(Math.random()*15)+85})))}catch(e){console.log(`AI Proxy Error or Non-VIP:`,e),_(!0),p(`[AI Standard Mode] Để sử dụng đầy đủ mô hình trí tuệ nhân tạo nâng cao, bạn cần nâng cấp VIP. Tuy nhiên, hệ thống AI Cơ Bản đã tìm thấy các bộ truyện phù hợp nhất dựa trên từ khóa phân tích:`);let t=c.replace(/(main|truyện|tìm|có|yếu tố|không|sát phạt|độc hành|vô cực|thế lực|nâng cấp|quyết đoán)/gi,``).trim().split(/[\s,]+/)[0]||`truyện`;try{let e=await y.get(`/api/books`,{params:{q:t,per_page:3}});e.data&&e.data.books&&e.data.books.length>0?h(e.data.books.map(e=>({...e,matchScore:Math.floor(Math.random()*10)+90}))):h(((await y.get(`/api/books`,{params:{per_page:3}})).data.books||[]).map(e=>({...e,matchScore:82})))}catch(e){console.error(e)}}finally{d(!1)}}},className:`flex gap-2`,children:[(0,x.jsx)(`input`,{type:`text`,placeholder:`Ví dụ: Tìm truyện linh dị kinh dị đô thị có nhân vật chính lạnh lùng...`,value:c,onChange:e=>l(e.target.value),className:`flex-1 px-4 py-3.5 bg-[#0b0b14] border border-[#2d2d6b]/50 rounded-2xl text-white outline-none focus:border-amber-400 transition-colors text-sm`}),(0,x.jsx)(`button`,{type:`submit`,disabled:u||!c.trim(),className:`px-5 bg-gradient-to-r from-amber-500 to-amber-600 hover:brightness-105 disabled:opacity-50 text-white font-bold rounded-2xl shadow-lg transition-all flex items-center justify-center gap-1 text-sm`,children:u?(0,x.jsx)(n,{className:`w-4 h-4 animate-spin`}):(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(a,{className:`w-4 h-4`}),` Gửi`]})})]}),u&&(0,x.jsxs)(`div`,{className:`py-8 text-center text-slate-500 space-y-3`,children:[(0,x.jsx)(n,{className:`w-8 h-8 animate-spin mx-auto text-amber-500`}),(0,x.jsx)(`p`,{className:`text-xs`,children:`AI đang phân tích cốt truyện và lọc đầu truyện...`})]}),!u&&(f||m.length>0)&&(0,x.jsxs)(`div`,{className:`space-y-4 border-t border-white/5 pt-4`,children:[f&&(0,x.jsxs)(`div`,{className:`bg-[#121225]/40 border border-[#2d2d6b]/30 rounded-2xl p-4 text-xs text-slate-300 leading-relaxed`,children:[g&&(0,x.jsxs)(`div`,{className:`flex items-center gap-1.5 text-amber-400 font-bold mb-2`,children:[(0,x.jsx)(o,{className:`w-4 h-4`}),` AI Standard Mode (Giới hạn VIP)`]}),(0,x.jsx)(`p`,{className:`whitespace-pre-line`,children:f})]}),m.length>0&&(0,x.jsxs)(`div`,{className:`space-y-2`,children:[(0,x.jsx)(`span`,{className:`text-slate-500 text-xs font-bold uppercase tracking-wider block`,children:`Truyện Khớp Nhiều Nhất:`}),(0,x.jsx)(`div`,{className:`space-y-3`,children:m.map(e=>(0,x.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#2d2d6b]/30 rounded-2xl p-4 flex gap-4 items-center justify-between hover:border-amber-400 transition-all cursor-pointer`,onClick:()=>{i&&i(e),r()},children:[(0,x.jsxs)(`div`,{className:`flex gap-3 items-center min-w-0`,children:[e.cover?(0,x.jsx)(`img`,{src:e.cover,alt:`cover`,className:`w-[45px] h-[60px] object-cover rounded-lg border border-[#2d2d55] shadow-md bg-[#0f0f1a]`,onError:e=>{e.target.remove()}}):(0,x.jsx)(`div`,{className:`w-[45px] h-[60px] rounded-lg border border-[#2d2d55] bg-[#0f0f1a] flex items-center justify-center text-slate-500`,children:(0,x.jsx)(s,{className:`w-5 h-5`})}),(0,x.jsxs)(`div`,{className:`min-w-0`,children:[(0,x.jsx)(`h4`,{className:`text-slate-100 font-bold text-sm truncate`,children:e.title_vietphrase||e.title}),(0,x.jsxs)(`p`,{className:`text-slate-500 text-xs mt-0.5 truncate`,children:[`Tác giả: `,e.author_hanviet||e.author]}),(0,x.jsx)(`div`,{className:`flex gap-1.5 mt-1.5`,children:e.categories&&e.categories.split(`, `).slice(0,2).map((e,t)=>(0,x.jsx)(`span`,{className:`px-1.5 py-0.5 rounded bg-emerald-500/10 border border-emerald-500/20 text-emerald-400 text-[9px]`,children:e},t))})]})]}),(0,x.jsxs)(`div`,{className:`text-right shrink-0`,children:[(0,x.jsxs)(`span`,{className:`text-amber-400 text-xs font-extrabold block`,children:[e.matchScore,`%`]}),(0,x.jsx)(`span`,{className:`text-slate-500 text-[9px]`,children:`AI Match`})]})]},e.id))})]})]})]}),(0,x.jsxs)(`div`,{className:`border-t border-white/5 pt-3 mt-3 flex justify-between items-center text-[10px] text-slate-500`,children:[(0,x.jsx)(`span`,{children:`Hệ thống phân tích từ kho truyện 930k+ đầu mục`}),(0,x.jsx)(`span`,{children:`Nâng cấp VIP để mở khóa GPT/Gemini AI đầy đủ`})]})]})}):null}function S(){let{t:a,lang:o}=m(),{user:s}=u(),[f,p]=ee(),g=d(),_=e=>e?{玄幻:o===`vi`?`Huyền Huyễn`:o===`en`?`Fantasy`:`玄幻`,都市:o===`vi`?`Đô Thị`:o===`en`?`Urban`:`都市`,言情:o===`vi`?`Ngôn Tình`:o===`en`?`Romance`:`言情`,女生:o===`vi`?`Nữ Sinh`:o===`en`?`Female Lead`:`女生`,科幻:o===`vi`?`Khoa Huyễn`:o===`en`?`Sci-Fi`:`科幻`,修真:o===`vi`?`Tu Chân`:o===`en`?`Cultivation`:`修真`,仙侠:o===`vi`?`Tiên Hiệp`:o===`en`?`Xianxia`:`仙侠`,武侠:o===`vi`?`Võ Hiệp`:o===`en`?`Wuxia`:`武侠`,历史:o===`vi`?`Lịch Sử`:o===`en`?`History`:`历史`,网游:o===`vi`?`Võng Du`:o===`en`?`Gaming`:`网游`,同人:o===`vi`?`Đồng Nhân`:o===`en`?`Fanfiction`:`同人`,其他:o===`vi`?`Thể loại khác`:o===`en`?`Others`:`其他`}[e]||e:a.allCategories,[S,C]=(0,b.useState)([]),[le,w]=(0,b.useState)(!0),[T,E]=(0,b.useState)(``),[D,O]=(0,b.useState)(``),[ue,k]=(0,b.useState)(`all`),[A,j]=(0,b.useState)(``),[M,de]=(0,b.useState)(``),[N,fe]=(0,b.useState)(``),[P,F]=(0,b.useState)(``),[I,L]=(0,b.useState)(`site_count DESC`),[pe,me]=(0,b.useState)(!1),[R,z]=(0,b.useState)(1),[B,V]=(0,b.useState)(1),[H,U]=(0,b.useState)(0),[he,ge]=(0,b.useState)({total:931427,duplicates:0}),[_e,ve]=(0,b.useState)(null),[ye,be]=(0,b.useState)(null),[xe,Se]=(0,b.useState)(!1),[Ce,W]=(0,b.useState)(new Set),[we,Te]=(0,b.useState)([]),[Ee,De]=(0,b.useState)(!1),{activeAudioObj:Oe,setActiveAudioObj:G}=ne(),[K,q]=(0,b.useState)(0),[ke,J]=(0,b.useState)(`original`),[Ae,Y]=(0,b.useState)(``),[je,Me]=(0,b.useState)(!1),[X,Ne]=(0,b.useState)([{id:1,title:`Hắc Ám Văn Minh`,title_vietphrase:`Hắc Ám Văn Minh`,author:`Cổ Hi`,author_hanviet:`Cổ Hi`,categories:`Huyền Huyễn, Mạt Thế, Khoa Huyễn`,cover:`https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?w=200&auto=format&fit=crop&q=60`,description:`Khi bóng tối bao phủ địa cầu, nhân loại đối mặt với kỷ nguyên hắc ám tột cùng. Các nguồn văn minh bị phá hủy hoàn toàn, những loài thú biến dị trỗi dậy, kẻ mạnh mới có quyền sinh tồn...`},{id:2,title:`Đấu Phá Thương Khung`,title_vietphrase:`Đấu Phá Thương Khung`,author:`Thiên Tàm Thổ Đậu`,author_hanviet:`Thiên Tàm Thổ Đậu`,categories:`Tiên Hiệp, Huyền Huyễn`,cover:`https://images.unsplash.com/photo-1543002588-bfa74002ed7e?w=200&auto=format&fit=crop&q=60`,description:`Nơi đây là thế giới của Đấu Khí. Không có ma pháp hoa lệ, chỉ có đấu khí sinh sôi phát triển đến đỉnh phong! Tiêu Viêm - một thiên tài bỗng chốc sa sút, bắt đầu cuộc hành trình nghịch thiên cải mệnh...`},{id:3,title:`Hộc Châu Phu Nhân`,title_vietphrase:`Hộc Châu Phu Nhân`,author:`Tiêu Như Sắt`,author_hanviet:`Tiêu Như Sắt`,categories:`Ngôn Tình, Cổ Đại, Nữ Sinh`,cover:`https://images.unsplash.com/photo-1512820790803-83ca734da794?w=200&auto=format&fit=crop&q=60`,description:`Nơi Giao Châu xa xôi có bộ tộc mò ngọc trai quý hiếm. Cuộc đời nàng Diệp Hải Thị xoay vần giữa tranh đoạt quyền lực nơi cung đình triều đình đại chiến và mối tình đầy ngang trái...`}]),Pe=[{id:1,user:`Minh Quân`,avatar:`https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=80&auto=format&fit=crop&q=60`,source:`Metruyenchu`,comment:`bên nguồn chữ một cho màn Trong 😂`,time:`2 phút trước`},{id:2,user:`Thanh Trúc`,avatar:`https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=80&auto=format&fit=crop&q=60`,source:`Truyenchu`,comment:`bên thảo của màn Trong 😆`,time:`1 phút trước`},{id:3,user:`Quốc Bảo`,avatar:`https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=80&auto=format&fit=crop&q=60`,source:`Nady knise`,comment:`trên đàn nên to...`,time:`1 phút trước`},{id:4,user:`Lan Hương`,avatar:`https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=80&auto=format&fit=crop&q=60`,source:`Metruyenchu`,comment:`(Tốt) chặn khỉn hồi Uanb u oại thi mượt 😮`,time:`1 phút trước`}];(0,b.useEffect)(()=>{Fe(),Ie()},[s]),(0,b.useEffect)(()=>{let e=f.get(`q`),t=f.get(`search_field`),n=f.get(`category`),r=!1,i={};e&&(O(e),i.q=e,r=!0),t&&(k(t),i.search_field=t,r=!0),n&&(j(n),i.category=n,r=!0),r?(Z(i),p({},{replace:!0})):Z()},[f]),(0,b.useEffect)(()=>{f.get(`q`)||f.get(`search_field`)||f.get(`category`)||Z()},[R,A,M,N,P,I]),(0,b.useEffect)(()=>{(async()=>{try{let e=[...X];for(let t=0;t0){let r=n.data.books[0];e[t]={...e[t],id:r.id,cover:r.cover||e[t].cover,title_vietphrase:r.title_vietphrase||r.title,author_hanviet:r.author_hanviet||r.author,urls:r.urls,categories:r.categories||e[t].categories}}}Ne(e)}catch(e){console.error(`Failed to sync hero books with database:`,e)}})()},[]),(0,b.useEffect)(()=>{J(`original`),Y(``)},[K]);let Fe=async()=>{try{let e=await y.get(`/api/stats`);ge({total:e.data.total_books||931427,duplicates:e.data.duplicates||0})}catch(e){console.error(e)}},Ie=async()=>{if(!s){W(new Set);return}try{let e=await y.get(`/api/bookshelf`);W(new Set(e.data.map(e=>e.book_id)))}catch(e){console.error(e)}},Z=async(e={})=>{w(!0),E(``);try{let t={q:e.q===void 0?D:e.q,category:e.category===void 0?A:e.category,source:e.source===void 0?M:e.source,dup:e.dup===void 0?N:e.dup,sort:I,search_field:e.search_field===void 0?ue:e.search_field,min_chapters:P,page:R,per_page:30},n=await y.get(`/api/books`,{params:t});C(n.data.books||[]),V(n.data.pages||1),U(n.data.total||0),n.data.books&&R===1&&!A&&!M&&!D&&Te([{id:1,title:`Hắc Ám Văn Minh`,author:`Cổ Hi`,trend:`up`,diff:1},{id:2,title:`Hộc ẩm chúa tể`,author:`Linh Hạ Cửu Thập Độ`,trend:`up`,diff:2},{id:3,title:`10 Lần Thôn Tương`,author:`Luân Hồi Thiên Trọng`,trend:`down`,diff:1},{id:4,title:`Mộ Ngôn`,author:`Nguôn`,trend:`none`,diff:0}])}catch(e){E(e.response?.data?.error||a.connError)}finally{w(!1)}},Le=e=>{k(`author`),O(e),z(1),Z({search_field:`author`,q:e})},Re=e=>{j(e),z(1),Z({category:e})},ze=e=>{e.preventDefault(),z(1),Z()},Be=e=>{e.id&&g(`/book/${e.id}`)},Ve=async e=>{if(!s){alert(`Vui lòng đăng nhập để lưu sách.`);return}let t=Ce.has(e),n=t?`/api/bookshelf/remove`:`/api/bookshelf/add`;try{await y.post(n,{book_id:e}),W(n=>{let r=new Set(n);return t?r.delete(e):r.add(e),r})}catch(e){alert(e.response?.data?.error||`Lỗi xử lý tủ sách.`)}},He=async e=>{if(_e===e){ve(null),be(null);return}ve(e),Se(!0);try{be((await y.get(`/api/book/${e}/translations`)).data),await y.post(`/api/history/add`,{book_id:e,last_chapter:`Đang xem so sánh`})}catch(e){console.error(e)}finally{Se(!1)}},Ue=()=>{O(``),k(`all`),j(``),de(``),fe(``),F(``),L(`site_count DESC`),z(1)},We=async()=>{w(!0);try{let e=Math.floor(Math.random()*20)+1,t=await y.get(`/api/books`,{params:{page:e,per_page:30}});if(t.data&&t.data.books&&t.data.books.length>0){let e=Math.floor(Math.random()*t.data.books.length),n=t.data.books[e];C([n]),V(1),U(1),G(n)}}catch(e){console.error(`Gacha failed:`,e)}finally{w(!1)}},Q=async e=>{let t=X[K];if(e===`original`){J(`original`);return}Me(!0);try{try{let n=await y.post(`/api/translate`,{texts:[t.description],mode:e===`en`?`en`:`vietphrase`});n.data&&n.data.translations&&n.data.translations[0]&&(Y(n.data.translations[0]),J(e))}catch(n){console.warn(`[Discover] Cloud translation failed, trying offline localTranslator:`,n),await v.loadDictionaries(),Y(v.translateSentence(t.description,`advanced`)),J(e)}}catch{alert(`Hạn mức dịch máy chủ đã hết và bộ dịch offline gặp lỗi.`)}finally{Me(!1)}},Ge=()=>{let e=X[K];G(e)},Ke=e=>{C([e]),V(1),U(1)},$=X[K],qe=ke===`original`?$.description:Ae||$.description;return(0,x.jsxs)(i,{stats:he,children:[(0,x.jsxs)(`div`,{className:`relative w-full rounded-2xl sm:rounded-3xl overflow-hidden mb-6 min-h-[220px] sm:min-h-[360px] bg-[#0b0b14] border border-[#1f1f3a]/80 shadow-2xl flex flex-col justify-end`,children:[(0,x.jsx)(`div`,{className:`absolute inset-0 bg-cover bg-center transition-all duration-700`,style:{backgroundImage:`url('hero_banner.png')`}}),(0,x.jsx)(`div`,{className:`absolute inset-0 bg-gradient-to-r from-[#0b0b14] via-[#0b0b14]/75 to-transparent`}),(0,x.jsxs)(`div`,{className:`relative z-10 p-4 sm:p-8 md:p-12 max-w-2xl text-left space-y-2 sm:space-y-4 self-start`,children:[(0,x.jsx)(`h2`,{className:`text-lg sm:text-3xl md:text-4xl font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-yellow-300 via-amber-400 to-amber-200 tracking-wide uppercase`,children:o===`vi`?`TRUYỆN ĐỀ CỬ XUẤT SẮC TUẦN NÀY`:o===`en`?`WEEKLY FEATURED NOVEL`:`本周精选推荐`}),(0,x.jsx)(`h3`,{className:`text-base sm:text-xl md:text-2xl font-bold text-white tracking-wide`,children:$.title_vietphrase}),(0,x.jsxs)(`p`,{className:`text-slate-400 text-xs mt-1 hidden sm:block`,children:[`✍ `,o===`vi`?`Tác giả:`:o===`en`?`Author:`:`作者:`,` `,(0,x.jsx)(`strong`,{className:`text-brand-300 font-semibold`,children:$.author_hanviet}),` · `,o===`vi`?`Thể loại:`:o===`en`?`Categories:`:`题材:`,` `,(0,x.jsx)(`span`,{className:`text-slate-300 font-medium`,children:$.categories})]}),(0,x.jsx)(`p`,{className:`text-slate-300 text-xs leading-relaxed line-clamp-2 sm:line-clamp-3 bg-[#0b0b14]/60 backdrop-blur-sm p-3 sm:p-4 rounded-xl border border-white/5`,children:je?o===`vi`?`Đang dịch nội dung...`:o===`en`?`Translating content...`:`正在翻译内容...`:qe}),(0,x.jsxs)(`div`,{className:`flex flex-wrap gap-2 sm:gap-4 pt-1 sm:pt-2`,children:[(0,x.jsxs)(`button`,{onClick:Ge,className:`inline-flex items-center gap-2 bg-purple-600 hover:bg-purple-500 active:scale-95 text-white font-extrabold px-4 sm:px-6 py-2.5 sm:py-3 rounded-full shadow-lg transition-all text-xs`,children:[o===`vi`?`Nghe Tóm Tắt (TTS)`:o===`en`?`Listen Summary (TTS)`:`听取大纲 (TTS)`,` `,(0,x.jsx)(`span`,{className:`text-purple-300`,children:`| 🔊`})]}),(0,x.jsxs)(`div`,{className:`inline-flex items-center gap-1.5 bg-[#121225]/80 border border-white/10 px-3 sm:px-4 py-2 sm:py-2.5 rounded-full text-xs font-bold`,children:[(0,x.jsx)(`span`,{className:`text-slate-400 text-[10px] hidden sm:inline`,children:o===`vi`?`Dịch Nhanh`:o===`en`?`Quick Translate`:`快速翻译`}),(0,x.jsx)(`button`,{onClick:()=>Q(`vi`),className:`hover:scale-115 transition-transform`,title:`Thuần Việt`,children:`🇻🇳`}),(0,x.jsx)(`button`,{onClick:()=>Q(`en`),className:`hover:scale-115 transition-transform`,title:`English`,children:`🇺🇸`}),(0,x.jsx)(`button`,{onClick:()=>Q(`original`),className:`hover:scale-115 transition-transform`,title:`Original Chinese`,children:`🇨🇳`})]})]})]}),(0,x.jsxs)(`div`,{className:`absolute right-8 bottom-8 z-10 flex items-center gap-3`,children:[(0,x.jsx)(`button`,{onClick:()=>q(e=>(e-1+X.length)%X.length),className:`p-2 bg-black/50 hover:bg-black/75 rounded-full border border-white/10 text-white transition-all`,children:(0,x.jsx)(re,{className:`w-4 h-4`})}),(0,x.jsx)(`div`,{className:`flex gap-1.5`,children:X.map((e,t)=>(0,x.jsx)(`button`,{onClick:()=>q(t),className:`w-2.5 h-2.5 rounded-full transition-all ${K===t?`bg-purple-500 w-6`:`bg-white/20`}`},t))}),(0,x.jsx)(`button`,{onClick:()=>q(e=>(e+1)%X.length),className:`p-2 bg-black/50 hover:bg-black/75 rounded-full border border-white/10 text-white transition-all`,children:(0,x.jsx)(h,{className:`w-4 h-4`})})]})]}),(0,x.jsxs)(`div`,{className:`grid grid-cols-1 lg:grid-cols-4 gap-6`,children:[(0,x.jsxs)(`div`,{className:`lg:col-span-3 space-y-6`,children:[(0,x.jsxs)(`form`,{onSubmit:ze,className:`bg-[#121225]/80 border border-[#1f1f3a]/80 rounded-2xl p-5 space-y-4 shadow-xl`,children:[(0,x.jsxs)(`div`,{className:`flex flex-col sm:flex-row gap-2`,children:[(0,x.jsxs)(`div`,{className:`relative flex-1`,children:[(0,x.jsx)(c,{className:`absolute left-3.5 top-1/2 -translate-y-1/2 w-4 h-4 text-purple-400`}),(0,x.jsx)(`input`,{type:`text`,placeholder:a.searchPlaceholder,value:D,onChange:e=>O(e.target.value),className:`w-full pl-10 pr-4 py-3 bg-[#0b0b14] border border-[#1f1f3a] rounded-xl text-white outline-none focus:border-purple-500 transition-colors text-xs`})]}),(0,x.jsxs)(`div`,{className:`flex gap-2 w-full sm:w-auto shrink-0`,children:[(0,x.jsx)(`button`,{type:`submit`,className:`flex-1 sm:flex-initial bg-purple-600 hover:bg-purple-500 text-white font-bold px-5 py-3 rounded-xl shadow-md transition-all text-xs text-center`,children:o===`vi`?`Tìm`:o===`en`?`Search`:`搜索`}),(0,x.jsxs)(`button`,{type:`button`,onClick:()=>me(e=>!e),className:`px-3 py-3 rounded-xl border text-xs font-bold transition-all flex items-center justify-center gap-1.5 ${pe?`bg-purple-600/20 border-purple-500/40 text-purple-300`:`bg-[#0b0b14] border-[#1f1f3a] text-slate-400 hover:text-white`}`,title:o===`vi`?`Bộ lọc nâng cao`:o===`en`?`Advanced filters`:`高级筛选`,children:[(0,x.jsx)(ae,{className:`w-4 h-4`}),(0,x.jsx)(`span`,{className:`hidden sm:inline`,children:o===`vi`?`Bộ lọc`:o===`en`?`Filters`:`筛选`})]}),(0,x.jsxs)(`button`,{type:`button`,onClick:()=>De(!0),className:`flex-1 sm:flex-initial bg-gradient-to-r from-amber-500 to-amber-600 hover:brightness-105 text-[#0b0b14] font-extrabold px-4 py-3 rounded-xl shadow-lg transition-all text-xs flex items-center justify-center gap-1.5`,children:[(0,x.jsx)(t,{className:`w-4 h-4 fill-current animate-pulse`}),(0,x.jsx)(`span`,{children:o===`vi`?`AI`:o===`en`?`AI Search`:`AI`})]})]})]}),(0,x.jsxs)(`div`,{className:`${pe?`grid`:`hidden lg:grid`} grid-cols-2 md:grid-cols-3 gap-3 pt-2`,children:[(0,x.jsxs)(`select`,{value:ue,onChange:e=>k(e.target.value),className:`bg-[#0b0b14] border border-[#1f1f3a] text-xs font-semibold rounded-xl p-3 text-slate-300 outline-none cursor-pointer focus:border-purple-500`,children:[(0,x.jsx)(`option`,{value:`all`,children:a.searchFieldAll}),(0,x.jsx)(`option`,{value:`title`,children:a.searchFieldTitle}),(0,x.jsx)(`option`,{value:`author`,children:a.searchFieldAuthor}),(0,x.jsx)(`option`,{value:`hanviet`,children:a.searchFieldHanviet}),(0,x.jsx)(`option`,{value:`vietphrase`,children:a.searchFieldVietphrase}),(0,x.jsx)(`option`,{value:`chinese`,children:a.searchFieldChinese}),(0,x.jsx)(`option`,{value:`description`,children:a.searchFieldDesc})]}),(0,x.jsxs)(`select`,{value:A,onChange:e=>{j(e.target.value),z(1)},className:`bg-[#0b0b14] border border-[#1f1f3a] text-xs font-semibold rounded-xl p-3 text-slate-300 outline-none cursor-pointer focus:border-purple-500`,children:[(0,x.jsx)(`option`,{value:``,children:a.allCategories}),[`玄幻`,`都市`,`言情`,`女生`,`科幻`,`修真`,`仙侠`,`武侠`,`历史`,`网游`,`同人`,`其他`].map(e=>(0,x.jsx)(`option`,{value:e,children:_(e)},e))]}),(0,x.jsxs)(`select`,{value:M,onChange:e=>{de(e.target.value),z(1)},className:`bg-[#0b0b14] border border-[#1f1f3a] text-xs font-semibold rounded-xl p-3 text-slate-300 outline-none cursor-pointer focus:border-purple-500`,children:[(0,x.jsx)(`option`,{value:``,children:a.allSources}),[`Ixdzs`,`Biquge`,`41nr`,`Quanben`,`Faloo`,`Fanqie`,`Hjwzw`].map(e=>(0,x.jsx)(`option`,{value:e,children:e},e))]}),(0,x.jsxs)(`select`,{value:N,onChange:e=>{fe(e.target.value),z(1)},className:`bg-[#0b0b14] border border-[#1f1f3a] text-xs font-semibold rounded-xl p-3 text-slate-300 outline-none cursor-pointer focus:border-purple-500`,children:[(0,x.jsx)(`option`,{value:``,children:a.allDup}),(0,x.jsx)(`option`,{value:`multi`,children:a.dupMulti}),(0,x.jsx)(`option`,{value:`single`,children:a.dupSingle})]}),(0,x.jsxs)(`select`,{value:P,onChange:e=>{F(e.target.value),z(1)},className:`bg-[#0b0b14] border border-[#1f1f3a] text-xs font-semibold rounded-xl p-3 text-slate-300 outline-none cursor-pointer focus:border-purple-500`,children:[(0,x.jsx)(`option`,{value:``,children:a.allChapters}),(0,x.jsx)(`option`,{value:`100`,children:a.ch100}),(0,x.jsx)(`option`,{value:`500`,children:a.ch500}),(0,x.jsx)(`option`,{value:`1000`,children:a.ch1000}),(0,x.jsx)(`option`,{value:`2000`,children:a.ch2000})]}),(0,x.jsxs)(`select`,{value:I,onChange:e=>{L(e.target.value),z(1)},className:`bg-[#0b0b14] border border-[#1f1f3a] text-xs font-semibold rounded-xl p-3 text-slate-300 outline-none cursor-pointer focus:border-purple-500`,children:[(0,x.jsx)(`option`,{value:`site_count DESC`,children:a.sortBy.site_count}),(0,x.jsx)(`option`,{value:`chapters_max DESC`,children:a.sortBy.chapters_max}),(0,x.jsx)(`option`,{value:`word_count_max DESC`,children:a.sortBy.word_count_max}),(0,x.jsx)(`option`,{value:`title ASC`,children:a.sortBy.title_asc}),(0,x.jsx)(`option`,{value:`title DESC`,children:a.sortBy.title_desc}),(0,x.jsx)(`option`,{value:`id ASC`,children:a.sortBy.default})]})]}),(0,x.jsxs)(`div`,{className:`flex justify-between items-center border-t border-[#1f1f3a]/30 pt-3`,children:[(0,x.jsx)(`span`,{className:`text-slate-500 text-xs`,children:o===`vi`?(0,x.jsxs)(x.Fragment,{children:[`Tìm thấy `,(0,x.jsx)(`strong`,{children:H.toLocaleString()}),` truyện`]}):o===`en`?(0,x.jsxs)(x.Fragment,{children:[`Found `,(0,x.jsx)(`strong`,{children:H.toLocaleString()}),` novels`]}):(0,x.jsxs)(x.Fragment,{children:[`找到 `,(0,x.jsx)(`strong`,{children:H.toLocaleString()}),` 部小说`]})}),(0,x.jsxs)(`div`,{className:`flex items-center gap-4`,children:[(0,x.jsxs)(`button`,{type:`button`,onClick:We,className:`inline-flex items-center gap-1.5 text-amber-400 hover:text-amber-300 transition-colors text-xs font-extrabold`,children:[(0,x.jsx)(se,{className:`w-3.5 h-3.5`}),` `,o===`vi`?`Random Truyện (Gacha)`:o===`en`?`Random Novel (Gacha)`:`随机小说 (抽卡)`]}),(0,x.jsxs)(`button`,{type:`button`,onClick:Ue,className:`inline-flex items-center gap-1 text-slate-400 hover:text-white transition-colors text-xs font-bold`,children:[(0,x.jsx)(te,{className:`w-3.5 h-3.5`}),` `,a.clearFilter]})]})]})]}),le?(0,x.jsxs)(`div`,{className:`py-20 text-center text-slate-500`,children:[(0,x.jsx)(n,{className:`w-8 h-8 animate-spin mx-auto mb-3 text-brand-500`}),(0,x.jsx)(`span`,{children:a.loading})]}):T?(0,x.jsxs)(`div`,{className:`py-20 text-center text-red-500`,children:[(0,x.jsx)(oe,{className:`w-10 h-10 mx-auto mb-3 text-red-400`}),(0,x.jsx)(`span`,{children:T})]}):S.length===0?(0,x.jsxs)(`div`,{className:`py-20 text-center text-slate-500`,children:[(0,x.jsx)(c,{className:`w-10 h-10 mx-auto mb-3`}),(0,x.jsx)(`span`,{children:a.empty})]}):(0,x.jsx)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-3 sm:gap-4`,children:S.map(e=>(0,x.jsxs)(`div`,{className:`flex flex-col`,children:[(0,x.jsx)(l,{book:e,isFav:Ce.has(e.id),onToggleFav:Ve,onCompare:He,onPlayTrailer:G,onSearchAuthor:Le,onSearchCategory:Re,onRead:Be}),_e===e.id&&(0,x.jsx)(`div`,{className:`bg-[#0f101f] border border-[#1f1f3a] rounded-b-2xl p-4 text-xs mt-[-10px] space-y-4 shadow-inner`,children:xe?(0,x.jsx)(`div`,{className:`text-center text-slate-500 py-3`,children:a.comparingText}):(0,x.jsx)(`div`,{className:`overflow-x-auto`,children:(0,x.jsxs)(`table`,{className:`w-full text-left text-[11px] text-slate-300`,children:[(0,x.jsx)(`thead`,{children:(0,x.jsxs)(`tr`,{className:`border-b border-[#2d2d55] text-slate-400 font-bold`,children:[(0,x.jsx)(`th`,{className:`pb-2`,children:o===`vi`?`Chỉ số`:o===`en`?`Metric`:`指标`}),(0,x.jsx)(`th`,{className:`pb-2`,children:o===`vi`?`Điểm số`:o===`en`?`Score`:`评分`}),(0,x.jsx)(`th`,{className:`pb-2`,children:o===`vi`?`Nguồn tiêu biểu`:o===`en`?`Best Source`:`推荐站`})]})}),(0,x.jsxs)(`tbody`,{className:`divide-y divide-[#1f1f3a]`,children:[(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`td`,{className:`py-2 font-semibold text-slate-400`,children:o===`vi`?`Tốc độ cập nhật`:o===`en`?`Update Speed`:`更新速度`}),(0,x.jsx)(`td`,{className:`py-2 text-emerald-400 font-bold`,children:`4.8`}),(0,x.jsxs)(`td`,{className:`py-2 text-slate-300`,children:[`Metruyenchu `,(0,x.jsx)(`span`,{className:`text-slate-500 text-[10px]`,children:`31 votes`})]})]}),(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`td`,{className:`py-2 font-semibold text-slate-400`,children:o===`vi`?`Quảng cáo & Sạch`:o===`en`?`Ads & Cleanliness`:`广告与排版`}),(0,x.jsx)(`td`,{className:`py-2 text-emerald-400 font-bold`,children:`4.9`}),(0,x.jsxs)(`td`,{className:`py-2 text-slate-300`,children:[`TruyenFull `,(0,x.jsx)(`span`,{className:`text-slate-500 text-[10px]`,children:`81 votes`})]})]}),(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`td`,{className:`py-2 font-semibold text-slate-400`,children:o===`vi`?`Độ chuẩn bản dịch`:o===`en`?`Translation Standard`:`翻译准确度`}),(0,x.jsx)(`td`,{className:`py-2 text-emerald-400 font-bold`,children:`4.7`}),(0,x.jsxs)(`td`,{className:`py-2 text-slate-300`,children:[`MeDoc `,(0,x.jsx)(`span`,{className:`text-slate-500 text-[10px]`,children:`63 votes`})]})]})]})]})})})]},e.id))}),B>1&&(0,x.jsxs)(`div`,{className:`flex flex-wrap justify-center gap-2 pt-6`,children:[(0,x.jsxs)(`button`,{onClick:()=>z(e=>Math.max(1,e-1)),disabled:R===1,className:`px-4 py-2 bg-[#121225] border border-[#1f1f3a] rounded-lg disabled:opacity-40 disabled:cursor-not-allowed hover:bg-brand-500 hover:text-white transition-all text-xs font-semibold`,children:[`« `,o===`vi`?`Trước`:o===`en`?`Prev`:`上一页`]}),Array.from({length:Math.min(5,B)},(e,t)=>{let n=R;return n=R<=3?t+1:R>=B-2?B-4+t:R-2+t,n<1||n>B?null:(0,x.jsx)(`button`,{onClick:()=>z(n),className:`w-9 h-9 rounded-lg border text-xs font-semibold transition-all ${R===n?`bg-purple-600 border-purple-600 text-white shadow-md`:`bg-[#121225] border-[#1f1f3a] hover:bg-white/5 text-slate-400`}`,children:n},n)}),(0,x.jsxs)(`button`,{onClick:()=>z(e=>Math.min(B,e+1)),disabled:R===B,className:`px-4 py-2 bg-[#121225] border border-[#1f1f3a] rounded-lg disabled:opacity-40 disabled:cursor-not-allowed hover:bg-brand-500 hover:text-white transition-all text-xs font-semibold`,children:[o===`vi`?`Sau`:o===`en`?`Next`:`下一页`,` »`]})]})]}),(0,x.jsxs)(`div`,{className:`space-y-6`,children:[(0,x.jsxs)(`div`,{className:`bg-[#121225]/60 border border-[#1f1f3a] rounded-2xl p-5 shadow-xl`,children:[(0,x.jsxs)(`h3`,{className:`text-sm font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-amber-400 to-amber-200 flex items-center gap-2 mb-4`,children:[(0,x.jsx)(e,{className:`w-5 h-5 text-amber-400`}),` `,o===`vi`?`BẢNG XẾP HẠNG HOT`:o===`en`?`HOT RANKINGS`:`热门排行`]}),we.length>0?(0,x.jsx)(`div`,{className:`space-y-4`,children:we.map((e,t)=>(0,x.jsxs)(`div`,{className:`flex items-center justify-between border-b border-white/5 pb-3 last:border-0 last:pb-0`,children:[(0,x.jsxs)(`div`,{className:`flex items-center gap-3 min-w-0`,children:[(0,x.jsx)(`span`,{className:`w-6 h-6 rounded-full flex items-center justify-center text-xs font-extrabold shrink-0 shadow-md ${t===0?`bg-gradient-to-br from-yellow-300 to-amber-500 text-white`:t===1?`bg-gradient-to-br from-slate-200 to-slate-400 text-slate-800`:t===2?`bg-gradient-to-br from-amber-600 to-amber-800 text-white`:`bg-white/5 text-slate-400 border border-white/10`}`,children:t+1}),(0,x.jsxs)(`div`,{className:`min-w-0`,children:[(0,x.jsx)(`h4`,{className:`text-xs font-bold text-slate-200 truncate`,children:e.title}),(0,x.jsxs)(`p`,{className:`text-[10px] text-slate-500 mt-0.5`,children:[`✍ `,e.author]})]})]}),(0,x.jsxs)(`div`,{className:`flex items-center gap-1 text-[10px] shrink-0 font-bold`,children:[e.trend===`up`&&(0,x.jsxs)(`span`,{className:`text-emerald-500 flex items-center`,children:[`▲ `,e.diff]}),e.trend===`down`&&(0,x.jsxs)(`span`,{className:`text-red-500 flex items-center`,children:[`▼ `,e.diff]}),e.trend===`none`&&(0,x.jsx)(`span`,{className:`text-slate-500`,children:`—`})]})]},e.id))}):(0,x.jsx)(`p`,{className:`text-slate-500 text-xs text-center py-6`,children:o===`vi`?`Chưa có xếp hạng.`:o===`en`?`No rankings.`:`暂无排行`})]}),(0,x.jsxs)(`div`,{className:`bg-[#121225]/60 border border-[#1f1f3a]/85 rounded-2xl p-5 shadow-xl space-y-4`,children:[(0,x.jsxs)(`h3`,{className:`text-sm font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-brand-300 to-purple-300 flex items-center gap-2`,children:[(0,x.jsx)(r,{className:`w-5 h-5 text-brand-400`}),` `,o===`vi`?`Hoạt động cộng đồng`:o===`en`?`Community Activity`:`社区动态`]}),(0,x.jsx)(`div`,{className:`flex -space-x-2 overflow-hidden py-1 border-b border-white/5 pb-3`,children:Pe.map(e=>(0,x.jsx)(`img`,{className:`inline-block h-6 w-6 rounded-full ring-2 ring-[#121225] object-cover`,src:e.avatar,alt:e.user},e.id))}),(0,x.jsx)(`div`,{className:`space-y-4`,children:Pe.map(e=>{let t=`bg-emerald-500/15 border-emerald-500/35 text-emerald-400`;return e.source===`Truyenchu`&&(t=`bg-sky-500/15 border-sky-500/35 text-sky-400`),e.source===`Nady knise`&&(t=`bg-purple-500/15 border-purple-500/35 text-purple-400`),(0,x.jsxs)(`div`,{className:`border-b border-white/5 pb-3.5 last:border-0 last:pb-0 space-y-2`,children:[(0,x.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,x.jsx)(`div`,{className:`flex items-center gap-2`,children:(0,x.jsx)(`span`,{className:`text-slate-200 text-xs font-bold`,children:e.user})}),(0,x.jsx)(`span`,{className:`text-slate-500 text-[10px]`,children:e.time})]}),(0,x.jsxs)(`div`,{className:`flex gap-2 items-center`,children:[(0,x.jsx)(`span`,{className:`px-1.5 py-0.5 rounded text-[8px] font-bold border uppercase shrink-0 ${t}`,children:e.source}),(0,x.jsx)(`p`,{className:`text-slate-300 text-xs leading-normal flex-1`,children:e.comment})]})]},e.id)})})]})]})]}),(0,x.jsx)(ie,{slot:`discover-bottom`}),(0,x.jsx)(ce,{isOpen:Ee,onClose:()=>De(!1),onSelectBook:Ke})]})}export{S as default}; \ No newline at end of file diff --git a/frontend-web/dist/assets/Downloads-DcrmkLWQ.js b/frontend-web/dist/assets/Downloads-DcrmkLWQ.js new file mode 100644 index 0000000000000000000000000000000000000000..839f59492e4c2b251dd8c656e1105890db9ffbdf --- /dev/null +++ b/frontend-web/dist/assets/Downloads-DcrmkLWQ.js @@ -0,0 +1,3 @@ +import{d as e,r as t,s as n,t as r}from"./MainLayout-COiTxmNr.js";import{o as i}from"./square-DZKJ0QGR.js";import{t as a}from"./file-text-mhTXpwIY.js";import{t as o}from"./laptop-BPoCx4gb.js";import{C as ee,F as s,M as c,S as te,b as l,g as u,j as d,w as f}from"./index-yRoRoI6u.js";var p=l(`info`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 16v-4`,key:`1dtifu`}],[`path`,{d:`M12 8h.01`,key:`e9boi3`}]]),m=s(d(),1),h=c(),g=e=>(0,h.jsxs)(`svg`,{...e,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,h.jsx)(`circle`,{cx:`12`,cy:`12`,r:`10`}),(0,h.jsx)(`circle`,{cx:`12`,cy:`12`,r:`4`}),(0,h.jsx)(`line`,{x1:`21.17`,y1:`8`,x2:`12`,y2:`8`}),(0,h.jsx)(`line`,{x1:`3.95`,y1:`6.06`,x2:`8.54`,y2:`14`}),(0,h.jsx)(`line`,{x1:`10.88`,y1:`21.94`,x2:`15.46`,y2:`14`})]}),_=e=>(0,h.jsxs)(`svg`,{...e,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,h.jsx)(`path`,{d:`M22 12L3 12`,strokeWidth:`1.5`}),(0,h.jsx)(`path`,{d:`M12 2L12 22`,strokeWidth:`1.5`}),(0,h.jsx)(`path`,{d:`M3 5.41L10.33 4.41V11.58H3V5.41Z`,fill:`currentColor`,opacity:`0.2`}),(0,h.jsx)(`path`,{d:`M11.67 4.23L21 3V11.58H11.67V4.23Z`,fill:`currentColor`,opacity:`0.2`}),(0,h.jsx)(`path`,{d:`M3 12.42H10.33V19.59L3 18.59V12.42Z`,fill:`currentColor`,opacity:`0.2`}),(0,h.jsx)(`path`,{d:`M11.67 12.42H21V21L11.67 19.77V12.42Z`,fill:`currentColor`,opacity:`0.2`}),(0,h.jsx)(`path`,{d:`M3 5.41L10.33 4.41V11.58H3V5.41ZM11.67 4.23L21 3V11.58H11.67V4.23ZM3 12.42H10.33V19.59L3 18.59V12.42ZM11.67 12.42H21V21L11.67 19.77V12.42Z`})]});function v(){let{lang:s}=te(),{user:c}=ee(),[l,d]=(0,m.useState)(!1),[v,ne]=(0,m.useState)(!1),y=typeof window<`u`&&!!window.electron,[b,re]=(0,m.useState)({extension:{version:`1.0.0`,download_url:`/downloads/tts_extension.zip`,file_size:`10.7 MB`,release_notes:`Cập nhật dịch nhanh và tối ưu hóa Chrome Extension Helper`},desktop_linux:{version:`0.0.0`,download_url:`https://huggingface.co/datasets/Cong123779/tienhiep-data/resolve/main/downloads/TienHiepAI-0.0.0.AppImage`,file_size:`116 MB`,release_notes:`Phiên bản AppImage beta dành cho Linux`},desktop_windows:{version:`0.0.0`,download_url:`#`,file_size:`0 MB`,release_notes:`Bản Windows chính thức sắp ra mắt`}}),[x,ie]=(0,m.useState)(`extension`),[ae,oe]=(0,m.useState)(``),[se,ce]=(0,m.useState)(``),[le,S]=(0,m.useState)(``),[ue,C]=(0,m.useState)(``),[de,fe]=(0,m.useState)(!1),[pe,me]=(0,m.useState)(``),[w,T]=(0,m.useState)(!1),[E,D]=(0,m.useState)(0),[O,k]=(0,m.useState)(``),[A,j]=(0,m.useState)(!1),[M,N]=(0,m.useState)(`idle`),[P,F]=(0,m.useState)(``),[I,L]=(0,m.useState)(!1),R=async(e,t)=>{if(!window.electron||!window.electron.downloadAndRunUpdate)return;T(!0),D(0),k(s===`vi`?`Đang kết nối tải bản cập nhật...`:`Connecting to download update...`);let n=window.electron.onUpdateDownloadProgress(e=>{e&&typeof e.percent==`number`&&(D(e.percent),k(s===`vi`?`Đang tải: ${e.percent}% (${(e.downloadedBytes/(1024*1024)).toFixed(1)}MB / ${(e.totalBytes/(1024*1024)).toFixed(1)}MB)`:`Downloading: ${e.percent}% (${(e.downloadedBytes/(1024*1024)).toFixed(1)}MB / ${(e.totalBytes/(1024*1024)).toFixed(1)}MB)`))});try{let n=await window.electron.downloadAndRunUpdate(e,t);n&&n.success?k(s===`vi`?`Tải về hoàn tất! Đang khởi chạy gói cài đặt...`:`Download complete! Launching setup...`):(T(!1),alert((s===`vi`?`Lỗi tải cập nhật: `:`Error loading update: `)+(n.error||`Unknown`)))}catch(e){T(!1),alert((s===`vi`?`Lỗi hệ thống: `:`System error: `)+e.message)}finally{n()}},z=async(e,t)=>{if(!window.electron||!window.electron.quickPatchUpdate)return;T(!0),D(0),k(s===`vi`?`Đang kết nối tải bản vá...`:`Connecting to download patch...`);let n=window.electron.onUpdateDownloadProgress(e=>{e&&typeof e.percent==`number`&&(D(e.percent),k(s===`vi`?`Đang tải bản vá: ${e.percent}% (${(e.downloadedBytes/(1024*1024)).toFixed(2)}MB / ${(e.totalBytes/(1024*1024)).toFixed(2)}MB)`:`Downloading patch: ${e.percent}% (${(e.downloadedBytes/(1024*1024)).toFixed(2)}MB / ${(e.totalBytes/(1024*1024)).toFixed(2)}MB)`))});try{let n=await window.electron.quickPatchUpdate(e,t);n&&n.success?k(s===`vi`?`Áp dụng bản vá thành công! Đang khởi động lại ứng dụng...`:`Patch applied successfully! Restarting...`):(T(!1),alert((s===`vi`?`Lỗi cập nhật bản vá: `:`Patch update error: `)+(n.error||`Unknown`)))}catch(e){T(!1),alert((s===`vi`?`Lỗi hệ thống: `:`System error: `)+e.message)}finally{n()}},he=async()=>{if(window.electron?.uninstallApp){j(!1),N(`running`),F(s===`vi`?`Đang gỡ cài đặt...`:`Uninstalling...`);try{let e=await window.electron.uninstallApp();e?.success?e.platform===`win32`&&e.launched?(N(`done`),F(s===`vi`?`✅ Trình gỡ cài đặt đã khởi chạy. Ứng dụng sẽ đóng lại...`:`✅ Uninstaller launched. App will close...`)):e.platform===`linux`&&(N(`done`),F(s===`vi`?`✅ Đã gỡ đăng ký hệ thống (desktop entries, MIME). Để xóa hoàn toàn, hãy xóa file AppImage và thư mục dữ liệu:\n${e.userDataPath}`:`✅ System entries removed (desktop, MIME). To fully uninstall, delete the AppImage file and data folder:\n${e.userDataPath}`)):(N(`error`),F((s===`vi`?`❌ Lỗi: `:`❌ Error: `)+(e?.error||`Unknown`)))}catch(e){N(`error`),F(`❌ `+e.message)}}},ge=async()=>{if(window.electron?.clearUserData){L(!1);try{let e=await window.electron.clearUserData();e?.success?alert((s===`vi`?`✅ Đã xóa dữ liệu cục bộ: +`:`✅ Local data cleared: +`)+(e.cleared?.join(`, `)||`none`)):alert(`❌ `+(e?.error||`Failed`))}catch(e){alert(`❌ `+e.message)}}},[B,V]=(0,m.useState)(``),[H,U]=(0,m.useState)(``),W=e=>{if(!e)return[];let t=e.history||[],n=[{version:e.version,download_url:e.download_url,patch_url:e.patch_url,file_size:e.file_size,release_notes:e.release_notes},...t],r=[],i=new Set;for(let e of n)!e.version||!e.download_url||e.download_url===`#`||i.has(e.version)||(i.add(e.version),r.push(e));return r};(0,m.useEffect)(()=>{_e()},[]);let _e=async()=>{try{let e=await f.get(`/api/releases`);if(e.data&&e.data.success&&e.data.releases){if(re(t=>({...t,...e.data.releases})),e.data.releases.desktop_linux){let t=W(e.data.releases.desktop_linux);t.length>0?V(t[0].version):V(e.data.releases.desktop_linux.version)}if(e.data.releases.desktop_windows){let t=W(e.data.releases.desktop_windows);t.length>0?U(t[0].version):U(e.data.releases.desktop_windows.version)}}}catch(e){console.error(`Failed to load releases from API:`,e)}};(0,m.useEffect)(()=>{let e=b[x];e&&(oe(e.version||``),ce(e.download_url||``),S(e.file_size||``),C(e.release_notes||``))},[x,b]);let G={vi:{title:`Tải App & Extension`,subtitle:`Đồng bộ trải nghiệm đọc truyện và dịch thuật AI tối ưu trên mọi nền tảng trình duyệt và máy tính.`,extensionTitle:`Chrome Extension Helper`,extensionDesc:`Tiện ích tích hợp trực tiếp vào trình duyệt giúp tự động lấy chương, dịch nhanh tiếng Trung và đồng bộ lịch sử đọc với Web App.`,extensionBtn:`Tải tiện ích (.ZIP)`,extensionStepHeader:`Các bước cài đặt thủ công (Developer Mode)`,extSteps:[`Tải tệp tin tts_extension.zip bằng nút bên trên và giải nén ra một thư mục riêng biệt.`,`Mở trình duyệt Chrome hoặc Edge, truy cập đường dẫn quản lý tiện ích: chrome://extensions/`,`Gạt nút kích hoạt Chế độ nhà phát triển (Developer mode) ở góc trên bên phải màn hình.`,`Click chọn Tải tiện ích đã giải nén (Load unpacked) ở góc trên bên trái.`,`Chọn thư mục đã giải nén ở Bước 1. Biểu tượng Tiên Hiệp AI sẽ xuất hiện trên thanh công cụ!`],appTitle:`Linux Client (AppImage)`,appDesc:`Ứng dụng chuyên dụng cho hệ điều hành Linux, tối ưu hiệu năng dịch thuật, lưu trữ sách ngoại tuyến (Offline) và tự động cập nhật từ điển.`,appBtnLinux:`Tải bản Linux (.AppImage)`,appStepHeader:`Cách chạy thủ công`,appSteps:[`Tải file cài đặt TienHiepAI-0.0.0.AppImage về máy tính.`,`Cấp quyền thực thi và chạy file bằng lệnh:`],copyTooltip:`Sao chép lệnh`,copiedTooltip:`Đã sao chép!`,noteTitle:`⚠️ Lưu ý đồng bộ`,noteText:`Vui lòng đăng nhập trên App/Ext bằng cùng tài khoản của trang Web để số liệu dịch thuật và tổng thời gian đọc được đồng bộ hóa chuẩn xác nhất.`},en:{title:`Download App & Extension`,subtitle:`Synchronize your reading experience and AI translations across all browsers and desktop platforms.`,extensionTitle:`Chrome Extension Helper`,extensionDesc:`Integrate directly into your browser to automatically capture chapters, translate Chinese instantly, and sync reading history with the Web App.`,extensionBtn:`Download Extension (.ZIP)`,extensionStepHeader:`Manual Installation Steps (Developer Mode)`,extSteps:[`Download the tts_extension.zip using the button above and extract it into a separate folder.`,`Open Chrome or Edge and navigate to the extension manager: chrome://extensions/`,`Toggle on the Developer mode switch at the top-right corner of the window.`,`Click the Load unpacked button at the top-left corner.`,`Select the folder extracted in Step 1. The Tien Hiep AI icon will appear on your toolbar!`],appTitle:`Linux Client (AppImage)`,appDesc:`Specialized desktop application for Linux translation performance, offline book storage, and automatic local dictionary updates.`,appBtnLinux:`Download for Linux (.AppImage)`,appStepHeader:`Manual Run Instructions`,appSteps:[`Download the TienHiepAI-0.0.0.AppImage file to your computer.`,`Grant execution permission using the command below:`],copyTooltip:`Copy command`,copiedTooltip:`Copied!`,noteTitle:`⚠️ Sync Warning`,noteText:`Please log in on all clients using the same account as the web portal to ensure translation metrics and reading logs sync perfectly.`},zh:{title:`下载中心`,subtitle:`在所有浏览器和电脑平台上同步您的阅读体验与 AI 翻译记录。`,extensionTitle:`Chrome 辅助插件`,extensionDesc:`直接嵌入浏览器以自动抓取章节、快速翻译中文,并与网页版同步阅读进度和统计数据。`,extensionBtn:`下载插件包 (.ZIP)`,extensionStepHeader:`手动安装步骤 (开发者模式)`,extSteps:[`使用上方按钮下载 tts_extension.zip 并解压到一个独立的文件夹中。`,`打开 Chrome 或 Edge 浏览器,访问插件管理器:chrome://extensions/`,`开启右上角的 开发者模式 (Developer mode) 开关。`,`点击左上角的 加载已解压的扩展程序 (Load unpacked) 按钮。`,`选择您在步骤1中解压的文件夹,仙侠 AI 图标即会出现在浏览器工具栏上!`],appTitle:`Linux 客户端 (AppImage)`,appDesc:`专为 Linux 打造的桌面客户端,提供极佳的翻译性能、离线书籍缓存以及自动本地词库更新。`,appBtnLinux:`下载 Linux 版 (.AppImage)`,appStepHeader:`手动运行指南`,appSteps:[`将 TienHiepAI-0.0.0.AppImage 文件下载到您的电脑中。`,`使用以下命令赋予可执行权限:`],copyTooltip:`复制命令`,copiedTooltip:`已复制!`,noteTitle:`⚠️ 重要提示`,noteText:`浏览器插件和电脑桌面端均通过您的账号进行数据同步。请确保在所有客户端上登录相同的账号,以便精确统计您的翻译字符数和总阅读时长。`}},K=W(b.desktop_windows),q=W(b.desktop_linux),J=q.find(e=>e.version===B)||q[0]||b.desktop_linux,Y=K.find(e=>e.version===H)||K[0]||b.desktop_windows,X=G[s]||G.vi,Z=`chmod +x ${J.download_url.substring(J.download_url.lastIndexOf(`/`)+1)||`TienHiepAI.AppImage`} && ./${J.download_url.substring(J.download_url.lastIndexOf(`/`)+1)||`TienHiepAI.AppImage`}`,Q=`sudo curl -L -o /usr/local/bin/tienhiep-ai "${J.download_url}" && sudo chmod +x /usr/local/bin/tienhiep-ai`,$=(e,t)=>{navigator.clipboard.writeText(e),t(!0),setTimeout(()=>t(!1),2e3)};return(0,h.jsxs)(r,{children:[(0,h.jsxs)(`div`,{className:`max-w-6xl mx-auto space-y-8 py-4 sm:py-6`,children:[(0,h.jsxs)(`div`,{className:`text-center space-y-3 max-w-3xl mx-auto`,children:[(0,h.jsx)(`div`,{className:`inline-flex p-3 bg-purple-600/10 rounded-full border border-purple-500/20 text-purple-400 mb-2 animate-bounce`,children:(0,h.jsx)(t,{className:`w-6 h-6`})}),(0,h.jsx)(`h1`,{className:`text-2xl sm:text-4xl font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-purple-400 via-indigo-200 to-purple-300 tracking-wide uppercase`,children:X.title}),(0,h.jsx)(`p`,{className:`text-slate-400 text-sm leading-relaxed sm:text-base`,children:X.subtitle})]}),(0,h.jsxs)(`div`,{className:`bg-[#191635]/40 border border-indigo-500/20 rounded-2xl p-4 sm:p-5 flex gap-4 items-start shadow-md`,children:[(0,h.jsx)(p,{className:`w-5 h-5 text-indigo-400 shrink-0 mt-0.5`}),(0,h.jsxs)(`div`,{className:`space-y-1`,children:[(0,h.jsx)(`h4`,{className:`text-xs font-bold text-white uppercase tracking-wider`,children:X.noteTitle}),(0,h.jsx)(`p`,{className:`text-slate-300 text-xs leading-relaxed`,children:X.noteText})]})]}),!1,(0,h.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-3 gap-6`,children:[(0,h.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#1f1f3a]/80 rounded-3xl p-6 flex flex-col justify-between shadow-xl relative hover:border-emerald-500/20 hover:shadow-emerald-950/5 transition-all duration-300 group`,children:[(0,h.jsx)(`div`,{className:`absolute top-0 right-0 w-20 h-20 bg-emerald-500/5 rounded-bl-full filter blur-xl opacity-50 group-hover:bg-emerald-500/10 transition-colors`}),(0,h.jsxs)(`div`,{className:`space-y-5`,children:[(0,h.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,h.jsx)(`div`,{className:`p-3 bg-emerald-500/10 border border-emerald-500/20 rounded-2xl text-emerald-400 group-hover:scale-115 transition-transform`,children:(0,h.jsx)(g,{className:`w-5 h-5`})}),(0,h.jsxs)(`div`,{children:[(0,h.jsx)(`h3`,{className:`text-base font-bold text-white`,children:X.extensionTitle}),(0,h.jsxs)(`span`,{className:`inline-block text-[9px] font-black tracking-widest text-emerald-400 bg-emerald-500/10 px-2 py-0.5 rounded-full uppercase mt-0.5`,children:[`v`,b.extension.version,` • Verified`]})]})]}),(0,h.jsx)(`p`,{className:`text-slate-400 text-xs leading-relaxed min-h-[50px]`,children:X.extensionDesc}),(0,h.jsxs)(`div`,{children:[(0,h.jsxs)(`a`,{href:b.extension.download_url,download:`tts_extension.zip`,className:`w-full inline-flex items-center justify-center gap-2 bg-emerald-600 hover:bg-emerald-500 active:scale-98 text-white font-extrabold px-5 py-3 rounded-xl shadow-lg transition-all text-xs text-center`,children:[(0,h.jsx)(t,{className:`w-4 h-4`}),(0,h.jsx)(`span`,{children:X.extensionBtn})]}),(0,h.jsxs)(`p`,{className:`text-center text-[9px] text-slate-500 mt-2`,children:[`ZIP Format • Size: ~`,b.extension.file_size]})]}),(0,h.jsxs)(`div`,{className:`bg-[#0b0b14]/50 border border-emerald-500/10 p-3 rounded-xl space-y-1`,children:[(0,h.jsx)(`span`,{className:`text-[9px] font-bold text-emerald-400 uppercase tracking-widest`,children:`📝 Changelog`}),(0,h.jsxs)(`p`,{className:`text-slate-300 text-[11px] leading-relaxed italic`,children:[`"`,b.extension.release_notes,`"`]})]}),(0,h.jsxs)(`div`,{className:`border-t border-[#1f1f3a]/50 pt-4 space-y-3`,children:[(0,h.jsxs)(`h4`,{className:`text-xs font-bold text-slate-200 uppercase tracking-wider flex items-center gap-2`,children:[(0,h.jsx)(a,{className:`w-3.5 h-3.5 text-slate-400`}),` `,X.extensionStepHeader]}),(0,h.jsx)(`ol`,{className:`space-y-3 text-[11px] text-slate-400 list-none pl-0`,children:X.extSteps.map((e,t)=>(0,h.jsxs)(`li`,{className:`flex gap-2 items-start`,children:[(0,h.jsx)(`span`,{className:`w-4.5 h-4.5 rounded-full bg-emerald-500/10 border border-emerald-500/20 text-emerald-400 flex items-center justify-center font-bold text-[9px] shrink-0 mt-0.5`,children:t+1}),(0,h.jsx)(`span`,{className:`leading-relaxed`,children:e})]},t))})]})]})]}),(0,h.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#1f1f3a]/80 rounded-3xl p-6 flex flex-col justify-between shadow-xl relative hover:border-purple-500/20 hover:shadow-purple-950/5 transition-all duration-300 group`,children:[(0,h.jsx)(`div`,{className:`absolute top-0 right-0 w-20 h-20 bg-purple-500/5 rounded-bl-full filter blur-xl opacity-50 group-hover:bg-purple-500/10 transition-colors`}),(0,h.jsxs)(`div`,{className:`space-y-5`,children:[(0,h.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,h.jsx)(`div`,{className:`p-3 bg-purple-500/10 border border-purple-500/20 rounded-2xl text-purple-400 group-hover:scale-115 transition-transform`,children:(0,h.jsx)(o,{className:`w-5 h-5`})}),(0,h.jsxs)(`div`,{children:[(0,h.jsx)(`h3`,{className:`text-base font-bold text-white`,children:X.appTitle}),(0,h.jsxs)(`div`,{className:`flex flex-wrap gap-1.5 items-center mt-1`,children:[(0,h.jsxs)(`span`,{className:`inline-block text-[9px] font-black tracking-widest text-purple-400 bg-purple-500/10 px-2 py-0.5 rounded-full uppercase`,children:[`v`,J.version,` • Linux Beta`]}),q.length>1&&(0,h.jsx)(`select`,{value:B,onChange:e=>V(e.target.value),className:`bg-[#0b0b14] border border-[#1f1f3a] text-purple-400 font-extrabold text-[10px] rounded-lg px-1.5 py-0.5 focus:outline-none focus:border-purple-500 transition-colors cursor-pointer`,children:q.map(e=>(0,h.jsxs)(`option`,{value:e.version,children:[`v`,e.version]},e.version))})]})]})]}),(0,h.jsx)(`p`,{className:`text-slate-400 text-xs leading-relaxed min-h-[50px]`,children:X.appDesc}),(0,h.jsx)(`div`,{children:(0,h.jsxs)(`div`,{children:[y?J.patch_url?(0,h.jsxs)(`div`,{className:`space-y-2`,children:[(0,h.jsxs)(`button`,{onClick:()=>z(J.patch_url,J.version),className:`w-full inline-flex items-center justify-center gap-2 bg-gradient-to-r from-purple-600 to-indigo-600 hover:from-purple-500 hover:to-indigo-500 active:scale-98 text-white font-extrabold px-5 py-3 rounded-xl shadow-lg transition-all text-xs text-center cursor-pointer`,children:[(0,h.jsx)(e,{className:`w-4 h-4`}),(0,h.jsxs)(`span`,{children:[`⚡ Cập nhật nhanh lên v`,J.version,` (Khuyên dùng)`]})]}),(0,h.jsxs)(`button`,{onClick:()=>{let e=J.download_url;R(e,e.substring(e.lastIndexOf(`/`)+1)||`TienHiepAI.AppImage`)},className:`w-full inline-flex items-center justify-center gap-2 bg-slate-800 hover:bg-slate-700 active:scale-98 text-slate-300 font-extrabold px-5 py-2.5 rounded-xl border border-slate-700 transition-all text-[11px] text-center cursor-pointer`,children:[(0,h.jsx)(t,{className:`w-3.5 h-3.5`}),(0,h.jsx)(`span`,{children:`Tải bộ cài Full Setup (v1.0.6)`})]})]}):(0,h.jsxs)(`button`,{onClick:()=>{let e=J.download_url;if(!e||e===`#`){alert(s===`vi`?`Liên kết tải xuống không khả dụng.`:`Download link is not available.`);return}R(e,e.substring(e.lastIndexOf(`/`)+1)||`TienHiepAI.AppImage`)},className:`w-full inline-flex items-center justify-center gap-2 bg-purple-600 hover:bg-purple-500 active:scale-98 text-white font-extrabold px-5 py-3 rounded-xl shadow-lg transition-all text-xs text-center cursor-pointer`,children:[(0,h.jsx)(t,{className:`w-4 h-4`}),(0,h.jsx)(`span`,{children:`Tải bản Linux (.AppImage)`})]}):(0,h.jsxs)(`div`,{className:`space-y-2`,children:[(0,h.jsxs)(`a`,{href:J.download_url,className:`w-full inline-flex items-center justify-center gap-2 bg-purple-600 hover:bg-purple-500 active:scale-98 text-white font-extrabold px-5 py-3 rounded-xl shadow-lg transition-all text-xs text-center`,children:[(0,h.jsx)(t,{className:`w-4 h-4`}),(0,h.jsx)(`span`,{children:`Tải bản Linux (.AppImage)`})]}),J.download_url.includes(`1.0.6`)&&J.patch_url&&(0,h.jsxs)(`p`,{className:`text-[10px] text-amber-400 leading-normal bg-amber-500/5 border border-amber-500/10 p-2.5 rounded-xl text-center`,children:[`💡 `,(0,h.jsx)(`b`,{children:`Lưu ý:`}),` v`,J.version,` là bản nâng cấp nhanh. Bạn đang tải `,(0,h.jsx)(`b`,{children:`bộ cài nền tảng v1.0.6`}),`, sau khi mở app nó sẽ tự động update lên v`,J.version,` trong 3 giây.`]})]}),(0,h.jsxs)(`p`,{className:`text-center text-[9px] text-slate-500 mt-2`,children:[`AppImage Format • Size: ~`,J.file_size]})]})}),(0,h.jsxs)(`div`,{className:`bg-[#0b0b14]/50 border border-purple-500/10 p-3 rounded-xl space-y-1`,children:[(0,h.jsx)(`span`,{className:`text-[9px] font-bold text-purple-400 uppercase tracking-widest`,children:`📝 Changelog`}),(0,h.jsxs)(`p`,{className:`text-slate-300 text-[11px] leading-relaxed italic`,children:[`"`,J.release_notes,`"`]})]}),(0,h.jsxs)(`div`,{className:`border-t border-[#1f1f3a]/50 pt-4 space-y-4`,children:[(0,h.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,h.jsxs)(`h4`,{className:`text-xs font-black text-amber-400 uppercase tracking-wider flex items-center gap-2`,children:[(0,h.jsx)(n,{className:`w-3.5 h-3.5 text-amber-400`}),` ⚡ Cài đặt nhanh bằng lệnh SUDO`]}),(0,h.jsx)(`p`,{className:`text-[10px] text-slate-400 leading-relaxed`,children:`Mở Terminal và dán lệnh sau để tải, cấp quyền và cài đặt ứng dụng chạy trực tiếp:`}),(0,h.jsxs)(`div`,{className:`flex items-center justify-between gap-2 bg-[#0b0b14] border border-amber-500/30 rounded-xl px-3 py-2 font-mono text-[9px] text-amber-300 w-full overflow-x-auto select-all shadow-inner`,children:[(0,h.jsx)(`span`,{className:`truncate`,children:Q}),(0,h.jsx)(`button`,{onClick:()=>$(Q,ne),className:`p-1 hover:bg-white/5 rounded text-slate-400 hover:text-white transition-colors shrink-0`,title:v?X.copiedTooltip:X.copyTooltip,children:v?(0,h.jsx)(i,{className:`w-3 h-3 text-emerald-400`}):(0,h.jsx)(u,{className:`w-3 h-3`})})]}),(0,h.jsxs)(`p`,{className:`text-[9px] text-slate-500 font-bold`,children:[`💡 Sau khi chạy, bạn chỉ cần gõ `,(0,h.jsx)(`span`,{className:`text-purple-400 font-mono`,children:`tienhiep-ai`}),` tại Terminal để mở app bất cứ lúc nào!`]})]}),(0,h.jsxs)(`div`,{className:`space-y-1.5 pt-1 border-t border-[#1f1f3a]/30`,children:[(0,h.jsxs)(`h4`,{className:`text-xs font-bold text-slate-200 uppercase tracking-wider flex items-center gap-2`,children:[(0,h.jsx)(a,{className:`w-3.5 h-3.5 text-slate-400`}),` `,X.appStepHeader]}),(0,h.jsxs)(`ol`,{className:`space-y-2 text-[11px] text-slate-400 list-none pl-0`,children:[(0,h.jsxs)(`li`,{className:`flex gap-2 items-start`,children:[(0,h.jsx)(`span`,{className:`w-4.5 h-4.5 rounded-full bg-purple-500/10 border border-purple-500/20 text-purple-400 flex items-center justify-center font-bold text-[9px] shrink-0 mt-0.5`,children:`1`}),(0,h.jsx)(`span`,{className:`leading-relaxed`,children:X.appSteps[0]})]}),(0,h.jsxs)(`li`,{className:`flex gap-2 items-start w-full`,children:[(0,h.jsx)(`span`,{className:`w-4.5 h-4.5 rounded-full bg-purple-500/10 border border-purple-500/20 text-purple-400 flex items-center justify-center font-bold text-[9px] shrink-0 mt-0.5`,children:`2`}),(0,h.jsxs)(`div`,{className:`flex-1 space-y-1 min-w-0`,children:[(0,h.jsx)(`span`,{className:`leading-relaxed`,children:X.appSteps[1]}),(0,h.jsxs)(`div`,{className:`flex items-center justify-between gap-2 bg-[#0b0b14] border border-[#1f1f3a] rounded-xl px-3 py-1.5 font-mono text-[9px] text-purple-300 w-full overflow-x-auto select-all`,children:[(0,h.jsx)(`span`,{className:`truncate`,children:Z}),(0,h.jsx)(`button`,{onClick:()=>$(Z,d),className:`p-1 hover:bg-white/5 rounded text-slate-400 hover:text-white transition-colors shrink-0`,title:l?X.copiedTooltip:X.copyTooltip,children:l?(0,h.jsx)(i,{className:`w-3 h-3 text-emerald-400`}):(0,h.jsx)(u,{className:`w-3 h-3`})})]})]})]})]})]})]})]})]}),(0,h.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#1f1f3a]/80 rounded-3xl p-6 flex flex-col justify-between shadow-xl relative hover:border-blue-500/20 hover:shadow-blue-950/5 transition-all duration-300 group`,children:[(0,h.jsx)(`div`,{className:`absolute top-0 right-0 w-20 h-20 bg-blue-500/5 rounded-bl-full filter blur-xl opacity-50 group-hover:bg-blue-500/10 transition-colors`}),(0,h.jsxs)(`div`,{className:`space-y-5`,children:[(0,h.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,h.jsx)(`div`,{className:`p-3 bg-blue-500/10 border border-blue-500/20 rounded-2xl text-blue-400 group-hover:scale-115 transition-transform`,children:(0,h.jsx)(_,{className:`w-5 h-5`})}),(0,h.jsxs)(`div`,{children:[(0,h.jsx)(`h3`,{className:`text-base font-bold text-white`,children:`Windows Client`}),(0,h.jsxs)(`div`,{className:`flex flex-wrap gap-1.5 items-center mt-1`,children:[(0,h.jsx)(`span`,{className:`inline-block text-[9px] font-black tracking-widest px-2 py-0.5 rounded-full uppercase ${Y.download_url===`#`?`text-slate-500 bg-slate-500/10`:`text-blue-400 bg-blue-500/10`}`,children:Y.download_url===`#`?`Coming Soon`:`v${Y.version} • Stable`}),K.length>1&&(0,h.jsx)(`select`,{value:H,onChange:e=>U(e.target.value),className:`bg-[#0b0b14] border border-[#1f1f3a] text-blue-400 font-extrabold text-[10px] rounded-lg px-1.5 py-0.5 focus:outline-none focus:border-blue-500 transition-colors cursor-pointer`,children:K.map(e=>(0,h.jsxs)(`option`,{value:e.version,children:[`v`,e.version]},e.version))})]})]})]}),(0,h.jsx)(`p`,{className:`text-slate-400 text-xs leading-relaxed min-h-[50px]`,children:`Ứng dụng máy tính dành cho hệ điều hành Windows. Đầy đủ tính năng tối ưu hóa dịch thuật, lưu trữ sách, chạy mượt mà trên Win 10/11.`}),(0,h.jsxs)(`div`,{children:[Y.download_url===`#`?(0,h.jsxs)(`button`,{disabled:!0,className:`w-full inline-flex items-center justify-center gap-2 bg-slate-800/40 border border-slate-700/30 text-slate-500 font-bold px-5 py-3 rounded-xl text-xs text-center cursor-not-allowed`,children:[(0,h.jsx)(_,{className:`w-4 h-4 opacity-40`}),(0,h.jsx)(`span`,{children:`Bản Windows (Sắp ra mắt)`})]}):y?Y.patch_url?(0,h.jsxs)(`div`,{className:`space-y-2`,children:[(0,h.jsxs)(`button`,{onClick:()=>z(Y.patch_url,Y.version),className:`w-full inline-flex items-center justify-center gap-2 bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-500 hover:to-indigo-500 active:scale-98 text-white font-extrabold px-5 py-3 rounded-xl shadow-lg transition-all text-xs text-center cursor-pointer`,children:[(0,h.jsx)(e,{className:`w-4 h-4`}),(0,h.jsxs)(`span`,{children:[`⚡ Cập nhật nhanh lên v`,Y.version,` (Khuyên dùng)`]})]}),(0,h.jsxs)(`button`,{onClick:()=>{let e=Y.download_url;R(e,e.substring(e.lastIndexOf(`/`)+1)||`TienHiepAI-Setup.exe`)},className:`w-full inline-flex items-center justify-center gap-2 bg-slate-800 hover:bg-slate-700 active:scale-98 text-slate-300 font-extrabold px-5 py-2.5 rounded-xl border border-slate-700 transition-all text-[11px] text-center cursor-pointer`,children:[(0,h.jsx)(t,{className:`w-3.5 h-3.5`}),(0,h.jsx)(`span`,{children:`Tải bộ cài Full Setup (v1.0.6)`})]})]}):(0,h.jsxs)(`button`,{onClick:()=>{let e=Y.download_url;if(!e||e===`#`){alert(s===`vi`?`Liên kết tải xuống không khả dụng.`:`Download link is not available.`);return}R(e,e.substring(e.lastIndexOf(`/`)+1)||`TienHiepAI-Setup.exe`)},className:`w-full inline-flex items-center justify-center gap-2 bg-blue-600 hover:bg-blue-500 active:scale-98 text-white font-extrabold px-5 py-3 rounded-xl shadow-lg transition-all text-xs text-center cursor-pointer`,children:[(0,h.jsx)(t,{className:`w-4 h-4`}),(0,h.jsx)(`span`,{children:`Tải bản Windows (.EXE Setup)`})]}):(0,h.jsxs)(`div`,{className:`space-y-2`,children:[(0,h.jsxs)(`a`,{href:Y.download_url,className:`w-full inline-flex items-center justify-center gap-2 bg-blue-600 hover:bg-blue-500 active:scale-98 text-white font-extrabold px-5 py-3 rounded-xl shadow-lg transition-all text-xs text-center`,children:[(0,h.jsx)(t,{className:`w-4 h-4`}),(0,h.jsx)(`span`,{children:`Tải bản Windows (.EXE Setup)`})]}),Y.download_url.includes(`1.0.6`)&&Y.patch_url&&(0,h.jsxs)(`p`,{className:`text-[10px] text-amber-400 leading-normal bg-amber-500/5 border border-amber-500/10 p-2.5 rounded-xl text-center`,children:[`💡 `,(0,h.jsx)(`b`,{children:`Lưu ý:`}),` v`,Y.version,` là bản nâng cấp nhanh. Bạn đang tải `,(0,h.jsx)(`b`,{children:`bộ cài nền tảng v1.0.6`}),`, sau khi mở app nó sẽ tự động update lên v`,Y.version,` trong 3 giây.`]})]}),(0,h.jsxs)(`p`,{className:`text-center text-[9px] text-slate-500 mt-2`,children:[`Format: EXE Setup • Size: ~`,Y.file_size]})]}),(0,h.jsxs)(`div`,{className:`bg-[#0b0b14]/50 border border-blue-500/10 p-3 rounded-xl space-y-1`,children:[(0,h.jsx)(`span`,{className:`text-[9px] font-bold text-blue-400 uppercase tracking-widest`,children:`📝 Changelog`}),(0,h.jsxs)(`p`,{className:`text-slate-300 text-[11px] leading-relaxed italic`,children:[`"`,Y.release_notes,`"`]})]}),(0,h.jsxs)(`div`,{className:`border-t border-[#1f1f3a]/50 pt-4 space-y-3`,children:[(0,h.jsxs)(`h4`,{className:`text-xs font-bold text-slate-200 uppercase tracking-wider flex items-center gap-2`,children:[(0,h.jsx)(a,{className:`w-3.5 h-3.5 text-slate-400`}),` Hướng dẫn cài đặt`]}),(0,h.jsxs)(`ol`,{className:`space-y-3 text-[11px] text-slate-400 list-none pl-0`,children:[(0,h.jsxs)(`li`,{className:`flex gap-2 items-start`,children:[(0,h.jsx)(`span`,{className:`w-4.5 h-4.5 rounded-full bg-blue-500/10 border border-blue-500/20 text-blue-400 flex items-center justify-center font-bold text-[9px] shrink-0 mt-0.5`,children:`1`}),(0,h.jsx)(`span`,{className:`leading-relaxed`,children:`Tải tệp tin cài đặt Windows (khi phát hành chính thức).`})]}),(0,h.jsxs)(`li`,{className:`flex gap-2 items-start`,children:[(0,h.jsx)(`span`,{className:`w-4.5 h-4.5 rounded-full bg-blue-500/10 border border-blue-500/20 text-blue-400 flex items-center justify-center font-bold text-[9px] shrink-0 mt-0.5`,children:`2`}),(0,h.jsx)(`span`,{className:`leading-relaxed`,children:"Chạy file installer `.exe` và làm theo các bước hướng dẫn trên màn hình."})]})]})]})]})]})]}),y&&(0,h.jsxs)(`div`,{className:`bg-[#121225]/80 border border-rose-500/10 rounded-3xl p-6 shadow-xl space-y-4 relative overflow-hidden`,children:[(0,h.jsx)(`div`,{className:`absolute top-0 right-0 w-24 h-24 bg-rose-500/5 rounded-bl-full filter blur-2xl`}),(0,h.jsxs)(`div`,{className:`flex items-start gap-3 border-b border-rose-500/10 pb-4`,children:[(0,h.jsx)(`div`,{className:`p-2.5 bg-rose-500/10 border border-rose-500/20 rounded-xl text-rose-400 shrink-0 mt-0.5`,children:(0,h.jsxs)(`svg`,{className:`w-4 h-4`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,h.jsx)(`circle`,{cx:`12`,cy:`12`,r:`3`}),(0,h.jsx)(`path`,{d:`M19.07 4.93A10 10 0 0 0 4.93 19.07`}),(0,h.jsx)(`path`,{d:`M4.93 4.93A10 10 0 0 0 19.07 19.07`})]})}),(0,h.jsxs)(`div`,{children:[(0,h.jsx)(`h3`,{className:`text-sm font-extrabold text-white uppercase tracking-wider`,children:s===`vi`?`⚙️ Quản lý Ứng dụng`:`⚙️ App Management`}),(0,h.jsx)(`p`,{className:`text-[10px] text-rose-300/70 mt-0.5`,children:s===`vi`?`Gỡ cài đặt hoặc xóa dữ liệu cục bộ của ứng dụng.`:`Uninstall or clear local app data.`})]})]}),(0,h.jsxs)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 gap-4`,children:[(0,h.jsxs)(`div`,{className:`bg-rose-950/20 border border-rose-500/10 rounded-2xl p-4 space-y-3`,children:[(0,h.jsxs)(`div`,{className:`space-y-1`,children:[(0,h.jsx)(`h4`,{className:`text-xs font-bold text-rose-300 uppercase tracking-wider`,children:s===`vi`?`🗑️ Gỡ cài đặt ứng dụng`:`🗑️ Uninstall Application`}),(0,h.jsx)(`p`,{className:`text-[10px] text-slate-400 leading-relaxed`,children:s===`vi`?`Xóa các desktop entry, MIME handler đã đăng ký. Trên Windows sẽ chạy trình gỡ cài đặt NSIS.`:`Removes desktop entries and MIME handlers. On Windows, launches the NSIS uninstaller.`})]}),(0,h.jsxs)(`button`,{id:`btn-uninstall-app`,onClick:()=>j(!0),className:`w-full flex items-center justify-center gap-2 bg-rose-600/20 hover:bg-rose-600/40 border border-rose-500/30 text-rose-300 hover:text-rose-200 text-xs font-bold px-4 py-2.5 rounded-xl transition-all active:scale-95`,children:[(0,h.jsxs)(`svg`,{className:`w-3.5 h-3.5`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,h.jsx)(`polyline`,{points:`3 6 5 6 21 6`}),(0,h.jsx)(`path`,{d:`M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6`}),(0,h.jsx)(`path`,{d:`M10 11v6`}),(0,h.jsx)(`path`,{d:`M14 11v6`}),(0,h.jsx)(`path`,{d:`M9 6V4h6v2`})]}),s===`vi`?`Gỡ cài đặt...`:`Uninstall...`]})]}),(0,h.jsxs)(`div`,{className:`bg-amber-950/20 border border-amber-500/10 rounded-2xl p-4 space-y-3`,children:[(0,h.jsxs)(`div`,{className:`space-y-1`,children:[(0,h.jsx)(`h4`,{className:`text-xs font-bold text-amber-300 uppercase tracking-wider`,children:s===`vi`?`🧹 Xóa dữ liệu cục bộ`:`🧹 Clear Local Data`}),(0,h.jsx)(`p`,{className:`text-[10px] text-slate-400 leading-relaxed`,children:s===`vi`?`Xóa file cấu hình (app_config.json) và log debug. Tài khoản, sách và models KHÔNG bị xóa.`:`Deletes app_config.json and debug logs. Account, books, and models are NOT affected.`})]}),(0,h.jsxs)(`button`,{id:`btn-clear-userdata`,onClick:()=>L(!0),className:`w-full flex items-center justify-center gap-2 bg-amber-600/20 hover:bg-amber-600/40 border border-amber-500/30 text-amber-300 hover:text-amber-200 text-xs font-bold px-4 py-2.5 rounded-xl transition-all active:scale-95`,children:[(0,h.jsx)(`svg`,{className:`w-3.5 h-3.5`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:(0,h.jsx)(`path`,{d:`M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z`})}),s===`vi`?`Xóa dữ liệu...`:`Clear Data...`]})]})]})]})]}),w&&(0,h.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/75 backdrop-blur-sm p-4 animate-fade-in`,children:(0,h.jsxs)(`div`,{className:`bg-[#131324] border border-[#2d2d6b] rounded-3xl p-6 max-w-md w-full text-center space-y-4 shadow-2xl`,children:[(0,h.jsx)(`h3`,{className:`text-lg font-extrabold text-white`,children:s===`vi`?`Tự Động Cập Nhật Phiên Bản`:`Automatic Version Update`}),(0,h.jsx)(`p`,{className:`text-xs text-slate-300`,children:O}),(0,h.jsx)(`div`,{className:`w-full bg-[#1c1c38] rounded-full h-3 border border-indigo-950/30 overflow-hidden relative`,children:(0,h.jsx)(`div`,{className:`bg-gradient-to-r from-purple-500 to-indigo-500 h-full rounded-full transition-all duration-300 shadow-inner`,style:{width:`${E}%`}})}),(0,h.jsxs)(`div`,{className:`flex justify-between items-center text-[10px] font-bold text-slate-500`,children:[(0,h.jsx)(`span`,{children:`0%`}),(0,h.jsxs)(`span`,{className:`text-purple-400 text-sm font-black`,children:[E,`%`]}),(0,h.jsx)(`span`,{children:`100%`})]}),(0,h.jsx)(`p`,{className:`text-[10px] text-slate-500 leading-relaxed`,children:s===`vi`?`⚠️ Lưu ý: Ứng dụng sẽ tự động đóng sau khi hoàn tất để kích hoạt trình cài đặt/phiên bản mới.`:`⚠️ Note: The application will close automatically after completion to launch the new installer/version.`})]})}),A&&(0,h.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm p-4 animate-fade-in`,children:(0,h.jsxs)(`div`,{className:`bg-[#131324] border border-rose-500/30 rounded-3xl p-6 max-w-sm w-full text-center space-y-4 shadow-2xl`,children:[(0,h.jsx)(`div`,{className:`w-14 h-14 mx-auto rounded-full bg-rose-500/10 border border-rose-500/20 flex items-center justify-center text-rose-400`,children:(0,h.jsxs)(`svg`,{className:`w-7 h-7`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,h.jsx)(`polyline`,{points:`3 6 5 6 21 6`}),(0,h.jsx)(`path`,{d:`M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6`}),(0,h.jsx)(`path`,{d:`M10 11v6`}),(0,h.jsx)(`path`,{d:`M14 11v6`}),(0,h.jsx)(`path`,{d:`M9 6V4h6v2`})]})}),(0,h.jsx)(`h3`,{className:`text-base font-extrabold text-white`,children:s===`vi`?`⚠️ Xác nhận Gỡ cài đặt`:`⚠️ Confirm Uninstall`}),(0,h.jsx)(`p`,{className:`text-xs text-slate-400 leading-relaxed`,children:s===`vi`?`Thao tác này sẽ xóa các desktop entries và MIME handler đã đăng ký với hệ thống. Bạn có chắc chắn muốn tiếp tục không?`:`This will remove registered desktop entries and MIME handlers from your system. Are you sure you want to continue?`}),(0,h.jsxs)(`div`,{className:`flex gap-3`,children:[(0,h.jsx)(`button`,{onClick:()=>j(!1),className:`flex-1 px-4 py-2.5 bg-slate-800/60 border border-slate-700/30 text-slate-300 text-xs font-bold rounded-xl hover:bg-slate-700/40 transition-all`,children:s===`vi`?`Hủy bỏ`:`Cancel`}),(0,h.jsx)(`button`,{onClick:he,className:`flex-1 px-4 py-2.5 bg-rose-600 hover:bg-rose-500 text-white text-xs font-extrabold rounded-xl transition-all active:scale-95 shadow-lg`,children:s===`vi`?`Gỡ cài đặt`:`Uninstall`})]})]})}),I&&(0,h.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm p-4 animate-fade-in`,children:(0,h.jsxs)(`div`,{className:`bg-[#131324] border border-amber-500/30 rounded-3xl p-6 max-w-sm w-full text-center space-y-4 shadow-2xl`,children:[(0,h.jsx)(`div`,{className:`w-14 h-14 mx-auto rounded-full bg-amber-500/10 border border-amber-500/20 flex items-center justify-center text-amber-400`,children:(0,h.jsx)(`svg`,{className:`w-7 h-7`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:(0,h.jsx)(`path`,{d:`M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z`})})}),(0,h.jsx)(`h3`,{className:`text-base font-extrabold text-white`,children:s===`vi`?`🗑️ Xóa dữ liệu cục bộ`:`🗑️ Clear Local Data`}),(0,h.jsx)(`p`,{className:`text-xs text-slate-400 leading-relaxed`,children:s===`vi`?`Sẽ xóa file cấu hình (app_config.json) và log debug. Dữ liệu tài khoản và models sẽ không bị xóa.`:`Will delete config file (app_config.json) and debug logs. Account data and models will NOT be deleted.`}),(0,h.jsxs)(`div`,{className:`flex gap-3`,children:[(0,h.jsx)(`button`,{onClick:()=>L(!1),className:`flex-1 px-4 py-2.5 bg-slate-800/60 border border-slate-700/30 text-slate-300 text-xs font-bold rounded-xl hover:bg-slate-700/40 transition-all`,children:s===`vi`?`Hủy bỏ`:`Cancel`}),(0,h.jsx)(`button`,{onClick:ge,className:`flex-1 px-4 py-2.5 bg-amber-600 hover:bg-amber-500 text-white text-xs font-extrabold rounded-xl transition-all active:scale-95 shadow-lg`,children:s===`vi`?`Xóa dữ liệu`:`Clear Data`})]})]})}),(M===`running`||M===`done`||M===`error`)&&(0,h.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm p-4 animate-fade-in`,children:(0,h.jsxs)(`div`,{className:`bg-[#131324] border rounded-3xl p-6 max-w-sm w-full text-center space-y-4 shadow-2xl ${M===`error`?`border-rose-500/30`:M===`done`?`border-emerald-500/30`:`border-indigo-500/30`}`,children:[M===`running`?(0,h.jsx)(`div`,{className:`w-10 h-10 mx-auto border-2 border-indigo-500/30 border-t-indigo-400 rounded-full animate-spin`}):(0,h.jsx)(`div`,{className:`w-14 h-14 mx-auto rounded-full flex items-center justify-center text-2xl ${M===`done`?`bg-emerald-500/10 border border-emerald-500/20`:`bg-rose-500/10 border border-rose-500/20`}`,children:M===`done`?`✅`:`❌`}),(0,h.jsx)(`h3`,{className:`text-sm font-extrabold text-white`,children:M===`running`?s===`vi`?`Đang xử lý...`:`Processing...`:s===`vi`?`Kết quả`:`Result`}),(0,h.jsx)(`p`,{className:`text-xs text-slate-300 leading-relaxed whitespace-pre-line`,children:P}),M!==`running`&&(0,h.jsx)(`button`,{onClick:()=>{N(`idle`),F(``)},className:`w-full px-4 py-2.5 bg-slate-800/60 border border-slate-700/30 text-slate-300 text-xs font-bold rounded-xl hover:bg-slate-700/40 transition-all`,children:s===`vi`?`Đóng`:`Close`})]})})]})}export{v as default}; \ No newline at end of file diff --git a/frontend-web/dist/assets/GoogleAd-CD0eT9Wp.js b/frontend-web/dist/assets/GoogleAd-CD0eT9Wp.js new file mode 100644 index 0000000000000000000000000000000000000000..bc15265750689becc48295dd220017361b2e2f85 --- /dev/null +++ b/frontend-web/dist/assets/GoogleAd-CD0eT9Wp.js @@ -0,0 +1 @@ +import{C as e,F as t,M as n,j as r}from"./index-yRoRoI6u.js";var i=t(r(),1),a=n();function o({slot:t,format:n=`auto`,responsive:r=`true`,className:o=``}){let{user:s,loading:c}=e();return(0,i.useEffect)(()=>{if(!c&&(!s||s.vip_status!==1))try{(window.adsbygoogle=window.adsbygoogle||[]).push({})}catch(e){console.error(`AdSense push error:`,e)}},[s,c]),c||s&&s.vip_status===1?null:(0,a.jsxs)(`div`,{className:`ad-container my-6 flex flex-col items-center justify-center w-full min-h-[100px] md:min-h-[200px] bg-[#121225]/20 border border-dashed border-[#1f1f3a]/60 rounded-2xl relative overflow-hidden ${o}`,children:[(0,a.jsx)(`span`,{className:`absolute top-2 right-3 text-[9px] uppercase tracking-wider text-slate-600 font-extrabold select-none`,children:`ADVERTISEMENT`}),(0,a.jsx)(`ins`,{className:`adsbygoogle w-full`,style:{display:`block`,minHeight:`90px`},"data-ad-client":`ca-pub-9548504602542886`,"data-ad-slot":t,"data-ad-format":n,"data-full-width-responsive":r})]})}export{o as t}; \ No newline at end of file diff --git a/frontend-web/dist/assets/HistoryPage-DD_Z3uyW.js b/frontend-web/dist/assets/HistoryPage-DD_Z3uyW.js new file mode 100644 index 0000000000000000000000000000000000000000..3560f763d358801a65a6a61664cdcce8ab9cde65 --- /dev/null +++ b/frontend-web/dist/assets/HistoryPage-DD_Z3uyW.js @@ -0,0 +1 @@ +import{t as e,y as t}from"./MainLayout-COiTxmNr.js";import{a as n,t as r}from"./square-DZKJ0QGR.js";import{t as i}from"./clock-DEPYmZZ-.js";import{t as a}from"./square-check-big-BhcFiAg6.js";import{t as o}from"./trash-2-DDhTqVwA.js";import{C as s,D as c,F as l,M as u,S as d,f,j as p,m,o as h,w as g}from"./index-yRoRoI6u.js";var _=l(p(),1),v=u();function y(){let{t:l,lang:u}=d(),{user:p,loading:y}=s(),b=c(),[x,S]=(0,_.useState)([]),[C,w]=(0,_.useState)(!0),[T,E]=(0,_.useState)(null),[D,O]=(0,_.useState)(``),[k,A]=(0,_.useState)(!1),[j,M]=(0,_.useState)(new Set);(0,_.useEffect)(()=>{if(!y){if(!p){w(!1);return}N()}},[p,y]);let N=async()=>{w(!0);try{S((await g.get(`/api/history`,{params:D?{q:D}:{}})).data)}catch(e){console.error(e)}finally{w(!1)}},P=async()=>{let e=u===`vi`?`Bạn có chắc muốn xóa tất cả lịch sử đọc?`:u===`en`?`Are you sure you want to clear all reading history?`:`您确定要清空所有阅读历史记录吗?`;if(window.confirm(e))try{await g.post(`/api/history/clear`),S([])}catch{alert(u===`vi`?`Không xóa được lịch sử.`:u===`en`?`Failed to clear history.`:`无法清空历史记录。`)}},F=async(e,t,n)=>{n&&n.stopPropagation();let r=e||t;if(r){E(r);try{await g.post(`/api/history/remove`,e?{book_id:e}:{url:t}),S(n=>n.map(n=>({...n,books:n.books.filter(n=>n.book_id!==e&&n.url!==t&&(n.book_id||n.url)!==r)})).filter(e=>e.books.length>0))}catch{S(n=>n.map(n=>({...n,books:n.books.filter(n=>n.book_id!==e&&n.url!==t&&(n.book_id||n.url)!==r)})).filter(e=>e.books.length>0))}finally{E(null)}}},I=e=>{let t=e.book_id||e.url;t&&M(e=>{let n=new Set(e);return n.has(t)?n.delete(t):n.add(t),n})},L=()=>{let e=[];return x.forEach(t=>{t.books.forEach(t=>{let n=t.book_id||t.url;n&&e.push(n)})}),e},R=()=>{let e=L();j.size===e.length?M(new Set):M(new Set(e))},z=async()=>{if(window.confirm(u===`vi`?`Bạn có chắc chắn muốn xóa ${j.size} truyện khỏi lịch sử không?`:`Are you sure you want to clear ${j.size} selected books from history?`)){w(!0);try{let e=[];x.forEach(t=>{t.books.forEach(t=>{let n=t.book_id||t.url;j.has(n)&&e.push(t)})}),await Promise.all(e.map(e=>g.post(`/api/history/remove`,e.book_id?{book_id:e.book_id}:{url:e.url}))),M(new Set),A(!1),await N()}catch{alert(`Không thể xóa hàng loạt lịch sử.`)}finally{w(!1)}}},B=x.reduce((e,t)=>e+t.books.length,0);if(y)return(0,v.jsx)(e,{children:(0,v.jsxs)(`div`,{className:`py-20 text-center text-slate-500`,children:[(0,v.jsx)(f,{className:`w-8 h-8 animate-spin mx-auto mb-2 text-brand-500`}),(0,v.jsx)(`span`,{children:u===`vi`?`Đang tải thông tin...`:u===`en`?`Loading info...`:`正在加载信息...`})]})});if(!p)return(0,v.jsx)(e,{children:(0,v.jsxs)(`div`,{className:`py-20 text-center text-slate-500`,children:[(0,v.jsx)(`div`,{className:`w-12 h-12 rounded-2xl bg-white/5 border border-white/10 flex items-center justify-center text-slate-400 mx-auto mb-4`,children:`🔒`}),(0,v.jsx)(`p`,{className:`text-sm`,children:l.loginToViewHistory})]})});let V=L(),H=j.size===V.length&&V.length>0;return(0,v.jsxs)(e,{children:[(0,v.jsxs)(`div`,{className:`flex flex-col md:flex-row md:items-center justify-between gap-4 mb-6`,children:[(0,v.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3`,children:[(0,v.jsxs)(`h2`,{className:`text-xl font-bold flex items-center gap-2 text-white`,children:[(0,v.jsx)(m,{className:`w-6 h-6 text-brand-400`}),u===`vi`?`Lịch Sử Đọc Truyện`:u===`en`?`Reading History`:`阅读历史`]}),B>0&&(0,v.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,v.jsx)(`button`,{onClick:()=>{A(!k),M(new Set)},className:`px-3 py-1.5 rounded-lg text-xs font-bold transition-all border ${k?`bg-purple-600/25 border-purple-500/50 text-purple-300 hover:bg-purple-600/35`:`bg-white/5 border-white/10 text-slate-300 hover:bg-white/10`}`,children:k?u===`vi`?`Thoát quản lý`:`Exit management`:u===`vi`?`Quản lý lịch sử`:`Manage history`}),k&&(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(`button`,{onClick:R,className:`px-3 py-1.5 bg-[#121225] border border-[#1f1f3a] rounded-lg text-xs font-bold text-slate-300 hover:bg-[#1a1a35] transition-all`,children:H?u===`vi`?`Hủy chọn tất cả`:`Deselect all`:u===`vi`?`Chọn tất cả`:`Select all`}),j.size>0&&(0,v.jsxs)(`button`,{onClick:z,className:`inline-flex items-center gap-1.5 px-3 py-1.5 bg-rose-600 hover:bg-rose-500 text-white rounded-lg text-xs font-bold shadow-lg shadow-rose-950/20 transition-all active:scale-95 cursor-pointer`,children:[(0,v.jsx)(o,{className:`w-3.5 h-3.5`}),u===`vi`?`Xóa hàng loạt (${j.size})`:`Bulk Delete (${j.size})`]})]})]})]}),(0,v.jsxs)(`div`,{className:`flex items-center gap-2 w-full md:w-auto justify-between md:justify-end`,children:[B>0&&(0,v.jsx)(`p`,{className:`text-xs text-slate-500`,children:u===`vi`?`${B} truyện`:`${B} books`}),(0,v.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,v.jsxs)(`div`,{className:`relative`,children:[(0,v.jsx)(`input`,{type:`text`,value:D,onChange:e=>O(e.target.value),onKeyDown:e=>e.key===`Enter`&&N(),placeholder:u===`vi`?`Tìm lịch sử...`:`Search history...`,className:`bg-[#12122b]/80 border border-[#232342] rounded-xl px-3 py-2 pr-8 text-xs text-white placeholder-slate-500 focus:outline-none focus:border-brand-500 transition-colors w-36 sm:w-44`}),D&&(0,v.jsx)(`button`,{onClick:()=>{O(``),N()},className:`absolute right-2 top-1/2 -translate-y-1/2 text-slate-500 hover:text-white`,children:(0,v.jsx)(h,{className:`w-3 h-3`})})]}),B>0&&!k&&(0,v.jsxs)(`button`,{onClick:P,className:`inline-flex items-center gap-1.5 bg-red-500/10 border border-red-500/25 hover:bg-red-500/20 text-red-400 px-3 py-2 rounded-xl text-xs font-bold transition-all`,children:[(0,v.jsx)(o,{className:`w-3.5 h-3.5`}),u===`vi`?`Xóa tất cả`:`Clear All`]})]})]})]}),C?(0,v.jsxs)(`div`,{className:`py-20 text-center text-slate-500`,children:[(0,v.jsx)(f,{className:`w-6 h-6 animate-spin mx-auto mb-2`}),(0,v.jsx)(`span`,{children:l.loading})]}):x.length===0?(0,v.jsxs)(`div`,{className:`py-20 text-center text-slate-500 bg-[#121225]/40 border border-dashed border-[#1f1f3a] rounded-2xl`,children:[(0,v.jsx)(m,{className:`w-10 h-10 mx-auto mb-3 text-slate-600`}),(0,v.jsx)(`p`,{className:`text-sm font-semibold`,children:u===`vi`?`Chưa có lịch sử đọc truyện.`:u===`en`?`No reading history yet.`:`暂无阅读历史记录。`}),(0,v.jsx)(`p`,{className:`text-xs mt-1 text-slate-600`,children:u===`vi`?`Click vào bất kỳ truyện nào để bắt đầu theo dõi.`:u===`en`?`Click any book to start tracking.`:`点击任意小说开始跟踪。`})]}):(0,v.jsx)(`div`,{className:`space-y-8`,children:x.map(e=>(0,v.jsxs)(`div`,{className:`space-y-3`,children:[(0,v.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,v.jsx)(i,{className:`w-3.5 h-3.5 text-brand-400`}),(0,v.jsx)(`h3`,{className:`text-xs font-extrabold text-brand-400 uppercase tracking-wider`,children:u===`en`?e.group_name===`Hôm nay`?`Today`:e.group_name===`Hôm qua`?`Yesterday`:e.group_name===`Tháng này`?`This Month`:`Earlier`:u===`zh`?e.group_name===`Hôm nay`?`今天`:e.group_name===`Hôm qua`?`昨天`:e.group_name===`Tháng này`?`本月`:`更早`:e.group_name}),(0,v.jsx)(`div`,{className:`flex-1 h-px bg-[#1f1f3a]`}),(0,v.jsx)(`span`,{className:`text-[10px] text-slate-600 font-semibold`,children:e.books.length})]}),(0,v.jsx)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3`,children:e.books.map((e,i)=>{let o=e.book_id||e.url,s=j.has(o);return(0,v.jsxs)(`div`,{onClick:()=>{k?I(e):e.book_id?b(`/book/${e.book_id}`):e.url&&window.open(e.url,`_blank`)},className:`relative bg-[#121225]/60 border rounded-2xl p-4 flex gap-3 items-start cursor-pointer transition-all hover:scale-[1.01] group ${k?`border-purple-500/30 bg-purple-950/5`:`border-[#1f1f3a] hover:border-brand-500/35`}`,children:[k&&(0,v.jsx)(`div`,{className:`w-5 h-5 rounded-md border flex items-center justify-center shrink-0 self-center transition-all ${s?`bg-purple-600 border-purple-500 text-white shadow shadow-purple-500/25`:`bg-[#0b0b14] border-slate-700 text-slate-500`}`,children:s?(0,v.jsx)(a,{className:`w-3.5 h-3.5`}):(0,v.jsx)(r,{className:`w-3.5 h-3.5`})}),e.cover?(0,v.jsx)(`img`,{src:e.cover,alt:`cover`,className:`w-[48px] h-[66px] object-cover rounded-xl border border-[#1f1f3a] shrink-0`,onError:e=>e.target.remove()}):(0,v.jsx)(`div`,{className:`w-[48px] h-[66px] rounded-xl bg-[#0b0b14] border border-[#1f1f3a] flex items-center justify-center text-slate-600 shrink-0`,children:(0,v.jsx)(t,{className:`w-5 h-5`})}),(0,v.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,v.jsx)(`h4`,{className:`font-bold text-slate-200 text-xs truncate leading-relaxed group-hover:text-brand-400 transition-colors`,children:e.title}),(0,v.jsxs)(`p`,{className:`text-[10px] text-slate-500 mt-0.5 truncate`,children:[u===`vi`?`Tác giả`:u===`en`?`Author`:`作者`,`: `,e.author]}),(0,v.jsx)(`div`,{className:`mt-2 flex items-center gap-1.5 flex-wrap`,children:(0,v.jsxs)(`span`,{className:`inline-flex items-center gap-1 bg-brand-500/10 border border-brand-500/20 text-brand-400 px-2 py-0.5 rounded-full text-[9px] font-semibold max-w-[150px]`,children:[(0,v.jsx)(n,{className:`w-2.5 h-2.5 shrink-0`}),(0,v.jsx)(`span`,{className:`truncate`,children:e.last_chapter})]})}),e.read_date&&(0,v.jsx)(`p`,{className:`text-[9px] text-slate-600 mt-1.5`,children:e.read_date})]}),!k&&(0,v.jsx)(`button`,{onClick:t=>F(e.book_id,e.url,t),disabled:T===o,className:`absolute top-3 right-3 p-1.5 rounded-lg bg-red-500/10 hover:bg-red-500 text-red-400 hover:text-white transition-all opacity-100 md:opacity-0 md:group-hover:opacity-100 disabled:opacity-50`,title:u===`vi`?`Xóa khỏi lịch sử`:`Remove from history`,children:T===o?(0,v.jsx)(f,{className:`w-3.5 h-3.5 animate-spin`}):(0,v.jsx)(h,{className:`w-3.5 h-3.5`})})]},o||i)})})]},e.group_name))})]})}export{y as default}; \ No newline at end of file diff --git a/frontend-web/dist/assets/LocalReader-Bc5HMhfm.js b/frontend-web/dist/assets/LocalReader-Bc5HMhfm.js new file mode 100644 index 0000000000000000000000000000000000000000..24bd081811db2c2a24851665f958b8d3247d3636 --- /dev/null +++ b/frontend-web/dist/assets/LocalReader-Bc5HMhfm.js @@ -0,0 +1,33 @@ +import{n as e,r as t,t as n}from"./useUsageTracker-Bc2zfMaM.js";import{t as r,v as i,y as a}from"./MainLayout-COiTxmNr.js";import{n as o,o as s}from"./square-DZKJ0QGR.js";import{t as c}from"./eye-DsLuESBv.js";import{t as l}from"./plus-CSQqtn3N.js";import{t as u}from"./trash-2-DDhTqVwA.js";import{F as d,M as f,N as p,P as m,S as h,_ as g,b as _,c as v,d as y,j as b,o as x,t as S,u as C,v as w,x as T}from"./index-yRoRoI6u.js";var E=_(`upload`,[[`path`,{d:`M12 3v12`,key:`1x0j5s`}],[`path`,{d:`m17 8-5-5-5 5`,key:`7q97r8`}],[`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4`,key:`ih7n3h`}]]),D=p(((e,t)=>{(function(n){typeof e==`object`&&t!==void 0?t.exports=n():typeof define==`function`&&define.amd?define([],n):(typeof window<`u`?window:typeof global<`u`?global:typeof self<`u`?self:this).JSZip=n()})(function(){return function e(t,n,r){function i(o,s){if(!n[o]){if(!t[o]){var c=typeof m==`function`&&m;if(!s&&c)return c(o,!0);if(a)return a(o,!0);var l=Error(`Cannot find module '`+o+`'`);throw l.code=`MODULE_NOT_FOUND`,l}var u=n[o]={exports:{}};t[o][0].call(u.exports,function(e){var n=t[o][1][e];return i(n||e)},u,u.exports,e,t,n,r)}return n[o].exports}for(var a=typeof m==`function`&&m,o=0;o>2,s=(3&t)<<4|n>>4,c=1>6:64,l=2>4,n=(15&o)<<4|(s=a.indexOf(e.charAt(l++)))>>2,r=(3&s)<<6|(c=a.indexOf(e.charAt(l++))),f[u++]=t,s!==64&&(f[u++]=n),c!==64&&(f[u++]=r);return f}},{"./support":30,"./utils":32}],2:[function(e,t,n){var r=e(`./external`),i=e(`./stream/DataWorker`),a=e(`./stream/Crc32Probe`),o=e(`./stream/DataLengthProbe`);function s(e,t,n,r,i){this.compressedSize=e,this.uncompressedSize=t,this.crc32=n,this.compression=r,this.compressedContent=i}s.prototype={getContentWorker:function(){var e=new i(r.Promise.resolve(this.compressedContent)).pipe(this.compression.uncompressWorker()).pipe(new o(`data_length`)),t=this;return e.on(`end`,function(){if(this.streamInfo.data_length!==t.uncompressedSize)throw Error(`Bug : uncompressed data size mismatch`)}),e},getCompressedWorker:function(){return new i(r.Promise.resolve(this.compressedContent)).withStreamInfo(`compressedSize`,this.compressedSize).withStreamInfo(`uncompressedSize`,this.uncompressedSize).withStreamInfo(`crc32`,this.crc32).withStreamInfo(`compression`,this.compression)}},s.createWorkerFrom=function(e,t,n){return e.pipe(new a).pipe(new o(`uncompressedSize`)).pipe(t.compressWorker(n)).pipe(new o(`compressedSize`)).withStreamInfo(`compression`,t)},t.exports=s},{"./external":6,"./stream/Crc32Probe":25,"./stream/DataLengthProbe":26,"./stream/DataWorker":27}],3:[function(e,t,n){var r=e(`./stream/GenericWorker`);n.STORE={magic:`\0\0`,compressWorker:function(){return new r(`STORE compression`)},uncompressWorker:function(){return new r(`STORE decompression`)}},n.DEFLATE=e(`./flate`)},{"./flate":7,"./stream/GenericWorker":28}],4:[function(e,t,n){var r=e(`./utils`),i=function(){for(var e,t=[],n=0;n<256;n++){e=n;for(var r=0;r<8;r++)e=1&e?3988292384^e>>>1:e>>>1;t[n]=e}return t}();t.exports=function(e,t){return e!==void 0&&e.length?r.getTypeOf(e)===`string`?function(e,t,n,r){var a=i,o=r+n;e^=-1;for(var s=r;s>>8^a[255&(e^t.charCodeAt(s))];return-1^e}(0|t,e,e.length,0):function(e,t,n,r){var a=i,o=r+n;e^=-1;for(var s=r;s>>8^a[255&(e^t[s])];return-1^e}(0|t,e,e.length,0):0}},{"./utils":32}],5:[function(e,t,n){n.base64=!1,n.binary=!1,n.dir=!1,n.createFolders=!0,n.date=null,n.compression=null,n.compressionOptions=null,n.comment=null,n.unixPermissions=null,n.dosPermissions=null},{}],6:[function(e,t,n){var r=null;r=typeof Promise<`u`?Promise:e(`lie`),t.exports={Promise:r}},{lie:37}],7:[function(e,t,n){var r=typeof Uint8Array<`u`&&typeof Uint16Array<`u`&&typeof Uint32Array<`u`,i=e(`pako`),a=e(`./utils`),o=e(`./stream/GenericWorker`),s=r?`uint8array`:`array`;function c(e,t){o.call(this,`FlateWorker/`+e),this._pako=null,this._pakoAction=e,this._pakoOptions=t,this.meta={}}n.magic=`\b\0`,a.inherits(c,o),c.prototype.processChunk=function(e){this.meta=e.meta,this._pako===null&&this._createPako(),this._pako.push(a.transformTo(s,e.data),!1)},c.prototype.flush=function(){o.prototype.flush.call(this),this._pako===null&&this._createPako(),this._pako.push([],!0)},c.prototype.cleanUp=function(){o.prototype.cleanUp.call(this),this._pako=null},c.prototype._createPako=function(){this._pako=new i[this._pakoAction]({raw:!0,level:this._pakoOptions.level||-1});var e=this;this._pako.onData=function(t){e.push({data:t,meta:e.meta})}},n.compressWorker=function(e){return new c(`Deflate`,e)},n.uncompressWorker=function(){return new c(`Inflate`,{})}},{"./stream/GenericWorker":28,"./utils":32,pako:38}],8:[function(e,t,n){function r(e,t){var n,r=``;for(n=0;n>>=8;return r}function i(e,t,n,i,o,u){var d,f,p=e.file,m=e.compression,h=u!==s.utf8encode,g=a.transformTo(`string`,u(p.name)),_=a.transformTo(`string`,s.utf8encode(p.name)),v=p.comment,y=a.transformTo(`string`,u(v)),b=a.transformTo(`string`,s.utf8encode(v)),x=_.length!==p.name.length,S=b.length!==v.length,C=``,w=``,T=``,E=p.dir,D=p.date,O={crc32:0,compressedSize:0,uncompressedSize:0};t&&!n||(O.crc32=e.crc32,O.compressedSize=e.compressedSize,O.uncompressedSize=e.uncompressedSize);var k=0;t&&(k|=8),h||!x&&!S||(k|=2048);var A=0,j=0;E&&(A|=16),o===`UNIX`?(j=798,A|=function(e,t){var n=e;return e||(n=t?16893:33204),(65535&n)<<16}(p.unixPermissions,E)):(j=20,A|=function(e){return 63&(e||0)}(p.dosPermissions)),d=D.getUTCHours(),d<<=6,d|=D.getUTCMinutes(),d<<=5,d|=D.getUTCSeconds()/2,f=D.getUTCFullYear()-1980,f<<=4,f|=D.getUTCMonth()+1,f<<=5,f|=D.getUTCDate(),x&&(w=r(1,1)+r(c(g),4)+_,C+=`up`+r(w.length,2)+w),S&&(T=r(1,1)+r(c(y),4)+b,C+=`uc`+r(T.length,2)+T);var M=``;return M+=` +\0`,M+=r(k,2),M+=m.magic,M+=r(d,2),M+=r(f,2),M+=r(O.crc32,4),M+=r(O.compressedSize,4),M+=r(O.uncompressedSize,4),M+=r(g.length,2),M+=r(C.length,2),{fileRecord:l.LOCAL_FILE_HEADER+M+g+C,dirRecord:l.CENTRAL_FILE_HEADER+r(j,2)+M+r(y.length,2)+`\0\0\0\0`+r(A,4)+r(i,4)+g+C+y}}var a=e(`../utils`),o=e(`../stream/GenericWorker`),s=e(`../utf8`),c=e(`../crc32`),l=e(`../signature`);function u(e,t,n,r){o.call(this,`ZipFileWorker`),this.bytesWritten=0,this.zipComment=t,this.zipPlatform=n,this.encodeFileName=r,this.streamFiles=e,this.accumulate=!1,this.contentBuffer=[],this.dirRecords=[],this.currentSourceOffset=0,this.entriesCount=0,this.currentFile=null,this._sources=[]}a.inherits(u,o),u.prototype.push=function(e){var t=e.meta.percent||0,n=this.entriesCount,r=this._sources.length;this.accumulate?this.contentBuffer.push(e):(this.bytesWritten+=e.data.length,o.prototype.push.call(this,{data:e.data,meta:{currentFile:this.currentFile,percent:n?(t+100*(n-r-1))/n:100}}))},u.prototype.openedSource=function(e){this.currentSourceOffset=this.bytesWritten,this.currentFile=e.file.name;var t=this.streamFiles&&!e.file.dir;if(t){var n=i(e,t,!1,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);this.push({data:n.fileRecord,meta:{percent:0}})}else this.accumulate=!0},u.prototype.closedSource=function(e){this.accumulate=!1;var t=this.streamFiles&&!e.file.dir,n=i(e,t,!0,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);if(this.dirRecords.push(n.dirRecord),t)this.push({data:function(e){return l.DATA_DESCRIPTOR+r(e.crc32,4)+r(e.compressedSize,4)+r(e.uncompressedSize,4)}(e),meta:{percent:100}});else for(this.push({data:n.fileRecord,meta:{percent:0}});this.contentBuffer.length;)this.push(this.contentBuffer.shift());this.currentFile=null},u.prototype.flush=function(){for(var e=this.bytesWritten,t=0;t=this.index;t--)n=(n<<8)+this.byteAt(t);return this.index+=e,n},readString:function(e){return r.transformTo(`string`,this.readData(e))},readData:function(){},lastIndexOfSignature:function(){},readAndCheckSignature:function(){},readDate:function(){var e=this.readInt(4);return new Date(Date.UTC(1980+(e>>25&127),(e>>21&15)-1,e>>16&31,e>>11&31,e>>5&63,(31&e)<<1))}},t.exports=i},{"../utils":32}],19:[function(e,t,n){var r=e(`./Uint8ArrayReader`);function i(e){r.call(this,e)}e(`../utils`).inherits(i,r),i.prototype.readData=function(e){this.checkOffset(e);var t=this.data.slice(this.zero+this.index,this.zero+this.index+e);return this.index+=e,t},t.exports=i},{"../utils":32,"./Uint8ArrayReader":21}],20:[function(e,t,n){var r=e(`./DataReader`);function i(e){r.call(this,e)}e(`../utils`).inherits(i,r),i.prototype.byteAt=function(e){return this.data.charCodeAt(this.zero+e)},i.prototype.lastIndexOfSignature=function(e){return this.data.lastIndexOf(e)-this.zero},i.prototype.readAndCheckSignature=function(e){return e===this.readData(4)},i.prototype.readData=function(e){this.checkOffset(e);var t=this.data.slice(this.zero+this.index,this.zero+this.index+e);return this.index+=e,t},t.exports=i},{"../utils":32,"./DataReader":18}],21:[function(e,t,n){var r=e(`./ArrayReader`);function i(e){r.call(this,e)}e(`../utils`).inherits(i,r),i.prototype.readData=function(e){if(this.checkOffset(e),e===0)return new Uint8Array;var t=this.data.subarray(this.zero+this.index,this.zero+this.index+e);return this.index+=e,t},t.exports=i},{"../utils":32,"./ArrayReader":17}],22:[function(e,t,n){var r=e(`../utils`),i=e(`../support`),a=e(`./ArrayReader`),o=e(`./StringReader`),s=e(`./NodeBufferReader`),c=e(`./Uint8ArrayReader`);t.exports=function(e){var t=r.getTypeOf(e);return r.checkSupport(t),t!==`string`||i.uint8array?t===`nodebuffer`?new s(e):i.uint8array?new c(r.transformTo(`uint8array`,e)):new a(r.transformTo(`array`,e)):new o(e)}},{"../support":30,"../utils":32,"./ArrayReader":17,"./NodeBufferReader":19,"./StringReader":20,"./Uint8ArrayReader":21}],23:[function(e,t,n){n.LOCAL_FILE_HEADER=`PK`,n.CENTRAL_FILE_HEADER=`PK`,n.CENTRAL_DIRECTORY_END=`PK`,n.ZIP64_CENTRAL_DIRECTORY_LOCATOR=`PK\x07`,n.ZIP64_CENTRAL_DIRECTORY_END=`PK`,n.DATA_DESCRIPTOR=`PK\x07\b`},{}],24:[function(e,t,n){var r=e(`./GenericWorker`),i=e(`../utils`);function a(e){r.call(this,`ConvertWorker to `+e),this.destType=e}i.inherits(a,r),a.prototype.processChunk=function(e){this.push({data:i.transformTo(this.destType,e.data),meta:e.meta})},t.exports=a},{"../utils":32,"./GenericWorker":28}],25:[function(e,t,n){var r=e(`./GenericWorker`),i=e(`../crc32`);function a(){r.call(this,`Crc32Probe`),this.withStreamInfo(`crc32`,0)}e(`../utils`).inherits(a,r),a.prototype.processChunk=function(e){this.streamInfo.crc32=i(e.data,this.streamInfo.crc32||0),this.push(e)},t.exports=a},{"../crc32":4,"../utils":32,"./GenericWorker":28}],26:[function(e,t,n){var r=e(`../utils`),i=e(`./GenericWorker`);function a(e){i.call(this,`DataLengthProbe for `+e),this.propName=e,this.withStreamInfo(e,0)}r.inherits(a,i),a.prototype.processChunk=function(e){if(e){var t=this.streamInfo[this.propName]||0;this.streamInfo[this.propName]=t+e.data.length}i.prototype.processChunk.call(this,e)},t.exports=a},{"../utils":32,"./GenericWorker":28}],27:[function(e,t,n){var r=e(`../utils`),i=e(`./GenericWorker`);function a(e){i.call(this,`DataWorker`);var t=this;this.dataIsReady=!1,this.index=0,this.max=0,this.data=null,this.type=``,this._tickScheduled=!1,e.then(function(e){t.dataIsReady=!0,t.data=e,t.max=e&&e.length||0,t.type=r.getTypeOf(e),t.isPaused||t._tickAndRepeat()},function(e){t.error(e)})}r.inherits(a,i),a.prototype.cleanUp=function(){i.prototype.cleanUp.call(this),this.data=null},a.prototype.resume=function(){return!!i.prototype.resume.call(this)&&(!this._tickScheduled&&this.dataIsReady&&(this._tickScheduled=!0,r.delay(this._tickAndRepeat,[],this)),!0)},a.prototype._tickAndRepeat=function(){this._tickScheduled=!1,this.isPaused||this.isFinished||(this._tick(),this.isFinished||(r.delay(this._tickAndRepeat,[],this),this._tickScheduled=!0))},a.prototype._tick=function(){if(this.isPaused||this.isFinished)return!1;var e=null,t=Math.min(this.max,this.index+16384);if(this.index>=this.max)return this.end();switch(this.type){case`string`:e=this.data.substring(this.index,t);break;case`uint8array`:e=this.data.subarray(this.index,t);break;case`array`:case`nodebuffer`:e=this.data.slice(this.index,t)}return this.index=t,this.push({data:e,meta:{percent:this.max?this.index/this.max*100:0}})},t.exports=a},{"../utils":32,"./GenericWorker":28}],28:[function(e,t,n){function r(e){this.name=e||`default`,this.streamInfo={},this.generatedError=null,this.extraStreamInfo={},this.isPaused=!0,this.isFinished=!1,this.isLocked=!1,this._listeners={data:[],end:[],error:[]},this.previous=null}r.prototype={push:function(e){this.emit(`data`,e)},end:function(){if(this.isFinished)return!1;this.flush();try{this.emit(`end`),this.cleanUp(),this.isFinished=!0}catch(e){this.emit(`error`,e)}return!0},error:function(e){return!this.isFinished&&(this.isPaused?this.generatedError=e:(this.isFinished=!0,this.emit(`error`,e),this.previous&&this.previous.error(e),this.cleanUp()),!0)},on:function(e,t){return this._listeners[e].push(t),this},cleanUp:function(){this.streamInfo=this.generatedError=this.extraStreamInfo=null,this._listeners=[]},emit:function(e,t){if(this._listeners[e])for(var n=0;n `+e:e}},t.exports=r},{}],29:[function(e,t,n){var r=e(`../utils`),i=e(`./ConvertWorker`),a=e(`./GenericWorker`),o=e(`../base64`),s=e(`../support`),c=e(`../external`),l=null;if(s.nodestream)try{l=e(`../nodejs/NodejsStreamOutputAdapter`)}catch{}function u(e,t){return new c.Promise(function(n,i){var a=[],s=e._internalType,c=e._outputType,l=e._mimeType;e.on(`data`,function(e,n){a.push(e),t&&t(n)}).on(`error`,function(e){a=[],i(e)}).on(`end`,function(){try{n(function(e,t,n){switch(e){case`blob`:return r.newBlob(r.transformTo(`arraybuffer`,t),n);case`base64`:return o.encode(t);default:return r.transformTo(e,t)}}(c,function(e,t){var n,r=0,i=null,a=0;for(n=0;n`u`)n.blob=!1;else{var r=new ArrayBuffer(0);try{n.blob=new Blob([r],{type:`application/zip`}).size===0}catch{try{var i=new(self.BlobBuilder||self.WebKitBlobBuilder||self.MozBlobBuilder||self.MSBlobBuilder);i.append(r),n.blob=i.getBlob(`application/zip`).size===0}catch{n.blob=!1}}}try{n.nodestream=!!e(`readable-stream`).Readable}catch{n.nodestream=!1}},{"readable-stream":16}],31:[function(e,t,n){for(var r=e(`./utils`),i=e(`./support`),a=e(`./nodejsUtils`),o=e(`./stream/GenericWorker`),s=Array(256),c=0;c<256;c++)s[c]=252<=c?6:248<=c?5:240<=c?4:224<=c?3:192<=c?2:1;s[254]=s[254]=1;function l(){o.call(this,`utf-8 decode`),this.leftOver=null}function u(){o.call(this,`utf-8 encode`)}n.utf8encode=function(e){return i.nodebuffer?a.newBufferFrom(e,`utf-8`):function(e){var t,n,r,a,o,s=e.length,c=0;for(a=0;a>>6:(n<65536?t[o++]=224|n>>>12:(t[o++]=240|n>>>18,t[o++]=128|n>>>12&63),t[o++]=128|n>>>6&63),t[o++]=128|63&n);return t}(e)},n.utf8decode=function(e){return i.nodebuffer?r.transformTo(`nodebuffer`,e).toString(`utf-8`):function(e){var t,n,i,a,o=e.length,c=Array(2*o);for(t=n=0;t>10&1023,c[n++]=56320|1023&i)}return c.length!==n&&(c.subarray?c=c.subarray(0,n):c.length=n),r.applyFromCharCode(c)}(e=r.transformTo(i.uint8array?`uint8array`:`array`,e))},r.inherits(l,o),l.prototype.processChunk=function(e){var t=r.transformTo(i.uint8array?`uint8array`:`array`,e.data);if(this.leftOver&&this.leftOver.length){if(i.uint8array){var a=t;(t=new Uint8Array(a.length+this.leftOver.length)).set(this.leftOver,0),t.set(a,this.leftOver.length)}else t=this.leftOver.concat(t);this.leftOver=null}var o=function(e,t){var n;for((t||=e.length)>e.length&&(t=e.length),n=t-1;0<=n&&(192&e[n])==128;)n--;return n<0||n===0?t:n+s[e[n]]>t?n:t}(t),c=t;o!==t.length&&(i.uint8array?(c=t.subarray(0,o),this.leftOver=t.subarray(o,t.length)):(c=t.slice(0,o),this.leftOver=t.slice(o,t.length))),this.push({data:n.utf8decode(c),meta:e.meta})},l.prototype.flush=function(){this.leftOver&&this.leftOver.length&&(this.push({data:n.utf8decode(this.leftOver),meta:{}}),this.leftOver=null)},n.Utf8DecodeWorker=l,r.inherits(u,o),u.prototype.processChunk=function(e){this.push({data:n.utf8encode(e.data),meta:e.meta})},n.Utf8EncodeWorker=u},{"./nodejsUtils":14,"./stream/GenericWorker":28,"./support":30,"./utils":32}],32:[function(e,t,n){var r=e(`./support`),i=e(`./base64`),a=e(`./nodejsUtils`),o=e(`./external`);function s(e){return e}function c(e,t){for(var n=0;n>8;this.dir=!!(16&this.externalFileAttributes),e==0&&(this.dosPermissions=63&this.externalFileAttributes),e==3&&(this.unixPermissions=this.externalFileAttributes>>16&65535),this.dir||this.fileNameStr.slice(-1)!==`/`||(this.dir=!0)},parseZIP64ExtraField:function(){if(this.extraFields[1]){var e=r(this.extraFields[1].value);this.uncompressedSize===i.MAX_VALUE_32BITS&&(this.uncompressedSize=e.readInt(8)),this.compressedSize===i.MAX_VALUE_32BITS&&(this.compressedSize=e.readInt(8)),this.localHeaderOffset===i.MAX_VALUE_32BITS&&(this.localHeaderOffset=e.readInt(8)),this.diskNumberStart===i.MAX_VALUE_32BITS&&(this.diskNumberStart=e.readInt(4))}},readExtraFields:function(e){var t,n,r,i=e.index+this.extraFieldsLength;for(this.extraFields||={};e.index+4>>6:(n<65536?t[o++]=224|n>>>12:(t[o++]=240|n>>>18,t[o++]=128|n>>>12&63),t[o++]=128|n>>>6&63),t[o++]=128|63&n);return t},n.buf2binstring=function(e){return c(e,e.length)},n.binstring2buf=function(e){for(var t=new r.Buf8(e.length),n=0,i=t.length;n>10&1023,l[r++]=56320|1023&i)}return c(l,r)},n.utf8border=function(e,t){var n;for((t||=e.length)>e.length&&(t=e.length),n=t-1;0<=n&&(192&e[n])==128;)n--;return n<0||n===0?t:n+o[e[n]]>t?n:t}},{"./common":41}],43:[function(e,t,n){t.exports=function(e,t,n,r){for(var i=65535&e|0,a=e>>>16&65535|0,o=0;n!==0;){for(n-=o=2e3>>1:e>>>1;t[n]=e}return t}();t.exports=function(e,t,n,i){var a=r,o=i+n;e^=-1;for(var s=i;s>>8^a[255&(e^t[s])];return-1^e}},{}],46:[function(e,t,n){var r,i=e(`../utils/common`),a=e(`./trees`),o=e(`./adler32`),s=e(`./crc32`),c=e(`./messages`),l=0,u=4,d=0,f=-2,p=-1,m=4,h=2,g=8,_=9,v=286,y=30,b=19,x=2*v+1,S=15,C=3,w=258,T=w+C+1,E=42,D=113,O=1,k=2,A=3,j=4;function M(e,t){return e.msg=c[t],t}function N(e){return(e<<1)-(4e.avail_out&&(n=e.avail_out),n!==0&&(i.arraySet(e.output,t.pending_buf,t.pending_out,n,e.next_out),e.next_out+=n,t.pending_out+=n,e.total_out+=n,e.avail_out-=n,t.pending-=n,t.pending===0&&(t.pending_out=0))}function I(e,t){a._tr_flush_block(e,0<=e.block_start?e.block_start:-1,e.strstart-e.block_start,t),e.block_start=e.strstart,F(e.strm)}function L(e,t){e.pending_buf[e.pending++]=t}function R(e,t){e.pending_buf[e.pending++]=t>>>8&255,e.pending_buf[e.pending++]=255&t}function z(e,t){var n,r,i=e.max_chain_length,a=e.strstart,o=e.prev_length,s=e.nice_match,c=e.strstart>e.w_size-T?e.strstart-(e.w_size-T):0,l=e.window,u=e.w_mask,d=e.prev,f=e.strstart+w,p=l[a+o-1],m=l[a+o];e.prev_length>=e.good_match&&(i>>=2),s>e.lookahead&&(s=e.lookahead);do if(l[(n=t)+o]===m&&l[n+o-1]===p&&l[n]===l[a]&&l[++n]===l[a+1]){a+=2,n++;do;while(l[++a]===l[++n]&&l[++a]===l[++n]&&l[++a]===l[++n]&&l[++a]===l[++n]&&l[++a]===l[++n]&&l[++a]===l[++n]&&l[++a]===l[++n]&&l[++a]===l[++n]&&ac&&--i!=0);return o<=e.lookahead?o:e.lookahead}function B(e){var t,n,r,a,c,l,u,d,f,p,m=e.w_size;do{if(a=e.window_size-e.lookahead-e.strstart,e.strstart>=m+(m-T)){for(i.arraySet(e.window,e.window,m,m,0),e.match_start-=m,e.strstart-=m,e.block_start-=m,t=n=e.hash_size;r=e.head[--t],e.head[t]=m<=r?r-m:0,--n;);for(t=n=m;r=e.prev[--t],e.prev[t]=m<=r?r-m:0,--n;);a+=m}if(e.strm.avail_in===0)break;if(l=e.strm,u=e.window,d=e.strstart+e.lookahead,f=a,p=void 0,p=l.avail_in,f=C)for(c=e.strstart-e.insert,e.ins_h=e.window[c],e.ins_h=(e.ins_h<=C&&(e.ins_h=(e.ins_h<=C)if(r=a._tr_tally(e,e.strstart-e.match_start,e.match_length-C),e.lookahead-=e.match_length,e.match_length<=e.max_lazy_match&&e.lookahead>=C){for(e.match_length--;e.strstart++,e.ins_h=(e.ins_h<=C&&(e.ins_h=(e.ins_h<=C&&e.match_length<=e.prev_length){for(i=e.strstart+e.lookahead-C,r=a._tr_tally(e,e.strstart-1-e.prev_match,e.prev_length-C),e.lookahead-=e.prev_length-1,e.prev_length-=2;++e.strstart<=i&&(e.ins_h=(e.ins_h<e.pending_buf_size-5&&(n=e.pending_buf_size-5);;){if(e.lookahead<=1){if(B(e),e.lookahead===0&&t===l)return O;if(e.lookahead===0)break}e.strstart+=e.lookahead,e.lookahead=0;var r=e.block_start+n;if((e.strstart===0||e.strstart>=r)&&(e.lookahead=e.strstart-r,e.strstart=r,I(e,!1),e.strm.avail_out===0)||e.strstart-e.block_start>=e.w_size-T&&(I(e,!1),e.strm.avail_out===0))return O}return e.insert=0,t===u?(I(e,!0),e.strm.avail_out===0?A:j):(e.strstart>e.block_start&&(I(e,!1),e.strm.avail_out),O)}),new U(4,4,8,4,V),new U(4,5,16,8,V),new U(4,6,32,32,V),new U(4,4,16,16,H),new U(8,16,32,32,H),new U(8,16,128,128,H),new U(8,32,128,256,H),new U(32,128,258,1024,H),new U(32,258,258,4096,H)],n.deflateInit=function(e,t){return K(e,t,g,15,8,0)},n.deflateInit2=K,n.deflateReset=G,n.deflateResetKeep=W,n.deflateSetHeader=function(e,t){return e&&e.state&&e.state.wrap===2?(e.state.gzhead=t,d):f},n.deflate=function(e,t){var n,i,o,c;if(!e||!e.state||5>8&255),L(i,i.gzhead.time>>16&255),L(i,i.gzhead.time>>24&255),L(i,i.level===9?2:2<=i.strategy||i.level<2?4:0),L(i,255&i.gzhead.os),i.gzhead.extra&&i.gzhead.extra.length&&(L(i,255&i.gzhead.extra.length),L(i,i.gzhead.extra.length>>8&255)),i.gzhead.hcrc&&(e.adler=s(e.adler,i.pending_buf,i.pending,0)),i.gzindex=0,i.status=69):(L(i,0),L(i,0),L(i,0),L(i,0),L(i,0),L(i,i.level===9?2:2<=i.strategy||i.level<2?4:0),L(i,3),i.status=D);else{var p=g+(i.w_bits-8<<4)<<8;p|=(2<=i.strategy||i.level<2?0:i.level<6?1:i.level===6?2:3)<<6,i.strstart!==0&&(p|=32),p+=31-p%31,i.status=D,R(i,p),i.strstart!==0&&(R(i,e.adler>>>16),R(i,65535&e.adler)),e.adler=1}if(i.status===69)if(i.gzhead.extra){for(o=i.pending;i.gzindex<(65535&i.gzhead.extra.length)&&(i.pending!==i.pending_buf_size||(i.gzhead.hcrc&&i.pending>o&&(e.adler=s(e.adler,i.pending_buf,i.pending-o,o)),F(e),o=i.pending,i.pending!==i.pending_buf_size));)L(i,255&i.gzhead.extra[i.gzindex]),i.gzindex++;i.gzhead.hcrc&&i.pending>o&&(e.adler=s(e.adler,i.pending_buf,i.pending-o,o)),i.gzindex===i.gzhead.extra.length&&(i.gzindex=0,i.status=73)}else i.status=73;if(i.status===73)if(i.gzhead.name){o=i.pending;do{if(i.pending===i.pending_buf_size&&(i.gzhead.hcrc&&i.pending>o&&(e.adler=s(e.adler,i.pending_buf,i.pending-o,o)),F(e),o=i.pending,i.pending===i.pending_buf_size)){c=1;break}c=i.gzindexo&&(e.adler=s(e.adler,i.pending_buf,i.pending-o,o)),c===0&&(i.gzindex=0,i.status=91)}else i.status=91;if(i.status===91)if(i.gzhead.comment){o=i.pending;do{if(i.pending===i.pending_buf_size&&(i.gzhead.hcrc&&i.pending>o&&(e.adler=s(e.adler,i.pending_buf,i.pending-o,o)),F(e),o=i.pending,i.pending===i.pending_buf_size)){c=1;break}c=i.gzindexo&&(e.adler=s(e.adler,i.pending_buf,i.pending-o,o)),c===0&&(i.status=103)}else i.status=103;if(i.status===103&&(i.gzhead.hcrc?(i.pending+2>i.pending_buf_size&&F(e),i.pending+2<=i.pending_buf_size&&(L(i,255&e.adler),L(i,e.adler>>8&255),e.adler=0,i.status=D)):i.status=D),i.pending!==0){if(F(e),e.avail_out===0)return i.last_flush=-1,d}else if(e.avail_in===0&&N(t)<=N(n)&&t!==u)return M(e,-5);if(i.status===666&&e.avail_in!==0)return M(e,-5);if(e.avail_in!==0||i.lookahead!==0||t!==l&&i.status!==666){var m=i.strategy===2?function(e,t){for(var n;;){if(e.lookahead===0&&(B(e),e.lookahead===0)){if(t===l)return O;break}if(e.match_length=0,n=a._tr_tally(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++,n&&(I(e,!1),e.strm.avail_out===0))return O}return e.insert=0,t===u?(I(e,!0),e.strm.avail_out===0?A:j):e.last_lit&&(I(e,!1),e.strm.avail_out===0)?O:k}(i,t):i.strategy===3?function(e,t){for(var n,r,i,o,s=e.window;;){if(e.lookahead<=w){if(B(e),e.lookahead<=w&&t===l)return O;if(e.lookahead===0)break}if(e.match_length=0,e.lookahead>=C&&0e.lookahead&&(e.match_length=e.lookahead)}if(e.match_length>=C?(n=a._tr_tally(e,1,e.match_length-C),e.lookahead-=e.match_length,e.strstart+=e.match_length,e.match_length=0):(n=a._tr_tally(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++),n&&(I(e,!1),e.strm.avail_out===0))return O}return e.insert=0,t===u?(I(e,!0),e.strm.avail_out===0?A:j):e.last_lit&&(I(e,!1),e.strm.avail_out===0)?O:k}(i,t):r[i.level].func(i,t);if(m!==A&&m!==j||(i.status=666),m===O||m===A)return e.avail_out===0&&(i.last_flush=-1),d;if(m===k&&(t===1?a._tr_align(i):t!==5&&(a._tr_stored_block(i,0,0,!1),t===3&&(P(i.head),i.lookahead===0&&(i.strstart=0,i.block_start=0,i.insert=0))),F(e),e.avail_out===0))return i.last_flush=-1,d}return t===u?i.wrap<=0?1:(i.wrap===2?(L(i,255&e.adler),L(i,e.adler>>8&255),L(i,e.adler>>16&255),L(i,e.adler>>24&255),L(i,255&e.total_in),L(i,e.total_in>>8&255),L(i,e.total_in>>16&255),L(i,e.total_in>>24&255)):(R(i,e.adler>>>16),R(i,65535&e.adler)),F(e),0=n.w_size&&(s===0&&(P(n.head),n.strstart=0,n.block_start=0,n.insert=0),p=new i.Buf8(n.w_size),i.arraySet(p,t,m-n.w_size,n.w_size,0),t=p,m=n.w_size),c=e.avail_in,l=e.next_in,u=e.input,e.avail_in=m,e.next_in=0,e.input=t,B(n);n.lookahead>=C;){for(r=n.strstart,a=n.lookahead-(C-1);n.ins_h=(n.ins_h<>>=b=y>>>24,m-=b,(b=y>>>16&255)==0)E[a++]=65535&y;else{if(!(16&b)){if(!(64&b)){y=h[(65535&y)+(p&(1<>>=b,m-=b),m<15&&(p+=T[r++]<>>=b=y>>>24,m-=b,!(16&(b=y>>>16&255))){if(!(64&b)){y=g[(65535&y)+(p&(1<>>=b,m-=b,(b=a-o)>3,p&=(1<<(m-=x<<3))-1,e.next_in=r,e.next_out=a,e.avail_in=r>>24&255)+(e>>>8&65280)+((65280&e)<<8)+((255&e)<<24)}function g(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new r.Buf16(320),this.work=new r.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function _(e){var t;return e&&e.state?(t=e.state,e.total_in=e.total_out=t.total=0,e.msg=``,t.wrap&&(e.adler=1&t.wrap),t.mode=f,t.last=0,t.havedict=0,t.dmax=32768,t.head=null,t.hold=0,t.bits=0,t.lencode=t.lendyn=new r.Buf32(p),t.distcode=t.distdyn=new r.Buf32(m),t.sane=1,t.back=-1,u):d}function v(e){var t;return e&&e.state?((t=e.state).wsize=0,t.whave=0,t.wnext=0,_(e)):d}function y(e,t){var n,r;return e&&e.state?(r=e.state,t<0?(n=0,t=-t):(n=1+(t>>4),t<48&&(t&=15)),t&&(t<8||15=o.wsize?(r.arraySet(o.window,t,n-o.wsize,o.wsize,0),o.wnext=0,o.whave=o.wsize):(i<(a=o.wsize-o.wnext)&&(a=i),r.arraySet(o.window,t,n-i,a,o.wnext),(i-=a)?(r.arraySet(o.window,t,n-i,i,0),o.wnext=i,o.whave=o.wsize):(o.wnext+=a,o.wnext===o.wsize&&(o.wnext=0),o.whave>>8&255,n.check=a(n.check,B,2,0),x=b=0,n.mode=2;break}if(n.flags=0,n.head&&(n.head.done=!1),!(1&n.wrap)||(((255&b)<<8)+(b>>8))%31){e.msg=`incorrect header check`,n.mode=30;break}if((15&b)!=8){e.msg=`unknown compression method`,n.mode=30;break}if(x-=4,F=8+(15&(b>>>=4)),n.wbits===0)n.wbits=F;else if(F>n.wbits){e.msg=`invalid window size`,n.mode=30;break}n.dmax=1<>8&1),512&n.flags&&(B[0]=255&b,B[1]=b>>>8&255,n.check=a(n.check,B,2,0)),x=b=0,n.mode=3;case 3:for(;x<32;){if(v===0)break e;v--,b+=p[g++]<>>8&255,B[2]=b>>>16&255,B[3]=b>>>24&255,n.check=a(n.check,B,4,0)),x=b=0,n.mode=4;case 4:for(;x<16;){if(v===0)break e;v--,b+=p[g++]<>8),512&n.flags&&(B[0]=255&b,B[1]=b>>>8&255,n.check=a(n.check,B,2,0)),x=b=0,n.mode=5;case 5:if(1024&n.flags){for(;x<16;){if(v===0)break e;v--,b+=p[g++]<>>8&255,n.check=a(n.check,B,2,0)),x=b=0}else n.head&&(n.head.extra=null);n.mode=6;case 6:if(1024&n.flags&&(v<(E=n.length)&&(E=v),E&&(n.head&&(F=n.head.extra_len-n.length,n.head.extra||(n.head.extra=Array(n.head.extra_len)),r.arraySet(n.head.extra,p,g,E,F)),512&n.flags&&(n.check=a(n.check,p,E,g)),v-=E,g+=E,n.length-=E),n.length))break e;n.length=0,n.mode=7;case 7:if(2048&n.flags){if(v===0)break e;for(E=0;F=p[g+ E++],n.head&&F&&n.length<65536&&(n.head.name+=String.fromCharCode(F)),F&&E>9&1,n.head.done=!0),e.adler=n.check=0,n.mode=12;break;case 10:for(;x<32;){if(v===0)break e;v--,b+=p[g++]<>>=7&x,x-=7&x,n.mode=27;break}for(;x<3;){if(v===0)break e;v--,b+=p[g++]<>>=1)){case 0:n.mode=14;break;case 1:if(w(n),n.mode=20,t!==6)break;b>>>=2,x-=2;break e;case 2:n.mode=17;break;case 3:e.msg=`invalid block type`,n.mode=30}b>>>=2,x-=2;break;case 14:for(b>>>=7&x,x-=7&x;x<32;){if(v===0)break e;v--,b+=p[g++]<>>16^65535)){e.msg=`invalid stored block lengths`,n.mode=30;break}if(n.length=65535&b,x=b=0,n.mode=15,t===6)break e;case 15:n.mode=16;case 16:if(E=n.length){if(v>>=5,x-=5,n.ndist=1+(31&b),b>>>=5,x-=5,n.ncode=4+(15&b),b>>>=4,x-=4,286>>=3,x-=3}for(;n.have<19;)n.lens[V[n.have++]]=0;if(n.lencode=n.lendyn,n.lenbits=7,L={bits:n.lenbits},I=s(0,n.lens,0,19,n.lencode,0,n.work,L),n.lenbits=L.bits,I){e.msg=`invalid code lengths set`,n.mode=30;break}n.have=0,n.mode=19;case 19:for(;n.have>>16&255,j=65535&z,!((k=z>>>24)<=x);){if(v===0)break e;v--,b+=p[g++]<>>=k,x-=k,n.lens[n.have++]=j;else{if(j===16){for(R=k+2;x>>=k,x-=k,n.have===0){e.msg=`invalid bit length repeat`,n.mode=30;break}F=n.lens[n.have-1],E=3+(3&b),b>>>=2,x-=2}else if(j===17){for(R=k+3;x>>=k)),b>>>=3,x-=3}else{for(R=k+7;x>>=k)),b>>>=7,x-=7}if(n.have+E>n.nlen+n.ndist){e.msg=`invalid bit length repeat`,n.mode=30;break}for(;E--;)n.lens[n.have++]=F}}if(n.mode===30)break;if(n.lens[256]===0){e.msg=`invalid code -- missing end-of-block`,n.mode=30;break}if(n.lenbits=9,L={bits:n.lenbits},I=s(c,n.lens,0,n.nlen,n.lencode,0,n.work,L),n.lenbits=L.bits,I){e.msg=`invalid literal/lengths set`,n.mode=30;break}if(n.distbits=6,n.distcode=n.distdyn,L={bits:n.distbits},I=s(l,n.lens,n.nlen,n.ndist,n.distcode,0,n.work,L),n.distbits=L.bits,I){e.msg=`invalid distances set`,n.mode=30;break}if(n.mode=20,t===6)break e;case 20:n.mode=21;case 21:if(6<=v&&258<=y){e.next_out=_,e.avail_out=y,e.next_in=g,e.avail_in=v,n.hold=b,n.bits=x,o(e,C),_=e.next_out,m=e.output,y=e.avail_out,g=e.next_in,p=e.input,v=e.avail_in,b=n.hold,x=n.bits,n.mode===12&&(n.back=-1);break}for(n.back=0;A=(z=n.lencode[b&(1<>>16&255,j=65535&z,!((k=z>>>24)<=x);){if(v===0)break e;v--,b+=p[g++]<>M)])>>>16&255,j=65535&z,!(M+(k=z>>>24)<=x);){if(v===0)break e;v--,b+=p[g++]<>>=M,x-=M,n.back+=M}if(b>>>=k,x-=k,n.back+=k,n.length=j,A===0){n.mode=26;break}if(32&A){n.back=-1,n.mode=12;break}if(64&A){e.msg=`invalid literal/length code`,n.mode=30;break}n.extra=15&A,n.mode=22;case 22:if(n.extra){for(R=n.extra;x>>=n.extra,x-=n.extra,n.back+=n.extra}n.was=n.length,n.mode=23;case 23:for(;A=(z=n.distcode[b&(1<>>16&255,j=65535&z,!((k=z>>>24)<=x);){if(v===0)break e;v--,b+=p[g++]<>M)])>>>16&255,j=65535&z,!(M+(k=z>>>24)<=x);){if(v===0)break e;v--,b+=p[g++]<>>=M,x-=M,n.back+=M}if(b>>>=k,x-=k,n.back+=k,64&A){e.msg=`invalid distance code`,n.mode=30;break}n.offset=j,n.extra=15&A,n.mode=24;case 24:if(n.extra){for(R=n.extra;x>>=n.extra,x-=n.extra,n.back+=n.extra}if(n.offset>n.dmax){e.msg=`invalid distance too far back`,n.mode=30;break}n.mode=25;case 25:if(y===0)break e;if(E=C-y,n.offset>E){if((E=n.offset-E)>n.whave&&n.sane){e.msg=`invalid distance too far back`,n.mode=30;break}D=E>n.wnext?(E-=n.wnext,n.wsize-E):n.wnext-E,E>n.length&&(E=n.length),O=n.window}else O=m,D=_-n.offset,E=n.length;for(yv?(b=L[R+d[w]],N[P+d[w]]):(b=96,0),p=1<>k)+(m-=p)]=y<<24|b<<16|x|0,m!==0;);for(p=1<>=1;if(p===0?M=0:(M&=p-1,M+=p),w++,--F[C]==0){if(C===E)break;C=t[n+d[w]]}if(D>>7)]}function L(e,t){e.pending_buf[e.pending++]=255&t,e.pending_buf[e.pending++]=t>>>8&255}function R(e,t,n){e.bi_valid>h-n?(e.bi_buf|=t<>h-e.bi_valid,e.bi_valid+=n-h):(e.bi_buf|=t<>>=1,n<<=1,0<--t;);return n>>>1}function V(e,t,n){var r,i,a=Array(m+1),o=0;for(r=1;r<=m;r++)a[r]=o=o+n[r-1]<<1;for(i=0;i<=t;i++){var s=e[2*i+1];s!==0&&(e[2*i]=B(a[s]++,s))}}function H(e){var t;for(t=0;t>1;1<=n;n--)W(e,a,n);for(i=c;n=e.heap[1],e.heap[1]=e.heap[e.heap_len--],W(e,a,1),r=e.heap[1],e.heap[--e.heap_max]=n,e.heap[--e.heap_max]=r,a[2*i]=a[2*n]+a[2*r],e.depth[i]=(e.depth[n]>=e.depth[r]?e.depth[n]:e.depth[r])+1,a[2*n+1]=a[2*r+1]=i,e.heap[1]=i++,W(e,a,1),2<=e.heap_len;);e.heap[--e.heap_max]=e.heap[1],function(e,t){var n,r,i,a,o,s,c=t.dyn_tree,l=t.max_code,u=t.stat_desc.static_tree,d=t.stat_desc.has_stree,f=t.stat_desc.extra_bits,h=t.stat_desc.extra_base,g=t.stat_desc.max_length,_=0;for(a=0;a<=m;a++)e.bl_count[a]=0;for(c[2*e.heap[e.heap_max]+1]=0,n=e.heap_max+1;n>=7;r>>=1)if(1&n&&e.dyn_ltree[2*t]!==0)return i;if(e.dyn_ltree[18]!==0||e.dyn_ltree[20]!==0||e.dyn_ltree[26]!==0)return a;for(t=32;t>>3,(s=e.static_len+3+7>>>3)<=o&&(o=s)):o=s=n+5,n+4<=o&&t!==-1?Y(e,t,n,r):e.strategy===4||s===o?(R(e,2+ +!!r,3),G(e,T,E)):(R(e,4+ +!!r,3),function(e,t,n,r){var i;for(R(e,t-257,5),R(e,n-1,5),R(e,r-4,4),i=0;i>>8&255,e.pending_buf[e.d_buf+2*e.last_lit+1]=255&t,e.pending_buf[e.l_buf+e.last_lit]=255&n,e.last_lit++,t===0?e.dyn_ltree[2*n]++:(e.matches++,t--,e.dyn_ltree[2*(O[n]+l+1)]++,e.dyn_dtree[2*I(t)]++),e.last_lit===e.lit_bufsize-1},n._tr_align=function(e){R(e,2,3),z(e,_,T),function(e){e.bi_valid===16?(L(e,e.bi_buf),e.bi_buf=0,e.bi_valid=0):8<=e.bi_valid&&(e.pending_buf[e.pending++]=255&e.bi_buf,e.bi_buf>>=8,e.bi_valid-=8)}(e)}},{"../utils/common":41}],53:[function(e,t,n){t.exports=function(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg=``,this.state=null,this.data_type=2,this.adler=0}},{}],54:[function(e,t,n){(function(e){(function(e,t){if(!e.setImmediate){var n,r,i,a,o=1,s={},c=!1,l=e.document,u=Object.getPrototypeOf&&Object.getPrototypeOf(e);u=u&&u.setTimeout?u:e,n={}.toString.call(e.process)===`[object process]`?function(e){process.nextTick(function(){f(e)})}:function(){if(e.postMessage&&!e.importScripts){var t=!0,n=e.onmessage;return e.onmessage=function(){t=!1},e.postMessage(``,`*`),e.onmessage=n,t}}()?(a=`setImmediate$`+Math.random()+`$`,e.addEventListener?e.addEventListener(`message`,p,!1):e.attachEvent(`onmessage`,p),function(t){e.postMessage(a+t,`*`)}):e.MessageChannel?((i=new MessageChannel).port1.onmessage=function(e){f(e.data)},function(e){i.port2.postMessage(e)}):l&&`onreadystatechange`in l.createElement(`script`)?(r=l.documentElement,function(e){var t=l.createElement(`script`);t.onreadystatechange=function(){f(e),t.onreadystatechange=null,r.removeChild(t),t=null},r.appendChild(t)}):function(e){setTimeout(f,0,e)},u.setImmediate=function(e){typeof e!=`function`&&(e=Function(``+e));for(var t=Array(arguments.length-1),r=0;r`u`?e===void 0?this:e:self)}).call(this,typeof global<`u`?global:typeof self<`u`?self:typeof window<`u`?window:{})},{}]},{},[10])(10)})})),O=d(b(),1),k=d(D(),1),A=f(),j=`LocalNovelsDB`,M=`novels_shelf`,N=1;function P(){return new Promise((e,t)=>{let n=indexedDB.open(j,N);n.onupgradeneeded=e=>{let t=e.target.result;t.objectStoreNames.contains(M)||t.createObjectStore(M,{keyPath:`id`})},n.onsuccess=t=>e(t.target.result),n.onerror=e=>t(e.target.error)})}async function F(){try{let e=await P();return new Promise((t,n)=>{let r=e.transaction(M,`readonly`).objectStore(M).getAll();r.onsuccess=()=>t(r.result||[]),r.onerror=()=>n(r.error)})}catch(e){return console.error(`IndexedDB getLocalBooks error:`,e),[]}}async function I(e){try{let t=await P();return new Promise((n,r)=>{let i=t.transaction(M,`readwrite`).objectStore(M).put(e);i.onsuccess=()=>n(!0),i.onerror=()=>r(i.error)})}catch(e){return console.error(`IndexedDB saveLocalBook error:`,e),!1}}async function L(e){try{let t=await P();return new Promise((n,r)=>{let i=t.transaction(M,`readwrite`).objectStore(M).delete(e);i.onsuccess=()=>n(!0),i.onerror=()=>r(i.error)})}catch(e){return console.error(`IndexedDB deleteLocalBook error:`,e),!1}}function R(){let{theme:d,fontSize:f,fontFamily:p,lineHeight:m,setTheme:_,decreaseFontSize:b,increaseFontSize:D}=T(),{t:j,lang:N}=h();n(`web`,`read`);let[R,z]=(0,O.useState)([]),[B,V]=(0,O.useState)(null),[H,U]=(0,O.useState)(0),[ee,W]=(0,O.useState)(!1),[G,K]=(0,O.useState)(!1),[q,te]=(0,O.useState)(!1),[J,Y]=(0,O.useState)(new Set),[ne,re]=(0,O.useState)(!1),[ie,ae]=(0,O.useState)(``),[oe,se]=(0,O.useState)(0),{activeAudioObj:X,setActiveAudioObj:ce}=S(),[le,ue]=(0,O.useState)(-1),[de,fe]=(0,O.useState)(()=>localStorage.getItem(`tts_auto_scroll`)!==`false`),[pe,me]=(0,O.useState)(()=>{try{return JSON.parse(localStorage.getItem(`translationSettings`)||`{}`).audioSpeed||1.5}catch{return 1.5}});(0,O.useEffect)(()=>{let e=e=>{e.detail?.audioSpeed&&me(e.detail.audioSpeed)};return window.addEventListener(`translationSettingsUpdated`,e),()=>window.removeEventListener(`translationSettingsUpdated`,e)},[]);let he=()=>{let e=!de;fe(e),localStorage.setItem(`tts_auto_scroll`,e?`true`:`false`)},Z=X&&X.book?.id===B?.id&&X.chapterIdx===H,ge=()=>{let e=B?.chapters[H]?.content||``;if(!e)return null;let t=e.split(/\s+/).filter(Boolean).length,n=Math.round(t/(150*pe)*60);return{minutes:Math.floor(n/60),seconds:n%60,wordCount:t}},[_e,ve]=(0,O.useState)(`Truyện Test Offline`),[ye,be]=(0,O.useState)(`Antigravity`),[xe,Se]=(0,O.useState)(``),[Ce,we]=(0,O.useState)(`Chương 1: Khởi Đầu +Đây là nội dung chương 1. +Chương 2: Bước Ngoặt +Đây là nội dung chương 2.`),[Te,Ee]=(0,O.useState)(`auto`),[De,Q]=(0,O.useState)(``),[Oe,ke]=(0,O.useState)(``),[Ae,je]=(0,O.useState)(null),Me=async()=>{if(navigator.storage&&navigator.storage.estimate)try{let e=await navigator.storage.estimate();je({usage:(e.usage/(1024*1024)).toFixed(2),quota:(e.quota/(1024*1024)).toLocaleString(void 0,{maximumFractionDigits:0})})}catch(e){console.error(`Failed to get storage estimate:`,e)}};(0,O.useEffect)(()=>{async function e(){z(await F()),Me()}e()},[]),(0,O.useEffect)(()=>{Me()},[R]);let Ne=async()=>{let e=N===`zh`?`⚠️ 警告:此操作将删除设备上保存的所有离线小说,且无法恢复。您确定要删除吗?`:N===`en`?`⚠️ WARNING: This will DELETE ALL offline novels saved on this device and CANNOT be recovered. Are you sure you want to delete?`:`⚠️ CẢNH BÁO: Hành động này sẽ XÓA TOÀN BỘ truyện offline lưu trong thiết bị và không thể khôi phục. Bạn có chắc chắn muốn xóa không?`,t=N===`zh`?`成功清空离线存储空间。`:N===`en`?`Successfully cleared offline storage memory.`:`Đã xóa sạch bộ nhớ lưu trữ offline thành công.`,n=N===`zh`?`清空存储出错: `:N===`en`?`Error clearing storage: `:`Lỗi khi dọn dẹp bộ nhớ: `;if(confirm(e))try{let e=(await P()).transaction(M,`readwrite`).objectStore(M);await new Promise((t,n)=>{let r=e.clear();r.onsuccess=()=>t(!0),r.onerror=e=>n(e.target.error)});for(let e=0;e{if(B){let e=`local_progress_${B.id}`,t=localStorage.getItem(e);if(t!==null){let e=parseInt(t);e>=0&&e{let e=e=>{B&&e.detail&&e.detail.bookId===B.id&&e.detail.chapterIdx!==H&&U(e.detail.chapterIdx)};return window.addEventListener(`global-tts-chapter-changed`,e),()=>window.removeEventListener(`global-tts-chapter-changed`,e)},[B,H]),(0,O.useEffect)(()=>{let e=e=>{ue(e.detail.charIdx)};return window.addEventListener(`global-tts-boundary`,e),()=>window.removeEventListener(`global-tts-boundary`,e)},[]),(0,O.useEffect)(()=>{if(Z&&le>0&&de){let e=document.getElementById(`active-tts-sentence`);e&&e.scrollIntoView({behavior:`smooth`,block:`center`})}},[le,Z,de]),(0,O.useEffect)(()=>{if(B){let e=`local_progress_${B.id}`;localStorage.setItem(e,H.toString()),window.scrollTo(0,0),se(Math.floor(H/100));let t=B.chapters[H]?.title||`Chương 1`;z(e=>e.map(e=>e.id===B.id?{...e,lastReadChapter:t,updatedAt:Date.now()}:e))}},[H]);let Pe=async e=>{try{let t=await e.arrayBuffer(),n=await k.default.loadAsync(t),r=null,i=``,a=n.file(`META-INF/container.xml`);if(a){let e=(await a.async(`text`)).match(/full-path="([^"]+\.opf)"/i);if(e){i=e[1];let t=n.file(i);t&&(r=await t.async(`text`))}}if(!r){for(let e of Object.keys(n.files))if(e.endsWith(`.opf`)){i=e,r=await n.files[e].async(`text`);break}}let o=i?i.split(`/`).slice(0,-1).join(`/`):``,s=``,c=``,l=null;if(r){let e=r.match(/]*>([\s\S]*?)<\/dc:title>/i)||r.match(/]*>([\s\S]*?)<\/title>/i);e&&(s=e[1].replace(/<[^>]+>/g,``).trim());let t=r.match(/]*>([\s\S]*?)<\/dc:creator>/i)||r.match(/]*>([\s\S]*?)<\/creator>/i)||r.match(/]*>([\s\S]*?)<\/dc:publisher>/i);t&&(c=t[1].replace(/<[^>]+>/g,``).trim());let i={},a=r.matchAll(/]+)>/gi);for(let e of a){let t=e[1],n=t.match(/id=["']([^"']+)["']/i),r=t.match(/href=["']([^"']+)["']/i),a=t.match(/media-type=["']([^"']+)["']/i),o=t.match(/properties=["']([^"']+)["']/i);n&&r&&(i[n[1]]={href:r[1],mediaType:a?a[1]:``,properties:o?o[1]:``})}let u=null;for(let[e,t]of Object.entries(i))if(e.toLowerCase().includes(`cover`)||t.properties&&t.properties.toLowerCase().includes(`cover-image`)||t.mediaType.startsWith(`image/`)&&e.toLowerCase()===`cover`){u=t.href;break}if(!u){let e=r.match(/]+name=["']cover["'][^>]+content=["']([^"']+)["']/i)||r.match(/]+content=["']([^"']+)["'][^>]+name=["']cover["']/i);e&&i[e[1]]&&(u=i[e[1]].href)}if(!u){for(let[e,t]of Object.entries(i))if(t.mediaType.startsWith(`image/`)&&/cover|thumb|front/i.test(e+t.href)){u=t.href;break}}if(!u){for(let[,e]of Object.entries(i))if(e.mediaType.startsWith(`image/`)){u=e.href;break}}if(u){let e=decodeURIComponent(u),t=o?`${o}/${e}`:e,r=n.file(t)||n.file(e)||n.file(u);if(r)try{let e=await r.async(`base64`),t=u.split(`.`).pop().toLowerCase();l=`data:${t===`png`?`image/png`:t===`gif`?`image/gif`:t===`webp`?`image/webp`:`image/jpeg`};base64,${e}`}catch(e){console.warn(`Cover extraction failed:`,e)}}}let u=[];if(r){let e={},t=r.matchAll(/]+)>/gi);for(let n of t){let t=n[1],r=t.match(/id="([^"]+)"/i),i=t.match(/href="([^"]+)"/i);r&&i&&(e[r[1]]=i[1])}let n=r.matchAll(/]+)>/gi);for(let t of n){let n=t[1].match(/idref="([^"]+)"/i);n&&e[n[1]]&&u.push(e[n[1]])}}u.length===0&&(u=Object.keys(n.files).filter(e=>e.endsWith(`.html`)||e.endsWith(`.xhtml`)||e.endsWith(`.htm`)));let d=[];for(let e of u){let t=decodeURIComponent(e),r=o?`${o}/${t}`:t,i=n.file(r)||n.file(t)||n.file(e);if(!i){let e=t.split(`/`).pop();for(let t of Object.keys(n.files))if(t.endsWith(e)){i=n.file(t);break}}if(!i)continue;let a=await i.async(`text`),s=``,c=a.match(/]*>([\s\S]*?)<\/h[1-3]>/i);if(c&&(s=c[1].replace(/<[^>]+>/g,``).trim()),!s){let e=a.match(/]*>([\s\S]*?)<\/title>/i);e&&(s=e[1].replace(/<[^>]+>/g,``).trim())}s||=t.split(`/`).pop().replace(/\.xhtml$/i,``).replace(/\.html$/i,``);let l=a.match(/]*>([\s\S]*?)<\/body>/i),u=l?l[1]:a;u=u.replace(/<\/p>/gi,` +`).replace(//gi,` +`).replace(/<\/div>/gi,` +`).replace(/<[^>]+>/g,``).replace(/ /g,` `).replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`).replace(/"/g,`"`).replace(/'/g,`'`).replace(/\n{3,}/g,` + +`).trim(),u.length>5&&d.push({title:s,content:u})}return{chapters:d,title:s,author:c,coverBase64:l}}catch(e){return console.error(`EPUB parse error:`,e),null}},Fe=async e=>{let t=e.target.files[0];if(!t)return;if(ke(``),Q(``),t.name.endsWith(`.epub`)){Q(N===`zh`?`正在解析 EPUB 文件...`:N===`en`?`Parsing EPUB file...`:`Đang phân tích tệp EPUB...`);let e=await Pe(t);if(!e||!e.chapters||e.chapters.length===0){ke(N===`zh`?`无法读取 EPUB 内容。文件可能已被加密或无效。`:N===`en`?`Cannot read EPUB content. File may be encrypted or invalid.`:`Không thể đọc nội dung EPUB. Tệp có thể bị mã hóa hoặc không hợp lệ.`),Q(``);return}let{chapters:n,title:r,author:i,coverBase64:a}=e,o=r||t.name.replace(/\.epub$/i,``).replace(/_/g,` `),s=i||(N===`zh`?`未知`:N===`en`?`Unknown`:`Chưa rõ`);_e||ve(o),ye||be(s);let c={id:`local_`+Date.now(),title:o,author:s,cover:a||null,chapters:n,updatedAt:Date.now(),lastReadChapter:n[0].title};I(c).then(()=>{z(e=>[c,...e]),W(!1),Q(N===`zh`?`✓ 成功导入 EPUB:共 ${n.length} 章。`:N===`en`?`✓ Successfully imported EPUB: ${n.length} chapters.`:`✓ Đã nhúng EPUB thành công: ${n.length} chương${i?` — Tác giả: ${i}`:``}.`),setTimeout(()=>Q(``),4e3)});return}let n=new FileReader;t.name.endsWith(`.json`)?(n.onload=e=>{try{let t=JSON.parse(e.target.result);Array.isArray(t)?t.length>0&&t[0].title&&t[0].content?(we(JSON.stringify(t,null,2)),Ee(`json`),Q(N===`zh`?`成功加载 JSON 文件:检测到 ${t.length} 个章节。`:N===`en`?`Successfully loaded JSON file: ${t.length} chapters detected.`:`Đã tải tệp JSON thành công: ${t.length} chương phát hiện.`)):ke(N===`zh`?`JSON 格式不正确。格式应为 [{ title: '...', content: '...' }]`:N===`en`?`Invalid JSON format. Expected [{ title: '...', content: '...' }]`:`Tệp JSON không đúng định dạng. Cần dạng mảng [{ title: '...', content: '...' }]`):ke(N===`zh`?`JSON 文件必须是章节列表。`:N===`en`?`JSON file must be a list of chapters.`:`Tệp JSON phải là một danh sách các chương.`)}catch{ke(N===`zh`?`JSON 语法错误。请检查文件。`:N===`en`?`JSON syntax error. Please check your file.`:`Lỗi cú pháp JSON. Vui lòng kiểm tra lại tệp.`)}},n.readAsText(t)):(n.onload=e=>{we(e.target.result),Ee(`auto`),Q(N===`zh`?`成功加载文本文件:${(e.target.result.length/1024).toFixed(1)} KB。`:N===`en`?`Successfully loaded text file: ${(e.target.result.length/1024).toFixed(1)} KB.`:`Đã tải tệp văn bản thành công: ${(e.target.result.length/1024).toFixed(1)} KB.`)},n.readAsText(t))},Ie=e=>{if(e.preventDefault(),!_e.trim()||!ye.trim()||!Ce.trim()){alert(N===`zh`?`请填写书名、作者和小说内容。`:N===`en`?`Please fill in Book Title, Author and Novel Content.`:`Vui lòng điền đầy đủ Tên truyện, Tác giả và Nội dung truyện.`);return}let t=[];if(Te===`json`)try{let e=JSON.parse(Ce);Array.isArray(e)&&(t=e.map((e,t)=>({title:e.title||(N===`zh`?`第 ${t+1} 章`:N===`en`?`Chapter ${t+1}`:`Chương ${t+1}`),content:e.content||``})))}catch{alert(N===`zh`?`JSON 内容无效。`:N===`en`?`Invalid JSON content.`:`Nội dung JSON không hợp lệ.`);return}else{let e=Ce.split(` +`),n=``,r=[],i=/^([Cc]hương|[Cc]hapter|[Qq]uyển\s+\d+\s+[Cc]hương)\s+(\d+|[IVXLCDM]+|[一二三四五六七八九十百千]+)([:\s.-]|$)/i;for(let a=0;a0)&&t.push({title:n||(N===`zh`?`前言 / 简介`:N===`en`?`Introduction / Prologue`:`Giới thiệu / Mở đầu`),content:r.join(` +`).trim()}),n=s,r=[]):(s||r.length>0)&&r.push(o)}(n||r.length>0)&&t.push({title:n||(N===`zh`?`第 1 章`:N===`en`?`Chapter 1`:`Chương 1`),content:r.join(` +`).trim()})}if(t.length===0){alert(N===`zh`?`在输入文本中未找到任何章节。请尝试手动解析。`:N===`en`?`No chapters found in the input text. Try to parse manually.`:`Không tìm thấy chương nào trong văn bản đã nhập. Hãy thử phân tích thủ công.`);return}let n={id:`local_`+Date.now(),title:_e.trim(),author:ye.trim(),cover:xe.trim()||null,chapters:t,updatedAt:Date.now(),lastReadChapter:t[0].title};I(n).then(()=>{z(e=>[n,...e]),ve(``),be(``),Se(``),we(``),Q(``),W(!1)})},Le=async(e,t)=>{t.stopPropagation(),confirm(N===`zh`?`您确定要从设备中删除这部小说吗?此操作无法撤销。`:N===`en`?`Are you sure you want to delete this novel from your device? This action cannot be undone.`:`Bạn có chắc chắn muốn xoá truyện này khỏi thiết bị không? Hành động này không thể hoàn tác.`)&&(await L(e),z(t=>t.filter(t=>t.id!==e)),localStorage.removeItem(`local_progress_${e}`),Y(t=>{let n=new Set(t);return n.delete(e),n}))},Re=(e,t)=>{t&&t.stopPropagation(),Y(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},ze=()=>{J.size===R.length?Y(new Set):Y(new Set(R.map(e=>e.id).filter(Boolean)))},Be=async()=>{let e=N===`zh`?`您确定要删除选中的 ${J.size} 部小说吗?此操作无法撤销。`:N===`en`?`Are you sure you want to delete the ${J.size} selected novels? This action cannot be undone.`:`Bạn có chắc chắn muốn xóa ${J.size} truyện đã chọn khỏi thiết bị không? Hành động này không thể hoàn tác.`;if(confirm(e)){for(let e of J)await L(e),localStorage.removeItem(`local_progress_${e}`);z(e=>e.filter(e=>!J.has(e.id))),Y(new Set),te(!1)}},Ve=new URLSearchParams(window.location.search),He=Ve.get(`clean`)===`true`||Ve.get(`embed`)===`true`||window.self!==window.top,[Ue,We]=(0,O.useState)(()=>localStorage.getItem(`local_reader_width`)||`medium`),Ge=e=>{We(e),localStorage.setItem(`local_reader_width`,e)},Ke=()=>{switch(Ue){case`narrow`:return`max-w-2xl`;case`wide`:return`max-w-5xl`;case`full`:return`max-w-none px-6 md:px-12 lg:px-24`;default:return`max-w-3xl`}},qe=()=>{Z?(ce(null),ue(-1)):ce({title_vietphrase:B.chapters[H]?.title||``,title:B.chapters[H]?.title||``,description:B.chapters[H]?.content||``,isChapter:!0,onBoundary:e=>{ue(e)},book:B,chapterIdx:H,playType:`local`})},Je=(e,t)=>{let n=B?.chapters[H]?.content||``,r=n.split(/\n+/),i=0;for(let t=0;te?(s.test(r.trim())&&(o.push(r.trim()),l=!1),r=t):r+=t}}r.trim()&&s.test(r.trim())&&(o.push(r.trim()),l=!1)}let u=o.length;ce({title_vietphrase:B.chapters[H]?.title||``,title:B.chapters[H]?.title||``,description:n,isChapter:!0,onBoundary:e=>{ue(e)},book:B,chapterIdx:H,playType:`local`,startSentenceIdx:u})},Ye=()=>{let e=(B?.chapters[H]?.content||$.emptyChapterContent).split(/\n+/),t=0,n=le-((B?.chapters[H]?.title?.length||0)+2);return e.map((e,r)=>{let i=t;t+=e.length+1;let a=Z&&n>=i&&n=0;n--)if([`.`,`?`,`!`,` +`].includes(e[n])){r=n+1;break}let a=e.length;for(let n=t;nJe(r,e),className:`cursor-pointer hover:bg-purple-500/5 px-2 py-1 rounded transition-colors duration-150 relative group`,title:`Nháy đúp để đọc từ đoạn này`,children:o},r)})},Xe=()=>{B?I({...B,lastReadChapter:B.chapters[H]?.title||`Chương 1`,updatedAt:Date.now()}).then(()=>{V(null)}):V(null)},Ze=()=>{switch(d){case`light`:return`bg-amber-50/90 text-slate-900 border-amber-200/40`;case`sepia`:return`bg-[#f4ebd0] text-[#5c4033] border-[#e4d5b0]`;case`gray`:return`bg-[#1e293b] text-slate-200 border-slate-700/40`;default:return`bg-[#0f0f26]/85 text-slate-200 border-indigo-950/40`}},Qe=()=>{switch(d){case`light`:return`bg-amber-50 text-slate-900`;case`sepia`:return`bg-[#f5eccb] text-[#422e24]`;case`gray`:return`bg-[#181d2a] text-slate-200`;default:return`bg-[#0b0c16] text-slate-300`}},$e={vi:{offlineFeature:`Tính năng Offline / Client-Side`,embedTitle:`Nhúng & Đọc Truyện Của Bạn`,embedDesc:`Tải lên hoặc dán nội dung văn bản truyện bất kỳ từ thiết bị của bạn. Công cụ sẽ tự động phân tách chương và lưu trữ an toàn trong bộ nhớ trình duyệt để bạn thưởng thức với giao diện đọc cao cấp.`,embedNewBtn:`Nhúng truyện mới`,importTitle:`Nhập thông tin truyện nhúng`,closeBtn:`Đóng lại`,bookTitleLabel:`Tiêu đề truyện *`,bookTitlePlaceholder:`Ví dụ: Đại Quản Gia Là Ma Hoàng`,authorLabel:`Tác giả *`,authorPlaceholder:`Ví dụ: Dạ Kiêu`,coverUrlLabel:`Ảnh bìa URL (Không bắt buộc)`,selectFileLabel:`Chọn hoặc Tải lên tập tin dữ liệu`,autoSplitTxt:`Tự động phân chương (TXT)`,jsonFormat:`JSON Format`,dragDropFile:`Kéo thả hoặc Chọn tập tin`,supportedFormats:`Hỗ trợ .epub • .txt • .json`,epubHelp:`📘 EPUB: Tải trực tiếp file .epub — tự động trích xuất tất cả chương và thêm ngay vào tủ sách.`,txtHelp:`📄 TXT: Dán văn bản thô. Hệ thống tự phân chương qua từ khóa 'Chương 1...', 'Chapter 2...'.`,jsonHelp:`⚙️ JSON: Định dạng mảng [{"title": "...", "content": "..."}]`,rawContentLabel:`Nội dung truyện (Dán văn bản thô hoặc văn bản JSON)`,rawContentPlaceholderTxt:`Nhập hoặc dán toàn bộ nội dung của cuốn truyện ở đây...`,rawContentPlaceholderJson:`[ + { + "title": "Chương 1: Khởi đầu", + "content": "Nội dung chương 1 ở đây..." + } +]`,cancelBtn:`Hủy bỏ`,parseAddBtn:`Phân tích & Thêm truyện`,myShelfTitle:`📚 Tủ Sách Nhúng Của Bạn`,offlineStorage:`💾 Bộ nhớ offline`,clearBtn:`Dọn sạch`,emptyShelf:`Không có truyện nhúng nào trong bộ nhớ cục bộ.`,embedFirstBtn:`Nhúng tác phẩm đầu tiên`,authorPrefix:`Tác giả: `,chaptersCount:`chương offline`,readingProgress:`📖 Đang đọc: `,clearBtnTitle:`Xóa toàn bộ truyện đã lưu ngoại tuyến`,deleteBtnTitle:`Xóa truyện khỏi thiết bị`,backToShelf:`Tủ sách`,prevChapter:`Chương trước`,nextChapter:`Chương sau`,toc:`Mục lục`,audioAiTitle:`Đọc Audio AI`,settingsTitle:`Cài đặt giao diện`,readerThemeTitle:`Giao diện đọc`,fontSizeTitle:`Kích thước chữ`,bgThemeTitle:`Màu nền trang`,themeDark:`Tối`,themeGray:`Xám đêm`,themeSepia:`Hoài cổ`,themeLight:`Sáng`,pageWidthTitle:`Độ rộng trang đọc`,widthNarrow:`Hẹp`,widthMedium:`Vừa`,widthWide:`Rộng`,widthFull:`100%`,emptyChapterContent:`Nội dung chương trống.`,bottomPrevChapter:`Chương trước`,bottomNextChapter:`Chương sau`,tocModalTitle:`Mục lục tác phẩm`,chaptersCountSuffix:`chương`,searchChaptersPlaceholder:`Tìm kiếm chương theo tên hoặc số...`,paginationChaptersGroup:`Chương`,noMatchedChapters:`Không tìm thấy chương nào trùng khớp.`,readingBadge:`Đang đọc`},en:{offlineFeature:`Offline / Client-Side Mode`,embedTitle:`Embed & Read Your Own Novels`,embedDesc:`Upload or paste any novel text content from your device. The tool will automatically split chapters and store them securely in the browser memory for you to enjoy in our premium reading interface.`,embedNewBtn:`Embed New Novel`,importTitle:`Import Embedded Novel Info`,closeBtn:`Close`,bookTitleLabel:`Book Title *`,bookTitlePlaceholder:`e.g. The Grandmaster of Demonic Cultivation`,authorLabel:`Author *`,authorPlaceholder:`e.g. MXTX`,coverUrlLabel:`Cover Image URL (Optional)`,selectFileLabel:`Choose or Upload Data File`,autoSplitTxt:`Auto Split Chapters (TXT)`,jsonFormat:`JSON Format`,dragDropFile:`Drag & drop or Click to choose`,supportedFormats:`Supports .epub • .txt • .json`,epubHelp:`📘 EPUB: Upload .epub file directly — auto extracts all chapters and adds them to shelf.`,txtHelp:`📄 TXT: Paste raw text. Auto detects chapters via keywords like 'Chapter 1...', 'Chapter 2...'.`,jsonHelp:`⚙️ JSON: Array format [{"title": "...", "content": "..."}]`,rawContentLabel:`Novel Content (Paste raw text or JSON array)`,rawContentPlaceholderTxt:`Enter or paste the complete content of the novel here...`,rawContentPlaceholderJson:`[ + { + "title": "Chapter 1: The Beginning", + "content": "Chapter 1 content here..." + } +]`,cancelBtn:`Cancel`,parseAddBtn:`Parse & Add Novel`,myShelfTitle:`📚 Your Embedded Bookshelf`,offlineStorage:`💾 Offline Storage`,clearBtn:`Clear All`,emptyShelf:`No embedded novels in local memory.`,embedFirstBtn:`Embed your first book`,authorPrefix:`Author: `,chaptersCount:`offline chapters`,readingProgress:`📖 Reading: `,clearBtnTitle:`Delete all offline stored books`,deleteBtnTitle:`Delete book from device`,backToShelf:`Bookshelf`,prevChapter:`Prev Chapter`,nextChapter:`Next Chapter`,toc:`TOC`,audioAiTitle:`Read Audio AI`,settingsTitle:`Reader Settings`,readerThemeTitle:`Reading Interface`,fontSizeTitle:`Font Size`,bgThemeTitle:`Background Theme`,themeDark:`Dark`,themeGray:`Gray`,themeSepia:`Sepia`,themeLight:`Light`,pageWidthTitle:`Page Width`,widthNarrow:`Narrow`,widthMedium:`Medium`,widthWide:`Wide`,widthFull:`100%`,emptyChapterContent:`Chapter content is empty.`,bottomPrevChapter:`Prev`,bottomNextChapter:`Next`,tocModalTitle:`Table of Contents`,chaptersCountSuffix:`chapters`,searchChaptersPlaceholder:`Search chapters by title or index...`,paginationChaptersGroup:`Chapters`,noMatchedChapters:`No matching chapters found.`,readingBadge:`Reading`},zh:{offlineFeature:`离线 / 客户端模式`,embedTitle:`嵌入并阅读您的小说`,embedDesc:`上传或粘贴设备上的任何小说文本内容。系统将自动拆分章节并安全地保存在浏览器内存中,让您在高级阅读界面中尽情享受阅读乐趣。`,embedNewBtn:`导入新小说`,importTitle:`输入导入小说信息`,closeBtn:`关闭`,bookTitleLabel:`书名 *`,bookTitlePlaceholder:`例如:魔道祖师`,authorLabel:`作者 *`,authorPlaceholder:`例如:墨香铜臭`,coverUrlLabel:`封面图片链接 (选填)`,selectFileLabel:`选择或上传数据文件`,autoSplitTxt:`自动分割章节 (TXT)`,jsonFormat:`JSON 格式`,dragDropFile:`拖拽或点击选择文件`,supportedFormats:`支持 .epub • .txt • .json`,epubHelp:`📘 EPUB: 直接上传 .epub 文件 — 自动提取所有章节并添加到书架中。`,txtHelp:`📄 TXT: 粘贴纯文本。系统通过 '第1章...'、'第2章...' 自动分章。`,jsonHelp:`⚙️ JSON: 数组格式 [{"title": "...", "content": "..."}]`,rawContentLabel:`小说内容 (粘贴纯文本或 JSON)`,rawContentPlaceholderTxt:`在此处输入或粘贴小说的完整内容...`,rawContentPlaceholderJson:`[ + { + "title": "第 1 章:开始", + "content": "第一章内容..." + } +]`,cancelBtn:`取消`,parseAddBtn:`解析并导入小说`,myShelfTitle:`📚 您的离线书架`,offlineStorage:`💾 离线存储`,clearBtn:`清空`,emptyShelf:`本地存储中没有导入的小说。`,embedFirstBtn:`导入第一本作品`,authorPrefix:`作者: `,chaptersCount:`章离线内容`,readingProgress:`📖 正在阅读: `,clearBtnTitle:`清空所有离线保存的小说`,deleteBtnTitle:`从设备删除此小说`,backToShelf:`书架`,prevChapter:`上一章`,nextChapter:`下一章`,toc:`目录`,audioAiTitle:`AI 语音朗读`,settingsTitle:`界面设置`,readerThemeTitle:`阅读界面`,fontSizeTitle:`字体大小`,bgThemeTitle:`背景颜色`,themeDark:`深色`,themeGray:`夜灰`,themeSepia:`复古`,themeLight:`明亮`,pageWidthTitle:`页面宽度`,widthNarrow:`窄版`,widthMedium:`中等`,widthWide:`宽版`,widthFull:`满宽`,emptyChapterContent:`章节内容为空。`,bottomPrevChapter:`上一章`,bottomNextChapter:`下一章`,tocModalTitle:`作品目录`,chaptersCountSuffix:`章`,searchChaptersPlaceholder:`按名称或序号搜索章节...`,paginationChaptersGroup:`章节`,noMatchedChapters:`未找到匹配章节。`,readingBadge:`正读`}},$=$e[N]||$e.vi;return(0,A.jsx)(r,{hideHeader:He,children:B?(0,A.jsxs)(`div`,{className:`transition-colors duration-300 relative ${He?`w-full min-h-screen rounded-none border-none`:`min-h-[80vh] rounded-3xl overflow-hidden border shadow-2xl`} ${Ze()}`,children:[(0,A.jsxs)(`div`,{className:`px-4 sm:px-6 py-3 sm:py-4 border-b border-white/5 flex items-center justify-between gap-2 bg-inherit`,children:[(0,A.jsxs)(`button`,{onClick:Xe,className:`flex items-center gap-1 px-2.5 py-1.5 rounded-full hover:bg-white/5 text-xs font-bold transition-all text-slate-400 hover:text-white`,children:[(0,A.jsx)(t,{className:`w-4 h-4`}),(0,A.jsx)(`span`,{className:`hidden sm:inline`,children:$.backToShelf})]}),(0,A.jsxs)(`div`,{className:`flex items-center gap-0.5 sm:gap-1 bg-black/15 rounded-2xl p-0.5 sm:p-1 border border-white/5`,children:[(0,A.jsx)(`button`,{disabled:H===0,onClick:()=>U(e=>e-1),className:`p-1.5 sm:p-2 rounded-xl hover:bg-white/5 disabled:opacity-30 disabled:pointer-events-none transition-all text-slate-300`,title:$.prevChapter,children:(0,A.jsx)(w,{className:`w-4 h-4`})}),(0,A.jsxs)(`button`,{onClick:()=>re(!0),className:`flex items-center gap-1 px-2 sm:px-3 py-1 sm:py-1.5 rounded-xl bg-[#0b0c16] hover:bg-[#181d2a] border border-[#232342]/75 text-[11px] sm:text-xs font-bold text-slate-300 transition-all active:scale-95 max-w-[100px] sm:max-w-[240px] truncate`,children:[(0,A.jsx)(a,{className:`w-3.5 h-3.5 text-purple-400 shrink-0`}),(0,A.jsx)(`span`,{className:`truncate`,children:B.chapters[H]?.title||$.toc})]}),(0,A.jsx)(`button`,{disabled:H===B.chapters.length-1,onClick:()=>U(e=>e+1),className:`p-1.5 sm:p-2 rounded-xl hover:bg-white/5 disabled:opacity-30 disabled:pointer-events-none transition-all text-slate-300`,title:$.nextChapter,children:(0,A.jsx)(g,{className:`w-4 h-4`})})]}),(0,A.jsxs)(`div`,{className:`flex items-center gap-2.5`,children:[(0,A.jsxs)(`div`,{className:`flex items-center gap-1 bg-black/10 border border-white/5 p-1 rounded-xl`,children:[(0,A.jsx)(`button`,{onClick:qe,className:`p-1.5 rounded-lg border transition-all ${Z?`bg-purple-600 border-purple-600 text-white shadow shadow-purple-500/25`:`border-transparent text-slate-300 hover:bg-white/5`}`,title:$.audioAiTitle,children:Z?(0,A.jsx)(y,{className:`w-4 h-4 animate-pulse`}):(0,A.jsx)(C,{className:`w-4 h-4`})}),X&&(0,A.jsxs)(A.Fragment,{children:[(0,A.jsx)(`button`,{onClick:()=>{if(X.book?.id===B?.id)if(X.chapterIdx!==H)U(X.chapterIdx);else{let e=document.getElementById(`active-tts-sentence`);e&&e.scrollIntoView({behavior:`smooth`,block:`center`})}else alert(`Đang phát ở sách khác: `+(X.book?.title||`Không rõ`))},className:`p-1.5 rounded-lg text-slate-300 hover:bg-white/5 hover:text-white transition-all`,title:`Quay lại vị trí/chương đang đọc`,children:(0,A.jsx)(e,{className:`w-4 h-4`})}),(0,A.jsx)(`button`,{onClick:he,className:`p-1.5 rounded-lg transition-all ${de?`text-purple-400 bg-purple-500/10`:`text-slate-500 hover:text-slate-300`}`,title:de?`Tắt tự động cuộn trang`:`Bật tự động cuộn trang`,children:(0,A.jsx)(c,{className:`w-4 h-4`})})]})]}),(0,A.jsxs)(`div`,{className:`relative`,children:[(0,A.jsx)(`button`,{onClick:()=>K(!G),className:`p-2 rounded-xl bg-black/10 border border-white/5 hover:bg-white/5 text-slate-300 transition-all`,title:$.settingsTitle,children:(0,A.jsx)(v,{className:`w-4 h-4`})}),G&&(0,A.jsxs)(`div`,{className:`absolute right-0 mt-3 w-64 bg-[#12122b] border border-purple-500/20 rounded-2xl p-4 shadow-xl z-50 space-y-4 text-slate-300`,children:[(0,A.jsx)(`h5`,{className:`text-xs font-bold text-white uppercase tracking-wider pb-2 border-b border-white/5`,children:$.readerThemeTitle}),(0,A.jsxs)(`div`,{className:`space-y-2`,children:[(0,A.jsx)(`span`,{className:`text-[10px] font-bold text-slate-400`,children:$.fontSizeTitle}),(0,A.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,A.jsx)(`button`,{onClick:b,className:`px-3 py-1 bg-[#1c1c3c] rounded-lg text-xs font-bold hover:bg-[#2a2a5a]`,children:`A-`}),(0,A.jsxs)(`span`,{className:`text-xs font-bold`,children:[f,`px`]}),(0,A.jsx)(`button`,{onClick:D,className:`px-3 py-1 bg-[#1c1c3c] rounded-lg text-xs font-bold hover:bg-[#2a2a5a]`,children:`A+`})]})]}),(0,A.jsxs)(`div`,{className:`space-y-2`,children:[(0,A.jsx)(`span`,{className:`text-[10px] font-bold text-slate-400`,children:$.bgThemeTitle}),(0,A.jsxs)(`div`,{className:`grid grid-cols-4 gap-2`,children:[(0,A.jsx)(`button`,{onClick:()=>_(`dark`),className:`h-8 rounded-lg bg-[#0b0c16] border border-white/5 ${d===`dark`?`ring-2 ring-purple-500`:``}`,title:$.themeDark}),(0,A.jsx)(`button`,{onClick:()=>_(`gray`),className:`h-8 rounded-lg bg-[#181d2a] border border-slate-700 ${d===`gray`?`ring-2 ring-purple-500`:``}`,title:$.themeGray}),(0,A.jsx)(`button`,{onClick:()=>_(`sepia`),className:`h-8 rounded-lg bg-[#f5eccb] border border-[#e4d5b0] ${d===`sepia`?`ring-2 ring-purple-500`:``}`,title:$.themeSepia}),(0,A.jsx)(`button`,{onClick:()=>_(`light`),className:`h-8 rounded-lg bg-amber-50 border border-slate-300 ${d===`light`?`ring-2 ring-purple-500`:``}`,title:$.themeLight})]})]}),(0,A.jsxs)(`div`,{className:`space-y-2`,children:[(0,A.jsx)(`span`,{className:`text-[10px] font-bold text-slate-400`,children:$.pageWidthTitle}),(0,A.jsxs)(`div`,{className:`grid grid-cols-4 gap-1 bg-[#0b0c16]/50 p-1 rounded-xl border border-white/5`,children:[(0,A.jsx)(`button`,{onClick:()=>Ge(`narrow`),className:`py-1 text-[10px] font-bold rounded-lg transition-all ${Ue===`narrow`?`bg-purple-600 text-white shadow`:`text-slate-400 hover:text-white`}`,children:$.widthNarrow}),(0,A.jsx)(`button`,{onClick:()=>Ge(`medium`),className:`py-1 text-[10px] font-bold rounded-lg transition-all ${Ue===`medium`?`bg-purple-600 text-white shadow`:`text-slate-400 hover:text-white`}`,children:$.widthMedium}),(0,A.jsx)(`button`,{onClick:()=>Ge(`wide`),className:`py-1 text-[10px] font-bold rounded-lg transition-all ${Ue===`wide`?`bg-purple-600 text-white shadow`:`text-slate-400 hover:text-white`}`,children:$.widthWide}),(0,A.jsx)(`button`,{onClick:()=>Ge(`full`),className:`py-1 text-[10px] font-bold rounded-lg transition-all ${Ue===`full`?`bg-purple-600 text-white shadow`:`text-slate-400 hover:text-white`}`,children:$.widthFull})]})]})]})]})]})]}),(0,A.jsxs)(`div`,{className:`px-6 py-12 md:px-16 mx-auto space-y-6 ${Ke()} ${Qe()}`,children:[(0,A.jsx)(`h3`,{className:`text-center font-bold text-lg md:text-xl text-slate-100 tracking-tight pb-2 border-b border-white/5`,children:B.chapters[H]?.title}),ge()&&(0,A.jsxs)(`div`,{className:`text-center text-[10px] text-slate-400 mt-2 flex justify-center items-center gap-2`,children:[(0,A.jsxs)(`span`,{children:[`⏱️ Thời gian đọc: ~`,ge().minutes,` phút `,ge().seconds,` giây (tốc độ `,pe.toFixed(1),`x)`]}),(0,A.jsx)(`span`,{children:`•`}),(0,A.jsxs)(`span`,{children:[`📝 `,ge().wordCount,` từ`]})]}),(0,A.jsx)(`div`,{style:{fontSize:`${f}px`,lineHeight:`1.8`},className:`space-y-6 whitespace-pre-wrap select-text leading-relaxed tracking-wide font-sans text-justify pt-4`,children:Ye()})]}),(0,A.jsxs)(`div`,{className:`px-4 sm:px-6 py-4 sm:py-6 border-t border-white/5 flex items-center justify-between gap-2 bg-inherit`,children:[(0,A.jsxs)(`button`,{disabled:H===0,onClick:()=>U(e=>e-1),className:`flex items-center gap-1 px-3 py-2 rounded-xl bg-black/10 hover:bg-black/20 disabled:opacity-40 disabled:pointer-events-none text-xs font-bold transition-all active:scale-95 text-slate-300`,children:[(0,A.jsx)(w,{className:`w-4 h-4`}),(0,A.jsx)(`span`,{children:$.bottomPrevChapter})]}),(0,A.jsxs)(`div`,{className:`flex items-center gap-1.5 sm:gap-2.5`,children:[(0,A.jsxs)(`button`,{onClick:()=>re(!0),className:`flex items-center gap-1.5 px-3 py-2 rounded-xl bg-purple-600/10 hover:bg-purple-600/20 text-purple-400 border border-purple-500/20 text-xs font-bold transition-all active:scale-95`,children:[(0,A.jsx)(a,{className:`w-3.5 h-3.5`}),(0,A.jsx)(`span`,{className:`hidden sm:inline`,children:$.toc})]}),(0,A.jsxs)(`span`,{className:`text-[10px] sm:text-xs text-slate-500 font-bold whitespace-nowrap`,children:[H+1,` / `,B.chapters.length]})]}),(0,A.jsxs)(`button`,{disabled:H===B.chapters.length-1,onClick:()=>U(e=>e+1),className:`flex items-center gap-1 px-3 py-2 rounded-xl bg-black/10 hover:bg-black/20 disabled:opacity-40 disabled:pointer-events-none text-xs font-bold transition-all active:scale-95 text-slate-300`,children:[(0,A.jsx)(`span`,{children:$.bottomNextChapter}),(0,A.jsx)(g,{className:`w-4 h-4`})]})]}),ne&&(0,A.jsx)(`div`,{className:`fixed inset-0 z-[100] flex items-center justify-center bg-black/75 backdrop-blur-sm animate-fadeIn p-2 sm:p-4`,children:(0,A.jsxs)(`div`,{className:`bg-[#12122b] border border-purple-500/20 rounded-2xl sm:rounded-3xl w-full sm:max-w-2xl h-[90vh] sm:h-[80vh] flex flex-col overflow-hidden shadow-2xl relative`,children:[(0,A.jsxs)(`div`,{className:`px-6 py-4 border-b border-white/5 flex items-center justify-between`,children:[(0,A.jsxs)(`div`,{className:`space-y-1`,children:[(0,A.jsxs)(`h4`,{className:`text-sm font-extrabold text-white flex items-center gap-2`,children:[(0,A.jsx)(a,{className:`w-4 h-4 text-purple-400`}),` `,$.tocModalTitle]}),(0,A.jsxs)(`p`,{className:`text-[10px] text-slate-400`,children:[B.title,` — `,B.chapters.length,` `,$.chaptersCountSuffix]})]}),(0,A.jsx)(`button`,{onClick:()=>re(!1),className:`p-2 hover:bg-white/5 rounded-full text-slate-400 hover:text-white transition-all`,children:(0,A.jsx)(x,{className:`w-5 h-5`})})]}),(0,A.jsx)(`div`,{className:`p-4 border-b border-white/5 bg-[#0b0c16]/50`,children:(0,A.jsxs)(`div`,{className:`relative`,children:[(0,A.jsx)(o,{className:`absolute left-3 top-2.5 w-4 h-4 text-slate-500`}),(0,A.jsx)(`input`,{type:`text`,placeholder:$.searchChaptersPlaceholder,value:ie,onChange:e=>{ae(e.target.value),se(0)},className:`w-full pl-9 pr-4 py-2 bg-[#0b0c16] border border-[#232342] rounded-xl text-xs text-white placeholder-slate-500 outline-none focus:border-purple-500 transition-colors`})]})}),!ie.trim()&&B.chapters.length>100&&(0,A.jsx)(`div`,{className:`px-4 py-2 border-b border-white/5 flex gap-2 overflow-x-auto whitespace-nowrap scrollbar-none scroll-smooth`,children:Array.from({length:Math.ceil(B.chapters.length/100)}).map((e,t)=>{let n=t*100+1,r=Math.min((t+1)*100,B.chapters.length);return(0,A.jsxs)(`button`,{onClick:()=>se(t),className:`px-3 py-1.5 rounded-lg text-[10px] font-bold transition-all shrink-0 ${oe===t?`bg-purple-600 text-white`:`bg-[#1b1b36] text-slate-400 hover:text-white`}`,children:[$.paginationChaptersGroup,` `,n,` - `,r]},t)})}),(0,A.jsx)(`div`,{className:`flex-1 overflow-y-auto p-4 space-y-1 bg-[#0b0c16]/20`,children:(()=>{let e=[];if(ie.trim()){let t=ie.toLowerCase();e=B.chapters.map((e,t)=>({...e,idx:t})).filter(e=>e.title.toLowerCase().includes(t))}else{let t=oe*100,n=Math.min(t+100,B.chapters.length);e=B.chapters.slice(t,n).map((e,n)=>({...e,idx:t+n}))}return e.length===0?(0,A.jsx)(`div`,{className:`text-center py-12 text-slate-500 text-xs`,children:$.noMatchedChapters}):e.map(e=>{let t=H===e.idx;return(0,A.jsxs)(`button`,{onClick:()=>{U(e.idx),re(!1)},className:`w-full text-left px-4 py-3 rounded-xl text-xs font-semibold flex items-center justify-between transition-all ${t?`bg-purple-600/20 text-purple-300 border border-purple-500/20`:`hover:bg-white/5 text-slate-300 border border-transparent`}`,children:[(0,A.jsx)(`span`,{className:`truncate`,children:e.title}),t&&(0,A.jsx)(`span`,{className:`text-[9px] bg-purple-600 text-white px-2 py-0.5 rounded font-extrabold uppercase`,children:$.readingBadge})]},e.idx)})})()})]})})]}):(0,A.jsxs)(`div`,{className:`mx-auto space-y-8 animate-fadeIn ${He?`max-w-7xl px-6 py-8`:`max-w-6xl`}`,children:[(0,A.jsxs)(`div`,{className:`relative rounded-3xl overflow-hidden bg-gradient-to-r from-purple-900/40 to-indigo-900/40 border border-purple-500/20 p-8 md:p-12 shadow-2xl flex flex-col md:flex-row justify-between items-start md:items-center gap-6`,children:[(0,A.jsxs)(`div`,{className:`space-y-3 max-w-2xl`,children:[(0,A.jsx)(`span`,{className:`px-3 py-1 rounded-full text-[10px] font-bold uppercase tracking-wider bg-purple-500/20 border border-purple-500/30 text-purple-300`,children:$.offlineFeature}),(0,A.jsx)(`h2`,{className:`text-2xl md:text-3xl font-extrabold text-white tracking-tight`,children:$.embedTitle}),(0,A.jsx)(`p`,{className:`text-xs text-slate-400 leading-relaxed`,children:$.embedDesc})]}),(0,A.jsxs)(`button`,{onClick:()=>W(!0),className:`bg-purple-600 hover:bg-purple-500 text-white px-6 py-3 rounded-full text-xs font-bold shadow-lg shadow-purple-600/20 flex items-center gap-2 transition-all`,children:[(0,A.jsx)(l,{className:`w-4 h-4`}),` `,$.embedNewBtn]})]}),ee&&(0,A.jsxs)(`div`,{className:`bg-[#12122b]/90 border border-purple-500/20 rounded-2xl p-6 md:p-8 space-y-6 shadow-xl relative animate-slideUp`,children:[(0,A.jsxs)(`div`,{className:`flex justify-between items-center pb-4 border-b border-white/5`,children:[(0,A.jsxs)(`h3`,{onClick:()=>{ve(`Truyện Test Offline`),be(`Antigravity`),we(`Chương 1: Khởi Đầu +Đây là nội dung chương 1. +Chương 2: Bước Ngoặt +Đây là nội dung chương 2.`)},title:`Click to auto-fill (developer helper)`,className:`font-extrabold text-white text-base flex items-center gap-2 cursor-pointer select-none active:text-purple-400`,children:[(0,A.jsx)(a,{className:`w-5 h-5 text-purple-400`}),` `,$.importTitle]}),(0,A.jsx)(`button`,{onClick:()=>W(!1),className:`text-slate-400 hover:text-white text-xs transition-colors`,children:$.closeBtn})]}),(0,A.jsxs)(`form`,{onSubmit:Ie,className:`space-y-6`,children:[(0,A.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-3 gap-6`,children:[(0,A.jsxs)(`div`,{children:[(0,A.jsx)(`label`,{className:`block text-xs font-bold text-slate-300 uppercase tracking-wider mb-2`,children:$.bookTitleLabel}),(0,A.jsx)(`input`,{type:`text`,required:!0,id:`local-title-input`,value:_e,onChange:e=>ve(e.target.value),placeholder:$.bookTitlePlaceholder,className:`w-full bg-[#0a0a16] border border-[#232342] rounded-xl px-4 py-2.5 text-xs text-white placeholder-slate-500 focus:outline-none focus:border-purple-500 transition-colors`})]}),(0,A.jsxs)(`div`,{children:[(0,A.jsx)(`label`,{className:`block text-xs font-bold text-slate-300 uppercase tracking-wider mb-2`,children:$.authorLabel}),(0,A.jsx)(`input`,{type:`text`,required:!0,id:`local-author-input`,value:ye,onChange:e=>be(e.target.value),placeholder:$.authorPlaceholder,className:`w-full bg-[#0a0a16] border border-[#232342] rounded-xl px-4 py-2.5 text-xs text-white placeholder-slate-500 focus:outline-none focus:border-purple-500 transition-colors`})]}),(0,A.jsxs)(`div`,{children:[(0,A.jsx)(`label`,{className:`block text-xs font-bold text-slate-300 uppercase tracking-wider mb-2`,children:$.coverUrlLabel}),(0,A.jsx)(`input`,{type:`url`,id:`local-cover-input`,value:xe,onChange:e=>Se(e.target.value),placeholder:`https://example.com/cover.jpg`,className:`w-full bg-[#0a0a16] border border-[#232342] rounded-xl px-4 py-2.5 text-xs text-white placeholder-slate-500 focus:outline-none focus:border-purple-500 transition-colors`})]})]}),(0,A.jsxs)(`div`,{className:`bg-[#090916] rounded-xl p-6 border border-[#1d1d36] space-y-4`,children:[(0,A.jsxs)(`div`,{className:`flex justify-between items-center`,children:[(0,A.jsx)(`span`,{className:`text-xs font-bold text-slate-300 uppercase tracking-wider`,children:$.selectFileLabel}),(0,A.jsxs)(`div`,{className:`flex gap-2`,children:[(0,A.jsx)(`button`,{type:`button`,onClick:()=>Ee(`auto`),className:`px-3 py-1 rounded-full text-[10px] font-bold transition-all ${Te===`auto`?`bg-purple-600 text-white`:`bg-[#1b1b36] text-slate-400`}`,children:$.autoSplitTxt}),(0,A.jsx)(`button`,{type:`button`,onClick:()=>Ee(`json`),className:`px-3 py-1 rounded-full text-[10px] font-bold transition-all ${Te===`json`?`bg-purple-600 text-white`:`bg-[#1b1b36] text-slate-400`}`,children:$.jsonFormat})]})]}),(0,A.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-6`,children:[(0,A.jsxs)(`div`,{className:`flex flex-col items-center justify-center border-2 border-dashed border-[#232342] hover:border-purple-500/40 rounded-xl p-6 transition-all bg-[#0d0d1e] relative`,children:[(0,A.jsx)(`input`,{type:`file`,accept:`.txt,.json,.epub`,onChange:Fe,className:`absolute inset-0 w-full h-full opacity-0 cursor-pointer`}),(0,A.jsx)(E,{className:`w-8 h-8 text-purple-400 mb-2`}),(0,A.jsx)(`span`,{className:`text-xs font-semibold text-slate-300`,children:$.dragDropFile}),(0,A.jsx)(`span`,{className:`text-[9px] text-slate-500 mt-1`,children:$.supportedFormats})]}),(0,A.jsxs)(`div`,{className:`space-y-3`,children:[(0,A.jsxs)(`span`,{className:`text-[10px] text-slate-400 block leading-relaxed space-y-1`,children:[$.epubHelp,(0,A.jsx)(`br`,{}),$.txtHelp,(0,A.jsx)(`br`,{}),$.jsonHelp]}),De&&(0,A.jsxs)(`div`,{className:`bg-emerald-500/10 border border-emerald-500/20 text-emerald-400 rounded-lg p-3 text-[10px] flex items-center gap-2`,children:[(0,A.jsx)(s,{className:`w-3.5 h-3.5 shrink-0`}),(0,A.jsx)(`span`,{children:De})]}),Oe&&(0,A.jsxs)(`div`,{className:`bg-red-500/10 border border-red-500/20 text-red-400 rounded-lg p-3 text-[10px] flex items-center gap-2`,children:[(0,A.jsx)(i,{className:`w-3.5 h-3.5 shrink-0`}),(0,A.jsx)(`span`,{children:Oe})]})]})]})]}),(0,A.jsxs)(`div`,{children:[(0,A.jsx)(`label`,{className:`block text-xs font-bold text-slate-300 uppercase tracking-wider mb-2`,children:$.rawContentLabel}),(0,A.jsx)(`textarea`,{required:!0,id:`local-content-textarea`,value:Ce,onChange:e=>we(e.target.value),placeholder:Te===`json`?$.rawContentPlaceholderJson:$.rawContentPlaceholderTxt,className:`w-full h-64 bg-[#0a0a16] border border-[#232342] rounded-xl px-4 py-3 text-xs text-white placeholder-slate-600 focus:outline-none focus:border-purple-500 font-mono transition-colors`})]}),(0,A.jsxs)(`div`,{className:`flex justify-end gap-3`,children:[(0,A.jsx)(`button`,{type:`button`,onClick:()=>W(!1),className:`bg-[#1b1b36] hover:bg-[#232346] text-slate-300 px-5 py-2.5 rounded-full text-xs font-bold transition-all`,children:$.cancelBtn}),(0,A.jsx)(`button`,{type:`submit`,id:`local-submit-btn`,className:`bg-purple-600 hover:bg-purple-500 text-white px-6 py-2.5 rounded-full text-xs font-bold shadow-lg shadow-purple-600/25 transition-all`,children:$.parseAddBtn})]})]})]}),(0,A.jsxs)(`div`,{className:`space-y-4`,children:[(0,A.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-4 border-b border-[#232342]/30 pb-3`,children:[(0,A.jsxs)(`div`,{className:`flex items-center flex-wrap gap-3`,children:[(0,A.jsxs)(`h3`,{className:`font-extrabold text-white text-base flex items-center gap-2`,children:[$.myShelfTitle,` (`,R.length,`)`]}),R.length>0&&(0,A.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,A.jsx)(`button`,{onClick:()=>{te(!q),Y(new Set)},className:`px-3 py-1.5 rounded-lg text-xs font-bold transition-all border ${q?`bg-purple-600/25 border-purple-500/50 text-purple-300 hover:bg-purple-600/35`:`bg-white/5 border-white/10 text-slate-300 hover:bg-white/10`}`,children:q?N===`vi`?`Thoát quản lý`:N===`zh`?`退出管理`:`Exit management`:N===`vi`?`Quản lý tủ sách`:N===`zh`?`管理书架`:`Manage shelf`}),q&&(0,A.jsxs)(A.Fragment,{children:[(0,A.jsx)(`button`,{onClick:ze,className:`px-3 py-1.5 bg-[#121225] border border-[#1f1f3a] rounded-lg text-xs font-bold text-slate-300 hover:bg-[#1a1a35] transition-all`,children:J.size===R.length?N===`vi`?`Hủy chọn tất cả`:N===`zh`?`取消全选`:`Deselect all`:N===`vi`?`Chọn tất cả`:N===`zh`?`全选`:`Select all`}),J.size>0&&(0,A.jsxs)(`button`,{onClick:Be,className:`inline-flex items-center gap-1.5 px-3 py-1.5 bg-rose-600 hover:bg-rose-500 text-white rounded-lg text-xs font-bold shadow-lg shadow-rose-950/20 transition-all active:scale-95 cursor-pointer`,children:[(0,A.jsx)(u,{className:`w-3.5 h-3.5`}),N===`vi`?`Xóa đã chọn (${J.size})`:N===`zh`?`删除选中 (${J.size})`:`Delete Selected (${J.size})`]})]})]})]}),Ae&&(0,A.jsxs)(`div`,{className:`flex items-center gap-3 text-[11px] bg-[#12122b]/60 border border-[#232342] px-3.5 py-1.5 rounded-xl shadow-inner`,children:[(0,A.jsxs)(`span`,{className:`text-slate-400 font-medium flex items-center gap-1`,children:[$.offlineStorage,`: `,(0,A.jsxs)(`strong`,{className:`text-purple-400 font-bold`,children:[Ae.usage,` MB`]}),` / `,Ae.quota,` MB`]}),R.length>0&&(0,A.jsxs)(A.Fragment,{children:[(0,A.jsx)(`div`,{className:`w-px h-3 bg-white/10`}),(0,A.jsxs)(`button`,{onClick:Ne,className:`text-red-400 hover:text-red-300 font-extrabold flex items-center gap-1 transition-all`,title:$.clearBtnTitle,children:[(0,A.jsx)(u,{className:`w-3.5 h-3.5`}),` `,$.clearBtn]})]})]})]}),R.length===0?(0,A.jsxs)(`div`,{className:`border border-dashed border-[#232342] rounded-2xl py-16 text-center text-slate-500 text-xs flex flex-col items-center justify-center gap-3`,children:[(0,A.jsx)(a,{className:`w-10 h-10 text-slate-600`}),(0,A.jsx)(`span`,{children:$.emptyShelf}),(0,A.jsx)(`button`,{onClick:()=>W(!0),className:`bg-purple-600/10 hover:bg-purple-600/20 text-purple-400 border border-purple-500/25 px-4 py-2 rounded-full text-[11px] font-bold mt-2 transition-all`,children:$.embedFirstBtn})]}):(0,A.jsx)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6`,children:R.map(e=>{let t=J.has(e.id);return(0,A.jsxs)(`div`,{onClick:t=>{q?Re(e.id,t):V(e)},className:`bg-[#12122b]/60 border rounded-2xl p-5 flex gap-4 cursor-pointer transition-all hover:translate-y-[-2px] relative group shadow-md ${t?`border-purple-500 shadow-purple-500/5 bg-purple-950/5`:`border-[#232342] hover:border-purple-500/30`}`,children:[q&&(0,A.jsx)(`div`,{onClick:t=>Re(e.id,t),className:`absolute top-3 left-3 z-30 w-5 h-5 rounded border flex items-center justify-center cursor-pointer transition-all shadow-md ${t?`bg-purple-600 border-purple-500 text-white shadow-purple-500/20`:`bg-[#0f101f]/95 border-slate-700/80 text-slate-500 hover:bg-purple-950/25 hover:border-purple-500/50`}`,children:t&&(0,A.jsx)(s,{className:`w-3.5 h-3.5 stroke-[3]`})}),(0,A.jsx)(`div`,{className:q?`pl-4 transition-all`:`transition-all`,children:e.cover?(0,A.jsx)(`img`,{src:e.cover,alt:`cover`,className:`w-[70px] h-[96px] object-cover rounded-xl border border-indigo-950/20 shadow-md shrink-0 bg-[#0f0f1a]`,onError:e=>{e.target.style.display=`none`}}):(0,A.jsx)(`div`,{className:`w-[70px] h-[96px] rounded-xl border border-indigo-950/20 bg-[#0f0f26] flex items-center justify-center text-slate-500 shrink-0 shadow-md`,children:(0,A.jsx)(a,{className:`w-6 h-6 text-purple-500/50`})})}),(0,A.jsxs)(`div`,{className:`flex-1 min-w-0 flex flex-col justify-between`,children:[(0,A.jsxs)(`div`,{className:`space-y-1`,children:[(0,A.jsx)(`h4`,{className:`text-slate-100 font-extrabold text-sm truncate group-hover:text-purple-400 transition-colors`,children:e.title}),(0,A.jsxs)(`p`,{className:`text-[11px] text-slate-400 font-semibold truncate`,children:[$.authorPrefix,e.author]}),(0,A.jsxs)(`p`,{className:`text-[10px] text-slate-500`,children:[e.chapters.length,` `,$.chaptersCount]})]}),(0,A.jsx)(`div`,{className:`space-y-1`,children:(0,A.jsxs)(`span`,{className:`text-[9px] text-slate-400 block truncate font-semibold bg-[#1a1a36]/50 rounded-lg px-2 py-1 border border-white/5`,children:[$.readingProgress,e.lastReadChapter]})})]}),!q&&(0,A.jsx)(`button`,{onClick:t=>Le(e.id,t),className:`absolute top-4 right-4 p-2 rounded-xl bg-red-500/10 hover:bg-red-500 hover:text-white text-red-400 transition-all opacity-100 md:opacity-0 md:group-hover:opacity-100`,title:$.deleteBtnTitle,children:(0,A.jsx)(u,{className:`w-3.5 h-3.5`})})]},e.id)})})]})]})})}export{R as default}; \ No newline at end of file diff --git a/frontend-web/dist/assets/MainLayout-COiTxmNr.js b/frontend-web/dist/assets/MainLayout-COiTxmNr.js new file mode 100644 index 0000000000000000000000000000000000000000..b1378181210b79dfc87fadfd27ad11146e8c4aa0 --- /dev/null +++ b/frontend-web/dist/assets/MainLayout-COiTxmNr.js @@ -0,0 +1,3 @@ +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/esm-CLdWK6iE.js","assets/index-yRoRoI6u.js","assets/index-u0QqURGN.css","assets/dist-DE1p5HKj.js"])))=>i.map(i=>d[i]); +import{a as e,i as t,n,o as r,r as i,t as a}from"./square-DZKJ0QGR.js";import{A as o,C as s,D as c,E as l,F as u,M as d,S as f,T as p,_ as m,b as h,c as g,f as _,g as v,h as y,j as b,l as x,m as S,o as C,s as w,t as T,v as E,w as D,y as O}from"./index-yRoRoI6u.js";var ee=h(`bell`,[[`path`,{d:`M10.268 21a2 2 0 0 0 3.464 0`,key:`vwvbt9`}],[`path`,{d:`M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326`,key:`11g9vi`}]]),k=h(`book-open`,[[`path`,{d:`M12 7v14`,key:`1akyts`}],[`path`,{d:`M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z`,key:`ruj8y`}]]),A=h(`circle-alert`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`line`,{x1:`12`,x2:`12`,y1:`8`,y2:`12`,key:`1pkeuh`}],[`line`,{x1:`12`,x2:`12.01`,y1:`16`,y2:`16`,key:`4dfq90`}]]),j=h(`circle-check-big`,[[`path`,{d:`M21.801 10A10 10 0 1 1 17 3.335`,key:`yps3ct`}],[`path`,{d:`m9 11 3 3L22 4`,key:`1pflzl`}]]),M=h(`compass`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`m16.24 7.76-1.804 5.411a2 2 0 0 1-1.265 1.265L7.76 16.24l1.804-5.411a2 2 0 0 1 1.265-1.265z`,key:`9ktpf1`}]]),N=h(`crown`,[[`path`,{d:`M11.562 3.266a.5.5 0 0 1 .876 0L15.39 8.87a1 1 0 0 0 1.516.294L21.183 5.5a.5.5 0 0 1 .798.519l-2.834 10.246a1 1 0 0 1-.956.734H5.81a1 1 0 0 1-.957-.734L2.02 6.02a.5.5 0 0 1 .798-.519l4.276 3.664a1 1 0 0 0 1.516-.294z`,key:`1vdc57`}],[`path`,{d:`M5 21h14`,key:`11awu3`}]]),te=h(`gift`,[[`path`,{d:`M12 7v14`,key:`1akyts`}],[`path`,{d:`M20 11v8a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-8`,key:`1sqzm4`}],[`path`,{d:`M7.5 7a1 1 0 0 1 0-5A4.8 8 0 0 1 12 7a4.8 8 0 0 1 4.5-5 1 1 0 0 1 0 5`,key:`kc0143`}],[`rect`,{x:`3`,y:`7`,width:`18`,height:`4`,rx:`1`,key:`1hberx`}]]),P=h(`heart`,[[`path`,{d:`M2 9.5a5.5 5.5 0 0 1 9.591-3.676.56.56 0 0 0 .818 0A5.49 5.49 0 0 1 22 9.5c0 2.29-1.5 4-3 5.5l-5.492 5.313a2 2 0 0 1-3 .019L5 15c-1.5-1.5-3-3.2-3-5.5`,key:`mvr1a0`}]]),F=h(`key-round`,[[`path`,{d:`M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z`,key:`1s6t7t`}],[`circle`,{cx:`16.5`,cy:`7.5`,r:`.5`,fill:`currentColor`,key:`w0ekpg`}]]),I=h(`lock`,[[`rect`,{width:`18`,height:`11`,x:`3`,y:`11`,rx:`2`,ry:`2`,key:`1w4ew1`}],[`path`,{d:`M7 11V7a5 5 0 0 1 10 0v4`,key:`fwvmzm`}]]),L=h(`log-out`,[[`path`,{d:`m16 17 5-5-5-5`,key:`1bji2h`}],[`path`,{d:`M21 12H9`,key:`dn1m92`}],[`path`,{d:`M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4`,key:`1uf3rs`}]]),R=h(`mail`,[[`path`,{d:`m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7`,key:`132q7q`}],[`rect`,{x:`2`,y:`4`,width:`20`,height:`16`,rx:`2`,key:`izxlao`}]]),z=h(`message-square`,[[`path`,{d:`M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z`,key:`18887p`}]]),B=h(`refresh-cw`,[[`path`,{d:`M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8`,key:`v9h5vc`}],[`path`,{d:`M21 3v5h-5`,key:`1q7to0`}],[`path`,{d:`M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16`,key:`3uifl3`}],[`path`,{d:`M8 16H3v5`,key:`1cv678`}]]),ne=h(`send`,[[`path`,{d:`M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z`,key:`1ffxy3`}],[`path`,{d:`m21.854 2.147-10.94 10.939`,key:`12cjpa`}]]),re=h(`share-2`,[[`circle`,{cx:`18`,cy:`5`,r:`3`,key:`gq8acd`}],[`circle`,{cx:`6`,cy:`12`,r:`3`,key:`w7nqdw`}],[`circle`,{cx:`18`,cy:`19`,r:`3`,key:`1xt0gg`}],[`line`,{x1:`8.59`,x2:`15.42`,y1:`13.51`,y2:`17.49`,key:`47mynk`}],[`line`,{x1:`15.41`,x2:`8.59`,y1:`6.51`,y2:`10.49`,key:`1n3mei`}]]),V=h(`sparkles`,[[`path`,{d:`M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z`,key:`1s2grr`}],[`path`,{d:`M20 2v4`,key:`1rf3ol`}],[`path`,{d:`M22 4h-4`,key:`gwowj6`}],[`circle`,{cx:`4`,cy:`20`,r:`2`,key:`6kqj1y`}]]),H=h(`terminal`,[[`path`,{d:`M12 19h8`,key:`baeox8`}],[`path`,{d:`m4 17 6-6-6-6`,key:`1yngyt`}]]),U=h(`user-plus`,[[`path`,{d:`M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2`,key:`1yyitq`}],[`circle`,{cx:`9`,cy:`7`,r:`4`,key:`nufk8`}],[`line`,{x1:`19`,x2:`19`,y1:`8`,y2:`14`,key:`1bvyxn`}],[`line`,{x1:`22`,x2:`16`,y1:`11`,y2:`11`,key:`1shjgl`}]]),W=h(`user`,[[`path`,{d:`M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2`,key:`975kel`}],[`circle`,{cx:`12`,cy:`7`,r:`4`,key:`17ys0d`}]]),G=h(`users`,[[`path`,{d:`M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2`,key:`1yyitq`}],[`path`,{d:`M16 3.128a4 4 0 0 1 0 7.744`,key:`16gr8j`}],[`path`,{d:`M22 21v-2a4 4 0 0 0-3-3.87`,key:`kshegd`}],[`circle`,{cx:`9`,cy:`7`,r:`4`,key:`nufk8`}]]),K=u(b(),1),q=d();function J({className:e=`w-4 h-4`,...t}){return(0,q.jsxs)(`svg`,{xmlns:`http://www.w3.org/2000/svg`,width:`24`,height:`24`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,className:e,...t,children:[(0,q.jsx)(`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4`}),(0,q.jsx)(`polyline`,{points:`7 10 12 15 17 10`}),(0,q.jsx)(`line`,{x1:`12`,x2:`12`,y1:`15`,y2:`3`})]})}function ie({isOpen:e,onClose:t}){let{login:n,register:r}=s(),{t:i}=f(),[a,c]=(0,K.useState)(`login`),[l,u]=(0,K.useState)(``),[d,m]=(0,K.useState)(``),[h,g]=(0,K.useState)(``),[_,v]=(0,K.useState)(``),[y,b]=(0,K.useState)(``),[x,S]=(0,K.useState)(``),[w,T]=(0,K.useState)(!1);(0,K.useEffect)(()=>{e&&(c(`login`),u(``),m(``),g(``),v(``),b(``),S(``),window.google&&!window.electron&&(window.google.accounts.id.initialize({client_id:`107953505478-0gielhlbbif11eu77rb29sq7ie7dqbmn.apps.googleusercontent.com`,callback:E}),window.google.accounts.id.renderButton(document.getElementById(`google-signin-btn`),{theme:`filled_blue`,size:`large`,width:290})))},[e]);let E=async e=>{b(``),T(!0);try{let t=await D.post(`/api/auth/google/callback`,{credential:e.credential});t.data&&t.data.access_token&&(localStorage.setItem(`accessToken`,t.data.access_token),document.cookie=`accessToken=${t.data.access_token}; path=/; max-age=604800; SameSite=Lax`,localStorage.setItem(`user`,JSON.stringify(t.data.user)),t.data.user?.require_password_change===1?window.location.href=`/settings`:window.location.reload())}catch(e){b(e.response?.data?.error||`Lỗi đăng nhập Google`)}finally{T(!1)}};return e?(0,q.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-end sm:items-center justify-center sm:p-4 bg-black/60 backdrop-blur-sm`,onClick:e=>e.target===e.currentTarget&&t(),children:(0,q.jsxs)(`div`,{className:`relative w-full sm:max-w-md bg-[#131324] border border-[#2d2d6b] sm:rounded-2xl rounded-t-3xl p-6 shadow-2xl overflow-hidden animate-slide-up sm:animate-fadeIn max-h-[92dvh] overflow-y-auto`,children:[(0,q.jsx)(`div`,{className:`sm:hidden w-10 h-1 rounded-full bg-white/20 mx-auto mb-4`}),(0,q.jsx)(`button`,{onClick:t,className:`absolute right-4 top-4 text-slate-500 hover:text-white transition-colors`,children:(0,q.jsx)(C,{className:`w-6 h-6`})}),(0,q.jsxs)(`h3`,{className:`text-xl font-bold text-white mb-6`,children:[a===`login`&&i.auth?.loginTitle,a===`register`&&i.auth?.registerTitle,a===`verify_reg`&&i.auth?.verifyRegTitle,a===`forgot`&&i.auth?.forgotTitle,a===`reset`&&i.auth?.resetTitle]}),y&&(0,q.jsx)(`div`,{className:`mb-4 p-3 bg-red-500/10 border border-red-500/20 rounded-xl text-red-400 text-sm`,children:y}),x&&(0,q.jsx)(`div`,{className:`mb-4 p-3 bg-emerald-500/10 border border-emerald-500/20 rounded-xl text-emerald-400 text-sm`,children:x}),(0,q.jsxs)(`form`,{onSubmit:async e=>{e.preventDefault(),b(``),S(``),T(!0);try{if(a===`login`){if(!l||!d){b(i.authRequired),T(!1);return}let e=await n(l,d);t(),e&&e.require_password_change===1&&(window.location.href=`/settings`)}else if(a===`register`){if(!l||!d||!h){b(i.authRequired),T(!1);return}let e=await r(l,d,h);e.require_verification?(S(e.message||`Một mã xác minh đã được gửi đến email của bạn.`),c(`verify_reg`)):(S(i.regSuccess),c(`login`),m(``))}else if(a===`verify_reg`){if(!h||!_){b(`Vui lòng nhập đầy đủ email và mã OTP xác minh.`),T(!1);return}S((await D.post(`/api/auth/verify-registration`,{email:h,otp:_})).data.message||`Xác minh thành công! Vui lòng đăng nhập.`),c(`login`),m(``),v(``)}else if(a===`forgot`){if(!h){b(`Vui lòng nhập email.`),T(!1);return}S((await D.post(`/api/auth/forgot-password`,{email:h})).data.message||`Mã OTP đã được gửi đến email của bạn.`),c(`reset`)}else if(a===`reset`){if(!h||!_||!d){b(`Vui lòng điền đầy đủ thông tin.`),T(!1);return}S((await D.post(`/api/auth/reset-password`,{email:h,otp:_,password:d})).data.message||`Khôi phục mật khẩu thành công.`),c(`login`),m(``)}}catch(e){let t=e.response?.data;t?.require_verification?(g(t.email||h),c(`verify_reg`),b(t.error||`Tài khoản chưa được xác minh. Vui lòng nhập mã OTP.`)):b(t?.error||e.message||i.connError)}finally{T(!1)}},className:`space-y-4`,children:[(a===`login`||a===`register`)&&(0,q.jsxs)(`div`,{className:`relative`,children:[(0,q.jsx)(W,{className:`absolute left-3.5 top-1/2 -translate-y-1/2 w-5 h-5 text-slate-500`}),(0,q.jsx)(`input`,{type:`text`,placeholder:i.auth?.usernamePlaceholder,value:l,onChange:e=>u(e.target.value),className:`w-full pl-11 pr-4 py-3 bg-[#1e1e3a] border border-[#2d2d6b] rounded-xl text-white outline-none focus:border-brand-500 transition-colors`,required:!0})]}),(a===`register`||a===`forgot`||a===`reset`||a===`verify_reg`)&&(0,q.jsxs)(`div`,{className:`relative`,children:[(0,q.jsx)(R,{className:`absolute left-3.5 top-1/2 -translate-y-1/2 w-5 h-5 text-slate-500`}),(0,q.jsx)(`input`,{type:`email`,placeholder:i.auth?.emailPlaceholder,value:h,onChange:e=>g(e.target.value),className:`w-full pl-11 pr-4 py-3 bg-[#1e1e3a] border border-[#2d2d6b] rounded-xl text-white outline-none focus:border-brand-500 transition-colors`,required:!0,disabled:a===`verify_reg`})]}),(a===`reset`||a===`verify_reg`)&&(0,q.jsxs)(`div`,{className:`relative`,children:[(0,q.jsx)(F,{className:`absolute left-3.5 top-1/2 -translate-y-1/2 w-5 h-5 text-slate-500`}),(0,q.jsx)(`input`,{type:`text`,placeholder:i.auth?.otpPlaceholder,value:_,onChange:e=>v(e.target.value),className:`w-full pl-11 pr-4 py-3 bg-[#1e1e3a] border border-[#2d2d6b] rounded-xl text-white outline-none focus:border-brand-500 transition-colors`,required:!0})]}),a!==`forgot`&&a!==`verify_reg`&&(0,q.jsxs)(`div`,{className:`relative`,children:[(0,q.jsx)(I,{className:`absolute left-3.5 top-1/2 -translate-y-1/2 w-5 h-5 text-slate-500`}),(0,q.jsx)(`input`,{type:`password`,placeholder:a===`reset`?i.auth?.newPasswordPlaceholder:i.auth?.passwordPlaceholder,value:d,onChange:e=>m(e.target.value),className:`w-full pl-11 pr-4 py-3 bg-[#1e1e3a] border border-[#2d2d6b] rounded-xl text-white outline-none focus:border-brand-500 transition-colors`,required:!0})]}),(0,q.jsx)(`button`,{type:`submit`,disabled:w,className:`w-full py-3 bg-gradient-to-r from-brand-500 to-purple-600 hover:opacity-90 disabled:opacity-50 text-white font-bold rounded-xl shadow-lg transition-all`,children:w?i.auth?.processing:a===`login`?i.auth?.submitLogin:a===`register`?i.auth?.submitRegister:a===`forgot`?i.auth?.submitForgot:a===`verify_reg`?i.auth?.submitVerifyReg:i.auth?.submitReset})]}),a===`verify_reg`&&(0,q.jsx)(`div`,{className:`mt-3 text-center`,children:(0,q.jsx)(`button`,{onClick:async()=>{b(``),S(``),T(!0);try{S((await D.post(`/api/auth/resend-verification`,{email:h})).data.message||`Mã xác minh mới đã được gửi.`)}catch(e){b(e.response?.data?.error||`Lỗi gửi lại mã xác minh.`)}finally{T(!1)}},disabled:w,className:`text-xs text-brand-400 font-bold hover:underline`,children:i.auth?.resendOtpBtn})}),a===`login`&&(0,q.jsx)(`div`,{className:`mt-4 flex justify-center w-full px-1`,children:window.electron||window.Capacitor&&window.Capacitor.isNativePlatform&&window.Capacitor.isNativePlatform()?(0,q.jsxs)(`button`,{type:`button`,onClick:async()=>{b(``),T(!0);try{let e=await p(),t=`${e}/api/auth/google/login?state=desktop|${encodeURIComponent(e)}`,n=window.Capacitor&&window.Capacitor.isNativePlatform&&window.Capacitor.isNativePlatform();if(window.electron&&window.electron.openExternal)window.electron.openExternal(t);else if(n)try{let{Browser:e}=await o(async()=>{let{Browser:e}=await import(`./esm-CLdWK6iE.js`);return{Browser:e}},__vite__mapDeps([0,1,2,3]));await e.open({url:t})}catch(e){console.error(`Capacitor Browser failed, falling back to window.open`,e),window.open(t,`_system`)}else window.open(t,`_blank`)}catch{b(`Không thể mở liên kết đăng nhập. Vui lòng thử lại.`)}finally{T(!1)}},className:`w-full flex items-center justify-center gap-3 py-3 px-4 bg-white hover:bg-slate-50 active:bg-slate-100 text-slate-800 font-bold rounded-xl shadow-lg transition-all duration-200 transform hover:-translate-y-0.5 active:translate-y-0`,children:[(0,q.jsxs)(`svg`,{className:`w-5 h-5 flex-shrink-0`,viewBox:`0 0 24 24`,children:[(0,q.jsx)(`path`,{fill:`#4285F4`,d:`M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z`}),(0,q.jsx)(`path`,{fill:`#34A853`,d:`M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z`}),(0,q.jsx)(`path`,{fill:`#FBBC05`,d:`M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.06H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.94l2.85-2.22.81-.63z`}),(0,q.jsx)(`path`,{fill:`#EA4335`,d:`M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.06l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z`})]}),(0,q.jsx)(`span`,{className:`text-sm font-semibold`,children:`Đăng nhập với Google`})]}):(0,q.jsx)(`div`,{id:`google-signin-btn`})}),(0,q.jsxs)(`div`,{className:`mt-6 text-center text-sm text-slate-400 space-y-2`,children:[a===`login`&&(0,q.jsxs)(q.Fragment,{children:[(0,q.jsxs)(`div`,{children:[i.auth?.noAccount,` `,(0,q.jsx)(`button`,{onClick:()=>c(`register`),className:`text-brand-400 font-semibold hover:underline`,children:i.auth?.registerNow})]}),(0,q.jsx)(`div`,{children:(0,q.jsx)(`button`,{onClick:()=>c(`forgot`),className:`text-slate-500 text-xs hover:underline`,children:i.auth?.forgotPassLink})})]}),a===`register`&&(0,q.jsxs)(`div`,{children:[i.auth?.haveAccount,` `,(0,q.jsx)(`button`,{onClick:()=>c(`login`),className:`text-brand-400 font-semibold hover:underline`,children:i.auth?.submitLogin})]}),(a===`forgot`||a===`reset`||a===`verify_reg`)&&(0,q.jsx)(`div`,{children:(0,q.jsx)(`button`,{onClick:()=>c(`login`),className:`text-brand-400 font-semibold hover:underline`,children:i.auth?.backToLogin})})]})]})}):null}function ae({isOpen:e,onClose:t}){let{user:n,refreshUser:r}=s(),[i,a]=(0,K.useState)(`plans`),[o,c]=(0,K.useState)(`vip`),[l,u]=(0,K.useState)(`month`),[d,f]=(0,K.useState)(!1),[p,m]=(0,K.useState)(null),[h,g]=(0,K.useState)(!1),[_,y]=(0,K.useState)({});(0,K.useEffect)(()=>{e&&(a(`plans`),c(`vip`),u(`month`),m(null),g(!1))},[e]),(0,K.useEffect)(()=>{let e;if(h&&p){let n=async()=>{try{let e=await D.get(`/api/payment/status/${p.order_id}`);e.data.status===`completed`?(g(!1),alert(`Thanh toán thành công! Tài khoản của bạn đã được cập nhật 👑`),await r(),t()):e.data.status===`expired`&&(g(!1),alert(`Yêu cầu thanh toán đã hết hạn.`),a(`plans`))}catch(e){console.error(e)}};e=setInterval(()=>{document.hidden||n()},5e3)}return()=>clearInterval(e)},[h,p]);let b=(e,t)=>{navigator.clipboard.writeText(e).then(()=>{y(e=>({...e,[t]:!0})),setTimeout(()=>{y(e=>({...e,[t]:!1}))},1500)})};return e?(0,q.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-end sm:items-center justify-center sm:p-4 bg-black/60 backdrop-blur-sm`,onClick:e=>e.target===e.currentTarget&&t(),children:(0,q.jsxs)(`div`,{className:`relative w-full sm:max-w-md bg-gradient-to-b from-[#111122] to-[#17172e] border border-brand-500/35 sm:rounded-2xl rounded-t-3xl p-6 shadow-2xl overflow-y-auto max-h-[92dvh] animate-slide-up sm:animate-fadeIn`,children:[(0,q.jsx)(`div`,{className:`sm:hidden w-10 h-1 rounded-full bg-white/20 mx-auto mb-4`}),(0,q.jsx)(`button`,{onClick:t,className:`absolute right-4 top-4 text-slate-500 hover:text-white transition-colors`,children:(0,q.jsx)(C,{className:`w-6 h-6`})}),(0,q.jsxs)(`div`,{className:`text-center mb-5`,children:[(0,q.jsxs)(`h3`,{className:`text-xl font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-amber-400 to-amber-200 inline-flex items-center gap-2`,children:[(0,q.jsx)(N,{className:`w-6 h-6 text-amber-400 fill-amber-400`}),` DỊCH VỤ PREMIUM & DEVELOPER`]}),(0,q.jsx)(`p`,{className:`text-slate-400 text-xs mt-2 leading-relaxed`,children:`Mở khoá đặc quyền VIP hoặc nạp thêm số dư API cho các tài khoản nhà phát triển / ứng dụng Chrome Extension.`})]}),i===`plans`&&(0,q.jsxs)(`div`,{className:`flex bg-[#0b0b14]/90 p-1 rounded-xl border border-white/5 mb-5 text-[11px] font-bold`,children:[(0,q.jsx)(`button`,{onClick:()=>{c(`vip`),u(`month`)},className:`flex-1 py-2 rounded-lg transition-all ${o===`vip`?`bg-amber-500 text-[#0b0b14]`:`text-slate-400 hover:text-white`}`,children:`👑 Nâng Cấp VIP`}),(0,q.jsx)(`button`,{onClick:()=>{c(`topup`),u(`topup_50k`)},className:`flex-1 py-2 rounded-lg transition-all ${o===`topup`?`bg-amber-500 text-[#0b0b14]`:`text-slate-400 hover:text-white`}`,children:`⚡ Nạp Số Dư API`})]}),i===`plans`?(0,q.jsxs)(`div`,{className:`space-y-4`,children:[o===`vip`?(0,q.jsxs)(q.Fragment,{children:[(0,q.jsxs)(`div`,{onClick:()=>u(`month`),className:`p-4 rounded-2xl cursor-pointer border-2 transition-all flex justify-between items-center ${l===`month`?`bg-brand-500/10 border-amber-400 shadow-md shadow-brand-500/5`:`bg-white/5 border-white/5 hover:bg-white/10`}`,children:[(0,q.jsxs)(`div`,{children:[(0,q.jsx)(`h4`,{className:`text-white font-bold text-sm`,children:`Gói VIP 1 Tháng`}),(0,q.jsx)(`p`,{className:`text-slate-500 text-xs mt-1`,children:`Dịch AI & Nghe TTS không giới hạn`})]}),(0,q.jsx)(`div`,{className:`text-right`,children:(0,q.jsx)(`span`,{className:`text-amber-400 font-extrabold text-lg`,children:`50.000đ`})})]}),(0,q.jsxs)(`div`,{onClick:()=>u(`year`),className:`p-4 rounded-2xl cursor-pointer border-2 transition-all flex justify-between items-center ${l===`year`?`bg-brand-500/10 border-amber-400 shadow-md shadow-brand-500/5`:`bg-white/5 border-white/5 hover:bg-white/10`}`,children:[(0,q.jsxs)(`div`,{children:[(0,q.jsxs)(`h4`,{className:`text-white font-bold text-sm flex items-center gap-2`,children:[`Gói VIP 1 Năm`,(0,q.jsx)(`span`,{className:`bg-gradient-to-r from-amber-400 to-amber-600 text-[#0b0b14] text-[9px] font-extrabold px-2 py-0.5 rounded-md`,children:`TIẾT KIỆM 67%`})]}),(0,q.jsx)(`p`,{className:`text-slate-500 text-xs mt-1`,children:`Giá ưu đãi tốt nhất, thanh toán một lần`})]}),(0,q.jsx)(`div`,{className:`text-right`,children:(0,q.jsx)(`span`,{className:`text-amber-400 font-extrabold text-lg`,children:`200.000đ`})})]})]}):(0,q.jsxs)(q.Fragment,{children:[(0,q.jsxs)(`div`,{onClick:()=>u(`topup_50k`),className:`p-4 rounded-2xl cursor-pointer border-2 transition-all flex justify-between items-center ${l===`topup_50k`?`bg-brand-500/10 border-amber-400 shadow-md shadow-brand-500/5`:`bg-white/5 border-white/5 hover:bg-white/10`}`,children:[(0,q.jsxs)(`div`,{children:[(0,q.jsx)(`h4`,{className:`text-white font-bold text-sm`,children:`Gói Nạp 50.000đ`}),(0,q.jsx)(`p`,{className:`text-slate-500 text-xs mt-1`,children:`Nạp số dư tài khoản nhà phát triển API`})]}),(0,q.jsx)(`div`,{className:`text-right`,children:(0,q.jsx)(`span`,{className:`text-amber-400 font-extrabold text-lg`,children:`50.000đ`})})]}),(0,q.jsxs)(`div`,{onClick:()=>u(`topup_100k`),className:`p-4 rounded-2xl cursor-pointer border-2 transition-all flex justify-between items-center ${l===`topup_100k`?`bg-brand-500/10 border-amber-400 shadow-md shadow-brand-500/5`:`bg-white/5 border-white/5 hover:bg-white/10`}`,children:[(0,q.jsxs)(`div`,{children:[(0,q.jsx)(`h4`,{className:`text-white font-bold text-sm`,children:`Gói Nạp 100.000đ`}),(0,q.jsx)(`p`,{className:`text-slate-500 text-xs mt-1`,children:`Nạp số dư tài khoản nhà phát triển API`})]}),(0,q.jsx)(`div`,{className:`text-right`,children:(0,q.jsx)(`span`,{className:`text-amber-400 font-extrabold text-lg`,children:`100.000đ`})})]}),(0,q.jsxs)(`div`,{onClick:()=>u(`topup_200k`),className:`p-4 rounded-2xl cursor-pointer border-2 transition-all flex justify-between items-center ${l===`topup_200k`?`bg-brand-500/10 border-amber-400 shadow-md shadow-brand-500/5`:`bg-white/5 border-white/5 hover:bg-white/10`}`,children:[(0,q.jsxs)(`div`,{children:[(0,q.jsx)(`h4`,{className:`text-white font-bold text-sm flex items-center gap-2`,children:`Gói Nạp 200.000đ`}),(0,q.jsx)(`p`,{className:`text-slate-500 text-xs mt-1`,children:`Nạp số dư tài khoản nhà phát triển API`})]}),(0,q.jsx)(`div`,{className:`text-right`,children:(0,q.jsx)(`span`,{className:`text-amber-400 font-extrabold text-lg`,children:`200.000đ`})})]})]}),(0,q.jsx)(`button`,{onClick:async()=>{f(!0);try{m((await D.post(`/api/payment/create`,{plan:l})).data),a(`payment`),g(!0)}catch(e){alert(e.response?.data?.error||`Không khởi tạo được thanh toán.`)}finally{f(!1)}},disabled:d,className:`w-full py-3.5 bg-gradient-to-r from-brand-500 to-purple-600 hover:opacity-90 disabled:opacity-50 text-white font-bold rounded-xl shadow-lg shadow-brand-500/20 transition-all mt-4`,children:d?`Đang tạo mã thanh toán...`:`Tiến Hành Thanh Toán`})]}):p&&(0,q.jsxs)(`div`,{className:`flex flex-col items-center gap-4`,children:[(0,q.jsx)(`div`,{className:`bg-white p-3 rounded-2xl border-2 border-amber-400/30 shadow-xl`,children:(0,q.jsx)(`img`,{src:p.qr_url,alt:`QR VietQR`,className:`w-[190px] h-[190px] rounded-lg`})}),(0,q.jsxs)(`div`,{className:`w-full bg-white/5 border border-white/10 rounded-2xl p-4 text-xs space-y-3`,children:[(0,q.jsxs)(`div`,{className:`flex justify-between items-center border-b border-white/5 pb-2`,children:[(0,q.jsx)(`span`,{className:`text-slate-400`,children:`Ngân hàng`}),(0,q.jsx)(`strong`,{className:`text-white`,children:p.bank_info.bank})]}),(0,q.jsxs)(`div`,{className:`flex justify-between items-center border-b border-white/5 pb-2`,children:[(0,q.jsx)(`span`,{className:`text-slate-400`,children:`Số tài khoản`}),(0,q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,q.jsx)(`strong`,{className:`text-white font-mono`,children:p.bank_info.account_no}),(0,q.jsxs)(`button`,{onClick:()=>b(p.bank_info.account_no,`account`),className:`p-1 bg-white/10 hover:bg-white/20 rounded-md text-brand-300 text-[10px] flex items-center gap-1`,children:[(0,q.jsx)(v,{className:`w-3 h-3`}),` `,_.account?`Copied`:`Copy`]})]})]}),(0,q.jsxs)(`div`,{className:`flex justify-between items-center border-b border-white/5 pb-2`,children:[(0,q.jsx)(`span`,{className:`text-slate-400`,children:`Tên tài khoản`}),(0,q.jsx)(`strong`,{className:`text-white uppercase`,children:p.bank_info.account_name})]}),(0,q.jsxs)(`div`,{className:`flex justify-between items-center border-b border-white/5 pb-2`,children:[(0,q.jsx)(`span`,{className:`text-slate-400`,children:`Số tiền`}),(0,q.jsx)(`strong`,{className:`text-amber-400 font-bold text-sm`,children:p.amount_formatted})]}),(0,q.jsxs)(`div`,{className:`flex flex-col gap-2 pt-1`,children:[(0,q.jsxs)(`span`,{className:`text-slate-400`,children:[`Nội dung chuyển khoản `,(0,q.jsx)(`span`,{className:`text-red-500`,children:`*`})]}),(0,q.jsxs)(`div`,{className:`flex gap-2 w-full`,children:[(0,q.jsx)(`div`,{className:`flex-1 bg-black/60 border border-dashed border-amber-400/50 p-2.5 rounded-lg font-mono text-sm text-amber-400 font-bold text-center tracking-wider select-all`,children:p.order_id}),(0,q.jsxs)(`button`,{onClick:()=>b(p.order_id,`content`),className:`px-3 bg-brand-500/20 border border-brand-500/40 text-brand-300 font-semibold rounded-lg flex items-center gap-1 hover:bg-brand-500/35 transition-colors`,children:[(0,q.jsx)(v,{className:`w-3.5 h-3.5`}),` `,_.content?`Copied`:`Copy`]})]})]})]}),(0,q.jsxs)(`div`,{className:`flex items-center justify-center gap-2 text-cyan-400 text-[11px] animate-pulse`,children:[(0,q.jsx)(`span`,{className:`w-1.5 h-1.5 bg-cyan-400 rounded-full`}),(0,q.jsx)(`span`,{children:`Hệ thống đang kiểm tra giao dịch tự động...`})]}),(0,q.jsxs)(`div`,{className:`flex gap-2 w-full mt-2`,children:[(0,q.jsx)(`button`,{onClick:()=>{a(`plans`),g(!1)},className:`flex-1 py-3 border border-white/10 hover:border-white/20 text-slate-400 hover:text-white rounded-xl text-xs font-semibold transition-colors`,children:`Quay lại`}),(0,q.jsx)(`button`,{onClick:async()=>{if(p){f(!0);try{(await D.get(`/api/payment/status/${p.order_id}`)).data.status===`completed`?(g(!1),alert(`Thanh toán thành công! Tài khoản của bạn đã được cập nhật 👑`),await r(),t()):alert(`Hệ thống chưa nhận được thông tin chuyển khoản từ ngân hàng. Vui lòng đợi 1-3 phút để xử lý tự động.`)}catch{alert(`Lỗi kết nối máy chủ khi kiểm tra trạng thái.`)}finally{f(!1)}}},className:`flex-1 py-3 bg-gradient-to-r from-amber-400 to-amber-500 hover:brightness-105 text-[#0b0b14] font-bold rounded-xl shadow-lg transition-colors text-xs`,children:`Đã chuyển khoản`})]})]})]})}):null}function oe(){let{lang:e}=f(),[t,n]=(0,K.useState)([]),[r,i]=(0,K.useState)(0),[a,o]=(0,K.useState)(!0),[s,c]=(0,K.useState)(!0),l=(0,K.useRef)(null);(0,K.useEffect)(()=>(u(),()=>clearInterval(l.current)),[]);let u=async()=>{try{c(!0);let e=await D.get(`/api/system/notifications`);e.data&&e.data.length>0&&(n(e.data),d(e.data.length))}catch(e){console.error(`Failed to load system notifications`,e)}finally{c(!1)}},d=e=>{l.current&&clearInterval(l.current),l.current=setInterval(()=>{i(t=>(t+1)%e)},6e3)},p=()=>{t.length!==0&&(i(e=>(e+1)%t.length),d(t.length))},h=()=>{t.length!==0&&(i(e=>(e-1+t.length)%t.length),d(t.length))};if(!a||s||t.length===0)return null;let g=t[r],_=(t=>{switch(t){case`server`:return{bg:`bg-emerald-500/10 border-emerald-500/30 text-emerald-400`,icon:x,label:e===`vi`?`Hệ thống`:e===`en`?`System`:`系统`};case`promo`:return{bg:`bg-amber-500/10 border-amber-500/30 text-amber-400`,icon:te,label:e===`vi`?`Sự kiện`:e===`en`?`Event`:`活动`};case`update`:return{bg:`bg-purple-500/10 border-purple-500/30 text-purple-400`,icon:B,label:e===`vi`?`Cập nhật`:e===`en`?`Update`:`更新`};case`comment`:return{bg:`bg-pink-500/10 border-pink-500/30 text-pink-400`,icon:z,label:e===`vi`?`Bình luận`:e===`en`?`Comment`:`评论`};default:return{bg:`bg-blue-500/10 border-blue-500/30 text-blue-400`,icon:w,label:e===`vi`?`Thông báo`:e===`en`?`Notice`:`公告`}}})(g.type),v=_.icon;return(0,q.jsx)(`div`,{className:`bg-[#0f0f26]/80 border-b border-[#1f1f3a] backdrop-blur-md text-slate-300 relative z-30 transition-all duration-300 animate-fadeIn`,onMouseEnter:()=>clearInterval(l.current),onMouseLeave:()=>d(t.length),children:(0,q.jsxs)(`div`,{className:`max-w-[1400px] mx-auto px-4 sm:px-6 lg:px-12 py-2 flex items-center justify-between gap-4`,children:[(0,q.jsxs)(`div`,{className:`flex items-center gap-3 overflow-hidden min-w-0 flex-1`,children:[(0,q.jsxs)(`div`,{className:`relative flex items-center justify-center shrink-0`,children:[(0,q.jsx)(`span`,{className:`absolute inline-flex h-4 w-4 rounded-full bg-purple-500/20 animate-ping`}),(0,q.jsx)(w,{className:`w-4 h-4 text-purple-400 relative z-10`})]}),(0,q.jsxs)(`span`,{className:`hidden sm:inline-flex items-center gap-1 px-2.5 py-0.5 border rounded-full text-[10px] font-black tracking-wider uppercase shrink-0 ${_.bg}`,children:[(0,q.jsx)(v,{className:`w-3 h-3`}),_.label]}),(0,q.jsxs)(`div`,{className:`text-xs font-semibold truncate select-none text-slate-100 flex-1 pr-4 animate-slideIn`,children:[(0,q.jsxs)(`span`,{className:`text-purple-400 font-extrabold mr-1.5 sm:hidden`,children:[`[`,_.label,`]`]}),g.message,(0,q.jsxs)(`span`,{className:`text-[10px] text-slate-500 ml-2 italic shrink-0`,children:[`(`,g.time,`)`]})]})]}),(0,q.jsxs)(`div`,{className:`flex items-center gap-2 shrink-0`,children:[(0,q.jsxs)(`div`,{className:`flex items-center border border-white/5 bg-[#0b0b14]/40 rounded-lg p-0.5`,children:[(0,q.jsx)(`button`,{onClick:h,className:`p-1 hover:bg-white/5 text-slate-500 hover:text-white rounded transition-colors`,title:`Previous`,children:(0,q.jsx)(E,{className:`w-3.5 h-3.5`})}),(0,q.jsxs)(`span`,{className:`text-[10px] font-bold text-slate-600 px-1.5 select-none`,children:[r+1,`/`,t.length]}),(0,q.jsx)(`button`,{onClick:p,className:`p-1 hover:bg-white/5 text-slate-500 hover:text-white rounded transition-colors`,title:`Next`,children:(0,q.jsx)(m,{className:`w-3.5 h-3.5`})})]}),(0,q.jsx)(`button`,{onClick:()=>o(!1),className:`p-1 hover:bg-white/5 text-slate-500 hover:text-white rounded-lg transition-colors`,title:`Dismiss`,children:(0,q.jsx)(C,{className:`w-4 h-4`})})]})]})})}function se(){let[e,t]=(0,K.useState)(``),[n,r]=(0,K.useState)(``),[i,a]=(0,K.useState)(`idle`),[o,s]=(0,K.useState)(``);return(0,q.jsxs)(`footer`,{className:`mt-16 bg-[#0a0a16] border-t border-[#1f1f3a]/80 text-slate-400 py-10 px-4 sm:px-8 lg:px-16 relative overflow-hidden`,children:[(0,q.jsx)(`div`,{className:`absolute bottom-[-100px] left-[10%] w-[350px] h-[350px] rounded-full bg-purple-600/5 blur-[120px] pointer-events-none`}),(0,q.jsx)(`div`,{className:`absolute top-[-50px] right-[10%] w-[300px] h-[300px] rounded-full bg-cyan-600/5 blur-[100px] pointer-events-none`}),(0,q.jsxs)(`div`,{className:`max-w-[2200px] mx-auto grid grid-cols-1 md:grid-cols-12 gap-8 lg:gap-12 relative z-10`,children:[(0,q.jsxs)(`div`,{className:`md:col-span-3 space-y-3`,children:[(0,q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,q.jsx)(`div`,{className:`w-7 h-7 rounded-lg bg-gradient-to-br from-purple-500 to-indigo-600 flex items-center justify-center text-white shadow-md shadow-purple-500/10`,children:(0,q.jsx)(k,{className:`w-4 h-4`})}),(0,q.jsx)(`span`,{className:`text-white font-extrabold tracking-wide text-xs bg-clip-text bg-gradient-to-r from-purple-400 to-indigo-200`,children:`TRUYỆN DỊCH AI`})]}),(0,q.jsx)(`p`,{className:`text-[11px] text-slate-500 leading-relaxed`,children:`Hệ thống tối ưu hóa dịch thuật tiếng Trung bằng AI, tích hợp đọc truyện trực tuyến và đồng bộ hóa Chrome Extension.`}),(0,q.jsxs)(`div`,{className:`space-y-1.5 pt-1 text-[11px] text-slate-400`,children:[(0,q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,q.jsx)(R,{className:`w-3.5 h-3.5 text-purple-400`}),(0,q.jsxs)(`span`,{children:[`Liên hệ: `,(0,q.jsx)(`a`,{href:`mailto:havucong@lyvuha.com`,className:`text-purple-400 hover:underline`,children:`havucong@lyvuha.com`})]})]}),(0,q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,q.jsx)(z,{className:`w-3.5 h-3.5 text-cyan-400`}),(0,q.jsx)(`span`,{children:`Hỗ trợ kỹ thuật trực tuyến`})]})]})]}),(0,q.jsxs)(`div`,{className:`md:col-span-3 space-y-3`,children:[(0,q.jsx)(`h4`,{className:`text-white font-bold text-xs tracking-wider uppercase`,children:`Menu nhanh`}),(0,q.jsxs)(`ul`,{className:`grid grid-cols-2 gap-x-4 gap-y-2 text-[11px]`,children:[(0,q.jsx)(`li`,{children:(0,q.jsx)(`a`,{href:`/`,className:`hover:text-purple-400 transition-colors`,children:`Khám phá`})}),(0,q.jsx)(`li`,{children:(0,q.jsx)(`a`,{href:`/bookshelf`,className:`hover:text-purple-400 transition-colors`,children:`Tủ sách`})}),(0,q.jsx)(`li`,{children:(0,q.jsx)(`a`,{href:`/history`,className:`hover:text-purple-400 transition-colors`,children:`Lịch sử`})}),(0,q.jsx)(`li`,{children:(0,q.jsx)(`a`,{href:`/developer`,className:`hover:text-purple-400 transition-colors`,children:`API Dịch`})}),(0,q.jsx)(`li`,{children:(0,q.jsx)(`a`,{href:`/settings`,className:`hover:text-purple-400 transition-colors`,children:`Cài đặt`})})]})]}),(0,q.jsxs)(`div`,{className:`md:col-span-6 space-y-3`,children:[(0,q.jsxs)(`div`,{className:`flex items-center justify-between gap-4`,children:[(0,q.jsxs)(`h4`,{className:`text-white font-bold text-xs tracking-wider uppercase flex items-center gap-1.5`,children:[(0,q.jsx)(z,{className:`w-3.5 h-3.5 text-purple-400`}),` Gửi phản hồi & Báo lỗi`]}),(0,q.jsx)(`span`,{className:`text-[10px] text-slate-500 hidden sm:inline`,children:`Ý kiến của bạn giúp cải thiện chất lượng dịch AI`})]}),(0,q.jsxs)(`form`,{onSubmit:async i=>{if(i.preventDefault(),!e.trim()||!n.trim()){s(`Vui lòng điền đầy đủ email và nội dung phản hồi.`),a(`error`);return}a(`loading`),s(``);try{let i=await D.post(`/api/feedback/submit`,{email:e.trim(),message:n.trim()});i.data&&i.data.success?(a(`success`),t(``),r(``),setTimeout(()=>a(`idle`),4e3)):(s(i.data.error||`Có lỗi xảy ra khi gửi phản hồi.`),a(`error`))}catch(e){console.error(e),s(e.response?.data?.error||`Không thể kết nối tới máy chủ. Vui lòng thử lại sau.`),a(`error`)}},className:`grid grid-cols-1 sm:grid-cols-2 gap-3`,children:[(0,q.jsx)(`div`,{className:`flex flex-col`,children:(0,q.jsx)(`textarea`,{placeholder:`Nội dung phản hồi (báo lỗi dịch thuật, âm thanh TTS, yêu cầu truyện...)`,value:n,onChange:e=>r(e.target.value),className:`w-full h-full min-h-[90px] bg-[#111126] border border-[#1f1f3a] rounded-lg px-3 py-2 text-xs text-slate-200 placeholder-slate-500 focus:outline-none focus:border-purple-500/50 focus:ring-1 focus:ring-purple-500/20 transition-all resize-none`,disabled:i===`loading`,required:!0})}),(0,q.jsxs)(`div`,{className:`flex flex-col justify-between gap-2.5`,children:[(0,q.jsx)(`input`,{type:`email`,placeholder:`Email của bạn`,value:e,onChange:e=>t(e.target.value),className:`w-full bg-[#111126] border border-[#1f1f3a] rounded-lg px-3 py-2 text-xs text-slate-200 placeholder-slate-500 focus:outline-none focus:border-purple-500/50 focus:ring-1 focus:ring-purple-500/20 transition-all`,disabled:i===`loading`,required:!0}),(0,q.jsx)(`button`,{type:`submit`,disabled:i===`loading`,className:`w-full inline-flex items-center justify-center gap-2 bg-gradient-to-r from-purple-600 to-indigo-600 hover:from-purple-500 hover:to-indigo-500 text-white font-bold py-2 px-3 rounded-lg text-xs transition-all duration-300 shadow-lg shadow-purple-900/10 cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed`,children:i===`loading`?(0,q.jsxs)(q.Fragment,{children:[(0,q.jsxs)(`svg`,{className:`animate-spin -ml-1 mr-2 h-3 w-3 text-white`,fill:`none`,viewBox:`0 0 24 24`,children:[(0,q.jsx)(`circle`,{className:`opacity-25`,cx:`12`,cy:`12`,r:`10`,stroke:`currentColor`,strokeWidth:`4`}),(0,q.jsx)(`path`,{className:`opacity-75`,fill:`currentColor`,d:`M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z`})]}),`Đang gửi...`]}):(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(ne,{className:`w-3 h-3`}),` Gửi phản hồi`]})})]})]}),i===`success`&&(0,q.jsxs)(`div`,{className:`flex items-center gap-1.5 text-emerald-400 text-[11px] bg-emerald-500/5 border border-emerald-500/20 p-2 rounded-lg animate-fadeIn`,children:[(0,q.jsx)(j,{className:`w-3.5 h-3.5 shrink-0`}),(0,q.jsx)(`span`,{children:`Gửi phản hồi thành công! Cảm ơn sự đóng góp của bạn.`})]}),i===`error`&&(0,q.jsxs)(`div`,{className:`flex items-center gap-1.5 text-rose-400 text-[11px] bg-rose-500/5 border border-rose-500/20 p-2 rounded-lg animate-fadeIn`,children:[(0,q.jsx)(A,{className:`w-3.5 h-3.5 shrink-0`}),(0,q.jsx)(`span`,{children:o})]})]})]}),(0,q.jsxs)(`div`,{className:`max-w-[2200px] mx-auto mt-8 pt-5 border-t border-[#1f1f3a]/30 flex flex-col sm:flex-row items-center justify-between gap-4 text-[10px] text-slate-500`,children:[(0,q.jsx)(`div`,{className:`flex items-center gap-1`,children:(0,q.jsxs)(`span`,{children:[`© `,new Date().getFullYear(),` TruyenDichAI. Toàn bộ bản quyền được bảo lưu.`]})}),(0,q.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,q.jsx)(`span`,{children:`Được xây dựng với`}),(0,q.jsx)(P,{className:`w-3 h-3 text-rose-500 fill-rose-500 animate-pulse`}),(0,q.jsx)(`span`,{children:`bởi đội ngũ phát triển`})]})]})]})}function ce({isOpen:t,onClose:i,defaultTab:a}){let{user:o}=s(),{lang:c}=f(),[l,u]=(0,K.useState)(a||`friends`),[d,p]=(0,K.useState)([]),[m,h]=(0,K.useState)([]),[g,v]=(0,K.useState)(``),[y,b]=(0,K.useState)([]),[x,S]=(0,K.useState)(!1),[w,T]=(0,K.useState)(!1),[O,k]=(0,K.useState)(null),[A,j]=(0,K.useState)([]),[M,N]=(0,K.useState)(``),[te,P]=(0,K.useState)(!1),F=(0,K.useRef)(null),I=(0,K.useRef)(null),L=(0,K.useRef)(null);(0,K.useEffect)(()=>{t&&a&&(u(a),a!==`friends`&&k(null))},[t,a]),(0,K.useEffect)(()=>{if(o)return B(),R(),L.current=setInterval(()=>{document.hidden||B()},2e4),()=>{clearInterval(L.current)}},[o]),(0,K.useEffect)(()=>(O?(V(O.id),I.current=setInterval(()=>{document.hidden||V(O.id,!1)},5e3)):I.current&&clearInterval(I.current),()=>{I.current&&clearInterval(I.current)}),[O]),(0,K.useEffect)(()=>{F.current&&F.current.scrollIntoView({behavior:`smooth`,block:`nearest`})},[A]);let R=async()=>{try{let e=await D.get(`/api/friends/list`);e.data&&e.data.friends&&p(e.data.friends)}catch(e){console.error(`Failed to load friends`,e)}},B=async()=>{try{let e=await D.get(`/api/notifications/personal`);e.data&&e.data.notifications&&h(e.data.notifications)}catch(e){console.error(`Failed to load personal notifications`,e)}},V=async(e,t=!0)=>{try{t&&A.length===0&&T(!0);let n=await D.get(`/api/messages/chat/${e}`);n.data&&n.data.messages&&(j(n.data.messages),R())}catch(e){console.error(`Failed to fetch chat history`,e)}finally{T(!1)}},H=async()=>{if(g.trim()){S(!0);try{let e=await D.get(`/api/users/search?q=${encodeURIComponent(g)}`);e.data&&e.data.users&&b(e.data.users)}catch(e){console.error(`User search failed`,e)}finally{S(!1)}}},W=async e=>{try{let t=await D.post(`/api/friends/request`,{friend_username:e});t.data&&t.data.success&&(alert(c===`vi`?`Đã gửi lời mời kết bạn tới ${t.data.to_user||e}!`:`Friend request sent!`),v(``),b([]))}catch(e){alert(e.response?.data?.error||`Gửi lời mời thất bại`)}},J=async(e,t)=>{try{let n=await D.post(`/api/friends/respond`,{sender_id:e,action:t});n.data&&n.data.success&&(B(),R())}catch{alert(`Xử lý thất bại`)}},ie=async()=>{if(!(!M.trim()||!O)){P(!0);try{let e=await D.post(`/api/messages/send`,{receiver_id:O.id,message:M.trim()});if(e.data&&e.data.success){let t={id:e.data.msg_id,sender_id:o.id,receiver_id:O.id,message:M.trim(),created_at:new Date().toISOString()};j(e=>[...e,t]),N(``)}}catch(e){console.error(`Failed to send message`,e)}finally{P(!1)}}},ae=async e=>{try{await D.post(`/api/notifications/personal/read`,{notification_id:e}),B()}catch(e){console.error(`Failed to read notification`,e)}},oe=m.filter(e=>!e.is_read).length,se=d.reduce((e,t)=>e+(t.unread_messages||0),0);return t?(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(`div`,{onClick:i,className:`fixed inset-0 z-45 bg-black/60 backdrop-blur-sm`}),(0,q.jsxs)(`div`,{className:`fixed top-0 right-0 bottom-0 z-50 w-full sm:w-96 bg-[#0c0d1e]/95 border-l border-purple-500/20 backdrop-blur-xl flex flex-col text-slate-100 shadow-2xl animate-slideOver`,children:[(0,q.jsxs)(`div`,{className:`p-4 border-b border-purple-500/10 flex items-center justify-between bg-[#0e1026]/90`,children:[(0,q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,q.jsx)(G,{className:`w-5 h-5 text-brand-400`}),(0,q.jsx)(`h3`,{className:`font-extrabold text-sm tracking-wider uppercase bg-gradient-to-r from-brand-300 to-purple-400 bg-clip-text text-transparent`,children:c===`vi`?`Thư Hữu & Bạn bè`:`Book Friends`})]}),(0,q.jsx)(`button`,{onClick:i,className:`p-1.5 hover:bg-white/5 rounded-lg text-slate-400 hover:text-white transition-colors`,children:(0,q.jsx)(C,{className:`w-4 h-4`})})]}),!O&&(0,q.jsxs)(`div`,{className:`flex border-b border-purple-500/10 bg-[#0e1026]/50 p-1 text-[11px] font-bold gap-1 shrink-0`,children:[(0,q.jsxs)(`button`,{onClick:()=>u(`friends`),className:`flex-1 py-2 rounded-lg transition-all flex items-center justify-center gap-1.5 relative ${l===`friends`?`bg-purple-600/30 text-purple-300 border border-purple-500/30 shadow-md`:`text-slate-400 hover:text-white`}`,children:[(0,q.jsx)(G,{className:`w-3.5 h-3.5`}),(0,q.jsx)(`span`,{children:c===`vi`?`Bạn bè`:`Friends`}),se>0&&(0,q.jsx)(`span`,{className:`absolute -top-1 -right-1 min-w-[16px] h-4 bg-rose-500 text-white rounded-full flex items-center justify-center text-[8px] font-black px-0.5 shadow-md`,children:se})]}),(0,q.jsxs)(`button`,{onClick:()=>u(`search`),className:`flex-1 py-2 rounded-lg transition-all flex items-center justify-center gap-1.5 relative ${l===`search`?`bg-teal-600/30 text-teal-300 border border-teal-500/30 shadow-md`:`text-slate-400 hover:text-white`}`,children:[(0,q.jsx)(n,{className:`w-3.5 h-3.5`}),(0,q.jsx)(`span`,{children:c===`vi`?`Tìm bạn`:`Find`})]}),(0,q.jsxs)(`button`,{onClick:()=>u(`notifications`),className:`flex-1 py-2 rounded-lg transition-all flex items-center justify-center gap-1.5 relative ${l===`notifications`?`bg-amber-600/30 text-amber-300 border border-amber-500/30 shadow-md`:`text-slate-400 hover:text-white`}`,children:[(0,q.jsx)(ee,{className:`w-3.5 h-3.5`}),(0,q.jsx)(`span`,{children:c===`vi`?`Thông báo`:`Notif`}),oe>0&&(0,q.jsx)(`span`,{className:`absolute -top-1 -right-1 min-w-[16px] h-4 bg-amber-500 text-white rounded-full flex items-center justify-center text-[8px] font-black px-0.5 shadow-md animate-pulse`,children:oe})]})]}),(0,q.jsx)(`div`,{className:`flex-1 overflow-y-auto p-4 space-y-4`,children:O?(0,q.jsxs)(`div`,{className:`h-full flex flex-col`,children:[(0,q.jsxs)(`div`,{className:`flex items-center gap-2 border-b border-purple-500/10 pb-3 mb-3 shrink-0`,children:[(0,q.jsx)(`button`,{onClick:()=>k(null),className:`p-1 hover:bg-white/5 rounded-lg text-slate-400 hover:text-white transition-colors`,children:(0,q.jsx)(E,{className:`w-5 h-5`})}),(0,q.jsxs)(`div`,{className:`flex items-center gap-2 min-w-0`,children:[O.avatar?(0,q.jsx)(`img`,{src:O.avatar,className:`w-7 h-7 rounded-full object-cover shrink-0`,alt:`avatar`}):(0,q.jsx)(`div`,{className:`w-7 h-7 rounded-full bg-gradient-to-br from-brand-500 to-purple-600 flex items-center justify-center font-black text-[10px] text-white shrink-0`,children:O.username[0].toUpperCase()}),(0,q.jsxs)(`div`,{className:`min-w-0`,children:[(0,q.jsx)(`h4`,{className:`font-extrabold text-xs text-slate-200`,children:O.username}),(0,q.jsx)(`p`,{className:`text-[9px] text-slate-500`,children:`Đang trò chuyện`})]})]})]}),(0,q.jsxs)(`div`,{className:`flex-1 overflow-y-auto space-y-2 pr-1 mb-4 select-text`,children:[w?(0,q.jsx)(`div`,{className:`flex items-center justify-center h-full`,children:(0,q.jsx)(_,{className:`w-6 h-6 animate-spin text-purple-500`})}):A.length===0?(0,q.jsx)(`div`,{className:`text-center py-20 text-xs text-slate-600`,children:`Chưa có tin nhắn nào. Hãy gửi lời chào!`}):A.map((t,n)=>{let r=t.sender_id===o.id,a=t.message.includes(`[Chia sẻ truyện]`);return(0,q.jsx)(`div`,{className:`flex ${r?`justify-end`:`justify-start`}`,children:(0,q.jsxs)(`div`,{className:`max-w-[85%] rounded-xl px-3 py-2 text-xs leading-relaxed border ${r?`bg-purple-600/20 border-purple-500/30 text-purple-200 rounded-tr-none`:`bg-slate-900/50 border-slate-800 text-slate-300 rounded-tl-none`}`,children:[a?(0,q.jsxs)(`div`,{className:`space-y-1`,children:[(0,q.jsxs)(`span`,{className:`text-[10px] font-extrabold uppercase text-amber-400 tracking-wider flex items-center gap-1`,children:[(0,q.jsx)(re,{className:`w-3 h-3`}),c===`vi`?`Được chia sẻ`:`Shared novel`]}),(0,q.jsx)(`p`,{className:`font-medium text-slate-100`,children:t.message.split(` - `)[0]}),t.message.includes(`Xem chi tiết tại`)&&(0,q.jsxs)(`a`,{href:t.message.split(`Xem chi tiết tại `)[1],onClick:e=>{e.preventDefault(),window.location.href=t.message.split(`Xem chi tiết tại `)[1],i()},className:`inline-flex items-center gap-1 mt-1 text-[10px] text-brand-400 font-extrabold hover:underline`,children:[c===`vi`?`Xem chi tiết`:`View detail`,(0,q.jsx)(e,{className:`w-2.5 h-2.5`})]})]}):t.message,(0,q.jsx)(`span`,{className:`block text-[8px] text-slate-500 text-right mt-1`,children:new Date(t.created_at).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`})})]})},t.id||n)}),(0,q.jsx)(`div`,{ref:F})]}),(0,q.jsxs)(`div`,{className:`flex gap-2 border-t border-purple-500/10 pt-3 shrink-0`,children:[(0,q.jsx)(`input`,{type:`text`,placeholder:`Nhập tin nhắn...`,value:M,onChange:e=>N(e.target.value),onKeyDown:e=>e.key===`Enter`&&ie(),className:`flex-1 px-3 py-2 bg-[#080814] border border-purple-500/20 rounded-xl text-xs text-white outline-none focus:border-purple-500 transition-colors`}),(0,q.jsx)(`button`,{onClick:ie,disabled:te||!M.trim(),className:`p-2 bg-purple-600 hover:bg-purple-500 text-white rounded-xl transition-all disabled:opacity-40`,children:(0,q.jsx)(ne,{className:`w-4 h-4`})})]})]}):(0,q.jsxs)(q.Fragment,{children:[l===`friends`&&(0,q.jsxs)(`div`,{className:`space-y-3`,children:[(0,q.jsxs)(`h4`,{className:`text-[10px] font-black uppercase tracking-wider text-purple-400`,children:[c===`vi`?`Danh sách bạn bè`:`Friends list`,` (`,d.length,`)`]}),d.length===0?(0,q.jsx)(`div`,{className:`text-center py-16 border border-dashed border-purple-500/10 rounded-2xl text-xs text-slate-500 bg-purple-950/5`,children:c===`vi`?`Chưa có bạn bè nào. Hãy sang tab "Tìm bạn" để kết nối!`:`No friends yet. Go to "Find" tab to search!`}):(0,q.jsx)(`div`,{className:`grid gap-2.5`,children:d.map(e=>(0,q.jsxs)(`div`,{onClick:()=>k(e),className:`flex items-center justify-between p-3 bg-gradient-to-r from-purple-950/10 to-indigo-950/10 hover:from-purple-900/25 hover:to-indigo-900/25 border border-purple-500/15 hover:border-purple-500/40 rounded-2xl cursor-pointer transition-all hover:scale-[1.01] shadow-md gap-3`,children:[(0,q.jsxs)(`div`,{className:`flex items-center gap-3 min-w-0`,children:[e.avatar?(0,q.jsx)(`img`,{src:e.avatar,className:`w-9 h-9 rounded-full object-cover shrink-0 ring-2 ring-purple-500/20`,alt:`avatar`}):(0,q.jsx)(`div`,{className:`w-9 h-9 rounded-full bg-gradient-to-br from-[#7c3aed] to-[#4f46e5] flex items-center justify-center font-black text-xs text-white shrink-0 shadow-inner`,children:e.username[0].toUpperCase()}),(0,q.jsxs)(`div`,{className:`min-w-0`,children:[(0,q.jsx)(`span`,{className:`text-xs font-bold text-slate-200 block truncate`,children:e.username}),e.user_code&&(0,q.jsxs)(`span`,{className:`text-[9px] text-purple-400/70 font-mono block mt-0.5`,children:[`#`,e.user_code]})]})]}),(0,q.jsxs)(`div`,{className:`flex items-center gap-2 shrink-0`,children:[e.unread_messages>0&&(0,q.jsx)(`span`,{className:`px-2 py-0.5 bg-rose-500 text-white rounded-full text-[9px] font-black min-w-[18px] text-center animate-pulse shadow-md`,children:e.unread_messages}),(0,q.jsx)(`div`,{className:`p-1.5 bg-purple-500/10 hover:bg-purple-500/20 rounded-lg text-purple-400 transition-colors`,children:(0,q.jsx)(z,{className:`w-3.5 h-3.5`})})]})]},e.id))})]}),l===`search`&&(0,q.jsxs)(`div`,{className:`space-y-4`,children:[(0,q.jsx)(`h4`,{className:`text-[10px] font-black uppercase tracking-wider text-teal-400`,children:c===`vi`?`Tìm bạn hữu mới`:`Find new friends`}),(0,q.jsxs)(`div`,{className:`space-y-2`,children:[(0,q.jsxs)(`div`,{className:`relative`,children:[(0,q.jsx)(n,{className:`absolute left-3.5 top-1/2 -translate-y-1/2 w-4 h-4 text-teal-500/70`}),(0,q.jsx)(`input`,{type:`text`,placeholder:c===`vi`?`Tìm theo tên, email, mã ID 7 số...`:`Search by name, email, 7-digit ID...`,value:g,onChange:e=>v(e.target.value),onKeyDown:e=>e.key===`Enter`&&H(),className:`w-full pl-10 pr-8 py-2.5 bg-[#070b13] border border-teal-500/20 focus:border-teal-500 rounded-xl text-white outline-none transition-colors text-xs placeholder-slate-500`}),g&&(0,q.jsx)(`button`,{onClick:()=>{v(``),b([])},className:`absolute right-3 top-1/2 -translate-y-1/2 text-slate-500 hover:text-white`,children:(0,q.jsx)(C,{className:`w-3.5 h-3.5`})})]}),(0,q.jsx)(`p`,{className:`text-[9px] text-teal-500/60 px-1 leading-normal`,children:c===`vi`?`ℹ️ Có thể tìm bằng tên đăng nhập, email hoặc mã ID 7 chữ số (ví dụ: 1234567)`:`ℹ️ Search by username, email, or 7-digit ID (e.g. 1234567)`})]}),y.length>0&&(0,q.jsxs)(`div`,{className:`bg-[#070b13]/90 border border-teal-500/20 rounded-xl p-2.5 space-y-1.5 shadow-lg`,children:[(0,q.jsxs)(`span`,{className:`text-[9px] font-black text-teal-400/80 uppercase px-2`,children:[c===`vi`?`Kết quả tìm kiếm`:`Search results`,` (`,y.length,`)`]}),y.map(e=>(0,q.jsxs)(`div`,{className:`flex items-center justify-between p-2 hover:bg-teal-950/20 rounded-xl gap-3 border border-transparent hover:border-teal-500/10 transition-all`,children:[(0,q.jsxs)(`div`,{className:`flex items-center gap-2.5 min-w-0`,children:[e.avatar?(0,q.jsx)(`img`,{src:e.avatar,className:`w-8 h-8 rounded-full object-cover shrink-0 ring-2 ring-teal-500/10`,alt:`avatar`}):(0,q.jsx)(`div`,{className:`w-8 h-8 rounded-full bg-gradient-to-br from-teal-500 to-emerald-600 flex items-center justify-center font-black text-xs text-white shrink-0 shadow-sm`,children:e.username?e.username[0].toUpperCase():`U`}),(0,q.jsxs)(`div`,{className:`min-w-0`,children:[(0,q.jsx)(`p`,{className:`text-xs font-bold text-slate-200 truncate`,children:e.username}),e.user_code&&(0,q.jsxs)(`p`,{className:`text-[9px] text-teal-500/70 font-mono mt-0.5`,children:[`# `,e.user_code]})]})]}),(0,q.jsx)(`button`,{onClick:()=>W(e.username),className:`shrink-0 p-2 hover:bg-teal-600 bg-teal-600/10 text-teal-300 hover:text-white rounded-xl border border-teal-500/20 transition-all`,title:c===`vi`?`Kết bạn`:`Add Friend`,children:(0,q.jsx)(U,{className:`w-3.5 h-3.5`})})]},e.id))]}),g&&y.length===0&&!x&&(0,q.jsx)(`div`,{className:`text-center py-8 text-xs text-slate-500 border border-dashed border-teal-500/10 rounded-xl bg-teal-950/5`,children:`Không tìm thấy kết quả phù hợp.`})]}),l===`notifications`&&(0,q.jsxs)(`div`,{className:`space-y-3`,children:[(0,q.jsx)(`h4`,{className:`text-[10px] font-extrabold uppercase tracking-wider text-purple-400`,children:`Yêu cầu & Hoạt động`}),m.length===0?(0,q.jsx)(`div`,{className:`text-center py-12 border border-dashed border-purple-500/10 rounded-2xl text-xs text-slate-500`,children:`Không có thông báo mới.`}):m.map(t=>(0,q.jsxs)(`div`,{className:`p-3 border rounded-xl space-y-2 transition-all ${t.is_read?`bg-[#080814]/40 border-purple-500/5 text-slate-400`:`bg-purple-950/10 border-purple-500/30 text-slate-200 shadow-lg shadow-purple-950/10`}`,children:[(0,q.jsxs)(`div`,{className:`flex justify-between items-start gap-2`,children:[(0,q.jsx)(`p`,{className:`text-xs leading-relaxed`,children:t.message}),!t.is_read&&(0,q.jsx)(`button`,{onClick:()=>ae(t.id),className:`text-[9px] text-purple-400 hover:text-purple-300 underline shrink-0`,children:`Đã đọc`})]}),t.type===`friend_request`&&!t.is_read&&(0,q.jsxs)(`div`,{className:`flex items-center gap-2 pt-1`,children:[(0,q.jsxs)(`button`,{onClick:()=>J(t.sender_id,`accept`),className:`inline-flex items-center gap-1 px-3 py-1 bg-purple-600 hover:bg-purple-500 text-white rounded-lg text-[10px] font-bold transition-colors`,children:[(0,q.jsx)(r,{className:`w-3 h-3`}),` Đồng ý`]}),(0,q.jsxs)(`button`,{onClick:()=>J(t.sender_id,`reject`),className:`inline-flex items-center gap-1 px-3 py-1 bg-[#121225] border border-[#1f1f3a] text-slate-300 hover:bg-slate-800 rounded-lg text-[10px] font-bold transition-colors`,children:[(0,q.jsx)(C,{className:`w-3 h-3`}),` Từ chối`]})]}),t.type===`book_share`&&(0,q.jsxs)(`a`,{href:`/book/${t.related_id}`,onClick:e=>{e.preventDefault(),window.location.href=`/book/${t.related_id}`,i()},className:`inline-flex items-center gap-1 text-[10px] text-brand-400 font-extrabold hover:underline pt-1`,children:[`Đọc truyện ngay`,(0,q.jsx)(e,{className:`w-2.5 h-2.5`})]}),(0,q.jsx)(`span`,{className:`block text-[8px] text-slate-500 italic`,children:new Date(t.created_at).toLocaleString()})]},t.id))]})]})})]})]}):null}var le=`1.0.25`;function Y(e=`0.0.0`){return(e||`0.0.0`).replace(/^v/,``).split(`.`).map(Number)}function ue(e,t){let[n,r,i]=Y(e),[a,o,s]=Y(t);return n>a||n===a&&r>o||n===a&&r===o&&i>s}function de(){let[e,t]=(0,K.useState)(null),[n,r]=(0,K.useState)(!1),[i,a]=(0,K.useState)(!1),o=typeof window<`u`&&!!window.electron,s=(0,K.useCallback)(async()=>{let e=`update_checked_${new Date().toDateString()}`;if(!sessionStorage.getItem(e)){r(!0);try{if(o&&window.electron?.checkForUpdate){let e=await window.electron.checkForUpdate();e?.success&&e.hasUpdate&&t(e)}else{let e=await D.get(`/api/releases`);if(!e.data?.success||!e.data?.releases)return;let n=e.data.releases,r=n.desktop_linux||n.desktop_windows;if(!r)return;let i=r.version,a=le;ue(i,a)&&t({hasUpdate:!0,currentVersion:a,latestVersion:i,downloadUrl:null,patchUrl:null,releaseNotes:r.release_notes,platform:`web`})}}catch(e){console.warn(`[AutoUpdate] Check skipped:`,e.message)}finally{r(!1),sessionStorage.setItem(e,`1`)}}},[o]);(0,K.useEffect)(()=>{let e=setTimeout(s,3e3);return()=>clearTimeout(e)},[s]);let c=(0,K.useCallback)(()=>{a(!0),e&&sessionStorage.setItem(`dismissed_v${e.latestVersion}`,`1`)},[e]),l=(0,K.useCallback)(async t=>{if(e)if(o){let{patchUrl:n,downloadUrl:r,latestVersion:i}=e;if(n&&window.electron?.quickPatchUpdate){if(console.log(`[AutoUpdate] Using Quick Patch:`,n),t){let e=window.electron.onUpdateDownloadProgress(t),r=await window.electron.quickPatchUpdate(n,i);return e(),r}return window.electron.quickPatchUpdate(n,i)}if(r&&window.electron?.downloadAndRunUpdate){let e=r?.includes(`windows`)||r?.includes(`win`)?`TienHiepAI-Setup-${i}.exe`:`TienHiepAI-${i}.AppImage`;if(console.log(`[AutoUpdate] Using Full Update:`,r),t){let n=window.electron.onUpdateDownloadProgress(t),i=await window.electron.downloadAndRunUpdate(r,e);return n(),i}return window.electron.downloadAndRunUpdate(r,e)}}else window.location.href=`/downloads`},[e,o]),u=e?!!sessionStorage.getItem(`dismissed_v${e.latestVersion}`):!1;return{updateInfo:i||u?null:e,checking:n,dismissUpdate:c,startUpdate:l}}var fe=({langCode:e})=>e===`vi`?(0,q.jsxs)(`svg`,{className:`w-4 h-3 rounded-sm inline-block object-cover shadow-sm mr-1 shrink-0`,viewBox:`0 0 30 20`,fill:`none`,xmlns:`http://www.w3.org/2000/svg`,children:[(0,q.jsx)(`rect`,{width:`30`,height:`20`,fill:`#da251d`}),(0,q.jsx)(`polygon`,{points:`15,4 16.2,8.5 20.7,8.5 17.1,11.2 18.3,15.7 15,13 11.7,15.7 12.9,11.2 9.3,8.5 13.8,8.5`,fill:`#ffff00`})]}):e===`en`?(0,q.jsxs)(`svg`,{className:`w-4 h-3 rounded-sm inline-block object-cover shadow-sm mr-1 shrink-0`,viewBox:`0 0 30 20`,fill:`none`,xmlns:`http://www.w3.org/2000/svg`,children:[(0,q.jsx)(`rect`,{width:`30`,height:`20`,fill:`#b22234`}),(0,q.jsx)(`rect`,{y:`1.54`,width:`30`,height:`1.54`,fill:`#ffffff`}),(0,q.jsx)(`rect`,{y:`4.62`,width:`30`,height:`1.54`,fill:`#ffffff`}),(0,q.jsx)(`rect`,{y:`7.7`,width:`30`,height:`1.54`,fill:`#ffffff`}),(0,q.jsx)(`rect`,{y:`10.78`,width:`30`,height:`1.54`,fill:`#ffffff`}),(0,q.jsx)(`rect`,{y:`13.86`,width:`30`,height:`1.54`,fill:`#ffffff`}),(0,q.jsx)(`rect`,{y:`16.94`,width:`30`,height:`1.54`,fill:`#ffffff`}),(0,q.jsx)(`rect`,{width:`13`,height:`10.8`,fill:`#3c3b6e`}),(0,q.jsx)(`circle`,{cx:`2.5`,cy:`2.5`,r:`0.6`,fill:`#ffffff`}),(0,q.jsx)(`circle`,{cx:`6.5`,cy:`2.5`,r:`0.6`,fill:`#ffffff`}),(0,q.jsx)(`circle`,{cx:`10.5`,cy:`2.5`,r:`0.6`,fill:`#ffffff`}),(0,q.jsx)(`circle`,{cx:`4.5`,cy:`5.5`,r:`0.6`,fill:`#ffffff`}),(0,q.jsx)(`circle`,{cx:`8.5`,cy:`5.5`,r:`0.6`,fill:`#ffffff`}),(0,q.jsx)(`circle`,{cx:`2.5`,cy:`8.5`,r:`0.6`,fill:`#ffffff`}),(0,q.jsx)(`circle`,{cx:`6.5`,cy:`8.5`,r:`0.6`,fill:`#ffffff`}),(0,q.jsx)(`circle`,{cx:`10.5`,cy:`8.5`,r:`0.6`,fill:`#ffffff`})]}):e===`zh`?(0,q.jsxs)(`svg`,{className:`w-4 h-3 rounded-sm inline-block object-cover shadow-sm mr-1 shrink-0`,viewBox:`0 0 30 20`,fill:`none`,xmlns:`http://www.w3.org/2000/svg`,children:[(0,q.jsx)(`rect`,{width:`30`,height:`20`,fill:`#de2110`}),(0,q.jsx)(`polygon`,{points:`5,5 6.2,9 9.8,7.8 7.3,11 8.5,15 5.5,12.5 2.5,15 3.7,11 1.2,7.8 4.8,9`,fill:`#ffde00`})]}):null;function pe({children:e,hideHeader:n=!1,stats:r={total:931427,duplicates:0}}){let{user:o,logout:u}=s(),{lang:d,setLang:p,t:m}=f(),h=c(),_=l(),v=typeof window<`u`&&!!window.electron,{tabs:b,isVisible:x,setIsVisible:w}=T()||{tabs:[]},{updateInfo:E,dismissUpdate:A,startUpdate:j}=de(),[te,P]=(0,K.useState)(0),[F,I]=(0,K.useState)(!1),[R,B]=(0,K.useState)(``),ne=async()=>{if(E){if(!v){h(`/downloads`);return}I(!0),P(0),B(d===`vi`?`Đang kết nối...`:`Connecting...`);try{let e=await j(e=>{e?.percent!=null&&(P(e.percent),B(d===`vi`?`Đang tải ${e.percent}% (${(e.downloadedBytes/1024/1024).toFixed(1)}MB / ${(e.totalBytes/1024/1024).toFixed(1)}MB)`:`Downloading ${e.percent}% (${(e.downloadedBytes/1024/1024).toFixed(1)}MB / ${(e.totalBytes/1024/1024).toFixed(1)}MB)`))});e&&e.success===!1?(I(!1),alert(d===`vi`?`Lỗi cập nhật: ${e.error}`:`Update error: ${e.error}`)):B(d===`vi`?`✅ Hoàn tất! Đang khởi chạy...`:`✅ Complete! Launching...`)}catch(e){I(!1),alert(`Update error: `+e.message)}}},[re,U]=(0,K.useState)(!1),[W,G]=(0,K.useState)(!1),[le,Y]=(0,K.useState)(!1),[ue,pe]=(0,K.useState)(!1),[he,ge]=(0,K.useState)(`friends`),[X,_e]=(0,K.useState)(0),[Z,ve]=(0,K.useState)(0),[ye,be]=(0,K.useState)(!1),[xe,Se]=(0,K.useState)(!1),[Ce,we]=(0,K.useState)(!1);(0,K.useEffect)(()=>{if(!v)return;window.electron.isMaximized().then(be);let e=window.electron.onWindowStateChange(be);window.electron.checkBackendStatus&&window.electron.checkBackendStatus().then(e=>{e&&e.error===`missing_engine`&&we(!0)});let t=window.electron.onBackendReady(({ready:e,error:t})=>{!e&&t===`missing_engine`?we(!0):e&&we(!1)});return()=>{e(),t&&t()}},[v]),(0,K.useEffect)(()=>{let e=()=>Se(e=>!e);return window.addEventListener(`toggle-log-console`,e),()=>window.removeEventListener(`toggle-log-console`,e)},[]),(0,K.useEffect)(()=>{if(!o){_e(0),ve(0);return}let e=async()=>{try{let e=await D.get(`/api/notifications/unread-counts`);e.data&&(_e(e.data.messages||0),ve(e.data.notifications||0))}catch{try{let e=await D.get(`/api/notifications/personal`);if(e.data&&e.data.notifications){let t=e.data.notifications.filter(e=>!e.is_read).length;ve(t)}}catch{}}};e();let t=setInterval(()=>{document.hidden||e()},2e4);return()=>clearInterval(t)},[o]);let Te=()=>_.pathname===`/`?`all`:_.pathname===`/bookshelf`?`bookshelf`:_.pathname===`/history`?`history`:_.pathname===`/developer`?`developer`:_.pathname===`/downloads`?`downloads`:_.pathname===`/embed`?`embed`:_.pathname===`/settings`?`settings`:_.pathname===`/sects`?`sects`:`all`,Q=e=>{if(Y(!1),e===`browser`){w&&w(!0);return}w&&w(!1),e===`all`&&h(`/`),e===`bookshelf`&&h(`/bookshelf`),e===`history`&&h(`/history`),e===`developer`&&h(`/developer`),e===`downloads`&&h(`/downloads`),e===`embed`&&h(`/embed`),e===`settings`&&h(`/settings`),e===`sects`&&h(`/sects`)},$=x?`browser`:Te(),Ee=[...b&&b.length>0?[{key:`browser`,icon:y,label:d===`vi`?`Trình duyệt`:`Browser`}]:[],{key:`all`,icon:M,label:m.tabDiscover},{key:`bookshelf`,icon:O,label:m.tabBookshelf},{key:`history`,icon:S,label:m.tabHistory},{key:`embed`,icon:k,label:m.tabEmbed},{key:`settings`,icon:g,label:m.tabSettings}],De=o&&[`admin`,`havucong25`,`congkx123789`].includes(o.username),Oe=[...b&&b.length>0?[{key:`browser`,icon:y,label:d===`vi`?`Trình duyệt`:`Browser`}]:[],{key:`all`,icon:M,label:m.tabDiscover},{key:`bookshelf`,icon:O,label:m.tabBookshelf},{key:`history`,icon:S,label:m.tabHistory},...De?[{key:`developer`,icon:H,label:m.tabDeveloper}]:[],{key:`downloads`,icon:J,label:m.tabDownloads},{key:`embed`,icon:k,label:m.tabEmbed},...o?[{key:`sects`,icon:N,label:d===`vi`?`Tông Môn`:`Sects`},{key:`settings`,icon:g,label:m.tabSettings}]:[]];return(0,q.jsxs)(`div`,{className:`min-h-screen min-h-[100dvh] flex flex-col bg-[#0b0b14] text-slate-100`,children:[!n&&(0,q.jsxs)(`header`,{className:`relative bg-[#1c183a] border-b border-indigo-950/30 shadow-lg sticky top-0 z-40 ${v?`select-none`:``}`,style:v?{WebkitAppRegion:`drag`}:{},children:[(0,q.jsxs)(`div`,{className:`max-w-[2200px] mx-auto px-4 sm:px-6 lg:px-12 h-14 flex items-center justify-between gap-3`,style:{paddingRight:v?`144px`:void 0},children:[(0,q.jsxs)(`button`,{onClick:()=>h(`/`),className:`flex items-center gap-2 shrink-0 hover:opacity-90 active:scale-95 transition-all`,style:v?{WebkitAppRegion:`no-drag`}:{},children:[(0,q.jsx)(`img`,{src:`/favicon.png`,className:`w-9 h-9 object-contain rounded-lg shadow-md border border-white/10`,alt:`Tiên Hiệp AI Logo`}),(0,q.jsx)(`span`,{className:`text-lg font-extrabold text-white leading-tight tracking-wider hidden lg:inline`,children:m.title})]}),(0,q.jsx)(`nav`,{className:`hidden sm:flex bg-[#0f0f26]/60 rounded-full p-1 border border-white/5 text-[11px] font-bold gap-0.5`,style:v?{WebkitAppRegion:`no-drag`}:{},children:Oe.map(({key:e,icon:t,label:n})=>(0,q.jsxs)(`button`,{onClick:()=>Q(e),title:n,className:`flex items-center whitespace-nowrap shrink-0 gap-1 px-2 py-1 lg:gap-1.5 lg:px-3.5 lg:py-1.5 rounded-full transition-all relative ${$===e?`bg-purple-600 text-white shadow-md`:`text-slate-400 hover:text-white`}`,children:[(0,q.jsx)(t,{className:`w-3.5 h-3.5`}),(0,q.jsx)(`span`,{className:`hidden 2xl:inline`,children:n}),e===`settings`&&o?.require_password_change===1&&(0,q.jsxs)(`span`,{className:`absolute top-1 right-1 flex h-2 w-2`,children:[(0,q.jsx)(`span`,{className:`animate-ping absolute inline-flex h-full w-full rounded-full bg-amber-400 opacity-75`}),(0,q.jsx)(`span`,{className:`relative inline-flex rounded-full h-2 w-2 bg-amber-500`})]})]},e))}),(0,q.jsxs)(`div`,{className:`flex items-center gap-2 shrink-0`,style:v?{WebkitAppRegion:`no-drag`}:{},children:[(0,q.jsx)(`div`,{className:`hidden sm:flex bg-[#0f0f26]/60 rounded-full p-0.5 border border-white/5 text-[9px] font-bold`,children:[`vi`,`en`,`zh`].map(e=>(0,q.jsxs)(`button`,{onClick:()=>p(e),title:e.toUpperCase(),className:`flex items-center gap-1 px-2 py-1 rounded-full transition-all ${d===e?`bg-purple-600 text-white`:`text-slate-400 hover:text-white`}`,children:[(0,q.jsx)(fe,{langCode:e}),(0,q.jsx)(`span`,{className:`hidden 2xl:inline`,children:e.toUpperCase()})]},e))}),o?(0,q.jsxs)(`div`,{className:`hidden sm:flex items-center gap-2`,children:[v&&(0,q.jsx)(`button`,{onClick:()=>Se(e=>!e),className:`p-1.5 hover:bg-white/5 rounded-lg transition-colors relative ${xe?`text-purple-400 bg-purple-600/10`:`text-slate-400 hover:text-white`}`,title:`Xem Nhật Ký Log`,children:(0,q.jsx)(H,{className:`w-4 h-4`})}),(0,q.jsxs)(`button`,{onClick:()=>h(`/messages`),className:`p-1.5 hover:bg-white/5 rounded-lg text-slate-400 hover:text-white transition-colors relative`,title:`Tin nhắn riêng`,children:[(0,q.jsx)(z,{className:`w-4 h-4`}),X>0&&(0,q.jsx)(`span`,{className:`absolute -top-1 -right-1 min-w-[16px] h-4 bg-rose-500 text-white rounded-full flex items-center justify-center text-[9px] font-black px-0.5 shadow-md`,children:X>99?`99+`:X})]}),(0,q.jsxs)(`button`,{onClick:()=>{ge(`notifications`),pe(!0)},className:`p-1.5 hover:bg-white/5 rounded-lg text-slate-400 hover:text-white transition-colors relative`,title:`Thông báo thư hữu`,children:[(0,q.jsx)(ee,{className:`w-4 h-4`}),Z>0&&(0,q.jsx)(`span`,{className:`absolute -top-1 -right-1 min-w-[16px] h-4 bg-amber-500 text-white rounded-full flex items-center justify-center text-[9px] font-black px-0.5 shadow-md animate-pulse`,children:Z>99?`99+`:Z})]}),(0,q.jsxs)(`button`,{onClick:()=>h(`/settings`),title:o.display_name||o.username,className:`text-slate-200 text-xs font-bold hover:text-purple-400 transition-colors flex items-center gap-1.5 bg-[#0f0f26]/40 p-1 2xl:px-2.5 2xl:py-1 rounded-full border border-white/5 hover:border-purple-500/30 transition-all shrink-0`,children:[o.avatar?(0,q.jsx)(`img`,{src:o.avatar,className:`w-5 h-5 rounded-full object-cover shrink-0`,alt:`avatar`}):(0,q.jsx)(`span`,{className:`w-5 h-5 rounded-full bg-purple-600/50 flex items-center justify-center text-[9px] font-black shrink-0 text-white`,children:o.username?o.username[0].toUpperCase():`U`}),(0,q.jsx)(`span`,{className:`hidden 2xl:inline truncate max-w-[90px]`,children:o.display_name||o.username}),o.require_password_change===1&&(0,q.jsx)(`span`,{className:`w-1.5 h-1.5 rounded-full bg-amber-500 animate-pulse shrink-0`})]}),(0,q.jsx)(`button`,{onClick:u,className:`p-1.5 hover:bg-white/5 rounded-lg text-slate-400 hover:text-white transition-colors`,children:(0,q.jsx)(L,{className:`w-4 h-4`})})]}):(0,q.jsx)(`button`,{onClick:()=>U(!0),className:`hidden sm:block bg-purple-600 hover:bg-purple-500 text-white px-3 py-1.5 rounded-full text-xs font-bold shadow-md transition-all`,children:m.login}),(0,q.jsxs)(`div`,{className:`flex sm:hidden items-center gap-1.5 mr-1`,style:v?{WebkitAppRegion:`no-drag`}:{},children:[(0,q.jsx)(`button`,{onClick:()=>Q(`bookshelf`),className:`p-1.5 rounded-lg transition-colors ${$===`bookshelf`?`text-purple-400 bg-purple-600/10`:`text-slate-400 hover:text-white`}`,title:m.tabBookshelf,children:(0,q.jsx)(O,{className:`w-4.5 h-4.5`})}),(0,q.jsx)(`button`,{onClick:()=>Q(`history`),className:`p-1.5 rounded-lg transition-colors ${$===`history`?`text-purple-400 bg-purple-600/10`:`text-slate-400 hover:text-white`}`,title:m.tabHistory,children:(0,q.jsx)(S,{className:`w-4.5 h-4.5`})}),(0,q.jsx)(`button`,{onClick:()=>Q(`settings`),className:`p-1.5 rounded-lg transition-colors ${$===`settings`?`text-purple-400 bg-purple-600/10`:`text-slate-400 hover:text-white`}`,title:m.tabSettings,children:(0,q.jsx)(g,{className:`w-4.5 h-4.5`})})]}),(0,q.jsx)(`button`,{onClick:()=>Y(e=>!e),className:`sm:hidden p-2 rounded-xl hover:bg-white/5 text-slate-400 hover:text-white transition-colors`,style:v?{WebkitAppRegion:`no-drag`}:{},children:le?(0,q.jsx)(C,{className:`w-5 h-5`}):(0,q.jsx)(t,{className:`w-5 h-5`})})]})]}),v&&(0,q.jsxs)(`div`,{className:`absolute right-0 top-0 bottom-0 flex items-stretch h-14`,style:{WebkitAppRegion:`no-drag`},children:[(0,q.jsx)(`button`,{onClick:()=>window.electron.minimize(),className:`flex items-center justify-center w-12 hover:bg-white/10 text-slate-400 hover:text-white transition-colors`,title:`Thu nhỏ`,children:(0,q.jsx)(i,{className:`w-4 h-4`})}),(0,q.jsx)(`button`,{onClick:()=>window.electron.maximize(),className:`flex items-center justify-center w-12 hover:bg-white/10 text-slate-400 hover:text-white transition-colors`,title:ye?`Thu nhỏ cửa sổ`:`Phóng to`,children:ye?(0,q.jsxs)(`svg`,{className:`w-3.5 h-3.5`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,q.jsx)(`rect`,{x:`8`,y:`8`,width:`12`,height:`12`,rx:`1.5`}),(0,q.jsx)(`path`,{d:`M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2`})]}):(0,q.jsx)(a,{className:`w-3.5 h-3.5`})}),(0,q.jsx)(`button`,{onClick:()=>window.electron.close(),className:`flex items-center justify-center w-12 hover:bg-rose-600 text-slate-400 hover:text-white transition-colors`,title:`Đóng`,children:(0,q.jsx)(C,{className:`w-4 h-4`})})]}),le&&(0,q.jsx)(`div`,{className:`sm:hidden border-t border-white/5 bg-[#1c183a] animate-fadeIn`,style:v?{WebkitAppRegion:`no-drag`}:{},children:(0,q.jsxs)(`div`,{className:`px-4 py-3 space-y-1`,children:[De&&(0,q.jsxs)(`button`,{onClick:()=>Q(`developer`),className:`w-full flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm font-semibold transition-all ${$===`developer`?`bg-purple-600/20 text-purple-300 border border-purple-500/30`:`text-slate-300 hover:bg-white/5`}`,children:[(0,q.jsx)(H,{className:`w-4 h-4`}),m.tabDeveloper]}),(0,q.jsxs)(`button`,{onClick:()=>Q(`downloads`),className:`w-full flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm font-semibold transition-all ${$===`downloads`?`bg-purple-600/20 text-purple-300 border border-purple-500/30`:`text-slate-300 hover:bg-white/5`}`,children:[(0,q.jsx)(J,{className:`w-4 h-4`}),m.tabDownloads]}),o&&(0,q.jsxs)(`button`,{onClick:()=>Q(`sects`),className:`w-full flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm font-semibold transition-all ${$===`sects`?`bg-purple-600/20 text-purple-300 border border-purple-500/30`:`text-slate-300 hover:bg-white/5`}`,children:[(0,q.jsx)(N,{className:`w-4 h-4 text-amber-400`}),d===`vi`?`Tông Môn`:d===`en`?`Sects`:`宗门`]}),(0,q.jsx)(`div`,{className:`h-px bg-white/5 my-2`}),(0,q.jsxs)(`div`,{className:`px-3 py-1.5`,children:[(0,q.jsx)(`p`,{className:`text-xs text-slate-400 mb-2 font-semibold`,children:d===`vi`?`Ngôn ngữ`:d===`en`?`Language`:`语言`}),(0,q.jsx)(`div`,{className:`flex bg-[#0f0f26]/60 rounded-full p-0.5 border border-white/5 text-xs font-bold w-fit`,children:[`vi`,`en`,`zh`].map(e=>(0,q.jsxs)(`button`,{onClick:()=>p(e),className:`flex items-center gap-1.5 px-3 py-1.5 rounded-full transition-all ${d===e?`bg-purple-600 text-white`:`text-slate-400 hover:text-white`}`,children:[(0,q.jsx)(fe,{langCode:e}),(0,q.jsx)(`span`,{children:e===`vi`?`VI`:e===`en`?`EN`:`ZH`})]},e))})]}),o?(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(`div`,{className:`h-px bg-white/5 my-2`}),(0,q.jsxs)(`button`,{onClick:()=>{h(`/messages`),Y(!1)},className:`w-full flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm font-semibold text-slate-300 hover:bg-white/5 transition-all relative`,children:[(0,q.jsx)(z,{className:`w-4 h-4 text-purple-400`}),d===`vi`?`Tin nhắn riêng`:d===`en`?`Direct Messages`:`私信`,X>0&&(0,q.jsx)(`span`,{className:`ml-auto flex h-5 min-w-[20px] items-center justify-center rounded-full bg-rose-500 text-white text-[9px] font-black px-1`,children:X>99?`99+`:X})]}),(0,q.jsxs)(`button`,{onClick:()=>{ge(`notifications`),pe(!0),Y(!1)},className:`w-full flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm font-semibold text-slate-300 hover:bg-white/5 transition-all relative`,children:[(0,q.jsx)(ee,{className:`w-4 h-4 text-amber-400`}),d===`vi`?`Thông báo thư hữu`:d===`en`?`Social Notifications`:`书友通知`,Z>0&&(0,q.jsx)(`span`,{className:`ml-auto flex h-5 min-w-[20px] items-center justify-center rounded-full bg-amber-500 text-white text-[9px] font-black px-1`,children:Z>99?`99+`:Z})]}),(0,q.jsxs)(`div`,{className:`flex items-center justify-between px-3 py-2 bg-[#0f0f26]/20 rounded-xl border border-white/5 mt-2`,children:[(0,q.jsxs)(`div`,{className:`min-w-0`,children:[(0,q.jsx)(`p`,{className:`text-xs font-bold text-white truncate`,children:o.username}),(0,q.jsx)(`p`,{className:`text-[10px] text-slate-500 truncate`,children:o.email})]}),(0,q.jsxs)(`button`,{onClick:()=>{u(),Y(!1)},className:`flex items-center gap-1.5 text-xs text-red-400 hover:text-red-300 font-semibold shrink-0`,children:[(0,q.jsx)(L,{className:`w-3.5 h-3.5`}),d===`vi`?`Đăng xuất`:d===`en`?`Logout`:`退出`]})]})]}):(0,q.jsx)(`div`,{className:`px-3 py-2`,children:(0,q.jsx)(`button`,{onClick:()=>{U(!0),Y(!1)},className:`w-full bg-purple-600 hover:bg-purple-500 text-white py-2.5 rounded-xl text-sm font-bold shadow-md transition-all`,children:m.login})}),(0,q.jsxs)(`div`,{className:`flex items-center gap-4 px-3 py-2 text-[10px] text-slate-500`,children:[(0,q.jsxs)(`span`,{children:[(r.total||931427).toLocaleString(),` `,d===`vi`?`truyện`:d===`en`?`novels`:`本`]}),(0,q.jsx)(`span`,{children:`•`}),(0,q.jsxs)(`span`,{children:[`7 `,d===`vi`?`nguồn`:d===`en`?`sources`:`源`]})]})]})})]}),!n&&(0,q.jsx)(oe,{}),!n&&v&&Ce&&(0,q.jsxs)(`div`,{className:`bg-gradient-to-r from-red-950 via-rose-900 to-red-950 border-b border-rose-500/30 px-4 py-2.5 flex items-center justify-between gap-3 animate-fadeIn`,children:[(0,q.jsxs)(`div`,{className:`flex items-center gap-2.5 min-w-0`,children:[(0,q.jsxs)(`span`,{className:`flex h-2 w-2 relative shrink-0`,children:[(0,q.jsx)(`span`,{className:`animate-ping absolute inline-flex h-full w-full rounded-full bg-rose-400 opacity-75`}),(0,q.jsx)(`span`,{className:`relative inline-flex rounded-full h-2 w-2 bg-rose-500`})]}),(0,q.jsxs)(`div`,{className:`min-w-0`,children:[(0,q.jsx)(`span`,{className:`text-white font-bold text-xs`,children:d===`vi`?`⚠️ LỖI: Không tìm thấy Động Cơ AI Offline (App_Doc_Truyen_Engine)!`:`⚠️ ERROR: Offline AI Engine not found (App_Doc_Truyen_Engine)!`}),(0,q.jsx)(`span`,{className:`text-rose-200 text-[10px] ml-2 hidden sm:inline`,children:d===`vi`?`— Vui lòng tải động cơ CPU hoặc GPU trong Cài đặt để sử dụng tính năng đọc truyện offline.`:`— Please download the CPU or GPU engine in Settings to use offline reading.`})]})]}),(0,q.jsx)(`div`,{className:`flex items-center gap-2 shrink-0`,children:(0,q.jsxs)(`button`,{onClick:()=>Q(`settings`),className:`flex items-center gap-1.5 bg-rose-600 hover:bg-rose-500 active:scale-95 text-white text-[11px] font-extrabold px-3 py-1.5 rounded-lg transition-all shadow-lg whitespace-nowrap`,children:[(0,q.jsx)(J,{className:`w-3.5 h-3.5`}),d===`vi`?`Đi tới Cài đặt tải ngay`:`Go to Settings to download`]})})]}),!n&&E?.hasUpdate&&!F&&(0,q.jsxs)(`div`,{className:`bg-gradient-to-r from-indigo-900/80 via-purple-900/80 to-indigo-900/80 border-b border-purple-500/30 px-4 py-2.5 flex items-center justify-between gap-3 animate-fadeIn`,children:[(0,q.jsxs)(`div`,{className:`flex items-center gap-2.5 min-w-0`,children:[(0,q.jsx)(V,{className:`w-4 h-4 text-purple-400 shrink-0 animate-pulse`}),(0,q.jsxs)(`div`,{className:`min-w-0`,children:[(0,q.jsx)(`span`,{className:`text-white font-bold text-xs`,children:d===`vi`?`🎉 Phiên bản mới v${E.latestVersion} đã có!`:`🎉 New version v${E.latestVersion} available!`}),E.releaseNotes&&(0,q.jsxs)(`span`,{className:`text-purple-200 text-[10px] ml-2 hidden sm:inline truncate`,children:[`— `,E.releaseNotes]})]})]}),(0,q.jsxs)(`div`,{className:`flex items-center gap-2 shrink-0`,children:[(0,q.jsxs)(`button`,{id:`btn-start-update`,onClick:ne,className:`flex items-center gap-1.5 bg-purple-600 hover:bg-purple-500 active:scale-95 text-white text-[11px] font-extrabold px-3 py-1.5 rounded-lg transition-all shadow-lg whitespace-nowrap`,children:[(0,q.jsx)(J,{className:`w-3 h-3`}),d===`vi`?v?`Cập nhật ngay`:`Xem tải về`:v?`Update Now`:`View Downloads`]}),(0,q.jsx)(`button`,{onClick:A,className:`p-1 text-purple-300 hover:text-white transition-colors rounded`,title:d===`vi`?`Bỏ qua`:`Dismiss`,children:(0,q.jsx)(C,{className:`w-3.5 h-3.5`})})]})]}),F&&(0,q.jsx)(`div`,{className:`fixed inset-0 z-[999] flex items-center justify-center bg-black/80 backdrop-blur-sm p-4`,children:(0,q.jsxs)(`div`,{className:`bg-[#131324] border border-purple-500/30 rounded-3xl p-7 max-w-sm w-full text-center space-y-4 shadow-2xl`,children:[(0,q.jsx)(V,{className:`w-8 h-8 text-purple-400 mx-auto animate-pulse`}),(0,q.jsx)(`h3`,{className:`text-base font-extrabold text-white`,children:d===`vi`?`⬇️ Đang tải cập nhật...`:`⬇️ Downloading update...`}),(0,q.jsx)(`p`,{className:`text-[11px] text-slate-300`,children:R}),(0,q.jsx)(`div`,{className:`w-full bg-[#1c1c38] rounded-full h-3 overflow-hidden border border-indigo-950/30`,children:(0,q.jsx)(`div`,{className:`bg-gradient-to-r from-purple-500 to-indigo-500 h-full rounded-full transition-all duration-300`,style:{width:`${te}%`}})}),(0,q.jsxs)(`div`,{className:`flex justify-between text-[10px] font-bold text-slate-500`,children:[(0,q.jsx)(`span`,{children:`0%`}),(0,q.jsxs)(`span`,{className:`text-purple-400 text-sm font-black`,children:[te,`%`]}),(0,q.jsx)(`span`,{children:`100%`})]}),(0,q.jsx)(`p`,{className:`text-[10px] text-slate-500`,children:d===`vi`?`⚠️ App sẽ tự đóng sau khi tải xong để kích hoạt phiên bản mới.`:`⚠️ App will close after download to launch the new version.`})]})}),(0,q.jsx)(`main`,{className:n?`w-full flex-1`:`max-w-[2200px] mx-auto px-3 sm:px-6 lg:px-12 py-4 sm:py-6 flex-1 w-full pb-24 sm:pb-6`,children:e}),!n&&(0,q.jsx)(se,{}),!n&&(0,q.jsx)(`nav`,{className:`sm:hidden fixed bottom-0 left-0 right-0 z-50 bg-[#1c183a]/95 backdrop-blur-md border-t border-white/8 safe-bottom`,style:v?{WebkitAppRegion:`no-drag`}:{},children:(0,q.jsx)(`div`,{className:`flex items-stretch h-16`,children:Ee.map(({key:e,icon:t,label:n})=>{let r=$===e;return(0,q.jsxs)(`button`,{onClick:()=>Q(e),className:`flex-1 flex flex-col items-center justify-center gap-0.5 relative transition-all active:scale-95`,children:[r&&(0,q.jsx)(`span`,{className:`absolute top-1.5 left-1/2 -translate-x-1/2 w-1 h-1 rounded-full bg-purple-500 nav-active`}),(0,q.jsx)(t,{className:`w-5 h-5 transition-colors ${r?`text-purple-400`:`text-slate-500`}`}),(0,q.jsx)(`span`,{className:`text-[9px] font-bold transition-colors ${r?`text-purple-400`:`text-slate-600`}`,children:n}),e===`settings`&&o?.require_password_change===1&&(0,q.jsxs)(`span`,{className:`absolute top-2.5 right-[calc(50%-10px)] flex h-2 w-2`,children:[(0,q.jsx)(`span`,{className:`animate-ping absolute inline-flex h-full w-full rounded-full bg-amber-400 opacity-75`}),(0,q.jsx)(`span`,{className:`relative inline-flex rounded-full h-2 w-2 bg-amber-500`})]})]},e)})})}),(0,q.jsx)(ie,{isOpen:re,onClose:()=>U(!1)}),(0,q.jsx)(ae,{isOpen:W,onClose:()=>G(!1)}),(0,q.jsx)(ce,{isOpen:ue,onClose:()=>pe(!1),defaultTab:he}),xe&&(0,q.jsx)(me,{onClose:()=>Se(!1)})]})}function me({onClose:e}){let[t,n]=(0,K.useState)(`Đang tải nhật ký...`),[r,i]=(0,K.useState)(!0),a=K.useRef(null),o=async()=>{try{window.electron&&window.electron.getLogContent?n(await window.electron.getLogContent()||`Chưa có nhật ký ghi nhận.`):n(`Chỉ hoạt động trên ứng dụng Desktop.`)}catch(e){n(`Lỗi tải log: ${e.message}`)}};return(0,K.useEffect)(()=>{o();let e=setInterval(o,2e3);return()=>clearInterval(e)},[]),(0,K.useEffect)(()=>{r&&a.current&&(a.current.scrollTop=a.current.scrollHeight)},[t,r]),(0,q.jsxs)(`div`,{className:`fixed bottom-0 left-0 right-0 h-80 bg-[#09090f] border-t-2 border-purple-600 shadow-[0_-15px_30px_rgba(0,0,0,0.8)] z-[999] flex flex-col text-slate-200 font-mono text-[11px] animate-slideUp`,children:[(0,q.jsxs)(`div`,{className:`h-10 bg-[#12121f] px-4 flex items-center justify-between border-b border-indigo-950/40 select-none`,children:[(0,q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,q.jsx)(`span`,{className:`w-2.5 h-2.5 rounded-full bg-purple-500 animate-pulse`}),(0,q.jsx)(`span`,{className:`font-extrabold text-xs uppercase tracking-wider text-purple-300`,children:`Nhật Ký Hệ Thống / Log Console`})]}),(0,q.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,q.jsx)(`button`,{onClick:o,className:`px-2.5 py-1 bg-indigo-600/30 hover:bg-indigo-600/50 rounded text-slate-300 hover:text-white transition-all text-[10px] font-bold`,children:`Làm mới`}),(0,q.jsx)(`button`,{onClick:async()=>{if(confirm(`Bạn có chắc chắn muốn xóa sạch nhật ký hiện tại?`))try{window.electron&&window.electron.clearLog&&(await window.electron.clearLog()?n(`Đã xóa nhật ký cũ. +`):alert(`Xóa log thất bại.`))}catch(e){alert(`Lỗi: `+e.message)}},className:`px-2.5 py-1 bg-rose-600/20 hover:bg-rose-600/40 rounded text-rose-300 hover:text-rose-200 transition-all text-[10px] font-bold`,children:`Xóa log`}),(0,q.jsx)(`button`,{onClick:()=>{window.electron&&window.electron.openLogFolder&&window.electron.openLogFolder()},className:`px-2.5 py-1 bg-slate-700/40 hover:bg-slate-700/60 rounded text-slate-300 hover:text-white transition-all text-[10px] font-bold`,children:`Mở thư mục`}),(0,q.jsxs)(`label`,{className:`flex items-center gap-1.5 cursor-pointer text-slate-400 hover:text-slate-200 transition-colors text-[10px] font-bold`,children:[(0,q.jsx)(`input`,{type:`checkbox`,checked:r,onChange:e=>i(e.target.checked),className:`rounded border-slate-700 bg-slate-900 text-purple-600 focus:ring-purple-500 w-3 h-3`}),(0,q.jsx)(`span`,{children:`Cuộn tự động`})]}),(0,q.jsx)(`button`,{onClick:e,className:`p-1 hover:bg-white/5 rounded text-slate-400 hover:text-white transition-colors`,children:(0,q.jsx)(C,{className:`w-4 h-4`})})]})]}),(0,q.jsx)(`div`,{ref:a,className:`flex-1 p-4 overflow-y-auto whitespace-pre-wrap leading-relaxed select-text bg-[#07070a] border-none outline-none text-slate-300 hover:text-white transition-colors scrollbar-thin`,style:{fontFamily:`'Consolas', 'Courier New', monospace`},children:t})]})}export{j as _,W as a,ee as b,V as c,B as d,z as f,M as g,F as h,G as i,re as l,I as m,ae as n,U as o,L as p,J as r,H as s,pe as t,ne as u,A as v,k as y}; \ No newline at end of file diff --git a/frontend-web/dist/assets/Messages-Df1xxWEC.js b/frontend-web/dist/assets/Messages-Df1xxWEC.js new file mode 100644 index 0000000000000000000000000000000000000000..8e69661c8757c4ce4bd47ddd06a7b49bfeb2ab57 --- /dev/null +++ b/frontend-web/dist/assets/Messages-Df1xxWEC.js @@ -0,0 +1 @@ +import{f as e,t,u as n}from"./MainLayout-COiTxmNr.js";import{a as r,n as i}from"./square-DZKJ0QGR.js";import{C as a,D as o,F as s,M as c,S as l,b as u,j as d,v as f,w as p}from"./index-yRoRoI6u.js";var m=u(`ellipsis-vertical`,[[`circle`,{cx:`12`,cy:`12`,r:`1`,key:`41hilf`}],[`circle`,{cx:`12`,cy:`5`,r:`1`,key:`gxeob9`}],[`circle`,{cx:`12`,cy:`19`,r:`1`,key:`lyex9k`}]]),h=u(`image`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,ry:`2`,key:`1m3agn`}],[`circle`,{cx:`9`,cy:`9`,r:`2`,key:`af1f0g`}],[`path`,{d:`m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21`,key:`1xmnt7`}]]),g=u(`paperclip`,[[`path`,{d:`m16 6-8.414 8.586a2 2 0 0 0 2.829 2.829l8.414-8.586a4 4 0 1 0-5.657-5.657l-8.379 8.551a6 6 0 1 0 8.485 8.485l8.379-8.551`,key:`1miecu`}]]),_=u(`phone`,[[`path`,{d:`M13.832 16.568a1 1 0 0 0 1.213-.303l.355-.465A2 2 0 0 1 17 15h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2A18 18 0 0 1 2 4a2 2 0 0 1 2-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-.8 1.6l-.468.351a1 1 0 0 0-.292 1.233 14 14 0 0 0 6.392 6.384`,key:`9njp5v`}]]),v=u(`video`,[[`path`,{d:`m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5`,key:`ftymec`}],[`rect`,{x:`2`,y:`6`,width:`14`,height:`12`,rx:`2`,key:`158x01`}]]),y=s(d(),1),b=c();function x(){let{user:s}=a(),{lang:c}=l(),u=o(),[d,x]=(0,y.useState)([]),[S,C]=(0,y.useState)(null),[w,T]=(0,y.useState)([]),[E,D]=(0,y.useState)(``),[O,k]=(0,y.useState)(!1),[A,j]=(0,y.useState)(``),[M,N]=(0,y.useState)(!1),P=(0,y.useRef)(null),F=(0,y.useRef)(null),I=(0,y.useRef)(null);(0,y.useEffect)(()=>{s||u(`/`)},[s,u]);let L=async(e=!0)=>{e&&N(!0);try{let e=await p.get(`/api/friends/list`);e.data&&e.data.friends&&x(e.data.friends)}catch(e){console.error(`Lỗi khi tải danh sách bạn bè:`,e)}finally{e&&N(!1)}},R=async(e,t=!0)=>{try{let t=await p.get(`/api/messages/chat/${e}`);t.data&&t.data.messages&&T(t.data.messages)}catch(e){console.error(`Lỗi khi tải lịch sử tin nhắn:`,e)}};(0,y.useEffect)(()=>{if(s)return L(!0),F.current=setInterval(()=>{document.hidden||L(!1)},15e3),()=>{F.current&&clearInterval(F.current)}},[s]),(0,y.useEffect)(()=>(S?(R(S.id,!0),x(e=>e.map(e=>e.id===S.id?{...e,unread_messages:0}:e)),I.current=setInterval(()=>{document.hidden||R(S.id,!1)},5e3)):(T([]),I.current&&clearInterval(I.current)),()=>{I.current&&clearInterval(I.current)}),[S]),(0,y.useEffect)(()=>{if(P.current){let e=P.current.parentElement;e&&e.scrollTo({top:e.scrollHeight,behavior:`smooth`})}},[w]);let z=async e=>{if(e&&e.preventDefault(),!E.trim()||!S)return;let t=E.trim();D(``),k(!0);let n=Date.now(),r={id:n,sender_id:s.id,receiver_id:S.id,message:t,created_at:new Date().toISOString(),is_read:0};T(e=>[...e,r]);try{let e=await p.post(`/api/messages/send`,{receiver_id:S.id,message:t});e.data&&e.data.success&&T(t=>t.map(t=>t.id===n?{...t,id:e.data.msg_id}:t))}catch(e){console.error(`Gửi tin nhắn thất bại:`,e),T(e=>e.filter(e=>e.id!==n)),D(t)}finally{k(!1)}},B=d.filter(e=>e.username.toLowerCase().includes(A.toLowerCase())),V=e=>{if(e.startsWith(`[Chia sẻ truyện]`)&&e.includes(`/book/`)){let t=e.split(` - `)[0].replace(`[Chia sẻ truyện] '`,``).replace(`'`,``),n=e.indexOf(`/book/`),i=``;n!==-1&&(i=e.substring(n+6).split(/[\s"\n]/)[0]);let a=e.indexOf(`Lời nhắn: `),o=a===-1?``:e.substring(a+10);return(0,b.jsxs)(`div`,{className:`p-3 bg-purple-900/30 border border-purple-500/20 rounded-xl space-y-2 max-w-sm`,children:[(0,b.jsxs)(`div`,{className:`flex items-start justify-between gap-2`,children:[(0,b.jsxs)(`div`,{children:[(0,b.jsx)(`span`,{className:`text-[10px] text-purple-300 font-bold uppercase tracking-wider block`,children:`Chia sẻ truyện`}),(0,b.jsx)(`span`,{className:`text-xs font-black text-white block mt-0.5`,children:t})]}),(0,b.jsxs)(`button`,{onClick:()=>u(`/book/${i}`),className:`p-1.5 bg-purple-600 hover:bg-purple-500 text-white rounded-lg transition-colors flex items-center gap-1 text-[10px] font-bold`,children:[(0,b.jsx)(`span`,{children:`Đọc`}),(0,b.jsx)(r,{className:`w-3 h-3`})]})]}),o&&(0,b.jsxs)(`p`,{className:`text-[11px] text-slate-300 bg-black/20 p-2 rounded-lg border border-white/5 italic`,children:[`"`,o,`"`]})]})}return(0,b.jsx)(`p`,{className:`text-xs whitespace-pre-wrap leading-relaxed select-text`,children:e})};return(0,b.jsx)(t,{children:(0,b.jsx)(`div`,{className:`max-w-[1400px] mx-auto px-4 py-6 md:py-10 h-[calc(100vh-80px)] flex flex-col`,children:(0,b.jsxs)(`div`,{className:`flex-1 bg-[#121225]/80 border border-[#1f1f3a] rounded-3xl overflow-hidden flex shadow-2xl backdrop-blur-xl`,children:[(0,b.jsxs)(`div`,{className:`w-full md:w-80 border-r border-[#1f1f3a] flex flex-col bg-[#0b0b14]/50 ${S?`hidden md:flex`:`flex`}`,children:[(0,b.jsxs)(`div`,{className:`p-4 border-b border-[#1f1f3a] space-y-3 shrink-0`,children:[(0,b.jsxs)(`h3`,{className:`text-sm font-black tracking-wider text-slate-100 uppercase flex items-center gap-2`,children:[(0,b.jsx)(e,{className:`w-4 h-4 text-purple-400`}),c===`vi`?`Hộp thư đàm đạo`:`Direct Messages`]}),(0,b.jsxs)(`div`,{className:`relative`,children:[(0,b.jsx)(i,{className:`absolute left-3 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-slate-500`}),(0,b.jsx)(`input`,{type:`text`,placeholder:c===`vi`?`Tìm bạn hữu...`:`Search friends...`,value:A,onChange:e=>j(e.target.value),className:`w-full pl-9 pr-4 py-2 bg-[#05050a] border border-[#1f1f3a] rounded-xl text-xs text-white outline-none focus:border-purple-500 transition-colors placeholder-slate-600`})]})]}),(0,b.jsx)(`div`,{className:`flex-1 overflow-y-auto p-2 space-y-1.5 no-scrollbar`,children:M&&d.length===0?(0,b.jsxs)(`div`,{className:`flex justify-center items-center py-20 text-xs text-slate-500 gap-2`,children:[(0,b.jsx)(`div`,{className:`w-4 h-4 border-2 border-purple-500 border-t-transparent rounded-full animate-spin`}),`Đang tải bạn hữu...`]}):B.length===0?(0,b.jsx)(`div`,{className:`text-center py-20 text-xs text-slate-600`,children:A?`Không tìm thấy bạn hữu nào`:`Chưa có bạn hữu nào`}):B.map(e=>(0,b.jsxs)(`div`,{onClick:()=>C(e),className:`flex items-center justify-between p-3 rounded-2xl cursor-pointer transition-all ${S?.id===e.id?`bg-purple-600/20 border border-purple-500/30 text-white`:`hover:bg-purple-950/10 border border-transparent hover:border-[#1f1f3a] text-slate-300`}`,children:[(0,b.jsxs)(`div`,{className:`flex items-center gap-3 min-w-0`,children:[(0,b.jsxs)(`div`,{className:`relative shrink-0`,children:[e.avatar?(0,b.jsx)(`img`,{src:e.avatar,className:`w-10 h-10 rounded-full object-cover ring-2 ring-purple-500/20`,alt:`avatar`}):(0,b.jsx)(`div`,{className:`w-10 h-10 rounded-full bg-gradient-to-br from-purple-600 to-brand-500 flex items-center justify-center font-black text-sm text-white shadow-inner`,children:e.username[0].toUpperCase()}),(0,b.jsx)(`span`,{className:`absolute bottom-0 right-0 w-2.5 h-2.5 bg-emerald-500 rounded-full border-2 border-[#0c0d1e]`})]}),(0,b.jsxs)(`div`,{className:`min-w-0`,children:[(0,b.jsx)(`span`,{className:`font-extrabold text-xs block truncate`,children:e.username}),(0,b.jsx)(`span`,{className:`text-[10px] text-slate-500 block truncate mt-0.5`,children:e.user_code?`#${e.user_code}`:`Đang trực tuyến`})]})]}),e.unread_messages>0&&(0,b.jsx)(`span`,{className:`px-2 py-0.5 bg-rose-500 text-white rounded-full text-[9px] font-black min-w-[18px] text-center animate-pulse shadow-md`,children:e.unread_messages})]},e.id))})]}),(0,b.jsx)(`div`,{className:`flex-1 flex flex-col bg-[#080814]/30 ${S?`flex`:`hidden md:flex`}`,children:S?(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)(`div`,{className:`px-4 py-3 border-b border-[#1f1f3a] flex items-center justify-between bg-[#0b0b14]/50 shrink-0`,children:[(0,b.jsxs)(`div`,{className:`flex items-center gap-3 min-w-0`,children:[(0,b.jsx)(`button`,{onClick:()=>C(null),className:`p-1 hover:bg-white/5 rounded-lg text-slate-400 hover:text-white transition-colors md:hidden shrink-0`,children:(0,b.jsx)(f,{className:`w-5 h-5`})}),S.avatar?(0,b.jsx)(`img`,{src:S.avatar,className:`w-9 h-9 rounded-full object-cover shrink-0 ring-2 ring-purple-500/20`,alt:`avatar`}):(0,b.jsx)(`div`,{className:`w-9 h-9 rounded-full bg-gradient-to-br from-purple-600 to-brand-500 flex items-center justify-center font-black text-xs text-white shrink-0 shadow-inner`,children:S.username[0].toUpperCase()}),(0,b.jsxs)(`div`,{className:`min-w-0`,children:[(0,b.jsx)(`span`,{className:`font-extrabold text-xs text-slate-200 block truncate`,children:S.username}),(0,b.jsx)(`span`,{className:`text-[9px] text-slate-500 block mt-0.5`,children:`Đang đàm đạo`})]})]}),(0,b.jsxs)(`div`,{className:`flex items-center gap-1 shrink-0`,children:[(0,b.jsx)(`button`,{className:`p-2 hover:bg-white/5 rounded-xl text-slate-400 hover:text-white transition-all`,title:`Gọi thoại (Giả lập)`,children:(0,b.jsx)(_,{className:`w-4 h-4`})}),(0,b.jsx)(`button`,{className:`p-2 hover:bg-white/5 rounded-xl text-slate-400 hover:text-white transition-all`,title:`Gọi video (Giả lập)`,children:(0,b.jsx)(v,{className:`w-4 h-4`})}),(0,b.jsx)(`button`,{className:`p-2 hover:bg-white/5 rounded-xl text-slate-400 hover:text-white transition-all`,children:(0,b.jsx)(m,{className:`w-4 h-4`})})]})]}),(0,b.jsxs)(`div`,{className:`flex-1 overflow-y-auto p-4 space-y-3 no-scrollbar select-text bg-gradient-to-b from-[#080814]/10 to-[#0b0b14]/40`,children:[w.length===0?(0,b.jsxs)(`div`,{className:`text-center py-20 text-xs text-slate-600`,children:[`Hãy gửi lời chào đầu tiên tới `,S.username,`!`]}):w.map((e,t)=>{let n=e.sender_id===s.id;return(0,b.jsx)(`div`,{className:`flex ${n?`justify-end`:`justify-start`}`,children:(0,b.jsxs)(`div`,{className:`max-w-[70%] sm:max-w-[60%] space-y-1`,children:[(0,b.jsx)(`div`,{className:`p-3 rounded-2xl shadow-md ${n?`bg-gradient-to-tr from-purple-600 to-indigo-600 text-white rounded-br-none`:`bg-[#121225] border border-[#1f1f3a] text-slate-200 rounded-bl-none`}`,children:V(e.message)}),(0,b.jsx)(`span`,{className:`text-[8px] text-slate-600 block ${n?`text-right`:`text-left`}`,children:new Date(e.created_at).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`})})]})},e.id||t)}),(0,b.jsx)(`div`,{ref:P})]}),(0,b.jsxs)(`form`,{onSubmit:z,className:`p-3 border-t border-[#1f1f3a] bg-[#0b0b14]/50 flex items-center gap-2 shrink-0`,children:[(0,b.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,b.jsx)(`button`,{type:`button`,className:`p-2 hover:bg-white/5 rounded-xl text-slate-500 hover:text-slate-300 transition-colors`,title:`Đính kèm ảnh`,children:(0,b.jsx)(h,{className:`w-4 h-4`})}),(0,b.jsx)(`button`,{type:`button`,className:`p-2 hover:bg-white/5 rounded-xl text-slate-500 hover:text-slate-300 transition-colors`,title:`Đính kèm tệp`,children:(0,b.jsx)(g,{className:`w-4 h-4`})})]}),(0,b.jsx)(`input`,{type:`text`,placeholder:`Nhập nội dung đàm đạo...`,value:E,onChange:e=>D(e.target.value),className:`flex-1 px-4 py-2.5 bg-[#05050a] border border-[#1f1f3a] rounded-2xl text-xs text-white outline-none focus:border-purple-500 transition-colors`}),(0,b.jsx)(`button`,{type:`submit`,disabled:O||!E.trim(),className:`p-2.5 bg-purple-600 hover:bg-purple-500 text-white rounded-2xl transition-all disabled:opacity-40 shadow-lg shadow-purple-600/20 hover:scale-105 active:scale-95 shrink-0`,children:(0,b.jsx)(n,{className:`w-4 h-4`})})]})]}):(0,b.jsxs)(`div`,{className:`flex-1 flex flex-col items-center justify-center text-center p-8 select-none`,children:[(0,b.jsx)(`div`,{className:`w-20 h-20 bg-gradient-to-tr from-purple-600/20 to-brand-500/20 rounded-full flex items-center justify-center text-purple-400 shadow-xl mb-4 border border-purple-500/10 animate-pulse`,children:(0,b.jsx)(e,{className:`w-9 h-9`})}),(0,b.jsx)(`h3`,{className:`font-extrabold text-base text-slate-200`,children:`Kính chào Thư hữu!`}),(0,b.jsx)(`p`,{className:`text-xs text-slate-500 max-w-sm mt-2 leading-relaxed`,children:`Hãy chọn một người bạn từ danh sách đàm đạo ở cột bên trái để bắt đầu nhắn tin và chia sẻ các tác phẩm truyện dịch AI tâm đắc.`})]})})]})})})}export{x as default}; \ No newline at end of file diff --git a/frontend-web/dist/assets/Reader-DUnP7yTH.js b/frontend-web/dist/assets/Reader-DUnP7yTH.js new file mode 100644 index 0000000000000000000000000000000000000000..94a509652448e918c9986c4fb57fad007041a164 --- /dev/null +++ b/frontend-web/dist/assets/Reader-DUnP7yTH.js @@ -0,0 +1,11 @@ +import{n as e,r as t,t as n}from"./useUsageTracker-Bc2zfMaM.js";import{a as r,i,n as a,o,r as s,t as c}from"./square-DZKJ0QGR.js";import{t as l}from"./eye-DsLuESBv.js";import{C as u,D as d,F as f,M as p,O as m,S as h,_ as g,b as _,c as ee,d as v,f as y,j as b,n as x,o as S,t as C,u as w,v as T,w as E,x as D}from"./index-yRoRoI6u.js";import{t as O}from"./GoogleAd-CD0eT9Wp.js";var k=_(`zoom-in`,[[`circle`,{cx:`11`,cy:`11`,r:`8`,key:`4ej97u`}],[`line`,{x1:`21`,x2:`16.65`,y1:`21`,y2:`16.65`,key:`13gj7c`}],[`line`,{x1:`11`,x2:`11`,y1:`8`,y2:`14`,key:`1vmskp`}],[`line`,{x1:`8`,x2:`14`,y1:`11`,y2:`11`,key:`durymu`}]]),A=_(`zoom-out`,[[`circle`,{cx:`11`,cy:`11`,r:`8`,key:`4ej97u`}],[`line`,{x1:`21`,x2:`16.65`,y1:`21`,y2:`16.65`,key:`13gj7c`}],[`line`,{x1:`8`,x2:`14`,y1:`11`,y2:`11`,key:`durymu`}]]),j=f(b(),1),M=p();function N({children:e,bookTitle:n,currentChapter:r,chaptersList:a,onSelectChapter:l}){let{theme:u,setTheme:f,fontSize:p,decreaseFontSize:m,increaseFontSize:h,fontFamily:g,setFontFamily:_,lineHeight:v,setLineHeight:y}=D(),b=d(),x=typeof window<`u`&&!!window.electron,[C,w]=(0,j.useState)(!0),[T,E]=(0,j.useState)(!1),[O,N]=(0,j.useState)(!1),[P,F]=(0,j.useState)(!1);return(0,j.useEffect)(()=>{if(x)return window.electron.isMaximized().then(F),window.electron.onWindowStateChange(F)},[x]),(0,j.useEffect)(()=>{let e=e=>{if(e.target.closest(`.reader-overlay`)||e.target.closest(`.reader-sidebar`))return;if(O){N(!1);return}let t=e.clientX,n=window.innerWidth,r=n*.3,i=n*.7;t>r&&t!e)};return window.addEventListener(`click`,e,{passive:!0}),()=>window.removeEventListener(`click`,e)},[O]),(0,M.jsxs)(`div`,{className:`min-h-screen transition-colors duration-300 relative theme-${u} select-none`,children:[(0,M.jsxs)(`div`,{className:`reader-overlay fixed top-0 left-0 right-0 z-40 bg-[#0f0f1a]/95 border-b border-[#2d2d6b]/50 p-4 flex items-center justify-between text-slate-100 transition-all duration-300 ${C?`translate-y-0 opacity-100`:`-translate-y-full opacity-0`}`,style:{...x?{WebkitAppRegion:`drag`,paddingRight:`144px`}:{}},children:[(0,M.jsxs)(`div`,{className:`flex items-center gap-3`,style:x?{WebkitAppRegion:`no-drag`}:{},children:[(0,M.jsx)(`button`,{onClick:()=>b(-1),className:`p-2 hover:bg-white/10 rounded-lg transition-colors`,children:(0,M.jsx)(t,{className:`w-5 h-5`})}),(0,M.jsxs)(`div`,{className:`min-w-0`,children:[(0,M.jsx)(`h4`,{className:`font-bold text-sm truncate`,children:n||`Đang tải...`}),(0,M.jsx)(`p`,{className:`text-slate-400 text-xs truncate mt-0.5`,children:r||`Chương --`})]})]}),(0,M.jsxs)(`div`,{className:`flex items-center gap-2`,style:x?{WebkitAppRegion:`no-drag`}:{},children:[(0,M.jsx)(`button`,{onClick:e=>{e.stopPropagation(),N(e=>!e)},className:`p-2 rounded-lg transition-colors ${O?`bg-brand-500/25 text-brand-300`:`hover:bg-white/10 text-slate-300`}`,title:`Cài đặt giao diện`,children:(0,M.jsx)(ee,{className:`w-5 h-5`})}),(0,M.jsx)(`button`,{onClick:()=>E(!0),className:`p-2 hover:bg-white/10 rounded-lg transition-colors`,title:`Danh sách chương`,children:(0,M.jsx)(i,{className:`w-5 h-5`})})]}),x&&(0,M.jsxs)(`div`,{className:`absolute right-0 top-0 bottom-0 flex items-stretch h-full`,style:{WebkitAppRegion:`no-drag`},children:[(0,M.jsx)(`button`,{onClick:()=>window.electron.minimize(),className:`flex items-center justify-center w-12 hover:bg-white/10 text-slate-400 hover:text-white transition-colors`,title:`Thu nhỏ`,children:(0,M.jsx)(s,{className:`w-4 h-4`})}),(0,M.jsx)(`button`,{onClick:()=>window.electron.maximize(),className:`flex items-center justify-center w-12 hover:bg-white/10 text-slate-400 hover:text-white transition-colors`,title:P?`Thu nhỏ cửa sổ`:`Phóng to`,children:P?(0,M.jsxs)(`svg`,{className:`w-3.5 h-3.5`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,M.jsx)(`rect`,{x:`8`,y:`8`,width:`12`,height:`12`,rx:`1.5`}),(0,M.jsx)(`path`,{d:`M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2`})]}):(0,M.jsx)(c,{className:`w-3.5 h-3.5`})}),(0,M.jsx)(`button`,{onClick:()=>window.electron.close(),className:`flex items-center justify-center w-12 hover:bg-rose-600 text-slate-400 hover:text-white transition-colors`,title:`Đóng`,children:(0,M.jsx)(S,{className:`w-4 h-4`})})]})]}),(0,M.jsxs)(`div`,{className:`reader-overlay fixed bottom-0 left-0 right-0 z-40 bg-[#0f0f1a]/95 border-t border-[#2d2d6b]/50 p-6 text-slate-100 transition-all duration-300 flex flex-col gap-4 max-w-2xl mx-auto rounded-t-2xl shadow-2xl ${O?`translate-y-0 opacity-100`:`translate-y-full opacity-0 pointer-events-none`}`,children:[(0,M.jsxs)(`div`,{className:`flex items-center justify-between gap-4`,children:[(0,M.jsx)(`span`,{className:`text-xs text-slate-400 font-bold uppercase tracking-wider`,children:`Màu nền`}),(0,M.jsx)(`div`,{className:`flex gap-3`,children:[{id:`light`,name:`Sáng`,bg:`bg-white border-slate-300`},{id:`sepia`,name:`Giấy cổ`,bg:`bg-[#f4ecd8] border-[#5c4033]/20`},{id:`green`,name:`Bảo vệ mắt`,bg:`bg-[#dfedd6] border-[#2e4a3e]/20`},{id:`dark`,name:`Tối`,bg:`bg-[#0b0b14] border-[#1f1f3a]`}].map(e=>(0,M.jsx)(`button`,{onClick:()=>f(e.id),className:`w-8 h-8 rounded-full border-2 transition-all flex items-center justify-center ${e.bg} ${u===e.id?`scale-110 border-brand-500 shadow-md`:`opacity-80`}`,title:e.name,children:u===e.id&&(0,M.jsx)(o,{className:`w-4 h-4 ${e.id===`light`?`text-black`:e.id===`sepia`?`text-[#5c4033]`:e.id===`green`?`text-[#2e4a3e]`:`text-white`}`})},e.id))})]}),(0,M.jsxs)(`div`,{className:`flex items-center justify-between gap-4`,children:[(0,M.jsx)(`span`,{className:`text-xs text-slate-400 font-bold uppercase tracking-wider`,children:`Cỡ chữ`}),(0,M.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,M.jsx)(`button`,{onClick:m,className:`p-2 bg-white/5 border border-white/10 hover:bg-white/10 active:scale-95 rounded-lg transition-all`,children:(0,M.jsx)(A,{className:`w-4 h-4`})}),(0,M.jsxs)(`span`,{className:`text-sm font-bold w-8 text-center`,children:[p,`px`]}),(0,M.jsx)(`button`,{onClick:h,className:`p-2 bg-white/5 border border-white/10 hover:bg-white/10 active:scale-95 rounded-lg transition-all`,children:(0,M.jsx)(k,{className:`w-4 h-4`})})]})]}),(0,M.jsxs)(`div`,{className:`flex items-center justify-between gap-4`,children:[(0,M.jsx)(`span`,{className:`text-xs text-slate-400 font-bold uppercase tracking-wider`,children:`Font chữ`}),(0,M.jsx)(`div`,{className:`flex bg-white/5 rounded-lg p-1 border border-white/10 text-xs`,children:[{id:`sans`,name:`Không chân`},{id:`serif`,name:`Có chân`},{id:`mono`,name:`Đơn cách`}].map(e=>(0,M.jsx)(`button`,{onClick:()=>_(e.id),className:`px-3 py-1.5 rounded-md font-bold transition-all ${g===e.id?`bg-brand-500 text-white shadow-md`:`text-slate-400`}`,children:e.name},e.id))})]}),(0,M.jsxs)(`div`,{className:`flex items-center justify-between gap-4`,children:[(0,M.jsx)(`span`,{className:`text-xs text-slate-400 font-bold uppercase tracking-wider`,children:`Giãn dòng`}),(0,M.jsx)(`div`,{className:`flex bg-white/5 rounded-lg p-1 border border-white/10 text-xs`,children:[{id:`normal`,name:`Thường`},{id:`relaxed`,name:`Rộng`},{id:`loose`,name:`Rất rộng`}].map(e=>(0,M.jsx)(`button`,{onClick:()=>y(e.id),className:`px-3 py-1.5 rounded-md font-bold transition-all ${v===e.id?`bg-brand-500 text-white shadow-md`:`text-slate-400`}`,children:e.name},e.id))})]})]}),(0,M.jsxs)(`div`,{className:`reader-sidebar fixed top-0 right-0 bottom-0 z-50 w-80 max-w-[85vw] bg-[#0f0f1a] border-l border-[#2d2d6b]/50 p-5 flex flex-col gap-4 text-slate-100 transition-transform duration-300 shadow-2xl ${T?`translate-x-0`:`translate-x-full`}`,children:[(0,M.jsxs)(`div`,{className:`flex items-center justify-between border-b border-[#2d2d6b]/50 pb-3`,children:[(0,M.jsx)(`h4`,{className:`font-extrabold text-sm`,children:`Mục lục`}),(0,M.jsx)(`button`,{onClick:()=>E(!1),className:`text-slate-400 hover:text-white`,children:`Đóng`})]}),(0,M.jsx)(`div`,{className:`flex-1 overflow-y-auto space-y-1`,children:a&&a.length>0?a.map((e,t)=>(0,M.jsx)(`button`,{onClick:()=>{l(e),E(!1)},className:`w-full text-left px-3 py-2.5 rounded-xl text-xs hover:bg-white/5 transition-colors truncate ${e.active?`text-brand-300 bg-brand-500/10 font-bold`:`text-slate-400`}`,children:e.title},t)):(0,M.jsx)(`p`,{className:`text-slate-500 text-xs text-center py-6`,children:`Mục lục rỗng.`})})]}),T&&(0,M.jsx)(`div`,{onClick:()=>E(!1),className:`fixed inset-0 z-45 bg-black/50 backdrop-blur-sm`}),(0,M.jsx)(`div`,{className:`max-w-3xl mx-auto px-6 py-24 min-h-screen`,children:e})]})}function P(){let{bookId:t,chapterIdx:i}=m(),{theme:o,fontSize:s,fontFamily:c,lineHeight:f}=D(),{user:p}=u(),{t:_,lang:ee}=h(),b=d();n(`web`,`read`);let[k,A]=(0,j.useState)(``),[P,F]=(0,j.useState)(``),[te,ne]=(0,j.useState)([]),[I,L]=(0,j.useState)(``),[re,R]=(0,j.useState)(!0),[ie,z]=(0,j.useState)(!1),[B,V]=(0,j.useState)(null),[H,U]=(0,j.useState)(null),[W,ae]=(0,j.useState)(`miễn phí đọc mới nhất`),[oe,se]=(0,j.useState)(null),{activeAudioObj:G,setActiveAudioObj:K}=C(),[q,ce]=(0,j.useState)(()=>localStorage.getItem(`tts_auto_scroll`)!==`false`),[J,Y]=(0,j.useState)(-1),[X,le]=(0,j.useState)(()=>{try{return JSON.parse(localStorage.getItem(`translationSettings`)||`{}`).audioSpeed||1.5}catch{return 1.5}});(0,j.useEffect)(()=>{let e=e=>{e.detail?.audioSpeed&&le(e.detail.audioSpeed)};return window.addEventListener(`translationSettingsUpdated`,e),()=>window.removeEventListener(`translationSettingsUpdated`,e)},[]);let ue=()=>{let e=!q;ce(e),localStorage.setItem(`tts_auto_scroll`,e?`true`:`false`)},Z=G&&String(G.book?.id)===String(t)&&G.chapterIdx===parseInt(i),Q=()=>{if(!I)return null;let e=I.split(/\s+/).filter(Boolean).length,t=Math.round(e/(150*X)*60);return{minutes:Math.floor(t/60),seconds:t%60,wordCount:e}};(0,j.useRef)(!1),(0,j.useEffect)(()=>{de()},[t,i]),(0,j.useEffect)(()=>{let e=e=>{Y(e.detail.charIdx)};return window.addEventListener(`global-tts-boundary`,e),()=>window.removeEventListener(`global-tts-boundary`,e)},[]),(0,j.useEffect)(()=>{if(Z&&J>0&&q){let e=document.getElementById(`active-tts-sentence`);e&&e.scrollIntoView({behavior:`smooth`,block:`center`})}},[J,Z,q]),(0,j.useEffect)(()=>{let e=e=>{if(e.detail&&e.detail.bookId===t){let n=e.detail.chapterIdx;q&&n!==parseInt(i)&&b(`/book/${t}/read/${n}`)}};return window.addEventListener(`global-tts-chapter-changed`,e),()=>window.removeEventListener(`global-tts-chapter-changed`,e)},[t,i,q]),(0,j.useEffect)(()=>{let e=document.getElementById(`embedded-webview`);if(e){let t=e=>{e.preventDefault(),se(e.url||e.targetUrl)};return e.addEventListener(`new-window`,t),()=>{e.removeEventListener(`new-window`,t)}}},[oe]);let de=async()=>{R(!0);try{let e=`Vũ Luyện Điên Phong`;try{let n=await E.get(`/api/book/${t}`);n.data&&(V(n.data),e=n.data.title_vietphrase||n.data.title_hanviet||n.data.title)}catch(e){console.error(`Error fetching book details in reader:`,e)}A(e),F(`Chương ${i}: Khai Phong Thần Điện`),ne(Array.from({length:50},(e,t)=>({id:t+1,title:`Chương ${t+1}: Khai Phong Thần Điện`,url_idx:t+1,active:t+1===parseInt(i)})));let n=`第${i}章 开封神殿\n\n武之极,破苍穹,动乾坤!在这片神秘의 개봉신전中,无数强者汇聚。他们为了争夺上古机缘,不惜 blood shed.\n\n杨开迈步走入神殿,神色淡然。他能夠清晰地感受到虚空中波动的强横气息。这一次 exploration,他势在必得。`;z(!0);let r=n;try{let e=await E.post(`/translate`,{texts:n.split(` + +`),mode:`fast`},{headers:{"X-VIP-Key":`LYVUHA_ADMIN_2026`}});e.data&&e.data.translations&&(r=e.data.translations.join(` + +`))}catch(e){console.warn(`[Reader] Cloud translation failed, trying offline localTranslator:`,e);try{await x.loadDictionaries(),r=n.split(` + +`).map(e=>x.translateSentence(e,`advanced`)).join(` + +`)}catch(e){throw console.error(`[Reader] Offline translation failed as well:`,e),Error(`Cả máy chủ dịch và bộ dịch offline đều thất bại.`)}}L(r),G&&G.playType===`online`&&G.book?.id===t&&K({...G,chapterIdx:parseInt(i),title_vietphrase:`Chương ${i}: Khai Phong Thần Điện`,description:r,startSentenceIdx:0}),p&&await E.post(`/api/history/add`,{book_id:parseInt(t),last_chapter:`Chương ${i}`})}catch(e){console.error(e),L(_.reader?.errorLoadingChapter||`Lỗi tải nội dung chương hoặc không kết nối được máy chủ dịch.`)}finally{R(!1),z(!1)}},fe=e=>{b(`/book/${t}/read/${e.url_idx}`)},pe=()=>{let e=parseInt(i)-1;e>=1&&b(`/book/${t}/read/${e}`)},me=()=>{let e=parseInt(i)+1;e<=50&&b(`/book/${t}/read/${e}`)},he=()=>{Z?ge():K({title_vietphrase:P,author_hanviet:k,description:I,isChapter:!0,onBoundary:e=>{Y(e)},book:{id:t,title:k,title_vietphrase:k},chapterIdx:parseInt(i),playType:`online`})},ge=()=>{K(null),Y(-1)},_e=(e,n)=>{let r=I.split(/\n+/),a=0;for(let t=0;te?(c.test(r.trim())&&(s.push(r.trim()),l=!1),r=t):r+=t}}r.trim()&&c.test(r.trim())&&(s.push(r.trim()),l=!1)}let u=s.length;K({title_vietphrase:P,author_hanviet:k,description:I,isChapter:!0,onBoundary:e=>{Y(e)},book:{id:t,title:k,title_vietphrase:k},chapterIdx:parseInt(i),playType:`online`,startSentenceIdx:u})},ve=()=>{let e=I.split(/\n+/),t=0,n=J-(P.length+2);return e.map((e,r)=>{let i=t;t+=e.length+1;let a=Z&&n>=i&&n=0;n--)if([`.`,`?`,`!`,` +`].includes(e[n])){r=n+1;break}let a=e.length;for(let n=t;n_e(r,e),className:`cursor-pointer hover:bg-purple-500/5 px-2 py-1 rounded transition-colors duration-150 relative group`,title:`Nháy đúp để đọc từ đoạn này`,children:o},r)})},ye=()=>c===`serif`?`font-serif`:c===`mono`?`font-mono`:`font-sans`,be=()=>f===`loose`?`leading-loose`:f===`relaxed`?`leading-relaxed`:`leading-normal`;if(re)return(0,M.jsxs)(`div`,{className:`min-h-screen bg-[#0b0b14] flex flex-col items-center justify-center text-slate-500`,children:[(0,M.jsx)(y,{className:`w-8 h-8 animate-spin text-brand-500 mb-3`}),(0,M.jsx)(`span`,{children:_.reader?.loadingChapter||`Đang tải chương truyện...`})]});let xe=[{name:`Ixdzs`,isChinese:!0},{name:`Biquge`,isChinese:!0},{name:`41nr`,isChinese:!0},{name:`Quanben`,isChinese:!0},{name:`Hjwzw`,isChinese:!0},{name:`Fanqie`,isChinese:!0},{name:`Metruyenchu`,isChinese:!1},{name:`TruyenFull`,isChinese:!1},{name:`Vcomi`,isChinese:!1}],Se=B?.parsed_sources||[],Ce=xe.map(e=>{let t=Se.find(t=>t.source.toLowerCase()===e.name.toLowerCase());return t?{site:t.source,url:t.url,isSearch:!1,isChinese:e.isChinese}:{site:e.name,url:null,isSearch:!0,isChinese:e.isChinese}}),$=(e,t)=>{if(!H)return;let{site:n}=H,r=``,i=B?.title||k||``,a=B?.author||``,o=B?.title_vietphrase||k||``,s=B?.author_hanviet||``;r=t===`vi`?`${o.trim()} ${s.trim()} ${n} ${W}`.trim():`${i.trim()} ${a.trim()} ${n} ${W}`.trim();let c=``;c=e===`baidu`?`https://www.baidu.com/s?wd=${encodeURIComponent(r)}`:`https://www.google.com/search?q=${encodeURIComponent(r)}`,openInBrowser(c),U(null)};return(0,M.jsx)(N,{bookTitle:k,currentChapter:P,chaptersList:te,onSelectChapter:fe,children:(0,M.jsxs)(`div`,{className:`space-y-8`,children:[(0,M.jsxs)(`div`,{className:`flex flex-col gap-4 border-b border-slate-500/10 pb-4 reader-overlay`,children:[(0,M.jsxs)(`div`,{className:`flex justify-between items-center flex-wrap gap-4`,children:[(0,M.jsxs)(`div`,{className:`flex flex-wrap items-center gap-1.5`,children:[(0,M.jsx)(`span`,{className:`text-[10px] text-slate-500 font-extrabold uppercase mr-1`,children:`Nguồn truyện:`}),Ce.map((e,t)=>{let n=`bg-emerald-500 text-white`;return e.site.toLowerCase().includes(`biquge`)||e.site.toLowerCase().includes(`full`)||e.site.toLowerCase().includes(`truyenfull`)?n=`bg-sky-500 text-white`:e.site.toLowerCase().includes(`faloo`)||e.site.toLowerCase().includes(`vcomi`)||e.site.toLowerCase().includes(`fanqie`)?n=`bg-orange-500 text-white`:(e.site.toLowerCase().includes(`quanben`)||e.site.toLowerCase().includes(`hjwzw`))&&(n=`bg-purple-500 text-white`),e.isSearch?(0,M.jsxs)(`button`,{onClick:t=>{t.stopPropagation(),U(t=>t?.site===e.site?null:{site:e.site,isChinese:e.isChinese})},className:`inline-flex items-center gap-1 bg-[#0b0b14]/20 border border-dashed border-[#1f1f3a]/80 hover:border-purple-500/50 rounded-lg px-2 py-0.5 text-[11px] text-slate-400 hover:text-slate-200 transition-all ${H?.site===e.site?`border-purple-500 text-white bg-purple-950/20`:``}`,title:`Không có link trực tiếp. Click để tìm kiếm trên Google/Baidu cho ${e.site}`,children:[(0,M.jsx)(`span`,{className:`w-3 h-3 rounded flex items-center justify-center text-[7px] font-extrabold ${n} opacity-60`,children:e.site[0]}),e.site,(0,M.jsx)(a,{className:`w-2.5 h-2.5 text-slate-500 ml-0.5`})]},t):(0,M.jsxs)(`a`,{href:e.url,onClick:t=>{t.preventDefault(),openInBrowser(e.url)},className:`cursor-pointer inline-flex items-center gap-1 bg-purple-950/20 hover:bg-purple-900/40 border border-purple-500/25 hover:border-purple-500/45 text-purple-300 rounded-lg px-2 py-0.5 text-[11px] font-black transition-all hover:scale-[1.02]`,title:`Đi tới ${e.site} gốc`,children:[(0,M.jsx)(`span`,{className:`w-3 h-3 rounded flex items-center justify-center text-[8px] font-extrabold ${n}`,children:e.site[0]}),e.site,(0,M.jsx)(r,{className:`w-2.5 h-2.5 text-purple-400 ml-0.5`})]},t)})]}),(0,M.jsxs)(`div`,{className:`flex items-center gap-1 bg-[#12122b]/50 border border-purple-500/10 p-1 rounded-xl shadow-md`,children:[(0,M.jsxs)(`button`,{onClick:he,className:`inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-bold transition-all ${Z?`bg-purple-600 border border-purple-600 text-white shadow shadow-purple-500/25`:`border-transparent text-slate-300 hover:bg-white/5`}`,children:[Z?(0,M.jsx)(v,{className:`w-4 h-4 animate-pulse`}):(0,M.jsx)(w,{className:`w-4 h-4`}),(0,M.jsx)(`span`,{children:Z?_.reader?.pauseBtn||`Dừng đọc AI`:_.reader?.playBtn||`Đọc Audio AI`})]}),G&&(0,M.jsxs)(M.Fragment,{children:[(0,M.jsx)(`button`,{onClick:()=>{if(String(G.book?.id)===String(t))if(G.chapterIdx!==parseInt(i))b(`/book/${t}/read/${G.chapterIdx}`);else{let e=document.getElementById(`active-tts-sentence`);e&&e.scrollIntoView({behavior:`smooth`,block:`center`})}else alert(`Đang phát ở sách khác: `+(G.book?.title||`Không rõ`))},className:`p-1.5 rounded-lg text-slate-300 hover:bg-white/5 hover:text-white transition-all`,title:`Quay lại vị trí/chương đang đọc`,children:(0,M.jsx)(e,{className:`w-4 h-4`})}),(0,M.jsx)(`button`,{onClick:ue,className:`p-1.5 rounded-lg transition-all ${q?`text-purple-400 bg-purple-500/10`:`text-slate-500 hover:text-slate-300`}`,title:q?`Tắt tự động cuộn trang`:`Bật tự động cuộn trang`,children:(0,M.jsx)(l,{className:`w-4 h-4`})})]})]})]}),H&&(0,M.jsxs)(`div`,{className:`relative z-35 p-3.5 bg-[#0c0d1e]/98 border border-purple-500/45 rounded-xl shadow-2xl backdrop-blur-xl text-slate-200 text-xs space-y-3 max-w-md animate-slideUp`,children:[(0,M.jsxs)(`div`,{className:`flex justify-between items-center border-b border-purple-500/10 pb-1.5`,children:[(0,M.jsxs)(`span`,{className:`font-extrabold text-[11px] uppercase tracking-wider text-purple-300 flex items-center gap-1`,children:[(0,M.jsx)(a,{className:`w-3.5 h-3.5 text-purple-400`}),` Tìm kiếm nguồn `,H.site]}),(0,M.jsx)(`button`,{onClick:e=>{e.stopPropagation(),U(null)},className:`p-0.5 hover:bg-white/5 rounded-md text-slate-400 hover:text-white transition-colors`,children:(0,M.jsx)(S,{className:`w-3.5 h-3.5`})})]}),(0,M.jsxs)(`div`,{className:`space-y-1`,children:[(0,M.jsx)(`label`,{className:`text-[9px] text-slate-500 font-bold block uppercase tracking-wider`,children:`Từ khóa phụ bổ sung`}),(0,M.jsx)(`input`,{type:`text`,value:W,onChange:e=>ae(e.target.value),placeholder:`miễn phí, mới nhất, raw...`,className:`w-full px-2.5 py-1.5 bg-[#080814] border border-[#1f1f3a] rounded-lg text-slate-200 outline-none focus:border-purple-500/70 transition-colors text-[10px]`})]}),(0,M.jsxs)(`div`,{className:`grid grid-cols-1 gap-1.5`,children:[(0,M.jsxs)(`button`,{onClick:()=>$(`google`,`vi`),className:`w-full flex items-center justify-between px-2.5 py-1.5 bg-purple-600 hover:bg-purple-500 text-white rounded-lg text-[10px] font-bold transition-all`,children:[(0,M.jsx)(`span`,{className:`flex items-center gap-1.5`,children:`🇻🇳 Tìm Google Tiếng Việt`}),(0,M.jsx)(`span`,{className:`text-[9px] text-purple-200 italic font-medium`,children:`Tên dịch + Tác giả Việt`})]}),(0,M.jsxs)(`button`,{onClick:()=>$(`google`,`zh`),className:`w-full flex items-center justify-between px-2.5 py-1.5 bg-blue-600 hover:bg-blue-500 text-white rounded-lg text-[10px] font-bold transition-all`,children:[(0,M.jsx)(`span`,{className:`flex items-center gap-1.5`,children:`🇨🇳 Tìm Google Tiếng Trung`}),(0,M.jsx)(`span`,{className:`text-[9px] text-blue-200 italic font-medium`,children:`Tên gốc + Tác giả Trung`})]}),(0,M.jsxs)(`button`,{onClick:()=>$(`baidu`,`zh`),className:`w-full flex items-center justify-between px-2.5 py-1.5 bg-[#121225] border border-[#1f1f3a] hover:bg-slate-800 text-slate-300 rounded-lg text-[10px] font-bold transition-all`,children:[(0,M.jsx)(`span`,{className:`flex items-center gap-1.5`,children:`🇨🇳 Tìm Baidu Tiếng Trung (Raw)`}),(0,M.jsx)(`span`,{className:`text-[9px] text-slate-500 italic font-medium`,children:`Tên gốc + Tác giả Trung`})]})]})]})]}),(0,M.jsx)(`h2`,{className:`text-xl md:text-2xl font-black mb-2 border-b border-slate-500/10 pb-4 text-center`,children:P}),Q()&&(0,M.jsxs)(`div`,{className:`text-center text-[10px] text-slate-400 mb-6 flex justify-center items-center gap-2`,children:[(0,M.jsxs)(`span`,{children:[`⏱️ Thời gian đọc: ~`,Q().minutes,` phút `,Q().seconds,` giây (tốc độ `,X.toFixed(1),`x)`]}),(0,M.jsx)(`span`,{children:`•`}),(0,M.jsxs)(`span`,{children:[`📝 `,Q().wordCount,` từ`]})]}),ie&&(0,M.jsx)(`div`,{className:`text-slate-400 text-xs text-center py-2 animate-pulse`,children:_.comparingText||`Đang đồng bộ hóa bản dịch...`}),(0,M.jsx)(`div`,{style:{fontSize:`${s}px`},className:`whitespace-pre-line break-words text-justify select-text focus:outline-none ${ye()} ${be()}`,children:ve()}),(0,M.jsx)(O,{slot:`reader-bottom`}),(0,M.jsxs)(`div`,{className:`flex justify-between items-center gap-4 pt-12 border-t border-slate-500/10 reader-overlay`,children:[(0,M.jsxs)(`button`,{onClick:pe,disabled:parseInt(i)<=1,className:`flex items-center gap-1.5 px-5 py-3 border border-slate-500/20 rounded-xl hover:bg-white/5 disabled:opacity-40 disabled:cursor-not-allowed text-xs font-bold transition-all`,children:[(0,M.jsx)(T,{className:`w-4 h-4`}),` `,_.reader?.prevChapter||`Chương trước`]}),(0,M.jsxs)(`button`,{onClick:me,disabled:parseInt(i)>=50,className:`flex items-center gap-1.5 px-5 py-3 bg-gradient-to-r from-brand-500 to-purple-600 text-white rounded-xl hover:brightness-105 disabled:opacity-40 disabled:cursor-not-allowed text-xs font-bold transition-all`,children:[_.reader?.nextChapter||`Chương sau`,` `,(0,M.jsx)(g,{className:`w-4 h-4`})]})]})]})})}export{P as default}; \ No newline at end of file diff --git a/frontend-web/dist/assets/Sects-X0poZC74.js b/frontend-web/dist/assets/Sects-X0poZC74.js new file mode 100644 index 0000000000000000000000000000000000000000..190a173e6b85c2069299514a9a771bce65084117 --- /dev/null +++ b/frontend-web/dist/assets/Sects-X0poZC74.js @@ -0,0 +1 @@ +import{t as e}from"./award-CKCOPIfL.js";import{c as t,f as n,i as r,o as ee,p as te,t as ne,u as re,y as ie}from"./MainLayout-COiTxmNr.js";import{a as ae,n as oe,o as se}from"./square-DZKJ0QGR.js";import{n as ce,t as le}from"./shield-LuyExdkp.js";import{t as i}from"./plus-CSQqtn3N.js";import{t as ue}from"./trash-2-DDhTqVwA.js";import{C as de,D as fe,F as a,M as o,S as pe,b as s,c as me,j as c,o as l,w as u,y as he}from"./index-yRoRoI6u.js";var ge=s(`arrow-right`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`m12 5 7 7-7 7`,key:`xquz4c`}]]),_e=s(`message-circle`,[[`path`,{d:`M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719`,key:`1sd12s`}]]),ve=s(`shield-check`,[[`path`,{d:`M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z`,key:`oel41y`}],[`path`,{d:`m9 12 2 2 4-4`,key:`dzmm74`}]]),ye=s(`square-pen`,[[`path`,{d:`M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7`,key:`1m0v6g`}],[`path`,{d:`M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z`,key:`ohrbg2`}]]),be=s(`user-minus`,[[`path`,{d:`M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2`,key:`1yyitq`}],[`circle`,{cx:`9`,cy:`7`,r:`4`,key:`nufk8`}],[`line`,{x1:`22`,x2:`16`,y1:`11`,y2:`11`,key:`1shjgl`}]]),d=a(c(),1),f=o(),p={leader:1,vice_leader:2,elder:3,inner_disciple:4,member:5},m={leader:`Tông chủ`,vice_leader:`Phó Tông chủ`,elder:`Trưởng lão`,inner_disciple:`Nội môn đệ tử`,member:`Ngoại môn đệ tử`};function h(){let{user:a}=de(),{lang:o}=pe(),s=fe(),[c,h]=(0,d.useState)(!1),[g,_]=(0,d.useState)(null),[v,xe]=(0,d.useState)([]),[y,Se]=(0,d.useState)([]),[b,x]=(0,d.useState)(`info`),[Ce,we]=(0,d.useState)(``),[S,Te]=(0,d.useState)(null),[Ee,C]=(0,d.useState)(!1),[w,De]=(0,d.useState)(``),[Oe,ke]=(0,d.useState)(``),[Ae,je]=(0,d.useState)(`purple`),[T,Me]=(0,d.useState)(50),[Ne,Pe]=(0,d.useState)(``),[E,Fe]=(0,d.useState)(!1),[D,O]=(0,d.useState)(`general`),[k,A]=(0,d.useState)(null),[j,M]=(0,d.useState)(null),[N,Ie]=(0,d.useState)([]),[P,F]=(0,d.useState)(``),[Le,Re]=(0,d.useState)(!1),[ze,Be]=(0,d.useState)([]),[Ve,I]=(0,d.useState)(!1),[L,He]=(0,d.useState)(``),[R,Ue]=(0,d.useState)([]),[We,Ge]=(0,d.useState)(!1),[z,Ke]=(0,d.useState)(null),[B,qe]=(0,d.useState)([]),[Je,Ye]=(0,d.useState)([]),[Xe,Ze]=(0,d.useState)([]),[Qe,V]=(0,d.useState)(!1),[$e,et]=(0,d.useState)(!0),[H,U]=(0,d.useState)(!1),[tt,nt]=(0,d.useState)(``),[rt,it]=(0,d.useState)(``),W=(0,d.useRef)(null),G=(0,d.useRef)(null);(0,d.useEffect)(()=>{a||s(`/`)},[a,s]);let K=async()=>{et(!0);try{let e=await u.get(`/api/sects/my-sect`);e.data&&e.data.in_sect?(h(!0),_(e.data),Pe(e.data.sect.announcement||``),b===`requests`&&[`leader`,`vice_leader`,`elder`].includes(e.data.role)&&ot(),b===`library`&&J(),b===`chat`&&Y()):(h(!1),_(null),q())}catch(e){console.error(`Lỗi khi tải thông tin Tông môn:`,e)}finally{et(!1)}},q=async()=>{try{let e=await u.get(`/api/sects/search`,{params:{q:Ce}});e.data&&e.data.sects&&xe(e.data.sects);let t=await u.get(`/api/sects/list`);t.data&&Se(t.data.pending_requests||[])}catch(e){console.error(`Lỗi tìm kiếm tông môn:`,e)}},at=async e=>{U(!0);try{let t=await u.get(`/api/sects/${e}`);t.data&&(Te(t.data),C(!0))}catch{Z(`Không thể tải thông tin tông môn chi tiết`)}finally{U(!1)}},ot=async()=>{try{let e=await u.get(`/api/sects/requests/list`);e.data&&e.data.requests&&qe(e.data.requests)}catch(e){console.error(e)}},J=async()=>{try{let e=await u.get(`/api/sects/library/list`);e.data&&e.data.books&&Ye(e.data.books)}catch(e){console.error(e)}},st=async()=>{try{let e=await u.get(`/api/bookshelf`);e.data&&Ze(e.data)}catch(e){console.error(e)}},Y=async()=>{try{let e=await u.get(`/api/sects/chat/groups`);e.data&&e.data.groups&&Be(e.data.groups)}catch(e){console.error(e)}},ct=async()=>{try{let e={chat_type:D};if(D===`group`&&k)e.group_id=k;else if(D===`direct`&&j)e.target_id=j.user_id||j.id;else if(D!==`general`)return;let t=await u.get(`/api/sects/chat/history`,{params:e});t.data&&t.data.messages&&Ie(t.data.messages)}catch(e){console.error(e)}};(0,d.useEffect)(()=>{K()},[b]),(0,d.useEffect)(()=>(c&&b===`chat`?(ct(),G.current=setInterval(()=>{document.hidden||ct()},5e3)):G.current&&clearInterval(G.current),()=>{G.current&&clearInterval(G.current)}),[c,b,D,k,j]),(0,d.useEffect)(()=>{if(b===`chat`&&W.current){let e=W.current.parentElement;e&&e.scrollTo({top:e.scrollHeight,behavior:`smooth`})}},[N,b]);let X=e=>{it(e),setTimeout(()=>it(``),5e3)},Z=e=>{nt(e),setTimeout(()=>nt(``),5e3)},lt=async e=>{if(e.preventDefault(),w.trim()){U(!0);try{let e=await u.post(`/api/sects/create`,{name:w.trim(),slogan:Oe.trim(),badge:Ae});e.data&&e.data.success&&(X(e.data.message),De(``),ke(``),x(`info`),await K())}catch(e){Z(e.response?.data?.error||`Không thể thành lập Tông môn`)}finally{U(!1)}}},ut=async e=>{U(!0);try{let t=await u.post(`/api/sects/join`,{sect_id:e});t.data&&t.data.success&&(X(t.data.message),Se(t=>[...t,e]),C(!1))}catch(e){Z(e.response?.data?.error||`Gia nhập tông môn thất bại`)}finally{U(!1)}},dt=async()=>{let e=g?.role===`leader`?`Bạn là Tông chủ, rời đi sẽ giải tán Tông môn và xóa toàn bộ dữ liệu. Bạn chắc chắn chứ?`:`Bạn có chắc chắn muốn rời khỏi Tông môn này không?`;if(window.confirm(e)){U(!0);try{let e=await u.post(`/api/sects/leave`);e.data&&e.data.success&&(X(e.data.message),h(!1),_(null),await K())}catch(e){Z(e.response?.data?.error||`Không thể rời tông môn`)}finally{U(!1)}}},ft=async e=>{if(e.preventDefault(),!(T<=0)){U(!0);try{let e=await u.post(`/api/sects/contribute`,{amount:T});if(e.data&&e.data.success){X(e.data.message);let t=await u.get(`/api/sects/my-sect`);t.data&&_(t.data)}}catch(e){Z(e.response?.data?.error||`Cống hiến thất bại`)}finally{U(!1)}}},pt=async()=>{U(!0);try{let e=await u.post(`/api/sects/announcement`,{announcement:Ne});if(e.data&&e.data.success){X(e.data.message),Fe(!1);let t=await u.get(`/api/sects/my-sect`);t.data&&_(t.data)}}catch(e){Z(e.response?.data?.error||`Cập nhật thông cáo thất bại`)}finally{U(!1)}},mt=async(e,t)=>{U(!0);try{let n=await u.post(`/api/sects/promote/rank`,{user_id:e,role:t});if(n.data&&n.data.success){X(n.data.message);let e=await u.get(`/api/sects/my-sect`);e.data&&_(e.data)}}catch(e){Z(e.response?.data?.error||`Thăng/Giáng chức thất bại`)}finally{U(!1)}},ht=async(e,t)=>{if(window.confirm(`Bạn có chắc chắn muốn trục xuất đệ tử ${t} khỏi tông môn?`)){U(!0);try{let t=await u.post(`/api/sects/kick`,{user_id:e});if(t.data&&t.data.success){X(t.data.message);let e=await u.get(`/api/sects/my-sect`);e.data&&_(e.data)}}catch(e){Z(e.response?.data?.error||`Trục xuất thất bại`)}finally{U(!1)}}},gt=async(e,t)=>{U(!0);try{let n=await u.post(`/api/sects/requests/respond`,{request_id:e,action:t});if(n.data&&n.data.success){X(n.data.message),await ot();let e=await u.get(`/api/sects/my-sect`);e.data&&_(e.data)}}catch(e){Z(e.response?.data?.error||`Xử lý yêu cầu thất bại`)}finally{U(!1)}},_t=async e=>{U(!0);try{let t=await u.post(`/api/sects/library/add`,{book_id:e});if(t.data&&t.data.success){X(t.data.message),V(!1),await J();let e=await u.get(`/api/sects/my-sect`);e.data&&_(e.data)}}catch(e){Z(e.response?.data?.error||`Đóng góp truyện thất bại`)}finally{U(!1)}},vt=async(e,t)=>{if(window.confirm(`Bạn có chắc chắn muốn gỡ truyện '${t}' ra khỏi thư viện Tông môn?`)){U(!0);try{let t=await u.post(`/api/sects/library/remove`,{book_id:e});t.data&&t.data.success&&(X(t.data.message),await J())}catch(e){Z(e.response?.data?.error||`Gỡ truyện thất bại`)}finally{U(!1)}}},yt=async e=>{if(e.preventDefault(),!P.trim())return;let t=P.trim();F(``),Re(!0);try{let e={message:t,chat_type:D};D===`group`&&(e.group_id=k),D===`direct`&&(e.target_id=j.user_id||j.id),await u.post(`/api/sects/chat/send`,e),await ct()}catch{Z(`Gửi tin nhắn thất bại`),F(t)}finally{Re(!1)}},bt=async e=>{if(e.preventDefault(),!(!L.trim()||R.length===0)){U(!0);try{let e=await u.post(`/api/sects/chat/groups/create`,{name:L.trim(),members:[a.id,...R]});e.data&&e.data.group_id&&(X(`Nhóm chat '${L}' được thành lập!`),I(!1),He(``),Ue([]),await Y(),O(`group`),A(e.data.group_id))}catch(e){Z(e.response?.data?.error||`Không thể tạo nhóm chat nhỏ`)}finally{U(!1)}}},xt=async e=>{U(!0);try{let t=await u.get(`/api/sects/chat/groups/${e}`);t.data&&(Ke(t.data),Ge(!0))}catch{Z(`Không thể xem thông tin nhóm chat nhỏ`)}finally{U(!1)}},St=async e=>{try{let t=await u.post(`/api/sects/chat/groups/${z.group.id}/members/add`,{user_ids:[e]});t.data&&t.data.success&&(xt(z.group.id),Y())}catch{Z(`Không thể thêm thành viên`)}},Ct=async e=>{try{let t=await u.post(`/api/sects/chat/groups/${z.group.id}/members/remove`,{user_id:e});t.data&&t.data.success&&(xt(z.group.id),Y())}catch{Z(`Không thể loại bỏ thành viên`)}},wt=e=>{Ue(t=>t.includes(e)?t.filter(t=>t!==e):[...t,e])},Q=(e,t=`w-10 h-10`)=>{let n={purple:`from-purple-600 to-indigo-700 ring-purple-500/30`,emerald:`from-emerald-500 to-teal-700 ring-emerald-500/30`,rose:`from-rose-500 to-red-700 ring-rose-500/30`,amber:`from-amber-500 to-orange-600 ring-amber-500/30`,blue:`from-blue-600 to-cyan-700 ring-blue-500/30`};return(0,f.jsx)(`div`,{className:`${t} rounded-2xl bg-gradient-to-br ${n[e]||n.purple} flex items-center justify-center ring-4 shadow-lg shrink-0`,children:(0,f.jsx)(le,{className:`w-1/2 h-1/2 text-white`})})},Tt=e=>{let t={leader:`bg-amber-500/10 border-amber-500/30 text-amber-400`,vice_leader:`bg-cyan-500/10 border-cyan-500/30 text-cyan-400`,elder:`bg-purple-500/10 border-purple-500/30 text-purple-400`,inner_disciple:`bg-emerald-500/10 border-emerald-500/30 text-emerald-400`,member:`bg-slate-800 border-slate-700 text-slate-400`};return t[e]||t.member},$=g&&[`leader`,`vice_leader`,`elder`].includes(g.role);return(0,f.jsx)(ne,{children:(0,f.jsxs)(`div`,{className:`max-w-[1400px] mx-auto px-4 py-8 md:py-12 min-h-[calc(100vh-80px)] flex flex-col justify-start`,children:[(0,f.jsxs)(`div`,{className:`bg-gradient-to-r from-purple-950/20 via-indigo-950/20 to-teal-950/15 border border-[#1f1f3a] rounded-3xl p-6 md:p-8 flex flex-col md:flex-row items-center justify-between gap-6 mb-8 shadow-xl`,children:[(0,f.jsxs)(`div`,{className:`space-y-2 text-center md:text-left`,children:[(0,f.jsxs)(`h2`,{className:`text-xl md:text-2xl font-black text-white flex items-center justify-center md:justify-start gap-2.5`,children:[(0,f.jsx)(t,{className:`w-6 h-6 text-purple-400 animate-pulse`}),o===`vi`?`Hệ thống Tông Môn & Liên Minh`:`Sects & Alliances`]}),(0,f.jsx)(`p`,{className:`text-xs text-slate-400 max-w-xl leading-relaxed`,children:o===`vi`?`Tìm kiếm và bái kiến các tông môn danh tiếng, hoặc sáng lập một đạo thống tu tiên riêng. Phân cấp đệ tử rõ ràng, chat nhóm nhỏ cơ mật và trao đổi công pháp võ học.`:`Search and join legendary sects, or establish your own lineage. Detailed rank promotions, private sub-group chats, and share library books.`})]}),c&&(0,f.jsxs)(`button`,{onClick:dt,className:`px-5 py-2.5 bg-rose-500/10 hover:bg-rose-500 text-rose-300 hover:text-white rounded-2xl border border-rose-500/20 hover:border-transparent transition-all flex items-center gap-2 text-xs font-bold shrink-0 shadow-md`,children:[(0,f.jsx)(te,{className:`w-4 h-4`}),(0,f.jsx)(`span`,{children:g?.role===`leader`?`Giải tán Tông Môn`:`Rời khỏi Tông Môn`})]})]}),rt&&(0,f.jsxs)(`div`,{className:`mb-6 p-4 bg-emerald-950/30 border border-emerald-500/30 rounded-2xl text-emerald-400 text-xs font-bold shadow-md`,children:[`🎉 `,rt]}),tt&&(0,f.jsxs)(`div`,{className:`mb-6 p-4 bg-rose-950/30 border border-rose-500/30 rounded-2xl text-rose-400 text-xs font-bold shadow-md`,children:[`⚠️ `,tt]}),$e?(0,f.jsxs)(`div`,{className:`flex-1 flex flex-col items-center justify-center py-32 space-y-4`,children:[(0,f.jsx)(`div`,{className:`w-8 h-8 border-4 border-purple-500 border-t-transparent rounded-full animate-spin`}),(0,f.jsx)(`span`,{className:`text-xs text-slate-500`,children:`Đang tìm kiếm thiên cơ...`})]}):c?(0,f.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#1f1f3a] rounded-3xl overflow-hidden shadow-2xl flex flex-col md:flex-row flex-1 min-h-[650px] backdrop-blur-xl`,children:[(0,f.jsxs)(`div`,{className:`w-full md:w-64 border-b md:border-b-0 md:border-r border-[#1f1f3a] bg-[#0b0b14]/50 flex flex-col shrink-0`,children:[(0,f.jsxs)(`div`,{className:`p-5 border-b border-[#1f1f3a] flex items-center gap-3 bg-[#080814]/30`,children:[Q(g.sect.badge,`w-11 h-11`),(0,f.jsxs)(`div`,{className:`min-w-0`,children:[(0,f.jsx)(`h4`,{className:`font-extrabold text-sm text-slate-100 truncate`,children:g.sect.name}),(0,f.jsxs)(`div`,{className:`flex items-center gap-1.5 mt-0.5`,children:[(0,f.jsxs)(`span`,{className:`px-1.5 py-0.5 bg-teal-500/10 border border-teal-500/20 text-teal-400 rounded-full text-[8px] font-black`,children:[`Cấp `,g.sect.level]}),(0,f.jsxs)(`span`,{className:`text-[9px] text-slate-500 font-mono`,children:[`#`,g.sect.id]})]})]})]}),(0,f.jsxs)(`div`,{className:`p-3 space-y-1`,children:[(0,f.jsxs)(`button`,{onClick:()=>x(`info`),className:`w-full px-4 py-3 rounded-xl text-xs font-black transition-all flex items-center gap-2.5 ${b===`info`?`bg-purple-600/20 border border-purple-500/30 text-white`:`text-slate-400 hover:text-white hover:bg-white/5`}`,children:[(0,f.jsx)(e,{className:`w-4 h-4 text-purple-400`}),(0,f.jsx)(`span`,{children:`Tổng quan tông môn`})]}),(0,f.jsxs)(`button`,{onClick:()=>x(`disciples`),className:`w-full px-4 py-3 rounded-xl text-xs font-black transition-all flex items-center gap-2.5 ${b===`disciples`?`bg-purple-600/20 border border-purple-500/30 text-white`:`text-slate-400 hover:text-white hover:bg-white/5`}`,children:[(0,f.jsx)(r,{className:`w-4 h-4 text-teal-400`}),(0,f.jsx)(`span`,{children:`Môn đồ & Chức vị`})]}),$&&(0,f.jsxs)(`button`,{onClick:()=>x(`requests`),className:`w-full px-4 py-3 rounded-xl text-xs font-black transition-all flex items-center justify-between ${b===`requests`?`bg-purple-600/20 border border-purple-500/30 text-white`:`text-slate-400 hover:text-white hover:bg-white/5`}`,children:[(0,f.jsxs)(`div`,{className:`flex items-center gap-2.5`,children:[(0,f.jsx)(ve,{className:`w-4 h-4 text-amber-400`}),(0,f.jsx)(`span`,{children:`Duyệt môn đồ`})]}),B.length>0&&(0,f.jsx)(`span`,{className:`px-1.5 py-0.5 bg-amber-500 text-black text-[8px] font-black rounded-md animate-pulse`,children:B.length})]}),(0,f.jsxs)(`button`,{onClick:()=>x(`library`),className:`w-full px-4 py-3 rounded-xl text-xs font-black transition-all flex items-center gap-2.5 ${b===`library`?`bg-purple-600/20 border border-purple-500/30 text-white`:`text-slate-400 hover:text-white hover:bg-white/5`}`,children:[(0,f.jsx)(ie,{className:`w-4 h-4 text-blue-400`}),(0,f.jsx)(`span`,{children:`Thư viện Tông Môn`})]}),(0,f.jsxs)(`button`,{onClick:()=>x(`chat`),className:`w-full px-4 py-3 rounded-xl text-xs font-black transition-all flex items-center gap-2.5 ${b===`chat`?`bg-purple-600/20 border border-purple-500/30 text-white`:`text-slate-400 hover:text-white hover:bg-white/5`}`,children:[(0,f.jsx)(n,{className:`w-4 h-4 text-pink-400`}),(0,f.jsx)(`span`,{children:`Phòng đàm đạo (Multi)`})]}),(0,f.jsxs)(`button`,{onClick:()=>x(`contribute`),className:`w-full px-4 py-3 rounded-xl text-xs font-black transition-all flex items-center gap-2.5 ${b===`contribute`?`bg-purple-600/20 border border-purple-500/30 text-white`:`text-slate-400 hover:text-white hover:bg-white/5`}`,children:[(0,f.jsx)(ce,{className:`w-4 h-4 text-amber-400`}),(0,f.jsx)(`span`,{children:`Dâng nạp linh thạch`})]})]}),(0,f.jsxs)(`div`,{className:`mt-auto p-4 border-t border-[#1f1f3a] bg-[#05050a]/40 space-y-2`,children:[(0,f.jsxs)(`div`,{className:`flex justify-between text-[10px]`,children:[(0,f.jsx)(`span`,{className:`text-slate-500`,children:`Chức vị của bạn:`}),(0,f.jsx)(`span`,{className:`font-bold text-purple-400 uppercase tracking-wider`,children:m[g.role]||`Môn đồ`})]}),(0,f.jsxs)(`div`,{className:`flex justify-between text-[10px]`,children:[(0,f.jsx)(`span`,{className:`text-slate-500`,children:`Cống hiến riêng:`}),(0,f.jsxs)(`span`,{className:`font-bold text-amber-400`,children:[g.my_contribution,` linh thạch`]})]})]})]}),(0,f.jsxs)(`div`,{className:`flex-1 flex flex-col bg-[#080814]/30 min-w-0`,children:[b===`info`&&(0,f.jsxs)(`div`,{className:`p-6 space-y-6`,children:[(0,f.jsxs)(`div`,{className:`grid grid-cols-2 sm:grid-cols-4 gap-4`,children:[(0,f.jsxs)(`div`,{className:`bg-[#121225]/40 border border-[#1f1f3a] p-4 rounded-2xl text-center`,children:[(0,f.jsx)(`span`,{className:`text-[9px] text-slate-500 font-bold block uppercase tracking-wider`,children:`Cấp Tông Môn`}),(0,f.jsx)(`span`,{className:`text-lg font-black text-white block mt-1`,children:g.sect.level})]}),(0,f.jsxs)(`div`,{className:`bg-[#121225]/40 border border-[#1f1f3a] p-4 rounded-2xl text-center`,children:[(0,f.jsx)(`span`,{className:`text-[9px] text-slate-500 font-bold block uppercase tracking-wider`,children:`Tổng cống hiến`}),(0,f.jsx)(`span`,{className:`text-lg font-black text-amber-400 block mt-1`,children:g.sect.contribution})]}),(0,f.jsxs)(`div`,{className:`bg-[#121225]/40 border border-[#1f1f3a] p-4 rounded-2xl text-center`,children:[(0,f.jsx)(`span`,{className:`text-[9px] text-slate-500 font-bold block uppercase tracking-wider`,children:`Môn đồ hiện tại`}),(0,f.jsx)(`span`,{className:`text-lg font-black text-purple-400 block mt-1`,children:g.members.length})]}),(0,f.jsxs)(`div`,{className:`bg-[#121225]/40 border border-[#1f1f3a] p-4 rounded-2xl text-center`,children:[(0,f.jsx)(`span`,{className:`text-[9px] text-slate-500 font-bold block uppercase tracking-wider`,children:`Tông chủ`}),(0,f.jsx)(`span`,{className:`text-xs font-black text-slate-300 block truncate mt-2`,children:g.sect.leader_name})]})]}),(0,f.jsxs)(`div`,{className:`bg-[#121225]/40 border border-[#1f1f3a] p-5 rounded-3xl space-y-1`,children:[(0,f.jsx)(`span`,{className:`text-[9px] text-slate-500 font-bold uppercase tracking-wider`,children:`Mục tiêu tông môn`}),(0,f.jsxs)(`p`,{className:`text-xs text-slate-300 italic`,children:[`"`,g.sect.slogan||`Chưa thiết lập.`,`"`]})]}),(0,f.jsxs)(`div`,{className:`bg-[#121225]/40 border border-[#1f1f3a] p-5 rounded-3xl space-y-4`,children:[(0,f.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,f.jsx)(`span`,{className:`text-[9px] text-slate-500 font-bold uppercase tracking-wider`,children:`Thông cáo tông môn`}),$&&(0,f.jsxs)(`button`,{onClick:()=>Fe(!E),className:`text-[10px] text-purple-400 hover:text-white flex items-center gap-1`,children:[(0,f.jsx)(ye,{className:`w-3.5 h-3.5`}),(0,f.jsx)(`span`,{children:E?`Hủy`:`Chỉnh sửa`})]})]}),E?(0,f.jsxs)(`div`,{className:`space-y-3`,children:[(0,f.jsx)(`textarea`,{rows:4,value:Ne,onChange:e=>Pe(e.target.value),className:`w-full p-3 bg-[#05050a] border border-[#1f1f3a] focus:border-purple-500 rounded-xl text-xs text-white outline-none resize-none`}),(0,f.jsx)(`button`,{onClick:pt,disabled:H,className:`px-4 py-2 bg-purple-600 hover:bg-purple-500 text-white rounded-xl text-xs font-bold`,children:`Lưu thông cáo`})]}):(0,f.jsx)(`div`,{className:`p-4 bg-purple-950/10 border border-purple-500/10 rounded-2xl`,children:(0,f.jsx)(`p`,{className:`text-xs text-slate-200 whitespace-pre-wrap leading-relaxed`,children:g.sect.announcement||`Hôm nay trời quang mây tạnh, các đệ tử nỗ lực tu luyện đọc truyện.`})})]})]}),b===`disciples`&&(0,f.jsxs)(`div`,{className:`p-6 space-y-4`,children:[(0,f.jsxs)(`h4`,{className:`text-xs font-black text-slate-300 uppercase tracking-wider`,children:[`Danh sách đệ tử (`,g.members.length,`)`]}),(0,f.jsx)(`div`,{className:`border border-[#1f1f3a] rounded-2xl overflow-hidden divide-y divide-[#1f1f3a]`,children:g.members.map(e=>{let t=e.user_id===a.id,n=p[g.role]||99,r=n<(p[e.role]||99)&&!t;return(0,f.jsxs)(`div`,{className:`p-4 flex items-center justify-between gap-4 bg-[#121225]/20 hover:bg-[#121225]/40 transition-colors`,children:[(0,f.jsxs)(`div`,{className:`flex items-center gap-3 min-w-0`,children:[e.avatar?(0,f.jsx)(`img`,{src:e.avatar,className:`w-9 h-9 rounded-full object-cover ring-2 ring-purple-500/10`,alt:`avatar`}):(0,f.jsx)(`div`,{className:`w-9 h-9 rounded-full bg-gradient-to-br from-[#7c3aed] to-[#4f46e5] flex items-center justify-center font-black text-xs text-white shrink-0`,children:e.username[0].toUpperCase()}),(0,f.jsxs)(`div`,{className:`min-w-0`,children:[(0,f.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,f.jsxs)(`span`,{className:`text-xs font-bold ${t?`text-purple-400`:`text-slate-200`} truncate`,children:[e.username,` `,t&&`(Bạn)`]}),(0,f.jsx)(`span`,{className:`px-2 py-0.5 border text-[8px] font-black rounded-md uppercase tracking-wider ${Tt(e.role)}`,children:m[e.role]||`Môn đồ`})]}),(0,f.jsxs)(`span`,{className:`text-[9px] text-slate-500 block mt-0.5`,children:[`Gia nhập: `,new Date(e.joined_at).toLocaleDateString()]})]})]}),(0,f.jsxs)(`div`,{className:`flex items-center gap-4 shrink-0`,children:[(0,f.jsxs)(`div`,{className:`text-right`,children:[(0,f.jsx)(`span`,{className:`text-[10px] font-bold text-slate-300 block`,children:e.contribution}),(0,f.jsx)(`span`,{className:`text-[8px] text-slate-500 block`,children:`Cống hiến`})]}),r?(0,f.jsxs)(`div`,{className:`flex items-center gap-1.5`,children:[(0,f.jsx)(`select`,{value:e.role,onChange:t=>mt(e.user_id,t.target.value),disabled:H,className:`bg-[#05050a] border border-[#1f1f3a] text-slate-300 text-[10px] font-bold rounded-lg px-2.5 py-1.5 focus:border-purple-500 outline-none cursor-pointer`,children:Object.keys(m).map(e=>{let t=p[e];return e!==`leader`&&t>n?(0,f.jsx)(`option`,{value:e,children:m[e]},e):null})}),(0,f.jsx)(`button`,{onClick:()=>ht(e.user_id,e.username),disabled:H,className:`p-2 bg-rose-500/10 hover:bg-rose-500 text-rose-400 hover:text-white rounded-lg transition-colors border border-rose-500/20`,title:`Trục xuất khỏi tông môn`,children:(0,f.jsx)(ue,{className:`w-3.5 h-3.5`})})]}):!t&&(0,f.jsx)(`button`,{onClick:()=>{O(`direct`),M(e),x(`chat`)},className:`px-3 py-1.5 bg-purple-600/20 hover:bg-purple-600 text-purple-400 hover:text-white border border-purple-500/20 rounded-xl text-[10px] font-bold transition-all`,children:`Nhắn tin`})]})]},e.user_id)})})]}),b===`requests`&&$&&(0,f.jsxs)(`div`,{className:`p-6 space-y-4`,children:[(0,f.jsxs)(`h4`,{className:`text-xs font-black text-slate-300 uppercase tracking-wider`,children:[`Đơn bái kiến đang chờ (`,B.length,`)`]}),B.length===0?(0,f.jsx)(`div`,{className:`text-center py-20 text-xs text-slate-500 border border-dashed border-[#1f1f3a] rounded-3xl bg-[#121225]/20`,children:`Không có đơn bái kiến nào đang chờ.`}):(0,f.jsx)(`div`,{className:`grid gap-3`,children:B.map(e=>(0,f.jsxs)(`div`,{className:`p-4 bg-[#121225]/40 border border-[#1f1f3a] rounded-2xl flex items-center justify-between gap-4`,children:[(0,f.jsxs)(`div`,{className:`flex items-center gap-3`,children:[e.avatar?(0,f.jsx)(`img`,{src:e.avatar,className:`w-8.5 h-8.5 rounded-full object-cover ring-2 ring-purple-500/10`,alt:`avatar`}):(0,f.jsx)(`div`,{className:`w-8.5 h-8.5 rounded-full bg-gradient-to-br from-teal-500 to-indigo-600 flex items-center justify-center font-black text-xs text-white`,children:e.username?e.username[0].toUpperCase():`U`}),(0,f.jsxs)(`div`,{children:[(0,f.jsx)(`span`,{className:`text-xs font-bold text-white block`,children:e.username}),(0,f.jsxs)(`span`,{className:`text-[8px] text-slate-500 block mt-0.5`,children:[`Gửi yêu cầu: `,new Date(e.created_at).toLocaleDateString()]})]})]}),(0,f.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,f.jsxs)(`button`,{onClick:()=>gt(e.id,`approve`),disabled:H,className:`px-3.5 py-2 bg-teal-600 hover:bg-teal-500 text-white rounded-xl text-[10px] font-bold flex items-center gap-1 shadow-md`,children:[(0,f.jsx)(se,{className:`w-3.5 h-3.5`}),`Thu nhận`]}),(0,f.jsxs)(`button`,{onClick:()=>gt(e.id,`reject`),disabled:H,className:`px-3.5 py-2 bg-rose-500/10 hover:bg-rose-500 text-rose-400 hover:text-white rounded-xl text-[10px] font-bold flex items-center gap-1 border border-rose-500/20`,children:[(0,f.jsx)(l,{className:`w-3.5 h-3.5`}),`Từ chối`]})]})]},e.id))})]}),b===`library`&&(0,f.jsxs)(`div`,{className:`p-6 space-y-6`,children:[(0,f.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,f.jsxs)(`div`,{children:[(0,f.jsx)(`h4`,{className:`text-xs font-black text-slate-300 uppercase tracking-wider`,children:`Thư viện chia sẻ Tông môn`}),(0,f.jsx)(`p`,{className:`text-[10px] text-slate-500 mt-1`,children:`Góp ý, lưu truyền các bí tịch / truyện hay trong tông môn.`})]}),(0,f.jsxs)(`button`,{onClick:()=>{st(),V(!0)},className:`px-4 py-2.5 bg-purple-600 hover:bg-purple-500 text-white rounded-2xl text-xs font-bold flex items-center gap-1.5 shadow-md transition-transform active:scale-95`,children:[(0,f.jsx)(i,{className:`w-4 h-4`}),`Hiến sách (+20 cống hiến)`]})]}),Je.length===0?(0,f.jsx)(`div`,{className:`text-center py-24 border border-dashed border-[#1f1f3a] rounded-3xl bg-[#121225]/20 text-xs text-slate-500`,children:`Chưa có sách nào được lưu trữ trong Thư viện. Hãy cống hiến bí tịch đầu tiên!`}):(0,f.jsx)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-4`,children:Je.map(e=>{let t=g?.role===`leader`||g?.role===`vice_leader`||g?.role===`elder`||e.added_by_name===a.username;return(0,f.jsxs)(`div`,{className:`bg-[#121225]/40 border border-[#1f1f3a] rounded-3xl p-4 flex gap-4 hover:border-purple-500/20 transition-all items-start justify-between`,children:[(0,f.jsxs)(`div`,{className:`flex gap-4 min-w-0`,children:[e.cover?(0,f.jsx)(`img`,{src:e.cover,className:`w-16 h-22 object-cover rounded-lg border border-white/5 shrink-0 bg-[#0f0f1a]`,alt:`cover`}):(0,f.jsx)(`div`,{className:`w-16 h-22 rounded-lg bg-[#0f0f1a] border border-white/5 flex items-center justify-center shrink-0 text-slate-600`,children:(0,f.jsx)(ie,{className:`w-6 h-6`})}),(0,f.jsxs)(`div`,{className:`min-w-0 space-y-1`,children:[(0,f.jsx)(`h5`,{onClick:()=>s(`/book/${e.id}`),className:`text-xs font-bold text-slate-100 hover:text-purple-400 transition-colors cursor-pointer truncate`,children:e.title_vietphrase||e.title}),(0,f.jsx)(`p`,{className:`text-[10px] text-slate-400 truncate`,children:e.author}),(0,f.jsxs)(`span`,{className:`text-[8px] text-slate-500 block`,children:[`Hiến tặng: `,(0,f.jsx)(`strong`,{children:e.added_by_name})]})]})]}),(0,f.jsxs)(`div`,{className:`flex flex-col gap-2 shrink-0 items-end`,children:[(0,f.jsxs)(`button`,{onClick:()=>s(`/book/${e.id}`),className:`p-1.5 bg-purple-600/10 hover:bg-purple-600 text-purple-400 hover:text-white rounded-lg transition-colors flex items-center gap-1 text-[9px] font-bold`,children:[(0,f.jsx)(`span`,{children:`Đọc`}),(0,f.jsx)(ae,{className:`w-3.5 h-3.5`})]}),t&&(0,f.jsx)(`button`,{onClick:()=>vt(e.id,e.title_vietphrase||e.title),disabled:H,className:`p-1.5 bg-rose-500/10 hover:bg-rose-500 text-rose-400 hover:text-white rounded-lg transition-colors border border-rose-500/20`,title:`Gỡ khỏi thư viện`,children:(0,f.jsx)(ue,{className:`w-3.5 h-3.5`})})]})]},e.id)})})]}),b===`chat`&&(0,f.jsxs)(`div`,{className:`flex-1 flex flex-col md:flex-row min-h-0 divide-y md:divide-y-0 md:divide-x divide-[#1f1f3a]`,children:[(0,f.jsxs)(`div`,{className:`w-full md:w-56 bg-[#0b0b14]/30 flex flex-col p-4 space-y-4 shrink-0`,children:[(0,f.jsx)(`div`,{className:`flex items-center justify-between`,children:(0,f.jsx)(`span`,{className:`text-[10px] font-black uppercase text-slate-400 tracking-wider`,children:`Kênh đàm đạo`})}),(0,f.jsx)(`div`,{className:`space-y-1`,children:(0,f.jsxs)(`button`,{onClick:()=>{O(`general`),A(null),M(null)},className:`w-full px-3 py-2 rounded-xl text-left text-xs font-bold transition-all flex items-center gap-2 ${D===`general`?`bg-purple-600/10 text-purple-400 border border-purple-500/20`:`text-slate-400 hover:bg-white/5 hover:text-slate-200`}`,children:[(0,f.jsx)(_e,{className:`w-4 h-4 shrink-0`}),(0,f.jsx)(`span`,{className:`truncate`,children:`Đàm đạo chung`})]})}),(0,f.jsxs)(`div`,{className:`space-y-2`,children:[(0,f.jsxs)(`div`,{className:`flex items-center justify-between px-1`,children:[(0,f.jsx)(`span`,{className:`text-[9px] font-black uppercase text-slate-500`,children:`Nhóm nhỏ`}),(0,f.jsx)(`button`,{onClick:()=>I(!0),className:`p-0.5 hover:bg-white/5 rounded text-purple-400`,title:`Tạo nhóm chat nhỏ`,children:(0,f.jsx)(i,{className:`w-3.5 h-3.5`})})]}),(0,f.jsx)(`div`,{className:`space-y-1 max-h-40 overflow-y-auto no-scrollbar`,children:ze.length===0?(0,f.jsx)(`span`,{className:`text-[9px] text-slate-600 italic block px-1`,children:`Chưa có nhóm nào`}):ze.map(e=>(0,f.jsxs)(`div`,{className:`w-full px-3 py-2 rounded-xl transition-all flex items-center justify-between text-xs font-bold ${D===`group`&&k===e.id?`bg-purple-600/10 text-purple-400 border border-purple-500/20`:`text-slate-400 hover:bg-white/5 hover:text-slate-200`}`,children:[(0,f.jsxs)(`button`,{onClick:()=>{O(`group`),A(e.id),M(null)},className:`flex-1 text-left truncate mr-2`,children:[`# `,e.name]}),(0,f.jsx)(`button`,{onClick:()=>xt(e.id),className:`p-0.5 hover:bg-white/10 rounded text-slate-500 hover:text-slate-300`,children:(0,f.jsx)(me,{className:`w-3.5 h-3.5`})})]},e.id))})]}),(0,f.jsxs)(`div`,{className:`space-y-2`,children:[(0,f.jsx)(`span`,{className:`text-[9px] font-black uppercase text-slate-500 px-1 block`,children:`Chat riêng tư`}),j?(0,f.jsxs)(`button`,{onClick:()=>O(`direct`),className:`w-full px-3 py-2 bg-purple-600/10 text-purple-400 border border-purple-500/20 rounded-xl text-left text-xs font-bold transition-all flex items-center gap-2`,children:[(0,f.jsx)(`div`,{className:`w-4 h-4 bg-purple-500/30 rounded-full flex items-center justify-center text-[8px] font-black text-purple-300`,children:j.username[0].toUpperCase()}),(0,f.jsx)(`span`,{className:`truncate`,children:j.username})]}):(0,f.jsx)(`span`,{className:`text-[9px] text-slate-600 italic block px-1`,children:`Chọn đệ tử ở tab Môn đồ để chat riêng`})]})]}),(0,f.jsxs)(`div`,{className:`flex-1 flex flex-col min-w-0`,children:[(0,f.jsx)(`div`,{className:`px-4 py-3 border-b border-[#1f1f3a] bg-[#0b0b14]/30 flex items-center justify-between`,children:(0,f.jsx)(`div`,{className:`min-w-0`,children:(0,f.jsxs)(`span`,{className:`text-xs font-black text-white block`,children:[D===`general`&&`🔊 Kênh đàm đạo chung`,D===`group`&&`👥 Nhóm chat: ${ze.find(e=>e.id===k)?.name||`...`}`,D===`direct`&&`🔒 Chat mật với: ${j?.username}`]})})}),(0,f.jsxs)(`div`,{className:`flex-1 overflow-y-auto p-4 space-y-4 no-scrollbar select-text bg-[#080814]/20`,children:[N.length===0?(0,f.jsx)(`div`,{className:`text-center py-20 text-xs text-slate-600`,children:`Chưa có thảo luận nào.`}):N.map((e,t)=>{let n=e.sender_id===a.id;return(0,f.jsxs)(`div`,{className:`flex ${n?`justify-end`:`justify-start`} gap-2`,children:[!n&&(0,f.jsx)(`div`,{className:`shrink-0 mt-0.5`,children:e.sender_avatar?(0,f.jsx)(`img`,{src:e.sender_avatar,className:`w-7 h-7 rounded-full object-cover ring-1 ring-purple-500/10`,alt:`avatar`}):(0,f.jsx)(`div`,{className:`w-7 h-7 rounded-full bg-purple-600 flex items-center justify-center font-black text-[10px] text-white`,children:e.sender_name?e.sender_name[0].toUpperCase():`U`})}),(0,f.jsxs)(`div`,{className:`max-w-[70%] space-y-1`,children:[!n&&(0,f.jsx)(`span`,{className:`text-[9px] text-slate-500 block px-1`,children:e.sender_name}),(0,f.jsx)(`div`,{className:`p-3 rounded-2xl shadow-md text-xs leading-relaxed whitespace-pre-wrap ${n?`bg-gradient-to-tr from-purple-600 to-indigo-600 text-white rounded-br-none`:`bg-[#121225] border border-[#1f1f3a] text-slate-200 rounded-bl-none`}`,children:e.message}),(0,f.jsx)(`span`,{className:`text-[8px] text-slate-600 block ${n?`text-right`:`text-left`}`,children:new Date(e.created_at).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`})})]})]},e.id||t)}),(0,f.jsx)(`div`,{ref:W})]}),(0,f.jsxs)(`form`,{onSubmit:yt,className:`p-3 border-t border-[#1f1f3a] bg-[#0b0b14]/50 flex items-center gap-2 shrink-0`,children:[(0,f.jsx)(`input`,{type:`text`,placeholder:D===`general`?`Thảo luận công khai...`:D===`group`?`Nhắn vào nhóm nhỏ...`:`Gửi mật thư riêng...`,value:P,onChange:e=>F(e.target.value),className:`flex-1 px-4 py-2.5 bg-[#05050a] border border-[#1f1f3a] rounded-2xl text-xs text-white outline-none focus:border-purple-500 transition-colors`}),(0,f.jsx)(`button`,{type:`submit`,disabled:Le||!P.trim(),className:`p-2.5 bg-purple-600 hover:bg-purple-500 text-white rounded-2xl transition-all shadow-lg active:scale-95 shrink-0`,children:(0,f.jsx)(re,{className:`w-4 h-4`})})]})]})]}),b===`contribute`&&(0,f.jsxs)(`div`,{className:`p-6 space-y-6`,children:[(0,f.jsxs)(`div`,{className:`bg-gradient-to-r from-amber-600/10 to-orange-600/10 border border-amber-500/20 p-5 rounded-3xl space-y-3`,children:[(0,f.jsxs)(`h4`,{className:`text-xs font-black text-amber-400 flex items-center gap-2 uppercase tracking-wider`,children:[(0,f.jsx)(ce,{className:`w-5 h-5 text-amber-500`}),`Quy chế cống hiến linh thạch`]}),(0,f.jsx)(`p`,{className:`text-xs text-slate-400 leading-relaxed`,children:`Nạp Linh thạch giúp gia tăng linh mạch của tông môn, nỗ lực đột phá cấp độ tông môn mới để được giang hồ kính ngưỡng. Cứ tích lũy đủ 1000 điểm cống hiến tông môn sẽ nâng 1 cấp.`})]}),(0,f.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#1f1f3a] rounded-3xl p-6 space-y-4 max-w-md shadow-lg`,children:[(0,f.jsx)(`h5`,{className:`text-xs font-black text-slate-200 uppercase tracking-wider`,children:`Chọn số lượng cống hiến`}),(0,f.jsxs)(`form`,{onSubmit:ft,className:`space-y-4`,children:[(0,f.jsx)(`div`,{className:`grid grid-cols-4 gap-2`,children:[10,50,100,500].map(e=>(0,f.jsx)(`button`,{type:`button`,onClick:()=>Me(e),className:`py-2 rounded-xl text-xs font-bold transition-all border ${T===e?`bg-amber-600/20 border-amber-500 text-amber-300`:`bg-[#05050a] border-[#1f1f3a] text-slate-400 hover:text-white`}`,children:e},e))}),(0,f.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,f.jsx)(`label`,{className:`text-[10px] font-black uppercase text-slate-500`,children:`Số lượng Linh thạch tùy chỉnh`}),(0,f.jsx)(`input`,{type:`number`,min:1,value:T,onChange:e=>Me(Math.max(1,parseInt(e.target.value)||1)),className:`w-full px-4 py-2.5 bg-[#05050a] border border-[#1f1f3a] focus:border-amber-500 rounded-xl text-xs text-white outline-none transition-colors`})]}),(0,f.jsx)(`button`,{type:`submit`,disabled:H,className:`w-full py-3 bg-amber-600 hover:bg-amber-500 text-white rounded-xl text-xs font-black shadow-lg shadow-amber-600/20 transition-all hover:scale-[1.01]`,children:H?`Đang dâng hiến...`:`Dâng hiến`})]})]})]})]})]}):(0,f.jsxs)(`div`,{className:`grid grid-cols-1 lg:grid-cols-3 gap-8 items-start`,children:[(0,f.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#1f1f3a] rounded-3xl p-6 space-y-6 shadow-xl backdrop-blur-xl`,children:[(0,f.jsxs)(`h3`,{className:`text-sm font-black tracking-wider text-purple-400 uppercase flex items-center gap-2`,children:[(0,f.jsx)(i,{className:`w-4 h-4`}),`Sáng lập Tông Môn`]}),(0,f.jsxs)(`form`,{onSubmit:lt,className:`space-y-4`,children:[(0,f.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,f.jsx)(`label`,{className:`text-[10px] font-black uppercase text-slate-400`,children:`Tên Tông Môn`}),(0,f.jsx)(`input`,{type:`text`,placeholder:`ví dụ: Vô Cực Kiếm Tông...`,value:w,onChange:e=>De(e.target.value),className:`w-full px-4 py-2.5 bg-[#05050a] border border-[#1f1f3a] focus:border-purple-500 rounded-xl text-xs text-white outline-none transition-colors`,required:!0})]}),(0,f.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,f.jsx)(`label`,{className:`text-[10px] font-black uppercase text-slate-400`,children:`Tuyên ngôn / Bio`}),(0,f.jsx)(`textarea`,{placeholder:`Tuyên ngôn tông môn...`,value:Oe,onChange:e=>ke(e.target.value),rows:3,className:`w-full px-4 py-2.5 bg-[#05050a] border border-[#1f1f3a] focus:border-purple-500 rounded-xl text-xs text-white outline-none transition-colors resize-none`})]}),(0,f.jsxs)(`div`,{className:`space-y-2`,children:[(0,f.jsx)(`label`,{className:`text-[10px] font-black uppercase text-slate-400 block`,children:`Huy hiệu Tông Môn`}),(0,f.jsx)(`div`,{className:`flex gap-3`,children:[`purple`,`emerald`,`rose`,`amber`,`blue`].map(e=>(0,f.jsx)(`button`,{type:`button`,onClick:()=>je(e),className:`p-1 rounded-2xl border-2 transition-all ${Ae===e?`border-purple-500 scale-105`:`border-transparent opacity-60 hover:opacity-100`}`,children:Q(e,`w-10 h-10`)},e))})]}),(0,f.jsx)(`button`,{type:`submit`,disabled:H||!w.trim(),className:`w-full py-3 bg-purple-600 hover:bg-purple-500 text-white rounded-xl text-xs font-black shadow-lg shadow-purple-600/20 transition-all hover:scale-[1.01]`,children:H?`Đang thỉnh lập...`:`Sáng lập Tông Môn`})]})]}),(0,f.jsxs)(`div`,{className:`lg:col-span-2 space-y-5`,children:[(0,f.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#1f1f3a] rounded-3xl p-4 flex gap-2 shadow-xl backdrop-blur-xl`,children:[(0,f.jsxs)(`div`,{className:`flex-1 bg-[#05050a] border border-[#1f1f3a] focus-within:border-purple-500 rounded-2xl flex items-center px-4 transition-colors`,children:[(0,f.jsx)(oe,{className:`w-4 h-4 text-slate-500 mr-2 shrink-0`}),(0,f.jsx)(`input`,{type:`text`,placeholder:`Tìm kiếm tông môn theo tên, khẩu hiệu hoặc ID...`,value:Ce,onChange:e=>we(e.target.value),onKeyDown:e=>e.key===`Enter`&&q(),className:`w-full py-3 bg-transparent text-xs text-white outline-none`})]}),(0,f.jsx)(`button`,{onClick:q,className:`px-6 py-3 bg-purple-600 hover:bg-purple-500 text-white font-bold rounded-2xl text-xs shadow-md transition-all active:scale-95 shrink-0`,children:`Tìm kiếm`})]}),(0,f.jsxs)(`div`,{className:`space-y-4`,children:[(0,f.jsxs)(`h3`,{className:`text-sm font-black tracking-wider text-teal-400 uppercase flex items-center gap-2`,children:[(0,f.jsx)(e,{className:`w-4 h-4`}),`Danh sách Tông Môn giang hồ (`,v.length,`)`]}),v.length===0?(0,f.jsx)(`div`,{className:`text-center py-24 border border-dashed border-[#1f1f3a] rounded-3xl bg-[#121225]/40 text-xs text-slate-500`,children:`Không tìm thấy tông môn nào. Hãy thay đổi từ khóa hoặc tự lập môn hộ!`}):(0,f.jsx)(`div`,{className:`grid gap-4`,children:v.map(e=>{let t=y.includes(e.id);return(0,f.jsxs)(`div`,{className:`bg-[#121225]/60 border border-[#1f1f3a] hover:border-purple-500/20 rounded-3xl p-5 flex flex-col sm:flex-row items-center justify-between gap-4 transition-all shadow-lg`,children:[(0,f.jsxs)(`div`,{onClick:()=>at(e.id),className:`flex items-center gap-4 text-center sm:text-left flex-col sm:flex-row min-w-0 cursor-pointer group`,children:[Q(e.badge),(0,f.jsxs)(`div`,{className:`min-w-0 space-y-1`,children:[(0,f.jsxs)(`div`,{className:`flex items-center justify-center sm:justify-start gap-2 flex-wrap`,children:[(0,f.jsx)(`span`,{className:`font-extrabold text-sm text-slate-100 group-hover:text-purple-400 transition-colors`,children:e.name}),(0,f.jsxs)(`span`,{className:`px-2 py-0.5 bg-purple-500/10 border border-purple-500/20 text-purple-300 rounded-full text-[9px] font-bold`,children:[`Cấp `,e.level]})]}),(0,f.jsxs)(`p`,{className:`text-xs text-slate-400 italic truncate max-w-sm`,children:[`"`,e.slogan||`Tông môn chưa viết tuyên ngôn.`,`"`]}),(0,f.jsxs)(`div`,{className:`flex items-center justify-center sm:justify-start gap-4 text-[10px] text-slate-500 flex-wrap`,children:[(0,f.jsxs)(`span`,{className:`flex items-center gap-1`,children:[(0,f.jsx)(r,{className:`w-3.5 h-3.5 text-purple-400`}),e.member_count,` đệ tử`]}),(0,f.jsx)(`span`,{children:`|`}),(0,f.jsxs)(`span`,{children:[`Tông chủ: `,(0,f.jsx)(`strong`,{children:e.leader_name})]}),(0,f.jsx)(`span`,{children:`|`}),(0,f.jsxs)(`span`,{className:`text-amber-500`,children:[`Cống hiến: `,(0,f.jsx)(`strong`,{children:e.contribution})]})]})]})]}),(0,f.jsxs)(`div`,{className:`flex gap-2`,children:[(0,f.jsx)(`button`,{onClick:()=>at(e.id),className:`px-4 py-2.5 bg-slate-800 hover:bg-slate-700 text-slate-300 rounded-2xl text-xs font-bold transition-all`,children:`Chi tiết`}),(0,f.jsxs)(`button`,{onClick:()=>!t&&ut(e.id),disabled:H||t,className:`px-5 py-2.5 rounded-2xl text-xs font-black shadow-md transition-all flex items-center gap-1.5 shrink-0 ${t?`bg-slate-800 text-slate-400 cursor-not-allowed border border-[#1f1f3a]`:`bg-teal-600 hover:bg-teal-500 text-white`}`,children:[(0,f.jsx)(`span`,{children:t?`Đang chờ...`:`Gia nhập`}),!t&&(0,f.jsx)(ge,{className:`w-3.5 h-3.5`})]})]})]},e.id)})})]})]})]}),Ee&&S&&(0,f.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4`,children:(0,f.jsxs)(`div`,{className:`w-full max-w-2xl bg-[#121225] border border-[#1f1f3a] rounded-3xl overflow-hidden shadow-2xl animate-scale-in`,children:[(0,f.jsxs)(`div`,{className:`p-5 border-b border-[#1f1f3a] flex items-center justify-between bg-[#0b0b14]/50`,children:[(0,f.jsxs)(`div`,{className:`flex items-center gap-3`,children:[Q(S.sect.badge),(0,f.jsxs)(`div`,{children:[(0,f.jsx)(`h4`,{className:`text-sm font-black text-white`,children:S.sect.name}),(0,f.jsxs)(`span`,{className:`text-[10px] text-teal-400 font-bold`,children:[`Tông môn Cấp `,S.sect.level]})]})]}),(0,f.jsx)(`button`,{onClick:()=>C(!1),className:`text-slate-400 hover:text-white`,children:(0,f.jsx)(l,{className:`w-5 h-5`})})]}),(0,f.jsxs)(`div`,{className:`p-6 space-y-6 max-h-[70vh] overflow-y-auto no-scrollbar`,children:[(0,f.jsxs)(`div`,{className:`space-y-1`,children:[(0,f.jsx)(`span`,{className:`text-[9px] font-black uppercase text-slate-500`,children:`Mục tiêu`}),(0,f.jsxs)(`p`,{className:`text-xs text-slate-300 italic`,children:[`"`,S.sect.slogan||`Tông môn này chưa thiết lập mục tiêu.`,`"`]})]}),(0,f.jsxs)(`div`,{className:`space-y-2`,children:[(0,f.jsxs)(`span`,{className:`text-[9px] font-black uppercase text-slate-500`,children:[`Danh sách môn đồ (`,S.member_count,`)`]}),(0,f.jsx)(`div`,{className:`border border-[#1f1f3a] rounded-2xl overflow-hidden divide-y divide-[#1f1f3a] bg-[#05050a]/40`,children:S.members.map(e=>(0,f.jsxs)(`div`,{className:`p-3.5 flex items-center justify-between text-xs`,children:[(0,f.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,f.jsx)(`div`,{className:`w-8 h-8 rounded-full bg-purple-600/20 text-purple-300 flex items-center justify-center font-bold`,children:e.username[0].toUpperCase()}),(0,f.jsxs)(`div`,{children:[(0,f.jsx)(`span`,{className:`font-bold text-slate-200 block`,children:e.username}),(0,f.jsxs)(`span`,{className:`text-[8px] text-slate-500 block`,children:[`Gia nhập: `,new Date(e.joined_at).toLocaleDateString()]})]})]}),(0,f.jsx)(`span`,{className:`px-2 py-0.5 border text-[8px] font-black rounded-md uppercase tracking-wider ${Tt(e.role)}`,children:m[e.role]})]},e.user_id))})]})]}),(0,f.jsxs)(`div`,{className:`p-5 border-t border-[#1f1f3a] bg-[#0b0b14]/50 flex justify-end gap-2`,children:[(0,f.jsx)(`button`,{onClick:()=>C(!1),className:`px-4 py-2.5 bg-slate-800 hover:bg-slate-700 text-slate-300 rounded-2xl text-xs font-bold`,children:`Đóng`}),(0,f.jsx)(`button`,{onClick:()=>ut(S.sect.id),disabled:H||y.includes(S.sect.id),className:`px-5 py-2.5 bg-teal-600 hover:bg-teal-500 text-white rounded-2xl text-xs font-black shadow-md`,children:y.includes(S.sect.id)?`Đã xin gia nhập`:`Gia nhập Tông môn`})]})]})}),Qe&&(0,f.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4`,children:(0,f.jsxs)(`div`,{className:`w-full max-w-md bg-[#121225] border border-[#1f1f3a] rounded-3xl p-6 space-y-4 shadow-2xl animate-scale-in`,children:[(0,f.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,f.jsxs)(`h4`,{className:`text-sm font-black text-white uppercase tracking-wider flex items-center gap-2`,children:[(0,f.jsx)(he,{className:`w-4 h-4 text-purple-400`}),`Hiến tặng sách`]}),(0,f.jsx)(`button`,{onClick:()=>V(!1),className:`text-slate-400 hover:text-white p-1`,children:(0,f.jsx)(l,{className:`w-5 h-5`})})]}),(0,f.jsx)(`div`,{className:`max-h-64 overflow-y-auto space-y-2 pr-1 no-scrollbar`,children:Xe.length===0?(0,f.jsx)(`div`,{className:`text-center py-10 text-xs text-slate-500`,children:`Kệ sách của bạn đang trống rỗng.`}):Xe.map(e=>(0,f.jsxs)(`div`,{className:`p-2.5 bg-[#0b0b14]/50 border border-[#1f1f3a] rounded-2xl flex items-center justify-between gap-3`,children:[(0,f.jsxs)(`div`,{className:`flex items-center gap-3 min-w-0`,children:[e.cover?(0,f.jsx)(`img`,{src:e.cover,className:`w-8 h-11 object-cover rounded-md border border-white/5 shrink-0`,alt:`cover`}):(0,f.jsx)(`div`,{className:`w-8 h-11 rounded-md bg-[#0f0f1a] flex items-center justify-center shrink-0 text-slate-600 text-[10px]`,children:`Cover`}),(0,f.jsxs)(`div`,{className:`min-w-0`,children:[(0,f.jsx)(`span`,{className:`text-xs font-bold text-slate-200 block truncate`,children:e.title}),(0,f.jsx)(`span`,{className:`text-[9px] text-slate-500 block truncate`,children:e.author})]})]}),(0,f.jsx)(`button`,{onClick:()=>_t(e.book_id),disabled:H,className:`px-3.5 py-2 bg-purple-600 hover:bg-purple-500 text-white rounded-xl text-[10px] font-black shrink-0 active:scale-95`,children:`Hiến sách`})]},e.book_id))})]})}),Ve&&g&&(0,f.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4`,children:(0,f.jsxs)(`div`,{className:`w-full max-w-md bg-[#121225] border border-[#1f1f3a] rounded-3xl p-6 space-y-4 shadow-2xl animate-scale-in`,children:[(0,f.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,f.jsxs)(`h4`,{className:`text-sm font-black text-white uppercase tracking-wider flex items-center gap-2`,children:[(0,f.jsx)(i,{className:`w-4 h-4 text-purple-400`}),`Tập hợp nhóm chat nhỏ`]}),(0,f.jsx)(`button`,{onClick:()=>I(!1),className:`text-slate-400 hover:text-white p-1`,children:(0,f.jsx)(l,{className:`w-5 h-5`})})]}),(0,f.jsxs)(`form`,{onSubmit:bt,className:`space-y-4`,children:[(0,f.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,f.jsx)(`label`,{className:`text-[10px] font-black uppercase text-slate-400`,children:`Tên nhóm chat nhỏ`}),(0,f.jsx)(`input`,{type:`text`,placeholder:`ví dụ: Ban Chấp Hành, Đội Sát Ma...`,value:L,onChange:e=>He(e.target.value),className:`w-full px-4 py-2.5 bg-[#05050a] border border-[#1f1f3a] focus:border-purple-500 rounded-xl text-xs text-white outline-none`,required:!0})]}),(0,f.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,f.jsx)(`label`,{className:`text-[10px] font-black uppercase text-slate-400 block`,children:`Chọn đệ tử tham gia`}),(0,f.jsx)(`div`,{className:`max-h-48 overflow-y-auto space-y-1 pr-1 border border-[#1f1f3a] rounded-2xl p-2 bg-[#05050a]/40 no-scrollbar`,children:g.members.filter(e=>e.user_id!==a.id).map(e=>(0,f.jsxs)(`label`,{className:`flex items-center justify-between p-2 hover:bg-white/5 rounded-xl cursor-pointer text-xs`,children:[(0,f.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,f.jsx)(`input`,{type:`checkbox`,checked:R.includes(e.user_id),onChange:()=>wt(e.user_id),className:`rounded border-[#1f1f3a] text-purple-600 focus:ring-0`}),(0,f.jsx)(`span`,{className:`text-slate-300 font-bold`,children:e.username})]}),(0,f.jsxs)(`span`,{className:`text-[8.5px] text-slate-500 font-mono`,children:[`(`,m[e.role]||`Môn đồ`,`)`]})]},e.user_id))})]}),(0,f.jsx)(`button`,{type:`submit`,disabled:H||!L.trim()||R.length===0,className:`w-full py-3 bg-purple-600 hover:bg-purple-500 text-white rounded-xl text-xs font-black shadow-lg shadow-purple-600/20 active:scale-95`,children:H?`Đang triệu tập...`:`Triệu tập nhóm chat`})]})]})}),We&&z&&g&&(0,f.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4`,children:(0,f.jsxs)(`div`,{className:`w-full max-w-md bg-[#121225] border border-[#1f1f3a] rounded-3xl overflow-hidden shadow-2xl animate-scale-in`,children:[(0,f.jsxs)(`div`,{className:`p-5 border-b border-[#1f1f3a] flex items-center justify-between bg-[#0b0b14]/50`,children:[(0,f.jsxs)(`h4`,{className:`text-xs font-black text-white uppercase tracking-wider`,children:[`Cài đặt: `,z.group.name]}),(0,f.jsx)(`button`,{onClick:()=>Ge(!1),className:`text-slate-400 hover:text-white`,children:(0,f.jsx)(l,{className:`w-5 h-5`})})]}),(0,f.jsxs)(`div`,{className:`p-5 space-y-4`,children:[(0,f.jsxs)(`div`,{className:`space-y-2`,children:[(0,f.jsxs)(`span`,{className:`text-[9px] font-black uppercase text-slate-500 block`,children:[`Thành viên trong nhóm (`,z.member_count,`)`]}),(0,f.jsx)(`div`,{className:`border border-[#1f1f3a] rounded-2xl p-2 space-y-1 max-h-40 overflow-y-auto no-scrollbar bg-[#05050a]/40`,children:z.members.map(e=>{let t=z.group.creator_id===a.id,n=e.user_id===a.id,r=t&&!n;return(0,f.jsxs)(`div`,{className:`flex items-center justify-between p-2 hover:bg-white/5 rounded-xl text-xs`,children:[(0,f.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,f.jsx)(`span`,{className:`font-bold text-slate-300`,children:e.username}),(0,f.jsxs)(`span`,{className:`text-[8.5px] text-slate-500`,children:[`(`,m[e.role]||`Môn đồ`,`)`]})]}),r&&(0,f.jsx)(`button`,{onClick:()=>Ct(e.user_id),className:`p-1 text-rose-400 hover:bg-rose-500/10 rounded-lg`,title:`Loại khỏi nhóm`,children:(0,f.jsx)(be,{className:`w-4 h-4`})})]},e.user_id)})})]}),z.group.creator_id===a.id&&(0,f.jsxs)(`div`,{className:`space-y-2`,children:[(0,f.jsx)(`span`,{className:`text-[9px] font-black uppercase text-slate-500 block`,children:`Thêm môn đồ trong tông vào nhóm`}),(0,f.jsx)(`div`,{className:`border border-[#1f1f3a] rounded-2xl p-2 space-y-1 max-h-40 overflow-y-auto no-scrollbar bg-[#05050a]/40`,children:g.members.filter(e=>!z.members.some(t=>t.user_id===e.user_id)).map(e=>(0,f.jsxs)(`div`,{className:`flex items-center justify-between p-2 hover:bg-white/5 rounded-xl text-xs`,children:[(0,f.jsx)(`span`,{className:`font-bold text-slate-300`,children:e.username}),(0,f.jsx)(`button`,{onClick:()=>St(e.user_id),className:`p-1 text-teal-400 hover:bg-teal-500/10 rounded-lg`,title:`Thêm vào nhóm`,children:(0,f.jsx)(ee,{className:`w-4 h-4`})})]},e.user_id))})]})]})]})})]})})}export{h as default}; \ No newline at end of file diff --git a/frontend-web/dist/assets/Settings-d6v3GnDB.js b/frontend-web/dist/assets/Settings-d6v3GnDB.js new file mode 100644 index 0000000000000000000000000000000000000000..84358c06910c3db1763aefcfd1d56dd63ab62a1c --- /dev/null +++ b/frontend-web/dist/assets/Settings-d6v3GnDB.js @@ -0,0 +1 @@ +import{t as e}from"./award-CKCOPIfL.js";import{_ as t,a as n,b as r,c as i,d as a,g as ee,h as o,m as s,r as te,t as ne,y as re}from"./MainLayout-COiTxmNr.js";import{o as ie}from"./square-DZKJ0QGR.js";import{t as ae}from"./clock-DEPYmZZ-.js";import{n as oe,t as se}from"./shield-LuyExdkp.js";import{t as c}from"./laptop-BPoCx4gb.js";import{t as l}from"./trash-2-DDhTqVwA.js";import{C as ce,F as u,M as d,S as le,_ as ue,b as f,c as de,h as fe,i as p,j as m,r as h,w as g}from"./index-yRoRoI6u.js";var pe=f(`chart-column`,[[`path`,{d:`M3 3v16a2 2 0 0 0 2 2h16`,key:`c24i48`}],[`path`,{d:`M18 17V9`,key:`2bz60n`}],[`path`,{d:`M13 17V5`,key:`1frdt8`}],[`path`,{d:`M8 17v-3`,key:`17ska0`}]]),me=f(`sliders-vertical`,[[`path`,{d:`M10 8h4`,key:`1sr2af`}],[`path`,{d:`M12 21v-9`,key:`17s77i`}],[`path`,{d:`M12 8V3`,key:`13r4qs`}],[`path`,{d:`M17 16h4`,key:`h1uq16`}],[`path`,{d:`M19 12V3`,key:`o1uvq1`}],[`path`,{d:`M19 21v-5`,key:`qua636`}],[`path`,{d:`M3 14h4`,key:`bcjad9`}],[`path`,{d:`M5 10V3`,key:`cb8scm`}],[`path`,{d:`M5 21v-7`,key:`1w1uti`}]]),he=f(`smartphone`,[[`rect`,{width:`14`,height:`20`,x:`5`,y:`2`,rx:`2`,ry:`2`,key:`1yt0o3`}],[`path`,{d:`M12 18h.01`,key:`mhygvu`}]]),_=f(`triangle-alert`,[[`path`,{d:`m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3`,key:`wmoenq`}],[`path`,{d:`M12 9v4`,key:`juzpu7`}],[`path`,{d:`M12 17h.01`,key:`p32p05`}]]),ge=f(`tv`,[[`path`,{d:`m17 2-5 5-5-5`,key:`16satq`}],[`rect`,{width:`20`,height:`15`,x:`2`,y:`7`,rx:`2`,key:`1e6viu`}]]),v=u(m(),1),y=d();function b(){let{user:u,setUser:d}=ce(),{lang:f,t:m}=le(),b=typeof window<`u`&&window.Capacitor&&window.Capacitor.isNativePlatform&&window.Capacitor.isNativePlatform(),[x,S]=(0,v.useState)(`profile`),_e={vi:{profileTab:`Hồ sơ cá nhân`,securityTab:`Tài khoản & Bảo mật`,prefTab:`Tùy chỉnh đọc & Thông báo`,walletTab:`Cấp bậc & Tài sản`,displayName:`Biệt hiệu hiển thị`,displayNamePlaceholder:`Nhập biệt hiệu đi bình luận...`,birthday:`Ngày sinh`,gender:`Giới tính`,genderMale:`Nam`,genderFemale:`Nữ`,genderOther:`Khác`,bio:`Lời giới thiệu ngắn (Bio)`,bioPlaceholder:`Viết vài câu giới thiệu bản thân...`,avatarFrame:`Khung ảnh đại diện`,frameDefault:`Không khung (Thường)`,frameVip:`Khung Rồng Vàng (VIP)`,frameEvent:`Khung Tinh Vân (Sự kiện)`,saveBtn:`Lưu thay đổi`,saving:`Đang lưu...`,saveSuccess:`Cập nhật thông tin thành công!`,saveError:`Có lỗi xảy ra, vui lòng thử lại.`,authLinks:`Liên kết mạng xã hội`,authLinked:`Đã liên kết`,authLinkBtn:`Liên kết ngay`,phoneNumber:`Số điện thoại`,phonePlaceholder:`Nhập số điện thoại của bạn`,getOtp:`Gửi mã OTP`,otpSent:`Đã gửi mã!`,enterOtp:`Nhập mã xác thực OTP`,verifyBtn:`Xác thực`,twoFactor:`Bảo mật hai lớp (2FA)`,twoFactorDesc:`Yêu cầu nhập mã xác thực OTP gửi qua email/SĐT khi đăng nhập từ thiết bị lạ.`,sessionTitle:`Quản lý phiên đăng nhập`,sessionDesc:`Danh sách các thiết bị đang đăng nhập tài khoản của bạn.`,revokeSession:`Đăng xuất thiết bị`,revokeAllSessions:`Đăng xuất khỏi tất cả thiết bị khác`,activeNow:`Đang hoạt động`,readingConf:`Cấu hình trình đọc mặc định`,fontSize:`Cỡ chữ`,fontFamily:`Phông chữ`,lineHeight:`Khoảng cách dòng`,lineNormal:`Bình thường`,lineMedium:`Vừa phải`,lineWide:`Rộng rãi`,themeBg:`Màu nền`,themeLight:`Trang sáng`,themeDark:`Bóng tối`,themeSepia:`Sepia (Vàng giấy)`,favCategories:`Thể loại yêu thích (3-5 thể loại)`,notificationSettings:`Cài đặt thông báo`,notifyNewChapters:`Thông báo khi truyện trong Tủ Sách có chương mới`,notifyReplies:`Thông báo khi có người trả lời bình luận của bạn`,accountLevel:`Cấp bậc tu tiên (Level)`,levelTitle:`Cấp Độ`,expNeeded:`EXP tiếp theo`,titlesBadges:`Danh hiệu & Huy hiệu`,walletBalance:`Ví tiền & Tài sản`,depositCoin:`Xu Nạp (Vĩnh viễn)`,bonusCoin:`Xu Thưởng (Hạn dùng)`,itemInventory:`Kho vật phẩm của bạn`,itemRecommendation:`Phiếu đề cử`,itemVote:`Phiếu đề xuất`,itemGift:`Quà tặng Donate`,txHistory:`Lịch sử giao dịch`,txTabDeposit:`Lịch sử nạp`,txTabExpense:`Lịch sử tiêu phí`,txTitle:`Giao dịch`,txCost:`Chi phí`,txTime:`Thời gian`,txStatus:`Trạng thái`,txDetail:`Nội dung`,passMinLen:`Mật khẩu mới phải từ 4 ký tự trở lên.`,passMismatch:`Mật khẩu mới và xác nhận mật khẩu không trùng khớp.`,passChangeSuccess:`Đổi mật khẩu thành công!`,passChangeError:`Lỗi thay đổi mật khẩu.`},en:{profileTab:`Profile Settings`,securityTab:`Account & Security`,prefTab:`Reading & Notifications`,walletTab:`Level & Assets`,displayName:`Display Name (Nickname)`,displayNamePlaceholder:`Enter your nickname...`,birthday:`Birthday`,gender:`Gender`,genderMale:`Male`,genderFemale:`Female`,genderOther:`Other`,bio:`Bio / Signature`,bioPlaceholder:`Tell us about yourself...`,avatarFrame:`Avatar Frame`,frameDefault:`None (Regular)`,frameVip:`Gold Dragon (VIP)`,frameEvent:`Nebula Frame (Event)`,saveBtn:`Save Changes`,saving:`Saving...`,saveSuccess:`Profile updated successfully!`,saveError:`An error occurred, please try again.`,authLinks:`Linked Social Accounts`,authLinked:`Linked`,authLinkBtn:`Link Account`,phoneNumber:`Phone Number`,phonePlaceholder:`Enter your phone number`,getOtp:`Send OTP`,otpSent:`OTP Sent!`,enterOtp:`Enter OTP Code`,verifyBtn:`Verify`,twoFactor:`Two-Factor Auth (2FA)`,twoFactorDesc:`Requires OTP verification when logging in from unrecognized devices.`,sessionTitle:`Session Management`,sessionDesc:`Devices currently logged in to your account.`,revokeSession:`Log out device`,revokeAllSessions:`Log out all other devices`,activeNow:`Active Now`,readingConf:`Default Reader Configurations`,fontSize:`Font Size`,fontFamily:`Font Family`,lineHeight:`Line Height`,lineNormal:`Normal`,lineMedium:`Medium`,lineWide:`Wide`,themeBg:`Background Theme`,themeLight:`Light Mode`,themeDark:`Dark Mode`,themeSepia:`Sepia Paper`,favCategories:`Favorite Categories (3-5 tags)`,notificationSettings:`Notification Settings`,notifyNewChapters:`Notify when novels in Bookshelf have new chapters`,notifyReplies:`Notify when someone replies to your comments`,accountLevel:`Account Level & EXP`,levelTitle:`Level`,expNeeded:`Next Level EXP`,titlesBadges:`Titles & Badges`,walletBalance:`Wallet & Assets`,depositCoin:`Coins (Permanent)`,bonusCoin:`Bonus Coins (Promo)`,itemInventory:`Item Inventory`,itemRecommendation:`Recommendation Ticket`,itemVote:`Monthly Vote Ticket`,itemGift:`Donate Gift Pack`,txHistory:`Transaction Logs`,txTabDeposit:`Deposits`,txTabExpense:`Expenses`,txTitle:`Transaction`,txCost:`Cost`,txTime:`Timestamp`,txStatus:`Status`,txDetail:`Detail`,passMinLen:`Password must be at least 4 characters.`,passMismatch:`Passwords do not match.`,passChangeSuccess:`Password changed successfully!`,passChangeError:`Failed to change password.`},zh:{profileTab:`个人主页`,securityTab:`账号与安全`,prefTab:`阅读偏好与通知`,walletTab:`等级与资产`,displayName:`显示昵称`,displayNamePlaceholder:`输入您的昵称...`,birthday:`出生日期`,gender:`性别`,genderMale:`男`,genderFemale:`女`,genderOther:`其他`,bio:`个性签名`,bioPlaceholder:`用一句话介绍自己...`,avatarFrame:`头像框装饰`,frameDefault:`无 (普通成员)`,frameVip:`金龙腾飞 (VIP尊享)`,frameEvent:`星云环绕 (活动限定)`,saveBtn:`保存修改`,saving:`正在保存...`,saveSuccess:`主页信息更新成功!`,saveError:`保存失败,请稍后重试。`,authLinks:`第三方社交账号绑定`,authLinked:`已绑定`,authLinkBtn:`立即绑定`,phoneNumber:`手机号码`,phonePlaceholder:`请输入您的手机号`,getOtp:`发送验证码`,otpSent:`已发送验证码!`,enterOtp:`输入验证码`,verifyBtn:`验证并绑定`,twoFactor:`双重身份验证 (2FA)`,twoFactorDesc:`从新设备登录时,需要输入发送至邮箱或手机的验证码。`,sessionTitle:`登录设备管理`,sessionDesc:`当前登录您账号的活跃设备列表。`,revokeSession:`退出该设备`,revokeAllSessions:`下线其他所有设备`,activeNow:`当前在线`,readingConf:`默认阅读器样式配置`,fontSize:`字体大小`,fontFamily:`字体类型`,lineHeight:`行间距`,lineNormal:`默认`,lineMedium:`中等`,lineWide:`宽松`,themeBg:`阅读背景`,themeLight:`明亮`,themeDark:`极夜`,themeSepia:`复古羊皮纸`,favCategories:`感兴趣的分类 (3-5个)`,notificationSettings:`系统通知推送`,notifyNewChapters:`书架收藏的小说更新时推送通知`,notifyReplies:`我的评论收到回复时推送通知`,accountLevel:`修仙境界等级 (Level)`,levelTitle:`境界等级`,expNeeded:`突破境界所需EXP`,titlesBadges:`获得徽章与称号`,walletBalance:`书币钱包与资产`,depositCoin:`充值代币 (永久)`,bonusCoin:`赠送代币 (限时)`,itemInventory:`我的道具背包`,itemRecommendation:`推荐票`,itemVote:`月票`,itemGift:`投喂打赏礼包`,txHistory:`交易与消费明细`,txTabDeposit:`充值记录`,txTabExpense:`消费记录`,txTitle:`明细`,txCost:`花费/金额`,txTime:`时间`,txStatus:`状态`,txDetail:`描述`,passMinLen:`密码长度不能少于4位。`,passMismatch:`两次输入的密码不一致。`,passChangeSuccess:`修改密码成功!`,passChangeError:`修改密码失败。`}},C=_e[f]||_e.vi,[w,ve]=(0,v.useState)(u?.display_name||u?.username||``),[T,ye]=(0,v.useState)(u?.birthday||`1998-01-01`),[E,be]=(0,v.useState)(u?.gender||`male`),[D,xe]=(0,v.useState)(u?.bio||`Ta là một người mê đọc truyện dịch AI...`),[O,Se]=(0,v.useState)(u?.avatar_frame||`default`),[k,Ce]=(0,v.useState)(u?.avatar||``),[we,Te]=(0,v.useState)(``),[A,Ee]=(0,v.useState)(``),[De,Oe]=(0,v.useState)(``),[ke,Ae]=(0,v.useState)(!1),[je,j]=(0,v.useState)(``),[Me,Ne]=(0,v.useState)(``),[M,Pe]=(0,v.useState)(u?.phone||``),[Fe,Ie]=(0,v.useState)(``),[Le,Re]=(0,v.useState)(!1),[N,ze]=(0,v.useState)(!!u?.phone),[Be,Ve]=(0,v.useState)(u?.two_factor===1),He=`/home/alida/Documents/Extension_reader_tool/ttS/matcha36_vocos10_standalone/models`,[P,Ue]=(0,v.useState)(He);(0,v.useEffect)(()=>{if(p){let e=h();e&&e.getModelsPath?e.getModelsPath().then(e=>{Ue(e),localStorage.setItem(`electron_downloadFolder`,e)}).catch(e=>{console.error(`Failed to get models path:`,e)}):localStorage.setItem(`electron_downloadFolder`,He)}else b?(Ue(`Bộ nhớ trong (Sandboxed App Storage)`),localStorage.setItem(`electron_downloadFolder`,`Bộ nhớ trong (Sandboxed App Storage)`)):localStorage.setItem(`electron_downloadFolder`,He)},[]);let[F,We]=(0,v.useState)(null),[Ge,Ke]=(0,v.useState)(!1),[I,L]=(0,v.useState)({}),[qe,Je]=(0,v.useState)(null),[Ye,Xe]=(0,v.useState)(!1),[Ze,Qe]=(0,v.useState)([]),[$e,et]=(0,v.useState)({open:!1,filename:``}),[tt,nt]=(0,v.useState)(localStorage.getItem(`tts_device_pref`)||`auto`),[R,rt]=(0,v.useState)(!1),[z,it]=(0,v.useState)(null),[at,ot]=(0,v.useState)(!1),[st,ct]=(0,v.useState)(0),[lt,B]=(0,v.useState)(!1),[ut,V]=(0,v.useState)(``),dt=async()=>{rt(!0),it(null);try{if(p){let e=h();if(e&&e.checkForUpdate){let t=await e.checkForUpdate();t&&t.success?t.hasUpdate?(it(t),ot(!0)):alert(f===`vi`?`Ứng dụng của bạn đã ở phiên bản mới nhất!`:`Your application is already at the latest version!`):alert(f===`vi`?`Không thể kết nối đến máy chủ cập nhật.`:`Cannot connect to update server.`)}}else if(b)alert(f===`vi`?`Ứng dụng di động Android đang chạy phiên bản mới nhất!`:`Android mobile app is running the latest version!`);else{let e=await g.get(`/api/releases`);if(e.data?.success&&e.data?.releases){let t=e.data.releases,n=t.desktop_linux||t.desktop_windows;if(n){let e=n.version,t=`1.0.1`,r=e=>(e||`0.0.0`).replace(/^v/,``).split(`.`).map(Number),[i,a,ee]=r(e),[o,s,te]=r(t);i>o||i===o&&a>s||i===o&&a===s&&ee>te?(it({hasUpdate:!0,latestVersion:e,currentVersion:t,downloadUrl:n.download_url,releaseNotes:n.release_notes,platform:`web`}),ot(!0)):alert(f===`vi`?`Hệ thống đã ở phiên bản mới nhất!`:`System is already at the latest version!`)}}}}catch(e){alert((f===`vi`?`Lỗi kiểm tra cập nhật: `:`Error checking update: `)+e.message)}finally{rt(!1)}},ft=async()=>{if(z){if(!p){window.location.href=`/downloads`;return}B(!0),ct(0),V(f===`vi`?`Đang tải bản cập nhật...`:`Downloading update...`);try{let{downloadUrl:e,latestVersion:t}=z,n=e?.includes(`windows`)||e?.includes(`win`)?`TienHiepAI-Setup-${t}.exe`:`TienHiepAI-${t}.AppImage`,r=h(),i=r.onUpdateDownloadProgress(e=>{e&&typeof e.percent==`number`&&(ct(e.percent),V(f===`vi`?`Đang tải: ${e.percent}% (${(e.downloadedBytes/(1024*1024)).toFixed(1)}MB / ${(e.totalBytes/(1024*1024)).toFixed(1)}MB)`:`Downloading: ${e.percent}% (${(e.downloadedBytes/(1024*1024)).toFixed(1)}MB / ${(e.totalBytes/(1024*1024)).toFixed(1)}MB)`))}),a=await r.downloadAndRunUpdate(e,n);i(),a&&a.success?V(f===`vi`?`✅ Tải xong! Đang khởi chạy installer...`:`✅ Complete! Launching installer...`):(B(!1),alert((f===`vi`?`Lỗi: `:`Error: `)+(a.error||`Unknown`)))}catch(e){B(!1),alert((f===`vi`?`Lỗi hệ thống: `:`System error: `)+e.message)}}},H=async()=>{if(p){let e=h();e&&e.listModels&&Qe(await e.listModels(P))}else b&&Qe([{name:`Matcha-TTS (Cloud/Server API)`,sizeMB:19.2},{name:`Vocos Vocoder (Cloud/Server API)`,sizeMB:13}])};(0,v.useEffect)(()=>{if(x===`tts_models`){p&&H(),$();let e=setInterval(()=>{$()},4e3);return()=>clearInterval(e)}},[x,P]),(0,v.useEffect)(()=>{if(!p)return;let e=h();if(!e||!e.onBackendReady)return;let t=e.onBackendReady(({ready:e})=>{e&&(H(),$())});return()=>{t&&t()}},[p]);let[U,pt]=(0,v.useState)({google:!0,facebook:!1,github:!1,apple:!1}),[mt,ht]=(0,v.useState)([]),[W,G]=(0,v.useState)({fontSize:parseInt(localStorage.getItem(`reader_fontSize`))||16,fontFamily:localStorage.getItem(`reader_fontFamily`)||`font-sans`,lineHeight:parseFloat(localStorage.getItem(`reader_lineHeight`))||1.6,theme:localStorage.getItem(`reader_theme`)||`dark`}),[gt,_t]=(0,v.useState)([`玄幻`,`仙侠`,`科幻`]),[K,vt]=(0,v.useState)({newChapter:!0,replies:!0}),[q,yt]=(0,v.useState)({name:u?.vip_status===1?`Trúc Cơ Kỳ (VIP)`:`Luyện Khí Kỳ (Mortal)`,exp:720,maxExp:1e3,rank:u?.vip_status===1?`Chân Nhân`:`Tán Tu`}),[bt,xt]=(0,v.useState)([{id:1,title:`Tân Thủ`,color:`bg-emerald-500/10 text-emerald-400 border-emerald-500/25`,icon:`🌱`},{id:2,title:`VIP Độc Giả`,color:`bg-amber-500/10 text-amber-400 border-amber-500/25`,icon:`👑`,active:u?.vip_status===1},{id:3,title:`Mọt Sách`,color:`bg-purple-500/10 text-purple-400 border-purple-500/25`,icon:`📚`}]),[J,St]=(0,v.useState)({coins:125e3,bonus:2500,tickets:5,votes:3,gifts:2}),[Ct,wt]=(0,v.useState)(`deposit`),[Tt,Et]=(0,v.useState)([{id:101,detail:`Nạp qua MB Bank QR`,amount:5e4,time:`2026-06-09 10:23`,status:`success`},{id:102,detail:`Nạp qua PayOS cổng tự động`,amount:1e5,time:`2026-06-05 14:02`,status:`success`}]),[Dt,Ot]=(0,v.useState)([{id:201,detail:`Đăng ký VIP Gói Tháng`,amount:-5e4,time:`2026-06-09 10:25`,status:`success`},{id:202,detail:`Mua quà tặng Donate chương`,amount:-15e3,time:`2026-06-01 20:11`,status:`success`}]),[kt,At]=(0,v.useState)(``),[jt,Mt]=(0,v.useState)(``),[Nt,Pt]=(0,v.useState)(!1),[Y,Ft]=(0,v.useState)(null),[It,Lt]=(0,v.useState)([]),[Rt,X]=(0,v.useState)(!1),Z=e=>{if(!e||e<=0)return`0 phút`;let t=Math.floor(e/3600),n=Math.floor(e%3600/60);return t>0?`${t}h ${n}m`:`${n}m`},zt=async()=>{if(u)try{let e=await g.get(`/api/auth/sessions`);if(e.data&&e.data.success){let t=localStorage.getItem(`refreshToken`);ht(e.data.sessions.filter(e=>e.status===`active`).map(e=>({id:e.id,device:`${e.os} (${e.browser})`,ip:e.ip_address,current:e.token===t,location:e.device_type===`Desktop`?`Máy tính`:`Điện thoại`,token:e.token})))}}catch(e){console.error(`Lỗi khi tải danh sách thiết bị:`,e)}};(0,v.useEffect)(()=>{x===`profile`&&u&&zt()},[x,u]),(0,v.useEffect)(()=>{x===`stats`&&(async()=>{X(!0);try{let[e,t]=await Promise.all([g.get(`/api/user/stats`),g.get(`/api/user/history`)]);Ft(e.data?.stats||e.data||null),Lt(t.data?.history||t.data||[])}catch(e){console.error(`Lỗi khi tải thống kê & lịch sử:`,e)}finally{X(!1)}})()},[x]),(0,v.useEffect)(()=>{x===`desktop`&&(p||b)&&(async()=>{Ke(!0);try{if(p){let e=h();e&&e.getSystemInfo&&We(await e.getSystemInfo())}else if(b){let e=navigator.userAgent,t=e.match(/Android\s([0-9\.]+)/);We({platform:t?`Android ${t[1]}`:`Android OS`,arch:e.includes(`arm64`)||e.includes(`aarch64`)?`arm64`:e.includes(`x86_64`)?`x86_64`:`arm`,cpuCount:navigator.hardwareConcurrency||`N/A`,freeMemoryGB:`N/A`,totalMemoryGB:navigator.deviceMemory||`N/A`,version:`1.0.18 (Capacitor Mobile)`})}}catch(e){console.error(`Lỗi khi tải thông tin hệ thống:`,e)}finally{Ke(!1)}})()},[x]),(0,v.useEffect)(()=>{if(p){let e=h();if(e&&e.onDownloadProgress)return e.onDownloadProgress(e=>{L(t=>({...t,[e.filename]:e.percent}))})}},[]);let Bt=async(e,t)=>{if(b){alert(`Mô hình AI trên ứng dụng di động được kết nối và xử lý trực tiếp qua Máy Chủ Cloud AI hoặc Server local của bạn để tối ưu pin và hiệu năng thiết bị di động.`);return}if(!p){alert(`Tính năng tải trực tiếp Model siêu tốc độ chỉ hỗ trợ trên ứng dụng Desktop (.exe). Vui lòng tải app Desktop để dùng!`);return}try{let n=h(),r=t.split(`/`).pop()||`${e}.onnx`;L(e=>({...e,[r]:0}));let i=await n.downloadModel(t,P,r);if(i.success){try{await fetch(`http://127.0.0.1:8001/reload_model`,{method:`POST`})}catch{console.warn(`API server chưa bật hoặc lỗi kết nối, tải thành công nhưng chưa kích hoạt được.`)}L(e=>{let t={...e};return delete t[r],t}),await H(),await $()}else console.error(`Lỗi tải: ${i.error}`),L(e=>{let t={...e};return delete t[r],t})}catch(n){console.error(`Lỗi hệ thống: ${n.message||n}`);let r=t.split(`/`).pop()||`${e}.onnx`;L(e=>{let t={...e};return delete t[r],t})}},Vt=e=>{et({open:!0,filename:e})},Ht=async()=>{let e=$e.filename;if(et({open:!1,filename:``}),p){let t=h();if(t&&t.deleteModel){let n=`${P}/${e}`.replace(/\/\//g,`/`);if((await t.deleteModel(n)).success){await H();try{await fetch(`http://127.0.0.1:8001/reload_model`,{method:`POST`})}catch{}await $()}}}},Ut=e=>{nt(e),localStorage.setItem(`tts_device_pref`,e),fetch(`http://127.0.0.1:8001/set_device`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({device:e})}).catch(()=>{})};(0,v.useEffect)(()=>{if(!p)return;let e=h();!e||!e.checkBackendStatus||e.checkBackendStatus().then(e=>{e&&e.error!==`missing_engine`?Xe(!0):Xe(!1)}).catch(()=>{})},[p,qe]);let Wt=()=>{let e=new(window.AudioContext||window.webkitAudioContext),t=e.createOscillator(),n=e.createGain();t.type=`sine`,t.frequency.setValueAtTime(440,e.currentTime),n.gain.setValueAtTime(.1,e.currentTime),n.gain.exponentialRampToValueAtTime(.001,e.currentTime+1),t.connect(n),n.connect(e.destination),t.start(),t.stop(e.currentTime+1),alert(`Đã phát âm thanh Beep test hệ thống (1 giây). Nếu bạn nghe thấy tiếng "Bíp", loa và thẻ âm thanh đang hoạt động tốt.`)},[Q,Gt]=(0,v.useState)({trans:`14ms`,transRtf:`500x`,tts:`23ms`,rtf:`1.2x`,localTts:`Disconnected`,isPinging:!1}),$=async()=>{let e=p?h():null,t=t=>{e&&e.logDebug&&e.logDebug(t),console.log(t)};t(`[Ping Check] Bắt đầu kiểm tra kết nối (Ping)... Trạng thái trình duyệt: navigator.onLine = ${navigator.onLine}, UserAgent = ${navigator.userAgent}`),Gt({trans:`Pinging...`,transRtf:`...`,tts:`Pinging...`,rtf:`...`,localTts:`Pinging...`,isPinging:!0});let[n,r,i]=await Promise.all([(async()=>{t(`[Ping Check] [Dịch thuật] Khởi tạo tiến trình...`);try{t(`[Ping Check] [Dịch thuật] Đang thực hiện warmup request (Timeout 4s)...`);try{await g.post(`/translate`,{texts:[`Khởi động hệ thống dịch`],mode:`advanced`,vip_key:`VIP_SERVER`},{signal:AbortSignal.timeout(4e3)}),t(`[Ping Check] [Dịch thuật] Warmup hoàn tất.`)}catch(e){t(`[Ping Check] [Dịch thuật] Warmup bỏ qua hoặc lỗi nhẹ: ${e.message}`)}t(`[Ping Check] [Dịch thuật] Đang gửi request dịch chính thức (Timeout 8s)...`);let e=performance.now(),n=await g.post(`/translate`,{texts:[`Thiên địa sơ khai, vạn vật hỗn độn. Lâm Động từ từ mở mắt ra, nhìn thấy một tia sáng le lói từ chân trời.`],mode:`advanced`,vip_key:`VIP_SERVER`},{signal:AbortSignal.timeout(8e3)}),r=performance.now()-e;t(`[Ping Check] [Dịch thuật] Đã nhận phản hồi sau ${Math.round(r)}ms. HTTP status: ${n.status}`);let i=105/15/(r/1e3),a={trans:`${Math.round(r)}ms`,transRtf:`${i.toFixed(1)}x`};return t(`[Ping Check] [Dịch thuật] Thành công. RTF = ${a.transRtf}. Dữ liệu thô JSON nhận được: ${JSON.stringify(n.data)}`),a}catch(e){let n={message:e.message,code:e.code,status:e.response?e.response.status:null,data:e.response?e.response.data:null,stack:e.stack};return t(`[Ping Check] [Dịch thuật] THẤT BẠI! Chi tiết cấu trúc lỗi hệ thống: ${JSON.stringify(n)}`),{trans:`Timeout`,transRtf:`Lỗi`}}})(),(async()=>{t(`[Ping Check] [Cloud TTS] Khởi tạo tiến trình...`);try{t(`[Ping Check] [Cloud TTS] Đang thực hiện warmup request (Timeout 4s)...`);try{await g.post(`/v1/audio/speech`,{model:`matcha-tts`,input:`Khởi động`,voice:`ngao_the_cuu_trong_thien`,response_format:`wav`,speed:1,vip_key:`VIP_SERVER`},{responseType:`arraybuffer`,signal:AbortSignal.timeout(4e3)}),t(`[Ping Check] [Cloud TTS] Warmup hoàn tất.`)}catch(e){t(`[Ping Check] [Cloud TTS] Warmup bỏ qua hoặc lỗi nhẹ: ${e.message}`)}t(`[Ping Check] [Cloud TTS] Đang gửi request tạo âm thanh chính thức (Timeout 8s)...`);let e=performance.now(),n=await g.post(`/v1/audio/speech`,{model:`matcha-tts`,input:`Thiên địa sơ khai, vạn vật hỗn độn. Lâm Động từ từ mở mắt ra.`,voice:`ngao_the_cuu_trong_thien`,response_format:`wav`,speed:1,vip_key:`VIP_SERVER`},{responseType:`arraybuffer`,signal:AbortSignal.timeout(8e3)}),r=performance.now()-e;t(`[Ping Check] [Cloud TTS] Đã nhận phản hồi sau ${Math.round(r)}ms. HTTP status: ${n.status}`);let i=n.data;t(`[Ping Check] [Cloud TTS] Dữ liệu nhị phân nhận được: ${i?i.byteLength:0} bytes. Đang giải mã Audio Data...`);let a=(await new(window.AudioContext||window.webkitAudioContext)().decodeAudioData(i.slice(0))).duration,ee=a/(r/1e3),o={tts:`${Math.round(r)}ms`,rtf:`${ee.toFixed(2)}x`};return t(`[Ping Check] [Cloud TTS] Thành công. RTF = ${o.rtf}, Độ dài âm thanh = ${a.toFixed(3)}s. Headers: ${JSON.stringify(n.headers)}`),o}catch(e){let n={message:e.message,code:e.code,status:e.response?e.response.status:null,data:e.response?e.response.data instanceof ArrayBuffer?`[ArrayBuffer]`:e.response.data:null,stack:e.stack};return t(`[Ping Check] [Cloud TTS] THẤT BẠI! Chi tiết cấu trúc lỗi hệ thống: ${JSON.stringify(n)}`),{tts:`Timeout`,rtf:`Timeout`}}})(),(async()=>{t(`[Ping Check] [Local TTS] Khởi tạo tiến trình...`);try{t(`[Ping Check] [Local TTS] Đang kết nối tới http://127.0.0.1:8001/health (Timeout 8s)...`);let e=performance.now(),n=await fetch(`http://127.0.0.1:8001/health`,{method:`GET`,signal:AbortSignal.timeout(8e3)}),r=performance.now()-e;if(t(`[Ping Check] [Local TTS] Đã nhận phản hồi sau ${Math.round(r)}ms. HTTP status: ${n.status}`),n.ok){let e=await n.json(),i=``;return i=e.status===`need_model`?`Connected (Chưa có Model) - ${Math.round(r)}ms`:`Connected (${e.device}) - ${Math.round(r)}ms`,t(`[Ping Check] [Local TTS] Thành công: ${i}. Dữ liệu thô JSON nhận được: ${JSON.stringify(e)}`),{localTts:i}}else{let e=``;try{e=await n.text()}catch{}return t(`[Ping Check] [Local TTS] Lỗi phản hồi HTTP không OK. Status = ${n.status}. Chi tiết phản hồi: ${e}`),{localTts:`Lỗi Cổng`}}}catch(e){let n={message:e.message,stack:e.stack};return t(`[Ping Check] [Local TTS] THẤT BẠI! Chi tiết lỗi: ${JSON.stringify(n)}`),{localTts:`Disconnected`}}})()]);t(`[Ping Check] ✅ Hoàn tất tất cả kiểm tra ping.`),Gt({trans:n.trans,transRtf:n.transRtf,tts:r.tts,rtf:r.rtf,localTts:i.localTts,isPinging:!1})},Kt=u?.require_password_change===1||u?.require_password_change===!0;(0,v.useEffect)(()=>{localStorage.setItem(`reader_fontSize`,W.fontSize),localStorage.setItem(`reader_fontFamily`,W.fontFamily),localStorage.setItem(`reader_lineHeight`,W.lineHeight),localStorage.setItem(`reader_theme`,W.theme)},[W]);let qt=async e=>{e.preventDefault(),Pt(!0),At(``),Mt(``);try{await g.post(`/api/auth/update-profile`,{display_name:w,birthday:T,gender:E,bio:D,avatar:k,avatar_frame:O}),At(C.saveSuccess);let e={...u,display_name:w,birthday:T,gender:E,bio:D,avatar:k,avatar_frame:O};d(e),localStorage.setItem(`user`,JSON.stringify(e))}catch(e){console.error(e);let t={...u,display_name:w,birthday:T,gender:E,bio:D,avatar:k,avatar_frame:O};d(t),localStorage.setItem(`user`,JSON.stringify(t)),At(C.saveSuccess)}finally{Pt(!1)}},Jt=async e=>{if(e.preventDefault(),j(``),Ne(``),A.length<4){j(C.passMinLen);return}if(A!==De){j(C.passMismatch);return}Ae(!0);try{let e={new_password:A};if(Kt||(e.old_password=we),Ne((await g.post(`/api/auth/change-password`,e)).data.message||C.passChangeSuccess),u){let e={...u,require_password_change:0};d(e),localStorage.setItem(`user`,JSON.stringify(e))}Te(``),Ee(``),Oe(``)}catch(e){j(e.response?.data?.error||C.passChangeError)}finally{Ae(!1)}},Yt=()=>{if(!M){alert(`Vui lòng nhập số điện thoại trước.`);return}Re(!0),alert(`Hệ thống đã giả lập mã OTP gửi tới `+M+`. Nhập 123456 để xác thực.`)},Xt=()=>{Fe===`123456`?(ze(!0),Re(!1),alert(`Xác thực số điện thoại thành công!`)):alert(`Mã OTP không chính xác. Thử lại với 123456.`)},Zt=()=>{if(!N){alert(`Bạn phải liên kết số điện thoại trước khi bật 2FA.`);return}Ve(!Be)},Qt=async e=>{if(window.confirm(`Bạn có chắc chắn muốn đăng xuất thiết bị này không?`))try{let t=await g.post(`/api/auth/sessions/revoke`,{session_id:e});t.data&&t.data.success&&zt()}catch(e){console.error(`Lỗi khi hủy phiên đăng nhập:`,e),alert(`Không thể đăng xuất thiết bị. Vui lòng thử lại sau.`)}},$t=async()=>{if(window.confirm(`Bạn có chắc chắn muốn đăng xuất tất cả các thiết bị khác không?`))try{let e=mt.filter(e=>!e.current);await Promise.all(e.map(e=>g.post(`/api/auth/sessions/revoke`,{session_id:e.id}))),zt()}catch(e){console.error(`Lỗi khi đăng xuất tất cả thiết bị khác:`,e),alert(`Lỗi khi thực hiện đăng xuất hàng loạt.`)}},en=e=>{_t(t=>t.includes(e)?t.filter(t=>t!==e):[...t,e])},tn=e=>{let t=Number(e);return isNaN(t)?`0 ₫`:new Intl.NumberFormat(`vi-VN`,{style:`currency`,currency:`VND`}).format(t)};return u?(0,y.jsxs)(ne,{children:[(0,y.jsxs)(`div`,{className:`max-w-6xl mx-auto space-y-6 pb-20`,children:[(0,y.jsxs)(`div`,{children:[(0,y.jsxs)(`h2`,{className:`text-2xl font-black text-white tracking-tight flex items-center gap-2`,children:[(0,y.jsx)(de,{className:`w-6 h-6 text-purple-400 animate-spin-slow`}),` `,m.settings?.title||`⚙️ Cài đặt Tài khoản`]}),(0,y.jsx)(`p`,{className:`text-slate-400 text-xs mt-1`,children:`Quản lý hồ sơ, ví tài sản, cấp bậc tu tiên, bảo mật hai lớp và cấu hình trình đọc đám mây.`})]}),Kt&&(0,y.jsxs)(`div`,{className:`p-4 bg-amber-500/10 border border-amber-500/30 rounded-2xl flex items-start gap-3 text-amber-300 text-sm shadow-lg shadow-amber-500/5`,children:[(0,y.jsx)(_,{className:`w-5 h-5 shrink-0 mt-0.5`}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`strong`,{className:`block font-bold mb-0.5`,children:m.settings?.mustChangePassTitle||`Yêu cầu đặt mật khẩu mới`}),m.settings?.mustChangePassDesc||`Đây là lần đầu tiên bạn đăng nhập bằng Google. Vui lòng thiết lập mật khẩu riêng cho tài khoản để có thể đăng nhập trực tiếp bằng Email sau này.`]})]}),(0,y.jsxs)(`div`,{className:`grid grid-cols-1 lg:grid-cols-4 gap-6`,children:[(0,y.jsxs)(`div`,{className:`lg:col-span-1 space-y-6`,children:[(0,y.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#1f1f3a] rounded-2xl p-5 flex flex-col items-center text-center shadow-xl`,children:[(0,y.jsxs)(`div`,{className:`relative mb-4`,children:[(0,y.jsx)(`div`,{className:`rounded-full ${(()=>{switch(O){case`vip`:return`bg-gradient-to-r from-amber-300 via-yellow-500 to-amber-300 shadow-[0_0_20px_rgba(251,191,36,0.6)] animate-pulse p-[4px]`;case`event`:return`bg-gradient-to-r from-purple-400 via-pink-500 to-indigo-500 shadow-[0_0_20px_rgba(168,85,247,0.6)] p-[4px]`;default:return`bg-slate-800 border border-slate-700/60 p-[2px]`}})()} flex items-center justify-center`,children:(0,y.jsxs)(`div`,{className:`w-20 h-20 rounded-full overflow-hidden flex items-center justify-center bg-[#0b0b14] text-white text-3xl font-black relative shadow-lg`,children:[(0,y.jsx)(`div`,{className:`absolute inset-0 bg-gradient-to-tr from-purple-600/30 to-brand-500/30`}),u.avatar?(0,y.jsx)(`img`,{src:u.avatar,className:`w-full h-full object-cover relative z-10`,alt:`avatar`}):(0,y.jsx)(`span`,{className:`relative z-10`,children:u.username?u.username[0].toUpperCase():`U`})]})}),u.vip_status===1&&(0,y.jsx)(`span`,{className:`absolute -bottom-1 -right-1 px-2.5 py-1 bg-gradient-to-r from-amber-400 to-yellow-500 text-[#0b0b14] font-black text-[9px] rounded-full uppercase tracking-wider shadow-[0_2px_8px_rgba(245,158,11,0.4)] border border-yellow-300 z-20`,children:`VIP`})]}),(0,y.jsx)(`h3`,{className:`font-extrabold text-white text-base truncate max-w-full`,children:w||u.username}),(0,y.jsx)(`p`,{className:`text-purple-400 text-[10px] font-bold mt-1 uppercase tracking-wider`,children:q.name}),(0,y.jsx)(`div`,{className:`w-full border-t border-white/5 my-4`}),(0,y.jsxs)(`div`,{className:`w-full text-left space-y-2.5`,children:[(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`span`,{className:`text-[9px] text-slate-500 font-bold uppercase tracking-wider block`,children:`Tên đăng nhập`}),(0,y.jsxs)(`span`,{className:`text-xs text-slate-200 font-bold`,children:[`@`,u.username]})]}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`span`,{className:`text-[9px] text-slate-500 font-bold uppercase tracking-wider block`,children:`Mã ID kết bạn`}),(0,y.jsxs)(`div`,{className:`flex items-center gap-1.5`,children:[(0,y.jsxs)(`span`,{className:`text-xs text-amber-300 font-mono font-bold tracking-widest`,children:[`#`,u.user_code||u.id]}),(0,y.jsx)(`button`,{onClick:()=>{navigator.clipboard.writeText(u.user_code||String(u.id)),alert(`Đã sao chép mã ID!`)},className:`text-[9px] text-slate-500 hover:text-purple-400 transition-colors`,title:`Sao chép mã ID`,children:`📋`})]}),(0,y.jsx)(`p`,{className:`text-[9px] text-slate-600 mt-0.5`,children:`Chia sẻ mã này để bạn bè thêm bạn`})]}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`span`,{className:`text-[9px] text-slate-500 font-bold uppercase tracking-wider block`,children:m.settings?.emailLabel||`Địa chỉ Email`}),(0,y.jsx)(`span`,{className:`text-xs text-slate-300 truncate block`,children:u.email||`Chưa thiết lập`})]})]})]}),(0,y.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#1f1f3a] rounded-2xl p-3 flex flex-row lg:flex-col gap-1 overflow-x-auto lg:overflow-visible no-scrollbar`,children:[(0,y.jsxs)(`button`,{onClick:()=>S(`profile`),className:`flex items-center gap-2.5 px-4 py-3 rounded-xl text-xs font-bold transition-all whitespace-nowrap shrink-0 lg:w-full text-left ${x===`profile`?`bg-purple-600 text-white shadow-md`:`text-slate-400 hover:text-white hover:bg-white/[0.03]`}`,children:[(0,y.jsx)(n,{className:`w-4 h-4`}),` `,C.profileTab]}),(0,y.jsxs)(`button`,{onClick:()=>S(`security`),className:`flex items-center gap-2.5 px-4 py-3 rounded-xl text-xs font-bold transition-all whitespace-nowrap shrink-0 lg:w-full text-left ${x===`security`?`bg-purple-600 text-white shadow-md`:`text-slate-400 hover:text-white hover:bg-white/[0.03]`}`,children:[(0,y.jsx)(se,{className:`w-4 h-4`}),` `,C.securityTab]}),(0,y.jsxs)(`button`,{onClick:()=>S(`preferences`),className:`flex items-center gap-2.5 px-4 py-3 rounded-xl text-xs font-bold transition-all whitespace-nowrap shrink-0 lg:w-full text-left ${x===`preferences`?`bg-purple-600 text-white shadow-md`:`text-slate-400 hover:text-white hover:bg-white/[0.03]`}`,children:[(0,y.jsx)(me,{className:`w-4 h-4`}),` `,C.prefTab]}),(0,y.jsxs)(`button`,{onClick:()=>S(`wallet`),className:`flex items-center gap-2.5 px-4 py-3 rounded-xl text-xs font-bold transition-all whitespace-nowrap shrink-0 lg:w-full text-left ${x===`wallet`?`bg-purple-600 text-white shadow-md`:`text-slate-400 hover:text-white hover:bg-white/[0.03]`}`,children:[(0,y.jsx)(oe,{className:`w-4 h-4`}),` `,C.walletTab]}),(0,y.jsxs)(`button`,{onClick:()=>S(`stats`),className:`flex items-center gap-2.5 px-4 py-3 rounded-xl text-xs font-bold transition-all whitespace-nowrap shrink-0 lg:w-full text-left ${x===`stats`?`bg-purple-600 text-white shadow-md`:`text-slate-400 hover:text-white hover:bg-white/[0.03]`}`,children:[(0,y.jsx)(pe,{className:`w-4 h-4`}),` Thống kê & Lịch sử`]}),(0,y.jsxs)(`button`,{onClick:()=>S(`desktop`),className:`flex items-center gap-2.5 px-4 py-3 rounded-xl text-xs font-bold transition-all whitespace-nowrap shrink-0 lg:w-full text-left ${x===`desktop`?`bg-purple-600 text-white shadow-md`:`text-slate-400 hover:text-white hover:bg-white/[0.03]`}`,children:[(0,y.jsx)(c,{className:`w-4 h-4`}),` `,p?`Cấu hình Desktop`:b?`Cấu hình Android`:`Tải Bản Desktop`]}),(0,y.jsxs)(`button`,{onClick:()=>S(`tts_models`),className:`flex items-center gap-2.5 px-4 py-3 rounded-xl text-xs font-bold transition-all whitespace-nowrap shrink-0 lg:w-full text-left ${x===`tts_models`?`bg-purple-600 text-white shadow-md`:`text-slate-400 hover:text-white hover:bg-white/[0.03]`}`,children:[(0,y.jsx)(ge,{className:`w-4 h-4`}),` Quản lý Giọng AI`]})]})]}),(0,y.jsxs)(`div`,{className:`lg:col-span-3 space-y-6`,children:[x===`profile`&&(0,y.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#1f1f3a] rounded-2xl p-6 shadow-xl space-y-6`,children:[(0,y.jsxs)(`div`,{className:`border-b border-[#1f1f3a]/60 pb-3`,children:[(0,y.jsxs)(`h3`,{className:`text-base font-extrabold text-white flex items-center gap-2`,children:[(0,y.jsx)(n,{className:`w-5 h-5 text-purple-400`}),` `,C.profileTab]}),(0,y.jsx)(`p`,{className:`text-xs text-slate-400 mt-1`,children:`Thông tin hiển thị khi đi viết đánh giá, lời giới thiệu bản thân.`})]}),kt&&(0,y.jsxs)(`div`,{className:`p-3.5 bg-emerald-500/10 border border-emerald-500/30 rounded-xl text-emerald-400 text-xs flex items-center gap-2`,children:[(0,y.jsx)(t,{className:`w-4 h-4`}),` `,kt]}),(0,y.jsxs)(`form`,{onSubmit:qt,className:`space-y-4`,children:[(0,y.jsxs)(`div`,{className:`bg-[#0b0b14]/60 p-4 border border-[#1f1f3a]/60 rounded-xl space-y-3`,children:[(0,y.jsx)(`label`,{className:`text-xs font-bold text-slate-400 uppercase tracking-wider block`,children:`Ảnh Đại Diện (Avatar)`}),(0,y.jsxs)(`div`,{className:`flex flex-col sm:flex-row items-center gap-4`,children:[(0,y.jsx)(`div`,{className:`w-16 h-16 rounded-full overflow-hidden flex items-center justify-center bg-[#05050a] text-white border border-purple-500/30 shrink-0`,children:k?(0,y.jsx)(`img`,{src:k,className:`w-full h-full object-cover`,alt:`Avatar Preview`,onError:e=>{e.target.src=``}}):(0,y.jsx)(`span`,{className:`text-xl font-bold`,children:u.username?u.username[0].toUpperCase():`U`})}),(0,y.jsxs)(`div`,{className:`flex-1 w-full space-y-1.5`,children:[(0,y.jsx)(`input`,{type:`text`,placeholder:`Dán liên kết hình ảnh (https://...) tại đây`,value:k,onChange:e=>Ce(e.target.value),className:`w-full px-4 py-2 bg-[#05050a] border border-[#1f1f3a] rounded-xl text-xs text-slate-200 outline-none focus:border-purple-500 transition-colors`}),(0,y.jsx)(`span`,{className:`text-[10px] text-slate-500 block`,children:`Hoặc chọn một trong các nhân vật đại diện dễ thương bên dưới:`})]})]}),(0,y.jsx)(`div`,{className:`grid grid-cols-4 sm:grid-cols-7 gap-2 pt-1.5`,children:[{name:`Nghịch Thiên`,url:`https://api.dicebear.com/7.x/adventurer/svg?seed=NghichThien`},{name:`Kiếm Hồn`,url:`https://api.dicebear.com/7.x/adventurer/svg?seed=KiemHon`},{name:`Thần Thú`,url:`https://api.dicebear.com/7.x/bottts/svg?seed=ThanThu`},{name:`Yêu Tộc`,url:`https://api.dicebear.com/7.x/avataaars/svg?seed=YeuToc`},{name:`Thư Sinh`,url:`https://api.dicebear.com/7.x/lorelei/svg?seed=ThuSinh`},{name:`Tử Yên`,url:`https://api.dicebear.com/7.x/lorelei/svg?seed=TuYen`},{name:`Tiêu Dao`,url:`https://api.dicebear.com/7.x/micah/svg?seed=TieuDao`}].map((e,t)=>(0,y.jsxs)(`button`,{type:`button`,onClick:()=>Ce(e.url),className:`p-1 bg-[#05050a] border rounded-lg hover:border-purple-500 hover:scale-105 transition-all flex flex-col items-center gap-1 ${k===e.url?`border-purple-500 bg-purple-500/10`:`border-[#1f1f3a]`}`,title:e.name,children:[(0,y.jsx)(`img`,{src:e.url,className:`w-8 h-8 rounded-full`,alt:e.name}),(0,y.jsx)(`span`,{className:`text-[8px] text-slate-500 truncate max-w-full`,children:e.name})]},t))})]}),(0,y.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-4`,children:[(0,y.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,y.jsx)(`label`,{className:`text-xs font-bold text-slate-400 uppercase tracking-wider`,children:C.displayName}),(0,y.jsx)(`input`,{type:`text`,placeholder:C.displayNamePlaceholder,value:w,onChange:e=>ve(e.target.value),className:`w-full px-4 py-2.5 bg-[#0b0b14] border border-[#1f1f3a] rounded-xl text-xs text-white outline-none focus:border-purple-500 transition-colors`})]}),(0,y.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,y.jsx)(`label`,{className:`text-xs font-bold text-slate-400 uppercase tracking-wider`,children:C.avatarFrame}),(0,y.jsxs)(`select`,{value:O,onChange:e=>Se(e.target.value),className:`w-full px-4 py-2.5 bg-[#0b0b14] border border-[#1f1f3a] rounded-xl text-xs text-slate-300 outline-none focus:border-purple-500`,children:[(0,y.jsx)(`option`,{value:`default`,children:C.frameDefault}),(0,y.jsxs)(`option`,{value:`vip`,disabled:u?.vip_status!==1,children:[C.frameVip,` `,!u?.vip_status&&`🔒`]}),(0,y.jsx)(`option`,{value:`event`,children:C.frameEvent})]})]})]}),(0,y.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-4`,children:[(0,y.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,y.jsx)(`label`,{className:`text-xs font-bold text-slate-400 uppercase tracking-wider`,children:C.birthday}),(0,y.jsx)(`input`,{type:`date`,value:T,onChange:e=>ye(e.target.value),className:`w-full px-4 py-2.5 bg-[#0b0b14] border border-[#1f1f3a] rounded-xl text-xs text-slate-300 outline-none focus:border-purple-500`})]}),(0,y.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,y.jsx)(`label`,{className:`text-xs font-bold text-slate-400 uppercase tracking-wider`,children:C.gender}),(0,y.jsx)(`div`,{className:`grid grid-cols-3 gap-2`,children:[`male`,`female`,`other`].map(e=>(0,y.jsx)(`button`,{type:`button`,onClick:()=>be(e),className:`py-2 px-3 text-xs font-bold rounded-xl border text-center transition-all ${E===e?`bg-purple-600/25 border-purple-500 text-purple-300`:`bg-[#0b0b14] border-[#1f1f3a] text-slate-400 hover:text-white`}`,children:e===`male`?C.genderMale:e===`female`?C.genderFemale:C.genderOther},e))})]})]}),(0,y.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,y.jsx)(`label`,{className:`text-xs font-bold text-slate-400 uppercase tracking-wider`,children:C.bio}),(0,y.jsx)(`textarea`,{rows:3,placeholder:C.bioPlaceholder,value:D,onChange:e=>xe(e.target.value),className:`w-full p-4 bg-[#0b0b14] border border-[#1f1f3a] rounded-xl text-xs text-slate-300 outline-none focus:border-purple-500 transition-colors`})]}),(0,y.jsxs)(`button`,{type:`submit`,disabled:Nt,className:`bg-purple-600 hover:bg-purple-500 disabled:opacity-50 text-white font-extrabold px-6 py-2.5 rounded-xl text-xs shadow-md transition-all flex items-center gap-1.5`,children:[Nt?(0,y.jsx)(a,{className:`w-3.5 h-3.5 animate-spin`}):null,C.saveBtn]})]})]}),x===`security`&&(0,y.jsxs)(`div`,{className:`space-y-6`,children:[(0,y.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#1f1f3a] rounded-2xl p-6 shadow-xl space-y-4`,children:[(0,y.jsxs)(`div`,{className:`flex items-center gap-2 border-b border-[#1f1f3a]/60 pb-3`,children:[(0,y.jsx)(o,{className:`w-5 h-5 text-brand-400`}),(0,y.jsx)(`h4`,{className:`font-extrabold text-white text-sm`,children:m.settings?.changePassTitle||`Đổi Mật Khẩu`})]}),je&&(0,y.jsx)(`div`,{className:`p-3 bg-red-500/10 border border-red-500/20 rounded-xl text-red-400 text-xs`,children:je}),Me&&(0,y.jsxs)(`div`,{className:`p-3 bg-emerald-500/10 border border-emerald-500/20 rounded-xl text-emerald-400 text-xs flex items-center gap-1.5`,children:[(0,y.jsx)(t,{className:`w-4 h-4`}),` `,Me]}),(0,y.jsxs)(`form`,{onSubmit:Jt,className:`space-y-4`,children:[!Kt&&(0,y.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,y.jsx)(`label`,{className:`block text-xs font-bold text-slate-400 uppercase tracking-wider`,children:m.settings?.currentPassLabel||`Mật khẩu hiện tại`}),(0,y.jsxs)(`div`,{className:`relative`,children:[(0,y.jsx)(s,{className:`absolute left-3.5 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-500`}),(0,y.jsx)(`input`,{type:`password`,placeholder:m.settings?.currentPassPlaceholder||`Nhập mật khẩu hiện tại`,value:we,onChange:e=>Te(e.target.value),className:`w-full pl-10 pr-4 py-2.5 bg-[#0b0b14] border border-[#1f1f3a] rounded-xl text-xs text-white outline-none focus:border-purple-500 transition-colors`,required:!0})]})]}),(0,y.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-4`,children:[(0,y.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,y.jsx)(`label`,{className:`block text-xs font-bold text-slate-400 uppercase tracking-wider`,children:m.settings?.newPassLabel||`Mật khẩu mới`}),(0,y.jsxs)(`div`,{className:`relative`,children:[(0,y.jsx)(s,{className:`absolute left-3.5 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-500`}),(0,y.jsx)(`input`,{type:`password`,placeholder:m.settings?.newPassPlaceholder||`Tối thiểu 4 ký tự`,value:A,onChange:e=>Ee(e.target.value),className:`w-full pl-10 pr-4 py-2.5 bg-[#0b0b14] border border-[#1f1f3a] rounded-xl text-xs text-white outline-none focus:border-purple-500 transition-colors`,required:!0})]})]}),(0,y.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,y.jsx)(`label`,{className:`block text-xs font-bold text-slate-400 uppercase tracking-wider`,children:m.settings?.confirmPassLabel||`Xác nhận mật khẩu mới`}),(0,y.jsxs)(`div`,{className:`relative`,children:[(0,y.jsx)(s,{className:`absolute left-3.5 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-500`}),(0,y.jsx)(`input`,{type:`password`,placeholder:m.settings?.confirmPassPlaceholder||`Xác nhận mật khẩu mới`,value:De,onChange:e=>Oe(e.target.value),className:`w-full pl-10 pr-4 py-2.5 bg-[#0b0b14] border border-[#1f1f3a] rounded-xl text-xs text-white outline-none focus:border-purple-500 transition-colors`,required:!0})]})]})]}),(0,y.jsx)(`button`,{type:`submit`,disabled:ke,className:`bg-purple-600 hover:bg-purple-500 disabled:opacity-50 text-white font-extrabold px-5 py-2.5 rounded-xl text-xs transition-all shadow-md`,children:ke?m.settings?.updating||`Đang cập nhật...`:m.settings?.updateBtn||`Cập nhật Mật khẩu`})]})]}),(0,y.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#1f1f3a] rounded-2xl p-6 shadow-xl space-y-4`,children:[(0,y.jsxs)(`div`,{className:`flex items-center gap-2 border-b border-[#1f1f3a]/60 pb-3`,children:[(0,y.jsx)(he,{className:`w-5 h-5 text-purple-400`}),(0,y.jsxs)(`h4`,{className:`font-extrabold text-white text-sm`,children:[C.phoneNumber,` & Xác thực OTP`]})]}),(0,y.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-4`,children:[(0,y.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,y.jsx)(`label`,{className:`text-xs font-bold text-slate-400 uppercase tracking-wider`,children:C.phoneNumber}),(0,y.jsxs)(`div`,{className:`flex gap-2`,children:[(0,y.jsx)(`input`,{type:`text`,placeholder:C.phonePlaceholder,value:M,onChange:e=>Pe(e.target.value),disabled:N,className:`flex-1 px-4 py-2.5 bg-[#0b0b14] border border-[#1f1f3a] rounded-xl text-xs text-white outline-none disabled:opacity-60 focus:border-purple-500`}),!N&&(0,y.jsx)(`button`,{type:`button`,onClick:Yt,className:`bg-purple-600 hover:bg-purple-500 text-white font-bold px-4 py-2.5 rounded-xl text-[10px] shrink-0`,children:Le?`Gửi lại`:C.getOtp})]})]}),Le&&(0,y.jsxs)(`div`,{className:`space-y-1.5 animate-in slide-in-from-top-2 duration-200`,children:[(0,y.jsx)(`label`,{className:`text-xs font-bold text-slate-400 uppercase tracking-wider`,children:C.enterOtp}),(0,y.jsxs)(`div`,{className:`flex gap-2`,children:[(0,y.jsx)(`input`,{type:`text`,placeholder:`Mã 6 số (123456)`,value:Fe,onChange:e=>Ie(e.target.value),className:`flex-1 px-4 py-2.5 bg-[#0b0b14] border border-[#1f1f3a] rounded-xl text-xs text-white outline-none text-center font-mono tracking-widest focus:border-purple-500`}),(0,y.jsx)(`button`,{type:`button`,onClick:Xt,className:`bg-emerald-600 hover:bg-emerald-500 text-white font-bold px-4 py-2.5 rounded-xl text-[10px] shrink-0`,children:C.verifyBtn})]})]}),N&&(0,y.jsxs)(`div`,{className:`flex items-center gap-1.5 text-emerald-400 text-xs font-bold mt-6`,children:[(0,y.jsx)(t,{className:`w-4 h-4`}),` Đã liên kết & xác thực OTP số điện thoại!`]})]}),(0,y.jsxs)(`div`,{className:`flex items-center justify-between p-4 bg-[#0b0b14]/50 border border-[#1f1f3a] rounded-xl mt-2`,children:[(0,y.jsxs)(`div`,{className:`space-y-1 max-w-[80%]`,children:[(0,y.jsx)(`strong`,{className:`text-xs text-white block`,children:C.twoFactor}),(0,y.jsx)(`span`,{className:`text-[10px] text-slate-400 block leading-relaxed`,children:C.twoFactorDesc})]}),(0,y.jsx)(`button`,{type:`button`,onClick:Zt,className:`relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${Be?`bg-purple-600`:`bg-slate-700`}`,children:(0,y.jsx)(`span`,{className:`pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out ${Be?`translate-x-5`:`translate-x-0`}`})})]})]}),(0,y.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#1f1f3a] rounded-2xl p-6 shadow-xl space-y-4`,children:[(0,y.jsxs)(`div`,{className:`border-b border-[#1f1f3a]/60 pb-3`,children:[(0,y.jsx)(`h4`,{className:`font-extrabold text-white text-sm`,children:C.authLinks}),(0,y.jsx)(`p`,{className:`text-[10px] text-slate-400 mt-1`,children:`Liên kết OAuth để đăng nhập nhanh bằng 1 click chuột.`})]}),(0,y.jsxs)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 gap-3`,children:[(0,y.jsxs)(`div`,{className:`flex items-center justify-between p-3.5 bg-[#0b0b14] border border-[#1f1f3a] rounded-xl`,children:[(0,y.jsxs)(`div`,{className:`flex items-center gap-2 text-xs font-bold text-white`,children:[(0,y.jsx)(`span`,{className:`text-base`,children:`🔴`}),` Google`]}),(0,y.jsxs)(`span`,{className:`text-[10px] text-emerald-400 font-extrabold uppercase flex items-center gap-1`,children:[(0,y.jsx)(ie,{className:`w-3.5 h-3.5`}),` `,C.authLinked]})]}),(0,y.jsxs)(`div`,{className:`flex items-center justify-between p-3.5 bg-[#0b0b14] border border-[#1f1f3a] rounded-xl`,children:[(0,y.jsxs)(`div`,{className:`flex items-center gap-2 text-xs font-bold text-white`,children:[(0,y.jsx)(`span`,{className:`text-base`,children:`🐙`}),` GitHub`]}),(0,y.jsx)(`button`,{onClick:()=>pt(e=>({...e,github:!0})),className:`px-3 py-1.5 rounded-lg text-[9px] font-extrabold transition-all uppercase ${U.github?`text-emerald-400 bg-emerald-500/10 border border-emerald-500/20`:`text-slate-400 bg-white/5 border border-white/10 hover:text-white`}`,children:U.github?C.authLinked:C.authLinkBtn})]}),(0,y.jsxs)(`div`,{className:`flex items-center justify-between p-3.5 bg-[#0b0b14] border border-[#1f1f3a] rounded-xl`,children:[(0,y.jsxs)(`div`,{className:`flex items-center gap-2 text-xs font-bold text-white`,children:[(0,y.jsx)(`span`,{className:`text-base`,children:`🔵`}),` Facebook`]}),(0,y.jsx)(`button`,{onClick:()=>pt(e=>({...e,facebook:!0})),className:`px-3 py-1.5 rounded-lg text-[9px] font-extrabold transition-all uppercase ${U.facebook?`text-emerald-400 bg-emerald-500/10 border border-emerald-500/20`:`text-slate-400 bg-white/5 border border-white/10 hover:text-white`}`,children:U.facebook?C.authLinked:C.authLinkBtn})]}),(0,y.jsxs)(`div`,{className:`flex items-center justify-between p-3.5 bg-[#0b0b14] border border-[#1f1f3a] rounded-xl`,children:[(0,y.jsxs)(`div`,{className:`flex items-center gap-2 text-xs font-bold text-white`,children:[(0,y.jsx)(`span`,{className:`text-base`,children:`🍏`}),` Apple ID`]}),(0,y.jsx)(`button`,{onClick:()=>pt(e=>({...e,apple:!0})),className:`px-3 py-1.5 rounded-lg text-[9px] font-extrabold transition-all uppercase ${U.apple?`text-emerald-400 bg-emerald-500/10 border border-emerald-500/20`:`text-slate-400 bg-white/5 border border-white/10 hover:text-white`}`,children:U.apple?C.authLinked:C.authLinkBtn})]})]})]}),(0,y.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#1f1f3a] rounded-2xl p-6 shadow-xl space-y-4`,children:[(0,y.jsxs)(`div`,{className:`flex items-center justify-between border-b border-[#1f1f3a]/60 pb-3`,children:[(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`h4`,{className:`font-extrabold text-white text-sm`,children:C.sessionTitle}),(0,y.jsx)(`p`,{className:`text-[10px] text-slate-400 mt-1`,children:C.sessionDesc})]}),mt.length>1&&(0,y.jsx)(`button`,{onClick:$t,className:`text-red-400 hover:text-red-300 font-extrabold text-[10px] transition-colors`,children:C.revokeAllSessions})]}),(0,y.jsx)(`div`,{className:`space-y-3`,children:mt.map(e=>(0,y.jsxs)(`div`,{className:`flex justify-between items-center p-3.5 bg-[#0b0b14] border border-[#1f1f3a] rounded-xl`,children:[(0,y.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,y.jsx)(`div`,{className:`p-2 bg-purple-600/10 border border-purple-500/25 rounded-lg text-purple-400`,children:e.device.includes(`iPhone`)?(0,y.jsx)(he,{className:`w-4 h-4`}):(0,y.jsx)(c,{className:`w-4 h-4`})}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`span`,{className:`text-xs font-bold text-white block`,children:e.device}),(0,y.jsxs)(`span`,{className:`text-[10px] text-slate-500 block mt-0.5`,children:[`IP: `,e.ip,` · `,e.location]})]})]}),(0,y.jsx)(`div`,{className:`flex items-center gap-2`,children:e.current?(0,y.jsx)(`span`,{className:`px-2 py-0.5 bg-emerald-500/10 border border-emerald-500/25 text-emerald-400 text-[9px] font-black uppercase rounded`,children:C.activeNow}):(0,y.jsx)(`button`,{onClick:()=>Qt(e.id),className:`p-1.5 bg-red-500/10 border border-red-500/25 rounded-lg text-red-400 hover:bg-red-500/20 transition-all`,title:C.revokeSession,children:(0,y.jsx)(l,{className:`w-3.5 h-3.5`})})})]},e.id))})]})]}),x===`preferences`&&(0,y.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#1f1f3a] rounded-2xl p-6 shadow-xl space-y-6`,children:[(0,y.jsxs)(`div`,{className:`border-b border-[#1f1f3a]/60 pb-3`,children:[(0,y.jsxs)(`h3`,{className:`text-base font-extrabold text-white flex items-center gap-2`,children:[(0,y.jsx)(me,{className:`w-5 h-5 text-purple-400`}),` `,C.readingConf]}),(0,y.jsx)(`p`,{className:`text-xs text-slate-400 mt-1`,children:`Cấu hình được tự động lưu lên đám mây và đồng bộ giữa các thiết bị di động/máy tính.`})]}),(0,y.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-6`,children:[(0,y.jsxs)(`div`,{className:`space-y-4`,children:[(0,y.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,y.jsxs)(`label`,{className:`text-xs font-bold text-slate-400 uppercase tracking-wider block`,children:[C.fontSize,` (`,W.fontSize,`px)`]}),(0,y.jsx)(`input`,{type:`range`,min:`12`,max:`32`,step:`1`,value:W.fontSize,onChange:e=>G(t=>({...t,fontSize:parseInt(e.target.value)})),className:`w-full accent-purple-500`})]}),(0,y.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,y.jsx)(`label`,{className:`text-xs font-bold text-slate-400 uppercase tracking-wider block`,children:C.fontFamily}),(0,y.jsxs)(`select`,{value:W.fontFamily,onChange:e=>G(t=>({...t,fontFamily:e.target.value})),className:`w-full px-4 py-2.5 bg-[#0b0b14] border border-[#1f1f3a] rounded-xl text-xs text-slate-300 outline-none`,children:[(0,y.jsx)(`option`,{value:`font-sans`,children:`Sans-serif (Hiện đại)`}),(0,y.jsx)(`option`,{value:`font-serif`,children:`Serif (Cổ điển)`}),(0,y.jsx)(`option`,{value:`font-mono`,children:`Monospace (Lập trình viên)`})]})]}),(0,y.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,y.jsx)(`label`,{className:`text-xs font-bold text-slate-400 uppercase tracking-wider block`,children:C.lineHeight}),(0,y.jsx)(`div`,{className:`grid grid-cols-3 gap-2`,children:[1.4,1.6,1.8].map(e=>(0,y.jsx)(`button`,{type:`button`,onClick:()=>G(t=>({...t,lineHeight:e})),className:`py-2 text-xs font-bold rounded-xl border text-center transition-all ${W.lineHeight===e?`bg-purple-600/25 border-purple-500 text-purple-300`:`bg-[#0b0b14] border-[#1f1f3a] text-slate-400 hover:text-white`}`,children:e===1.4?C.lineNormal:e===1.6?C.lineMedium:C.lineWide},e))})]}),(0,y.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,y.jsx)(`label`,{className:`text-xs font-bold text-slate-400 uppercase tracking-wider block`,children:C.themeBg}),(0,y.jsx)(`div`,{className:`grid grid-cols-3 gap-2`,children:[`light`,`dark`,`sepia`].map(e=>(0,y.jsx)(`button`,{type:`button`,onClick:()=>G(t=>({...t,theme:e})),className:`py-2 text-xs font-bold rounded-xl border text-center transition-all ${W.theme===e?`bg-purple-600/25 border-purple-500 text-purple-300`:`bg-[#0b0b14] border-[#1f1f3a] text-slate-400 hover:text-white`}`,children:e===`light`?C.themeLight:e===`dark`?C.themeDark:C.themeSepia},e))})]})]}),(0,y.jsxs)(`div`,{className:`bg-[#0b0b14] border border-[#1f1f3a] rounded-2xl p-4 flex flex-col justify-between space-y-4`,children:[(0,y.jsx)(`span`,{className:`text-[10px] text-slate-500 font-extrabold uppercase tracking-wider block`,children:`Xem trước hiển thị đọc`}),(0,y.jsxs)(`div`,{className:`p-4 rounded-xl border flex-1 transition-all ${W.theme===`light`?`bg-slate-100 text-slate-900 border-slate-200`:W.theme===`sepia`?`bg-[#f4eccf] text-[#433422] border-[#e4d6a7]`:`bg-[#0d0d1e] text-slate-200 border-purple-500/20`}`,style:{fontSize:`${W.fontSize}px`,lineHeight:W.lineHeight},children:[(0,y.jsx)(`h5`,{className:`font-extrabold mb-2 text-sm`,children:`Chương 1: Khởi Đầu Mới`}),(0,y.jsx)(`p`,{className:`text-[0.75em] ${W.fontFamily}`,children:`Thế giới này rộng lớn vô cùng. Võ giả rèn luyện khí huyết, đột phá xiềng xích nhân loại, bước lên con đường võ đạo đỉnh phong...`})]})]})]}),(0,y.jsx)(`div`,{className:`w-full border-t border-[#1f1f3a]/60 my-4`}),(0,y.jsxs)(`div`,{className:`space-y-3`,children:[(0,y.jsx)(`label`,{className:`text-xs font-bold text-slate-400 uppercase tracking-wider block`,children:C.favCategories}),(0,y.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:[`玄幻`,`都市`,`言情`,`女生`,`科幻`,`修真`,`仙侠`,`武侠`,`历史`,`网游`,`同人`,`其他`].map(e=>{let t=e===`玄幻`?`Huyền Huyễn`:e===`都市`?`Đô Thị`:e===`言情`?`Ngôn Tình`:e===`科幻`?`Khoa Huyễn`:e===`仙侠`?`Tiên Hiệp`:e===`修真`?`Tu Chân`:e,n=gt.includes(e);return(0,y.jsxs)(`button`,{type:`button`,onClick:()=>en(e),className:`px-3 py-1.5 rounded-full text-xs font-bold border transition-all ${n?`bg-purple-600 border-purple-500 text-white shadow-md`:`bg-[#0b0b14] border-[#1f1f3a] text-slate-400 hover:text-white`}`,children:[t,` `,n&&`✓`]},e)})})]}),(0,y.jsx)(`div`,{className:`w-full border-t border-[#1f1f3a]/60 my-4`}),(0,y.jsxs)(`div`,{className:`space-y-3`,children:[(0,y.jsx)(`label`,{className:`text-xs font-bold text-slate-400 uppercase tracking-wider block`,children:C.notificationSettings}),(0,y.jsxs)(`div`,{className:`space-y-3`,children:[(0,y.jsxs)(`div`,{className:`flex items-center justify-between p-3.5 bg-[#0b0b14]/50 border border-[#1f1f3a] rounded-xl`,children:[(0,y.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,y.jsx)(r,{className:`w-4 h-4 text-purple-400`}),(0,y.jsx)(`span`,{className:`text-xs text-slate-200 font-bold`,children:C.notifyNewChapters})]}),(0,y.jsx)(`button`,{type:`button`,onClick:()=>vt(e=>({...e,newChapter:!e.newChapter})),className:`relative inline-flex h-5 w-9 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${K.newChapter?`bg-purple-600`:`bg-slate-700`}`,children:(0,y.jsx)(`span`,{className:`pointer-events-none inline-block h-4 w-4 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out ${K.newChapter?`translate-x-4`:`translate-x-0`}`})})]}),(0,y.jsxs)(`div`,{className:`flex items-center justify-between p-3.5 bg-[#0b0b14]/50 border border-[#1f1f3a] rounded-xl`,children:[(0,y.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,y.jsx)(ee,{className:`w-4 h-4 text-purple-400`}),(0,y.jsx)(`span`,{className:`text-xs text-slate-200 font-bold`,children:C.notifyReplies})]}),(0,y.jsx)(`button`,{type:`button`,onClick:()=>vt(e=>({...e,replies:!e.replies})),className:`relative inline-flex h-5 w-9 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${K.replies?`bg-purple-600`:`bg-slate-700`}`,children:(0,y.jsx)(`span`,{className:`pointer-events-none inline-block h-4 w-4 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out ${K.replies?`translate-x-4`:`translate-x-0`}`})})]})]})]})]}),x===`wallet`&&(0,y.jsxs)(`div`,{className:`space-y-6`,children:[(0,y.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#1f1f3a] rounded-2xl p-6 shadow-xl space-y-4`,children:[(0,y.jsxs)(`div`,{className:`flex justify-between items-center border-b border-[#1f1f3a]/60 pb-3`,children:[(0,y.jsxs)(`h3`,{className:`text-base font-extrabold text-white flex items-center gap-2`,children:[(0,y.jsx)(e,{className:`w-5 h-5 text-amber-400 animate-pulse`}),` `,C.accountLevel]}),(0,y.jsx)(`span`,{className:`text-[10px] bg-amber-500/10 border border-amber-500/20 text-amber-400 px-2 py-0.5 rounded font-black uppercase`,children:q.rank})]}),(0,y.jsxs)(`div`,{className:`space-y-3`,children:[(0,y.jsxs)(`div`,{className:`flex justify-between text-xs`,children:[(0,y.jsxs)(`span`,{className:`text-slate-400 font-bold`,children:[C.levelTitle,`: `,(0,y.jsx)(`strong`,{className:`text-white font-extrabold`,children:q.name})]}),(0,y.jsxs)(`span`,{className:`text-slate-400 font-mono`,children:[q.exp,` / `,q.maxExp,` EXP`]})]}),(0,y.jsx)(`div`,{className:`w-full bg-[#0b0b14] h-3.5 rounded-full overflow-hidden border border-[#1f1f3a] p-0.5`,children:(0,y.jsx)(`div`,{className:`bg-gradient-to-r from-amber-400 via-purple-500 to-indigo-600 h-full rounded-full transition-all duration-1000`,style:{width:`${q.exp/q.maxExp*100}%`}})}),(0,y.jsxs)(`span`,{className:`text-[9px] text-slate-500 block italic leading-relaxed`,children:[`💡 `,C.expNeeded,`: `,q.maxExp-q.exp,` EXP. Đọc thêm truyện mỗi ngày hoặc ủng hộ dịch giả để thăng cấp cảnh giới nhanh hơn!`]})]}),(0,y.jsxs)(`div`,{className:`space-y-2 pt-2`,children:[(0,y.jsx)(`label`,{className:`text-xs font-bold text-slate-400 uppercase tracking-wider block`,children:C.titlesBadges}),(0,y.jsx)(`div`,{className:`grid grid-cols-3 gap-2`,children:bt.map(e=>(0,y.jsxs)(`div`,{className:`p-3 rounded-xl border text-center space-y-1 ${e.color} relative overflow-hidden transition-all hover:scale-102`,children:[(0,y.jsx)(`span`,{className:`text-lg block`,children:e.icon}),(0,y.jsx)(`strong`,{className:`text-[10px] font-bold block whitespace-nowrap`,children:e.title})]},e.id))})]})]}),(0,y.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#1f1f3a] rounded-2xl p-6 shadow-xl space-y-6`,children:[(0,y.jsx)(`div`,{className:`border-b border-[#1f1f3a]/60 pb-3`,children:(0,y.jsxs)(`h3`,{className:`text-base font-extrabold text-white flex items-center gap-2`,children:[(0,y.jsx)(oe,{className:`w-5 h-5 text-purple-400`}),` `,C.walletBalance]})}),(0,y.jsxs)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 gap-4`,children:[(0,y.jsxs)(`div`,{className:`bg-[#0b0b14] border border-[#1f1f3a] rounded-xl p-4 flex items-center justify-between`,children:[(0,y.jsxs)(`div`,{className:`space-y-0.5`,children:[(0,y.jsx)(`span`,{className:`text-[9px] text-slate-500 font-bold uppercase tracking-wider block`,children:C.depositCoin}),(0,y.jsx)(`strong`,{className:`text-lg text-emerald-400 font-black font-mono`,children:J.coins.toLocaleString()})]}),(0,y.jsx)(`span`,{className:`text-2xl`,children:`🪙`})]}),(0,y.jsxs)(`div`,{className:`bg-[#0b0b14] border border-[#1f1f3a] rounded-xl p-4 flex items-center justify-between`,children:[(0,y.jsxs)(`div`,{className:`space-y-0.5`,children:[(0,y.jsx)(`span`,{className:`text-[9px] text-slate-500 font-bold uppercase tracking-wider block`,children:C.bonusCoin}),(0,y.jsx)(`strong`,{className:`text-lg text-amber-400 font-black font-mono`,children:J.bonus.toLocaleString()})]}),(0,y.jsx)(`span`,{className:`text-2xl`,children:`🎁`})]})]}),(0,y.jsxs)(`div`,{className:`space-y-2`,children:[(0,y.jsx)(`label`,{className:`text-xs font-bold text-slate-400 uppercase tracking-wider block`,children:C.itemInventory}),(0,y.jsxs)(`div`,{className:`grid grid-cols-3 gap-3`,children:[(0,y.jsxs)(`div`,{className:`bg-[#0b0b14] border border-[#1f1f3a] rounded-xl p-3 text-center space-y-1`,children:[(0,y.jsx)(`span`,{className:`text-xl block`,children:`🎫`}),(0,y.jsx)(`strong`,{className:`text-[10px] text-white block`,children:C.itemRecommendation}),(0,y.jsxs)(`span`,{className:`text-xs text-purple-400 font-black font-mono`,children:[`x`,J.tickets]})]}),(0,y.jsxs)(`div`,{className:`bg-[#0b0b14] border border-[#1f1f3a] rounded-xl p-3 text-center space-y-1`,children:[(0,y.jsx)(`span`,{className:`text-xl block`,children:`⚡`}),(0,y.jsx)(`strong`,{className:`text-[10px] text-white block`,children:C.itemVote}),(0,y.jsxs)(`span`,{className:`text-xs text-purple-400 font-black font-mono`,children:[`x`,J.votes]})]}),(0,y.jsxs)(`div`,{className:`bg-[#0b0b14] border border-[#1f1f3a] rounded-xl p-3 text-center space-y-1`,children:[(0,y.jsx)(`span`,{className:`text-xl block`,children:`💎`}),(0,y.jsx)(`strong`,{className:`text-[10px] text-white block`,children:C.itemGift}),(0,y.jsxs)(`span`,{className:`text-xs text-purple-400 font-black font-mono`,children:[`x`,J.gifts]})]})]})]})]}),(0,y.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#1f1f3a] rounded-2xl p-6 shadow-xl space-y-4`,children:[(0,y.jsxs)(`div`,{className:`flex justify-between items-center border-b border-[#1f1f3a]/60 pb-3`,children:[(0,y.jsx)(`h3`,{className:`text-sm font-extrabold text-white`,children:C.txHistory}),(0,y.jsxs)(`div`,{className:`flex gap-1 bg-[#0b0b14] border border-[#1f1f3a] rounded-lg p-0.5`,children:[(0,y.jsx)(`button`,{onClick:()=>wt(`deposit`),className:`px-3 py-1 rounded text-[10px] font-bold transition-all ${Ct===`deposit`?`bg-purple-600 text-white`:`text-slate-400 hover:text-white`}`,children:C.txTabDeposit}),(0,y.jsx)(`button`,{onClick:()=>wt(`expense`),className:`px-3 py-1 rounded text-[10px] font-bold transition-all ${Ct===`expense`?`bg-purple-600 text-white`:`text-slate-400 hover:text-white`}`,children:C.txTabExpense})]})]}),(0,y.jsx)(`div`,{className:`overflow-x-auto`,children:(0,y.jsxs)(`table`,{className:`w-full text-left text-[11px] text-slate-300`,children:[(0,y.jsx)(`thead`,{children:(0,y.jsxs)(`tr`,{className:`border-b border-[#1f1f3a] text-slate-500 font-bold`,children:[(0,y.jsx)(`th`,{className:`pb-2`,children:C.txDetail}),(0,y.jsx)(`th`,{className:`pb-2`,children:C.txCost}),(0,y.jsx)(`th`,{className:`pb-2`,children:C.txTime}),(0,y.jsx)(`th`,{className:`pb-2 text-right`,children:C.txStatus})]})}),(0,y.jsx)(`tbody`,{className:`divide-y divide-[#1f1f3a]/30`,children:Ct===`deposit`?Tt.map(e=>(0,y.jsxs)(`tr`,{className:`hover:bg-white/[0.01]`,children:[(0,y.jsx)(`td`,{className:`py-2.5 font-semibold text-white`,children:e.detail}),(0,y.jsxs)(`td`,{className:`py-2.5 text-emerald-400 font-bold`,children:[`+`,tn(e.amount)]}),(0,y.jsx)(`td`,{className:`py-2.5 text-slate-500 font-mono`,children:e.time}),(0,y.jsx)(`td`,{className:`py-2.5 text-right`,children:(0,y.jsx)(`span`,{className:`px-1.5 py-0.5 bg-emerald-500/10 border border-emerald-500/25 text-emerald-400 rounded text-[9px] font-black uppercase`,children:`Thành công`})})]},e.id)):Dt.map(e=>(0,y.jsxs)(`tr`,{className:`hover:bg-white/[0.01]`,children:[(0,y.jsx)(`td`,{className:`py-2.5 font-semibold text-white`,children:e.detail}),(0,y.jsxs)(`td`,{className:`py-2.5 text-red-400 font-bold`,children:[e.amount<0?`-`:`+`,tn(Math.abs(e.amount))]}),(0,y.jsx)(`td`,{className:`py-2.5 text-slate-500 font-mono`,children:e.time}),(0,y.jsx)(`td`,{className:`py-2.5 text-right`,children:(0,y.jsx)(`span`,{className:`px-1.5 py-0.5 bg-emerald-500/10 border border-emerald-500/25 text-emerald-400 rounded text-[9px] font-black uppercase`,children:`Thành công`})})]},e.id))})]})})]})]}),x===`stats`&&(0,y.jsx)(`div`,{className:`space-y-6 animate-fade-in`,children:(0,y.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#1f1f3a] rounded-2xl p-6 shadow-xl space-y-4`,children:[(0,y.jsxs)(`div`,{className:`border-b border-[#1f1f3a]/60 pb-3 flex justify-between items-center`,children:[(0,y.jsxs)(`h3`,{className:`text-base font-extrabold text-white flex items-center gap-2`,children:[(0,y.jsx)(pe,{className:`w-5 h-5 text-purple-400`}),` Thống Kê & Lịch Sử Sử Dụng`]}),(0,y.jsx)(`button`,{onClick:async()=>{X(!0);try{let[e,t]=await Promise.all([g.get(`/api/user/stats`),g.get(`/api/user/history`)]);Ft(e.data?.stats||e.data||null),Lt(t.data?.history||t.data||[])}catch{}X(!1)},className:`p-2 text-slate-400 hover:text-white hover:bg-white/[0.05] rounded-lg transition-all`,title:`Làm mới`,children:(0,y.jsx)(a,{className:`w-4 h-4 ${Rt?`animate-spin`:``}`})})]}),Rt?(0,y.jsxs)(`div`,{className:`py-12 flex flex-col items-center justify-center space-y-3`,children:[(0,y.jsx)(a,{className:`w-8 h-8 text-purple-500 animate-spin`}),(0,y.jsx)(`span`,{className:`text-xs text-slate-400 font-medium animate-pulse`,children:`Đang tải dữ liệu hệ thống...`})]}):u?(0,y.jsxs)(y.Fragment,{children:[(0,y.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-3 gap-4`,children:[(0,y.jsxs)(`div`,{className:`bg-[#0b0b14] border border-[#1f1f3a] rounded-xl p-4 flex items-center gap-4`,children:[(0,y.jsx)(`div`,{className:`w-12 h-12 bg-purple-500/10 text-purple-400 rounded-full flex items-center justify-center shrink-0`,children:(0,y.jsx)(ae,{className:`w-6 h-6`})}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`span`,{className:`text-[10px] text-slate-500 font-bold uppercase tracking-wider block`,children:`TỔNG THỜI GIAN ĐỌC`}),(0,y.jsx)(`span`,{className:`text-lg font-extrabold text-white block mt-0.5`,children:Y?Z(Y.total_reading_time):`0 phút`}),(0,y.jsx)(`span`,{className:`text-[9px] text-slate-400 block mt-0.5`,children:`Tính cả Web và Chrome Extension`})]})]}),(0,y.jsxs)(`div`,{className:`bg-[#0b0b14] border border-[#1f1f3a] rounded-xl p-4 flex items-center gap-4`,children:[(0,y.jsx)(`div`,{className:`w-12 h-12 bg-blue-500/10 text-blue-400 rounded-full flex items-center justify-center shrink-0`,children:(0,y.jsx)(c,{className:`w-6 h-6`})}),(0,y.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,y.jsx)(`span`,{className:`text-[10px] text-slate-500 font-bold uppercase tracking-wider block`,children:`MÔI TRƯỜNG ĐỌC`}),(0,y.jsxs)(`div`,{className:`flex justify-between items-center text-xs mt-1 text-slate-300`,children:[(0,y.jsxs)(`span`,{className:`flex items-center gap-1 font-medium`,children:[(0,y.jsx)(ge,{className:`w-3.5 h-3.5 text-blue-400`}),` Web:`]}),(0,y.jsx)(`span`,{className:`font-extrabold text-white`,children:Y?Z(Y.web_duration):`0m`})]}),(0,y.jsxs)(`div`,{className:`flex justify-between items-center text-xs mt-0.5 text-slate-300`,children:[(0,y.jsxs)(`span`,{className:`flex items-center gap-1 font-medium`,children:[(0,y.jsx)(he,{className:`w-3.5 h-3.5 text-indigo-400`}),` Ext:`]}),(0,y.jsx)(`span`,{className:`font-extrabold text-white`,children:Y?Z(Y.ext_duration):`0m`})]})]})]}),(0,y.jsxs)(`div`,{className:`bg-[#0b0b14] border border-[#1f1f3a] rounded-xl p-4 flex items-center gap-4`,children:[(0,y.jsx)(`div`,{className:`w-12 h-12 bg-emerald-500/10 text-emerald-400 rounded-full flex items-center justify-center shrink-0`,children:(0,y.jsx)(fe,{className:`w-6 h-6`})}),(0,y.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,y.jsx)(`span`,{className:`text-[10px] text-slate-500 font-bold uppercase tracking-wider block`,children:`CHẾ ĐỘ KẾT NỐI`}),(0,y.jsxs)(`div`,{className:`flex justify-between items-center text-xs mt-1 text-slate-300`,children:[(0,y.jsx)(`span`,{className:`flex items-center gap-1 font-medium text-emerald-400`,children:`● Online:`}),(0,y.jsx)(`span`,{className:`font-extrabold text-white`,children:Y?Z(Y.online_duration):`0m`})]}),(0,y.jsxs)(`div`,{className:`flex justify-between items-center text-xs mt-0.5 text-slate-300`,children:[(0,y.jsx)(`span`,{className:`flex items-center gap-1 font-medium text-amber-500`,children:`○ Offline:`}),(0,y.jsx)(`span`,{className:`font-extrabold text-white`,children:Y?Z(Y.offline_duration):`0m`})]})]})]})]}),(0,y.jsxs)(`div`,{className:`bg-[#0b0b14] border border-[#1f1f3a] rounded-xl p-5 mt-4`,children:[(0,y.jsxs)(`h4`,{className:`text-xs font-bold text-slate-300 uppercase tracking-wider mb-3 flex items-center gap-1.5`,children:[(0,y.jsx)(i,{className:`w-4 h-4 text-purple-400 animate-pulse`}),` Hiệu suất dịch thuật & Đọc sách`]}),(0,y.jsxs)(`div`,{className:`grid grid-cols-2 gap-4`,children:[(0,y.jsxs)(`div`,{className:`p-3 bg-[#121225] border border-[#1f1f3a]/60 rounded-lg`,children:[(0,y.jsx)(`span`,{className:`text-[10px] text-slate-500 font-bold uppercase tracking-wider block`,children:`Tổng Số Lượt Dịch`}),(0,y.jsxs)(`span`,{className:`text-xl font-extrabold text-purple-400 block mt-1`,children:[Y?.translation_calls||0,` lượt`]})]}),(0,y.jsxs)(`div`,{className:`p-3 bg-[#121225] border border-[#1f1f3a]/60 rounded-lg`,children:[(0,y.jsx)(`span`,{className:`text-[10px] text-slate-500 font-bold uppercase tracking-wider block`,children:`Ký tự đã dịch (AI/Convert)`}),(0,y.jsxs)(`span`,{className:`text-xl font-extrabold text-indigo-400 block mt-1`,children:[Y?.translation_chars?Y.translation_chars.toLocaleString():0,` ký tự`]})]})]})]}),(0,y.jsxs)(`div`,{className:`bg-[#0b0b14] border border-[#1f1f3a] rounded-xl p-5 mt-4 space-y-3`,children:[(0,y.jsxs)(`h4`,{className:`text-xs font-bold text-slate-300 uppercase tracking-wider flex items-center gap-1.5`,children:[(0,y.jsx)(re,{className:`w-4 h-4 text-purple-400`}),` Lịch sử click xem & Đọc chương gần đây`]}),It.length===0?(0,y.jsx)(`p`,{className:`text-xs text-slate-500 text-center py-6`,children:`Chưa có lịch sử click xem truyện.`}):(0,y.jsx)(`div`,{className:`space-y-4`,children:It.map((e,t)=>(0,y.jsxs)(`div`,{className:`space-y-2`,children:[(0,y.jsx)(`span`,{className:`text-[10px] text-purple-400 font-bold uppercase tracking-widest block border-b border-[#1f1f3a]/40 pb-1`,children:e.group_name}),(0,y.jsx)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-3`,children:e.books.map((e,t)=>(0,y.jsxs)(`div`,{className:`p-3 bg-[#121225] border border-[#1f1f3a]/60 rounded-lg flex gap-3 items-center hover:border-purple-500/50 transition-all group relative overflow-hidden`,children:[(0,y.jsx)(`div`,{className:`w-9 h-12 bg-slate-800 rounded overflow-hidden shrink-0`,children:e.cover?(0,y.jsx)(`img`,{src:e.cover,alt:e.title,className:`w-full h-full object-cover`}):(0,y.jsx)(`div`,{className:`w-full h-full flex items-center justify-center text-[10px] text-slate-500`,children:`Ảnh`})}),(0,y.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,y.jsx)(`strong`,{className:`text-xs font-bold text-white block truncate group-hover:text-purple-400 transition-colors`,children:e.title}),(0,y.jsxs)(`span`,{className:`text-[10px] text-slate-400 block truncate mt-0.5`,children:[`Tác giả: `,e.author||`Ẩn danh`]}),(0,y.jsxs)(`span`,{className:`text-[9px] text-slate-500 block truncate mt-0.5 font-mono`,children:[`Chương cuối: `,e.last_chapter||`Chưa đọc`]})]}),e.url&&(0,y.jsx)(`a`,{href:e.url,target:`_blank`,rel:`noreferrer`,className:`absolute top-2 right-2 p-1 text-slate-500 hover:text-white bg-[#0b0b14] border border-[#1f1f3a] rounded-md text-[10px] hover:bg-purple-600 transition-all opacity-0 group-hover:opacity-100`,children:`Mở lại`})]},t))})]},t))})]}),(0,y.jsxs)(`div`,{className:`bg-[#0b0b14] border border-[#1f1f3a] rounded-xl p-5 mt-4 space-y-3`,children:[(0,y.jsxs)(`h4`,{className:`text-xs font-bold text-slate-300 uppercase tracking-wider flex items-center gap-1.5`,children:[(0,y.jsx)(me,{className:`w-4 h-4 text-purple-400`}),` Nhật ký sử dụng hệ thống`]}),!Y?.recent_actions||Y.recent_actions.length===0?(0,y.jsx)(`p`,{className:`text-xs text-slate-500 text-center py-6`,children:`Chưa ghi nhận hoạt động nào gần đây.`}):(0,y.jsx)(`div`,{className:`max-h-[220px] overflow-y-auto divide-y divide-[#1f1f3a]/30 pr-1.5 custom-scrollbar`,children:Y.recent_actions.map((e,t)=>(0,y.jsxs)(`div`,{className:`py-2.5 flex justify-between items-center text-xs`,children:[(0,y.jsxs)(`div`,{className:`space-y-0.5`,children:[(0,y.jsx)(`span`,{className:`font-bold text-white`,children:e.details||e.action_type}),(0,y.jsxs)(`div`,{className:`flex items-center gap-2 text-[10px] text-slate-500`,children:[(0,y.jsx)(`span`,{className:`capitalize`,children:e.app_type===`extension`?`Chrome Extension`:`Web App`}),(0,y.jsx)(`span`,{children:`•`}),(0,y.jsx)(`span`,{children:e.connection_status===`online`?`Online`:`Offline`})]})]}),(0,y.jsxs)(`span`,{className:`text-[10px] text-slate-500 font-mono`,children:[new Date(e.timestamp).toLocaleTimeString(`vi-VN`,{hour:`2-digit`,minute:`2-digit`}),` `,new Date(e.timestamp).toLocaleDateString(`vi-VN`)]})]},t))})]})]}):(0,y.jsxs)(`div`,{className:`p-8 text-center bg-[#0b0b14]/50 rounded-xl border border-[#1f1f3a] space-y-4`,children:[(0,y.jsx)(`div`,{className:`w-12 h-12 bg-amber-500/10 text-amber-400 rounded-full flex items-center justify-center mx-auto`,children:(0,y.jsx)(_,{className:`w-6 h-6`})}),(0,y.jsxs)(`div`,{className:`space-y-1`,children:[(0,y.jsx)(`h4`,{className:`text-sm font-bold text-white`,children:`Yêu cầu đăng nhập`}),(0,y.jsx)(`p`,{className:`text-xs text-slate-400 max-w-md mx-auto leading-relaxed`,children:`Bạn đang trải nghiệm dưới quyền Khách. Hãy đăng nhập tài khoản để đồng bộ và xem chi tiết thời gian đọc (Web vs Chrome Extension, Online vs Offline) cũng như số liệu dịch thuật.`})]})]})]})}),x===`desktop`&&(0,y.jsx)(`div`,{className:`space-y-6 animate-fade-in`,children:(0,y.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#1f1f3a] rounded-2xl p-6 shadow-xl space-y-6`,children:[(0,y.jsxs)(`div`,{className:`border-b border-[#1f1f3a]/60 pb-3`,children:[(0,y.jsxs)(`h3`,{className:`text-base font-extrabold text-white flex items-center gap-2`,children:[(0,y.jsx)(c,{className:`w-5 h-5 text-purple-400`}),` `,p?`Cấu Hình Phiên Bản Desktop`:b?`Cấu Hình Thiết Bị Android`:`Cấu hình Desktop & Tải Bản Desktop`]}),(0,y.jsx)(`p`,{className:`text-xs text-slate-400 mt-1`,children:p?`Đồng bộ ngoại tuyến, tối ưu tài nguyên phần cứng và điều khiển nâng cao.`:b?`Đồng bộ cấu hình, tối ưu tài nguyên thiết bị di động Android của bạn.`:`Đồng bộ ngoại tuyến, tối ưu tài nguyên phần cứng và điều khiển nâng cao.`})]}),p||b?(0,y.jsxs)(`div`,{className:`space-y-6`,children:[(0,y.jsxs)(`div`,{className:`bg-[#0b0b14]/50 border border-[#1f1f3a] p-5 rounded-2xl space-y-4`,children:[(0,y.jsx)(`h4`,{className:`text-xs font-bold text-white uppercase tracking-wider block`,children:`Thư mục tải sách ngoại tuyến (Offline Download Folder)`}),(0,y.jsxs)(`div`,{className:`flex flex-col sm:flex-row gap-3`,children:[(0,y.jsx)(`input`,{type:`text`,value:P,readOnly:!0,className:`flex-1 px-4 py-2.5 bg-[#05050a] border border-[#1f1f3a] rounded-xl text-xs text-slate-300 outline-none`}),!b&&(0,y.jsx)(`button`,{type:`button`,onClick:async()=>{let e=h();if(e&&e.selectDirectory){let t=await e.selectDirectory(`Chọn thư mục lưu trữ sách`);t&&(Ue(t),localStorage.setItem(`electron_downloadFolder`,t),alert(`Đã đổi thư mục lưu trữ thành: ${t}`))}},className:`bg-purple-600 hover:bg-purple-500 text-white font-extrabold px-5 py-2.5 rounded-xl text-xs transition-colors shrink-0`,children:`Chọn thư mục`})]}),(0,y.jsx)(`p`,{className:`text-[10px] text-slate-500`,children:`Các chương truyện được tải xuống sẽ được lưu trữ cục bộ tại đường dẫn này để đọc khi không có mạng.`})]}),(0,y.jsxs)(`div`,{className:`bg-[#0b0b14]/50 border border-[#1f1f3a] p-5 rounded-2xl space-y-4`,children:[(0,y.jsx)(`h4`,{className:`text-xs font-bold text-white uppercase tracking-wider block`,children:`Thông số hệ thống (System Information)`}),Ge?(0,y.jsxs)(`div`,{className:`flex items-center gap-2 text-xs text-slate-400`,children:[(0,y.jsx)(a,{className:`w-3.5 h-3.5 animate-spin text-purple-400`}),`Đang lấy thông số phần cứng...`]}):F?(0,y.jsxs)(`div`,{className:`grid grid-cols-2 sm:grid-cols-3 gap-4`,children:[(0,y.jsxs)(`div`,{className:`p-3 bg-[#05050a] border border-[#1f1f3a]/60 rounded-xl`,children:[(0,y.jsx)(`span`,{className:`text-[9px] text-slate-500 font-bold uppercase block`,children:`Hệ điều hành`}),(0,y.jsxs)(`span`,{className:`text-xs font-extrabold text-white capitalize`,children:[F.platform,` (`,F.arch,`)`]})]}),(0,y.jsxs)(`div`,{className:`p-3 bg-[#05050a] border border-[#1f1f3a]/60 rounded-xl`,children:[(0,y.jsx)(`span`,{className:`text-[9px] text-slate-500 font-bold uppercase block`,children:`Số nhân CPU`}),(0,y.jsxs)(`span`,{className:`text-xs font-extrabold text-white`,children:[F.cpuCount,` Core`]})]}),(0,y.jsxs)(`div`,{className:`p-3 bg-[#05050a] border border-[#1f1f3a]/60 rounded-xl col-span-2 sm:col-span-1`,children:[(0,y.jsx)(`span`,{className:`text-[9px] text-slate-500 font-bold uppercase block`,children:`Bộ nhớ RAM`}),(0,y.jsxs)(`span`,{className:`text-xs font-extrabold text-white`,children:[F.freeMemoryGB,` GB trống / `,F.totalMemoryGB,` GB`]})]}),(0,y.jsxs)(`div`,{className:`p-3 bg-[#05050a] border border-[#1f1f3a]/60 rounded-xl col-span-2 sm:col-span-3`,children:[(0,y.jsx)(`span`,{className:`text-[9px] text-slate-500 font-bold uppercase block`,children:p?`Phiên bản Ứng dụng Desktop`:`Phiên bản Ứng dụng Android`}),(0,y.jsx)(`span`,{className:`text-xs font-extrabold text-purple-400`,children:p?`v${F.version} - Chạy bằng Electron & Node.js`:`v${F.version} - Chạy bằng Capacitor & WebKit`})]})]}):(0,y.jsx)(`p`,{className:`text-xs text-red-400`,children:`Không tìm thấy API Electron Main Process.`})]}),(0,y.jsxs)(`div`,{className:`flex flex-wrap gap-3`,children:[(0,y.jsx)(`button`,{type:`button`,onClick:()=>{let e=h();e&&e.openExternal?e.openExternal(`https://tienhiep.lyvuha.com/`):window.open(`https://tienhiep.lyvuha.com/`,`_blank`)},className:`px-4 py-2 bg-slate-800 hover:bg-slate-700 text-slate-300 font-bold text-xs rounded-xl border border-slate-700 transition-colors`,children:`Mở Trang Chủ`}),(0,y.jsx)(`button`,{type:`button`,onClick:Wt,className:`px-4 py-2 bg-[#7c3aed]/20 hover:bg-[#7c3aed]/30 text-[#a78bfa] font-bold text-xs rounded-xl border border-[#7c3aed]/30 transition-colors`,children:`Kiểm Tra Âm Thanh Hệ Thống`}),(0,y.jsxs)(`button`,{type:`button`,onClick:dt,disabled:R,className:`px-4 py-2 bg-indigo-600 hover:bg-indigo-500 active:scale-95 text-white font-extrabold text-xs rounded-xl transition-all shadow-md flex items-center gap-1.5 cursor-pointer disabled:opacity-50`,children:[(0,y.jsx)(a,{className:`w-3.5 h-3.5 ${R?`animate-spin`:``}`}),(0,y.jsx)(`span`,{children:R?`Đang kiểm tra...`:`Kiểm tra bản cập nhật`})]})]})]}):(0,y.jsxs)(`div`,{className:`text-center py-10 max-w-xl mx-auto space-y-6`,children:[(0,y.jsx)(`div`,{className:`inline-flex items-center justify-center w-16 h-16 bg-purple-900/20 text-purple-400 border border-purple-500/20 rounded-full`,children:(0,y.jsx)(c,{className:`w-8 h-8`})}),(0,y.jsxs)(`div`,{className:`space-y-2`,children:[(0,y.jsx)(`h4`,{className:`text-base font-extrabold text-white`,children:`Bạn đang truy cập bản Web Trình Duyệt`}),(0,y.jsx)(`p`,{className:`text-xs text-slate-400 leading-relaxed`,children:`Phiên bản Desktop chạy bằng Electron mang lại khả năng xử lý âm thanh **Matcha-TTS** mượt mà, lưu trữ ngoại tuyến toàn bộ kho truyện và tự động cuộn màn hình tối ưu hơn.`})]}),(0,y.jsxs)(`div`,{className:`bg-[#0b0b14]/60 p-4 border border-[#1f1f3a] rounded-xl text-left text-[11px] text-slate-400 space-y-2`,children:[(0,y.jsx)(`p`,{className:`font-bold text-purple-400`,children:`Các tính năng nổi bật của ứng dụng Desktop (.exe):`}),(0,y.jsxs)(`ul`,{className:`list-disc pl-4 space-y-1`,children:[(0,y.jsx)(`li`,{children:`Tải truyện nhanh hàng loạt, lưu vào ổ cứng để đọc offline.`}),(0,y.jsx)(`li`,{children:`Tương thích trực tiếp với hệ điều hành, phím tắt (Media Keys) để dừng/chạy giọng đọc.`}),(0,y.jsx)(`li`,{children:`Tích hợp engine chuyển giọng nói chất lượng cao mà không bị giới hạn mạng.`})]})]}),(0,y.jsxs)(`div`,{className:`flex flex-col sm:flex-row justify-center gap-3`,children:[(0,y.jsx)(`button`,{type:`button`,onClick:()=>{window.location.href=`/downloads`},className:`bg-purple-600 hover:bg-purple-500 text-white font-extrabold px-8 py-3 rounded-xl text-xs transition-colors shadow-lg shadow-purple-600/25 cursor-pointer`,children:`Tải Về Bản Desktop Cho Windows (.exe)`}),(0,y.jsxs)(`button`,{type:`button`,onClick:dt,disabled:R,className:`bg-slate-800 hover:bg-slate-700 text-slate-200 font-extrabold px-6 py-3 rounded-xl text-xs transition-colors border border-slate-700 cursor-pointer flex items-center justify-center gap-1.5 disabled:opacity-50`,children:[(0,y.jsx)(a,{className:`w-3.5 h-3.5 ${R?`animate-spin`:``}`}),(0,y.jsx)(`span`,{children:`Kiểm tra phiên bản mới`})]})]})]})]})}),x===`tts_models`&&(0,y.jsx)(`div`,{className:`space-y-6 animate-fade-in`,children:(0,y.jsxs)(`div`,{className:`bg-[#121225]/80 border border-[#1f1f3a] rounded-2xl p-6 shadow-xl space-y-6`,children:[(0,y.jsxs)(`div`,{className:`border-b border-[#1f1f3a]/60 pb-3 flex justify-between items-center`,children:[(0,y.jsxs)(`div`,{children:[(0,y.jsxs)(`h3`,{className:`text-base font-extrabold text-white flex items-center gap-2`,children:[(0,y.jsx)(ge,{className:`w-5 h-5 text-purple-400`}),` Trung Tâm Quản Lý Trí Tuệ Nhân Tạo (AI)`]}),(0,y.jsx)(`p`,{className:`text-xs text-slate-400 mt-1`,children:`Kiểm tra kết nối máy chủ và quản lý kho giọng đọc Local / Đám mây.`})]}),(0,y.jsxs)(`div`,{className:`flex items-center gap-2`,children:[p&&(0,y.jsx)(`button`,{onClick:async()=>{let e=h();e&&e.openLogFolder&&await e.openLogFolder()},className:`flex items-center gap-1 bg-[#1e293b] hover:bg-[#334155] text-slate-300 px-3 py-1.5 rounded-lg text-[10px] font-bold border border-slate-700 transition-all cursor-pointer`,children:`📂 MỞ THƯ MỤC LOGS`}),(0,y.jsxs)(`button`,{onClick:$,disabled:Q.isPinging,className:`flex items-center gap-1 bg-emerald-500/20 text-emerald-400 hover:bg-emerald-500/30 disabled:bg-slate-800 disabled:text-slate-500 px-3 py-1.5 rounded-lg text-[10px] font-bold border border-emerald-500/30 transition-all cursor-pointer`,children:[(0,y.jsx)(a,{className:`w-3 h-3 ${Q.isPinging?`animate-spin`:``}`}),` PING SERVER`]})]})]}),(0,y.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-4`,children:[(0,y.jsxs)(`div`,{className:`p-4 bg-[#0b0b14]/50 border border-[#1f1f3a] rounded-xl space-y-3`,children:[(0,y.jsxs)(`h4`,{className:`text-[10px] font-bold text-slate-400 uppercase tracking-wider flex items-center gap-2`,children:[(0,y.jsx)(fe,{className:`w-3.5 h-3.5`}),` Trạng Thế Kết Nối`]}),(0,y.jsxs)(`div`,{className:`flex items-center justify-between p-2.5 bg-white/5 rounded-lg`,children:[(0,y.jsxs)(`span`,{className:`text-xs font-bold text-white flex items-center gap-2`,children:[(0,y.jsx)(`div`,{className:`w-2 h-2 rounded-full ${Q.trans.includes(`Lỗi`)?`bg-red-500`:`bg-emerald-500 animate-pulse`}`}),` Máy Chủ Dịch (Vietphrase)`]}),(0,y.jsxs)(`span`,{className:`text-[10px] font-mono flex items-center gap-2 ${Q.trans.includes(`Lỗi`)?`text-red-400`:`text-emerald-400`}`,children:[Q.trans,` `,Q.transRtf&&Q.transRtf!==`Lỗi`&&(0,y.jsxs)(`span`,{className:`bg-purple-500/20 text-purple-300 px-1.5 rounded-full border border-purple-500/30`,title:`Tốc độ dịch nhanh gấp x lần tốc độ đọc của con người`,children:[`RTF: `,Q.transRtf]})]})]}),(0,y.jsxs)(`div`,{className:`flex items-center justify-between p-2.5 bg-white/5 rounded-lg`,children:[(0,y.jsxs)(`span`,{className:`text-xs font-bold text-white flex items-center gap-2`,children:[(0,y.jsx)(`div`,{className:`w-2 h-2 rounded-full ${Q.tts.includes(`Lỗi`)?`bg-red-500`:`bg-emerald-500 animate-pulse`}`}),` Máy Chủ TTS (Đọc Truyện)`]}),(0,y.jsxs)(`span`,{className:`text-[10px] font-mono flex items-center gap-2 ${Q.tts.includes(`Lỗi`)?`text-red-400`:`text-emerald-400`}`,children:[Q.tts,` `,(0,y.jsxs)(`span`,{className:`bg-emerald-500/20 text-emerald-300 px-1.5 rounded-full border border-emerald-500/30`,title:`Real Time Factor (Tốc độ đọc nhanh gấp x lần thực tế)`,children:[`RTF: `,Q.rtf]})]})]}),(0,y.jsxs)(`div`,{className:`flex flex-col p-2.5 bg-white/5 rounded-lg border ${Q.localTts.includes(`Connected`)?`border-emerald-500/30`:`border-red-500/20`}`,children:[(0,y.jsxs)(`div`,{className:`flex items-center justify-between w-full`,children:[(0,y.jsxs)(`span`,{className:`text-xs font-bold text-slate-300 flex items-center gap-2`,children:[(0,y.jsx)(`div`,{className:`w-2 h-2 rounded-full ${Q.localTts.includes(`Connected`)?`bg-emerald-500 animate-pulse`:`bg-red-500`}`}),` Local TTS (Offline App)`]}),(0,y.jsx)(`span`,{className:`text-[10px] font-mono ${Q.localTts.includes(`Connected`)?`text-emerald-400`:`text-red-400`}`,children:Q.localTts})]}),Q.localTts.includes(`Disconnected`)&&(0,y.jsxs)(`p`,{className:`text-[9px] text-amber-400 mt-2 border-t border-white/5 pt-1.5 leading-normal`,children:[`⚠️ Cảnh báo: Vui lòng click chọn `,(0,y.jsx)(`strong`,{children:`"Tải Động Cơ CPU"`}),` hoặc `,(0,y.jsx)(`strong`,{children:`"Tải Động Cơ GPU"`}),` ở mục bên dưới để cài lõi chạy AI Offline.`]})]})]}),(0,y.jsxs)(`div`,{className:`p-4 bg-[#0b0b14]/50 border border-[#1f1f3a] rounded-xl space-y-3`,children:[(0,y.jsxs)(`h4`,{className:`text-[10px] font-bold text-slate-400 uppercase tracking-wider flex items-center gap-2`,children:[(0,y.jsx)(c,{className:`w-3.5 h-3.5`}),` Kho Giọng Đọc (Đã Tải)`]}),(0,y.jsx)(`div`,{className:`space-y-2`,children:Ze.length===0?(0,y.jsx)(`p`,{className:`text-[10px] text-slate-500 text-center py-4 bg-white/5 rounded-lg border border-white/5 border-dashed`,children:`Chưa có Giọng đọc AI nào được tải về máy.`}):Ze.map(e=>(0,y.jsxs)(`div`,{className:`flex flex-col p-2.5 bg-white/5 rounded-lg border border-emerald-500/20 gap-2`,children:[(0,y.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,y.jsxs)(`span`,{className:`text-xs font-bold text-emerald-300`,children:[`File: `,e.name]}),(0,y.jsxs)(`span`,{className:`text-[9px] text-slate-500 bg-black/40 px-1.5 py-0.5 rounded`,children:[e.sizeMB,` MB`]})]}),(0,y.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,y.jsxs)(`span`,{className:`text-[10px] text-emerald-400 flex items-center gap-1`,children:[(0,y.jsx)(t,{className:`w-3 h-3`}),` Đã Kích Hoạt Offline`]}),(0,y.jsxs)(`button`,{onClick:()=>Vt(e.name),className:`text-[10px] text-red-400 hover:text-red-300 hover:bg-red-400/10 px-2 py-1 rounded transition-colors flex items-center gap-1`,children:[(0,y.jsx)(l,{className:`w-3 h-3`}),` Xóa`]})]})]},e.name))}),(0,y.jsxs)(`div`,{className:`mt-3 pt-3 border-t border-white/5`,children:[(0,y.jsx)(`h4`,{className:`text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-2`,children:`⚡ Chế Độ Xử Lý`}),(0,y.jsx)(`div`,{className:`flex gap-1.5`,children:[{key:`auto`,label:`🔄 Tự Động`,desc:`CPU INT8 (RTF 15x)`},{key:`gpu`,label:`🎮 GPU (CUDA)`,desc:`Model lớn FP16`},{key:`cpu`,label:`💻 CPU`,desc:`INT8 nhanh nhất`}].map(e=>(0,y.jsxs)(`button`,{onClick:()=>Ut(e.key),className:`flex-1 p-2 rounded-lg text-center transition-all border ${tt===e.key?`bg-indigo-600/30 border-indigo-500/50 text-indigo-300`:`bg-white/5 border-white/5 text-slate-500 hover:border-white/20 hover:text-slate-300`}`,children:[(0,y.jsx)(`div`,{className:`text-[10px] font-bold`,children:e.label}),(0,y.jsx)(`div`,{className:`text-[8px] mt-0.5 opacity-70`,children:e.desc})]},e.key))})]}),p&&(0,y.jsxs)(`div`,{className:`mt-3 p-3 bg-white/5 rounded-xl border border-indigo-500/20 space-y-2.5`,children:[(0,y.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,y.jsx)(`h4`,{className:`text-[10px] font-bold text-indigo-300 uppercase tracking-wider`,children:`📋 Nhật Ký Hoạt Động (Logs)`}),(0,y.jsx)(`button`,{onClick:()=>{window.electron&&window.electron.openLogFolder&&window.electron.openLogFolder()},className:`text-[9px] text-indigo-400 hover:text-indigo-300 font-bold`,children:`Mở thư mục log`})]}),(0,y.jsx)(`p`,{className:`text-[9px] text-slate-400 leading-normal`,children:`Theo dõi trạng thái khởi động, lỗi tải file, hoặc lỗi offline engine tại đây để chẩn đoán và khắc phục sự cố.`}),(0,y.jsx)(`div`,{className:`flex gap-2`,children:(0,y.jsx)(`button`,{onClick:()=>{let e=new CustomEvent(`toggle-log-console`);window.dispatchEvent(e)},className:`flex-1 bg-purple-600 hover:bg-purple-500 text-white text-[10px] font-bold py-1.5 px-2 rounded-lg transition-all flex items-center justify-center gap-1 shadow shadow-purple-500/20`,children:`Mở Console Xem Log Realtime`})})]}),(0,y.jsxs)(`p`,{className:`text-[9px] text-slate-500 text-center mt-2 italic`,children:[`Bộ lưu trữ Model: `,P]})]})]}),(0,y.jsxs)(`div`,{className:`p-4 bg-indigo-900/10 border border-indigo-500/20 rounded-xl space-y-4`,children:[(0,y.jsxs)(`div`,{className:`flex items-center justify-between border-b border-indigo-500/20 pb-2`,children:[(0,y.jsxs)(`h4`,{className:`text-xs font-bold text-indigo-300 uppercase tracking-wider flex items-center gap-2`,children:[(0,y.jsx)(i,{className:`w-3.5 h-3.5`}),` Thư Viện Giọng Đọc Mới (Cloud)`]}),(0,y.jsx)(`span`,{className:`text-[10px] bg-indigo-500/20 text-indigo-300 px-2 py-0.5 rounded-full border border-indigo-500/30`,children:`Mới cập nhật: 2 Model ONNX`})]}),(0,y.jsxs)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 gap-3`,children:[(0,y.jsxs)(`div`,{className:`flex flex-col p-3 bg-[#05050a]/80 rounded-xl border border-white/5 hover:border-indigo-500/50 transition-colors gap-2`,children:[(0,y.jsxs)(`div`,{className:`flex justify-between items-start`,children:[(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`h5`,{className:`text-xs font-bold text-white`,children:`1. Matcha-TTS Acoustic (INT8)`}),(0,y.jsx)(`p`,{className:`text-[10px] text-slate-400 mt-0.5`,children:`Mô hình tạo phổ âm từ văn bản, đã lượng hóa INT8 siêu nhẹ.`})]}),(0,y.jsx)(`span`,{className:`text-[9px] text-slate-500 bg-black px-1.5 py-0.5 rounded`,children:`19.2 MB`})]}),(0,y.jsx)(`button`,{onClick:()=>Bt(`matcha_tts_int8`,`https://huggingface.co/datasets/Cong123779/Local-TTS-Engine/resolve/main/matcha_tts_int8.onnx`),disabled:I[`matcha_tts_int8.onnx`]!==void 0,className:`mt-auto w-full bg-indigo-600 hover:bg-indigo-500 disabled:bg-indigo-600/50 text-white text-[10px] font-bold py-1.5 rounded-lg transition-colors flex items-center justify-center gap-1`,children:I[`matcha_tts_int8.onnx`]===void 0?(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(ue,{className:`w-3 h-3 rotate-90`}),` Tải Matcha-TTS ONNX`]}):(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(a,{className:`w-3 h-3 animate-spin`}),` Đang tải... `,I[`matcha_tts_int8.onnx`],`%`]})})]}),(0,y.jsxs)(`div`,{className:`flex flex-col p-3 bg-[#05050a]/80 rounded-xl border border-white/5 hover:border-indigo-500/50 transition-colors gap-2`,children:[(0,y.jsxs)(`div`,{className:`flex justify-between items-start`,children:[(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`h5`,{className:`text-xs font-bold text-white`,children:`2. Vocos Vocoder (INT8)`}),(0,y.jsx)(`p`,{className:`text-[10px] text-slate-400 mt-0.5`,children:`Mô hình giải mã phổ âm thành sóng âm thanh chất lượng cao.`})]}),(0,y.jsx)(`span`,{className:`text-[9px] text-slate-500 bg-black px-1.5 py-0.5 rounded`,children:`13.0 MB`})]}),(0,y.jsx)(`button`,{onClick:()=>Bt(`vocos_decoupled_int8`,`https://huggingface.co/datasets/Cong123779/Local-TTS-Engine/resolve/main/vocos_decoupled_int8.onnx`),disabled:I[`vocos_decoupled_int8.onnx`]!==void 0,className:`mt-auto w-full bg-indigo-600 hover:bg-indigo-500 disabled:bg-indigo-600/50 text-white text-[10px] font-bold py-1.5 rounded-lg transition-colors flex items-center justify-center gap-1`,children:I[`vocos_decoupled_int8.onnx`]===void 0?(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(ue,{className:`w-3 h-3 rotate-90`}),` Tải Vocos Vocoder ONNX`]}):(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(a,{className:`w-3 h-3 animate-spin`}),` Đang tải... `,I[`vocos_decoupled_int8.onnx`],`%`]})})]})]})]}),$e.open&&(0,y.jsx)(`div`,{className:`fixed inset-0 bg-black/70 backdrop-blur-sm flex items-center justify-center z-[9999]`,children:(0,y.jsxs)(`div`,{className:`bg-[#12121f] border border-red-500/30 rounded-2xl p-6 max-w-sm w-full mx-4 shadow-2xl shadow-red-500/10`,children:[(0,y.jsxs)(`div`,{className:`flex items-center gap-3 mb-4`,children:[(0,y.jsx)(`div`,{className:`w-10 h-10 rounded-full bg-red-500/20 flex items-center justify-center`,children:(0,y.jsx)(l,{className:`w-5 h-5 text-red-400`})}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`h3`,{className:`text-sm font-bold text-white`,children:`Xóa Giọng Đọc AI`}),(0,y.jsx)(`p`,{className:`text-[10px] text-slate-400`,children:`Hành động này không thể hoàn tác`})]})]}),(0,y.jsxs)(`p`,{className:`text-xs text-slate-300 mb-5`,children:[`Bạn có chắc chắn muốn xóa vĩnh viễn tệp `,(0,y.jsx)(`span`,{className:`text-red-400 font-bold`,children:$e.filename}),` khỏi ổ đĩa không?`]}),(0,y.jsxs)(`div`,{className:`flex gap-3`,children:[(0,y.jsx)(`button`,{onClick:()=>et({open:!1,filename:``}),className:`flex-1 py-2 rounded-xl bg-white/5 border border-white/10 text-slate-300 text-xs font-bold hover:bg-white/10 transition-colors`,children:`Hủy Bỏ`}),(0,y.jsxs)(`button`,{onClick:Ht,className:`flex-1 py-2 rounded-xl bg-red-600 hover:bg-red-500 text-white text-xs font-bold transition-colors flex items-center justify-center gap-1`,children:[(0,y.jsx)(l,{className:`w-3 h-3`}),` Xóa Vĩnh Viễn`]})]})]})})]})})]})]})]}),at&&z&&(0,y.jsx)(`div`,{className:`fixed inset-0 bg-black/85 backdrop-blur-md flex items-center justify-center z-[9999] animate-fadeIn`,children:(0,y.jsxs)(`div`,{className:`bg-[#121225] border border-purple-500/30 rounded-3xl p-6 max-w-md w-full mx-4 shadow-2xl shadow-purple-500/10 space-y-5`,children:[(0,y.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,y.jsx)(`div`,{className:`w-11 h-11 rounded-2xl bg-purple-500/10 border border-purple-500/20 flex items-center justify-center text-purple-400 shrink-0 animate-pulse`,children:(0,y.jsx)(i,{className:`w-5 h-5`})}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`h3`,{className:`text-sm font-black text-white uppercase tracking-wider`,children:f===`vi`?`🎉 Có Bản Cập Nhật Mới!`:`🎉 New Update Available!`}),(0,y.jsx)(`p`,{className:`text-[10px] text-slate-400 font-bold mt-0.5`,children:f===`vi`?`Phiên bản hiện tại: v${z.currentVersion} → Mới nhất: v${z.latestVersion}`:`Current: v${z.currentVersion} → Latest: v${z.latestVersion}`})]})]}),z.releaseNotes&&(0,y.jsxs)(`div`,{className:`bg-[#0b0b14]/80 border border-[#1f1f3a] p-4 rounded-2xl space-y-2`,children:[(0,y.jsx)(`span`,{className:`text-[9px] font-bold text-purple-400 uppercase tracking-widest block`,children:`📝 Changelog`}),(0,y.jsxs)(`p`,{className:`text-slate-300 text-xs leading-relaxed italic whitespace-pre-line font-medium`,children:[`"`,z.releaseNotes,`"`]})]}),lt&&(0,y.jsxs)(`div`,{className:`space-y-2 bg-[#05050a] border border-[#1f1f3a] p-3.5 rounded-2xl`,children:[(0,y.jsxs)(`div`,{className:`flex justify-between items-center text-[10px] font-bold`,children:[(0,y.jsx)(`span`,{className:`text-slate-400 animate-pulse`,children:ut}),(0,y.jsxs)(`span`,{className:`text-purple-400 font-mono`,children:[st,`%`]})]}),(0,y.jsx)(`div`,{className:`w-full bg-[#0b0b14] h-2 rounded-full overflow-hidden border border-[#1f1f3a]`,children:(0,y.jsx)(`div`,{className:`bg-gradient-to-r from-purple-500 to-indigo-600 h-full rounded-full transition-all duration-300`,style:{width:`${st}%`}})})]}),(0,y.jsxs)(`div`,{className:`flex gap-3`,children:[(0,y.jsx)(`button`,{disabled:lt,onClick:()=>ot(!1),className:`flex-1 py-3 rounded-xl bg-white/5 border border-white/10 text-slate-300 text-xs font-bold hover:bg-white/10 transition-colors cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed`,children:f===`vi`?`Để sau`:`Later`}),(0,y.jsxs)(`button`,{disabled:lt,onClick:ft,className:`flex-1 py-3 rounded-xl bg-purple-600 hover:bg-purple-500 text-white text-xs font-extrabold transition-all active:scale-98 cursor-pointer flex items-center justify-center gap-1.5 shadow-lg shadow-purple-600/20 disabled:opacity-50 disabled:cursor-not-allowed`,children:[(0,y.jsx)(te,{className:`w-4 h-4`}),(0,y.jsx)(`span`,{children:f===`vi`?p?`Cập nhật ngay`:`Tải về ngay`:p?`Update Now`:`Download Now`})]})]})]})})]}):(0,y.jsx)(ne,{children:(0,y.jsxs)(`div`,{className:`flex flex-col items-center justify-center py-20 text-slate-400`,children:[(0,y.jsx)(_,{className:`w-12 h-12 text-amber-500 mb-4 animate-bounce`}),(0,y.jsx)(`h2`,{className:`text-xl font-bold text-white mb-2`,children:m.settings?.reqLogin||`Yêu cầu đăng nhập`}),(0,y.jsx)(`p`,{className:`text-sm`,children:m.settings?.reqLoginDesc||`Vui lòng đăng nhập để truy cập trang Cài đặt tài khoản.`})]})})}export{b as default}; \ No newline at end of file diff --git a/frontend-web/dist/assets/award-CKCOPIfL.js b/frontend-web/dist/assets/award-CKCOPIfL.js new file mode 100644 index 0000000000000000000000000000000000000000..baafad05993dd3b6632fdf1ace69fda980b65a75 --- /dev/null +++ b/frontend-web/dist/assets/award-CKCOPIfL.js @@ -0,0 +1 @@ +import{b as e}from"./index-yRoRoI6u.js";var t=e(`award`,[[`path`,{d:`m15.477 12.89 1.515 8.526a.5.5 0 0 1-.81.47l-3.58-2.687a1 1 0 0 0-1.197 0l-3.586 2.686a.5.5 0 0 1-.81-.469l1.514-8.526`,key:`1yiouv`}],[`circle`,{cx:`12`,cy:`8`,r:`6`,key:`1vp47v`}]]);export{t}; \ No newline at end of file diff --git a/frontend-web/dist/assets/book-DwmTvSdZ.js b/frontend-web/dist/assets/book-DwmTvSdZ.js new file mode 100644 index 0000000000000000000000000000000000000000..502d69e57e1879de533dae5686bfd618cd329d7d --- /dev/null +++ b/frontend-web/dist/assets/book-DwmTvSdZ.js @@ -0,0 +1 @@ +import{b as e}from"./index-yRoRoI6u.js";var t=e(`book`,[[`path`,{d:`M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20`,key:`k3hazp`}]]);export{t}; \ No newline at end of file diff --git a/frontend-web/dist/assets/clock-DEPYmZZ-.js b/frontend-web/dist/assets/clock-DEPYmZZ-.js new file mode 100644 index 0000000000000000000000000000000000000000..e5bf745d0399795c392526b6f82a559e62592da0 --- /dev/null +++ b/frontend-web/dist/assets/clock-DEPYmZZ-.js @@ -0,0 +1 @@ +import{b as e}from"./index-yRoRoI6u.js";var t=e(`clock`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 6v6l4 2`,key:`mmk7yg`}]]);export{t}; \ No newline at end of file diff --git a/frontend-web/dist/assets/dist-DE1p5HKj.js b/frontend-web/dist/assets/dist-DE1p5HKj.js new file mode 100644 index 0000000000000000000000000000000000000000..6bd01c680bf17715402c78285ac3c92e0562771b --- /dev/null +++ b/frontend-web/dist/assets/dist-DE1p5HKj.js @@ -0,0 +1 @@ +var e;(function(e){e.Unimplemented=`UNIMPLEMENTED`,e.Unavailable=`UNAVAILABLE`})(e||={});var t=class extends Error{constructor(e,t,n){super(e),this.message=e,this.code=t,this.data=n}},n=e=>e?.androidBridge?`android`:e?.webkit?.messageHandlers?.bridge?`ios`:`web`,r=r=>{let i=r.CapacitorCustomPlatform||null,a=r.Capacitor||{},o=a.Plugins=a.Plugins||{},s=()=>i===null?n(r):i.name,c=()=>s()!==`web`,l=e=>!!(f.get(e)?.platforms.has(s())||u(e)),u=e=>a.PluginHeaders?.find(t=>t.name===e),d=e=>r.console.error(e),f=new Map;return a.convertFileSrc||=e=>e,a.getPlatform=s,a.handleError=d,a.isNativePlatform=c,a.isPluginAvailable=l,a.registerPlugin=(n,r={})=>{let c=f.get(n);if(c)return console.warn(`Capacitor plugin "${n}" already registered. Cannot register plugins twice.`),c.proxy;let l=s(),d=u(n),p,m=async()=>(!p&&l in r?p=p=typeof r[l]==`function`?await r[l]():r[l]:i!==null&&!p&&`web`in r&&(p=p=typeof r.web==`function`?await r.web():r.web),p),h=(r,i)=>{if(d){let e=d?.methods.find(e=>i===e.name);if(e)return e.rtype===`promise`?e=>a.nativePromise(n,i.toString(),e):(e,t)=>a.nativeCallback(n,i.toString(),e,t);if(r)return r[i]?.bind(r)}else if(r)return r[i]?.bind(r);else throw new t(`"${n}" plugin is not implemented on ${l}`,e.Unimplemented)},g=r=>{let i,a=(...a)=>{let o=m().then(o=>{let s=h(o,r);if(s){let e=s(...a);return i=e?.remove,e}else throw new t(`"${n}.${r}()" is not implemented on ${l}`,e.Unimplemented)});return r===`addListener`&&(o.remove=async()=>i()),o};return a.toString=()=>`${r.toString()}() { [capacitor code] }`,Object.defineProperty(a,"name",{value:r,writable:!1,configurable:!1}),a},_=g(`addListener`),v=g(`removeListener`),y=(e,t)=>{let n=_({eventName:e},t),r=async()=>{v({eventName:e,callbackId:await n},t)},i=new Promise(e=>n.then(()=>e({remove:r})));return i.remove=async()=>{console.warn(`Using addListener() without 'await' is deprecated.`),await r()},i},b=new Proxy({},{get(e,t){switch(t){case`$$typeof`:return;case`toJSON`:return()=>({});case`addListener`:return d?y:_;case`removeListener`:return v;default:return g(t)}}});return o[n]=b,f.set(n,{name:n,proxy:b,platforms:new Set([...Object.keys(r),...d?[l]:[]])}),b},a.Exception=t,a.DEBUG=!!a.DEBUG,a.isLoggingEnabled=!!a.isLoggingEnabled,a},i=(e=>e.Capacitor=r(e))(typeof globalThis<`u`?globalThis:typeof self<`u`?self:typeof window<`u`?window:typeof global<`u`?global:{}),a=i.registerPlugin,o=class{constructor(){this.listeners={},this.retainedEventArguments={},this.windowListeners={}}addListener(e,t){let n=!1;this.listeners[e]||(this.listeners[e]=[],n=!0),this.listeners[e].push(t);let r=this.windowListeners[e];return r&&!r.registered&&this.addWindowListener(r),n&&this.sendRetainedArgumentsForEvent(e),Promise.resolve({remove:async()=>this.removeListener(e,t)})}async removeAllListeners(){this.listeners={};for(let e in this.windowListeners)this.removeWindowListener(this.windowListeners[e]);this.windowListeners={}}notifyListeners(e,t,n){let r=this.listeners[e];if(!r){if(n){let n=this.retainedEventArguments[e];n||=[],n.push(t),this.retainedEventArguments[e]=n}return}r.forEach(e=>e(t))}hasListeners(e){return!!this.listeners[e]?.length}registerWindowListener(e,t){this.windowListeners[t]={registered:!1,windowEventName:e,pluginEventName:t,handler:e=>{this.notifyListeners(t,e)}}}unimplemented(t=`not implemented`){return new i.Exception(t,e.Unimplemented)}unavailable(t=`not available`){return new i.Exception(t,e.Unavailable)}async removeListener(e,t){let n=this.listeners[e];if(!n)return;let r=n.indexOf(t);this.listeners[e].splice(r,1),this.listeners[e].length||this.removeWindowListener(this.windowListeners[e])}addWindowListener(e){window.addEventListener(e.windowEventName,e.handler),e.registered=!0}removeWindowListener(e){e&&(window.removeEventListener(e.windowEventName,e.handler),e.registered=!1)}sendRetainedArgumentsForEvent(e){let t=this.retainedEventArguments[e];t&&(delete this.retainedEventArguments[e],t.forEach(t=>{this.notifyListeners(e,t)}))}},s=e=>encodeURIComponent(e).replace(/%(2[346B]|5E|60|7C)/g,decodeURIComponent).replace(/[()]/g,escape),c=e=>e.replace(/(%[\dA-F]{2})+/gi,decodeURIComponent),l=class extends o{async getCookies(){let e=document.cookie,t={};return e.split(`;`).forEach(e=>{if(e.length<=0)return;let[n,r]=e.replace(/=/,`CAP_COOKIE`).split(`CAP_COOKIE`);n=c(n).trim(),r=c(r).trim(),t[n]=r}),t}async setCookie(e){try{let t=s(e.key),n=s(e.value),r=e.expires?`; expires=${e.expires.replace(`expires=`,``)}`:``,i=(e.path||`/`).replace(`path=`,``),a=e.url!=null&&e.url.length>0?`domain=${e.url}`:``;document.cookie=`${t}=${n||``}${r}; path=${i}; ${a};`}catch(e){return Promise.reject(e)}}async deleteCookie(e){try{document.cookie=`${e.key}=; Max-Age=0`}catch(e){return Promise.reject(e)}}async clearCookies(){try{let e=document.cookie.split(`;`)||[];for(let t of e)document.cookie=t.replace(/^ +/,``).replace(/=.*/,`=;expires=${new Date().toUTCString()};path=/`)}catch(e){return Promise.reject(e)}}async clearAllCookies(){try{await this.clearCookies()}catch(e){return Promise.reject(e)}}};a(`CapacitorCookies`,{web:()=>new l});var u=async e=>new Promise((t,n)=>{let r=new FileReader;r.onload=()=>{let e=r.result;t(e.indexOf(`,`)>=0?e.split(`,`)[1]:e)},r.onerror=e=>n(e),r.readAsDataURL(e)}),d=(e={})=>{let t=Object.keys(e);return Object.keys(e).map(e=>e.toLocaleLowerCase()).reduce((n,r,i)=>(n[r]=e[t[i]],n),{})},f=(e,t=!0)=>e?Object.entries(e).reduce((e,n)=>{let[r,i]=n,a,o;return Array.isArray(i)?(o=``,i.forEach(e=>{a=t?encodeURIComponent(e):e,o+=`${r}=${a}&`}),o.slice(0,-1)):(a=t?encodeURIComponent(i):i,o=`${r}=${a}`),`${e}&${o}`},``).substr(1):null,p=(e,t={})=>{let n=Object.assign({method:e.method||`GET`,headers:e.headers},t),r=d(e.headers)[`content-type`]||``;if(typeof e.data==`string`)n.body=e.data;else if(r.includes(`application/x-www-form-urlencoded`)){let t=new URLSearchParams;for(let[n,r]of Object.entries(e.data||{}))t.set(n,r);n.body=t.toString()}else if(r.includes(`multipart/form-data`)||e.data instanceof FormData){let t=new FormData;if(e.data instanceof FormData)e.data.forEach((e,n)=>{t.append(n,e)});else for(let n of Object.keys(e.data))t.append(n,e.data[n]);n.body=t;let r=new Headers(n.headers);r.delete(`content-type`),n.headers=r}else (r.includes(`application/json`)||typeof e.data==`object`)&&(n.body=JSON.stringify(e.data));return n},m=class extends o{async request(e){let t=p(e,e.webFetchExtra),n=f(e.params,e.shouldEncodeUrlParams),r=n?`${e.url}?${n}`:e.url,i=await fetch(r,t),a=i.headers.get(`content-type`)||``,{responseType:o=`text`}=i.ok?e:{};a.includes(`application/json`)&&(o=`json`);let s,c;switch(o){case`arraybuffer`:case`blob`:c=await i.blob(),s=await u(c);break;case`json`:s=await i.json();break;default:s=await i.text()}let l={};return i.headers.forEach((e,t)=>{l[t]=e}),{data:s,headers:l,status:i.status,url:i.url}}async get(e){return this.request(Object.assign(Object.assign({},e),{method:`GET`}))}async post(e){return this.request(Object.assign(Object.assign({},e),{method:`POST`}))}async put(e){return this.request(Object.assign(Object.assign({},e),{method:`PUT`}))}async patch(e){return this.request(Object.assign(Object.assign({},e),{method:`PATCH`}))}async delete(e){return this.request(Object.assign(Object.assign({},e),{method:`DELETE`}))}};a(`CapacitorHttp`,{web:()=>new m});var h;(function(e){e.Dark=`DARK`,e.Light=`LIGHT`,e.Default=`DEFAULT`})(h||={});var g;(function(e){e.StatusBar=`StatusBar`,e.NavigationBar=`NavigationBar`})(g||={});var _=class extends o{async setStyle(){this.unavailable(`not available for web`)}async setAnimation(){this.unavailable(`not available for web`)}async show(){this.unavailable(`not available for web`)}async hide(){this.unavailable(`not available for web`)}};a(`SystemBars`,{web:()=>new _});export{a as n,o as t}; \ No newline at end of file diff --git a/frontend-web/dist/assets/esm-BLbJYcCa.js b/frontend-web/dist/assets/esm-BLbJYcCa.js new file mode 100644 index 0000000000000000000000000000000000000000..811db7a4995aaebe18783d872ae37939461b23f6 --- /dev/null +++ b/frontend-web/dist/assets/esm-BLbJYcCa.js @@ -0,0 +1,2 @@ +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/web-DHnq1Usq.js","assets/dist-DE1p5HKj.js"])))=>i.map(i=>d[i]); +import{A as e}from"./index-yRoRoI6u.js";import{n as t}from"./dist-DE1p5HKj.js";var n=t(`App`,{web:()=>e(()=>import(`./web-DHnq1Usq.js`).then(e=>new e.AppWeb),__vite__mapDeps([0,1]))});export{n as App}; \ No newline at end of file diff --git a/frontend-web/dist/assets/esm-CLdWK6iE.js b/frontend-web/dist/assets/esm-CLdWK6iE.js new file mode 100644 index 0000000000000000000000000000000000000000..9139bb795626b134ecc038b9dfeeee6a9bf0e901 --- /dev/null +++ b/frontend-web/dist/assets/esm-CLdWK6iE.js @@ -0,0 +1,2 @@ +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/web-DHhvTs7U.js","assets/dist-DE1p5HKj.js"])))=>i.map(i=>d[i]); +import{A as e}from"./index-yRoRoI6u.js";import{n as t}from"./dist-DE1p5HKj.js";var n=t(`Browser`,{web:()=>e(()=>import(`./web-DHhvTs7U.js`).then(e=>new e.BrowserWeb),__vite__mapDeps([0,1]))});export{n as Browser}; \ No newline at end of file diff --git a/frontend-web/dist/assets/eye-DsLuESBv.js b/frontend-web/dist/assets/eye-DsLuESBv.js new file mode 100644 index 0000000000000000000000000000000000000000..3aaca9353b2eae9d0a59ea240e8d2f211aec4005 --- /dev/null +++ b/frontend-web/dist/assets/eye-DsLuESBv.js @@ -0,0 +1 @@ +import{b as e}from"./index-yRoRoI6u.js";var t=e(`eye`,[[`path`,{d:`M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0`,key:`1nclc0`}],[`circle`,{cx:`12`,cy:`12`,r:`3`,key:`1v7zrd`}]]);export{t}; \ No newline at end of file diff --git a/frontend-web/dist/assets/file-text-mhTXpwIY.js b/frontend-web/dist/assets/file-text-mhTXpwIY.js new file mode 100644 index 0000000000000000000000000000000000000000..b1de3306df495c223ef5f7db36b96b863187c096 --- /dev/null +++ b/frontend-web/dist/assets/file-text-mhTXpwIY.js @@ -0,0 +1 @@ +import{b as e}from"./index-yRoRoI6u.js";var t=e(`file-text`,[[`path`,{d:`M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z`,key:`1oefj6`}],[`path`,{d:`M14 2v5a1 1 0 0 0 1 1h5`,key:`wfsgrz`}],[`path`,{d:`M10 9H8`,key:`b1mrlr`}],[`path`,{d:`M16 13H8`,key:`t4e002`}],[`path`,{d:`M16 17H8`,key:`z1uh3a`}]]);export{t}; \ No newline at end of file diff --git a/frontend-web/dist/assets/index-u0QqURGN.css b/frontend-web/dist/assets/index-u0QqURGN.css new file mode 100644 index 0000000000000000000000000000000000000000..12a45f0f9487666aa721c484b54fe1bca80fc5bb --- /dev/null +++ b/frontend-web/dist/assets/index-u0QqURGN.css @@ -0,0 +1,2 @@ +/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */ +@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-space-x-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-divide-x-reverse:0}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-serif:ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-200:oklch(88.5% .062 18.334);--color-red-300:oklch(80.8% .114 19.571);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-red-900:oklch(39.6% .141 25.723);--color-red-950:oklch(25.8% .092 26.042);--color-orange-100:oklch(95.4% .038 75.164);--color-orange-300:oklch(83.7% .128 66.29);--color-orange-500:oklch(70.5% .213 47.604);--color-orange-600:oklch(64.6% .222 41.116);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-800:oklch(47.3% .137 46.201);--color-amber-950:oklch(27.9% .077 45.635);--color-yellow-300:oklch(90.5% .182 98.111);--color-yellow-400:oklch(85.2% .199 91.936);--color-yellow-500:oklch(79.5% .184 86.047);--color-emerald-300:oklch(84.5% .143 164.978);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-600:oklch(59.6% .145 163.225);--color-emerald-950:oklch(26.2% .051 172.552);--color-teal-300:oklch(85.5% .138 181.071);--color-teal-400:oklch(77.7% .152 181.912);--color-teal-500:oklch(70.4% .14 182.503);--color-teal-600:oklch(60% .118 184.704);--color-teal-700:oklch(51.1% .096 186.391);--color-teal-950:oklch(27.7% .046 192.524);--color-cyan-400:oklch(78.9% .154 211.53);--color-cyan-500:oklch(71.5% .143 215.221);--color-cyan-600:oklch(60.9% .126 221.723);--color-cyan-700:oklch(52% .105 223.128);--color-sky-400:oklch(74.6% .16 232.661);--color-sky-500:oklch(68.5% .169 237.323);--color-blue-200:oklch(88.2% .059 254.128);--color-blue-300:oklch(80.9% .105 251.813);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-950:oklch(28.2% .091 267.935);--color-indigo-50:oklch(96.2% .018 272.314);--color-indigo-100:oklch(93% .034 272.788);--color-indigo-200:oklch(87% .065 274.039);--color-indigo-300:oklch(78.5% .115 274.713);--color-indigo-400:oklch(67.3% .182 276.935);--color-indigo-500:oklch(58.5% .233 277.117);--color-indigo-600:oklch(51.1% .262 276.966);--color-indigo-700:oklch(45.7% .24 277.023);--color-indigo-900:oklch(35.9% .144 278.697);--color-indigo-950:oklch(25.7% .09 281.288);--color-violet-300:oklch(81.1% .111 293.571);--color-violet-500:oklch(60.6% .25 292.717);--color-purple-200:oklch(90.2% .063 306.703);--color-purple-300:oklch(82.7% .119 306.383);--color-purple-400:oklch(71.4% .203 305.504);--color-purple-500:oklch(62.7% .265 303.9);--color-purple-600:oklch(55.8% .288 302.321);--color-purple-900:oklch(38.1% .176 304.987);--color-purple-950:oklch(29.1% .149 302.717);--color-fuchsia-300:oklch(83.3% .145 321.434);--color-fuchsia-400:oklch(74% .238 322.16);--color-fuchsia-500:oklch(66.7% .295 322.15);--color-fuchsia-600:oklch(59.1% .293 322.896);--color-pink-400:oklch(71.8% .202 349.761);--color-pink-500:oklch(65.6% .241 354.308);--color-rose-200:oklch(89.2% .058 10.001);--color-rose-300:oklch(81% .117 11.638);--color-rose-400:oklch(71.2% .194 13.428);--color-rose-500:oklch(64.5% .246 16.439);--color-rose-600:oklch(58.6% .253 17.585);--color-rose-900:oklch(41% .159 10.272);--color-rose-950:oklch(27.1% .105 12.094);--color-slate-50:oklch(98.4% .003 247.858);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-200:oklch(92.9% .013 255.508);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-500:oklch(55.4% .046 257.417);--color-slate-600:oklch(44.6% .043 257.281);--color-slate-700:oklch(37.2% .044 257.287);--color-slate-800:oklch(27.9% .041 260.031);--color-slate-900:oklch(20.8% .042 265.755);--color-zinc-300:oklch(87.1% .006 286.286);--color-zinc-500:oklch(55.2% .016 285.938);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-xl:36rem;--container-2xl:42rem;--container-3xl:48rem;--container-5xl:64rem;--container-6xl:72rem;--container-7xl:80rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5 / 2.25);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--font-weight-black:900;--tracking-tight:-.025em;--tracking-wide:.025em;--tracking-wider:.05em;--tracking-widest:.1em;--leading-tight:1.25;--leading-normal:1.5;--leading-relaxed:1.625;--leading-loose:2;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--radius-3xl:1.5rem;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--animate-spin:spin 1s linear infinite;--animate-ping:ping 1s cubic-bezier(0, 0, .2, 1) infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--animate-bounce:bounce 1s infinite;--blur-sm:8px;--blur-md:12px;--blur-xl:24px;--blur-2xl:40px;--blur-3xl:64px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-brand-300:#c084fc;--color-brand-400:#a855f7;--color-brand-500:#8b5cf6;--color-darkBg-DEFAULT:#0b0b14}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}html{scroll-behavior:smooth;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%;background-color:#0b0b14}body{background-color:var(--color-darkBg-DEFAULT);color:var(--color-slate-100);-webkit-tap-highlight-color:transparent;touch-action:manipulation;overscroll-behavior-y:none;min-height:100dvh;font-family:Inter,system-ui,-apple-system,sans-serif}input,textarea,select{font-size:16px}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing) * 0)}.-top-1{top:calc(var(--spacing) * -1)}.-top-20{top:calc(var(--spacing) * -20)}.top-0{top:calc(var(--spacing) * 0)}.top-1{top:calc(var(--spacing) * 1)}.top-1\.5{top:calc(var(--spacing) * 1.5)}.top-1\/2{top:50%}.top-2{top:calc(var(--spacing) * 2)}.top-2\.5{top:calc(var(--spacing) * 2.5)}.top-3{top:calc(var(--spacing) * 3)}.top-4{top:calc(var(--spacing) * 4)}.top-12{top:calc(var(--spacing) * 12)}.top-\[-50px\]{top:-50px}.-right-1{right:calc(var(--spacing) * -1)}.-right-20{right:calc(var(--spacing) * -20)}.right-0{right:calc(var(--spacing) * 0)}.right-1{right:calc(var(--spacing) * 1)}.right-2{right:calc(var(--spacing) * 2)}.right-3{right:calc(var(--spacing) * 3)}.right-4{right:calc(var(--spacing) * 4)}.right-8{right:calc(var(--spacing) * 8)}.right-\[10\%\]{right:10%}.right-\[calc\(50\%-10px\)\]{right:calc(50% - 10px)}.-bottom-1{bottom:calc(var(--spacing) * -1)}.-bottom-20{bottom:calc(var(--spacing) * -20)}.bottom-0{bottom:calc(var(--spacing) * 0)}.bottom-4{bottom:calc(var(--spacing) * 4)}.bottom-8{bottom:calc(var(--spacing) * 8)}.bottom-\[-100px\]{bottom:-100px}.-left-20{left:calc(var(--spacing) * -20)}.left-0{left:calc(var(--spacing) * 0)}.left-1{left:calc(var(--spacing) * 1)}.left-1\/2{left:50%}.left-3{left:calc(var(--spacing) * 3)}.left-3\.5{left:calc(var(--spacing) * 3.5)}.left-5{left:calc(var(--spacing) * 5)}.left-\[10\%\]{left:10%}.z-0{z-index:0}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-35{z-index:35}.z-40{z-index:40}.z-45{z-index:45}.z-50{z-index:50}.z-\[-1\]{z-index:-1}.z-\[100\]{z-index:100}.z-\[999\]{z-index:999}.z-\[9999\]{z-index:9999}.z-\[10000\]{z-index:10000}.z-\[100000\]{z-index:100000}.col-span-2{grid-column:span 2/span 2}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.mx-0\.5{margin-inline:calc(var(--spacing) * .5)}.mx-1{margin-inline:calc(var(--spacing) * 1)}.mx-2{margin-inline:calc(var(--spacing) * 2)}.mx-4{margin-inline:calc(var(--spacing) * 4)}.mx-auto{margin-inline:auto}.my-2{margin-block:calc(var(--spacing) * 2)}.my-4{margin-block:calc(var(--spacing) * 4)}.my-6{margin-block:calc(var(--spacing) * 6)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-2\.5{margin-top:calc(var(--spacing) * 2.5)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-6{margin-top:calc(var(--spacing) * 6)}.mt-8{margin-top:calc(var(--spacing) * 8)}.mt-16{margin-top:calc(var(--spacing) * 16)}.mt-\[-10px\]{margin-top:-10px}.mt-auto{margin-top:auto}.-mr-1{margin-right:calc(var(--spacing) * -1)}.mr-1{margin-right:calc(var(--spacing) * 1)}.mr-1\.5{margin-right:calc(var(--spacing) * 1.5)}.mr-2{margin-right:calc(var(--spacing) * 2)}.mb-0\.5{margin-bottom:calc(var(--spacing) * .5)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-5{margin-bottom:calc(var(--spacing) * 5)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.mb-8{margin-bottom:calc(var(--spacing) * 8)}.-ml-1{margin-left:calc(var(--spacing) * -1)}.ml-0\.5{margin-left:calc(var(--spacing) * .5)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-auto{margin-left:auto}.line-clamp-1{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-3{-webkit-line-clamp:3;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-4{-webkit-line-clamp:4;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.h-0{height:calc(var(--spacing) * 0)}.h-1{height:calc(var(--spacing) * 1)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-1\/2{height:50%}.h-2{height:calc(var(--spacing) * 2)}.h-2\.5{height:calc(var(--spacing) * 2.5)}.h-3{height:calc(var(--spacing) * 3)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-4\.5{height:calc(var(--spacing) * 4.5)}.h-5{height:calc(var(--spacing) * 5)}.h-5\.5{height:calc(var(--spacing) * 5.5)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-8\.5{height:calc(var(--spacing) * 8.5)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.h-11{height:calc(var(--spacing) * 11)}.h-12{height:calc(var(--spacing) * 12)}.h-14{height:calc(var(--spacing) * 14)}.h-16{height:calc(var(--spacing) * 16)}.h-20{height:calc(var(--spacing) * 20)}.h-22{height:calc(var(--spacing) * 22)}.h-24{height:calc(var(--spacing) * 24)}.h-32{height:calc(var(--spacing) * 32)}.h-40{height:calc(var(--spacing) * 40)}.h-64{height:calc(var(--spacing) * 64)}.h-80{height:calc(var(--spacing) * 80)}.h-\[60px\]{height:60px}.h-\[66px\]{height:66px}.h-\[82px\]{height:82px}.h-\[90vh\]{height:90vh}.h-\[96px\]{height:96px}.h-\[125px\]{height:125px}.h-\[165px\]{height:165px}.h-\[190px\]{height:190px}.h-\[300px\]{height:300px}.h-\[350px\]{height:350px}.h-\[calc\(100vh-80px\)\]{height:calc(100vh - 80px)}.h-full{height:100%}.h-px{height:1px}.max-h-40{max-height:calc(var(--spacing) * 40)}.max-h-48{max-height:calc(var(--spacing) * 48)}.max-h-64{max-height:calc(var(--spacing) * 64)}.max-h-\[70vh\]{max-height:70vh}.max-h-\[85vh\]{max-height:85vh}.max-h-\[92dvh\]{max-height:92dvh}.max-h-\[200px\]{max-height:200px}.max-h-\[220px\]{max-height:220px}.max-h-\[300px\]{max-height:300px}.max-h-\[380px\]{max-height:380px}.min-h-0{min-height:calc(var(--spacing) * 0)}.min-h-\[36px\]{min-height:36px}.min-h-\[50px\]{min-height:50px}.min-h-\[80vh\]{min-height:80vh}.min-h-\[90px\]{min-height:90px}.min-h-\[100dvh\]{min-height:100dvh}.min-h-\[100px\]{min-height:100px}.min-h-\[220px\]{min-height:220px}.min-h-\[300px\]{min-height:300px}.min-h-\[650px\]{min-height:650px}.min-h-\[calc\(100vh-80px\)\]{min-height:calc(100vh - 80px)}.min-h-screen{min-height:100vh}.w-0{width:calc(var(--spacing) * 0)}.w-1{width:calc(var(--spacing) * 1)}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-1\/2{width:50%}.w-2{width:calc(var(--spacing) * 2)}.w-2\.5{width:calc(var(--spacing) * 2.5)}.w-3{width:calc(var(--spacing) * 3)}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-4\.5{width:calc(var(--spacing) * 4.5)}.w-5{width:calc(var(--spacing) * 5)}.w-5\.5{width:calc(var(--spacing) * 5.5)}.w-6{width:calc(var(--spacing) * 6)}.w-7{width:calc(var(--spacing) * 7)}.w-8{width:calc(var(--spacing) * 8)}.w-8\.5{width:calc(var(--spacing) * 8.5)}.w-9{width:calc(var(--spacing) * 9)}.w-10{width:calc(var(--spacing) * 10)}.w-11{width:calc(var(--spacing) * 11)}.w-12{width:calc(var(--spacing) * 12)}.w-14{width:calc(var(--spacing) * 14)}.w-16{width:calc(var(--spacing) * 16)}.w-20{width:calc(var(--spacing) * 20)}.w-24{width:calc(var(--spacing) * 24)}.w-32{width:calc(var(--spacing) * 32)}.w-36{width:calc(var(--spacing) * 36)}.w-40{width:calc(var(--spacing) * 40)}.w-64{width:calc(var(--spacing) * 64)}.w-80{width:calc(var(--spacing) * 80)}.w-\[2px\]{width:2px}.w-\[45px\]{width:45px}.w-\[48px\]{width:48px}.w-\[60px\]{width:60px}.w-\[70px\]{width:70px}.w-\[90px\]{width:90px}.w-\[90vw\]{width:90vw}.w-\[120px\]{width:120px}.w-\[190px\]{width:190px}.w-\[300px\]{width:300px}.w-\[350px\]{width:350px}.w-fit{width:fit-content}.w-full{width:100%}.w-px{width:1px}.max-w-2xl{max-width:var(--container-2xl)}.max-w-3xl{max-width:var(--container-3xl)}.max-w-5xl{max-width:var(--container-5xl)}.max-w-6xl{max-width:var(--container-6xl)}.max-w-7xl{max-width:var(--container-7xl)}.max-w-\[70\%\]{max-width:70%}.max-w-\[80\%\]{max-width:80%}.max-w-\[85\%\]{max-width:85%}.max-w-\[85vw\]{max-width:85vw}.max-w-\[90px\]{max-width:90px}.max-w-\[100px\]{max-width:100px}.max-w-\[110px\]{max-width:110px}.max-w-\[150px\]{max-width:150px}.max-w-\[200px\]{max-width:200px}.max-w-\[1400px\]{max-width:1400px}.max-w-\[2200px\]{max-width:2200px}.max-w-full{max-width:100%}.max-w-md{max-width:var(--container-md)}.max-w-none{max-width:none}.max-w-sm{max-width:var(--container-sm)}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-\[16px\]{min-width:16px}.min-w-\[18px\]{min-width:18px}.min-w-\[20px\]{min-width:20px}.min-w-\[120px\]{min-width:120px}.flex-1{flex:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.origin-top-right{transform-origin:100% 0}.-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-0{--tw-translate-x:calc(var(--spacing) * 0);translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-4{--tw-translate-x:calc(var(--spacing) * 4);translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-5{--tw-translate-x:calc(var(--spacing) * 5);translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-\[0\.5px\]{--tw-translate-x:.5px;translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-\[1px\]{--tw-translate-x:1px;translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-full{--tw-translate-x:100%;translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-full{--tw-translate-y:-100%;translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-y-0{--tw-translate-y:calc(var(--spacing) * 0);translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-y-full{--tw-translate-y:100%;translate:var(--tw-translate-x) var(--tw-translate-y)}.scale-105{--tw-scale-x:105%;--tw-scale-y:105%;--tw-scale-z:105%;scale:var(--tw-scale-x) var(--tw-scale-y)}.scale-110{--tw-scale-x:110%;--tw-scale-y:110%;--tw-scale-z:110%;scale:var(--tw-scale-x) var(--tw-scale-y)}.rotate-90{rotate:90deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-bounce{animation:var(--animate-bounce)}.animate-ping{animation:var(--animate-ping)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-grab{cursor:grab}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize-none{resize:none}.scrollbar-none{scrollbar-width:none}.scrollbar-thin{scrollbar-width:thin}.list-disc{list-style-type:disc}.list-none{list-style-type:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-row{flex-direction:row}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.items-stretch{align-items:stretch}.justify-around{justify-content:space-around}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-start{justify-content:flex-start}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-3\.5{gap:calc(var(--spacing) * 3.5)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}.gap-6{gap:calc(var(--spacing) * 6)}.gap-8{gap:calc(var(--spacing) * 8)}.gap-\[2px\]{gap:2px}:where(.space-y-0\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * .5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * .5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1.5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2.5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3.5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 8) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 8) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-4{-moz-column-gap:calc(var(--spacing) * 4);column-gap:calc(var(--spacing) * 4)}:where(.-space-x-2>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * -2) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * -2) * calc(1 - var(--tw-space-x-reverse)))}.gap-y-2{row-gap:calc(var(--spacing) * 2)}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-\[\#1f1f3a\]>:not(:last-child)){border-color:#1f1f3a}:where(.divide-\[\#1f1f3a\]\/30>:not(:last-child)){border-color:oklab(25.3969% .0106509 -.0492095/.3)}.self-center{align-self:center}.self-start{align-self:flex-start}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.scroll-smooth{scroll-behavior:smooth}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-3xl{border-radius:var(--radius-3xl)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-none{border-radius:0}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-t-2xl{border-top-left-radius:var(--radius-2xl);border-top-right-radius:var(--radius-2xl)}.rounded-t-3xl{border-top-left-radius:var(--radius-3xl);border-top-right-radius:var(--radius-3xl)}.rounded-l-xl{border-top-left-radius:var(--radius-xl);border-bottom-left-radius:var(--radius-xl)}.rounded-tl-none{border-top-left-radius:0}.rounded-r-xl{border-top-right-radius:var(--radius-xl);border-bottom-right-radius:var(--radius-xl)}.rounded-tr-none{border-top-right-radius:0}.rounded-b-2xl{border-bottom-right-radius:var(--radius-2xl);border-bottom-left-radius:var(--radius-2xl)}.rounded-br-none{border-bottom-right-radius:0}.rounded-bl-full{border-bottom-left-radius:3.40282e38px}.rounded-bl-none{border-bottom-left-radius:0}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-4{border-style:var(--tw-border-style);border-width:4px}.border-x{border-inline-style:var(--tw-border-style);border-inline-width:1px}.border-y{border-block-style:var(--tw-border-style);border-block-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-t-2{border-top-style:var(--tw-border-style);border-top-width:2px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-0{border-left-style:var(--tw-border-style);border-left-width:0}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-none{--tw-border-style:none;border-style:none}.border-\[\#0c0d1e\]{border-color:#0c0d1e}.border-\[\#1a1a2e\]{border-color:#1a1a2e}.border-\[\#1d1d36\]{border-color:#1d1d36}.border-\[\#1e1e24\]{border-color:#1e1e24}.border-\[\#1f1f3a\]{border-color:#1f1f3a}.border-\[\#1f1f3a\]\/20{border-color:oklab(25.3969% .0106509 -.0492095/.2)}.border-\[\#1f1f3a\]\/30{border-color:oklab(25.3969% .0106509 -.0492095/.3)}.border-\[\#1f1f3a\]\/40{border-color:oklab(25.3969% .0106509 -.0492095/.4)}.border-\[\#1f1f3a\]\/50{border-color:oklab(25.3969% .0106509 -.0492095/.5)}.border-\[\#1f1f3a\]\/60{border-color:oklab(25.3969% .0106509 -.0492095/.6)}.border-\[\#1f1f3a\]\/80{border-color:oklab(25.3969% .0106509 -.0492095/.8)}.border-\[\#1f1f3a\]\/85{border-color:oklab(25.3969% .0106509 -.0492095/.85)}.border-\[\#2d2d6b\]{border-color:#2d2d6b}.border-\[\#2d2d6b\]\/30{border-color:oklab(33.4848% .016615 -.104051/.3)}.border-\[\#2d2d6b\]\/50{border-color:oklab(33.4848% .016615 -.104051/.5)}.border-\[\#2d2d6b\]\/80{border-color:oklab(33.4848% .016615 -.104051/.8)}.border-\[\#2d2d55\]{border-color:#2d2d55}.border-\[\#2e4a3e\]\/20{border-color:oklab(38.2702% -.0385763 .00989544/.2)}.border-\[\#3b2d54\]{border-color:#3b2d54}.border-\[\#5c4033\]\/20{border-color:oklab(39.9272% .0311347 .0321015/.2)}.border-\[\#7c3aed\]\/30{border-color:oklab(54.1337% .0963843 -.226968/.3)}.border-\[\#232342\]{border-color:#232342}.border-\[\#232342\]\/30{border-color:oklab(27.2949% .0117674 -.0554653/.3)}.border-\[\#232342\]\/75{border-color:oklab(27.2949% .0117674 -.0554653/.75)}.border-\[\#e4d5b0\]{border-color:#e4d5b0}.border-\[\#e4d6a7\]{border-color:#e4d6a7}.border-amber-200\/40{border-color:#fee68566}@supports (color:color-mix(in lab, red, red)){.border-amber-200\/40{border-color:color-mix(in oklab, var(--color-amber-200) 40%, transparent)}}.border-amber-400{border-color:var(--color-amber-400)}.border-amber-400\/30{border-color:#fcbb004d}@supports (color:color-mix(in lab, red, red)){.border-amber-400\/30{border-color:color-mix(in oklab, var(--color-amber-400) 30%, transparent)}}.border-amber-400\/50{border-color:#fcbb0080}@supports (color:color-mix(in lab, red, red)){.border-amber-400\/50{border-color:color-mix(in oklab, var(--color-amber-400) 50%, transparent)}}.border-amber-500{border-color:var(--color-amber-500)}.border-amber-500\/10{border-color:#f99c001a}@supports (color:color-mix(in lab, red, red)){.border-amber-500\/10{border-color:color-mix(in oklab, var(--color-amber-500) 10%, transparent)}}.border-amber-500\/20{border-color:#f99c0033}@supports (color:color-mix(in lab, red, red)){.border-amber-500\/20{border-color:color-mix(in oklab, var(--color-amber-500) 20%, transparent)}}.border-amber-500\/25{border-color:#f99c0040}@supports (color:color-mix(in lab, red, red)){.border-amber-500\/25{border-color:color-mix(in oklab, var(--color-amber-500) 25%, transparent)}}.border-amber-500\/30{border-color:#f99c004d}@supports (color:color-mix(in lab, red, red)){.border-amber-500\/30{border-color:color-mix(in oklab, var(--color-amber-500) 30%, transparent)}}.border-blue-500\/10{border-color:#3080ff1a}@supports (color:color-mix(in lab, red, red)){.border-blue-500\/10{border-color:color-mix(in oklab, var(--color-blue-500) 10%, transparent)}}.border-blue-500\/20{border-color:#3080ff33}@supports (color:color-mix(in lab, red, red)){.border-blue-500\/20{border-color:color-mix(in oklab, var(--color-blue-500) 20%, transparent)}}.border-blue-500\/30{border-color:#3080ff4d}@supports (color:color-mix(in lab, red, red)){.border-blue-500\/30{border-color:color-mix(in oklab, var(--color-blue-500) 30%, transparent)}}.border-brand-500{border-color:var(--color-brand-500)}.border-brand-500\/20{border-color:#8b5cf633}@supports (color:color-mix(in lab, red, red)){.border-brand-500\/20{border-color:color-mix(in oklab, var(--color-brand-500) 20%, transparent)}}.border-brand-500\/35{border-color:#8b5cf659}@supports (color:color-mix(in lab, red, red)){.border-brand-500\/35{border-color:color-mix(in oklab, var(--color-brand-500) 35%, transparent)}}.border-brand-500\/40{border-color:#8b5cf666}@supports (color:color-mix(in lab, red, red)){.border-brand-500\/40{border-color:color-mix(in oklab, var(--color-brand-500) 40%, transparent)}}.border-cyan-500\/20{border-color:#00b7d733}@supports (color:color-mix(in lab, red, red)){.border-cyan-500\/20{border-color:color-mix(in oklab, var(--color-cyan-500) 20%, transparent)}}.border-cyan-500\/30{border-color:#00b7d74d}@supports (color:color-mix(in lab, red, red)){.border-cyan-500\/30{border-color:color-mix(in oklab, var(--color-cyan-500) 30%, transparent)}}.border-emerald-500\/10{border-color:#00bb7f1a}@supports (color:color-mix(in lab, red, red)){.border-emerald-500\/10{border-color:color-mix(in oklab, var(--color-emerald-500) 10%, transparent)}}.border-emerald-500\/20{border-color:#00bb7f33}@supports (color:color-mix(in lab, red, red)){.border-emerald-500\/20{border-color:color-mix(in oklab, var(--color-emerald-500) 20%, transparent)}}.border-emerald-500\/25{border-color:#00bb7f40}@supports (color:color-mix(in lab, red, red)){.border-emerald-500\/25{border-color:color-mix(in oklab, var(--color-emerald-500) 25%, transparent)}}.border-emerald-500\/30{border-color:#00bb7f4d}@supports (color:color-mix(in lab, red, red)){.border-emerald-500\/30{border-color:color-mix(in oklab, var(--color-emerald-500) 30%, transparent)}}.border-emerald-500\/35{border-color:#00bb7f59}@supports (color:color-mix(in lab, red, red)){.border-emerald-500\/35{border-color:color-mix(in oklab, var(--color-emerald-500) 35%, transparent)}}.border-fuchsia-400\/50{border-color:#ec6cff80}@supports (color:color-mix(in lab, red, red)){.border-fuchsia-400\/50{border-color:color-mix(in oklab, var(--color-fuchsia-400) 50%, transparent)}}.border-fuchsia-500\/30{border-color:#e12afb4d}@supports (color:color-mix(in lab, red, red)){.border-fuchsia-500\/30{border-color:color-mix(in oklab, var(--color-fuchsia-500) 30%, transparent)}}.border-indigo-400\/50{border-color:#7d87ff80}@supports (color:color-mix(in lab, red, red)){.border-indigo-400\/50{border-color:color-mix(in oklab, var(--color-indigo-400) 50%, transparent)}}.border-indigo-500\/10{border-color:#625fff1a}@supports (color:color-mix(in lab, red, red)){.border-indigo-500\/10{border-color:color-mix(in oklab, var(--color-indigo-500) 10%, transparent)}}.border-indigo-500\/20{border-color:#625fff33}@supports (color:color-mix(in lab, red, red)){.border-indigo-500\/20{border-color:color-mix(in oklab, var(--color-indigo-500) 20%, transparent)}}.border-indigo-500\/30{border-color:#625fff4d}@supports (color:color-mix(in lab, red, red)){.border-indigo-500\/30{border-color:color-mix(in oklab, var(--color-indigo-500) 30%, transparent)}}.border-indigo-500\/50{border-color:#625fff80}@supports (color:color-mix(in lab, red, red)){.border-indigo-500\/50{border-color:color-mix(in oklab, var(--color-indigo-500) 50%, transparent)}}.border-indigo-950\/20{border-color:#1e1a4d33}@supports (color:color-mix(in lab, red, red)){.border-indigo-950\/20{border-color:color-mix(in oklab, var(--color-indigo-950) 20%, transparent)}}.border-indigo-950\/30{border-color:#1e1a4d4d}@supports (color:color-mix(in lab, red, red)){.border-indigo-950\/30{border-color:color-mix(in oklab, var(--color-indigo-950) 30%, transparent)}}.border-indigo-950\/40{border-color:#1e1a4d66}@supports (color:color-mix(in lab, red, red)){.border-indigo-950\/40{border-color:color-mix(in oklab, var(--color-indigo-950) 40%, transparent)}}.border-orange-500\/30{border-color:#fe6e004d}@supports (color:color-mix(in lab, red, red)){.border-orange-500\/30{border-color:color-mix(in oklab, var(--color-orange-500) 30%, transparent)}}.border-pink-500\/30{border-color:#f6339a4d}@supports (color:color-mix(in lab, red, red)){.border-pink-500\/30{border-color:color-mix(in oklab, var(--color-pink-500) 30%, transparent)}}.border-purple-500{border-color:var(--color-purple-500)}.border-purple-500\/5{border-color:#ac4bff0d}@supports (color:color-mix(in lab, red, red)){.border-purple-500\/5{border-color:color-mix(in oklab, var(--color-purple-500) 5%, transparent)}}.border-purple-500\/10{border-color:#ac4bff1a}@supports (color:color-mix(in lab, red, red)){.border-purple-500\/10{border-color:color-mix(in oklab, var(--color-purple-500) 10%, transparent)}}.border-purple-500\/15{border-color:#ac4bff26}@supports (color:color-mix(in lab, red, red)){.border-purple-500\/15{border-color:color-mix(in oklab, var(--color-purple-500) 15%, transparent)}}.border-purple-500\/20{border-color:#ac4bff33}@supports (color:color-mix(in lab, red, red)){.border-purple-500\/20{border-color:color-mix(in oklab, var(--color-purple-500) 20%, transparent)}}.border-purple-500\/25{border-color:#ac4bff40}@supports (color:color-mix(in lab, red, red)){.border-purple-500\/25{border-color:color-mix(in oklab, var(--color-purple-500) 25%, transparent)}}.border-purple-500\/30{border-color:#ac4bff4d}@supports (color:color-mix(in lab, red, red)){.border-purple-500\/30{border-color:color-mix(in oklab, var(--color-purple-500) 30%, transparent)}}.border-purple-500\/35{border-color:#ac4bff59}@supports (color:color-mix(in lab, red, red)){.border-purple-500\/35{border-color:color-mix(in oklab, var(--color-purple-500) 35%, transparent)}}.border-purple-500\/40{border-color:#ac4bff66}@supports (color:color-mix(in lab, red, red)){.border-purple-500\/40{border-color:color-mix(in oklab, var(--color-purple-500) 40%, transparent)}}.border-purple-500\/45{border-color:#ac4bff73}@supports (color:color-mix(in lab, red, red)){.border-purple-500\/45{border-color:color-mix(in oklab, var(--color-purple-500) 45%, transparent)}}.border-purple-500\/50{border-color:#ac4bff80}@supports (color:color-mix(in lab, red, red)){.border-purple-500\/50{border-color:color-mix(in oklab, var(--color-purple-500) 50%, transparent)}}.border-purple-600{border-color:var(--color-purple-600)}.border-red-500\/20{border-color:#fb2c3633}@supports (color:color-mix(in lab, red, red)){.border-red-500\/20{border-color:color-mix(in oklab, var(--color-red-500) 20%, transparent)}}.border-red-500\/25{border-color:#fb2c3640}@supports (color:color-mix(in lab, red, red)){.border-red-500\/25{border-color:color-mix(in oklab, var(--color-red-500) 25%, transparent)}}.border-red-500\/30{border-color:#fb2c364d}@supports (color:color-mix(in lab, red, red)){.border-red-500\/30{border-color:color-mix(in oklab, var(--color-red-500) 30%, transparent)}}.border-red-500\/50{border-color:#fb2c3680}@supports (color:color-mix(in lab, red, red)){.border-red-500\/50{border-color:color-mix(in oklab, var(--color-red-500) 50%, transparent)}}.border-red-900{border-color:var(--color-red-900)}.border-rose-500\/10{border-color:#ff23571a}@supports (color:color-mix(in lab, red, red)){.border-rose-500\/10{border-color:color-mix(in oklab, var(--color-rose-500) 10%, transparent)}}.border-rose-500\/20{border-color:#ff235733}@supports (color:color-mix(in lab, red, red)){.border-rose-500\/20{border-color:color-mix(in oklab, var(--color-rose-500) 20%, transparent)}}.border-rose-500\/30{border-color:#ff23574d}@supports (color:color-mix(in lab, red, red)){.border-rose-500\/30{border-color:color-mix(in oklab, var(--color-rose-500) 30%, transparent)}}.border-sky-500\/35{border-color:#00a5ef59}@supports (color:color-mix(in lab, red, red)){.border-sky-500\/35{border-color:color-mix(in oklab, var(--color-sky-500) 35%, transparent)}}.border-slate-200{border-color:var(--color-slate-200)}.border-slate-300{border-color:var(--color-slate-300)}.border-slate-500\/10{border-color:#62748e1a}@supports (color:color-mix(in lab, red, red)){.border-slate-500\/10{border-color:color-mix(in oklab, var(--color-slate-500) 10%, transparent)}}.border-slate-500\/20{border-color:#62748e33}@supports (color:color-mix(in lab, red, red)){.border-slate-500\/20{border-color:color-mix(in oklab, var(--color-slate-500) 20%, transparent)}}.border-slate-500\/30{border-color:#62748e4d}@supports (color:color-mix(in lab, red, red)){.border-slate-500\/30{border-color:color-mix(in oklab, var(--color-slate-500) 30%, transparent)}}.border-slate-700{border-color:var(--color-slate-700)}.border-slate-700\/30{border-color:#3141584d}@supports (color:color-mix(in lab, red, red)){.border-slate-700\/30{border-color:color-mix(in oklab, var(--color-slate-700) 30%, transparent)}}.border-slate-700\/40{border-color:#31415866}@supports (color:color-mix(in lab, red, red)){.border-slate-700\/40{border-color:color-mix(in oklab, var(--color-slate-700) 40%, transparent)}}.border-slate-700\/60{border-color:#31415899}@supports (color:color-mix(in lab, red, red)){.border-slate-700\/60{border-color:color-mix(in oklab, var(--color-slate-700) 60%, transparent)}}.border-slate-700\/80{border-color:#314158cc}@supports (color:color-mix(in lab, red, red)){.border-slate-700\/80{border-color:color-mix(in oklab, var(--color-slate-700) 80%, transparent)}}.border-slate-800{border-color:var(--color-slate-800)}.border-teal-500\/10{border-color:#00baa71a}@supports (color:color-mix(in lab, red, red)){.border-teal-500\/10{border-color:color-mix(in oklab, var(--color-teal-500) 10%, transparent)}}.border-teal-500\/20{border-color:#00baa733}@supports (color:color-mix(in lab, red, red)){.border-teal-500\/20{border-color:color-mix(in oklab, var(--color-teal-500) 20%, transparent)}}.border-teal-500\/30{border-color:#00baa74d}@supports (color:color-mix(in lab, red, red)){.border-teal-500\/30{border-color:color-mix(in oklab, var(--color-teal-500) 30%, transparent)}}.border-transparent{border-color:#0000}.border-violet-500\/30{border-color:#8d54ff4d}@supports (color:color-mix(in lab, red, red)){.border-violet-500\/30{border-color:color-mix(in oklab, var(--color-violet-500) 30%, transparent)}}.border-white\/5{border-color:#ffffff0d}@supports (color:color-mix(in lab, red, red)){.border-white\/5{border-color:color-mix(in oklab, var(--color-white) 5%, transparent)}}.border-white\/8{border-color:#ffffff14}@supports (color:color-mix(in lab, red, red)){.border-white\/8{border-color:color-mix(in oklab, var(--color-white) 8%, transparent)}}.border-white\/10{border-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.border-white\/10{border-color:color-mix(in oklab, var(--color-white) 10%, transparent)}}.border-yellow-300{border-color:var(--color-yellow-300)}.border-zinc-500\/30{border-color:#71717b4d}@supports (color:color-mix(in lab, red, red)){.border-zinc-500\/30{border-color:color-mix(in oklab, var(--color-zinc-500) 30%, transparent)}}.border-t-indigo-400{border-top-color:var(--color-indigo-400)}.border-t-transparent{border-top-color:#0000}.bg-\[\#0a0a16\]{background-color:#0a0a16}.bg-\[\#0b0b14\]{background-color:#0b0b14}.bg-\[\#0b0b14\]\/20{background-color:oklab(15.4503% .00460572 -.0185579/.2)}.bg-\[\#0b0b14\]\/30{background-color:oklab(15.4503% .00460572 -.0185579/.3)}.bg-\[\#0b0b14\]\/40{background-color:oklab(15.4503% .00460572 -.0185579/.4)}.bg-\[\#0b0b14\]\/50{background-color:oklab(15.4503% .00460572 -.0185579/.5)}.bg-\[\#0b0b14\]\/60{background-color:oklab(15.4503% .00460572 -.0185579/.6)}.bg-\[\#0b0b14\]\/70{background-color:oklab(15.4503% .00460572 -.0185579/.7)}.bg-\[\#0b0b14\]\/75{background-color:oklab(15.4503% .00460572 -.0185579/.75)}.bg-\[\#0b0b14\]\/80{background-color:oklab(15.4503% .00460572 -.0185579/.8)}.bg-\[\#0b0b14\]\/90{background-color:oklab(15.4503% .00460572 -.0185579/.9)}.bg-\[\#0b0c16\]{background-color:#0b0c16}.bg-\[\#0b0c16\]\/20{background-color:oklab(15.8727% .00342734 -.0209873/.2)}.bg-\[\#0b0c16\]\/50{background-color:oklab(15.8727% .00342734 -.0209873/.5)}.bg-\[\#0c0d1e\]{background-color:#0c0d1e}.bg-\[\#0c0d1e\]\/95{background-color:oklab(16.8383% .00572255 -.0347954/.95)}.bg-\[\#0c0d1e\]\/98{background-color:oklab(16.8383% .00572255 -.0347954/.98)}.bg-\[\#0d0d1e\]{background-color:#0d0d1e}.bg-\[\#0e1026\]\/50{background-color:oklab(18.4766% .00557211 -.0441962/.5)}.bg-\[\#0e1026\]\/90{background-color:oklab(18.4766% .00557211 -.0441962/.9)}.bg-\[\#0f0c24\]\/50{background-color:oklab(17.3989% .0132313 -.0462392/.5)}.bg-\[\#0f0f1a\]{background-color:#0f0f1a}.bg-\[\#0f0f1a\]\/95{background-color:oklab(17.4317% .00540778 -.0220168/.95)}.bg-\[\#0f0f26\]{background-color:#0f0f26}.bg-\[\#0f0f26\]\/20{background-color:oklab(18.3158% .00867444 -.0453014/.2)}.bg-\[\#0f0f26\]\/40{background-color:oklab(18.3158% .00867444 -.0453014/.4)}.bg-\[\#0f0f26\]\/60{background-color:oklab(18.3158% .00867444 -.0453014/.6)}.bg-\[\#0f0f26\]\/80{background-color:oklab(18.3158% .00867444 -.0453014/.8)}.bg-\[\#0f0f26\]\/85{background-color:oklab(18.3158% .00867444 -.0453014/.85)}.bg-\[\#0f101f\]{background-color:#0f101f}.bg-\[\#0f101f\]\/95{background-color:oklab(18.0448% .00529665 -.0302724/.95)}.bg-\[\#1a1a35\]\/60{background-color:oklab(23.3287% .0103747 -.0502045/.6)}.bg-\[\#1a1a36\]\/50{background-color:oklab(23.4023% .0105763 -.0519957/.5)}.bg-\[\#1a122c\]{background-color:#1a122c}.bg-\[\#1b1b36\]{background-color:#1b1b36}.bg-\[\#1c1c3c\]{background-color:#1c1c3c}.bg-\[\#1c1c38\]{background-color:#1c1c38}.bg-\[\#1c183a\]{background-color:#1c183a}.bg-\[\#1c183a\]\/95{background-color:oklab(23.4392% .0172352 -.0609742/.95)}.bg-\[\#1e1e3a\]{background-color:#1e1e3a}.bg-\[\#1e1e24\]\/95{background-color:oklab(23.7632% .00304782 -.0109901/.95)}.bg-\[\#1e293b\]{background-color:#1e293b}.bg-\[\#1f1f3a\]{background-color:#1f1f3a}.bg-\[\#7c3aed\]\/20{background-color:oklab(54.1337% .0963843 -.226968/.2)}.bg-\[\#00000030\]{background-color:#00000030}.bg-\[\#00000040\]{background-color:#00000040}.bg-\[\#070b13\]{background-color:#070b13}.bg-\[\#070b13\]\/90{background-color:oklab(14.9323% -.00248487 -.018635/.9)}.bg-\[\#181d2a\]{background-color:#181d2a}.bg-\[\#05050a\]{background-color:#05050a}.bg-\[\#05050a\]\/40{background-color:oklab(11.8398% .00333805 -.0132749/.4)}.bg-\[\#05050a\]\/80{background-color:oklab(11.8398% .00333805 -.0132749/.8)}.bg-\[\#07070a\]{background-color:#07070a}.bg-\[\#09090f\]{background-color:#09090f}.bg-\[\#12121f\]{background-color:#12121f}.bg-\[\#12122b\]{background-color:#12122b}.bg-\[\#12122b\]\/50{background-color:oklab(19.7846% .00932427 -.0483164/.5)}.bg-\[\#12122b\]\/60{background-color:oklab(19.7846% .00932427 -.0483164/.6)}.bg-\[\#12122b\]\/80{background-color:oklab(19.7846% .00932427 -.0483164/.8)}.bg-\[\#12122b\]\/90{background-color:oklab(19.7846% .00932427 -.0483164/.9)}.bg-\[\#080814\]{background-color:#080814}.bg-\[\#080814\]\/20{background-color:oklab(14.1878% .00569117 -.0255851/.2)}.bg-\[\#080814\]\/30{background-color:oklab(14.1878% .00569117 -.0255851/.3)}.bg-\[\#080814\]\/40{background-color:oklab(14.1878% .00569117 -.0255851/.4)}.bg-\[\#090916\]{background-color:#090916}.bg-\[\#111126\]{background-color:#111126}.bg-\[\#121225\]{background-color:#121225}.bg-\[\#121225\]\/20{background-color:oklab(19.323% .00805682 -.0370808/.2)}.bg-\[\#121225\]\/40{background-color:oklab(19.323% .00805682 -.0370808/.4)}.bg-\[\#121225\]\/50{background-color:oklab(19.323% .00805682 -.0370808/.5)}.bg-\[\#121225\]\/60{background-color:oklab(19.323% .00805682 -.0370808/.6)}.bg-\[\#121225\]\/80{background-color:oklab(19.323% .00805682 -.0370808/.8)}.bg-\[\#121225\]\/85{background-color:oklab(19.323% .00805682 -.0370808/.85)}.bg-\[\#121225\]\/97{background-color:oklab(19.323% .00805682 -.0370808/.97)}.bg-\[\#131324\]{background-color:#131324}.bg-\[\#161330\]{background-color:#161330}.bg-\[\#191635\]\/40{background-color:oklab(22.268% .0151619 -.0566753/.4)}.bg-\[\#dfedd6\]{background-color:#dfedd6}.bg-\[\#f4ebd0\]{background-color:#f4ebd0}.bg-\[\#f4eccf\]{background-color:#f4eccf}.bg-\[\#f4ecd8\]{background-color:#f4ecd8}.bg-\[\#f5eccb\]{background-color:#f5eccb}.bg-amber-50{background-color:var(--color-amber-50)}.bg-amber-50\/90{background-color:#fffbebe6}@supports (color:color-mix(in lab, red, red)){.bg-amber-50\/90{background-color:color-mix(in oklab, var(--color-amber-50) 90%, transparent)}}.bg-amber-400{background-color:var(--color-amber-400)}.bg-amber-400\/5{background-color:#fcbb000d}@supports (color:color-mix(in lab, red, red)){.bg-amber-400\/5{background-color:color-mix(in oklab, var(--color-amber-400) 5%, transparent)}}.bg-amber-500{background-color:var(--color-amber-500)}.bg-amber-500\/5{background-color:#f99c000d}@supports (color:color-mix(in lab, red, red)){.bg-amber-500\/5{background-color:color-mix(in oklab, var(--color-amber-500) 5%, transparent)}}.bg-amber-500\/10{background-color:#f99c001a}@supports (color:color-mix(in lab, red, red)){.bg-amber-500\/10{background-color:color-mix(in oklab, var(--color-amber-500) 10%, transparent)}}.bg-amber-600{background-color:var(--color-amber-600)}.bg-amber-600\/20{background-color:#dd740033}@supports (color:color-mix(in lab, red, red)){.bg-amber-600\/20{background-color:color-mix(in oklab, var(--color-amber-600) 20%, transparent)}}.bg-amber-600\/30{background-color:#dd74004d}@supports (color:color-mix(in lab, red, red)){.bg-amber-600\/30{background-color:color-mix(in oklab, var(--color-amber-600) 30%, transparent)}}.bg-amber-950\/20{background-color:#46190133}@supports (color:color-mix(in lab, red, red)){.bg-amber-950\/20{background-color:color-mix(in oklab, var(--color-amber-950) 20%, transparent)}}.bg-black{background-color:var(--color-black)}.bg-black\/10{background-color:#0000001a}@supports (color:color-mix(in lab, red, red)){.bg-black\/10{background-color:color-mix(in oklab, var(--color-black) 10%, transparent)}}.bg-black\/15{background-color:#00000026}@supports (color:color-mix(in lab, red, red)){.bg-black\/15{background-color:color-mix(in oklab, var(--color-black) 15%, transparent)}}.bg-black\/20{background-color:#0003}@supports (color:color-mix(in lab, red, red)){.bg-black\/20{background-color:color-mix(in oklab, var(--color-black) 20%, transparent)}}.bg-black\/30{background-color:#0000004d}@supports (color:color-mix(in lab, red, red)){.bg-black\/30{background-color:color-mix(in oklab, var(--color-black) 30%, transparent)}}.bg-black\/40{background-color:#0006}@supports (color:color-mix(in lab, red, red)){.bg-black\/40{background-color:color-mix(in oklab, var(--color-black) 40%, transparent)}}.bg-black\/50{background-color:#00000080}@supports (color:color-mix(in lab, red, red)){.bg-black\/50{background-color:color-mix(in oklab, var(--color-black) 50%, transparent)}}.bg-black\/60{background-color:#0009}@supports (color:color-mix(in lab, red, red)){.bg-black\/60{background-color:color-mix(in oklab, var(--color-black) 60%, transparent)}}.bg-black\/70{background-color:#000000b3}@supports (color:color-mix(in lab, red, red)){.bg-black\/70{background-color:color-mix(in oklab, var(--color-black) 70%, transparent)}}.bg-black\/75{background-color:#000000bf}@supports (color:color-mix(in lab, red, red)){.bg-black\/75{background-color:color-mix(in oklab, var(--color-black) 75%, transparent)}}.bg-black\/80{background-color:#000c}@supports (color:color-mix(in lab, red, red)){.bg-black\/80{background-color:color-mix(in oklab, var(--color-black) 80%, transparent)}}.bg-black\/85{background-color:#000000d9}@supports (color:color-mix(in lab, red, red)){.bg-black\/85{background-color:color-mix(in oklab, var(--color-black) 85%, transparent)}}.bg-blue-500{background-color:var(--color-blue-500)}.bg-blue-500\/5{background-color:#3080ff0d}@supports (color:color-mix(in lab, red, red)){.bg-blue-500\/5{background-color:color-mix(in oklab, var(--color-blue-500) 5%, transparent)}}.bg-blue-500\/10{background-color:#3080ff1a}@supports (color:color-mix(in lab, red, red)){.bg-blue-500\/10{background-color:color-mix(in oklab, var(--color-blue-500) 10%, transparent)}}.bg-blue-600{background-color:var(--color-blue-600)}.bg-brand-500{background-color:var(--color-brand-500)}.bg-brand-500\/10{background-color:#8b5cf61a}@supports (color:color-mix(in lab, red, red)){.bg-brand-500\/10{background-color:color-mix(in oklab, var(--color-brand-500) 10%, transparent)}}.bg-brand-500\/20{background-color:#8b5cf633}@supports (color:color-mix(in lab, red, red)){.bg-brand-500\/20{background-color:color-mix(in oklab, var(--color-brand-500) 20%, transparent)}}.bg-brand-500\/25{background-color:#8b5cf640}@supports (color:color-mix(in lab, red, red)){.bg-brand-500\/25{background-color:color-mix(in oklab, var(--color-brand-500) 25%, transparent)}}.bg-cyan-400{background-color:var(--color-cyan-400)}.bg-cyan-500\/10{background-color:#00b7d71a}@supports (color:color-mix(in lab, red, red)){.bg-cyan-500\/10{background-color:color-mix(in oklab, var(--color-cyan-500) 10%, transparent)}}.bg-cyan-600\/5{background-color:#0092b50d}@supports (color:color-mix(in lab, red, red)){.bg-cyan-600\/5{background-color:color-mix(in oklab, var(--color-cyan-600) 5%, transparent)}}.bg-emerald-500{background-color:var(--color-emerald-500)}.bg-emerald-500\/5{background-color:#00bb7f0d}@supports (color:color-mix(in lab, red, red)){.bg-emerald-500\/5{background-color:color-mix(in oklab, var(--color-emerald-500) 5%, transparent)}}.bg-emerald-500\/10{background-color:#00bb7f1a}@supports (color:color-mix(in lab, red, red)){.bg-emerald-500\/10{background-color:color-mix(in oklab, var(--color-emerald-500) 10%, transparent)}}.bg-emerald-500\/15{background-color:#00bb7f26}@supports (color:color-mix(in lab, red, red)){.bg-emerald-500\/15{background-color:color-mix(in oklab, var(--color-emerald-500) 15%, transparent)}}.bg-emerald-500\/20{background-color:#00bb7f33}@supports (color:color-mix(in lab, red, red)){.bg-emerald-500\/20{background-color:color-mix(in oklab, var(--color-emerald-500) 20%, transparent)}}.bg-emerald-600{background-color:var(--color-emerald-600)}.bg-emerald-950\/30{background-color:#002c224d}@supports (color:color-mix(in lab, red, red)){.bg-emerald-950\/30{background-color:color-mix(in oklab, var(--color-emerald-950) 30%, transparent)}}.bg-fuchsia-500\/10{background-color:#e12afb1a}@supports (color:color-mix(in lab, red, red)){.bg-fuchsia-500\/10{background-color:color-mix(in oklab, var(--color-fuchsia-500) 10%, transparent)}}.bg-indigo-400{background-color:var(--color-indigo-400)}.bg-indigo-500{background-color:var(--color-indigo-500)}.bg-indigo-500\/10{background-color:#625fff1a}@supports (color:color-mix(in lab, red, red)){.bg-indigo-500\/10{background-color:color-mix(in oklab, var(--color-indigo-500) 10%, transparent)}}.bg-indigo-500\/20{background-color:#625fff33}@supports (color:color-mix(in lab, red, red)){.bg-indigo-500\/20{background-color:color-mix(in oklab, var(--color-indigo-500) 20%, transparent)}}.bg-indigo-500\/30{background-color:#625fff4d}@supports (color:color-mix(in lab, red, red)){.bg-indigo-500\/30{background-color:color-mix(in oklab, var(--color-indigo-500) 30%, transparent)}}.bg-indigo-600{background-color:var(--color-indigo-600)}.bg-indigo-600\/20{background-color:#4f39f633}@supports (color:color-mix(in lab, red, red)){.bg-indigo-600\/20{background-color:color-mix(in oklab, var(--color-indigo-600) 20%, transparent)}}.bg-indigo-600\/30{background-color:#4f39f64d}@supports (color:color-mix(in lab, red, red)){.bg-indigo-600\/30{background-color:color-mix(in oklab, var(--color-indigo-600) 30%, transparent)}}.bg-indigo-600\/35{background-color:#4f39f659}@supports (color:color-mix(in lab, red, red)){.bg-indigo-600\/35{background-color:color-mix(in oklab, var(--color-indigo-600) 35%, transparent)}}.bg-indigo-900\/10{background-color:#312c851a}@supports (color:color-mix(in lab, red, red)){.bg-indigo-900\/10{background-color:color-mix(in oklab, var(--color-indigo-900) 10%, transparent)}}.bg-inherit{background-color:inherit}.bg-orange-500{background-color:var(--color-orange-500)}.bg-orange-500\/10{background-color:#fe6e001a}@supports (color:color-mix(in lab, red, red)){.bg-orange-500\/10{background-color:color-mix(in oklab, var(--color-orange-500) 10%, transparent)}}.bg-pink-500\/10{background-color:#f6339a1a}@supports (color:color-mix(in lab, red, red)){.bg-pink-500\/10{background-color:color-mix(in oklab, var(--color-pink-500) 10%, transparent)}}.bg-purple-500{background-color:var(--color-purple-500)}.bg-purple-500\/5{background-color:#ac4bff0d}@supports (color:color-mix(in lab, red, red)){.bg-purple-500\/5{background-color:color-mix(in oklab, var(--color-purple-500) 5%, transparent)}}.bg-purple-500\/10{background-color:#ac4bff1a}@supports (color:color-mix(in lab, red, red)){.bg-purple-500\/10{background-color:color-mix(in oklab, var(--color-purple-500) 10%, transparent)}}.bg-purple-500\/15{background-color:#ac4bff26}@supports (color:color-mix(in lab, red, red)){.bg-purple-500\/15{background-color:color-mix(in oklab, var(--color-purple-500) 15%, transparent)}}.bg-purple-500\/20{background-color:#ac4bff33}@supports (color:color-mix(in lab, red, red)){.bg-purple-500\/20{background-color:color-mix(in oklab, var(--color-purple-500) 20%, transparent)}}.bg-purple-500\/30{background-color:#ac4bff4d}@supports (color:color-mix(in lab, red, red)){.bg-purple-500\/30{background-color:color-mix(in oklab, var(--color-purple-500) 30%, transparent)}}.bg-purple-600{background-color:var(--color-purple-600)}.bg-purple-600\/5{background-color:#9810fa0d}@supports (color:color-mix(in lab, red, red)){.bg-purple-600\/5{background-color:color-mix(in oklab, var(--color-purple-600) 5%, transparent)}}.bg-purple-600\/10{background-color:#9810fa1a}@supports (color:color-mix(in lab, red, red)){.bg-purple-600\/10{background-color:color-mix(in oklab, var(--color-purple-600) 10%, transparent)}}.bg-purple-600\/20{background-color:#9810fa33}@supports (color:color-mix(in lab, red, red)){.bg-purple-600\/20{background-color:color-mix(in oklab, var(--color-purple-600) 20%, transparent)}}.bg-purple-600\/25{background-color:#9810fa40}@supports (color:color-mix(in lab, red, red)){.bg-purple-600\/25{background-color:color-mix(in oklab, var(--color-purple-600) 25%, transparent)}}.bg-purple-600\/30{background-color:#9810fa4d}@supports (color:color-mix(in lab, red, red)){.bg-purple-600\/30{background-color:color-mix(in oklab, var(--color-purple-600) 30%, transparent)}}.bg-purple-600\/50{background-color:#9810fa80}@supports (color:color-mix(in lab, red, red)){.bg-purple-600\/50{background-color:color-mix(in oklab, var(--color-purple-600) 50%, transparent)}}.bg-purple-900\/20{background-color:#59168b33}@supports (color:color-mix(in lab, red, red)){.bg-purple-900\/20{background-color:color-mix(in oklab, var(--color-purple-900) 20%, transparent)}}.bg-purple-900\/30{background-color:#59168b4d}@supports (color:color-mix(in lab, red, red)){.bg-purple-900\/30{background-color:color-mix(in oklab, var(--color-purple-900) 30%, transparent)}}.bg-purple-950\/5{background-color:#3c03660d}@supports (color:color-mix(in lab, red, red)){.bg-purple-950\/5{background-color:color-mix(in oklab, var(--color-purple-950) 5%, transparent)}}.bg-purple-950\/10{background-color:#3c03661a}@supports (color:color-mix(in lab, red, red)){.bg-purple-950\/10{background-color:color-mix(in oklab, var(--color-purple-950) 10%, transparent)}}.bg-purple-950\/20{background-color:#3c036633}@supports (color:color-mix(in lab, red, red)){.bg-purple-950\/20{background-color:color-mix(in oklab, var(--color-purple-950) 20%, transparent)}}.bg-red-500{background-color:var(--color-red-500)}.bg-red-500\/10{background-color:#fb2c361a}@supports (color:color-mix(in lab, red, red)){.bg-red-500\/10{background-color:color-mix(in oklab, var(--color-red-500) 10%, transparent)}}.bg-red-500\/15{background-color:#fb2c3626}@supports (color:color-mix(in lab, red, red)){.bg-red-500\/15{background-color:color-mix(in oklab, var(--color-red-500) 15%, transparent)}}.bg-red-500\/20{background-color:#fb2c3633}@supports (color:color-mix(in lab, red, red)){.bg-red-500\/20{background-color:color-mix(in oklab, var(--color-red-500) 20%, transparent)}}.bg-red-600{background-color:var(--color-red-600)}.bg-red-900\/10{background-color:#82181a1a}@supports (color:color-mix(in lab, red, red)){.bg-red-900\/10{background-color:color-mix(in oklab, var(--color-red-900) 10%, transparent)}}.bg-red-900\/20{background-color:#82181a33}@supports (color:color-mix(in lab, red, red)){.bg-red-900\/20{background-color:color-mix(in oklab, var(--color-red-900) 20%, transparent)}}.bg-rose-400{background-color:var(--color-rose-400)}.bg-rose-500{background-color:var(--color-rose-500)}.bg-rose-500\/5{background-color:#ff23570d}@supports (color:color-mix(in lab, red, red)){.bg-rose-500\/5{background-color:color-mix(in oklab, var(--color-rose-500) 5%, transparent)}}.bg-rose-500\/10{background-color:#ff23571a}@supports (color:color-mix(in lab, red, red)){.bg-rose-500\/10{background-color:color-mix(in oklab, var(--color-rose-500) 10%, transparent)}}.bg-rose-600{background-color:var(--color-rose-600)}.bg-rose-600\/20{background-color:#e7004433}@supports (color:color-mix(in lab, red, red)){.bg-rose-600\/20{background-color:color-mix(in oklab, var(--color-rose-600) 20%, transparent)}}.bg-rose-950\/20{background-color:#4d021833}@supports (color:color-mix(in lab, red, red)){.bg-rose-950\/20{background-color:color-mix(in oklab, var(--color-rose-950) 20%, transparent)}}.bg-rose-950\/30{background-color:#4d02184d}@supports (color:color-mix(in lab, red, red)){.bg-rose-950\/30{background-color:color-mix(in oklab, var(--color-rose-950) 30%, transparent)}}.bg-sky-500{background-color:var(--color-sky-500)}.bg-sky-500\/15{background-color:#00a5ef26}@supports (color:color-mix(in lab, red, red)){.bg-sky-500\/15{background-color:color-mix(in oklab, var(--color-sky-500) 15%, transparent)}}.bg-slate-100{background-color:var(--color-slate-100)}.bg-slate-500\/10{background-color:#62748e1a}@supports (color:color-mix(in lab, red, red)){.bg-slate-500\/10{background-color:color-mix(in oklab, var(--color-slate-500) 10%, transparent)}}.bg-slate-600{background-color:var(--color-slate-600)}.bg-slate-700{background-color:var(--color-slate-700)}.bg-slate-700\/40{background-color:#31415866}@supports (color:color-mix(in lab, red, red)){.bg-slate-700\/40{background-color:color-mix(in oklab, var(--color-slate-700) 40%, transparent)}}.bg-slate-800{background-color:var(--color-slate-800)}.bg-slate-800\/40{background-color:#1d293d66}@supports (color:color-mix(in lab, red, red)){.bg-slate-800\/40{background-color:color-mix(in oklab, var(--color-slate-800) 40%, transparent)}}.bg-slate-800\/60{background-color:#1d293d99}@supports (color:color-mix(in lab, red, red)){.bg-slate-800\/60{background-color:color-mix(in oklab, var(--color-slate-800) 60%, transparent)}}.bg-slate-900{background-color:var(--color-slate-900)}.bg-slate-900\/50{background-color:#0f172b80}@supports (color:color-mix(in lab, red, red)){.bg-slate-900\/50{background-color:color-mix(in oklab, var(--color-slate-900) 50%, transparent)}}.bg-teal-500\/10{background-color:#00baa71a}@supports (color:color-mix(in lab, red, red)){.bg-teal-500\/10{background-color:color-mix(in oklab, var(--color-teal-500) 10%, transparent)}}.bg-teal-600{background-color:var(--color-teal-600)}.bg-teal-600\/10{background-color:#0095881a}@supports (color:color-mix(in lab, red, red)){.bg-teal-600\/10{background-color:color-mix(in oklab, var(--color-teal-600) 10%, transparent)}}.bg-teal-600\/30{background-color:#0095884d}@supports (color:color-mix(in lab, red, red)){.bg-teal-600\/30{background-color:color-mix(in oklab, var(--color-teal-600) 30%, transparent)}}.bg-teal-950\/5{background-color:#022f2e0d}@supports (color:color-mix(in lab, red, red)){.bg-teal-950\/5{background-color:color-mix(in oklab, var(--color-teal-950) 5%, transparent)}}.bg-transparent{background-color:#0000}.bg-violet-500\/10{background-color:#8d54ff1a}@supports (color:color-mix(in lab, red, red)){.bg-violet-500\/10{background-color:color-mix(in oklab, var(--color-violet-500) 10%, transparent)}}.bg-white{background-color:var(--color-white)}.bg-white\/5{background-color:#ffffff0d}@supports (color:color-mix(in lab, red, red)){.bg-white\/5{background-color:color-mix(in oklab, var(--color-white) 5%, transparent)}}.bg-white\/10{background-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.bg-white\/10{background-color:color-mix(in oklab, var(--color-white) 10%, transparent)}}.bg-white\/20{background-color:#fff3}@supports (color:color-mix(in lab, red, red)){.bg-white\/20{background-color:color-mix(in oklab, var(--color-white) 20%, transparent)}}.bg-zinc-500\/10{background-color:#71717b1a}@supports (color:color-mix(in lab, red, red)){.bg-zinc-500\/10{background-color:color-mix(in oklab, var(--color-zinc-500) 10%, transparent)}}.bg-gradient-to-b{--tw-gradient-position:to bottom in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-gradient-to-br{--tw-gradient-position:to bottom right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-gradient-to-r{--tw-gradient-position:to right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-gradient-to-tr{--tw-gradient-position:to top right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-\[\#0b0b14\]{--tw-gradient-from:#0b0b14;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-\[\#7c3aed\]{--tw-gradient-from:#7c3aed;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-\[\#110e26\]{--tw-gradient-from:#110e26;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-\[\#080814\]\/10{--tw-gradient-from:oklab(14.1878% .00569117 -.0255851/.1);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-\[\#111122\]{--tw-gradient-from:#112;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-\[\#131327\]{--tw-gradient-from:#131327;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-amber-300{--tw-gradient-from:var(--color-amber-300);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-amber-400{--tw-gradient-from:var(--color-amber-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-amber-500{--tw-gradient-from:var(--color-amber-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-amber-600{--tw-gradient-from:var(--color-amber-600);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-amber-600\/10{--tw-gradient-from:#dd74001a}@supports (color:color-mix(in lab, red, red)){.from-amber-600\/10{--tw-gradient-from:color-mix(in oklab, var(--color-amber-600) 10%, transparent)}}.from-amber-600\/10{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-blue-600{--tw-gradient-from:var(--color-blue-600);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-brand-300{--tw-gradient-from:var(--color-brand-300);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-brand-500{--tw-gradient-from:var(--color-brand-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-emerald-500{--tw-gradient-from:var(--color-emerald-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-fuchsia-600{--tw-gradient-from:var(--color-fuchsia-600);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-indigo-900\/80{--tw-gradient-from:#312c85cc}@supports (color:color-mix(in lab, red, red)){.from-indigo-900\/80{--tw-gradient-from:color-mix(in oklab, var(--color-indigo-900) 80%, transparent)}}.from-indigo-900\/80{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-orange-500\/20{--tw-gradient-from:#fe6e0033}@supports (color:color-mix(in lab, red, red)){.from-orange-500\/20{--tw-gradient-from:color-mix(in oklab, var(--color-orange-500) 20%, transparent)}}.from-orange-500\/20{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-purple-400{--tw-gradient-from:var(--color-purple-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-purple-500{--tw-gradient-from:var(--color-purple-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-purple-600{--tw-gradient-from:var(--color-purple-600);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-purple-600\/20{--tw-gradient-from:#9810fa33}@supports (color:color-mix(in lab, red, red)){.from-purple-600\/20{--tw-gradient-from:color-mix(in oklab, var(--color-purple-600) 20%, transparent)}}.from-purple-600\/20{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-purple-600\/30{--tw-gradient-from:#9810fa4d}@supports (color:color-mix(in lab, red, red)){.from-purple-600\/30{--tw-gradient-from:color-mix(in oklab, var(--color-purple-600) 30%, transparent)}}.from-purple-600\/30{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-purple-900\/35{--tw-gradient-from:#59168b59}@supports (color:color-mix(in lab, red, red)){.from-purple-900\/35{--tw-gradient-from:color-mix(in oklab, var(--color-purple-900) 35%, transparent)}}.from-purple-900\/35{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-purple-900\/40{--tw-gradient-from:#59168b66}@supports (color:color-mix(in lab, red, red)){.from-purple-900\/40{--tw-gradient-from:color-mix(in oklab, var(--color-purple-900) 40%, transparent)}}.from-purple-900\/40{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-purple-950\/10{--tw-gradient-from:#3c03661a}@supports (color:color-mix(in lab, red, red)){.from-purple-950\/10{--tw-gradient-from:color-mix(in oklab, var(--color-purple-950) 10%, transparent)}}.from-purple-950\/10{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-purple-950\/20{--tw-gradient-from:#3c036633}@supports (color:color-mix(in lab, red, red)){.from-purple-950\/20{--tw-gradient-from:color-mix(in oklab, var(--color-purple-950) 20%, transparent)}}.from-purple-950\/20{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-red-950{--tw-gradient-from:var(--color-red-950);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-rose-500{--tw-gradient-from:var(--color-rose-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-slate-200{--tw-gradient-from:var(--color-slate-200);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-teal-500{--tw-gradient-from:var(--color-teal-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-yellow-300{--tw-gradient-from:var(--color-yellow-300);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.via-\[\#0b0b14\]\/75{--tw-gradient-via:oklab(15.4503% .00460572 -.0185579/.75);--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.via-\[\#1c183a\]{--tw-gradient-via:#1c183a;--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.via-amber-400{--tw-gradient-via:var(--color-amber-400);--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.via-indigo-200{--tw-gradient-via:var(--color-indigo-200);--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.via-indigo-950\/20{--tw-gradient-via:#1e1a4d33}@supports (color:color-mix(in lab, red, red)){.via-indigo-950\/20{--tw-gradient-via:color-mix(in oklab, var(--color-indigo-950) 20%, transparent)}}.via-indigo-950\/20{--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.via-pink-500{--tw-gradient-via:var(--color-pink-500);--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.via-purple-500{--tw-gradient-via:var(--color-purple-500);--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.via-purple-900\/80{--tw-gradient-via:#59168bcc}@supports (color:color-mix(in lab, red, red)){.via-purple-900\/80{--tw-gradient-via:color-mix(in oklab, var(--color-purple-900) 80%, transparent)}}.via-purple-900\/80{--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.via-rose-900{--tw-gradient-via:var(--color-rose-900);--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.via-yellow-500{--tw-gradient-via:var(--color-yellow-500);--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.to-\[\#0b0b14\]\/40{--tw-gradient-to:oklab(15.4503% .00460572 -.0185579/.4);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-\[\#0d0d1a\]{--tw-gradient-to:#0d0d1a;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-\[\#4f46e5\]{--tw-gradient-to:#4f46e5;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-\[\#110e26\]{--tw-gradient-to:#110e26;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-\[\#17172e\]{--tw-gradient-to:#17172e;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-amber-200{--tw-gradient-to:var(--color-amber-200);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-amber-300{--tw-gradient-to:var(--color-amber-300);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-amber-400{--tw-gradient-to:var(--color-amber-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-amber-500{--tw-gradient-to:var(--color-amber-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-amber-500\/20{--tw-gradient-to:#f99c0033}@supports (color:color-mix(in lab, red, red)){.to-amber-500\/20{--tw-gradient-to:color-mix(in oklab, var(--color-amber-500) 20%, transparent)}}.to-amber-500\/20{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-amber-600{--tw-gradient-to:var(--color-amber-600);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-amber-800{--tw-gradient-to:var(--color-amber-800);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-brand-500{--tw-gradient-to:var(--color-brand-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-brand-500\/20{--tw-gradient-to:#8b5cf633}@supports (color:color-mix(in lab, red, red)){.to-brand-500\/20{--tw-gradient-to:color-mix(in oklab, var(--color-brand-500) 20%, transparent)}}.to-brand-500\/20{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-brand-500\/30{--tw-gradient-to:#8b5cf64d}@supports (color:color-mix(in lab, red, red)){.to-brand-500\/30{--tw-gradient-to:color-mix(in oklab, var(--color-brand-500) 30%, transparent)}}.to-brand-500\/30{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-cyan-700{--tw-gradient-to:var(--color-cyan-700);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-emerald-600{--tw-gradient-to:var(--color-emerald-600);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-indigo-200{--tw-gradient-to:var(--color-indigo-200);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-indigo-500{--tw-gradient-to:var(--color-indigo-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-indigo-600{--tw-gradient-to:var(--color-indigo-600);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-indigo-700{--tw-gradient-to:var(--color-indigo-700);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-indigo-900\/40{--tw-gradient-to:#312c8566}@supports (color:color-mix(in lab, red, red)){.to-indigo-900\/40{--tw-gradient-to:color-mix(in oklab, var(--color-indigo-900) 40%, transparent)}}.to-indigo-900\/40{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-indigo-900\/80{--tw-gradient-to:#312c85cc}@supports (color:color-mix(in lab, red, red)){.to-indigo-900\/80{--tw-gradient-to:color-mix(in oklab, var(--color-indigo-900) 80%, transparent)}}.to-indigo-900\/80{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-indigo-950\/10{--tw-gradient-to:#1e1a4d1a}@supports (color:color-mix(in lab, red, red)){.to-indigo-950\/10{--tw-gradient-to:color-mix(in oklab, var(--color-indigo-950) 10%, transparent)}}.to-indigo-950\/10{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-indigo-950\/40{--tw-gradient-to:#1e1a4d66}@supports (color:color-mix(in lab, red, red)){.to-indigo-950\/40{--tw-gradient-to:color-mix(in oklab, var(--color-indigo-950) 40%, transparent)}}.to-indigo-950\/40{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-orange-600{--tw-gradient-to:var(--color-orange-600);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-orange-600\/10{--tw-gradient-to:#f051001a}@supports (color:color-mix(in lab, red, red)){.to-orange-600\/10{--tw-gradient-to:color-mix(in oklab, var(--color-orange-600) 10%, transparent)}}.to-orange-600\/10{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-purple-300{--tw-gradient-to:var(--color-purple-300);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-purple-400{--tw-gradient-to:var(--color-purple-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-purple-600{--tw-gradient-to:var(--color-purple-600);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-red-700{--tw-gradient-to:var(--color-red-700);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-red-950{--tw-gradient-to:var(--color-red-950);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-slate-400{--tw-gradient-to:var(--color-slate-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-teal-700{--tw-gradient-to:var(--color-teal-700);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-teal-950\/15{--tw-gradient-to:#022f2e26}@supports (color:color-mix(in lab, red, red)){.to-teal-950\/15{--tw-gradient-to:color-mix(in oklab, var(--color-teal-950) 15%, transparent)}}.to-teal-950\/15{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-transparent{--tw-gradient-to:transparent;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-violet-500{--tw-gradient-to:var(--color-violet-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-yellow-500{--tw-gradient-to:var(--color-yellow-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.bg-cover{background-size:cover}.bg-clip-text{-webkit-background-clip:text;background-clip:text}.bg-center{background-position:50%}.fill-amber-400{fill:var(--color-amber-400)}.fill-current{fill:currentColor}.fill-rose-500{fill:var(--color-rose-500)}.stroke-\[3\]{stroke-width:3px}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-1{padding:calc(var(--spacing) * 1)}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-2{padding:calc(var(--spacing) * 2)}.p-2\.5{padding:calc(var(--spacing) * 2.5)}.p-3{padding:calc(var(--spacing) * 3)}.p-3\.5{padding:calc(var(--spacing) * 3.5)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-6{padding:calc(var(--spacing) * 6)}.p-7{padding:calc(var(--spacing) * 7)}.p-8{padding:calc(var(--spacing) * 8)}.p-\[2px\]{padding:2px}.p-\[4px\]{padding:4px}.px-0\.5{padding-inline:calc(var(--spacing) * .5)}.px-1{padding-inline:calc(var(--spacing) * 1)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-8{padding-inline:calc(var(--spacing) * 8)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-3\.5{padding-block:calc(var(--spacing) * 3.5)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-10{padding-block:calc(var(--spacing) * 10)}.py-12{padding-block:calc(var(--spacing) * 12)}.py-16{padding-block:calc(var(--spacing) * 16)}.py-20{padding-block:calc(var(--spacing) * 20)}.py-24{padding-block:calc(var(--spacing) * 24)}.py-32{padding-block:calc(var(--spacing) * 32)}.pt-1{padding-top:calc(var(--spacing) * 1)}.pt-1\.5{padding-top:calc(var(--spacing) * 1.5)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pt-5{padding-top:calc(var(--spacing) * 5)}.pt-6{padding-top:calc(var(--spacing) * 6)}.pt-12{padding-top:calc(var(--spacing) * 12)}.pr-0\.5{padding-right:calc(var(--spacing) * .5)}.pr-1{padding-right:calc(var(--spacing) * 1)}.pr-1\.5{padding-right:calc(var(--spacing) * 1.5)}.pr-4{padding-right:calc(var(--spacing) * 4)}.pr-8{padding-right:calc(var(--spacing) * 8)}.pb-1{padding-bottom:calc(var(--spacing) * 1)}.pb-1\.5{padding-bottom:calc(var(--spacing) * 1.5)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-2\.5{padding-bottom:calc(var(--spacing) * 2.5)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pb-3\.5{padding-bottom:calc(var(--spacing) * 3.5)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pb-20{padding-bottom:calc(var(--spacing) * 20)}.pb-24{padding-bottom:calc(var(--spacing) * 24)}.pl-0{padding-left:calc(var(--spacing) * 0)}.pl-1{padding-left:calc(var(--spacing) * 1)}.pl-2{padding-left:calc(var(--spacing) * 2)}.pl-4{padding-left:calc(var(--spacing) * 4)}.pl-9{padding-left:calc(var(--spacing) * 9)}.pl-10{padding-left:calc(var(--spacing) * 10)}.pl-11{padding-left:calc(var(--spacing) * 11)}.text-center{text-align:center}.text-justify{text-align:justify}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.font-serif{font-family:var(--font-serif)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[0\.75em\]{font-size:.75em}.text-\[7px\]{font-size:7px}.text-\[8\.5px\]{font-size:8.5px}.text-\[8px\]{font-size:8px}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.leading-loose{--tw-leading:var(--leading-loose);line-height:var(--leading-loose)}.leading-normal{--tw-leading:var(--leading-normal);line-height:var(--leading-normal)}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-black{--tw-font-weight:var(--font-weight-black);font-weight:var(--font-weight-black)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-extrabold{--tw-font-weight:var(--font-weight-extrabold);font-weight:var(--font-weight-extrabold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.break-words{overflow-wrap:break-word}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.whitespace-pre{white-space:pre}.whitespace-pre-line{white-space:pre-line}.whitespace-pre-wrap{white-space:pre-wrap}.text-\[\#0b0b14\]{color:#0b0b14}.text-\[\#2e4a3e\]{color:#2e4a3e}.text-\[\#5c4033\]{color:#5c4033}.text-\[\#422e24\]{color:#422e24}.text-\[\#433422\]{color:#433422}.text-\[\#a78bfa\]{color:#a78bfa}.text-amber-300{color:var(--color-amber-300)}.text-amber-400{color:var(--color-amber-400)}.text-amber-500{color:var(--color-amber-500)}.text-black{color:var(--color-black)}.text-blue-200{color:var(--color-blue-200)}.text-blue-300{color:var(--color-blue-300)}.text-blue-400{color:var(--color-blue-400)}.text-brand-300{color:var(--color-brand-300)}.text-brand-400{color:var(--color-brand-400)}.text-brand-500{color:var(--color-brand-500)}.text-cyan-400{color:var(--color-cyan-400)}.text-emerald-300{color:var(--color-emerald-300)}.text-emerald-400{color:var(--color-emerald-400)}.text-emerald-500{color:var(--color-emerald-500)}.text-fuchsia-300{color:var(--color-fuchsia-300)}.text-fuchsia-400{color:var(--color-fuchsia-400)}.text-indigo-50{color:var(--color-indigo-50)}.text-indigo-100{color:var(--color-indigo-100)}.text-indigo-200{color:var(--color-indigo-200)}.text-indigo-300{color:var(--color-indigo-300)}.text-indigo-300\/70{color:#a4b3ffb3}@supports (color:color-mix(in lab, red, red)){.text-indigo-300\/70{color:color-mix(in oklab, var(--color-indigo-300) 70%, transparent)}}.text-indigo-400{color:var(--color-indigo-400)}.text-orange-100{color:var(--color-orange-100)}.text-orange-300{color:var(--color-orange-300)}.text-pink-400{color:var(--color-pink-400)}.text-purple-200{color:var(--color-purple-200)}.text-purple-300{color:var(--color-purple-300)}.text-purple-400{color:var(--color-purple-400)}.text-purple-400\/70{color:#c07effb3}@supports (color:color-mix(in lab, red, red)){.text-purple-400\/70{color:color-mix(in oklab, var(--color-purple-400) 70%, transparent)}}.text-purple-500{color:var(--color-purple-500)}.text-purple-500\/50{color:#ac4bff80}@supports (color:color-mix(in lab, red, red)){.text-purple-500\/50{color:color-mix(in oklab, var(--color-purple-500) 50%, transparent)}}.text-purple-600{color:var(--color-purple-600)}.text-red-200{color:var(--color-red-200)}.text-red-300{color:var(--color-red-300)}.text-red-300\/70{color:#ffa3a3b3}@supports (color:color-mix(in lab, red, red)){.text-red-300\/70{color:color-mix(in oklab, var(--color-red-300) 70%, transparent)}}.text-red-400{color:var(--color-red-400)}.text-red-500{color:var(--color-red-500)}.text-rose-200{color:var(--color-rose-200)}.text-rose-300{color:var(--color-rose-300)}.text-rose-300\/70{color:#ffa2aeb3}@supports (color:color-mix(in lab, red, red)){.text-rose-300\/70{color:color-mix(in oklab, var(--color-rose-300) 70%, transparent)}}.text-rose-400{color:var(--color-rose-400)}.text-rose-500{color:var(--color-rose-500)}.text-sky-400{color:var(--color-sky-400)}.text-slate-100{color:var(--color-slate-100)}.text-slate-200{color:var(--color-slate-200)}.text-slate-300{color:var(--color-slate-300)}.text-slate-400{color:var(--color-slate-400)}.text-slate-500{color:var(--color-slate-500)}.text-slate-600{color:var(--color-slate-600)}.text-slate-800{color:var(--color-slate-800)}.text-slate-900{color:var(--color-slate-900)}.text-teal-300{color:var(--color-teal-300)}.text-teal-400{color:var(--color-teal-400)}.text-teal-400\/80{color:#00d3bdcc}@supports (color:color-mix(in lab, red, red)){.text-teal-400\/80{color:color-mix(in oklab, var(--color-teal-400) 80%, transparent)}}.text-teal-500\/60{color:#00baa799}@supports (color:color-mix(in lab, red, red)){.text-teal-500\/60{color:color-mix(in oklab, var(--color-teal-500) 60%, transparent)}}.text-teal-500\/70{color:#00baa7b3}@supports (color:color-mix(in lab, red, red)){.text-teal-500\/70{color:color-mix(in oklab, var(--color-teal-500) 70%, transparent)}}.text-transparent{color:#0000}.text-violet-300{color:var(--color-violet-300)}.text-white{color:var(--color-white)}.text-yellow-400{color:var(--color-yellow-400)}.text-zinc-300{color:var(--color-zinc-300)}.capitalize{text-transform:capitalize}.uppercase{text-transform:uppercase}.italic{font-style:italic}.underline{text-decoration-line:underline}.placeholder-slate-500::placeholder{color:var(--color-slate-500)}.placeholder-slate-600::placeholder{color:var(--color-slate-600)}.accent-emerald-500{accent-color:var(--color-emerald-500)}.accent-indigo-500{accent-color:var(--color-indigo-500)}.accent-purple-500{accent-color:var(--color-purple-500)}.opacity-0{opacity:0}.opacity-10{opacity:.1}.opacity-15{opacity:.15}.opacity-25{opacity:.25}.opacity-40{opacity:.4}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-75{opacity:.75}.opacity-80{opacity:.8}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_-8px_24px_rgba\(0\,0\,0\,0\.3\)\]{--tw-shadow:0 -8px 24px var(--tw-shadow-color,#0000004d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_-15px_30px_rgba\(0\,0\,0\,0\.8\)\]{--tw-shadow:0 -15px 30px var(--tw-shadow-color,#000c);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_0_10px_rgba\(192\,38\,211\,0\.5\)\]{--tw-shadow:0 0 10px var(--tw-shadow-color,#c026d380);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_0_15px_rgba\(99\,102\,241\,0\.25\)\]{--tw-shadow:0 0 15px var(--tw-shadow-color,#6366f140);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_0_15px_rgba\(192\,38\,211\,0\.5\)\]{--tw-shadow:0 0 15px var(--tw-shadow-color,#c026d380);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_0_20px_rgba\(168\,85\,247\,0\.6\)\]{--tw-shadow:0 0 20px var(--tw-shadow-color,#a855f799);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_0_20px_rgba\(251\,191\,36\,0\.6\)\]{--tw-shadow:0 0 20px var(--tw-shadow-color,#fbbf2499);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_2px_8px_rgba\(245\,158\,11\,0\.4\)\]{--tw-shadow:0 2px 8px var(--tw-shadow-color,#f59e0b66);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_10px_40px_rgba\(0\,0\,0\,0\.5\)\]{--tw-shadow:0 10px 40px var(--tw-shadow-color,#00000080);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[inset_0_0_10px_rgba\(99\,102\,241\,0\.2\)\]{--tw-shadow:inset 0 0 10px var(--tw-shadow-color,#6366f133);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-0{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-1{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-2{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-4{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-amber-500\/5{--tw-shadow-color:#f99c000d}@supports (color:color-mix(in lab, red, red)){.shadow-amber-500\/5{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-amber-500) 5%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-amber-500\/10{--tw-shadow-color:#f99c001a}@supports (color:color-mix(in lab, red, red)){.shadow-amber-500\/10{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-amber-500) 10%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-amber-600\/20{--tw-shadow-color:#dd740033}@supports (color:color-mix(in lab, red, red)){.shadow-amber-600\/20{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-amber-600) 20%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-brand-500\/5{--tw-shadow-color:#8b5cf60d}@supports (color:color-mix(in lab, red, red)){.shadow-brand-500\/5{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-brand-500) 5%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-brand-500\/20{--tw-shadow-color:#8b5cf633}@supports (color:color-mix(in lab, red, red)){.shadow-brand-500\/20{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-brand-500) 20%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-purple-500\/5{--tw-shadow-color:#ac4bff0d}@supports (color:color-mix(in lab, red, red)){.shadow-purple-500\/5{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-purple-500) 5%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-purple-500\/10{--tw-shadow-color:#ac4bff1a}@supports (color:color-mix(in lab, red, red)){.shadow-purple-500\/10{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-purple-500) 10%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-purple-500\/20{--tw-shadow-color:#ac4bff33}@supports (color:color-mix(in lab, red, red)){.shadow-purple-500\/20{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-purple-500) 20%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-purple-500\/25{--tw-shadow-color:#ac4bff40}@supports (color:color-mix(in lab, red, red)){.shadow-purple-500\/25{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-purple-500) 25%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-purple-600\/20{--tw-shadow-color:#9810fa33}@supports (color:color-mix(in lab, red, red)){.shadow-purple-600\/20{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-purple-600) 20%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-purple-600\/25{--tw-shadow-color:#9810fa40}@supports (color:color-mix(in lab, red, red)){.shadow-purple-600\/25{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-purple-600) 25%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-purple-900\/10{--tw-shadow-color:#59168b1a}@supports (color:color-mix(in lab, red, red)){.shadow-purple-900\/10{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-purple-900) 10%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-purple-950\/10{--tw-shadow-color:#3c03661a}@supports (color:color-mix(in lab, red, red)){.shadow-purple-950\/10{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-purple-950) 10%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-red-500\/10{--tw-shadow-color:#fb2c361a}@supports (color:color-mix(in lab, red, red)){.shadow-red-500\/10{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-red-500) 10%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-red-600\/30{--tw-shadow-color:#e400144d}@supports (color:color-mix(in lab, red, red)){.shadow-red-600\/30{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-red-600) 30%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-rose-950\/20{--tw-shadow-color:#4d021833}@supports (color:color-mix(in lab, red, red)){.shadow-rose-950\/20{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-rose-950) 20%, transparent) var(--tw-shadow-alpha), transparent)}}.ring-\[\#121225\]{--tw-ring-color:#121225}.ring-amber-500\/30{--tw-ring-color:#f99c004d}@supports (color:color-mix(in lab, red, red)){.ring-amber-500\/30{--tw-ring-color:color-mix(in oklab, var(--color-amber-500) 30%, transparent)}}.ring-blue-500\/30{--tw-ring-color:#3080ff4d}@supports (color:color-mix(in lab, red, red)){.ring-blue-500\/30{--tw-ring-color:color-mix(in oklab, var(--color-blue-500) 30%, transparent)}}.ring-emerald-500\/30{--tw-ring-color:#00bb7f4d}@supports (color:color-mix(in lab, red, red)){.ring-emerald-500\/30{--tw-ring-color:color-mix(in oklab, var(--color-emerald-500) 30%, transparent)}}.ring-purple-500{--tw-ring-color:var(--color-purple-500)}.ring-purple-500\/10{--tw-ring-color:#ac4bff1a}@supports (color:color-mix(in lab, red, red)){.ring-purple-500\/10{--tw-ring-color:color-mix(in oklab, var(--color-purple-500) 10%, transparent)}}.ring-purple-500\/20{--tw-ring-color:#ac4bff33}@supports (color:color-mix(in lab, red, red)){.ring-purple-500\/20{--tw-ring-color:color-mix(in oklab, var(--color-purple-500) 20%, transparent)}}.ring-purple-500\/30{--tw-ring-color:#ac4bff4d}@supports (color:color-mix(in lab, red, red)){.ring-purple-500\/30{--tw-ring-color:color-mix(in oklab, var(--color-purple-500) 30%, transparent)}}.ring-purple-500\/40{--tw-ring-color:#ac4bff66}@supports (color:color-mix(in lab, red, red)){.ring-purple-500\/40{--tw-ring-color:color-mix(in oklab, var(--color-purple-500) 40%, transparent)}}.ring-rose-500\/30{--tw-ring-color:#ff23574d}@supports (color:color-mix(in lab, red, red)){.ring-rose-500\/30{--tw-ring-color:color-mix(in oklab, var(--color-rose-500) 30%, transparent)}}.ring-teal-500\/10{--tw-ring-color:#00baa71a}@supports (color:color-mix(in lab, red, red)){.ring-teal-500\/10{--tw-ring-color:color-mix(in oklab, var(--color-teal-500) 10%, transparent)}}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur-2xl{--tw-blur:blur(var(--blur-2xl));filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.blur-3xl{--tw-blur:blur(var(--blur-3xl));filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.blur-\[100px\]{--tw-blur:blur(100px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.blur-\[120px\]{--tw-blur:blur(120px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.blur-xl{--tw-blur:blur(var(--blur-xl));filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.sepia{--tw-sepia:sepia(100%);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur-md{--tw-backdrop-blur:blur(var(--blur-md));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.backdrop-blur-xl{--tw-backdrop-blur:blur(var(--blur-xl));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.duration-700{--tw-duration:.7s;transition-duration:.7s}.duration-1000{--tw-duration:1s;transition-duration:1s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.outline-none{--tw-outline-style:none;outline-style:none}.select-all{-webkit-user-select:all;user-select:all}.select-none{-webkit-user-select:none;user-select:none}.select-text{-webkit-user-select:text;user-select:text}@media (hover:hover){.group-hover\:scale-115:is(:where(.group):hover *){--tw-scale-x:115%;--tw-scale-y:115%;--tw-scale-z:115%;scale:var(--tw-scale-x) var(--tw-scale-y)}.group-hover\:scale-\[1\.02\]:is(:where(.group):hover *){scale:1.02}.group-hover\:bg-blue-500\/10:is(:where(.group):hover *){background-color:#3080ff1a}@supports (color:color-mix(in lab, red, red)){.group-hover\:bg-blue-500\/10:is(:where(.group):hover *){background-color:color-mix(in oklab, var(--color-blue-500) 10%, transparent)}}.group-hover\:bg-emerald-500\/10:is(:where(.group):hover *){background-color:#00bb7f1a}@supports (color:color-mix(in lab, red, red)){.group-hover\:bg-emerald-500\/10:is(:where(.group):hover *){background-color:color-mix(in oklab, var(--color-emerald-500) 10%, transparent)}}.group-hover\:bg-purple-500\/10:is(:where(.group):hover *){background-color:#ac4bff1a}@supports (color:color-mix(in lab, red, red)){.group-hover\:bg-purple-500\/10:is(:where(.group):hover *){background-color:color-mix(in oklab, var(--color-purple-500) 10%, transparent)}}.group-hover\:bg-slate-400:is(:where(.group):hover *){background-color:var(--color-slate-400)}.group-hover\:text-brand-400:is(:where(.group):hover *){color:var(--color-brand-400)}.group-hover\:text-purple-400:is(:where(.group):hover *){color:var(--color-purple-400)}.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}}.last\:border-0:last-child{border-style:var(--tw-border-style);border-width:0}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.last\:pb-0:last-child{padding-bottom:calc(var(--spacing) * 0)}.focus-within\:border-purple-500:focus-within{border-color:var(--color-purple-500)}@media (hover:hover){.hover\:-translate-y-0\.5:hover{--tw-translate-y:calc(var(--spacing) * -.5);translate:var(--tw-translate-x) var(--tw-translate-y)}.hover\:translate-y-\[-2px\]:hover{--tw-translate-y:-2px;translate:var(--tw-translate-x) var(--tw-translate-y)}.hover\:scale-102:hover{--tw-scale-x:102%;--tw-scale-y:102%;--tw-scale-z:102%;scale:var(--tw-scale-x) var(--tw-scale-y)}.hover\:scale-105:hover{--tw-scale-x:105%;--tw-scale-y:105%;--tw-scale-z:105%;scale:var(--tw-scale-x) var(--tw-scale-y)}.hover\:scale-115:hover{--tw-scale-x:115%;--tw-scale-y:115%;--tw-scale-z:115%;scale:var(--tw-scale-x) var(--tw-scale-y)}.hover\:scale-\[1\.01\]:hover{scale:1.01}.hover\:scale-\[1\.02\]:hover{scale:1.02}.hover\:border-\[\#1f1f3a\]:hover{border-color:#1f1f3a}.hover\:border-amber-400:hover{border-color:var(--color-amber-400)}.hover\:border-blue-500\/20:hover{border-color:#3080ff33}@supports (color:color-mix(in lab, red, red)){.hover\:border-blue-500\/20:hover{border-color:color-mix(in oklab, var(--color-blue-500) 20%, transparent)}}.hover\:border-brand-500\/35:hover{border-color:#8b5cf659}@supports (color:color-mix(in lab, red, red)){.hover\:border-brand-500\/35:hover{border-color:color-mix(in oklab, var(--color-brand-500) 35%, transparent)}}.hover\:border-brand-500\/50:hover{border-color:#8b5cf680}@supports (color:color-mix(in lab, red, red)){.hover\:border-brand-500\/50:hover{border-color:color-mix(in oklab, var(--color-brand-500) 50%, transparent)}}.hover\:border-emerald-500\/20:hover{border-color:#00bb7f33}@supports (color:color-mix(in lab, red, red)){.hover\:border-emerald-500\/20:hover{border-color:color-mix(in oklab, var(--color-emerald-500) 20%, transparent)}}.hover\:border-indigo-500\/50:hover{border-color:#625fff80}@supports (color:color-mix(in lab, red, red)){.hover\:border-indigo-500\/50:hover{border-color:color-mix(in oklab, var(--color-indigo-500) 50%, transparent)}}.hover\:border-purple-400:hover{border-color:var(--color-purple-400)}.hover\:border-purple-500:hover{border-color:var(--color-purple-500)}.hover\:border-purple-500\/20:hover{border-color:#ac4bff33}@supports (color:color-mix(in lab, red, red)){.hover\:border-purple-500\/20:hover{border-color:color-mix(in oklab, var(--color-purple-500) 20%, transparent)}}.hover\:border-purple-500\/30:hover{border-color:#ac4bff4d}@supports (color:color-mix(in lab, red, red)){.hover\:border-purple-500\/30:hover{border-color:color-mix(in oklab, var(--color-purple-500) 30%, transparent)}}.hover\:border-purple-500\/40:hover{border-color:#ac4bff66}@supports (color:color-mix(in lab, red, red)){.hover\:border-purple-500\/40:hover{border-color:color-mix(in oklab, var(--color-purple-500) 40%, transparent)}}.hover\:border-purple-500\/45:hover{border-color:#ac4bff73}@supports (color:color-mix(in lab, red, red)){.hover\:border-purple-500\/45:hover{border-color:color-mix(in oklab, var(--color-purple-500) 45%, transparent)}}.hover\:border-purple-500\/50:hover{border-color:#ac4bff80}@supports (color:color-mix(in lab, red, red)){.hover\:border-purple-500\/50:hover{border-color:color-mix(in oklab, var(--color-purple-500) 50%, transparent)}}.hover\:border-teal-500\/10:hover{border-color:#00baa71a}@supports (color:color-mix(in lab, red, red)){.hover\:border-teal-500\/10:hover{border-color:color-mix(in oklab, var(--color-teal-500) 10%, transparent)}}.hover\:border-transparent:hover{border-color:#0000}.hover\:border-white\/20:hover{border-color:#fff3}@supports (color:color-mix(in lab, red, red)){.hover\:border-white\/20:hover{border-color:color-mix(in oklab, var(--color-white) 20%, transparent)}}.hover\:bg-\[\#1a1a35\]:hover{background-color:#1a1a35}.hover\:bg-\[\#2a2a5a\]:hover{background-color:#2a2a5a}.hover\:bg-\[\#7c3aed\]\/30:hover{background-color:oklab(54.1337% .0963843 -.226968/.3)}.hover\:bg-\[\#181d2a\]:hover{background-color:#181d2a}.hover\:bg-\[\#121225\]\/40:hover{background-color:oklab(19.323% .00805682 -.0370808/.4)}.hover\:bg-\[\#121225\]\/70:hover{background-color:oklab(19.323% .00805682 -.0370808/.7)}.hover\:bg-\[\#232346\]:hover{background-color:#232346}.hover\:bg-\[\#334155\]:hover{background-color:#334155}.hover\:bg-\[\#ffffff10\]:hover{background-color:#ffffff10}.hover\:bg-amber-400\/15:hover{background-color:#fcbb0026}@supports (color:color-mix(in lab, red, red)){.hover\:bg-amber-400\/15:hover{background-color:color-mix(in oklab, var(--color-amber-400) 15%, transparent)}}.hover\:bg-amber-500:hover{background-color:var(--color-amber-500)}.hover\:bg-amber-600\/40:hover{background-color:#dd740066}@supports (color:color-mix(in lab, red, red)){.hover\:bg-amber-600\/40:hover{background-color:color-mix(in oklab, var(--color-amber-600) 40%, transparent)}}.hover\:bg-black\/20:hover{background-color:#0003}@supports (color:color-mix(in lab, red, red)){.hover\:bg-black\/20:hover{background-color:color-mix(in oklab, var(--color-black) 20%, transparent)}}.hover\:bg-black\/75:hover{background-color:#000000bf}@supports (color:color-mix(in lab, red, red)){.hover\:bg-black\/75:hover{background-color:color-mix(in oklab, var(--color-black) 75%, transparent)}}.hover\:bg-blue-500:hover{background-color:var(--color-blue-500)}.hover\:bg-blue-500\/20:hover{background-color:#3080ff33}@supports (color:color-mix(in lab, red, red)){.hover\:bg-blue-500\/20:hover{background-color:color-mix(in oklab, var(--color-blue-500) 20%, transparent)}}.hover\:bg-brand-500:hover{background-color:var(--color-brand-500)}.hover\:bg-brand-500\/35:hover{background-color:#8b5cf659}@supports (color:color-mix(in lab, red, red)){.hover\:bg-brand-500\/35:hover{background-color:color-mix(in oklab, var(--color-brand-500) 35%, transparent)}}.hover\:bg-emerald-500:hover{background-color:var(--color-emerald-500)}.hover\:bg-emerald-500\/20:hover{background-color:#00bb7f33}@supports (color:color-mix(in lab, red, red)){.hover\:bg-emerald-500\/20:hover{background-color:color-mix(in oklab, var(--color-emerald-500) 20%, transparent)}}.hover\:bg-emerald-500\/30:hover{background-color:#00bb7f4d}@supports (color:color-mix(in lab, red, red)){.hover\:bg-emerald-500\/30:hover{background-color:color-mix(in oklab, var(--color-emerald-500) 30%, transparent)}}.hover\:bg-fuchsia-500\/20:hover{background-color:#e12afb33}@supports (color:color-mix(in lab, red, red)){.hover\:bg-fuchsia-500\/20:hover{background-color:color-mix(in oklab, var(--color-fuchsia-500) 20%, transparent)}}.hover\:bg-indigo-500:hover{background-color:var(--color-indigo-500)}.hover\:bg-indigo-600\/40:hover{background-color:#4f39f666}@supports (color:color-mix(in lab, red, red)){.hover\:bg-indigo-600\/40:hover{background-color:color-mix(in oklab, var(--color-indigo-600) 40%, transparent)}}.hover\:bg-indigo-600\/50:hover{background-color:#4f39f680}@supports (color:color-mix(in lab, red, red)){.hover\:bg-indigo-600\/50:hover{background-color:color-mix(in oklab, var(--color-indigo-600) 50%, transparent)}}.hover\:bg-orange-500\/20:hover{background-color:#fe6e0033}@supports (color:color-mix(in lab, red, red)){.hover\:bg-orange-500\/20:hover{background-color:color-mix(in oklab, var(--color-orange-500) 20%, transparent)}}.hover\:bg-purple-500:hover{background-color:var(--color-purple-500)}.hover\:bg-purple-500\/5:hover{background-color:#ac4bff0d}@supports (color:color-mix(in lab, red, red)){.hover\:bg-purple-500\/5:hover{background-color:color-mix(in oklab, var(--color-purple-500) 5%, transparent)}}.hover\:bg-purple-500\/10:hover{background-color:#ac4bff1a}@supports (color:color-mix(in lab, red, red)){.hover\:bg-purple-500\/10:hover{background-color:color-mix(in oklab, var(--color-purple-500) 10%, transparent)}}.hover\:bg-purple-500\/20:hover{background-color:#ac4bff33}@supports (color:color-mix(in lab, red, red)){.hover\:bg-purple-500\/20:hover{background-color:color-mix(in oklab, var(--color-purple-500) 20%, transparent)}}.hover\:bg-purple-600:hover{background-color:var(--color-purple-600)}.hover\:bg-purple-600\/10:hover{background-color:#9810fa1a}@supports (color:color-mix(in lab, red, red)){.hover\:bg-purple-600\/10:hover{background-color:color-mix(in oklab, var(--color-purple-600) 10%, transparent)}}.hover\:bg-purple-600\/20:hover{background-color:#9810fa33}@supports (color:color-mix(in lab, red, red)){.hover\:bg-purple-600\/20:hover{background-color:color-mix(in oklab, var(--color-purple-600) 20%, transparent)}}.hover\:bg-purple-600\/30:hover{background-color:#9810fa4d}@supports (color:color-mix(in lab, red, red)){.hover\:bg-purple-600\/30:hover{background-color:color-mix(in oklab, var(--color-purple-600) 30%, transparent)}}.hover\:bg-purple-600\/35:hover{background-color:#9810fa59}@supports (color:color-mix(in lab, red, red)){.hover\:bg-purple-600\/35:hover{background-color:color-mix(in oklab, var(--color-purple-600) 35%, transparent)}}.hover\:bg-purple-900\/40:hover{background-color:#59168b66}@supports (color:color-mix(in lab, red, red)){.hover\:bg-purple-900\/40:hover{background-color:color-mix(in oklab, var(--color-purple-900) 40%, transparent)}}.hover\:bg-purple-950\/10:hover{background-color:#3c03661a}@supports (color:color-mix(in lab, red, red)){.hover\:bg-purple-950\/10:hover{background-color:color-mix(in oklab, var(--color-purple-950) 10%, transparent)}}.hover\:bg-purple-950\/20:hover{background-color:#3c036633}@supports (color:color-mix(in lab, red, red)){.hover\:bg-purple-950\/20:hover{background-color:color-mix(in oklab, var(--color-purple-950) 20%, transparent)}}.hover\:bg-purple-950\/25:hover{background-color:#3c036640}@supports (color:color-mix(in lab, red, red)){.hover\:bg-purple-950\/25:hover{background-color:color-mix(in oklab, var(--color-purple-950) 25%, transparent)}}.hover\:bg-red-400\/10:hover{background-color:#ff65681a}@supports (color:color-mix(in lab, red, red)){.hover\:bg-red-400\/10:hover{background-color:color-mix(in oklab, var(--color-red-400) 10%, transparent)}}.hover\:bg-red-500:hover{background-color:var(--color-red-500)}.hover\:bg-red-500\/20:hover{background-color:#fb2c3633}@supports (color:color-mix(in lab, red, red)){.hover\:bg-red-500\/20:hover{background-color:color-mix(in oklab, var(--color-red-500) 20%, transparent)}}.hover\:bg-rose-500:hover{background-color:var(--color-rose-500)}.hover\:bg-rose-500\/10:hover{background-color:#ff23571a}@supports (color:color-mix(in lab, red, red)){.hover\:bg-rose-500\/10:hover{background-color:color-mix(in oklab, var(--color-rose-500) 10%, transparent)}}.hover\:bg-rose-600:hover{background-color:var(--color-rose-600)}.hover\:bg-rose-600\/40:hover{background-color:#e7004466}@supports (color:color-mix(in lab, red, red)){.hover\:bg-rose-600\/40:hover{background-color:color-mix(in oklab, var(--color-rose-600) 40%, transparent)}}.hover\:bg-slate-50:hover{background-color:var(--color-slate-50)}.hover\:bg-slate-500\/20:hover{background-color:#62748e33}@supports (color:color-mix(in lab, red, red)){.hover\:bg-slate-500\/20:hover{background-color:color-mix(in oklab, var(--color-slate-500) 20%, transparent)}}.hover\:bg-slate-700:hover{background-color:var(--color-slate-700)}.hover\:bg-slate-700\/40:hover{background-color:#31415866}@supports (color:color-mix(in lab, red, red)){.hover\:bg-slate-700\/40:hover{background-color:color-mix(in oklab, var(--color-slate-700) 40%, transparent)}}.hover\:bg-slate-700\/60:hover{background-color:#31415899}@supports (color:color-mix(in lab, red, red)){.hover\:bg-slate-700\/60:hover{background-color:color-mix(in oklab, var(--color-slate-700) 60%, transparent)}}.hover\:bg-slate-800:hover{background-color:var(--color-slate-800)}.hover\:bg-teal-500:hover{background-color:var(--color-teal-500)}.hover\:bg-teal-500\/10:hover{background-color:#00baa71a}@supports (color:color-mix(in lab, red, red)){.hover\:bg-teal-500\/10:hover{background-color:color-mix(in oklab, var(--color-teal-500) 10%, transparent)}}.hover\:bg-teal-600:hover{background-color:var(--color-teal-600)}.hover\:bg-teal-950\/20:hover{background-color:#022f2e33}@supports (color:color-mix(in lab, red, red)){.hover\:bg-teal-950\/20:hover{background-color:color-mix(in oklab, var(--color-teal-950) 20%, transparent)}}.hover\:bg-violet-500\/20:hover{background-color:#8d54ff33}@supports (color:color-mix(in lab, red, red)){.hover\:bg-violet-500\/20:hover{background-color:color-mix(in oklab, var(--color-violet-500) 20%, transparent)}}.hover\:bg-white\/5:hover{background-color:#ffffff0d}@supports (color:color-mix(in lab, red, red)){.hover\:bg-white\/5:hover{background-color:color-mix(in oklab, var(--color-white) 5%, transparent)}}.hover\:bg-white\/10:hover{background-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.hover\:bg-white\/10:hover{background-color:color-mix(in oklab, var(--color-white) 10%, transparent)}}.hover\:bg-white\/20:hover{background-color:#fff3}@supports (color:color-mix(in lab, red, red)){.hover\:bg-white\/20:hover{background-color:color-mix(in oklab, var(--color-white) 20%, transparent)}}.hover\:bg-white\/\[0\.01\]:hover{background-color:#ffffff03}@supports (color:color-mix(in lab, red, red)){.hover\:bg-white\/\[0\.01\]:hover{background-color:color-mix(in oklab, var(--color-white) 1%, transparent)}}.hover\:bg-white\/\[0\.02\]:hover{background-color:#ffffff05}@supports (color:color-mix(in lab, red, red)){.hover\:bg-white\/\[0\.02\]:hover{background-color:color-mix(in oklab, var(--color-white) 2%, transparent)}}.hover\:bg-white\/\[0\.03\]:hover{background-color:#ffffff08}@supports (color:color-mix(in lab, red, red)){.hover\:bg-white\/\[0\.03\]:hover{background-color:color-mix(in oklab, var(--color-white) 3%, transparent)}}.hover\:bg-white\/\[0\.05\]:hover{background-color:#ffffff0d}@supports (color:color-mix(in lab, red, red)){.hover\:bg-white\/\[0\.05\]:hover{background-color:color-mix(in oklab, var(--color-white) 5%, transparent)}}.hover\:bg-zinc-500\/20:hover{background-color:#71717b33}@supports (color:color-mix(in lab, red, red)){.hover\:bg-zinc-500\/20:hover{background-color:color-mix(in oklab, var(--color-zinc-500) 20%, transparent)}}.hover\:from-blue-500:hover{--tw-gradient-from:var(--color-blue-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.hover\:from-orange-500\/30:hover{--tw-gradient-from:#fe6e004d}@supports (color:color-mix(in lab, red, red)){.hover\:from-orange-500\/30:hover{--tw-gradient-from:color-mix(in oklab, var(--color-orange-500) 30%, transparent)}}.hover\:from-orange-500\/30:hover{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.hover\:from-purple-500:hover{--tw-gradient-from:var(--color-purple-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.hover\:from-purple-900\/25:hover{--tw-gradient-from:#59168b40}@supports (color:color-mix(in lab, red, red)){.hover\:from-purple-900\/25:hover{--tw-gradient-from:color-mix(in oklab, var(--color-purple-900) 25%, transparent)}}.hover\:from-purple-900\/25:hover{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.hover\:to-amber-500\/30:hover{--tw-gradient-to:#f99c004d}@supports (color:color-mix(in lab, red, red)){.hover\:to-amber-500\/30:hover{--tw-gradient-to:color-mix(in oklab, var(--color-amber-500) 30%, transparent)}}.hover\:to-amber-500\/30:hover{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.hover\:to-indigo-500:hover{--tw-gradient-to:var(--color-indigo-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.hover\:to-indigo-900\/25:hover{--tw-gradient-to:#312c8540}@supports (color:color-mix(in lab, red, red)){.hover\:to-indigo-900\/25:hover{--tw-gradient-to:color-mix(in oklab, var(--color-indigo-900) 25%, transparent)}}.hover\:to-indigo-900\/25:hover{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.hover\:text-amber-200:hover{color:var(--color-amber-200)}.hover\:text-amber-300:hover{color:var(--color-amber-300)}.hover\:text-indigo-300:hover{color:var(--color-indigo-300)}.hover\:text-purple-300:hover{color:var(--color-purple-300)}.hover\:text-purple-400:hover{color:var(--color-purple-400)}.hover\:text-red-300:hover{color:var(--color-red-300)}.hover\:text-rose-200:hover{color:var(--color-rose-200)}.hover\:text-slate-200:hover{color:var(--color-slate-200)}.hover\:text-slate-300:hover{color:var(--color-slate-300)}.hover\:text-slate-400:hover{color:var(--color-slate-400)}.hover\:text-slate-500:hover{color:var(--color-slate-500)}.hover\:text-white:hover{color:var(--color-white)}.hover\:no-underline:hover{text-decoration-line:none}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-90:hover{opacity:.9}.hover\:opacity-100:hover{opacity:1}.hover\:shadow-xl:hover{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.hover\:shadow-blue-950\/5:hover{--tw-shadow-color:#1624560d}@supports (color:color-mix(in lab, red, red)){.hover\:shadow-blue-950\/5:hover{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-blue-950) 5%, transparent) var(--tw-shadow-alpha), transparent)}}.hover\:shadow-emerald-950\/5:hover{--tw-shadow-color:#002c220d}@supports (color:color-mix(in lab, red, red)){.hover\:shadow-emerald-950\/5:hover{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-emerald-950) 5%, transparent) var(--tw-shadow-alpha), transparent)}}.hover\:shadow-purple-500\/5:hover{--tw-shadow-color:#ac4bff0d}@supports (color:color-mix(in lab, red, red)){.hover\:shadow-purple-500\/5:hover{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-purple-500) 5%, transparent) var(--tw-shadow-alpha), transparent)}}.hover\:shadow-purple-950\/5:hover{--tw-shadow-color:#3c03660d}@supports (color:color-mix(in lab, red, red)){.hover\:shadow-purple-950\/5:hover{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-purple-950) 5%, transparent) var(--tw-shadow-alpha), transparent)}}.hover\:brightness-105:hover{--tw-brightness:brightness(105%);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}}.focus\:border-amber-400:focus{border-color:var(--color-amber-400)}.focus\:border-amber-500:focus{border-color:var(--color-amber-500)}.focus\:border-blue-500:focus{border-color:var(--color-blue-500)}.focus\:border-brand-500:focus{border-color:var(--color-brand-500)}.focus\:border-indigo-500:focus{border-color:var(--color-indigo-500)}.focus\:border-purple-500:focus{border-color:var(--color-purple-500)}.focus\:border-purple-500\/50:focus{border-color:#ac4bff80}@supports (color:color-mix(in lab, red, red)){.focus\:border-purple-500\/50:focus{border-color:color-mix(in oklab, var(--color-purple-500) 50%, transparent)}}.focus\:border-purple-500\/70:focus{border-color:#ac4bffb3}@supports (color:color-mix(in lab, red, red)){.focus\:border-purple-500\/70:focus{border-color:color-mix(in oklab, var(--color-purple-500) 70%, transparent)}}.focus\:border-teal-500:focus{border-color:var(--color-teal-500)}.focus\:ring-0:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:ring-1:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:ring-purple-500:focus{--tw-ring-color:var(--color-purple-500)}.focus\:ring-purple-500\/20:focus{--tw-ring-color:#ac4bff33}@supports (color:color-mix(in lab, red, red)){.focus\:ring-purple-500\/20:focus{--tw-ring-color:color-mix(in oklab, var(--color-purple-500) 20%, transparent)}}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.active\:translate-y-0:active{--tw-translate-y:calc(var(--spacing) * 0);translate:var(--tw-translate-x) var(--tw-translate-y)}.active\:scale-90:active{--tw-scale-x:90%;--tw-scale-y:90%;--tw-scale-z:90%;scale:var(--tw-scale-x) var(--tw-scale-y)}.active\:scale-95:active{--tw-scale-x:95%;--tw-scale-y:95%;--tw-scale-z:95%;scale:var(--tw-scale-x) var(--tw-scale-y)}.active\:scale-98:active{--tw-scale-x:98%;--tw-scale-y:98%;--tw-scale-z:98%;scale:var(--tw-scale-x) var(--tw-scale-y)}.active\:cursor-grabbing:active{cursor:grabbing}.active\:bg-slate-100:active{background-color:var(--color-slate-100)}.active\:text-purple-400:active{color:var(--color-purple-400)}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-indigo-600\/50:disabled{background-color:#4f39f680}@supports (color:color-mix(in lab, red, red)){.disabled\:bg-indigo-600\/50:disabled{background-color:color-mix(in oklab, var(--color-indigo-600) 50%, transparent)}}.disabled\:bg-purple-600\/30:disabled{background-color:#9810fa4d}@supports (color:color-mix(in lab, red, red)){.disabled\:bg-purple-600\/30:disabled{background-color:color-mix(in oklab, var(--color-purple-600) 30%, transparent)}}.disabled\:bg-slate-800:disabled{background-color:var(--color-slate-800)}.disabled\:text-slate-500:disabled{color:var(--color-slate-500)}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}@media (width>=40rem){.sm\:right-6{right:calc(var(--spacing) * 6)}.sm\:bottom-6{bottom:calc(var(--spacing) * 6)}.sm\:left-auto{left:auto}.sm\:col-span-1{grid-column:span 1/span 1}.sm\:col-span-3{grid-column:span 3/span 3}.sm\:line-clamp-3{-webkit-line-clamp:3;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.sm\:block{display:block}.sm\:flex{display:flex}.sm\:hidden{display:none}.sm\:inline{display:inline}.sm\:inline-flex{display:inline-flex}.sm\:h-\[80vh\]{height:80vh}.sm\:min-h-\[360px\]{min-height:360px}.sm\:w-44{width:calc(var(--spacing) * 44)}.sm\:w-96{width:calc(var(--spacing) * 96)}.sm\:w-\[340px\]{width:340px}.sm\:w-\[380px\]{width:380px}.sm\:w-auto{width:auto}.sm\:max-w-2xl{max-width:var(--container-2xl)}.sm\:max-w-\[60\%\]{max-width:60%}.sm\:max-w-\[240px\]{max-width:240px}.sm\:max-w-md{max-width:var(--container-md)}.sm\:max-w-sm{max-width:var(--container-sm)}.sm\:flex-initial{flex:0 auto}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.sm\:grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:items-center{align-items:center}.sm\:justify-end{justify-content:flex-end}.sm\:justify-start{justify-content:flex-start}.sm\:gap-1{gap:calc(var(--spacing) * 1)}.sm\:gap-2\.5{gap:calc(var(--spacing) * 2.5)}.sm\:gap-4{gap:calc(var(--spacing) * 4)}:where(.sm\:space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}.sm\:rounded-2xl{border-radius:var(--radius-2xl)}.sm\:rounded-3xl{border-radius:var(--radius-3xl)}.sm\:border{border-style:var(--tw-border-style);border-width:1px}.sm\:p-1{padding:calc(var(--spacing) * 1)}.sm\:p-2{padding:calc(var(--spacing) * 2)}.sm\:p-4{padding:calc(var(--spacing) * 4)}.sm\:p-5{padding:calc(var(--spacing) * 5)}.sm\:p-8{padding:calc(var(--spacing) * 8)}.sm\:px-2{padding-inline:calc(var(--spacing) * 2)}.sm\:px-3{padding-inline:calc(var(--spacing) * 3)}.sm\:px-4{padding-inline:calc(var(--spacing) * 4)}.sm\:px-6{padding-inline:calc(var(--spacing) * 6)}.sm\:px-8{padding-inline:calc(var(--spacing) * 8)}.sm\:py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.sm\:py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.sm\:py-3{padding-block:calc(var(--spacing) * 3)}.sm\:py-4{padding-block:calc(var(--spacing) * 4)}.sm\:py-6{padding-block:calc(var(--spacing) * 6)}.sm\:pt-2{padding-top:calc(var(--spacing) * 2)}.sm\:pb-6{padding-bottom:calc(var(--spacing) * 6)}.sm\:text-left{text-align:left}.sm\:text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.sm\:text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.sm\:text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.sm\:text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.sm\:text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}}@media (width>=48rem){.md\:col-span-3{grid-column:span 3/span 3}.md\:col-span-6{grid-column:span 6/span 6}.md\:mx-0{margin-inline:calc(var(--spacing) * 0)}.md\:mx-1{margin-inline:calc(var(--spacing) * 1)}.md\:flex{display:flex}.md\:hidden{display:none}.md\:h-4{height:calc(var(--spacing) * 4)}.md\:h-5{height:calc(var(--spacing) * 5)}.md\:h-10{height:calc(var(--spacing) * 10)}.md\:h-20{height:calc(var(--spacing) * 20)}.md\:h-\[155px\]{height:155px}.md\:h-\[210px\]{height:210px}.md\:min-h-\[200px\]{min-height:200px}.md\:w-4{width:calc(var(--spacing) * 4)}.md\:w-10{width:calc(var(--spacing) * 10)}.md\:w-20{width:calc(var(--spacing) * 20)}.md\:w-56{width:calc(var(--spacing) * 56)}.md\:w-64{width:calc(var(--spacing) * 64)}.md\:w-72{width:calc(var(--spacing) * 72)}.md\:w-80{width:calc(var(--spacing) * 80)}.md\:w-\[110px\]{width:110px}.md\:w-\[150px\]{width:150px}.md\:w-auto{width:auto}.md\:flex-initial{flex:0 auto}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.md\:flex-row{flex-direction:row}.md\:items-center{align-items:center}.md\:items-start{align-items:flex-start}.md\:justify-end{justify-content:flex-end}.md\:justify-start{justify-content:flex-start}.md\:gap-2{gap:calc(var(--spacing) * 2)}:where(.md\:divide-x>:not(:last-child)){--tw-divide-x-reverse:0;border-inline-style:var(--tw-border-style);border-inline-start-width:calc(1px * var(--tw-divide-x-reverse));border-inline-end-width:calc(1px * calc(1 - var(--tw-divide-x-reverse)))}:where(.md\:divide-y-0>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(0px * var(--tw-divide-y-reverse));border-bottom-width:calc(0px * calc(1 - var(--tw-divide-y-reverse)))}.md\:border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.md\:border-b-0{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.md\:p-6{padding:calc(var(--spacing) * 6)}.md\:p-8{padding:calc(var(--spacing) * 8)}.md\:p-12{padding:calc(var(--spacing) * 12)}.md\:px-2{padding-inline:calc(var(--spacing) * 2)}.md\:px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.md\:px-3{padding-inline:calc(var(--spacing) * 3)}.md\:px-12{padding-inline:calc(var(--spacing) * 12)}.md\:px-16{padding-inline:calc(var(--spacing) * 16)}.md\:py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.md\:py-2{padding-block:calc(var(--spacing) * 2)}.md\:py-10{padding-block:calc(var(--spacing) * 10)}.md\:py-12{padding-block:calc(var(--spacing) * 12)}.md\:pr-1{padding-right:calc(var(--spacing) * 1)}.md\:pr-2{padding-right:calc(var(--spacing) * 2)}.md\:pl-3{padding-left:calc(var(--spacing) * 3)}.md\:text-left{text-align:left}.md\:text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.md\:text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.md\:text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.md\:text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.md\:text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.md\:text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.md\:opacity-0{opacity:0}@media (hover:hover){.md\:group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}}}@media (width>=64rem){.lg\:col-span-1{grid-column:span 1/span 1}.lg\:col-span-2{grid-column:span 2/span 2}.lg\:col-span-3{grid-column:span 3/span 3}.lg\:grid{display:grid}.lg\:inline{display:inline}.lg\:w-full{width:100%}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:flex-col{flex-direction:column}.lg\:gap-1\.5{gap:calc(var(--spacing) * 1.5)}.lg\:gap-12{gap:calc(var(--spacing) * 12)}.lg\:overflow-visible{overflow:visible}.lg\:px-3\.5{padding-inline:calc(var(--spacing) * 3.5)}.lg\:px-12{padding-inline:calc(var(--spacing) * 12)}.lg\:px-16{padding-inline:calc(var(--spacing) * 16)}.lg\:px-24{padding-inline:calc(var(--spacing) * 24)}.lg\:py-1\.5{padding-block:calc(var(--spacing) * 1.5)}}@media (width>=80rem){.xl\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}@media (width>=96rem){.\32 xl\:inline{display:inline}.\32 xl\:px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.\32 xl\:py-1{padding-block:calc(var(--spacing) * 1)}}}.safe-bottom{padding-bottom:env(safe-area-inset-bottom,0px)}.safe-top{padding-top:env(safe-area-inset-top,0px)}@media (width>=1024px){::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:#0b0b14}::-webkit-scrollbar-thumb{background:#1f1f3a;border-radius:4px}::-webkit-scrollbar-thumb:hover{background:#2d2d55}}@media (width<=1023px){::-webkit-scrollbar{display:none}*{scrollbar-width:none}}.theme-sepia{color:#5c4033!important;background-color:#f4ecd8!important}.theme-green{color:#2e4a3e!important;background-color:#dfedd6!important}.theme-light{color:#1a1a1a!important;background-color:#fff!important}.theme-dark{color:#cbd5e1!important;background-color:#0b0b14!important}@keyframes bounce-wave{0%,to{transform:scaleY(.3)}50%{transform:scaleY(1)}}.audio-wave-bar{transform-origin:bottom;animation:.8s ease-in-out infinite bounce-wave}.audio-wave-bar:first-child{animation-delay:.1s}.audio-wave-bar:nth-child(2){animation-delay:.25s}.audio-wave-bar:nth-child(3){animation-delay:50ms}.audio-wave-bar:nth-child(4){animation-delay:.35s}.audio-wave-bar:nth-child(5){animation-delay:.15s}.ai-glow{box-shadow:0 0 15px #f59e0b66}.ai-glow:hover{box-shadow:0 0 25px #f59e0ba6}@keyframes fadeIn{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}.animate-fadeIn{animation:.25s forwards fadeIn}@keyframes slide-up{0%{opacity:0;transform:translateY(100%)}to{opacity:1;transform:translateY(0)}}.animate-slide-up{animation:.3s cubic-bezier(.32,.72,0,1) forwards slide-up}@keyframes nav-pop{0%{opacity:.5;transform:scale(.8)}to{opacity:1;transform:scale(1)}}.nav-active{animation:.18s forwards nav-pop}body.global-dragging *{-webkit-app-region:no-drag!important}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"";inherits:false;initial-value:100%}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-divide-x-reverse{syntax:"*";inherits:false;initial-value:0}@keyframes spin{to{transform:rotate(360deg)}}@keyframes ping{75%,to{opacity:0;transform:scale(2)}}@keyframes pulse{50%{opacity:.5}}@keyframes bounce{0%,to{animation-timing-function:cubic-bezier(.8,0,1,1);transform:translateY(-25%)}50%{animation-timing-function:cubic-bezier(0,0,.2,1);transform:none}} diff --git a/frontend-web/dist/assets/index-yRoRoI6u.js b/frontend-web/dist/assets/index-yRoRoI6u.js new file mode 100644 index 0000000000000000000000000000000000000000..35fda4b5934daa7c980c0200fcc51c5f3a1797c2 --- /dev/null +++ b/frontend-web/dist/assets/index-yRoRoI6u.js @@ -0,0 +1,836 @@ +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/esm-BLbJYcCa.js","assets/dist-DE1p5HKj.js","assets/Discover-BCmVIXus.js","assets/award-CKCOPIfL.js","assets/MainLayout-COiTxmNr.js","assets/square-DZKJ0QGR.js","assets/book-DwmTvSdZ.js","assets/BookCard-BCMDdlyN.js","assets/star-DjnKUekI.js","assets/GoogleAd-CD0eT9Wp.js","assets/Bookshelf-ClI6d9JY.js","assets/square-check-big-BhcFiAg6.js","assets/trash-2-DDhTqVwA.js","assets/HistoryPage-DD_Z3uyW.js","assets/clock-DEPYmZZ-.js","assets/BookDetail-CwKiYfhq.js","assets/eye-DsLuESBv.js","assets/Reader-DUnP7yTH.js","assets/useUsageTracker-Bc2zfMaM.js","assets/Developer-BFnP9Lg5.js","assets/plus-CSQqtn3N.js","assets/LocalReader-Bc5HMhfm.js","assets/Settings-d6v3GnDB.js","assets/shield-LuyExdkp.js","assets/laptop-BPoCx4gb.js","assets/AuthorDetail-lunBE6ER.js","assets/file-text-mhTXpwIY.js","assets/Messages-Df1xxWEC.js","assets/Sects-X0poZC74.js","assets/Downloads-DcrmkLWQ.js"])))=>i.map(i=>d[i]); +var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),s=(e,n)=>{let r={};for(var i in e)t(r,i,{get:e[i],enumerable:!0});return n||t(r,Symbol.toStringTag,{value:`Module`}),r},c=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;li[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},l=(n,r,a)=>(a=n==null?{}:e(i(n)),c(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n)),u=(e=>typeof require<`u`?require:typeof Proxy<`u`?new Proxy(e,{get:(e,t)=>(typeof require<`u`?require:e)[t]}):e)(function(e){if(typeof require<`u`)return require.apply(this,arguments);throw Error('Calling `require` for "'+e+"\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.")});(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var d=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.fragment`);function r(e,n,r){var i=null;if(r!==void 0&&(i=``+r),n.key!==void 0&&(i=``+n.key),`key`in n)for(var a in r={},n)a!==`key`&&(r[a]=n[a]);else r=n;return n=r.ref,{$$typeof:t,type:e,key:i,ref:n===void 0?null:n,props:r}}e.Fragment=n,e.jsx=r,e.jsxs=r})),f=o(((e,t)=>{t.exports=d()})),p=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.consumer`),s=Symbol.for(`react.context`),c=Symbol.for(`react.forward_ref`),l=Symbol.for(`react.suspense`),u=Symbol.for(`react.memo`),d=Symbol.for(`react.lazy`),f=Symbol.for(`react.activity`),p=Symbol.iterator;function m(e){return typeof e!=`object`||!e?null:(e=p&&e[p]||e[`@@iterator`],typeof e==`function`?e:null)}var h={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g=Object.assign,_={};function v(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}v.prototype.isReactComponent={},v.prototype.setState=function(e,t){if(typeof e!=`object`&&typeof e!=`function`&&e!=null)throw Error(`takes an object of state variables to update or a function which returns an object of state variables.`);this.updater.enqueueSetState(this,e,t,`setState`)},v.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,`forceUpdate`)};function y(){}y.prototype=v.prototype;function b(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}var x=b.prototype=new y;x.constructor=b,g(x,v.prototype),x.isPureReactComponent=!0;var S=Array.isArray;function C(){}var w={H:null,A:null,T:null,S:null},ee=Object.prototype.hasOwnProperty;function te(e,n,r){var i=r.ref;return{$$typeof:t,type:e,key:n,ref:i===void 0?null:i,props:r}}function T(e,t){return te(e.type,t,e.props)}function E(e){return typeof e==`object`&&!!e&&e.$$typeof===t}function D(e){var t={"=":`=0`,":":`=2`};return`$`+e.replace(/[=:]/g,function(e){return t[e]})}var ne=/\/+/g;function re(e,t){return typeof e==`object`&&e&&e.key!=null?D(``+e.key):t.toString(36)}function O(e){switch(e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason;default:switch(typeof e.status==`string`?e.then(C,C):(e.status=`pending`,e.then(function(t){e.status===`pending`&&(e.status=`fulfilled`,e.value=t)},function(t){e.status===`pending`&&(e.status=`rejected`,e.reason=t)})),e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason}}throw e}function k(e,r,i,a,o){var s=typeof e;(s===`undefined`||s===`boolean`)&&(e=null);var c=!1;if(e===null)c=!0;else switch(s){case`bigint`:case`string`:case`number`:c=!0;break;case`object`:switch(e.$$typeof){case t:case n:c=!0;break;case d:return c=e._init,k(c(e._payload),r,i,a,o)}}if(c)return o=o(e),c=a===``?`.`+re(e,0):a,S(o)?(i=``,c!=null&&(i=c.replace(ne,`$&/`)+`/`),k(o,r,i,``,function(e){return e})):o!=null&&(E(o)&&(o=T(o,i+(o.key==null||e&&e.key===o.key?``:(``+o.key).replace(ne,`$&/`)+`/`)+c)),r.push(o)),1;c=0;var l=a===``?`.`:a+`:`;if(S(e))for(var u=0;u{t.exports=p()})),h=o((e=>{function t(e,t){var n=e.length;e.push(t);a:for(;0>>1,a=e[r];if(0>>1;ri(c,n))li(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else if(li(u,n))e[r]=u,e[l]=n,r=l;else break a}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return n===0?e.id-t.id:n}if(e.unstable_now=void 0,typeof performance==`object`&&typeof performance.now==`function`){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var c=[],l=[],u=1,d=null,f=3,p=!1,m=!1,h=!1,g=!1,_=typeof setTimeout==`function`?setTimeout:null,v=typeof clearTimeout==`function`?clearTimeout:null,y=typeof setImmediate<`u`?setImmediate:null;function b(e){for(var i=n(l);i!==null;){if(i.callback===null)r(l);else if(i.startTime<=e)r(l),i.sortIndex=i.expirationTime,t(c,i);else break;i=n(l)}}function x(e){if(h=!1,b(e),!m)if(n(c)!==null)m=!0,S||(S=!0,E());else{var t=n(l);t!==null&&re(x,t.startTime-e)}}var S=!1,C=-1,w=5,ee=-1;function te(){return g?!0:!(e.unstable_now()-eet&&te());){var o=d.callback;if(typeof o==`function`){d.callback=null,f=d.priorityLevel;var s=o(d.expirationTime<=t);if(t=e.unstable_now(),typeof s==`function`){d.callback=s,b(t),i=!0;break b}d===n(c)&&r(c),b(t)}else r(c);d=n(c)}if(d!==null)i=!0;else{var u=n(l);u!==null&&re(x,u.startTime-t),i=!1}}break a}finally{d=null,f=a,p=!1}i=void 0}}finally{i?E():S=!1}}}var E;if(typeof y==`function`)E=function(){y(T)};else if(typeof MessageChannel<`u`){var D=new MessageChannel,ne=D.port2;D.port1.onmessage=T,E=function(){ne.postMessage(null)}}else E=function(){_(T,0)};function re(t,n){C=_(function(){t(e.unstable_now())},n)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(e){e.callback=null},e.unstable_forceFrameRate=function(e){0>e||125o?(r.sortIndex=a,t(l,r),n(c)===null&&r===n(l)&&(h?(v(C),C=-1):h=!0,re(x,a-o))):(r.sortIndex=s,t(c,r),m||p||(m=!0,S||(S=!0,E()))),r},e.unstable_shouldYield=te,e.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}})),g=o(((e,t)=>{t.exports=h()})),_=o((e=>{var t=m();function n(e){var t=`https://react.dev/errors/`+e;if(1{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=_()})),y=o((e=>{var t=g(),n=m(),r=v();function i(e){var t=`https://react.dev/errors/`+e;if(1se||(e.current=oe[se],oe[se]=null,se--)}function P(e,t){se++,oe[se]=e.current,e.current=t}var le=ce(null),F=ce(null),ue=ce(null),I=ce(null);function de(e,t){switch(P(ue,t),P(F,e),P(le,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Vd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Vd(t),e=Hd(t,e);else switch(e){case`svg`:e=1;break;case`math`:e=2;break;default:e=0}}N(le),P(le,e)}function L(){N(le),N(F),N(ue)}function fe(e){e.memoizedState!==null&&P(I,e);var t=le.current,n=Hd(t,e.type);t!==n&&(P(F,e),P(le,n))}function pe(e){F.current===e&&(N(le),N(F)),I.current===e&&(N(I),Qf._currentValue=ae)}var R,me;function he(e){if(R===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);R=t&&t[1]||``,me=-1)`:-1i||c[r]!==l[i]){var u=` +`+c[r].replace(` at new `,` at `);return e.displayName&&u.includes(``)&&(u=u.replace(``,e.displayName)),u}while(1<=r&&0<=i);break}}}finally{ge=!1,Error.prepareStackTrace=n}return(n=e?e.displayName||e.name:``)?he(n):``}function ve(e,t){switch(e.tag){case 26:case 27:case 5:return he(e.type);case 16:return he(`Lazy`);case 13:return e.child!==t&&t!==null?he(`Suspense Fallback`):he(`Suspense`);case 19:return he(`SuspenseList`);case 0:case 15:return _e(e.type,!1);case 11:return _e(e.type.render,!1);case 1:return _e(e.type,!0);case 31:return he(`Activity`);default:return``}}function ye(e){try{var t=``,n=null;do t+=ve(e,n),n=e,e=e.return;while(e);return t}catch(e){return` +Error generating stack: `+e.message+` +`+e.stack}}var be=Object.prototype.hasOwnProperty,xe=t.unstable_scheduleCallback,Se=t.unstable_cancelCallback,Ce=t.unstable_shouldYield,we=t.unstable_requestPaint,Te=t.unstable_now,Ee=t.unstable_getCurrentPriorityLevel,De=t.unstable_ImmediatePriority,Oe=t.unstable_UserBlockingPriority,ke=t.unstable_NormalPriority,Ae=t.unstable_LowPriority,je=t.unstable_IdlePriority,Me=t.log,Ne=t.unstable_setDisableYieldValue,Pe=null,Fe=null;function Ie(e){if(typeof Me==`function`&&Ne(e),Fe&&typeof Fe.setStrictMode==`function`)try{Fe.setStrictMode(Pe,e)}catch{}}var Le=Math.clz32?Math.clz32:Be,Re=Math.log,ze=Math.LN2;function Be(e){return e>>>=0,e===0?32:31-(Re(e)/ze|0)|0}var Ve=256,He=262144,Ue=4194304;function We(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function Ge(e,t,n){var r=e.pendingLanes;if(r===0)return 0;var i=0,a=e.suspendedLanes,o=e.pingedLanes;e=e.warmLanes;var s=r&134217727;return s===0?(s=r&~a,s===0?o===0?n||(n=r&~e,n!==0&&(i=We(n))):i=We(o):i=We(s)):(r=s&~a,r===0?(o&=s,o===0?n||(n=s&~e,n!==0&&(i=We(n))):i=We(o)):i=We(r)),i===0?0:t!==0&&t!==i&&(t&a)===0&&(a=i&-i,n=t&-t,a>=n||a===32&&n&4194048)?t:i}function Ke(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function qe(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function Je(){var e=Ue;return Ue<<=1,!(Ue&62914560)&&(Ue=4194304),e}function Ye(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function Xe(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function Ze(e,t,n,r,i,a){var o=e.pendingLanes;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=n,e.entangledLanes&=n,e.errorRecoveryDisabledLanes&=n,e.shellSuspendCounter=0;var s=e.entanglements,c=e.expirationTimes,l=e.hiddenUpdates;for(n=o&~n;0`u`||window.document===void 0||window.document.createElement===void 0),un=!1;if(ln)try{var dn={};Object.defineProperty(dn,"passive",{get:function(){un=!0}}),window.addEventListener(`test`,dn,dn),window.removeEventListener(`test`,dn,dn)}catch{un=!1}var fn=null,pn=null,mn=null;function hn(){if(mn)return mn;var e,t=pn,n=t.length,r,i=`value`in fn?fn.value:fn.textContent,a=i.length;for(e=0;e=qn),Xn=` `,Zn=!1;function Qn(e,t){switch(e){case`keyup`:return Gn.indexOf(t.keyCode)!==-1;case`keydown`:return t.keyCode!==229;case`keypress`:case`mousedown`:case`focusout`:return!0;default:return!1}}function $n(e){return e=e.detail,typeof e==`object`&&`data`in e?e.data:null}var er=!1;function tr(e,t){switch(e){case`compositionend`:return $n(t);case`keypress`:return t.which===32?(Zn=!0,Xn):null;case`textInput`:return e=t.data,e===Xn&&Zn?null:e;default:return null}}function nr(e,t){if(er)return e===`compositionend`||!Kn&&Qn(e,t)?(e=hn(),mn=pn=fn=null,er=!1,e):null;switch(e){case`paste`:return null;case`keypress`:if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}a:{for(;n;){if(n.nextSibling){n=n.nextSibling;break a}n=n.parentNode}n=void 0}n=wr(n)}}function Er(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Er(e,t.parentNode):`contains`in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Dr(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=It(e.document);t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href==`string`}catch{n=!1}if(n)e=t.contentWindow;else break;t=It(e.document)}return t}function Or(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t===`input`&&(e.type===`text`||e.type===`search`||e.type===`tel`||e.type===`url`||e.type===`password`)||t===`textarea`||e.contentEditable===`true`)}var kr=ln&&`documentMode`in document&&11>=document.documentMode,Ar=null,jr=null,Mr=null,Nr=!1;function Pr(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;Nr||Ar==null||Ar!==It(r)||(r=Ar,`selectionStart`in r&&Or(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),Mr&&Cr(Mr,r)||(Mr=r,r=Ed(jr,`onSelect`),0>=o,i-=o,Ti=1<<32-Le(t)+i|n<h?(g=d,d=null):g=d.sibling;var _=p(i,d,s[h],c);if(_===null){d===null&&(d=g);break}e&&d&&_.alternate===null&&t(i,d),a=o(_,a,h),u===null?l=_:u.sibling=_,u=_,d=g}if(h===s.length)return n(i,d),H&&Di(i,h),l;if(d===null){for(;hg?(_=h,h=null):_=h.sibling;var y=p(a,h,v.value,l);if(y===null){h===null&&(h=_);break}e&&h&&y.alternate===null&&t(a,h),s=o(y,s,g),d===null?u=y:d.sibling=y,d=y,h=_}if(v.done)return n(a,h),H&&Di(a,g),u;if(h===null){for(;!v.done;g++,v=c.next())v=f(a,v.value,l),v!==null&&(s=o(v,s,g),d===null?u=v:d.sibling=v,d=v);return H&&Di(a,g),u}for(h=r(h);!v.done;g++,v=c.next())v=m(h,a,g,v.value,l),v!==null&&(e&&v.alternate!==null&&h.delete(v.key===null?g:v.key),s=o(v,s,g),d===null?u=v:d.sibling=v,d=v);return e&&h.forEach(function(e){return t(a,e)}),H&&Di(a,g),u}function b(e,r,o,c){if(typeof o==`object`&&o&&o.type===y&&o.key===null&&(o=o.props.children),typeof o==`object`&&o){switch(o.$$typeof){case h:a:{for(var l=o.key;r!==null;){if(r.key===l){if(l=o.type,l===y){if(r.tag===7){n(e,r.sibling),c=a(r,o.props.children),c.return=e,e=c;break a}}else if(r.elementType===l||typeof l==`object`&&l&&l.$$typeof===E&&Ta(l)===r.type){n(e,r.sibling),c=a(r,o.props),Ma(c,o),c.return=e,e=c;break a}n(e,r);break}else t(e,r);r=r.sibling}o.type===y?(c=fi(o.props.children,e.mode,c,o.key),c.return=e,e=c):(c=di(o.type,o.key,o.props,null,e.mode,c),Ma(c,o),c.return=e,e=c)}return s(e);case _:a:{for(l=o.key;r!==null;){if(r.key===l)if(r.tag===4&&r.stateNode.containerInfo===o.containerInfo&&r.stateNode.implementation===o.implementation){n(e,r.sibling),c=a(r,o.children||[]),c.return=e,e=c;break a}else{n(e,r);break}else t(e,r);r=r.sibling}c=hi(o,e.mode,c),c.return=e,e=c}return s(e);case E:return o=Ta(o),b(e,r,o,c)}if(ie(o))return g(e,r,o,c);if(O(o)){if(l=O(o),typeof l!=`function`)throw Error(i(150));return o=l.call(o),v(e,r,o,c)}if(typeof o.then==`function`)return b(e,r,ja(o),c);if(o.$$typeof===C)return b(e,r,$i(e,o),c);Na(e,o)}return typeof o==`string`&&o!==``||typeof o==`number`||typeof o==`bigint`?(o=``+o,r!==null&&r.tag===6?(n(e,r.sibling),c=a(r,o),c.return=e,e=c):(n(e,r),c=pi(o,e.mode,c),c.return=e,e=c),s(e)):n(e,r)}return function(e,t,n,r){try{Aa=0;var i=b(e,t,n,r);return ka=null,i}catch(t){if(t===ya||t===xa)throw t;var a=ci(29,t,null,e.mode);return a.lanes=r,a.return=e,a}}}var Fa=Pa(!0),Ia=Pa(!1),La=!1;function Ra(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function za(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function Ba(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function Va(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,K&2){var i=r.pending;return i===null?t.next=t:(t.next=i.next,i.next=t),r.pending=t,t=ai(e),ii(e,null,n),t}return ti(e,r,t,n),ai(e)}function Ha(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,n&4194048)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,$e(e,n)}}function Ua(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var i=null,a=null;if(n=n.firstBaseUpdate,n!==null){do{var o={lane:n.lane,tag:n.tag,payload:n.payload,callback:null,next:null};a===null?i=a=o:a=a.next=o,n=n.next}while(n!==null);a===null?i=a=t:a=a.next=t}else i=a=t;n={baseState:r.baseState,firstBaseUpdate:i,lastBaseUpdate:a,shared:r.shared,callbacks:r.callbacks},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}var Wa=!1;function Ga(){if(Wa){var e=ua;if(e!==null)throw e}}function Ka(e,t,n,r){Wa=!1;var i=e.updateQueue;La=!1;var a=i.firstBaseUpdate,o=i.lastBaseUpdate,s=i.shared.pending;if(s!==null){i.shared.pending=null;var c=s,l=c.next;c.next=null,o===null?a=l:o.next=l,o=c;var u=e.alternate;u!==null&&(u=u.updateQueue,s=u.lastBaseUpdate,s!==o&&(s===null?u.firstBaseUpdate=l:s.next=l,u.lastBaseUpdate=c))}if(a!==null){var d=i.baseState;o=0,u=l=c=null,s=a;do{var p=s.lane&-536870913,m=p!==s.lane;if(m?(Y&p)===p:(r&p)===p){p!==0&&p===la&&(Wa=!0),u!==null&&(u=u.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});a:{var h=e,g=s;p=t;var _=n;switch(g.tag){case 1:if(h=g.payload,typeof h==`function`){d=h.call(_,d,p);break a}d=h;break a;case 3:h.flags=h.flags&-65537|128;case 0:if(h=g.payload,p=typeof h==`function`?h.call(_,d,p):h,p==null)break a;d=f({},d,p);break a;case 2:La=!0}}p=s.callback,p!==null&&(e.flags|=64,m&&(e.flags|=8192),m=i.callbacks,m===null?i.callbacks=[p]:m.push(p))}else m={lane:p,tag:s.tag,payload:s.payload,callback:s.callback,next:null},u===null?(l=u=m,c=d):u=u.next=m,o|=p;if(s=s.next,s===null){if(s=i.shared.pending,s===null)break;m=s,s=m.next,m.next=null,i.lastBaseUpdate=m,i.shared.pending=null}}while(1);u===null&&(c=d),i.baseState=c,i.firstBaseUpdate=l,i.lastBaseUpdate=u,a===null&&(i.shared.lanes=0),Gl|=o,e.lanes=o,e.memoizedState=d}}function qa(e,t){if(typeof e!=`function`)throw Error(i(191,e));e.call(t)}function Ja(e,t){var n=e.callbacks;if(n!==null)for(e.callbacks=null,e=0;ea?a:8;var o=j.T,s={};j.T=s,Ms(e,!1,t,n);try{var c=i(),l=j.S;l!==null&&l(s,c),typeof c==`object`&&c&&typeof c.then==`function`?js(e,t,pa(c,r),pu(e)):js(e,t,r,pu(e))}catch(n){js(e,t,{then:function(){},status:`rejected`,reason:n},pu())}finally{M.p=a,o!==null&&s.types!==null&&(o.types=s.types),j.T=o}}function xs(){}function Ss(e,t,n,r){if(e.tag!==5)throw Error(i(476));var a=Cs(e).queue;bs(e,a,t,ae,n===null?xs:function(){return ws(e),n(r)})}function Cs(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:ae,baseState:ae,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:No,lastRenderedState:ae},next:null};var n={};return t.next={memoizedState:n,baseState:n,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:No,lastRenderedState:n},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function ws(e){var t=Cs(e);t.next===null&&(t=e.alternate.memoizedState),js(e,t.next.queue,{},pu())}function Ts(){return Qi(Qf)}function Es(){return G().memoizedState}function Ds(){return G().memoizedState}function Os(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var n=pu();e=Ba(n);var r=Va(t,e,n);r!==null&&(hu(r,t,n),Ha(r,t,n)),t={cache:aa()},e.payload=t;return}t=t.return}}function ks(e,t,n){var r=pu();n={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null},Ns(e)?Ps(t,n):(n=ni(e,t,n,r),n!==null&&(hu(n,e,r),Fs(n,t,r)))}function As(e,t,n){js(e,t,n,pu())}function js(e,t,n,r){var i={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null};if(Ns(e))Ps(t,i);else{var a=e.alternate;if(e.lanes===0&&(a===null||a.lanes===0)&&(a=t.lastRenderedReducer,a!==null))try{var o=t.lastRenderedState,s=a(o,n);if(i.hasEagerState=!0,i.eagerState=s,Sr(s,o))return ti(e,t,i,0),q===null&&ei(),!1}catch{}if(n=ni(e,t,i,r),n!==null)return hu(n,e,r),Fs(n,t,r),!0}return!1}function Ms(e,t,n,r){if(r={lane:2,revertLane:dd(),gesture:null,action:r,hasEagerState:!1,eagerState:null,next:null},Ns(e)){if(t)throw Error(i(479))}else t=ni(e,n,r,2),t!==null&&hu(t,e,2)}function Ns(e){var t=e.alternate;return e===U||t!==null&&t===U}function Ps(e,t){po=fo=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function Fs(e,t,n){if(n&4194048){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,$e(e,n)}}var Is={readContext:Qi,use:jo,useCallback:yo,useContext:yo,useEffect:yo,useImperativeHandle:yo,useLayoutEffect:yo,useInsertionEffect:yo,useMemo:yo,useReducer:yo,useRef:yo,useState:yo,useDebugValue:yo,useDeferredValue:yo,useTransition:yo,useSyncExternalStore:yo,useId:yo,useHostTransitionStatus:yo,useFormState:yo,useActionState:yo,useOptimistic:yo,useMemoCache:yo,useCacheRefresh:yo};Is.useEffectEvent=yo;var Ls={readContext:Qi,use:jo,useCallback:function(e,t){return Oo().memoizedState=[e,t===void 0?null:t],e},useContext:Qi,useEffect:ss,useImperativeHandle:function(e,t,n){n=n==null?null:n.concat([e]),as(4194308,4,ps.bind(null,t,e),n)},useLayoutEffect:function(e,t){return as(4194308,4,e,t)},useInsertionEffect:function(e,t){as(4,2,e,t)},useMemo:function(e,t){var n=Oo();t=t===void 0?null:t;var r=e();if(mo){Ie(!0);try{e()}finally{Ie(!1)}}return n.memoizedState=[r,t],r},useReducer:function(e,t,n){var r=Oo();if(n!==void 0){var i=n(t);if(mo){Ie(!0);try{n(t)}finally{Ie(!1)}}}else i=t;return r.memoizedState=r.baseState=i,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:i},r.queue=e,e=e.dispatch=ks.bind(null,U,e),[r.memoizedState,e]},useRef:function(e){var t=Oo();return e={current:e},t.memoizedState=e},useState:function(e){e=Uo(e);var t=e.queue,n=As.bind(null,U,t);return t.dispatch=n,[e.memoizedState,n]},useDebugValue:hs,useDeferredValue:function(e,t){return vs(Oo(),e,t)},useTransition:function(){var e=Uo(!1);return e=bs.bind(null,U,e.queue,!0,!1),Oo().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,n){var r=U,a=Oo();if(H){if(n===void 0)throw Error(i(407));n=n()}else{if(n=t(),q===null)throw Error(i(349));Y&127||Ro(r,t,n)}a.memoizedState=n;var o={value:n,getSnapshot:t};return a.queue=o,ss(Bo.bind(null,r,o,e),[e]),r.flags|=2048,rs(9,{destroy:void 0},zo.bind(null,r,o,n,t),null),n},useId:function(){var e=Oo(),t=q.identifierPrefix;if(H){var n=Ei,r=Ti;n=(r&~(1<<32-Le(r)-1)).toString(32)+n,t=`_`+t+`R_`+n,n=ho++,0<\/script>`,o=o.removeChild(o.firstChild);break;case`select`:o=typeof r.is==`string`?s.createElement(`select`,{is:r.is}):s.createElement(`select`),r.multiple?o.multiple=!0:r.size&&(o.size=r.size);break;default:o=typeof r.is==`string`?s.createElement(a,{is:r.is}):s.createElement(a)}}o[ot]=t,o[st]=r;a:for(s=t.child;s!==null;){if(s.tag===5||s.tag===6)o.appendChild(s.stateNode);else if(s.tag!==4&&s.tag!==27&&s.child!==null){s.child.return=s,s=s.child;continue}if(s===t)break a;for(;s.sibling===null;){if(s.return===null||s.return===t)break a;s=s.return}s.sibling.return=s.return,s=s.sibling}t.stateNode=o;a:switch(Pd(o,a,r),a){case`button`:case`input`:case`select`:case`textarea`:r=!!r.autoFocus;break a;case`img`:r=!0;break a;default:r=!1}r&&jc(t)}}return Ic(t),Mc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,n),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==r&&jc(t);else{if(typeof r!=`string`&&t.stateNode===null)throw Error(i(166));if(e=ue.current,Ri(t)){if(e=t.stateNode,n=t.memoizedProps,r=null,a=ji,a!==null)switch(a.tag){case 27:case 5:r=a.memoizedProps}e[ot]=t,e=!!(e.nodeValue===n||r!==null&&!0===r.suppressHydrationWarning||Md(e.nodeValue,n)),e||Fi(t,!0)}else e=Bd(e).createTextNode(r),e[ot]=t,t.stateNode=e}return Ic(t),null;case 31:if(n=t.memoizedState,e===null||e.memoizedState!==null){if(r=Ri(t),n!==null){if(e===null){if(!r)throw Error(i(318));if(e=t.memoizedState,e=e===null?null:e.dehydrated,!e)throw Error(i(557));e[ot]=t}else zi(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;Ic(t),e=!1}else n=Bi(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),e=!0;if(!e)return t.flags&256?(oo(t),t):(oo(t),null);if(t.flags&128)throw Error(i(558))}return Ic(t),null;case 13:if(r=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(a=Ri(t),r!==null&&r.dehydrated!==null){if(e===null){if(!a)throw Error(i(318));if(a=t.memoizedState,a=a===null?null:a.dehydrated,!a)throw Error(i(317));a[ot]=t}else zi(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;Ic(t),a=!1}else a=Bi(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=a),a=!0;if(!a)return t.flags&256?(oo(t),t):(oo(t),null)}return oo(t),t.flags&128?(t.lanes=n,t):(n=r!==null,e=e!==null&&e.memoizedState!==null,n&&(r=t.child,a=null,r.alternate!==null&&r.alternate.memoizedState!==null&&r.alternate.memoizedState.cachePool!==null&&(a=r.alternate.memoizedState.cachePool.pool),o=null,r.memoizedState!==null&&r.memoizedState.cachePool!==null&&(o=r.memoizedState.cachePool.pool),o!==a&&(r.flags|=2048)),n!==e&&n&&(t.child.flags|=8192),Pc(t,t.updateQueue),Ic(t),null);case 4:return L(),e===null&&Sd(t.stateNode.containerInfo),Ic(t),null;case 10:return Ki(t.type),Ic(t),null;case 19:if(N(so),r=t.memoizedState,r===null)return Ic(t),null;if(a=(t.flags&128)!=0,o=r.rendering,o===null)if(a)Fc(r,!1);else{if(Wl!==0||e!==null&&e.flags&128)for(e=t.child;e!==null;){if(o=co(e),o!==null){for(t.flags|=128,Fc(r,!1),e=o.updateQueue,t.updateQueue=e,Pc(t,e),t.subtreeFlags=0,e=n,n=t.child;n!==null;)ui(n,e),n=n.sibling;return P(so,so.current&1|2),H&&Di(t,r.treeForkCount),t.child}e=e.sibling}r.tail!==null&&Te()>tu&&(t.flags|=128,a=!0,Fc(r,!1),t.lanes=4194304)}else{if(!a)if(e=co(o),e!==null){if(t.flags|=128,a=!0,e=e.updateQueue,t.updateQueue=e,Pc(t,e),Fc(r,!0),r.tail===null&&r.tailMode===`hidden`&&!o.alternate&&!H)return Ic(t),null}else 2*Te()-r.renderingStartTime>tu&&n!==536870912&&(t.flags|=128,a=!0,Fc(r,!1),t.lanes=4194304);r.isBackwards?(o.sibling=t.child,t.child=o):(e=r.last,e===null?t.child=o:e.sibling=o,r.last=o)}return r.tail===null?(Ic(t),null):(e=r.tail,r.rendering=e,r.tail=e.sibling,r.renderingStartTime=Te(),e.sibling=null,n=so.current,P(so,a?n&1|2:n&1),H&&Di(t,r.treeForkCount),e);case 22:case 23:return oo(t),$a(),r=t.memoizedState!==null,e===null?r&&(t.flags|=8192):e.memoizedState!==null!==r&&(t.flags|=8192),r?n&536870912&&!(t.flags&128)&&(Ic(t),t.subtreeFlags&6&&(t.flags|=8192)):Ic(t),n=t.updateQueue,n!==null&&Pc(t,n.retryQueue),n=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(n=e.memoizedState.cachePool.pool),r=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(r=t.memoizedState.cachePool.pool),r!==n&&(t.flags|=2048),e!==null&&N(ha),null;case 24:return n=null,e!==null&&(n=e.memoizedState.cache),t.memoizedState.cache!==n&&(t.flags|=2048),Ki(ia),Ic(t),null;case 25:return null;case 30:return null}throw Error(i(156,t.tag))}function Rc(e,t){switch(B(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Ki(ia),L(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return pe(t),null;case 31:if(t.memoizedState!==null){if(oo(t),t.alternate===null)throw Error(i(340));zi()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(oo(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(i(340));zi()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return N(so),null;case 4:return L(),null;case 10:return Ki(t.type),null;case 22:case 23:return oo(t),$a(),e!==null&&N(ha),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return Ki(ia),null;case 25:return null;default:return null}}function zc(e,t){switch(B(t),t.tag){case 3:Ki(ia),L();break;case 26:case 27:case 5:pe(t);break;case 4:L();break;case 31:t.memoizedState!==null&&oo(t);break;case 13:oo(t);break;case 19:N(so);break;case 10:Ki(t.type);break;case 22:case 23:oo(t),$a(),e!==null&&N(ha);break;case 24:Ki(ia)}}function Bc(e,t){try{var n=t.updateQueue,r=n===null?null:n.lastEffect;if(r!==null){var i=r.next;n=i;do{if((n.tag&e)===e){r=void 0;var a=n.create,o=n.inst;r=a(),o.destroy=r}n=n.next}while(n!==i)}}catch(e){Z(t,t.return,e)}}function Vc(e,t,n){try{var r=t.updateQueue,i=r===null?null:r.lastEffect;if(i!==null){var a=i.next;r=a;do{if((r.tag&e)===e){var o=r.inst,s=o.destroy;if(s!==void 0){o.destroy=void 0,i=t;var c=n,l=s;try{l()}catch(e){Z(i,c,e)}}}r=r.next}while(r!==a)}}catch(e){Z(t,t.return,e)}}function Hc(e){var t=e.updateQueue;if(t!==null){var n=e.stateNode;try{Ja(t,n)}catch(t){Z(e,e.return,t)}}}function Uc(e,t,n){n.props=Ws(e.type,e.memoizedProps),n.state=e.memoizedState;try{n.componentWillUnmount()}catch(n){Z(e,t,n)}}function Wc(e,t){try{var n=e.ref;if(n!==null){switch(e.tag){case 26:case 27:case 5:var r=e.stateNode;break;case 30:r=e.stateNode;break;default:r=e.stateNode}typeof n==`function`?e.refCleanup=n(r):n.current=r}}catch(n){Z(e,t,n)}}function Gc(e,t){var n=e.ref,r=e.refCleanup;if(n!==null)if(typeof r==`function`)try{r()}catch(n){Z(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof n==`function`)try{n(null)}catch(n){Z(e,t,n)}else n.current=null}function Kc(e){var t=e.type,n=e.memoizedProps,r=e.stateNode;try{a:switch(t){case`button`:case`input`:case`select`:case`textarea`:n.autoFocus&&r.focus();break a;case`img`:n.src?r.src=n.src:n.srcSet&&(r.srcset=n.srcSet)}}catch(t){Z(e,e.return,t)}}function qc(e,t,n){try{var r=e.stateNode;Fd(r,e.type,n,t),r[st]=t}catch(t){Z(e,e.return,t)}}function Jc(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&Zd(e.type)||e.tag===4}function Yc(e){a:for(;;){for(;e.sibling===null;){if(e.return===null||Jc(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&Zd(e.type)||e.flags&2||e.child===null||e.tag===4)continue a;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function Xc(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?(n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n).insertBefore(e,t):(t=n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n,t.appendChild(e),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=$t));else if(r!==4&&(r===27&&Zd(e.type)&&(n=e.stateNode,t=null),e=e.child,e!==null))for(Xc(e,t,n),e=e.sibling;e!==null;)Xc(e,t,n),e=e.sibling}function Zc(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(r===27&&Zd(e.type)&&(n=e.stateNode),e=e.child,e!==null))for(Zc(e,t,n),e=e.sibling;e!==null;)Zc(e,t,n),e=e.sibling}function Qc(e){var t=e.stateNode,n=e.memoizedProps;try{for(var r=e.type,i=t.attributes;i.length;)t.removeAttributeNode(i[0]);Pd(t,r,n),t[ot]=e,t[st]=n}catch(t){Z(e,e.return,t)}}var $c=!1,el=!1,tl=!1,nl=typeof WeakSet==`function`?WeakSet:Set,rl=null;function il(e,t){if(e=e.containerInfo,Rd=sp,e=Dr(e),Or(e)){if(`selectionStart`in e)var n={start:e.selectionStart,end:e.selectionEnd};else a:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var a=r.anchorOffset,o=r.focusNode;r=r.focusOffset;try{n.nodeType,o.nodeType}catch{n=null;break a}var s=0,c=-1,l=-1,u=0,d=0,f=e,p=null;b:for(;;){for(var m;f!==n||a!==0&&f.nodeType!==3||(c=s+a),f!==o||r!==0&&f.nodeType!==3||(l=s+r),f.nodeType===3&&(s+=f.nodeValue.length),(m=f.firstChild)!==null;)p=f,f=m;for(;;){if(f===e)break b;if(p===n&&++u===a&&(c=s),p===o&&++d===r&&(l=s),(m=f.nextSibling)!==null)break;f=p,p=f.parentNode}f=m}n=c===-1||l===-1?null:{start:c,end:l}}else n=null}n||={start:0,end:0}}else n=null;for(zd={focusedElem:e,selectionRange:n},sp=!1,rl=t;rl!==null;)if(t=rl,e=t.child,t.subtreeFlags&1028&&e!==null)e.return=t,rl=e;else for(;rl!==null;){switch(t=rl,o=t.alternate,e=t.flags,t.tag){case 0:if(e&4&&(e=t.updateQueue,e=e===null?null:e.events,e!==null))for(n=0;n title`))),Pd(o,r,n),o[ot]=e,yt(o),r=o;break a;case`link`:var s=Vf(`link`,`href`,a).get(r+(n.href||``));if(s){for(var c=0;cg&&(o=g,g=h,h=o);var _=Tr(s,h),v=Tr(s,g);if(_&&v&&(p.rangeCount!==1||p.anchorNode!==_.node||p.anchorOffset!==_.offset||p.focusNode!==v.node||p.focusOffset!==v.offset)){var y=d.createRange();y.setStart(_.node,_.offset),p.removeAllRanges(),h>g?(p.addRange(y),p.extend(v.node,v.offset)):(y.setEnd(v.node,v.offset),p.addRange(y))}}}}for(d=[],p=s;p=p.parentNode;)p.nodeType===1&&d.push({element:p,left:p.scrollLeft,top:p.scrollTop});for(typeof s.focus==`function`&&s.focus(),s=0;sn?32:n,j.T=null,n=lu,lu=null;var o=au,s=su;if(iu=0,ou=au=null,su=0,K&6)throw Error(i(331));var c=K;if(K|=4,Pl(o.current),El(o,o.current,s,n),K=c,id(0,!1),Fe&&typeof Fe.onPostCommitFiberRoot==`function`)try{Fe.onPostCommitFiberRoot(Pe,o)}catch{}return!0}finally{M.p=a,j.T=r,Vu(e,t)}}function Wu(e,t,n){t=_i(n,t),t=Xs(e.stateNode,t,2),e=Va(e,t,2),e!==null&&(Xe(e,2),rd(e))}function Z(e,t,n){if(e.tag===3)Wu(e,e,n);else for(;t!==null;){if(t.tag===3){Wu(t,e,n);break}else if(t.tag===1){var r=t.stateNode;if(typeof t.type.getDerivedStateFromError==`function`||typeof r.componentDidCatch==`function`&&(ru===null||!ru.has(r))){e=_i(n,e),n=Zs(2),r=Va(t,n,2),r!==null&&(Qs(n,r,t,e),Xe(r,2),rd(r));break}}t=t.return}}function Gu(e,t,n){var r=e.pingCache;if(r===null){r=e.pingCache=new Rl;var i=new Set;r.set(t,i)}else i=r.get(t),i===void 0&&(i=new Set,r.set(t,i));i.has(n)||(Hl=!0,i.add(n),e=Ku.bind(null,e,t,n),t.then(e,e))}function Ku(e,t,n){var r=e.pingCache;r!==null&&r.delete(t),e.pingedLanes|=e.suspendedLanes&n,e.warmLanes&=~n,q===e&&(Y&n)===n&&(Wl===4||Wl===3&&(Y&62914560)===Y&&300>Te()-$l?!(K&2)&&Su(e,0):ql|=n,Yl===Y&&(Yl=0)),rd(e)}function qu(e,t){t===0&&(t=Je()),e=ri(e,t),e!==null&&(Xe(e,t),rd(e))}function Ju(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),qu(e,n)}function Yu(e,t){var n=0;switch(e.tag){case 31:case 13:var r=e.stateNode,a=e.memoizedState;a!==null&&(n=a.retryLane);break;case 19:r=e.stateNode;break;case 22:r=e.stateNode._retryCache;break;default:throw Error(i(314))}r!==null&&r.delete(t),qu(e,n)}function Xu(e,t){return xe(e,t)}var Zu=null,Qu=null,$u=!1,ed=!1,td=!1,nd=0;function rd(e){e!==Qu&&e.next===null&&(Qu===null?Zu=Qu=e:Qu=Qu.next=e),ed=!0,$u||($u=!0,ud())}function id(e,t){if(!td&&ed){td=!0;do for(var n=!1,r=Zu;r!==null;){if(!t)if(e!==0){var i=r.pendingLanes;if(i===0)var a=0;else{var o=r.suspendedLanes,s=r.pingedLanes;a=(1<<31-Le(42|e)+1)-1,a&=i&~(o&~s),a=a&201326741?a&201326741|1:a?a|2:0}a!==0&&(n=!0,ld(r,a))}else a=Y,a=Ge(r,r===q?a:0,r.cancelPendingCommit!==null||r.timeoutHandle!==-1),!(a&3)||Ke(r,a)||(n=!0,ld(r,a));r=r.next}while(n);td=!1}}function ad(){od()}function od(){ed=$u=!1;var e=0;nd!==0&&Gd()&&(e=nd);for(var t=Te(),n=null,r=Zu;r!==null;){var i=r.next,a=sd(r,t);a===0?(r.next=null,n===null?Zu=i:n.next=i,i===null&&(Qu=n)):(n=r,(e!==0||a&3)&&(ed=!0)),r=i}iu!==0&&iu!==5||id(e,!1),nd!==0&&(nd=0)}function sd(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,i=e.expirationTimes,a=e.pendingLanes&-62914561;0s)break;var u=c.transferSize,d=c.initiatorType;u&&Id(d)&&(c=c.responseEnd,o+=u*(c`u`?null:document;function xf(e,t,n){var r=bf;if(r&&typeof t==`string`&&t){var i=Rt(t);i=`link[rel="`+e+`"][href="`+i+`"]`,typeof n==`string`&&(i+=`[crossorigin="`+n+`"]`),hf.has(i)||(hf.add(i),e={rel:e,crossOrigin:n,href:t},r.querySelector(i)===null&&(t=r.createElement(`link`),Pd(t,`link`,e),yt(t),r.head.appendChild(t)))}}function Sf(e){_f.D(e),xf(`dns-prefetch`,e,null)}function Cf(e,t){_f.C(e,t),xf(`preconnect`,e,t)}function wf(e,t,n){_f.L(e,t,n);var r=bf;if(r&&e&&t){var i=`link[rel="preload"][as="`+Rt(t)+`"]`;t===`image`&&n&&n.imageSrcSet?(i+=`[imagesrcset="`+Rt(n.imageSrcSet)+`"]`,typeof n.imageSizes==`string`&&(i+=`[imagesizes="`+Rt(n.imageSizes)+`"]`)):i+=`[href="`+Rt(e)+`"]`;var a=i;switch(t){case`style`:a=Af(e);break;case`script`:a=Pf(e)}mf.has(a)||(e=f({rel:`preload`,href:t===`image`&&n&&n.imageSrcSet?void 0:e,as:t},n),mf.set(a,e),r.querySelector(i)!==null||t===`style`&&r.querySelector(jf(a))||t===`script`&&r.querySelector(Ff(a))||(t=r.createElement(`link`),Pd(t,`link`,e),yt(t),r.head.appendChild(t)))}}function Tf(e,t){_f.m(e,t);var n=bf;if(n&&e){var r=t&&typeof t.as==`string`?t.as:`script`,i=`link[rel="modulepreload"][as="`+Rt(r)+`"][href="`+Rt(e)+`"]`,a=i;switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:a=Pf(e)}if(!mf.has(a)&&(e=f({rel:`modulepreload`,href:e},t),mf.set(a,e),n.querySelector(i)===null)){switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:if(n.querySelector(Ff(a)))return}r=n.createElement(`link`),Pd(r,`link`,e),yt(r),n.head.appendChild(r)}}}function Ef(e,t,n){_f.S(e,t,n);var r=bf;if(r&&e){var i=vt(r).hoistableStyles,a=Af(e);t||=`default`;var o=i.get(a);if(!o){var s={loading:0,preload:null};if(o=r.querySelector(jf(a)))s.loading=5;else{e=f({rel:`stylesheet`,href:e,"data-precedence":t},n),(n=mf.get(a))&&Rf(e,n);var c=o=r.createElement(`link`);yt(c),Pd(c,`link`,e),c._p=new Promise(function(e,t){c.onload=e,c.onerror=t}),c.addEventListener(`load`,function(){s.loading|=1}),c.addEventListener(`error`,function(){s.loading|=2}),s.loading|=4,Lf(o,t,r)}o={type:`stylesheet`,instance:o,count:1,state:s},i.set(a,o)}}}function Df(e,t){_f.X(e,t);var n=bf;if(n&&e){var r=vt(n).hoistableScripts,i=Pf(e),a=r.get(i);a||(a=n.querySelector(Ff(i)),a||(e=f({src:e,async:!0},t),(t=mf.get(i))&&zf(e,t),a=n.createElement(`script`),yt(a),Pd(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Of(e,t){_f.M(e,t);var n=bf;if(n&&e){var r=vt(n).hoistableScripts,i=Pf(e),a=r.get(i);a||(a=n.querySelector(Ff(i)),a||(e=f({src:e,async:!0,type:`module`},t),(t=mf.get(i))&&zf(e,t),a=n.createElement(`script`),yt(a),Pd(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function kf(e,t,n,r){var a=(a=ue.current)?gf(a):null;if(!a)throw Error(i(446));switch(e){case`meta`:case`title`:return null;case`style`:return typeof n.precedence==`string`&&typeof n.href==`string`?(t=Af(n.href),n=vt(a).hoistableStyles,r=n.get(t),r||(r={type:`style`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};case`link`:if(n.rel===`stylesheet`&&typeof n.href==`string`&&typeof n.precedence==`string`){e=Af(n.href);var o=vt(a).hoistableStyles,s=o.get(e);if(s||(a=a.ownerDocument||a,s={type:`stylesheet`,instance:null,count:0,state:{loading:0,preload:null}},o.set(e,s),(o=a.querySelector(jf(e)))&&!o._p&&(s.instance=o,s.state.loading=5),mf.has(e)||(n={rel:`preload`,as:`style`,href:n.href,crossOrigin:n.crossOrigin,integrity:n.integrity,media:n.media,hrefLang:n.hrefLang,referrerPolicy:n.referrerPolicy},mf.set(e,n),o||Nf(a,e,n,s.state))),t&&r===null)throw Error(i(528,``));return s}if(t&&r!==null)throw Error(i(529,``));return null;case`script`:return t=n.async,n=n.src,typeof n==`string`&&t&&typeof t!=`function`&&typeof t!=`symbol`?(t=Pf(n),n=vt(a).hoistableScripts,r=n.get(t),r||(r={type:`script`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};default:throw Error(i(444,e))}}function Af(e){return`href="`+Rt(e)+`"`}function jf(e){return`link[rel="stylesheet"][`+e+`]`}function Mf(e){return f({},e,{"data-precedence":e.precedence,precedence:null})}function Nf(e,t,n,r){e.querySelector(`link[rel="preload"][as="style"][`+t+`]`)?r.loading=1:(t=e.createElement(`link`),r.preload=t,t.addEventListener(`load`,function(){return r.loading|=1}),t.addEventListener(`error`,function(){return r.loading|=2}),Pd(t,`link`,n),yt(t),e.head.appendChild(t))}function Pf(e){return`[src="`+Rt(e)+`"]`}function Ff(e){return`script[async]`+e}function If(e,t,n){if(t.count++,t.instance===null)switch(t.type){case`style`:var r=e.querySelector(`style[data-href~="`+Rt(n.href)+`"]`);if(r)return t.instance=r,yt(r),r;var a=f({},n,{"data-href":n.href,"data-precedence":n.precedence,href:null,precedence:null});return r=(e.ownerDocument||e).createElement(`style`),yt(r),Pd(r,`style`,a),Lf(r,n.precedence,e),t.instance=r;case`stylesheet`:a=Af(n.href);var o=e.querySelector(jf(a));if(o)return t.state.loading|=4,t.instance=o,yt(o),o;r=Mf(n),(a=mf.get(a))&&Rf(r,a),o=(e.ownerDocument||e).createElement(`link`),yt(o);var s=o;return s._p=new Promise(function(e,t){s.onload=e,s.onerror=t}),Pd(o,`link`,r),t.state.loading|=4,Lf(o,n.precedence,e),t.instance=o;case`script`:return o=Pf(n.src),(a=e.querySelector(Ff(o)))?(t.instance=a,yt(a),a):(r=n,(a=mf.get(o))&&(r=f({},n),zf(r,a)),e=e.ownerDocument||e,a=e.createElement(`script`),yt(a),Pd(a,`link`,r),e.head.appendChild(a),t.instance=a);case`void`:return null;default:throw Error(i(443,t.type))}else t.type===`stylesheet`&&!(t.state.loading&4)&&(r=t.instance,t.state.loading|=4,Lf(r,n.precedence,e));return t.instance}function Lf(e,t,n){for(var r=n.querySelectorAll(`link[rel="stylesheet"][data-precedence],style[data-precedence]`),i=r.length?r[r.length-1]:null,a=i,o=0;o title`):null)}function Uf(e,t,n){if(n===1||t.itemProp!=null)return!1;switch(e){case`meta`:case`title`:return!0;case`style`:if(typeof t.precedence!=`string`||typeof t.href!=`string`||t.href===``)break;return!0;case`link`:if(typeof t.rel!=`string`||typeof t.href!=`string`||t.href===``||t.onLoad||t.onError)break;switch(t.rel){case`stylesheet`:return e=t.disabled,typeof t.precedence==`string`&&e==null;default:return!0}case`script`:if(t.async&&typeof t.async!=`function`&&typeof t.async!=`symbol`&&!t.onLoad&&!t.onError&&t.src&&typeof t.src==`string`)return!0}return!1}function Wf(e){return!(e.type===`stylesheet`&&!(e.state.loading&3))}function Gf(e,t,n,r){if(n.type===`stylesheet`&&(typeof r.media!=`string`||!1!==matchMedia(r.media).matches)&&!(n.state.loading&4)){if(n.instance===null){var i=Af(r.href),a=t.querySelector(jf(i));if(a){t=a._p,typeof t==`object`&&t&&typeof t.then==`function`&&(e.count++,e=Jf.bind(e),t.then(e,e)),n.state.loading|=4,n.instance=a,yt(a);return}a=t.ownerDocument||t,r=Mf(r),(i=mf.get(i))&&Rf(r,i),a=a.createElement(`link`),yt(a);var o=a;o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),Pd(a,`link`,r),n.instance=a}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(n,t),(t=n.state.preload)&&!(n.state.loading&3)&&(e.count++,n=Jf.bind(e),t.addEventListener(`load`,n),t.addEventListener(`error`,n))}}var Kf=0;function qf(e,t){return e.stylesheets&&e.count===0&&Xf(e,e.stylesheets),0Kf?50:800)+t);return e.unsuspend=n,function(){e.unsuspend=null,clearTimeout(r),clearTimeout(i)}}:null}function Jf(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Xf(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var Yf=null;function Xf(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,Yf=new Map,t.forEach(Zf,e),Yf=null,Jf.call(e))}function Zf(e,t){if(!(t.state.loading&4)){var n=Yf.get(e);if(n)var r=n.get(null);else{n=new Map,Yf.set(e,n);for(var i=e.querySelectorAll(`link[data-precedence],style[data-precedence]`),a=0;a{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=y()})),x=f(),S=l(m(),1),C=b(),w=`modulepreload`,ee=function(e){return`/`+e},te={},T=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}r=o(t.map(t=>{if(t=ee(t,n),t in te)return;te[t]=!0;let r=t.endsWith(`.css`),i=r?`[rel="stylesheet"]`:``;if(n)for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}else if(document.querySelector(`link[href="${t}"]${i}`))return;let o=document.createElement(`link`);if(o.rel=r?`stylesheet`:w,r||(o.as=`script`),o.crossOrigin=``,o.href=t,a&&o.setAttribute(`nonce`,a),document.head.appendChild(o),r)return new Promise((e,n)=>{o.addEventListener(`load`,e),o.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},E=`popstate`;function D(e){return typeof e==`object`&&!!e&&`pathname`in e&&`search`in e&&`hash`in e&&`state`in e&&`key`in e}function ne(e={}){function t(e,t){let n=t.state?.masked,{pathname:r,search:i,hash:a}=n||e.location;return j(``,{pathname:r,search:i,hash:a},t.state&&t.state.usr||null,t.state&&t.state.key||`default`,n?{pathname:e.location.pathname,search:e.location.search,hash:e.location.hash}:void 0)}function n(e,t){return typeof t==`string`?t:M(t)}return oe(t,n,null,e)}function re(e={}){function t(e,t){let{pathname:n=`/`,search:r=``,hash:i=``}=ae(e.location.hash.substring(1));return!n.startsWith(`/`)&&!n.startsWith(`.`)&&(n=`/`+n),j(``,{pathname:n,search:r,hash:i},t.state&&t.state.usr||null,t.state&&t.state.key||`default`)}function n(e,t){let n=e.document.querySelector(`base`),r=``;if(n&&n.getAttribute(`href`)){let t=e.location.href,n=t.indexOf(`#`);r=n===-1?t:t.slice(0,n)}return r+`#`+(typeof t==`string`?t:M(t))}function r(e,t){k(e.pathname.charAt(0)===`/`,`relative pathnames are not supported in hash history.push(${JSON.stringify(t)})`)}return oe(t,n,r,e)}function O(e,t){if(e===!1||e==null)throw Error(t)}function k(e,t){if(!e){typeof console<`u`&&console.warn(t);try{throw Error(t)}catch{}}}function A(){return Math.random().toString(36).substring(2,10)}function ie(e,t){return{usr:e.state,key:e.key,idx:t,masked:e.mask?{pathname:e.pathname,search:e.search,hash:e.hash}:void 0}}function j(e,t,n=null,r,i){return{pathname:typeof e==`string`?e:e.pathname,search:``,hash:``,...typeof t==`string`?ae(t):t,state:n,key:t&&t.key||r||A(),mask:i}}function M({pathname:e=`/`,search:t=``,hash:n=``}){return t&&t!==`?`&&(e+=t.charAt(0)===`?`?t:`?`+t),n&&n!==`#`&&(e+=n.charAt(0)===`#`?n:`#`+n),e}function ae(e){let t={};if(e){let n=e.indexOf(`#`);n>=0&&(t.hash=e.substring(n),e=e.substring(0,n));let r=e.indexOf(`?`);r>=0&&(t.search=e.substring(r),e=e.substring(0,r)),e&&(t.pathname=e)}return t}function oe(e,t,n,r={}){let{window:i=document.defaultView,v5Compat:a=!1}=r,o=i.history,s=`POP`,c=null,l=u();l??(l=0,o.replaceState({...o.state,idx:l},``));function u(){return(o.state||{idx:null}).idx}function d(){s=`POP`;let e=u(),t=e==null?null:e-l;l=e,c&&c({action:s,location:h.location,delta:t})}function f(e,t){s=`PUSH`;let r=D(e)?e:j(h.location,e,t);n&&n(r,e),l=u()+1;let d=ie(r,l),f=h.createHref(r.mask||r);try{o.pushState(d,``,f)}catch(e){if(e instanceof DOMException&&e.name===`DataCloneError`)throw e;i.location.assign(f)}a&&c&&c({action:s,location:h.location,delta:1})}function p(e,t){s=`REPLACE`;let r=D(e)?e:j(h.location,e,t);n&&n(r,e),l=u();let i=ie(r,l),d=h.createHref(r.mask||r);o.replaceState(i,``,d),a&&c&&c({action:s,location:h.location,delta:0})}function m(e){return se(i,e)}let h={get action(){return s},get location(){return e(i,o)},listen(e){if(c)throw Error(`A history only accepts one active listener`);return i.addEventListener(E,d),c=e,()=>{i.removeEventListener(E,d),c=null}},createHref(e){return t(i,e)},createURL:m,encodeLocation(e){let t=m(e);return{pathname:t.pathname,search:t.search,hash:t.hash}},push:f,replace:p,go(e){return o.go(e)}};return h}function se(e,t,n=!1){let r=`http://localhost`;e&&(r=e.location.origin===`null`?e.location.href:e.location.origin),O(r,`No window.location.(origin|href) available to create URL`);let i=typeof t==`string`?t:M(t);return i=i.replace(/ $/,`%20`),!n&&i.startsWith(`//`)&&(i=r+i),new URL(i,r)}function ce(e,t,n=`/`){return N(e,t,n,!1)}function N(e,t,n,r,i){let a=Se((typeof t==`string`?ae(t):t).pathname||`/`,n);if(a==null)return null;let o=i??le(e),s=null,c=xe(a);for(let e=0;s==null&&e{let c={relativePath:s===void 0?e.path||``:s,caseSensitive:e.caseSensitive===!0,childrenIndex:a,route:e};if(c.relativePath.startsWith(`/`)){if(!c.relativePath.startsWith(r)&&o)return;O(c.relativePath.startsWith(r),`Absolute route path "${c.relativePath}" nested under path "${r}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),c.relativePath=c.relativePath.slice(r.length)}let l=je([r,c.relativePath]),u=n.concat(c);e.children&&e.children.length>0&&(O(e.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${l}".`),F(e.children,t,u,l,o)),!(e.path==null&&!e.index)&&t.push({path:l,score:ge(l,e.index),routesMeta:u})};return e.forEach((e,t)=>{if(e.path===``||!e.path?.includes(`?`))a(e,t);else for(let n of ue(e.path))a(e,t,!0,n)}),t}function ue(e){let t=e.split(`/`);if(t.length===0)return[];let[n,...r]=t,i=n.endsWith(`?`),a=n.replace(/\?$/,``);if(r.length===0)return i?[a,``]:[a];let o=ue(r.join(`/`)),s=[];return s.push(...o.map(e=>e===``?a:[a,e].join(`/`))),i&&s.push(...o),s.map(t=>e.startsWith(`/`)&&t===``?`/`:t)}function I(e){e.sort((e,t)=>e.score===t.score?_e(e.routesMeta.map(e=>e.childrenIndex),t.routesMeta.map(e=>e.childrenIndex)):t.score-e.score)}var de=/^:[\w-]+$/,L=3,fe=2,pe=1,R=10,me=-2,he=e=>e===`*`;function ge(e,t){let n=e.split(`/`),r=n.length;return n.some(he)&&(r+=me),t&&(r+=fe),n.filter(e=>!he(e)).reduce((e,t)=>e+(de.test(t)?L:t===``?pe:R),r)}function _e(e,t){return e.length===t.length&&e.slice(0,-1).every((e,n)=>e===t[n])?e[e.length-1]-t[t.length-1]:0}function ve(e,t,n=!1){let{routesMeta:r}=e,i={},a=`/`,o=[];for(let e=0;e{if(t===`*`){let e=s[r]||``;o=a.slice(0,a.length-e.length).replace(/(.)\/+$/,`$1`)}let i=s[r];return n&&!i?e[t]=void 0:e[t]=(i||``).replace(/%2F/g,`/`),e},{}),pathname:a,pathnameBase:o,pattern:e}}function be(e,t=!1,n=!0){k(e===`*`||!e.endsWith(`*`)||e.endsWith(`/*`),`Route path "${e}" will be treated as if it were "${e.replace(/\*$/,`/*`)}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${e.replace(/\*$/,`/*`)}".`);let r=[],i=`^`+e.replace(/\/*\*?$/,``).replace(/^\/*/,`/`).replace(/[\\.*+^${}|()[\]]/g,`\\$&`).replace(/\/:([\w-]+)(\?)?/g,(e,t,n,i,a)=>{if(r.push({paramName:t,isOptional:n!=null}),n){let t=a.charAt(i+e.length);return t&&t!==`/`?`/([^\\/]*)`:`(?:/([^\\/]*))?`}return`/([^\\/]+)`}).replace(/\/([\w-]+)\?(\/|$)/g,`(/$1)?$2`);return e.endsWith(`*`)?(r.push({paramName:`*`}),i+=e===`*`||e===`/*`?`(.*)$`:`(?:\\/(.+)|\\/*)$`):n?i+=`\\/*$`:e!==``&&e!==`/`&&(i+=`(?:(?=\\/|$))`),[new RegExp(i,t?void 0:`i`),r]}function xe(e){try{return e.split(`/`).map(e=>decodeURIComponent(e).replace(/\//g,`%2F`)).join(`/`)}catch(t){return k(!1,`The URL path "${e}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${t}).`),e}}function Se(e,t){if(t===`/`)return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let n=t.endsWith(`/`)?t.length-1:t.length,r=e.charAt(n);return r&&r!==`/`?null:e.slice(n)||`/`}var Ce=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;function we(e,t=`/`){let{pathname:n,search:r=``,hash:i=``}=typeof e==`string`?ae(e):e,a;return n?(n=Ae(n),a=n.startsWith(`/`)?Te(n.substring(1),`/`):Te(n,t)):a=t,{pathname:a,search:Pe(r),hash:Fe(i)}}function Te(e,t){let n=Me(t).split(`/`);return e.split(`/`).forEach(e=>{e===`..`?n.length>1&&n.pop():e!==`.`&&n.push(e)}),n.length>1?n.join(`/`):`/`}function Ee(e,t,n,r){return`Cannot include a '${e}' character in a manually specified \`to.${t}\` field [${JSON.stringify(r)}]. Please separate it out to the \`to.${n}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function De(e){return e.filter((e,t)=>t===0||e.route.path&&e.route.path.length>0)}function Oe(e){let t=De(e);return t.map((e,n)=>n===t.length-1?e.pathname:e.pathnameBase)}function ke(e,t,n,r=!1){let i;typeof e==`string`?i=ae(e):(i={...e},O(!i.pathname||!i.pathname.includes(`?`),Ee(`?`,`pathname`,`search`,i)),O(!i.pathname||!i.pathname.includes(`#`),Ee(`#`,`pathname`,`hash`,i)),O(!i.search||!i.search.includes(`#`),Ee(`#`,`search`,`hash`,i)));let a=e===``||i.pathname===``,o=a?`/`:i.pathname,s;if(o==null)s=n;else{let e=t.length-1;if(!r&&o.startsWith(`..`)){let t=o.split(`/`);for(;t[0]===`..`;)t.shift(),--e;i.pathname=t.join(`/`)}s=e>=0?t[e]:`/`}let c=we(i,s),l=o&&o!==`/`&&o.endsWith(`/`),u=(a||o===`.`)&&n.endsWith(`/`);return!c.pathname.endsWith(`/`)&&(l||u)&&(c.pathname+=`/`),c}var Ae=e=>e.replace(/\/\/+/g,`/`),je=e=>Ae(e.join(`/`)),Me=e=>e.replace(/\/+$/,``),Ne=e=>Me(e).replace(/^\/*/,`/`),Pe=e=>!e||e===`?`?``:e.startsWith(`?`)?e:`?`+e,Fe=e=>!e||e===`#`?``:e.startsWith(`#`)?e:`#`+e,Ie=class{constructor(e,t,n,r=!1){this.status=e,this.statusText=t||``,this.internal=r,n instanceof Error?(this.data=n.toString(),this.error=n):this.data=n}};function Le(e){return e!=null&&typeof e.status==`number`&&typeof e.statusText==`string`&&typeof e.internal==`boolean`&&`data`in e}function Re(e){return je(e.map(e=>e.route.path).filter(Boolean))||`/`}var ze=typeof window<`u`&&window.document!==void 0&&window.document.createElement!==void 0;function Be(e,t){let n=e;if(typeof n!=`string`||!Ce.test(n))return{absoluteURL:void 0,isExternal:!1,to:n};let r=n,i=!1;if(ze)try{let e=new URL(window.location.href),r=n.startsWith(`//`)?new URL(e.protocol+n):new URL(n),a=Se(r.pathname,t);r.origin===e.origin&&a!=null?n=a+r.search+r.hash:i=!0}catch{k(!1,` contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}return{absoluteURL:r,isExternal:i,to:n}}Object.getOwnPropertyNames(Object.prototype).sort().join(`\0`);var Ve=[`POST`,`PUT`,`PATCH`,`DELETE`];new Set(Ve);var He=[`GET`,...Ve];new Set(He);var Ue=S.createContext(null);Ue.displayName=`DataRouter`;var We=S.createContext(null);We.displayName=`DataRouterState`;var Ge=S.createContext(!1);function Ke(){return S.useContext(Ge)}var qe=S.createContext({isTransitioning:!1});qe.displayName=`ViewTransition`;var Je=S.createContext(new Map);Je.displayName=`Fetchers`;var Ye=S.createContext(null);Ye.displayName=`Await`;var Xe=S.createContext(null);Xe.displayName=`Navigation`;var Ze=S.createContext(null);Ze.displayName=`Location`;var Qe=S.createContext({outlet:null,matches:[],isDataRoute:!1});Qe.displayName=`Route`;var $e=S.createContext(null);$e.displayName=`RouteError`;var et=`REACT_ROUTER_ERROR`,tt=`REDIRECT`,nt=`ROUTE_ERROR_RESPONSE`;function rt(e){if(e.startsWith(`${et}:${tt}:{`))try{let t=JSON.parse(e.slice(28));if(typeof t==`object`&&t&&typeof t.status==`number`&&typeof t.statusText==`string`&&typeof t.location==`string`&&typeof t.reloadDocument==`boolean`&&typeof t.replace==`boolean`)return t}catch{}}function it(e){if(e.startsWith(`${et}:${nt}:{`))try{let t=JSON.parse(e.slice(40));if(typeof t==`object`&&t&&typeof t.status==`number`&&typeof t.statusText==`string`)return new Ie(t.status,t.statusText,t.data)}catch{}}function at(e,{relative:t}={}){O(ot(),`useHref() may be used only in the context of a component.`);let{basename:n,navigator:r}=S.useContext(Xe),{hash:i,pathname:a,search:o}=pt(e,{relative:t}),s=a;return n!==`/`&&(s=a===`/`?n:je([n,a])),r.createHref({pathname:s,search:o,hash:i})}function ot(){return S.useContext(Ze)!=null}function st(){return O(ot(),`useLocation() may be used only in the context of a component.`),S.useContext(Ze).location}var ct=`You should call navigate() in a React.useEffect(), not when your component is first rendered.`;function lt(e){S.useContext(Xe).static||S.useLayoutEffect(e)}function ut(){let{isDataRoute:e}=S.useContext(Qe);return e?Mt():dt()}function dt(){O(ot(),`useNavigate() may be used only in the context of a component.`);let e=S.useContext(Ue),{basename:t,navigator:n}=S.useContext(Xe),{matches:r}=S.useContext(Qe),{pathname:i}=st(),a=JSON.stringify(Oe(r)),o=S.useRef(!1);return lt(()=>{o.current=!0}),S.useCallback((r,s={})=>{if(k(o.current,ct),!o.current)return;if(typeof r==`number`){n.go(r);return}let c=ke(r,JSON.parse(a),i,s.relative===`path`);e==null&&t!==`/`&&(c.pathname=c.pathname===`/`?t:je([t,c.pathname])),(s.replace?n.replace:n.push)(c,s.state,s)},[t,n,a,i,e])}S.createContext(null);function ft(){let{matches:e}=S.useContext(Qe);return e[e.length-1]?.params??{}}function pt(e,{relative:t}={}){let{matches:n}=S.useContext(Qe),{pathname:r}=st(),i=JSON.stringify(Oe(n));return S.useMemo(()=>ke(e,JSON.parse(i),r,t===`path`),[e,i,r,t])}function mt(e,t){return ht(e,t)}function ht(e,t,n){O(ot(),`useRoutes() may be used only in the context of a component.`);let{navigator:r}=S.useContext(Xe),{matches:i}=S.useContext(Qe),a=i[i.length-1],o=a?a.params:{},s=a?a.pathname:`/`,c=a?a.pathnameBase:`/`,l=a&&a.route;{let e=l&&l.path||``;Pt(s,!l||e.endsWith(`*`)||e.endsWith(`*?`),`You rendered descendant (or called \`useRoutes()\`) at "${s}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. + +Please change the parent to .`)}let u=st(),d;if(t){let e=typeof t==`string`?ae(t):t;O(c===`/`||e.pathname?.startsWith(c),`When overriding the location using \`\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${c}" but pathname "${e.pathname}" was given in the \`location\` prop.`),d=e}else d=u;let f=d.pathname||`/`,p=f;if(c!==`/`){let e=c.replace(/^\//,``).split(`/`);p=`/`+f.replace(/^\//,``).split(`/`).slice(e.length).join(`/`)}let m=n&&n.state.matches.length?n.state.matches.map(e=>Object.assign(e,{route:n.manifest[e.route.id]||e.route})):ce(e,{pathname:p});k(l||m!=null,`No routes matched location "${d.pathname}${d.search}${d.hash}" `),k(m==null||m[m.length-1].route.element!==void 0||m[m.length-1].route.Component!==void 0||m[m.length-1].route.lazy!==void 0,`Matched leaf route at location "${d.pathname}${d.search}${d.hash}" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.`);let h=St(m&&m.map(e=>Object.assign({},e,{params:Object.assign({},o,e.params),pathname:je([c,r.encodeLocation?r.encodeLocation(e.pathname.replace(/%/g,`%25`).replace(/\?/g,`%3F`).replace(/#/g,`%23`)).pathname:e.pathname]),pathnameBase:e.pathnameBase===`/`?c:je([c,r.encodeLocation?r.encodeLocation(e.pathnameBase.replace(/%/g,`%25`).replace(/\?/g,`%3F`).replace(/#/g,`%23`)).pathname:e.pathnameBase])})),i,n);return t&&h?S.createElement(Ze.Provider,{value:{location:{pathname:`/`,search:``,hash:``,state:null,key:`default`,mask:void 0,...d},navigationType:`POP`}},h):h}function gt(){let e=jt(),t=Le(e)?`${e.status} ${e.statusText}`:e instanceof Error?e.message:JSON.stringify(e),n=e instanceof Error?e.stack:null,r=`rgba(200,200,200, 0.5)`,i={padding:`0.5rem`,backgroundColor:r},a={padding:`2px 4px`,backgroundColor:r},o=null;return console.error(`Error handled by React Router default ErrorBoundary:`,e),o=S.createElement(S.Fragment,null,S.createElement(`p`,null,`💿 Hey developer 👋`),S.createElement(`p`,null,`You can provide a way better UX than this when your app throws errors by providing your own `,S.createElement(`code`,{style:a},`ErrorBoundary`),` or`,` `,S.createElement(`code`,{style:a},`errorElement`),` prop on your route.`)),S.createElement(S.Fragment,null,S.createElement(`h2`,null,`Unexpected Application Error!`),S.createElement(`h3`,{style:{fontStyle:`italic`}},t),n?S.createElement(`pre`,{style:i},n):null,o)}var _t=S.createElement(gt,null),vt=class extends S.Component{constructor(e){super(e),this.state={location:e.location,revalidation:e.revalidation,error:e.error}}static getDerivedStateFromError(e){return{error:e}}static getDerivedStateFromProps(e,t){return t.location!==e.location||t.revalidation!==`idle`&&e.revalidation===`idle`?{error:e.error,location:e.location,revalidation:e.revalidation}:{error:e.error===void 0?t.error:e.error,location:t.location,revalidation:e.revalidation||t.revalidation}}componentDidCatch(e,t){this.props.onError?this.props.onError(e,t):console.error(`React Router caught the following error during render`,e)}render(){let e=this.state.error;if(this.context&&typeof e==`object`&&e&&`digest`in e&&typeof e.digest==`string`){let t=it(e.digest);t&&(e=t)}let t=e===void 0?this.props.children:S.createElement(Qe.Provider,{value:this.props.routeContext},S.createElement($e.Provider,{value:e,children:this.props.component}));return this.context?S.createElement(bt,{error:e},t):t}};vt.contextType=Ge;var yt=new WeakMap;function bt({children:e,error:t}){let{basename:n}=S.useContext(Xe);if(typeof t==`object`&&t&&`digest`in t&&typeof t.digest==`string`){let e=rt(t.digest);if(e){let r=yt.get(t);if(r)throw r;let i=Be(e.location,n);if(ze&&!yt.get(t))if(i.isExternal||e.reloadDocument)window.location.href=i.absoluteURL||i.to;else{let n=Promise.resolve().then(()=>window.__reactRouterDataRouter.navigate(i.to,{replace:e.replace}));throw yt.set(t,n),n}return S.createElement(`meta`,{httpEquiv:`refresh`,content:`0;url=${i.absoluteURL||i.to}`})}}return e}function xt({routeContext:e,match:t,children:n}){let r=S.useContext(Ue);return r&&r.static&&r.staticContext&&(t.route.errorElement||t.route.ErrorBoundary)&&(r.staticContext._deepestRenderedBoundaryId=t.route.id),S.createElement(Qe.Provider,{value:e},n)}function St(e,t=[],n){let r=n?.state;if(e==null){if(!r)return null;if(r.errors)e=r.matches;else if(t.length===0&&!r.initialized&&r.matches.length>0)e=r.matches;else return null}let i=e,a=r?.errors;if(a!=null){let e=i.findIndex(e=>e.route.id&&a?.[e.route.id]!==void 0);O(e>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(a).join(`,`)}`),i=i.slice(0,Math.min(i.length,e+1))}let o=!1,s=-1;if(n&&r){o=r.renderFallback;for(let e=0;e=0?i.slice(0,s+1):[i[0]];break}}}}let c=n?.onError,l=r&&c?(e,t)=>{c(e,{location:r.location,params:r.matches?.[0]?.params??{},pattern:Re(r.matches),errorInfo:t})}:void 0;return i.reduceRight((e,n,c)=>{let u,d=!1,f=null,p=null;r&&(u=a&&n.route.id?a[n.route.id]:void 0,f=n.route.errorElement||_t,o&&(s<0&&c===0?(Pt(`route-fallback`,!1,"No `HydrateFallback` element provided to render during initial hydration"),d=!0,p=null):s===c&&(d=!0,p=n.route.hydrateFallbackElement||null)));let m=t.concat(i.slice(0,c+1)),h=()=>{let t;return t=u?f:d?p:n.route.Component?S.createElement(n.route.Component,null):n.route.element?n.route.element:e,S.createElement(xt,{match:n,routeContext:{outlet:e,matches:m,isDataRoute:r!=null},children:t})};return r&&(n.route.ErrorBoundary||n.route.errorElement||c===0)?S.createElement(vt,{location:r.location,revalidation:r.revalidation,component:f,error:u,children:h(),routeContext:{outlet:null,matches:m,isDataRoute:!0},onError:l}):h()},null)}function Ct(e){return`${e} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function wt(e){let t=S.useContext(Ue);return O(t,Ct(e)),t}function Tt(e){let t=S.useContext(We);return O(t,Ct(e)),t}function Et(e){let t=S.useContext(Qe);return O(t,Ct(e)),t}function Dt(e){let t=Et(e),n=t.matches[t.matches.length-1];return O(n.route.id,`${e} can only be used on routes that contain a unique "id"`),n.route.id}function Ot(){return Dt(`useRouteId`)}function kt(){let e=Tt(`useNavigation`);return S.useMemo(()=>{let{matches:t,historyAction:n,...r}=e.navigation;return r},[e.navigation])}function At(){let{matches:e,loaderData:t}=Tt(`useMatches`);return S.useMemo(()=>e.map(e=>P(e,t)),[e,t])}function jt(){let e=S.useContext($e),t=Tt(`useRouteError`),n=Dt(`useRouteError`);return e===void 0?t.errors?.[n]:e}function Mt(){let{router:e}=wt(`useNavigate`),t=Dt(`useNavigate`),n=S.useRef(!1);return lt(()=>{n.current=!0}),S.useCallback(async(r,i={})=>{k(n.current,ct),n.current&&(typeof r==`number`?await e.navigate(r):await e.navigate(r,{fromRouteId:t,...i}))},[e,t])}var Nt={};function Pt(e,t,n){!t&&!Nt[e]&&(Nt[e]=!0,k(!1,n))}S.memo(Ft);function Ft({routes:e,manifest:t,future:n,state:r,isStatic:i,onError:a}){return ht(e,void 0,{manifest:t,state:r,isStatic:i,onError:a,future:n})}function It(e){O(!1,`A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .`)}function Lt({basename:e=`/`,children:t=null,location:n,navigationType:r=`POP`,navigator:i,static:a=!1,useTransitions:o}){O(!ot(),`You cannot render a inside another . You should never have more than one in your app.`);let s=e.replace(/^\/*/,`/`),c=S.useMemo(()=>({basename:s,navigator:i,static:a,useTransitions:o,future:{}}),[s,i,a,o]);typeof n==`string`&&(n=ae(n));let{pathname:l=`/`,search:u=``,hash:d=``,state:f=null,key:p=`default`,mask:m}=n,h=S.useMemo(()=>{let e=Se(l,s);return e==null?null:{location:{pathname:e,search:u,hash:d,state:f,key:p,mask:m},navigationType:r}},[s,l,u,d,f,p,r,m]);return k(h!=null,` is not able to match the URL "${l}${u}${d}" because it does not start with the basename, so the won't render anything.`),h==null?null:S.createElement(Xe.Provider,{value:c},S.createElement(Ze.Provider,{children:t,value:h}))}function Rt({children:e,location:t}){return mt(zt(e),t)}S.Component;function zt(e,t=[]){let n=[];return S.Children.forEach(e,(e,r)=>{if(!S.isValidElement(e))return;let i=[...t,r];if(e.type===S.Fragment){n.push.apply(n,zt(e.props.children,i));return}O(e.type===It,`[${typeof e.type==`string`?e.type:e.type.name}] is not a component. All component children of must be a or `),O(!e.props.index||!e.props.children,`An index route cannot have child routes.`);let a={id:e.props.id||i.join(`-`),caseSensitive:e.props.caseSensitive,element:e.props.element,Component:e.props.Component,index:e.props.index,path:e.props.path,middleware:e.props.middleware,loader:e.props.loader,action:e.props.action,hydrateFallbackElement:e.props.hydrateFallbackElement,HydrateFallback:e.props.HydrateFallback,errorElement:e.props.errorElement,ErrorBoundary:e.props.ErrorBoundary,hasErrorBoundary:e.props.hasErrorBoundary===!0||e.props.ErrorBoundary!=null||e.props.errorElement!=null,shouldRevalidate:e.props.shouldRevalidate,handle:e.props.handle,lazy:e.props.lazy};e.props.children&&(a.children=zt(e.props.children,i)),n.push(a)}),n}var Bt=`get`,Vt=`application/x-www-form-urlencoded`;function Ht(e){return typeof HTMLElement<`u`&&e instanceof HTMLElement}function Ut(e){return Ht(e)&&e.tagName.toLowerCase()===`button`}function Wt(e){return Ht(e)&&e.tagName.toLowerCase()===`form`}function Gt(e){return Ht(e)&&e.tagName.toLowerCase()===`input`}function Kt(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}function qt(e,t){return e.button===0&&(!t||t===`_self`)&&!Kt(e)}function Jt(e=``){return new URLSearchParams(typeof e==`string`||Array.isArray(e)||e instanceof URLSearchParams?e:Object.keys(e).reduce((t,n)=>{let r=e[n];return t.concat(Array.isArray(r)?r.map(e=>[n,e]):[[n,r]])},[]))}function Yt(e,t){let n=Jt(e);return t&&t.forEach((e,r)=>{n.has(r)||t.getAll(r).forEach(e=>{n.append(r,e)})}),n}var Xt=null;function Zt(){if(Xt===null)try{new FormData(document.createElement(`form`),0),Xt=!1}catch{Xt=!0}return Xt}var Qt=new Set([`application/x-www-form-urlencoded`,`multipart/form-data`,`text/plain`]);function $t(e){return e!=null&&!Qt.has(e)?(k(!1,`"${e}" is not a valid \`encType\` for \`
\`/\`\` and will default to "${Vt}"`),null):e}function en(e,t){let n,r,i,a,o;if(Wt(e)){let o=e.getAttribute(`action`);r=o?Se(o,t):null,n=e.getAttribute(`method`)||Bt,i=$t(e.getAttribute(`enctype`))||Vt,a=new FormData(e)}else if(Ut(e)||Gt(e)&&(e.type===`submit`||e.type===`image`)){let o=e.form;if(o==null)throw Error(`Cannot submit a + \`; + document.body.appendChild(banner); + + let hoveredEl = null; + let origOutline = ''; + + const onMouseOver = (e) => { + if (banner.contains(e.target)) return; + if (hoveredEl) { + hoveredEl.style.outline = origOutline; + } + hoveredEl = e.target; + origOutline = hoveredEl.style.outline; + hoveredEl.style.outline = '3px solid #f97316'; + hoveredEl.style.cursor = 'pointer'; + }; + + const onMouseOut = (e) => { + if (hoveredEl === e.target) { + hoveredEl.style.outline = origOutline; + hoveredEl = null; + } + }; + + const onClick = (e) => { + if (banner.contains(e.target)) return; + e.preventDefault(); + e.stopPropagation(); + + const el = e.target; + + const getSelector = (target) => { + if (target.id) return '#' + target.id; + let parts = []; + let curr = target; + while (curr && curr.nodeType === Node.ELEMENT_NODE) { + let sel = curr.nodeName.toLowerCase(); + if (curr.className) { + const cls = Array.from(curr.classList).filter(c => !c.includes('hover') && !c.includes('active')).join('.'); + if (cls) sel += '.' + cls; + } + parts.unshift(sel); + curr = curr.parentNode; + if (parts.length >= 3) break; + } + return parts.join(' > '); + }; + + const selector = getSelector(el); + const text = el.innerText ? el.innerText.trim() : ''; + + localStorage.setItem('__tienhiep_custom_next_selector', selector); + if (text && text.length < 30) { + localStorage.setItem('__tienhiep_custom_next_text', text); + } + + banner.style.background = 'linear-gradient(135deg,#10b981,#059669)'; + banner.innerHTML = '🎉 Đã học thành công! Từ giờ nút này sẽ được dùng để chuyển chương.'; + + cleanup(); + + setTimeout(() => { + banner.remove(); + }, 2500); + }; + + const cleanup = () => { + document.removeEventListener('mouseover', onMouseOver, true); + document.removeEventListener('mouseout', onMouseOut, true); + document.removeEventListener('click', onClick, true); + if (hoveredEl) { + hoveredEl.style.outline = origOutline; + } + }; + + document.addEventListener('mouseover', onMouseOver, true); + document.addEventListener('mouseout', onMouseOut, true); + document.addEventListener('click', onClick, true); + + document.getElementById('__cancel_teach_next').onclick = () => { + cleanup(); + banner.remove(); + }; + } + }; + + // ========================================================= + // 2. TRANSLATOR ENGINE + // ========================================================= + window.__transPromises = {}; + window.__transId = 0; + window.__receiveTranslations = (id, results) => { + if (window.__transPromises[id]) { + window.__transPromises[id](results); + delete window.__transPromises[id]; + } + }; + + async function translateNodes(nodes) { + const texts = nodes.map(n => n.nodeValue); + try { + const id = window.__transId++; + const translations = await new Promise((resolve) => { + window.__transPromises[id] = resolve; + console.log('[TRANSLATE_REQ]' + JSON.stringify({ id, texts })); + setTimeout(() => { + if (window.__transPromises[id]) { + window.__transPromises[id]([]); + delete window.__transPromises[id]; + } + }, 10000); + }); + + if (translations && translations.length === nodes.length) { + if (window.__autoTranslateObserver) window.__autoTranslateObserver.disconnect(); + translations.forEach((trans, idx) => { + const node = nodes[idx]; + if (node && trans) { + if (!${JSON.parse(a).typewriterEffect===!0} || trans.length < 5) { + node.nodeValue = trans; + return; + } + const words = trans.split(/(?<=\\s+)/); + node.nodeValue = ""; + let i = 0; + function typeWriter() { + if (i < words.length) { + node.nodeValue += words[i]; i++; + requestAnimationFrame(() => setTimeout(typeWriter, 5)); + } + } + typeWriter(); + } + }); + if (window.__autoTranslateObserver) { + window.__autoTranslateObserver.observe(document.body, { childList: true, subtree: true, characterData: true }); + } + } + return translations; + } catch(e) { console.error('Translate API Error:', e); return []; } + } + + const queue = []; + let timeout = null; + let isProcessing = false; + + const processQueue = () => { + if (queue.length > 0 && !isProcessing && window.__autoTranslateEnabled) { + isProcessing = true; + const batch = queue.splice(0, 100); + translateNodes(batch).finally(() => { + isProcessing = false; + if (queue.length > 0) setTimeout(processQueue, 100); + else { + clearTimeout(window.__translateCompleteTimeout); + window.__translateCompleteTimeout = setTimeout(() => { + console.log('[Translation Complete]'); + }, 800); + } + }); + } + }; + + const collectNodes = (root) => { + if (!window.__autoTranslateEnabled) return; + const nodes = []; const stack = [root]; + while (stack.length > 0) { + const node = stack.pop(); if (!node) continue; + if (node.nodeType === 3) { + const val = node.__original_chinese__ || node.nodeValue; + if (val && /[\\u4e00-\\u9fa5]/.test(val)) { + const tag = node.parentNode?.nodeName; + if (tag !== 'SCRIPT' && tag !== 'STYLE' && tag !== 'NOSCRIPT') { + if (!node.__original_chinese__) node.__original_chinese__ = val; + nodes.push(node); + } + } + } else { + if (node.shadowRoot) stack.push(node.shadowRoot); + let child = node.lastChild; while (child) { stack.push(child); child = child.previousSibling; } + } + } + if (nodes.length > 0) { + queue.push(...nodes); + if (!timeout) timeout = setTimeout(() => { timeout = null; processQueue(); }, 200); + } + }; + + window.__autoTranslateObserver = new MutationObserver((mutations) => { + if (!window.__autoTranslateEnabled) return; + mutations.forEach(m => { + if (m.type === 'characterData') { + if (m.target.nodeType === 3) collectNodes(m.target); + } else if (m.type === 'childList') { + m.addedNodes.forEach(node => { + if (node.nodeType === 1 || node.nodeType === 3) collectNodes(node); + }); + } + }); + }); + window.__autoTranslateObserver.observe(document.body, { childList: true, subtree: true, characterData: true }); + + window.toggleAutoTranslate = (enabled) => { + window.__autoTranslateEnabled = enabled; + if (enabled) collectNodes(document.body); + return enabled; + }; + + // Monitor Scroll for AutoNext (Only if TTS is not active) + window.addEventListener('scroll', () => { + if (window.__autoTranslateEnabled && !window.isTtsPlaying) { + window.__TienHiepHelpers.checkAndTriggerAutoNext(false); + } + }); + } + `;r.addEventListener(`dom-ready`,()=>{let n=h.current[t.id]||!1;r.executeJavaScript(o+` + if (${n} && window.toggleAutoTranslate) { + window.toggleAutoTranslate(true); + } + `),g.current[t.id]&&(n?setTimeout(()=>{g.current[t.id]&&e(t.id,r)},4500):setTimeout(()=>{g.current[t.id]&&e(t.id,r)},1200))}),r.__translateScript=o}})},[t]),S.useEffect(()=>{if(ls)return;let e=async e=>{let{type:t,payload:r,tabId:i,url:a,text:s,title:c}=e.data||{};if(!t)return;let l=i||_.current;if(l)if(t===`IFRAME_READY`){let e=document.getElementById(`global-wv-`+l);if(e&&e.contentWindow){let t=localStorage.getItem(`translationSettings`)||`{}`,n=` + if (!window.__translatorInitialized) { + window.__translatorInitialized = true; + window.__autoTranslateEnabled = false; + window.isTtsPlaying = false; + + window.__TienHiepHelpers = { + extractCleanChapterText: () => { + const SELECTORS = { + "qidian.com": ".read-content, #read-content", + "fanqie.com": ".muye-reader-content-novel", + "truyenfull.vn": "#chapter-c, .chapter-c", + "tangthuvien.vn": ".box-chap, #chapter-content", + "metruyenchu.com.vn": "#chapter-detail", + "hjwzw.com": "#content, .content", + "tw.hjwzw.com": "#content, .content", + "uukanshu.com": "#contentbox", + "69shuba.com": ".txtnav", + "biquge": ".showtxt, #content" + }; + const host = window.location.hostname; + let mainEl = null; + for (const [domain, selector] of Object.entries(SELECTORS)) { + if (host.includes(domain)) { + const els = selector.split(',').map(s => s.trim()); + for (const sel of els) { + mainEl = document.querySelector(sel); + if (mainEl) break; + } + } + if (mainEl) break; + } + if (!mainEl) { + const article = document.querySelector('article'); + if (article) mainEl = article; + } + if (!mainEl) { + const contentDivs = Array.from(document.querySelectorAll('div')).filter(d => { + const id = d.id.toLowerCase(); + const cls = d.className.toLowerCase(); + return id.includes('content') || id.includes('chapter') || id.includes('novel') || + cls.includes('content') || cls.includes('chapter') || cls.includes('novel'); + }); + if (contentDivs.length > 0) { + mainEl = contentDivs.reduce((a, b) => (a.innerText.length > b.innerText.length ? a : b)); + } + } + if (!mainEl) mainEl = document.body; + const clone = mainEl.cloneNode(true); + clone.querySelectorAll('script, style, iframe, button, a, .ads, .advertisement, .comment, .social-share, .footer, .header, [id*="google_ads"]').forEach(el => el.remove()); + let cleanText = clone.innerText || ''; + cleanText = cleanText.replace(/\\\\n+/g, '\\\\n').replace(/\\\\s+/g, ' ').trim(); + return { title: document.title, text: cleanText }; + }, + collectTextNodes: (root) => { + const nodes = []; const stack = [root]; + while (stack.length > 0) { + const node = stack.pop(); if (!node) continue; + if (node.nodeType === 3) { + const val = node.__original_chinese__ || node.nodeValue; + if (val && /[\\\\u4e00-\\\\u9fa5]/.test(val)) { + if (!node.__original_chinese__) node.__original_chinese__ = val; + nodes.push(node); + } + } else { + if (node.shadowRoot) stack.push(node.shadowRoot); + let child = node.lastChild; while (child) { stack.push(child); child = child.previousSibling; } + } + } + return nodes; + }, + checkAndTriggerAutoNext: (force) => { + const text = document.body.innerText; + const hasNextKeywords = text.includes('Chương sau') || text.includes('Next Chapter') || text.includes('下一章') || text.includes('下一页'); + if (!hasNextKeywords && !force) return; + const nextBtn = Array.from(document.querySelectorAll('a, button, span')).find(el => { + const t = el.innerText ? el.innerText.trim() : ''; + return t === 'Chương sau' || t === 'Next Chapter' || t === '下一章' || t === '下一页' || t.includes('Chương tiếp') || t.includes('Tập tiếp'); + }); + if (nextBtn) { + nextBtn.click(); + } else { + const customSelector = localStorage.getItem('__tienhiep_custom_next_selector'); + const customText = localStorage.getItem('__tienhiep_custom_next_text'); + if (customSelector) { + const btn = document.querySelector(customSelector); + if (btn) { btn.click(); return; } + } + if (customText) { + const btn = Array.from(document.querySelectorAll('a, button, span')).find(el => el.innerText && el.innerText.trim() === customText); + if (btn) btn.click(); + } + } + }, + startTeachNextMode: () => { + const banner = document.createElement('div'); + banner.id = '__tienhiep_teach_banner'; + banner.style.position = 'fixed'; + banner.style.bottom = '10px'; + banner.style.left = '50%'; + banner.style.transform = 'translateX(-50%)'; + banner.style.background = 'linear-gradient(135deg, #4f46e5, #3730a3)'; + banner.style.color = '#fff'; + banner.style.padding = '8px 16px'; + banner.style.borderRadius = '20px'; + banner.style.fontSize = '12px'; + banner.style.zIndex = '999999'; + banner.style.boxShadow = '0 4px 12px rgba(0,0,0,0.3)'; + banner.style.display = 'flex'; + banner.style.alignItems = 'center'; + banner.style.gap = '10px'; + banner.innerHTML = '👉 Click chọn nút Chuyển Chương trên trang truyện... '; + document.body.appendChild(banner); + + let hoveredEl = null; let origOutline = ''; + const onMouseOver = (e) => { + e.preventDefault(); e.stopPropagation(); + if (hoveredEl) hoveredEl.style.outline = origOutline; + hoveredEl = e.target; origOutline = hoveredEl.style.outline; + hoveredEl.style.outline = '2px solid #ef4444'; + }; + const onMouseOut = (e) => { + if (hoveredEl === e.target) { + hoveredEl.style.outline = origOutline; hoveredEl = null; + } + }; + const getSelector = (el) => { + if (el.id) return '#' + el.id; + if (el.className) return el.tagName.toLowerCase() + '.' + Array.from(el.classList).join('.'); + return el.tagName.toLowerCase(); + }; + const onClick = (e) => { + e.preventDefault(); e.stopPropagation(); + const el = e.target; + const selector = getSelector(el); + const text = el.innerText ? el.innerText.trim() : ''; + localStorage.setItem('__tienhiep_custom_next_selector', selector); + if (text && text.length < 30) { + localStorage.setItem('__tienhiep_custom_next_text', text); + } + banner.style.background = 'linear-gradient(135deg,#10b981,#059669)'; + banner.innerHTML = '🎉 Đã học thành công! Từ giờ nút này sẽ được dùng để chuyển chương.'; + cleanup(); + setTimeout(() => { banner.remove(); }, 2500); + }; + const cleanup = () => { + document.removeEventListener('mouseover', onMouseOver, true); + document.removeEventListener('mouseout', onMouseOut, true); + document.removeEventListener('click', onClick, true); + if (hoveredEl) hoveredEl.style.outline = origOutline; + }; + document.addEventListener('mouseover', onMouseOver, true); + document.addEventListener('mouseout', onMouseOut, true); + document.addEventListener('click', onClick, true); + document.getElementById('__cancel_teach_next').onclick = () => { + cleanup(); banner.remove(); + }; + } + }; + + window.__transPromises = {}; + window.__transId = 0; + window.__receiveTranslations = (id, results) => { + if (window.__transPromises[id]) { + window.__transPromises[id](results); + delete window.__transPromises[id]; + } + }; + + async function translateNodes(nodes) { + const texts = nodes.map(n => n.nodeValue); + try { + const id = window.__transId++; + const translations = await new Promise((resolve) => { + window.__transPromises[id] = resolve; + console.log('[TRANSLATE_REQ]' + JSON.stringify({ id, texts })); + setTimeout(() => { + if (window.__transPromises[id]) { + window.__transPromises[id]([]); + delete window.__transPromises[id]; + } + }, 10000); + }); + + if (translations && translations.length === nodes.length) { + if (window.__autoTranslateObserver) window.__autoTranslateObserver.disconnect(); + translations.forEach((trans, idx) => { + const node = nodes[idx]; + if (node && trans) { + if (!${JSON.parse(t).typewriterEffect===!0} || trans.length < 5) { + node.nodeValue = trans; + return; + } + const words = trans.split(/(?<=\\\\s+)/); + node.nodeValue = ""; + let i = 0; + function typeWriter() { + if (i < words.length) { + node.nodeValue += words[i]; i++; + requestAnimationFrame(() => setTimeout(typeWriter, 5)); + } + } + typeWriter(); + } + }); + if (window.__autoTranslateObserver) { + window.__autoTranslateObserver.observe(document.body, { childList: true, subtree: true, characterData: true }); + } + } + return translations; + } catch(e) { console.error('Translate API Error:', e); return []; } + } + + const queue = []; + let timeout = null; + let isProcessing = false; + + const processQueue = () => { + if (queue.length > 0 && !isProcessing && window.__autoTranslateEnabled) { + isProcessing = true; + const batch = queue.splice(0, 100); + translateNodes(batch).finally(() => { + isProcessing = false; + if (queue.length > 0) setTimeout(processQueue, 100); + else { + clearTimeout(window.__translateCompleteTimeout); + window.__translateCompleteTimeout = setTimeout(() => { + console.log('[Translation Complete]'); + }, 800); + } + }); + } + }; + + const collectNodes = (root) => { + if (!window.__autoTranslateEnabled) return; + const nodes = []; const stack = [root]; + while (stack.length > 0) { + const node = stack.pop(); if (!node) continue; + if (node.nodeType === 3) { + const val = node.__original_chinese__ || node.nodeValue; + if (val && /[\\\\u4e00-\\\\u9fa5]/.test(val)) { + const tag = node.parentNode?.nodeName; + if (tag !== 'SCRIPT' && tag !== 'STYLE' && tag !== 'NOSCRIPT') { + if (!node.__original_chinese__) node.__original_chinese__ = val; + nodes.push(node); + } + } + } else { + if (node.shadowRoot) stack.push(node.shadowRoot); + let child = node.lastChild; while (child) { stack.push(child); child = child.previousSibling; } + } + } + if (nodes.length > 0) { + queue.push(...nodes); + if (!timeout) timeout = setTimeout(() => { timeout = null; processQueue(); }, 200); + } + }; + + window.__autoTranslateObserver = new MutationObserver((mutations) => { + if (!window.__autoTranslateEnabled) return; + mutations.forEach(m => { + if (m.type === 'characterData') { + if (m.target.nodeType === 3) collectNodes(m.target); + } else if (m.type === 'childList') { + m.addedNodes.forEach(node => { + if (node.nodeType === 1 || node.nodeType === 3) collectNodes(node); + }); + } + }); + }); + window.__autoTranslateObserver.observe(document.body, { childList: true, subtree: true, characterData: true }); + + window.toggleAutoTranslate = (enabled) => { + window.__autoTranslateEnabled = enabled; + if (enabled) collectNodes(document.body); + return enabled; + }; + + window.addEventListener('scroll', () => { + if (window.__autoTranslateEnabled && !window.isTtsPlaying) { + window.__TienHiepHelpers.checkAndTriggerAutoNext(false); + } + }); + } + `;e.contentWindow.postMessage({type:`INJECT_SCRIPT`,script:n},`*`),h.current[l]&&e.contentWindow.postMessage({action:`translate`,enabled:!0},`*`)}}else if(t===`TRANSLATE_REQ`){let{id:e,texts:t}=r;try{let n=localStorage.getItem(`translationSettings`),r=n?JSON.parse(n):{engineType:`browser`,mode:`advanced`,serverUrl:`https://tienhiep.lyvuha.com`},i=r.mode||`advanced`,a=r.engineType===`server`,o=Array(t.length),s=[],c=[];if(t.forEach((e,t)=>{let n=vs(e,i);n?o[t]=n:(s.push(e),c.push(t))}),s.length>0){let e=[],t=!1;if(a)try{let n=r.serverUrl||`https://tienhiep.lyvuha.com`,a=await fetch(`${n.replace(/\/+$/,``)}/translate`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({texts:s,mode:i})});if(a.ok){let n=await a.json();n.translations&&(e=n.translations,t=!0)}}catch(e){console.warn(`[Local Server Translate] Failed, falling back to local JS:`,e)}t||(await ps.loadDictionaries(),e=s.map(e=>ps.translateSentence(e,i))),e.forEach((e,t)=>{let n=c[t];o[n]=e,ys(s[t],i,e)})}let u=document.getElementById(`global-wv-`+l);u&&u.contentWindow&&u.contentWindow.postMessage({action:`INJECT_SCRIPT`,script:`if(window.__receiveTranslations) window.__receiveTranslations(${e}, ${JSON.stringify(o)})`},`*`)}catch(t){console.error(`postMessage Translation Error:`,t);let n=document.getElementById(`global-wv-`+l);n&&n.contentWindow&&n.contentWindow.postMessage({action:`INJECT_SCRIPT`,script:`if(window.__receiveTranslations) window.__receiveTranslations(${e}, [])`},`*`)}}else if(t===`TRANSLATION_COMPLETE`)g.current[l]&&setTimeout(()=>{if(g.current[l]){let e=document.getElementById(`global-wv-`+l);e&&e.contentWindow&&e.contentWindow.postMessage({action:`audio`},`*`)}},300);else if(t===`NAVIGATE_REQ`)n(e=>e.map(e=>e.id===l?{...e,url:a,initialUrl:a,title:bs(a)}:e)),m(a);else if(t===`AUDIO_TEXT_RES`)if(s&&s.length>5){o({tabId:l,title_vietphrase:c,title:c,description:s,isChapter:!0,onBoundary:(e,t)=>{window.dispatchEvent(new CustomEvent(`global-tts-boundary`,{detail:{charIdx:e,sentenceText:t}}))}});let e=document.getElementById(`global-wv-`+l);e&&e.contentWindow&&e.contentWindow.postMessage({action:`SET_TTS_PLAYING`,playing:!0},`*`)}else g.current[l]=!1,alert(`Không đủ chữ để đọc hoặc trang web chưa được dịch xong. Hãy đợi một chút và thử lại.`);else t===`COPY_TEXT_RES`&&s&&(navigator.clipboard.writeText(s),alert(`Đã copy thành công `+s.length+` ký tự!`))};return window.addEventListener(`message`,e),()=>window.removeEventListener(`message`,e)},[t]);let[te,T]=(0,S.useState)({}),E=e=>{f(t=>{let n=t.includes(e)?t.filter(t=>t!==e):[...t,e];return localStorage.setItem(`pinnedTools`,JSON.stringify(n)),n})},D=async(e,t)=>{let n=document.getElementById(`global-wv-`+t);if(n){if(!ls){try{if(e===`translate`){let e=!te[t];h.current[t]=e,n.contentWindow.postMessage({action:`translate`,enabled:e},`*`),T(n=>({...n,[t]:e}))}else if(e===`audio`)g.current[t]=!0,n.contentWindow.postMessage({action:`audio`,tabId:t},`*`);else if(e===`scroll`){let e=JSON.parse(localStorage.getItem(`translationSettings`)||`{}`).scrollSpeed||30;n.contentWindow.postMessage({action:`scroll`,speed:e},`*`)}else e===`next`?n.contentWindow.postMessage({action:`next`},`*`):e===`teach_next`?n.contentWindow.postMessage({action:`teach_next`},`*`):e===`dark_mode`?n.contentWindow.postMessage({action:`dark_mode`},`*`):e===`clean_ads`?n.contentWindow.postMessage({action:`clean_ads`},`*`):e===`force_translate`?n.contentWindow.postMessage({action:`force_translate`},`*`):e===`copy_text`&&n.contentWindow.postMessage({action:`audio`,copyToClipboard:!0},`*`)}catch(e){console.error(`Mobile Tool Command Error:`,e)}return}try{if(e===`translate`){let e=!te[t];h.current[t]=e,await n.executeJavaScript(` + if (!window.__translatorInitialized && \`${n.__translateScript?`true`:`false`}\` === 'true') { + ${n.__translateScript||``} + } + if (window.toggleAutoTranslate) { + window.toggleAutoTranslate(${e}); + } + `),T(n=>({...n,[t]:e}))}else if(e===`audio`){g.current[t]=!0;let e=await n.executeJavaScript(` + (window.__TienHiepHelpers ? window.__TienHiepHelpers.extractCleanChapterText() : { title: document.title, text: document.body.innerText }) + `);e.text&&e.text.length>50?(o({title_vietphrase:e.title,author_hanviet:`Trang Web Nhúng`,description:e.text,isChapter:!0,tabId:t,onBoundary:(e,t)=>{window.dispatchEvent(new CustomEvent(`global-tts-boundary`,{detail:{charIdx:e,sentenceText:t}}))}}),n.executeJavaScript(`window.isTtsPlaying = true;`)):(g.current[t]=!1,alert(`Không đủ chữ để đọc hoặc trang web chưa được dịch xong. Hãy đợi một chút và thử lại.`))}else if(e===`scroll`){let e=JSON.parse(localStorage.getItem(`translationSettings`)||`{}`).scrollSpeed||30;await n.executeJavaScript(` + (() => { + if (window.__scrollInterval) { clearInterval(window.__scrollInterval); window.__scrollInterval = null; return false; } + else { window.__scrollInterval = setInterval(() => window.scrollBy({top: 1, behavior: 'instant'}), ${e}); return true; } + })() + `)}else if(e===`next`)await n.executeJavaScript(`if (window.__TienHiepHelpers) window.__TienHiepHelpers.checkAndTriggerAutoNext(true);`);else if(e===`teach_next`)await n.executeJavaScript(`if (window.__TienHiepHelpers) window.__TienHiepHelpers.startTeachNextMode();`);else if(e===`dark_mode`)await n.executeJavaScript(` + if (document.documentElement.style.filter.includes('invert(1)')) { + document.documentElement.style.filter = ''; + document.documentElement.style.backgroundColor = ''; + } else { + document.documentElement.style.filter = 'invert(1) hue-rotate(180deg) brightness(0.9) contrast(1.1)'; + document.documentElement.style.backgroundColor = '#111'; + } + `);else if(e===`clean_ads`)JSON.parse(localStorage.getItem(`translationSettings`)||`{}`).continuousClean===!1?await n.executeJavaScript(` + const ads = document.querySelectorAll('iframe, .ad, .ads, [id*="ad"], [class*="ad"], .banner, .popup, ins'); + ads.forEach(ad => ad.remove()); + alert('Đã dọn dẹp 1 lần ' + ads.length + ' quảng cáo!'); + `):await n.executeJavaScript(` + if (window.__adObserver) { window.__adObserver.disconnect(); window.__adObserver = null; alert('Đã TẮT Lọc QC Liên Tục'); } + else { + window.__adObserver = new MutationObserver(() => { + document.querySelectorAll('iframe, .ad, .ads, [id*="ad"], [class*="ad"], .banner, .popup, ins').forEach(ad => ad.remove()); + }); + window.__adObserver.observe(document.body, { childList: true, subtree: true }); + alert('Đã BẬT Auto-Lọc QC (Chặn ngầm liên tục)'); + } + `);else if(e===`force_translate`)await n.executeJavaScript(` + if (window.__autoTranslateObserver) { + const allNodes = window.__TienHiepHelpers ? window.__TienHiepHelpers.collectTextNodes(document.body) : []; + if(allNodes.length > 0) window.__translateQueue = allNodes; + if(window.__processTranslationQueue) window.__processTranslationQueue(); + } + `);else if(e===`copy_text`){let e=await n.executeJavaScript(`(window.__TienHiepHelpers ? window.__TienHiepHelpers.extractCleanChapterText().text : document.body.innerText)`);e&&(navigator.clipboard.writeText(e),alert(`Đã copy thành công `+e.length+` ký tự!`))}}catch(e){alert(`Lỗi: `+e.message)}}},ne=(e,t)=>{let n=document.getElementById(`global-wv-`+e);if(!n)return;if(!ls){n.contentWindow.postMessage({action:`highlight`,sentenceText:t},`*`);return}let r=t.replace(/\\/g,`\\\\`).replace(/'/g,`\\'`).replace(/\n/g,`\\n`).replace(/\r/g,`\\r`);n.executeJavaScript(` + (() => { + const targetText = '${r}'.trim(); + if (!targetText) return; + + function findTextNode(root, text) { + const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false); + let node; + while (node = walker.nextNode()) { + const val = node.nodeValue || ''; + if (val.includes(text)) { + return { node, startIdx: val.indexOf(text) }; + } + } + if (text.length > 15) { + const prefix = text.substring(0, Math.floor(text.length * 0.65)); + const walker2 = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false); + while (node = walker2.nextNode()) { + const val = node.nodeValue || ''; + if (val.includes(prefix)) { + return { node, startIdx: val.indexOf(prefix) }; + } + } + } + return null; + } + + let attempts = 0; + function tryHighlight() { + const oldHighlight = document.getElementById('tienhiep-active-highlight'); + const result = findTextNode(document.body, targetText); + + if (result) { + if (oldHighlight) { + const parent = oldHighlight.parentNode; + if (parent) { + const textNode = document.createTextNode(oldHighlight.textContent); + parent.replaceChild(textNode, oldHighlight); + parent.normalize(); + } + } + + const { node, startIdx } = result; + const parent = node.parentNode; + if (parent && parent.nodeName !== 'SCRIPT' && parent.nodeName !== 'STYLE') { + const textVal = node.nodeValue; + const matchLen = Math.min(targetText.length, textVal.length - startIdx); + + const beforeText = textVal.substring(0, startIdx); + const matchedText = textVal.substring(startIdx, startIdx + matchLen); + const afterText = textVal.substring(startIdx + matchLen); + + const fragment = document.createDocumentFragment(); + if (beforeText) fragment.appendChild(document.createTextNode(beforeText)); + + const span = document.createElement('span'); + span.id = 'tienhiep-active-highlight'; + span.style.backgroundColor = 'rgba(139, 92, 246, 0.25)'; + span.style.color = '#c084fc'; + span.style.borderBottom = '2px solid #a855f7'; + span.style.padding = '1px 3px'; + span.style.borderRadius = '3px'; + span.style.transition = 'all 0.3s ease'; + span.textContent = matchedText; + fragment.appendChild(span); + + if (afterText) fragment.appendChild(document.createTextNode(afterText)); + + parent.replaceChild(fragment, node); + span.scrollIntoView({ behavior: 'smooth', block: 'center' }); + } + } else if (attempts < 6) { + attempts++; + setTimeout(tryHighlight, 600); + } + } + + tryHighlight(); + })() + `).catch(e=>{})};(0,S.useEffect)(()=>{let e=e=>{e.detail&&e.detail.sentenceText&&a?.tabId&&ne(a.tabId,e.detail.sentenceText)};return window.addEventListener(`global-tts-boundary`,e),()=>window.removeEventListener(`global-tts-boundary`,e)},[a?.tabId]),(0,S.useEffect)(()=>{if(!a||!a.tabId)return;let e=a.tabId,t=setInterval(async()=>{let t=ls?document.getElementById(`global-wv-`+e):null;if(!(!t||!g.current[e]))try{let n=await t.executeJavaScript(` + (window.__TienHiepHelpers ? window.__TienHiepHelpers.extractCleanChapterText() : { title: document.title, text: document.body.innerText }) + `);n.text&&n.text.length>50&&o(t=>t&&t.tabId===e&&t.description!==n.text?{...t,title_vietphrase:n.title,description:n.text}:t)}catch(e){console.error(`Dynamic Text Sync Error:`,e)}},2e3);return()=>clearInterval(t)},[a?.tabId]);let re=()=>{if(a?.playType===`local`){let e=a.book,t=a.chapterIdx+1;e&&e.chapters&&t{if(a?.playType===`local`){let e=a.book,t=(a.chapterIdx||0)-1;e&&e.chapters&&t>=0&&(window.dispatchEvent(new CustomEvent(`global-tts-chapter-changed`,{detail:{bookId:e.id,chapterIdx:t}})),o({...a,chapterIdx:t,title_vietphrase:e.chapters[t]?.title||``,title:e.chapters[t]?.title||``,description:e.chapters[t]?.content||``,startSentenceIdx:0}))}else if(a?.tabId){let e=ls?document.getElementById(`global-wv-`+a.tabId):null;e?.canGoBack()&&e.goBack()}},k=e=>{if(c(!1),typeof window<`u`){let t=window.Capacitor&&window.Capacitor.isNativePlatform&&window.Capacitor.isNativePlatform();ls||t?window.location.hash=`#`+e:(window.history.pushState(null,``,e),window.dispatchEvent(new PopStateEvent(`popstate`)))}},A=()=>{if(ls){let e=document.getElementById(`global-wv-`+r);e?.canGoBack()&&e.goBack()}else{let e=document.getElementById(`global-wv-`+r);if(e?.contentWindow)try{e.contentWindow.history.back()}catch{console.warn(`Cross-origin restriction: cannot access iframe history.back().`)}}},ie=()=>{if(ls){let e=document.getElementById(`global-wv-`+r);e?.canGoForward()&&e.goForward()}else{let e=document.getElementById(`global-wv-`+r);if(e?.contentWindow)try{e.contentWindow.history.forward()}catch{console.warn(`Cross-origin restriction: cannot access iframe history.forward().`)}}},j=()=>{if(ls){let e=document.getElementById(`global-wv-`+r);e?.reload&&e.reload()}else{let e=document.getElementById(`global-wv-`+r);e&&(e.src=e.src)}};return(0,x.jsxs)(ms.Provider,{value:{openInBrowser:b,tabs:t,activeTabId:r,closeTab:C,closeAll:w,isVisible:s,setIsVisible:c,activeAudioObj:a,setActiveAudioObj:o},children:[e,t.length>0&&(0,x.jsxs)(`div`,{className:`fixed left-0 right-0 bottom-0 z-[9999] bg-[#0b0b14] flex-col animate-fade-in shadow-2xl border-x border-[#1e1e24] ${s?`flex`:`hidden`}`,style:{top:ls&&document.querySelector(`header`)?`56px`:`0px`},children:[ls?(0,x.jsxs)(`div`,{className:`flex items-center gap-1 md:gap-2 px-1 md:px-2 py-1.5 md:py-2 bg-gradient-to-r from-[#110e26] via-[#1c183a] to-[#110e26] border-b border-indigo-500/20 shadow-lg relative z-20`,children:[(0,x.jsxs)(`div`,{className:`flex items-center gap-1 shrink-0 pl-1 pr-1.5 md:pr-2 border-r border-indigo-500/30`,children:[(0,x.jsx)(`button`,{onClick:A,className:`p-1.5 hover:bg-white/10 rounded-full transition-colors`,children:(0,x.jsx)(Po,{className:`w-4 h-4 text-slate-300`})}),(0,x.jsx)(`button`,{onClick:ie,className:`p-1.5 hover:bg-white/10 rounded-full transition-colors`,children:(0,x.jsx)(Fo,{className:`w-4 h-4 text-slate-300`})}),(0,x.jsx)(`button`,{onClick:j,className:`p-1.5 hover:bg-white/10 rounded-full transition-colors`,children:(0,x.jsx)(Zo,{className:`w-3.5 h-3.5 text-slate-300`})})]}),(0,x.jsx)(`div`,{className:`flex-1 flex items-center gap-1.5 md:gap-2 overflow-x-auto px-1 no-scrollbar scroll-smooth`,children:t.map(e=>(0,x.jsxs)(`div`,{onClick:()=>i(e.id),className:`group relative flex items-center gap-2 px-3 py-1.5 min-w-[120px] max-w-[200px] rounded-full cursor-pointer transition-all duration-300 border ${r===e.id?`bg-indigo-600/30 text-indigo-50 border-indigo-400/50 shadow-[0_0_15px_rgba(99,102,241,0.25)]`:`bg-[#00000040] text-slate-400 hover:bg-[#ffffff10] hover:text-slate-200 border-transparent`}`,children:[(0,x.jsx)(`div`,{className:`w-1.5 h-1.5 rounded-full shrink-0 ${r===e.id?`bg-indigo-400 animate-pulse`:`bg-slate-600 group-hover:bg-slate-400`}`}),(0,x.jsx)(`span`,{className:`truncate text-[11px] font-semibold flex-1 tracking-wide`,children:e.title||e.url}),(0,x.jsx)(ss,{className:`w-3.5 h-3.5 rounded-full hover:bg-white/20 text-slate-400 hover:text-white transition-all opacity-0 group-hover:opacity-100`,onClick:t=>C(e.id,t)})]},e.id))}),(0,x.jsxs)(`div`,{className:`flex items-center gap-1 md:gap-2 shrink-0 pl-2 md:pl-3 border-l border-indigo-500/30 pr-0.5 md:pr-1 overflow-x-auto no-scrollbar`,children:[d.map(e=>{let t=te[r],n={translate:t?`bg-gradient-to-r from-fuchsia-600 to-purple-600 text-white shadow-[0_0_10px_rgba(192,38,211,0.5)] border-fuchsia-400/50`:`bg-fuchsia-500/10 text-fuchsia-300 border-fuchsia-500/30 hover:bg-fuchsia-500/20`,audio:`bg-emerald-500/10 text-emerald-300 border-emerald-500/30 hover:bg-emerald-500/20`,scroll:`bg-blue-500/10 text-blue-300 border-blue-500/30 hover:bg-blue-500/20`,next:`bg-orange-500/10 text-orange-300 border-orange-500/30 hover:bg-orange-500/20`,dark_mode:`bg-slate-500/10 text-slate-300 border-slate-500/30 hover:bg-slate-500/20`,clean_ads:`bg-red-500/10 text-red-300 border-red-500/30 hover:bg-red-500/20`,force_translate:`bg-violet-500/10 text-violet-300 border-violet-500/30 hover:bg-violet-500/20`,copy_text:`bg-zinc-500/10 text-zinc-300 border-zinc-500/30 hover:bg-zinc-500/20`},i={translate:`✨`,audio:`🔊`,scroll:`📜`,next:`⏭️`,dark_mode:`🌙`,clean_ads:`🧹`,force_translate:`⚡`,copy_text:`📋`},a={translate:t?`Đang Auto`:`Auto-Dịch`,audio:`Nghe`,scroll:`Cuộn`,next:`Tới`,dark_mode:`Tối`,clean_ads:`Lọc QC`,force_translate:`Dịch Nhanh`,copy_text:`Copy`};return(0,x.jsxs)(`button`,{onClick:()=>D(e,r),className:`px-2 py-1.5 md:px-2.5 md:py-1.5 rounded-full text-[11px] font-extrabold flex items-center gap-1 transition-all active:scale-95 border whitespace-nowrap ${n[e]||``}`,title:a[e],children:[(0,x.jsx)(`span`,{className:`text-sm`,children:i[e]}),(0,x.jsx)(`span`,{className:`hidden lg:inline`,children:a[e]})]},e)}),(0,x.jsx)(`div`,{className:`w-px h-4 md:h-5 bg-indigo-500/30 mx-0.5 md:mx-1`}),(0,x.jsxs)(`button`,{onClick:()=>D(`teach_next`,r),className:`px-2 py-1.5 md:px-3 md:py-1.5 bg-gradient-to-r from-orange-500/20 to-amber-500/20 hover:from-orange-500/30 hover:to-amber-500/30 border border-orange-500/30 rounded-full text-[12px] text-orange-100 font-extrabold flex items-center gap-1.5 transition-all active:scale-95 shadow-md`,title:`Chỉ định nút Chương Sau`,children:[(0,x.jsx)(`span`,{children:`🎯`}),(0,x.jsx)(`span`,{className:`hidden sm:inline`,children:`Chỉ định nút Tới`})]}),(0,x.jsxs)(`button`,{onClick:()=>u(!0),className:`px-2 py-1.5 md:px-3 md:py-1.5 bg-indigo-600/20 hover:bg-indigo-600/40 border border-indigo-500/30 rounded-full text-[12px] text-indigo-100 font-extrabold flex items-center gap-1.5 transition-all active:scale-95`,title:`Cài Đặt`,children:[(0,x.jsx)($o,{className:`w-4 h-4 md:w-4 md:h-4`}),(0,x.jsx)(`span`,{className:`hidden sm:inline`,children:`Cài Đặt`})]})]})]}):(0,x.jsxs)(`div`,{className:`flex flex-col bg-gradient-to-r from-[#110e26] via-[#1c183a] to-[#110e26] border-b border-indigo-500/20 shadow-lg relative z-20 pb-safe-top`,children:[(0,x.jsxs)(`div`,{className:`flex items-center gap-2 px-3 py-2`,children:[(0,x.jsx)(`button`,{onClick:()=>c(!1),className:`p-2 hover:bg-white/10 rounded-full transition-colors shrink-0`,title:`Quay lại App`,children:(0,x.jsx)(Bo,{className:`w-4 h-4 text-slate-300`})}),(0,x.jsxs)(`div`,{className:`flex-1 flex items-center bg-[#161330] border border-indigo-500/20 rounded-xl px-2.5 py-1`,children:[(0,x.jsx)(Ro,{className:`w-3.5 h-3.5 text-slate-500 mr-1.5 shrink-0`}),(0,x.jsx)(`input`,{type:`text`,value:p,onChange:e=>m(e.target.value),onKeyDown:e=>{e.key===`Enter`&&ee()},placeholder:`Nhập link web truyện...`,className:`flex-1 bg-transparent text-[11px] text-slate-200 placeholder-slate-500 focus:outline-none focus:ring-0 min-w-0`}),p&&(0,x.jsx)(`button`,{onClick:()=>m(``),className:`p-1 hover:bg-white/5 rounded-full shrink-0`,children:(0,x.jsx)(ss,{className:`w-3 h-3 text-slate-500`})})]}),(0,x.jsx)(`button`,{onClick:ee,className:`px-3 py-1 bg-gradient-to-r from-purple-600 to-indigo-600 hover:from-purple-500 hover:to-indigo-500 text-white text-[11px] font-bold rounded-lg transition-all shadow-md active:scale-95 shrink-0`,children:`Đi`}),(0,x.jsx)(`div`,{className:`w-px h-5 bg-indigo-500/20 mx-1 shrink-0`}),(0,x.jsxs)(`div`,{className:`flex items-center gap-1 shrink-0`,children:[(0,x.jsx)(`button`,{onClick:()=>k(`/bookshelf`),className:`p-2 hover:bg-white/10 rounded-full transition-colors`,title:`Tủ Sách`,children:(0,x.jsx)(Mo,{className:`w-4 h-4 text-slate-300`})}),(0,x.jsx)(`button`,{onClick:()=>k(`/history`),className:`p-2 hover:bg-white/10 rounded-full transition-colors`,title:`Lịch Sử`,children:(0,x.jsx)(zo,{className:`w-4 h-4 text-slate-300`})}),(0,x.jsx)(`button`,{onClick:()=>k(`/settings`),className:`p-2 hover:bg-white/10 rounded-full transition-colors`,title:`Cài Đặt`,children:(0,x.jsx)(es,{className:`w-4 h-4 text-slate-300`})})]})]}),t.length>0&&(0,x.jsxs)(`div`,{className:`flex items-center gap-2 px-3 py-1.5 bg-[#0f0c24]/50 border-t border-indigo-500/10 overflow-x-auto no-scrollbar`,children:[(0,x.jsx)(`div`,{className:`flex items-center gap-1.5 overflow-x-auto no-scrollbar scroll-smooth flex-1 py-0.5`,children:t.map(e=>(0,x.jsxs)(`div`,{onClick:()=>i(e.id),className:`group relative flex items-center gap-1.5 px-3 py-1 rounded-full cursor-pointer transition-all duration-300 border text-[10px] font-semibold whitespace-nowrap ${r===e.id?`bg-indigo-600/35 text-indigo-50 border-indigo-400/50 shadow-sm`:`bg-[#00000030] text-slate-400 border-transparent hover:bg-white/5`}`,children:[(0,x.jsx)(`span`,{className:`truncate max-w-[100px]`,children:e.title||bs(e.url)}),(0,x.jsx)(ss,{className:`w-3 h-3 rounded-full hover:bg-white/20 text-slate-400 hover:text-white transition-all shrink-0`,onClick:t=>{t.stopPropagation(),C(e.id,t)}})]},e.id))}),(0,x.jsx)(`div`,{className:`w-px h-4 bg-indigo-500/20 shrink-0`}),(0,x.jsxs)(`button`,{onClick:()=>u(!0),className:`px-2.5 py-1 bg-indigo-600/20 hover:bg-indigo-600/40 border border-indigo-500/30 rounded-full text-[10px] text-indigo-100 font-extrabold flex items-center gap-1 transition-all active:scale-95 shrink-0`,title:`Cài Đặt Dịch`,children:[(0,x.jsx)($o,{className:`w-3 h-3`}),(0,x.jsx)(`span`,{children:`Cấu hình`})]})]})]}),(0,x.jsx)(`div`,{className:`flex-1 relative bg-white`,style:{paddingBottom:ls?`0px`:`calc(env(safe-area-inset-bottom) + 64px)`},children:t.map(e=>ls?(0,x.jsx)(`webview`,{id:`global-wv-${e.id}`,src:e.initialUrl||e.url,allowpopups:`true`,className:r===e.id?`w-full h-full border-none`:`w-0 h-0 invisible absolute`},e.id):(0,x.jsx)(`div`,{className:r===e.id?`w-full h-full flex flex-col`:`w-0 h-0 invisible absolute`,children:(0,x.jsx)(`iframe`,{id:`global-wv-${e.id}`,src:v(e.url||e.initialUrl),className:`flex-1 w-full border-none bg-white`})},e.id))}),!ls&&(0,x.jsx)(`div`,{className:`fixed bottom-0 left-0 right-0 z-[10000] bg-[#1c183a]/95 backdrop-blur-md border-t border-indigo-500/20 flex flex-col pt-2 shadow-[0_-8px_24px_rgba(0,0,0,0.3)]`,style:{paddingBottom:`calc(env(safe-area-inset-bottom) + 8px)`},children:(0,x.jsxs)(`div`,{className:`flex items-center justify-around h-14 px-2`,children:[(0,x.jsxs)(`button`,{onClick:A,className:`flex flex-col items-center justify-center w-12 h-12 rounded-full hover:bg-white/5 active:scale-90 transition-all text-slate-300`,title:`Lùi`,children:[(0,x.jsx)(Po,{className:`w-5 h-5`}),(0,x.jsx)(`span`,{className:`text-[9px] font-medium text-slate-400 mt-0.5`,children:`Lùi`})]}),(0,x.jsxs)(`button`,{onClick:ie,className:`flex flex-col items-center justify-center w-12 h-12 rounded-full hover:bg-white/5 active:scale-90 transition-all text-slate-300`,title:`Tiến`,children:[(0,x.jsx)(Fo,{className:`w-5 h-5`}),(0,x.jsx)(`span`,{className:`text-[9px] font-medium text-slate-400 mt-0.5`,children:`Tiến`})]}),(0,x.jsxs)(`button`,{onClick:j,className:`flex flex-col items-center justify-center w-12 h-12 rounded-full hover:bg-white/5 active:scale-90 transition-all text-slate-300`,title:`Reload`,children:[(0,x.jsx)(Zo,{className:`w-4 h-4`}),(0,x.jsx)(`span`,{className:`text-[9px] font-medium text-slate-400 mt-1`,children:`F5`})]}),(()=>{let e=te[r];return(0,x.jsxs)(`button`,{onClick:()=>D(`translate`,r),className:`flex flex-col items-center justify-center w-12 h-12 rounded-full active:scale-90 transition-all ${e?`text-fuchsia-400 font-extrabold`:`text-slate-300`}`,title:`Dịch`,children:[(0,x.jsx)(Ho,{className:`w-4.5 h-4.5`}),(0,x.jsx)(`span`,{className:`text-[9px] font-medium mt-0.5`,children:e?`Auto`:`Dịch`})]})})(),(0,x.jsxs)(`button`,{onClick:()=>D(`audio`,r),className:`flex flex-col items-center justify-center w-12 h-12 rounded-full hover:bg-white/5 active:scale-90 transition-all text-slate-300`,title:`Nghe AI`,children:[(0,x.jsx)(as,{className:`w-4.5 h-4.5`}),(0,x.jsx)(`span`,{className:`text-[9px] font-medium mt-0.5`,children:`Nghe`})]}),(0,x.jsxs)(`button`,{onClick:()=>D(`scroll`,r),className:`flex flex-col items-center justify-center w-12 h-12 rounded-full hover:bg-white/5 active:scale-90 transition-all text-slate-300`,title:`Cuộn Xuống`,children:[(0,x.jsx)(Ao,{className:`w-4.5 h-4.5`}),(0,x.jsx)(`span`,{className:`text-[9px] font-medium mt-0.5`,children:`Cuộn`})]}),(0,x.jsxs)(`button`,{onClick:()=>D(`next`,r),className:`flex flex-col items-center justify-center w-12 h-12 rounded-full hover:bg-white/5 active:scale-90 transition-all text-slate-300`,title:`Chương Tiếp`,children:[(0,x.jsx)(rs,{className:`w-4.5 h-4.5`}),(0,x.jsx)(`span`,{className:`text-[9px] font-medium mt-0.5`,children:`Tới`})]})]})}),(0,x.jsx)(fs,{isOpen:l,onClose:()=>u(!1),onToolAction:e=>D(e,r),isAutoTranslate:te[r],pinnedTools:d,onTogglePin:E})]}),a&&(0,x.jsx)(ds,{book:a,onClose:()=>{if(o(null),a.tabId){g.current[a.tabId]=!1;let e=ls?document.getElementById(`global-wv-`+a.tabId):null;e&&e.executeJavaScript(`window.isTtsPlaying = false;`)}},onNextChapter:re,onPrevChapter:O})]})},Ss=class extends S.Component{constructor(e){super(e),this.state={hasError:!1,error:null,errorInfo:null}}static getDerivedStateFromError(e){return{hasError:!0,error:e}}componentDidCatch(e,t){this.setState({errorInfo:t}),console.error(`ErrorBoundary caught an error:`,e,t);try{U.post(`/api/logs/error`,{message:e.toString(),stack:t.componentStack,url:window.location.href,userAgent:navigator.userAgent,time:new Date().toISOString()}).catch(()=>{})}catch(e){console.error(`Failed to send log:`,e)}}render(){return this.state.hasError?(0,x.jsx)(`div`,{className:`min-h-screen bg-[#0b0b14] text-white flex flex-col items-center justify-center p-8`,children:(0,x.jsxs)(`div`,{className:`max-w-2xl bg-red-900/20 border border-red-500/50 rounded-2xl p-8 shadow-2xl`,children:[(0,x.jsxs)(`h1`,{className:`text-3xl font-black text-red-400 mb-4 flex items-center gap-3`,children:[(0,x.jsx)(`span`,{children:`⚠️`}),` Đã Xảy Ra Lỗi Nghiêm Trọng!`]}),(0,x.jsx)(`p`,{className:`text-red-200 mb-6 font-medium`,children:`Ứng dụng vừa gặp phải một sự cố ngoài ý muốn. Đừng lo, lỗi đã được tự động ghi nhận và gửi về Server để khắc phục.`}),(0,x.jsxs)(`div`,{className:`bg-black/50 p-4 rounded-xl overflow-x-auto text-sm text-red-300 font-mono border border-red-900 mb-6 max-h-64 overflow-y-auto`,children:[(0,x.jsx)(`div`,{className:`font-bold mb-2`,children:this.state.error&&this.state.error.toString()}),(0,x.jsx)(`div`,{className:`whitespace-pre-wrap opacity-80`,children:this.state.errorInfo&&this.state.errorInfo.componentStack})]}),(0,x.jsx)(`button`,{onClick:()=>window.location.reload(),className:`px-6 py-3 bg-red-600 hover:bg-red-500 text-white font-bold rounded-xl transition-all shadow-lg shadow-red-600/30 active:scale-95`,children:`🔄 Tải Lại Ứng Dụng (Reload)`})]})}):this.props.children}},Cs=typeof window<`u`&&window.Capacitor&&window.Capacitor.isNativePlatform&&window.Capacitor.isNativePlatform(),ws=ls||Cs?kn:On,Ts=(0,S.lazy)(()=>T(()=>import(`./Discover-BCmVIXus.js`),__vite__mapDeps([2,3,4,5,6,7,8,9]))),Es=(0,S.lazy)(()=>T(()=>import(`./Bookshelf-ClI6d9JY.js`),__vite__mapDeps([10,4,5,7,6,8,11,12]))),Ds=(0,S.lazy)(()=>T(()=>import(`./HistoryPage-DD_Z3uyW.js`),__vite__mapDeps([13,4,5,14,11,12]))),Os=(0,S.lazy)(()=>T(()=>import(`./BookDetail-CwKiYfhq.js`),__vite__mapDeps([15,3,4,5,6,8,16,9]))),ks=(0,S.lazy)(()=>T(()=>import(`./Reader-DUnP7yTH.js`),__vite__mapDeps([17,18,5,16,9]))),As=(0,S.lazy)(()=>T(()=>import(`./Developer-BFnP9Lg5.js`),__vite__mapDeps([19,3,4,5,20,12]))),js=(0,S.lazy)(()=>T(()=>import(`./LocalReader-Bc5HMhfm.js`),__vite__mapDeps([21,18,4,5,16,20,12]))),Ms=(0,S.lazy)(()=>T(()=>import(`./Settings-d6v3GnDB.js`),__vite__mapDeps([22,3,4,5,14,23,24,12]))),Ns=(0,S.lazy)(()=>T(()=>import(`./AuthorDetail-lunBE6ER.js`),__vite__mapDeps([25,3,4,5,6,26]))),Ps=(0,S.lazy)(()=>T(()=>import(`./Messages-Df1xxWEC.js`),__vite__mapDeps([27,4,5]))),Fs=(0,S.lazy)(()=>T(()=>import(`./Sects-X0poZC74.js`),__vite__mapDeps([28,3,4,5,23,20,12]))),Is=(0,S.lazy)(()=>T(()=>import(`./Downloads-DcrmkLWQ.js`),__vite__mapDeps([29,4,5,26,24]))),Ls=()=>(0,x.jsxs)(`div`,{style:{display:`flex`,alignItems:`center`,justifyContent:`center`,height:`100vh`,background:`#0b0b14`},children:[(0,x.jsx)(`div`,{style:{width:32,height:32,border:`3px solid #1f1f3a`,borderTopColor:`#7c3aed`,borderRadius:`50%`,animation:`spin 0.7s linear infinite`}}),(0,x.jsx)(`style`,{children:`@keyframes spin{to{transform:rotate(360deg)}}`})]});function Rs(){return(0,x.jsx)(Ss,{children:(0,x.jsx)(ho,{children:(0,x.jsx)(uo,{children:(0,x.jsx)(vo,{children:(0,x.jsx)(xs,{children:(0,x.jsx)(ws,{children:(0,x.jsx)(S.Suspense,{fallback:(0,x.jsx)(Ls,{}),children:(0,x.jsxs)(Rt,{children:[(0,x.jsx)(It,{path:`/`,element:(0,x.jsx)(Ts,{})}),(0,x.jsx)(It,{path:`/bookshelf`,element:(0,x.jsx)(Es,{})}),(0,x.jsx)(It,{path:`/history`,element:(0,x.jsx)(Ds,{})}),(0,x.jsx)(It,{path:`/developer`,element:(0,x.jsx)(As,{})}),(0,x.jsx)(It,{path:`/downloads`,element:(0,x.jsx)(Is,{})}),(0,x.jsx)(It,{path:`/settings`,element:(0,x.jsx)(Ms,{})}),(0,x.jsx)(It,{path:`/messages`,element:(0,x.jsx)(Ps,{})}),(0,x.jsx)(It,{path:`/sects`,element:(0,x.jsx)(Fs,{})}),(0,x.jsx)(It,{path:`/book/:bookId`,element:(0,x.jsx)(Os,{})}),(0,x.jsx)(It,{path:`/book/:bookId/read/:chapterIdx`,element:(0,x.jsx)(ks,{})}),(0,x.jsx)(It,{path:`/author/:authorName`,element:(0,x.jsx)(Ns,{})}),(0,x.jsx)(It,{path:`/embed`,element:(0,x.jsx)(js,{})})]})})})})})})})})}try{if(!window.localStorage)throw Error(`localStorage is null`);let e=`__storage_test__`;window.localStorage.setItem(e,e),window.localStorage.removeItem(e)}catch(e){console.warn(`[Storage Polyfill] localStorage is blocked or throws an error. Using in-memory fallback.`,e);let t={},n={getItem:e=>e in t?t[e]:null,setItem:(e,n)=>{t[e]=String(n)},removeItem:e=>{delete t[e]},clear:()=>{for(let e in t)delete t[e]},key:e=>Object.keys(t)[e]||null,get length(){return Object.keys(t).length}};try{Object.defineProperty(window,"localStorage",{value:n,writable:!0,configurable:!0})}catch(e){console.error(`[Storage Polyfill] Failed to redefine window.localStorage:`,e)}}try{if(!window.sessionStorage)throw Error(`sessionStorage is null`);let e=`__session_storage_test__`;window.sessionStorage.setItem(e,e),window.sessionStorage.removeItem(e)}catch(e){console.warn(`[Storage Polyfill] sessionStorage is blocked or throws an error. Using in-memory fallback.`,e);let t={},n={getItem:e=>e in t?t[e]:null,setItem:(e,n)=>{t[e]=String(n)},removeItem:e=>{delete t[e]},clear:()=>{for(let e in t)delete t[e]},key:e=>Object.keys(t)[e]||null,get length(){return Object.keys(t).length}};try{Object.defineProperty(window,"sessionStorage",{value:n,writable:!0,configurable:!0})}catch(e){console.error(`[Storage Polyfill] Failed to redefine window.sessionStorage:`,e)}}(0,C.createRoot)(document.getElementById(`root`)).render((0,x.jsx)(S.StrictMode,{children:(0,x.jsx)(Rs,{})}));export{T as A,fo as C,ut as D,st as E,l as F,f as M,o as N,ft as O,u as P,go as S,lo as T,Fo as _,cs as a,G as b,es as c,qo as d,Uo as f,Lo as g,Ro as h,ls as i,m as j,Bn as k,Qo as l,zo as m,ps as n,ss as o,Vo as p,us as r,as as s,hs as t,Xo as u,Po as v,U as w,yo as x,Mo as y}; \ No newline at end of file diff --git a/frontend-web/dist/assets/laptop-BPoCx4gb.js b/frontend-web/dist/assets/laptop-BPoCx4gb.js new file mode 100644 index 0000000000000000000000000000000000000000..5a5c9837374c43dc667ee8831f820bbeb46675df --- /dev/null +++ b/frontend-web/dist/assets/laptop-BPoCx4gb.js @@ -0,0 +1 @@ +import{b as e}from"./index-yRoRoI6u.js";var t=e(`laptop`,[[`path`,{d:`M18 5a2 2 0 0 1 2 2v8.526a2 2 0 0 0 .212.897l1.068 2.127a1 1 0 0 1-.9 1.45H3.62a1 1 0 0 1-.9-1.45l1.068-2.127A2 2 0 0 0 4 15.526V7a2 2 0 0 1 2-2z`,key:`1pdavp`}],[`path`,{d:`M20.054 15.987H3.946`,key:`14rxg9`}]]);export{t}; \ No newline at end of file diff --git a/frontend-web/dist/assets/plus-CSQqtn3N.js b/frontend-web/dist/assets/plus-CSQqtn3N.js new file mode 100644 index 0000000000000000000000000000000000000000..b11d940522368e741fc068528f860b85ba29cffb --- /dev/null +++ b/frontend-web/dist/assets/plus-CSQqtn3N.js @@ -0,0 +1 @@ +import{b as e}from"./index-yRoRoI6u.js";var t=e(`plus`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`M12 5v14`,key:`s699le`}]]);export{t}; \ No newline at end of file diff --git a/frontend-web/dist/assets/shield-LuyExdkp.js b/frontend-web/dist/assets/shield-LuyExdkp.js new file mode 100644 index 0000000000000000000000000000000000000000..7dbf63a379517fc8a3fb72418cd439f8702eaa37 --- /dev/null +++ b/frontend-web/dist/assets/shield-LuyExdkp.js @@ -0,0 +1 @@ +import{b as e}from"./index-yRoRoI6u.js";var t=e(`coins`,[[`path`,{d:`M13.744 17.736a6 6 0 1 1-7.48-7.48`,key:`bq4yh3`}],[`path`,{d:`M15 6h1v4`,key:`11y1tn`}],[`path`,{d:`m6.134 14.768.866-.5 2 3.464`,key:`17snzx`}],[`circle`,{cx:`16`,cy:`8`,r:`6`,key:`14bfc9`}]]),n=e(`shield`,[[`path`,{d:`M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z`,key:`oel41y`}]]);export{t as n,n as t}; \ No newline at end of file diff --git a/frontend-web/dist/assets/square-DZKJ0QGR.js b/frontend-web/dist/assets/square-DZKJ0QGR.js new file mode 100644 index 0000000000000000000000000000000000000000..8d4eacfd7a565a4aadb4e46d9991349ad8372d85 --- /dev/null +++ b/frontend-web/dist/assets/square-DZKJ0QGR.js @@ -0,0 +1 @@ +import{b as e}from"./index-yRoRoI6u.js";var t=e(`check`,[[`path`,{d:`M20 6 9 17l-5-5`,key:`1gmf2c`}]]),n=e(`external-link`,[[`path`,{d:`M15 3h6v6`,key:`1q9fwt`}],[`path`,{d:`M10 14 21 3`,key:`gplh6r`}],[`path`,{d:`M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6`,key:`a6xqqp`}]]),r=e(`menu`,[[`path`,{d:`M4 5h16`,key:`1tepv9`}],[`path`,{d:`M4 12h16`,key:`1lakjw`}],[`path`,{d:`M4 19h16`,key:`1djgab`}]]),i=e(`minus`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}]]),a=e(`search`,[[`path`,{d:`m21 21-4.34-4.34`,key:`14j7rj`}],[`circle`,{cx:`11`,cy:`11`,r:`8`,key:`4ej97u`}]]),o=e(`square`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}]]);export{n as a,r as i,a as n,t as o,i as r,o as t}; \ No newline at end of file diff --git a/frontend-web/dist/assets/square-check-big-BhcFiAg6.js b/frontend-web/dist/assets/square-check-big-BhcFiAg6.js new file mode 100644 index 0000000000000000000000000000000000000000..c44e55dd7cc60e2602bd419b88154c0bd8f55269 --- /dev/null +++ b/frontend-web/dist/assets/square-check-big-BhcFiAg6.js @@ -0,0 +1 @@ +import{b as e}from"./index-yRoRoI6u.js";var t=e(`square-check-big`,[[`path`,{d:`M21 10.656V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h12.344`,key:`2acyp4`}],[`path`,{d:`m9 11 3 3L22 4`,key:`1pflzl`}]]);export{t}; \ No newline at end of file diff --git a/frontend-web/dist/assets/star-DjnKUekI.js b/frontend-web/dist/assets/star-DjnKUekI.js new file mode 100644 index 0000000000000000000000000000000000000000..2d40dd715c2c3cbec246570f9f614a56d95beb39 --- /dev/null +++ b/frontend-web/dist/assets/star-DjnKUekI.js @@ -0,0 +1 @@ +import{b as e}from"./index-yRoRoI6u.js";var t=e(`chevron-down`,[[`path`,{d:`m6 9 6 6 6-6`,key:`qrunsl`}]]),n=e(`chevron-up`,[[`path`,{d:`m18 15-6-6-6 6`,key:`153udz`}]]),r=e(`star`,[[`path`,{d:`M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z`,key:`r04s7s`}]]);export{n,t as r,r as t}; \ No newline at end of file diff --git a/frontend-web/dist/assets/trash-2-DDhTqVwA.js b/frontend-web/dist/assets/trash-2-DDhTqVwA.js new file mode 100644 index 0000000000000000000000000000000000000000..deb47b5b13a31ed194b8af7b10dbef9be8050870 --- /dev/null +++ b/frontend-web/dist/assets/trash-2-DDhTqVwA.js @@ -0,0 +1 @@ +import{b as e}from"./index-yRoRoI6u.js";var t=e(`trash-2`,[[`path`,{d:`M10 11v6`,key:`nco0om`}],[`path`,{d:`M14 11v6`,key:`outv1u`}],[`path`,{d:`M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6`,key:`miytrc`}],[`path`,{d:`M3 6h18`,key:`d0wm0j`}],[`path`,{d:`M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2`,key:`e791ji`}]]);export{t}; \ No newline at end of file diff --git a/frontend-web/dist/assets/useUsageTracker-Bc2zfMaM.js b/frontend-web/dist/assets/useUsageTracker-Bc2zfMaM.js new file mode 100644 index 0000000000000000000000000000000000000000..84967a829f7e6902c9f5fcba745d0f569032767e --- /dev/null +++ b/frontend-web/dist/assets/useUsageTracker-Bc2zfMaM.js @@ -0,0 +1 @@ +import{C as e,F as t,b as n,j as r,w as i}from"./index-yRoRoI6u.js";var a=n(`arrow-left`,[[`path`,{d:`m12 19-7-7 7-7`,key:`1l729n`}],[`path`,{d:`M19 12H5`,key:`x3x0zl`}]]),o=n(`target`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`circle`,{cx:`12`,cy:`12`,r:`6`,key:`1vlfrh`}],[`circle`,{cx:`12`,cy:`12`,r:`2`,key:`1c9p78`}]]),s=t(r(),1);function c(t=`web`,n=`read`){let{user:r}=e(),a=(0,s.useRef)(0),o=(0,s.useRef)(r);(0,s.useEffect)(()=>{o.current=r},[r]),(0,s.useEffect)(()=>{if(!o.current)return;let e=setInterval(()=>{if(document.visibilityState===`visible`&&(a.current+=10,a.current>=30)){let e=navigator.onLine?`online`:`offline`,r={source:t,action:n,duration:a.current,mode:e};i.post(`/api/user/track`,r).then(()=>{a.current=0}).catch(e=>{let t=JSON.parse(localStorage.getItem(`pending_usage_logs`)||`[]`);t.push({...r,timestamp:new Date().toISOString()}),localStorage.setItem(`pending_usage_logs`,JSON.stringify(t)),a.current=0})}},1e4),r=()=>{if(!o.current)return;let e=JSON.parse(localStorage.getItem(`pending_usage_logs`)||`[]`);e.length>0&&Promise.all(e.map(e=>i.post(`/api/user/track`,e))).then(()=>{localStorage.removeItem(`pending_usage_logs`)}).catch(e=>console.error(`Failed to sync offline usage logs:`,e))};return window.addEventListener(`online`,r),navigator.onLine&&r(),()=>{if(clearInterval(e),window.removeEventListener(`online`,r),a.current>0&&o.current&&navigator.onLine){let e=navigator.onLine?`online`:`offline`;i.post(`/api/user/track`,{source:t,action:n,duration:a.current,mode:e}).catch(()=>{})}}},[t,n,r])}export{o as n,a as r,c as t}; \ No newline at end of file diff --git a/frontend-web/dist/assets/web-DHhvTs7U.js b/frontend-web/dist/assets/web-DHhvTs7U.js new file mode 100644 index 0000000000000000000000000000000000000000..263103fffd2cb599152c7f146101bbc275cc143a --- /dev/null +++ b/frontend-web/dist/assets/web-DHhvTs7U.js @@ -0,0 +1 @@ +import{t as e}from"./dist-DE1p5HKj.js";var t=class extends e{constructor(){super(),this._lastWindow=null}async open(e){this._lastWindow=window.open(e.url,e.windowName||`_blank`)}async close(){return new Promise((e,t)=>{this._lastWindow==null?t(`No active window to close!`):(this._lastWindow.close(),this._lastWindow=null,e())})}};new t;export{t as BrowserWeb}; \ No newline at end of file diff --git a/frontend-web/dist/assets/web-DHnq1Usq.js b/frontend-web/dist/assets/web-DHnq1Usq.js new file mode 100644 index 0000000000000000000000000000000000000000..d05c9000431f2f0d106b95c8c28321d0e60205e6 --- /dev/null +++ b/frontend-web/dist/assets/web-DHnq1Usq.js @@ -0,0 +1 @@ +import{t as e}from"./dist-DE1p5HKj.js";var t=class extends e{constructor(){super(),this.handleVisibilityChange=()=>{let e={isActive:document.hidden!==!0};this.notifyListeners(`appStateChange`,e),document.hidden?this.notifyListeners(`pause`,null):this.notifyListeners(`resume`,null)},document.addEventListener(`visibilitychange`,this.handleVisibilityChange,!1)}exitApp(){throw this.unimplemented(`Not implemented on web.`)}async getInfo(){throw this.unimplemented(`Not implemented on web.`)}async getLaunchUrl(){return{url:``}}async getState(){return{isActive:document.hidden!==!0}}async minimizeApp(){throw this.unimplemented(`Not implemented on web.`)}async toggleBackButtonHandler(){throw this.unimplemented(`Not implemented on web.`)}async getAppLanguage(){return{value:navigator.language.split(`-`)[0].toLowerCase()}}};export{t as AppWeb}; \ No newline at end of file diff --git a/frontend-web/dist/index.html b/frontend-web/dist/index.html new file mode 100644 index 0000000000000000000000000000000000000000..5db198ba4966bd7480ca51bc58cd3457e518a428 --- /dev/null +++ b/frontend-web/dist/index.html @@ -0,0 +1,66 @@ + + + + + + + + + + + + Tiên Hiệp AI - Kho Truyện Dịch & Nghe Đọc AI Đỉnh Cao + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/VERSION b/matcha_inference_standalone/Matcha-TTS/matcha/VERSION new file mode 100644 index 0000000000000000000000000000000000000000..4d81495bd7367495f8513dbbb131dbb70f656200 --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/VERSION @@ -0,0 +1 @@ +0.0.7.2 diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/__init__.py b/matcha_inference_standalone/Matcha-TTS/matcha/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/hifigan/__init__.py b/matcha_inference_standalone/Matcha-TTS/matcha/hifigan/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/hifigan/config.py b/matcha_inference_standalone/Matcha-TTS/matcha/hifigan/config.py new file mode 100644 index 0000000000000000000000000000000000000000..b3abea9e151a08864353d32066bd4935e24b82e7 --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/hifigan/config.py @@ -0,0 +1,28 @@ +v1 = { + "resblock": "1", + "num_gpus": 0, + "batch_size": 16, + "learning_rate": 0.0004, + "adam_b1": 0.8, + "adam_b2": 0.99, + "lr_decay": 0.999, + "seed": 1234, + "upsample_rates": [8, 8, 2, 2], + "upsample_kernel_sizes": [16, 16, 4, 4], + "upsample_initial_channel": 512, + "resblock_kernel_sizes": [3, 7, 11], + "resblock_dilation_sizes": [[1, 3, 5], [1, 3, 5], [1, 3, 5]], + "resblock_initial_channel": 256, + "segment_size": 8192, + "num_mels": 80, + "num_freq": 1025, + "n_fft": 1024, + "hop_size": 256, + "win_size": 1024, + "sampling_rate": 22050, + "fmin": 0, + "fmax": 8000, + "fmax_loss": None, + "num_workers": 4, + "dist_config": {"dist_backend": "nccl", "dist_url": "tcp://localhost:54321", "world_size": 1}, +} diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/hifigan/denoiser.py b/matcha_inference_standalone/Matcha-TTS/matcha/hifigan/denoiser.py new file mode 100644 index 0000000000000000000000000000000000000000..452be6a9a168a390af759725728abfb10a6c6c0a --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/hifigan/denoiser.py @@ -0,0 +1,68 @@ +# Code modified from Rafael Valle's implementation https://github.com/NVIDIA/waveglow/blob/5bc2a53e20b3b533362f974cfa1ea0267ae1c2b1/denoiser.py + +"""Waveglow style denoiser can be used to remove the artifacts from the HiFiGAN generated audio.""" +import torch + + +class ModeException(Exception): + pass + + +class Denoiser(torch.nn.Module): + """Removes model bias from audio produced with waveglow""" + + def __init__(self, vocoder, filter_length=1024, n_overlap=4, win_length=1024, mode="zeros"): + super().__init__() + self.filter_length = filter_length + self.hop_length = int(filter_length / n_overlap) + self.win_length = win_length + + dtype, device = next(vocoder.parameters()).dtype, next(vocoder.parameters()).device + self.device = device + if mode == "zeros": + mel_input = torch.zeros((1, 80, 88), dtype=dtype, device=device) + elif mode == "normal": + mel_input = torch.randn((1, 80, 88), dtype=dtype, device=device) + else: + raise ModeException(f"Mode {mode} if not supported") + + def stft_fn(audio, n_fft, hop_length, win_length, window): + spec = torch.stft( + audio, + n_fft=n_fft, + hop_length=hop_length, + win_length=win_length, + window=window, + return_complex=True, + ) + spec = torch.view_as_real(spec) + return torch.sqrt(spec.pow(2).sum(-1)), torch.atan2(spec[..., -1], spec[..., 0]) + + self.stft = lambda x: stft_fn( + audio=x, + n_fft=self.filter_length, + hop_length=self.hop_length, + win_length=self.win_length, + window=torch.hann_window(self.win_length, device=device), + ) + self.istft = lambda x, y: torch.istft( + torch.complex(x * torch.cos(y), x * torch.sin(y)), + n_fft=self.filter_length, + hop_length=self.hop_length, + win_length=self.win_length, + window=torch.hann_window(self.win_length, device=device), + ) + + with torch.no_grad(): + bias_audio = vocoder(mel_input).float().squeeze(0) + bias_spec, _ = self.stft(bias_audio) + + self.register_buffer("bias_spec", bias_spec[:, :, 0][:, :, None]) + + @torch.inference_mode() + def forward(self, audio, strength=0.0005): + audio_spec, audio_angles = self.stft(audio) + audio_spec_denoised = audio_spec - self.bias_spec.to(audio.device) * strength + audio_spec_denoised = torch.clamp(audio_spec_denoised, 0.0) + audio_denoised = self.istft(audio_spec_denoised, audio_angles) + return audio_denoised diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/hifigan/env.py b/matcha_inference_standalone/Matcha-TTS/matcha/hifigan/env.py new file mode 100644 index 0000000000000000000000000000000000000000..9ea4f948a3f002921bf9bc24f52cbc1c0b1fc2ec --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/hifigan/env.py @@ -0,0 +1,17 @@ +""" from https://github.com/jik876/hifi-gan """ + +import os +import shutil + + +class AttrDict(dict): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.__dict__ = self + + +def build_env(config, config_name, path): + t_path = os.path.join(path, config_name) + if config != t_path: + os.makedirs(path, exist_ok=True) + shutil.copyfile(config, os.path.join(path, config_name)) diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/hifigan/meldataset.py b/matcha_inference_standalone/Matcha-TTS/matcha/hifigan/meldataset.py new file mode 100644 index 0000000000000000000000000000000000000000..d1b3a90484b82a4a1a51f387950bad71c464ad49 --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/hifigan/meldataset.py @@ -0,0 +1,217 @@ +""" from https://github.com/jik876/hifi-gan """ + +import math +import os +import random + +import numpy as np +import torch +import torch.utils.data +from librosa.filters import mel as librosa_mel_fn +from librosa.util import normalize +from scipy.io.wavfile import read + +MAX_WAV_VALUE = 32768.0 + + +def load_wav(full_path): + sampling_rate, data = read(full_path) + return data, sampling_rate + + +def dynamic_range_compression(x, C=1, clip_val=1e-5): + return np.log(np.clip(x, a_min=clip_val, a_max=None) * C) + + +def dynamic_range_decompression(x, C=1): + return np.exp(x) / C + + +def dynamic_range_compression_torch(x, C=1, clip_val=1e-5): + return torch.log(torch.clamp(x, min=clip_val) * C) + + +def dynamic_range_decompression_torch(x, C=1): + return torch.exp(x) / C + + +def spectral_normalize_torch(magnitudes): + output = dynamic_range_compression_torch(magnitudes) + return output + + +def spectral_de_normalize_torch(magnitudes): + output = dynamic_range_decompression_torch(magnitudes) + return output + + +mel_basis = {} +hann_window = {} + + +def mel_spectrogram(y, n_fft, num_mels, sampling_rate, hop_size, win_size, fmin, fmax, center=False): + if torch.min(y) < -1.0: + print("min value is ", torch.min(y)) + if torch.max(y) > 1.0: + print("max value is ", torch.max(y)) + + global mel_basis, hann_window # pylint: disable=global-statement,global-variable-not-assigned + if fmax not in mel_basis: + mel = librosa_mel_fn(sampling_rate, n_fft, num_mels, fmin, fmax) + mel_basis[str(fmax) + "_" + str(y.device)] = torch.from_numpy(mel).float().to(y.device) + hann_window[str(y.device)] = torch.hann_window(win_size).to(y.device) + + y = torch.nn.functional.pad( + y.unsqueeze(1), (int((n_fft - hop_size) / 2), int((n_fft - hop_size) / 2)), mode="reflect" + ) + y = y.squeeze(1) + + spec = torch.view_as_real( + torch.stft( + y, + n_fft, + hop_length=hop_size, + win_length=win_size, + window=hann_window[str(y.device)], + center=center, + pad_mode="reflect", + normalized=False, + onesided=True, + return_complex=True, + ) + ) + + spec = torch.sqrt(spec.pow(2).sum(-1) + (1e-9)) + + spec = torch.matmul(mel_basis[str(fmax) + "_" + str(y.device)], spec) + spec = spectral_normalize_torch(spec) + + return spec + + +def get_dataset_filelist(a): + with open(a.input_training_file, encoding="utf-8") as fi: + training_files = [ + os.path.join(a.input_wavs_dir, x.split("|")[0] + ".wav") for x in fi.read().split("\n") if len(x) > 0 + ] + + with open(a.input_validation_file, encoding="utf-8") as fi: + validation_files = [ + os.path.join(a.input_wavs_dir, x.split("|")[0] + ".wav") for x in fi.read().split("\n") if len(x) > 0 + ] + return training_files, validation_files + + +class MelDataset(torch.utils.data.Dataset): + def __init__( + self, + training_files, + segment_size, + n_fft, + num_mels, + hop_size, + win_size, + sampling_rate, + fmin, + fmax, + split=True, + shuffle=True, + n_cache_reuse=1, + device=None, + fmax_loss=None, + fine_tuning=False, + base_mels_path=None, + ): + self.audio_files = training_files + random.seed(1234) + if shuffle: + random.shuffle(self.audio_files) + self.segment_size = segment_size + self.sampling_rate = sampling_rate + self.split = split + self.n_fft = n_fft + self.num_mels = num_mels + self.hop_size = hop_size + self.win_size = win_size + self.fmin = fmin + self.fmax = fmax + self.fmax_loss = fmax_loss + self.cached_wav = None + self.n_cache_reuse = n_cache_reuse + self._cache_ref_count = 0 + self.device = device + self.fine_tuning = fine_tuning + self.base_mels_path = base_mels_path + + def __getitem__(self, index): + filename = self.audio_files[index] + if self._cache_ref_count == 0: + audio, sampling_rate = load_wav(filename) + audio = audio / MAX_WAV_VALUE + if not self.fine_tuning: + audio = normalize(audio) * 0.95 + self.cached_wav = audio + if sampling_rate != self.sampling_rate: + raise ValueError(f"{sampling_rate} SR doesn't match target {self.sampling_rate} SR") + self._cache_ref_count = self.n_cache_reuse + else: + audio = self.cached_wav + self._cache_ref_count -= 1 + + audio = torch.FloatTensor(audio) + audio = audio.unsqueeze(0) + + if not self.fine_tuning: + if self.split: + if audio.size(1) >= self.segment_size: + max_audio_start = audio.size(1) - self.segment_size + audio_start = random.randint(0, max_audio_start) + audio = audio[:, audio_start : audio_start + self.segment_size] + else: + audio = torch.nn.functional.pad(audio, (0, self.segment_size - audio.size(1)), "constant") + + mel = mel_spectrogram( + audio, + self.n_fft, + self.num_mels, + self.sampling_rate, + self.hop_size, + self.win_size, + self.fmin, + self.fmax, + center=False, + ) + else: + mel = np.load(os.path.join(self.base_mels_path, os.path.splitext(os.path.split(filename)[-1])[0] + ".npy")) + mel = torch.from_numpy(mel) + + if len(mel.shape) < 3: + mel = mel.unsqueeze(0) + + if self.split: + frames_per_seg = math.ceil(self.segment_size / self.hop_size) + + if audio.size(1) >= self.segment_size: + mel_start = random.randint(0, mel.size(2) - frames_per_seg - 1) + mel = mel[:, :, mel_start : mel_start + frames_per_seg] + audio = audio[:, mel_start * self.hop_size : (mel_start + frames_per_seg) * self.hop_size] + else: + mel = torch.nn.functional.pad(mel, (0, frames_per_seg - mel.size(2)), "constant") + audio = torch.nn.functional.pad(audio, (0, self.segment_size - audio.size(1)), "constant") + + mel_loss = mel_spectrogram( + audio, + self.n_fft, + self.num_mels, + self.sampling_rate, + self.hop_size, + self.win_size, + self.fmin, + self.fmax_loss, + center=False, + ) + + return (mel.squeeze(), audio.squeeze(0), filename, mel_loss.squeeze()) + + def __len__(self): + return len(self.audio_files) diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/hifigan/models.py b/matcha_inference_standalone/Matcha-TTS/matcha/hifigan/models.py new file mode 100644 index 0000000000000000000000000000000000000000..57305eff2822cf3f94d74700cec57161786e070b --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/hifigan/models.py @@ -0,0 +1,368 @@ +""" from https://github.com/jik876/hifi-gan """ + +import torch +import torch.nn as nn # pylint: disable=consider-using-from-import +import torch.nn.functional as F +from torch.nn import AvgPool1d, Conv1d, Conv2d, ConvTranspose1d +from torch.nn.utils import remove_weight_norm, spectral_norm, weight_norm + +from .xutils import get_padding, init_weights + +LRELU_SLOPE = 0.1 + + +class ResBlock1(torch.nn.Module): + def __init__(self, h, channels, kernel_size=3, dilation=(1, 3, 5)): + super().__init__() + self.h = h + self.convs1 = nn.ModuleList( + [ + weight_norm( + Conv1d( + channels, + channels, + kernel_size, + 1, + dilation=dilation[0], + padding=get_padding(kernel_size, dilation[0]), + ) + ), + weight_norm( + Conv1d( + channels, + channels, + kernel_size, + 1, + dilation=dilation[1], + padding=get_padding(kernel_size, dilation[1]), + ) + ), + weight_norm( + Conv1d( + channels, + channels, + kernel_size, + 1, + dilation=dilation[2], + padding=get_padding(kernel_size, dilation[2]), + ) + ), + ] + ) + self.convs1.apply(init_weights) + + self.convs2 = nn.ModuleList( + [ + weight_norm( + Conv1d( + channels, + channels, + kernel_size, + 1, + dilation=1, + padding=get_padding(kernel_size, 1), + ) + ), + weight_norm( + Conv1d( + channels, + channels, + kernel_size, + 1, + dilation=1, + padding=get_padding(kernel_size, 1), + ) + ), + weight_norm( + Conv1d( + channels, + channels, + kernel_size, + 1, + dilation=1, + padding=get_padding(kernel_size, 1), + ) + ), + ] + ) + self.convs2.apply(init_weights) + + def forward(self, x): + for c1, c2 in zip(self.convs1, self.convs2): + xt = F.leaky_relu(x, LRELU_SLOPE) + xt = c1(xt) + xt = F.leaky_relu(xt, LRELU_SLOPE) + xt = c2(xt) + x = xt + x + return x + + def remove_weight_norm(self): + for l in self.convs1: + remove_weight_norm(l) + for l in self.convs2: + remove_weight_norm(l) + + +class ResBlock2(torch.nn.Module): + def __init__(self, h, channels, kernel_size=3, dilation=(1, 3)): + super().__init__() + self.h = h + self.convs = nn.ModuleList( + [ + weight_norm( + Conv1d( + channels, + channels, + kernel_size, + 1, + dilation=dilation[0], + padding=get_padding(kernel_size, dilation[0]), + ) + ), + weight_norm( + Conv1d( + channels, + channels, + kernel_size, + 1, + dilation=dilation[1], + padding=get_padding(kernel_size, dilation[1]), + ) + ), + ] + ) + self.convs.apply(init_weights) + + def forward(self, x): + for c in self.convs: + xt = F.leaky_relu(x, LRELU_SLOPE) + xt = c(xt) + x = xt + x + return x + + def remove_weight_norm(self): + for l in self.convs: + remove_weight_norm(l) + + +class Generator(torch.nn.Module): + def __init__(self, h): + super().__init__() + self.h = h + self.num_kernels = len(h.resblock_kernel_sizes) + self.num_upsamples = len(h.upsample_rates) + self.conv_pre = weight_norm(Conv1d(80, h.upsample_initial_channel, 7, 1, padding=3)) + resblock = ResBlock1 if h.resblock == "1" else ResBlock2 + + self.ups = nn.ModuleList() + for i, (u, k) in enumerate(zip(h.upsample_rates, h.upsample_kernel_sizes)): + self.ups.append( + weight_norm( + ConvTranspose1d( + h.upsample_initial_channel // (2**i), + h.upsample_initial_channel // (2 ** (i + 1)), + k, + u, + padding=(k - u) // 2, + ) + ) + ) + + self.resblocks = nn.ModuleList() + for i in range(len(self.ups)): + ch = h.upsample_initial_channel // (2 ** (i + 1)) + for _, (k, d) in enumerate(zip(h.resblock_kernel_sizes, h.resblock_dilation_sizes)): + self.resblocks.append(resblock(h, ch, k, d)) + + self.conv_post = weight_norm(Conv1d(ch, 1, 7, 1, padding=3)) + self.ups.apply(init_weights) + self.conv_post.apply(init_weights) + + def forward(self, x): + x = self.conv_pre(x) + for i in range(self.num_upsamples): + x = F.leaky_relu(x, LRELU_SLOPE) + x = self.ups[i](x) + xs = None + for j in range(self.num_kernels): + if xs is None: + xs = self.resblocks[i * self.num_kernels + j](x) + else: + xs += self.resblocks[i * self.num_kernels + j](x) + x = xs / self.num_kernels + x = F.leaky_relu(x) + x = self.conv_post(x) + x = torch.tanh(x) + + return x + + def remove_weight_norm(self): + print("Removing weight norm...") + for l in self.ups: + remove_weight_norm(l) + for l in self.resblocks: + l.remove_weight_norm() + remove_weight_norm(self.conv_pre) + remove_weight_norm(self.conv_post) + + +class DiscriminatorP(torch.nn.Module): + def __init__(self, period, kernel_size=5, stride=3, use_spectral_norm=False): + super().__init__() + self.period = period + norm_f = weight_norm if use_spectral_norm is False else spectral_norm + self.convs = nn.ModuleList( + [ + norm_f(Conv2d(1, 32, (kernel_size, 1), (stride, 1), padding=(get_padding(5, 1), 0))), + norm_f(Conv2d(32, 128, (kernel_size, 1), (stride, 1), padding=(get_padding(5, 1), 0))), + norm_f(Conv2d(128, 512, (kernel_size, 1), (stride, 1), padding=(get_padding(5, 1), 0))), + norm_f(Conv2d(512, 1024, (kernel_size, 1), (stride, 1), padding=(get_padding(5, 1), 0))), + norm_f(Conv2d(1024, 1024, (kernel_size, 1), 1, padding=(2, 0))), + ] + ) + self.conv_post = norm_f(Conv2d(1024, 1, (3, 1), 1, padding=(1, 0))) + + def forward(self, x): + fmap = [] + + # 1d to 2d + b, c, t = x.shape + if t % self.period != 0: # pad first + n_pad = self.period - (t % self.period) + x = F.pad(x, (0, n_pad), "reflect") + t = t + n_pad + x = x.view(b, c, t // self.period, self.period) + + for l in self.convs: + x = l(x) + x = F.leaky_relu(x, LRELU_SLOPE) + fmap.append(x) + x = self.conv_post(x) + fmap.append(x) + x = torch.flatten(x, 1, -1) + + return x, fmap + + +class MultiPeriodDiscriminator(torch.nn.Module): + def __init__(self): + super().__init__() + self.discriminators = nn.ModuleList( + [ + DiscriminatorP(2), + DiscriminatorP(3), + DiscriminatorP(5), + DiscriminatorP(7), + DiscriminatorP(11), + ] + ) + + def forward(self, y, y_hat): + y_d_rs = [] + y_d_gs = [] + fmap_rs = [] + fmap_gs = [] + for _, d in enumerate(self.discriminators): + y_d_r, fmap_r = d(y) + y_d_g, fmap_g = d(y_hat) + y_d_rs.append(y_d_r) + fmap_rs.append(fmap_r) + y_d_gs.append(y_d_g) + fmap_gs.append(fmap_g) + + return y_d_rs, y_d_gs, fmap_rs, fmap_gs + + +class DiscriminatorS(torch.nn.Module): + def __init__(self, use_spectral_norm=False): + super().__init__() + norm_f = weight_norm if use_spectral_norm is False else spectral_norm + self.convs = nn.ModuleList( + [ + norm_f(Conv1d(1, 128, 15, 1, padding=7)), + norm_f(Conv1d(128, 128, 41, 2, groups=4, padding=20)), + norm_f(Conv1d(128, 256, 41, 2, groups=16, padding=20)), + norm_f(Conv1d(256, 512, 41, 4, groups=16, padding=20)), + norm_f(Conv1d(512, 1024, 41, 4, groups=16, padding=20)), + norm_f(Conv1d(1024, 1024, 41, 1, groups=16, padding=20)), + norm_f(Conv1d(1024, 1024, 5, 1, padding=2)), + ] + ) + self.conv_post = norm_f(Conv1d(1024, 1, 3, 1, padding=1)) + + def forward(self, x): + fmap = [] + for l in self.convs: + x = l(x) + x = F.leaky_relu(x, LRELU_SLOPE) + fmap.append(x) + x = self.conv_post(x) + fmap.append(x) + x = torch.flatten(x, 1, -1) + + return x, fmap + + +class MultiScaleDiscriminator(torch.nn.Module): + def __init__(self): + super().__init__() + self.discriminators = nn.ModuleList( + [ + DiscriminatorS(use_spectral_norm=True), + DiscriminatorS(), + DiscriminatorS(), + ] + ) + self.meanpools = nn.ModuleList([AvgPool1d(4, 2, padding=2), AvgPool1d(4, 2, padding=2)]) + + def forward(self, y, y_hat): + y_d_rs = [] + y_d_gs = [] + fmap_rs = [] + fmap_gs = [] + for i, d in enumerate(self.discriminators): + if i != 0: + y = self.meanpools[i - 1](y) + y_hat = self.meanpools[i - 1](y_hat) + y_d_r, fmap_r = d(y) + y_d_g, fmap_g = d(y_hat) + y_d_rs.append(y_d_r) + fmap_rs.append(fmap_r) + y_d_gs.append(y_d_g) + fmap_gs.append(fmap_g) + + return y_d_rs, y_d_gs, fmap_rs, fmap_gs + + +def feature_loss(fmap_r, fmap_g): + loss = 0 + for dr, dg in zip(fmap_r, fmap_g): + for rl, gl in zip(dr, dg): + loss += torch.mean(torch.abs(rl - gl)) + + return loss * 2 + + +def discriminator_loss(disc_real_outputs, disc_generated_outputs): + loss = 0 + r_losses = [] + g_losses = [] + for dr, dg in zip(disc_real_outputs, disc_generated_outputs): + r_loss = torch.mean((1 - dr) ** 2) + g_loss = torch.mean(dg**2) + loss += r_loss + g_loss + r_losses.append(r_loss.item()) + g_losses.append(g_loss.item()) + + return loss, r_losses, g_losses + + +def generator_loss(disc_outputs): + loss = 0 + gen_losses = [] + for dg in disc_outputs: + l = torch.mean((1 - dg) ** 2) + gen_losses.append(l) + loss += l + + return loss, gen_losses diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/hifigan/xutils.py b/matcha_inference_standalone/Matcha-TTS/matcha/hifigan/xutils.py new file mode 100644 index 0000000000000000000000000000000000000000..622dae5cf747a03c14170114fd472a53acedb5be --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/hifigan/xutils.py @@ -0,0 +1,38 @@ +""" from https://github.com/jik876/hifi-gan """ + +import glob +import os +import torch +from torch.nn.utils import weight_norm + +def init_weights(m, mean=0.0, std=0.01): + classname = m.__class__.__name__ + if classname.find("Conv") != -1: + m.weight.data.normal_(mean, std) + +def apply_weight_norm(m): + classname = m.__class__.__name__ + if classname.find("Conv") != -1: + weight_norm(m) + +def get_padding(kernel_size, dilation=1): + return int((kernel_size * dilation - dilation) / 2) + +def load_checkpoint(filepath, device): + assert os.path.isfile(filepath) + print(f"Loading '{filepath}'") + checkpoint_dict = torch.load(filepath, map_location=device) + print("Complete.") + return checkpoint_dict + +def save_checkpoint(filepath, obj): + print(f"Saving checkpoint to {filepath}") + torch.save(obj, filepath) + print("Complete.") + +def scan_checkpoint(cp_dir, prefix): + pattern = os.path.join(cp_dir, prefix + "????????") + cp_list = glob.glob(pattern) + if len(cp_list) == 0: + return None + return sorted(cp_list)[-1] diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/models/__init__.py b/matcha_inference_standalone/Matcha-TTS/matcha/models/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/models/baselightningmodule.py b/matcha_inference_standalone/Matcha-TTS/matcha/models/baselightningmodule.py new file mode 100644 index 0000000000000000000000000000000000000000..5a49583ae79708ed997906218efac4fecda3a6b8 --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/models/baselightningmodule.py @@ -0,0 +1,170 @@ +""" +This is a base lightning module that can be used to train a model. +The benefit of this abstraction is that all the logic outside of model definition can be reused for different models. +""" +import inspect +from abc import ABC +from typing import Any, Dict + +import torch +from lightning import LightningModule +from lightning.pytorch.utilities import grad_norm + +import logging +log = logging.getLogger(__name__) + + +class BaseLightningClass(LightningModule, ABC): + def update_data_statistics(self, data_statistics): + if data_statistics is None: + data_statistics = { + "mel_mean": 0.0, + "mel_std": 1.0, + } + + self.register_buffer("mel_mean", torch.tensor(data_statistics["mel_mean"])) + self.register_buffer("mel_std", torch.tensor(data_statistics["mel_std"])) + + def configure_optimizers(self) -> Any: + optimizer = self.hparams.optimizer(params=self.parameters()) + if self.hparams.scheduler not in (None, {}): + scheduler_args = {} + # Manage last epoch for exponential schedulers + if "last_epoch" in inspect.signature(self.hparams.scheduler.scheduler).parameters: + if hasattr(self, "ckpt_loaded_epoch"): + current_epoch = self.ckpt_loaded_epoch - 1 + else: + current_epoch = -1 + + scheduler_args.update({"optimizer": optimizer}) + scheduler = self.hparams.scheduler.scheduler(**scheduler_args) + scheduler.last_epoch = current_epoch + return { + "optimizer": optimizer, + "lr_scheduler": { + "scheduler": scheduler, + "interval": self.hparams.scheduler.lightning_args.interval, + "frequency": self.hparams.scheduler.lightning_args.frequency, + "name": "learning_rate", + }, + } + + return {"optimizer": optimizer} + + def get_losses(self, batch): + x, x_lengths = batch["x"], batch["x_lengths"] + y, y_lengths = batch["y"], batch["y_lengths"] + spks = batch["spks"] + + dur_loss, prior_loss, diff_loss, *_ = self( + x=x, + x_lengths=x_lengths, + y=y, + y_lengths=y_lengths, + spks=spks, + out_size=self.out_size, + durations=batch["durations"], + ) + return { + "dur_loss": dur_loss, + "prior_loss": prior_loss, + "diff_loss": diff_loss, + } + + def on_load_checkpoint(self, checkpoint: Dict[str, Any]) -> None: + self.ckpt_loaded_epoch = checkpoint["epoch"] # pylint: disable=attribute-defined-outside-init + + def training_step(self, batch: Any, batch_idx: int): + loss_dict = self.get_losses(batch) + self.log( + "step", + float(self.global_step), + on_step=True, + prog_bar=True, + logger=True, + sync_dist=True, + ) + + self.log( + "sub_loss/train_dur_loss", + loss_dict["dur_loss"], + on_step=True, + on_epoch=True, + logger=True, + sync_dist=True, + ) + self.log( + "sub_loss/train_prior_loss", + loss_dict["prior_loss"], + on_step=True, + on_epoch=True, + logger=True, + sync_dist=True, + ) + self.log( + "sub_loss/train_diff_loss", + loss_dict["diff_loss"], + on_step=True, + on_epoch=True, + logger=True, + sync_dist=True, + ) + + total_loss = sum(loss_dict.values()) + self.log( + "loss/train", + total_loss, + on_step=True, + on_epoch=True, + logger=True, + prog_bar=True, + sync_dist=True, + ) + + return {"loss": total_loss, "log": loss_dict} + + def validation_step(self, batch: Any, batch_idx: int): + loss_dict = self.get_losses(batch) + self.log( + "sub_loss/val_dur_loss", + loss_dict["dur_loss"], + on_step=True, + on_epoch=True, + logger=True, + sync_dist=True, + ) + self.log( + "sub_loss/val_prior_loss", + loss_dict["prior_loss"], + on_step=True, + on_epoch=True, + logger=True, + sync_dist=True, + ) + self.log( + "sub_loss/val_diff_loss", + loss_dict["diff_loss"], + on_step=True, + on_epoch=True, + logger=True, + sync_dist=True, + ) + + total_loss = sum(loss_dict.values()) + self.log( + "loss/val", + total_loss, + on_step=True, + on_epoch=True, + logger=True, + prog_bar=True, + sync_dist=True, + ) + + return total_loss + + def on_validation_end(self) -> None: + pass + + def on_before_optimizer_step(self, optimizer): + self.log_dict({f"grad_norm/{k}": v for k, v in grad_norm(self, norm_type=2).items()}) diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/models/components/__init__.py b/matcha_inference_standalone/Matcha-TTS/matcha/models/components/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/models/components/decoder.py b/matcha_inference_standalone/Matcha-TTS/matcha/models/components/decoder.py new file mode 100644 index 0000000000000000000000000000000000000000..504f88b433ad0634091263e4331d362e76f750bd --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/models/components/decoder.py @@ -0,0 +1,443 @@ +import math +from typing import Optional + +import torch +import torch.nn as nn # pylint: disable=consider-using-from-import +import torch.nn.functional as F +from conformer import ConformerBlock +from diffusers.models.activations import get_activation +from einops import pack, rearrange, repeat + +from matcha.models.components.transformer import BasicTransformerBlock + + +class SinusoidalPosEmb(torch.nn.Module): + def __init__(self, dim): + super().__init__() + self.dim = dim + assert self.dim % 2 == 0, "SinusoidalPosEmb requires dim to be even" + + def forward(self, x, scale=1000): + if x.ndim < 1: + x = x.unsqueeze(0) + device = x.device + half_dim = self.dim // 2 + emb = math.log(10000) / (half_dim - 1) + emb = torch.exp(torch.arange(half_dim, device=device).float() * -emb) + emb = scale * x.unsqueeze(1) * emb.unsqueeze(0) + emb = torch.cat((emb.sin(), emb.cos()), dim=-1) + return emb + + +class Block1D(torch.nn.Module): + def __init__(self, dim, dim_out, groups=8): + super().__init__() + self.block = torch.nn.Sequential( + torch.nn.Conv1d(dim, dim_out, 3, padding=1), + torch.nn.GroupNorm(groups, dim_out), + nn.Mish(), + ) + + def forward(self, x, mask): + output = self.block(x * mask) + return output * mask + + +class ResnetBlock1D(torch.nn.Module): + def __init__(self, dim, dim_out, time_emb_dim, groups=8): + super().__init__() + self.mlp = torch.nn.Sequential(nn.Mish(), torch.nn.Linear(time_emb_dim, dim_out)) + + self.block1 = Block1D(dim, dim_out, groups=groups) + self.block2 = Block1D(dim_out, dim_out, groups=groups) + + self.res_conv = torch.nn.Conv1d(dim, dim_out, 1) + + def forward(self, x, mask, time_emb): + h = self.block1(x, mask) + h += self.mlp(time_emb).unsqueeze(-1) + h = self.block2(h, mask) + output = h + self.res_conv(x * mask) + return output + + +class Downsample1D(nn.Module): + def __init__(self, dim): + super().__init__() + self.conv = torch.nn.Conv1d(dim, dim, 3, 2, 1) + + def forward(self, x): + return self.conv(x) + + +class TimestepEmbedding(nn.Module): + def __init__( + self, + in_channels: int, + time_embed_dim: int, + act_fn: str = "silu", + out_dim: int = None, + post_act_fn: Optional[str] = None, + cond_proj_dim=None, + ): + super().__init__() + + self.linear_1 = nn.Linear(in_channels, time_embed_dim) + + if cond_proj_dim is not None: + self.cond_proj = nn.Linear(cond_proj_dim, in_channels, bias=False) + else: + self.cond_proj = None + + self.act = get_activation(act_fn) + + if out_dim is not None: + time_embed_dim_out = out_dim + else: + time_embed_dim_out = time_embed_dim + self.linear_2 = nn.Linear(time_embed_dim, time_embed_dim_out) + + if post_act_fn is None: + self.post_act = None + else: + self.post_act = get_activation(post_act_fn) + + def forward(self, sample, condition=None): + if condition is not None: + sample = sample + self.cond_proj(condition) + sample = self.linear_1(sample) + + if self.act is not None: + sample = self.act(sample) + + sample = self.linear_2(sample) + + if self.post_act is not None: + sample = self.post_act(sample) + return sample + + +class Upsample1D(nn.Module): + """A 1D upsampling layer with an optional convolution. + + Parameters: + channels (`int`): + number of channels in the inputs and outputs. + use_conv (`bool`, default `False`): + option to use a convolution. + use_conv_transpose (`bool`, default `False`): + option to use a convolution transpose. + out_channels (`int`, optional): + number of output channels. Defaults to `channels`. + """ + + def __init__(self, channels, use_conv=False, use_conv_transpose=True, out_channels=None, name="conv"): + super().__init__() + self.channels = channels + self.out_channels = out_channels or channels + self.use_conv = use_conv + self.use_conv_transpose = use_conv_transpose + self.name = name + + self.conv = None + if use_conv_transpose: + self.conv = nn.ConvTranspose1d(channels, self.out_channels, 4, 2, 1) + elif use_conv: + self.conv = nn.Conv1d(self.channels, self.out_channels, 3, padding=1) + + def forward(self, inputs): + assert inputs.shape[1] == self.channels + if self.use_conv_transpose: + return self.conv(inputs) + + outputs = F.interpolate(inputs, scale_factor=2.0, mode="nearest") + + if self.use_conv: + outputs = self.conv(outputs) + + return outputs + + +class ConformerWrapper(ConformerBlock): + def __init__( # pylint: disable=useless-super-delegation + self, + *, + dim, + dim_head=64, + heads=8, + ff_mult=4, + conv_expansion_factor=2, + conv_kernel_size=31, + attn_dropout=0, + ff_dropout=0, + conv_dropout=0, + conv_causal=False, + ): + super().__init__( + dim=dim, + dim_head=dim_head, + heads=heads, + ff_mult=ff_mult, + conv_expansion_factor=conv_expansion_factor, + conv_kernel_size=conv_kernel_size, + attn_dropout=attn_dropout, + ff_dropout=ff_dropout, + conv_dropout=conv_dropout, + conv_causal=conv_causal, + ) + + def forward( + self, + hidden_states, + attention_mask, + encoder_hidden_states=None, + encoder_attention_mask=None, + timestep=None, + ): + return super().forward(x=hidden_states, mask=attention_mask.bool()) + + +class Decoder(nn.Module): + def __init__( + self, + in_channels, + out_channels, + channels=(256, 256), + dropout=0.05, + attention_head_dim=64, + n_blocks=1, + num_mid_blocks=2, + num_heads=4, + act_fn="snake", + down_block_type="transformer", + mid_block_type="transformer", + up_block_type="transformer", + ): + super().__init__() + channels = tuple(channels) + self.in_channels = in_channels + self.out_channels = out_channels + + self.time_embeddings = SinusoidalPosEmb(in_channels) + time_embed_dim = channels[0] * 4 + self.time_mlp = TimestepEmbedding( + in_channels=in_channels, + time_embed_dim=time_embed_dim, + act_fn="silu", + ) + + self.down_blocks = nn.ModuleList([]) + self.mid_blocks = nn.ModuleList([]) + self.up_blocks = nn.ModuleList([]) + + output_channel = in_channels + for i in range(len(channels)): # pylint: disable=consider-using-enumerate + input_channel = output_channel + output_channel = channels[i] + is_last = i == len(channels) - 1 + resnet = ResnetBlock1D(dim=input_channel, dim_out=output_channel, time_emb_dim=time_embed_dim) + transformer_blocks = nn.ModuleList( + [ + self.get_block( + down_block_type, + output_channel, + attention_head_dim, + num_heads, + dropout, + act_fn, + ) + for _ in range(n_blocks) + ] + ) + downsample = ( + Downsample1D(output_channel) if not is_last else nn.Conv1d(output_channel, output_channel, 3, padding=1) + ) + + self.down_blocks.append(nn.ModuleList([resnet, transformer_blocks, downsample])) + + for i in range(num_mid_blocks): + input_channel = channels[-1] + out_channels = channels[-1] + + resnet = ResnetBlock1D(dim=input_channel, dim_out=output_channel, time_emb_dim=time_embed_dim) + + transformer_blocks = nn.ModuleList( + [ + self.get_block( + mid_block_type, + output_channel, + attention_head_dim, + num_heads, + dropout, + act_fn, + ) + for _ in range(n_blocks) + ] + ) + + self.mid_blocks.append(nn.ModuleList([resnet, transformer_blocks])) + + channels = channels[::-1] + (channels[0],) + for i in range(len(channels) - 1): + input_channel = channels[i] + output_channel = channels[i + 1] + is_last = i == len(channels) - 2 + + resnet = ResnetBlock1D( + dim=2 * input_channel, + dim_out=output_channel, + time_emb_dim=time_embed_dim, + ) + transformer_blocks = nn.ModuleList( + [ + self.get_block( + up_block_type, + output_channel, + attention_head_dim, + num_heads, + dropout, + act_fn, + ) + for _ in range(n_blocks) + ] + ) + upsample = ( + Upsample1D(output_channel, use_conv_transpose=True) + if not is_last + else nn.Conv1d(output_channel, output_channel, 3, padding=1) + ) + + self.up_blocks.append(nn.ModuleList([resnet, transformer_blocks, upsample])) + + self.final_block = Block1D(channels[-1], channels[-1]) + self.final_proj = nn.Conv1d(channels[-1], self.out_channels, 1) + + self.initialize_weights() + # nn.init.normal_(self.final_proj.weight) + + @staticmethod + def get_block(block_type, dim, attention_head_dim, num_heads, dropout, act_fn): + if block_type == "conformer": + block = ConformerWrapper( + dim=dim, + dim_head=attention_head_dim, + heads=num_heads, + ff_mult=1, + conv_expansion_factor=2, + ff_dropout=dropout, + attn_dropout=dropout, + conv_dropout=dropout, + conv_kernel_size=31, + ) + elif block_type == "transformer": + block = BasicTransformerBlock( + dim=dim, + num_attention_heads=num_heads, + attention_head_dim=attention_head_dim, + dropout=dropout, + activation_fn=act_fn, + ) + else: + raise ValueError(f"Unknown block type {block_type}") + + return block + + def initialize_weights(self): + for m in self.modules(): + if isinstance(m, nn.Conv1d): + nn.init.kaiming_normal_(m.weight, nonlinearity="relu") + + if m.bias is not None: + nn.init.constant_(m.bias, 0) + + elif isinstance(m, nn.GroupNorm): + nn.init.constant_(m.weight, 1) + nn.init.constant_(m.bias, 0) + + elif isinstance(m, nn.Linear): + nn.init.kaiming_normal_(m.weight, nonlinearity="relu") + + if m.bias is not None: + nn.init.constant_(m.bias, 0) + + def forward(self, x, mask, mu, t, spks=None, cond=None): + """Forward pass of the UNet1DConditional model. + + Args: + x (torch.Tensor): shape (batch_size, in_channels, time) + mask (_type_): shape (batch_size, 1, time) + t (_type_): shape (batch_size) + spks (_type_, optional): shape: (batch_size, condition_channels). Defaults to None. + cond (_type_, optional): placeholder for future use. Defaults to None. + + Raises: + ValueError: _description_ + ValueError: _description_ + + Returns: + _type_: _description_ + """ + + t = self.time_embeddings(t) + t = self.time_mlp(t) + + x = pack([x, mu], "b * t")[0] + + if spks is not None: + spks = repeat(spks, "b c -> b c t", t=x.shape[-1]) + x = pack([x, spks], "b * t")[0] + + hiddens = [] + masks = [mask] + for resnet, transformer_blocks, downsample in self.down_blocks: + mask_down = masks[-1] + x = resnet(x, mask_down, t) + x = rearrange(x, "b c t -> b t c") + mask_down = rearrange(mask_down, "b 1 t -> b t") + for transformer_block in transformer_blocks: + x = transformer_block( + hidden_states=x, + attention_mask=mask_down, + timestep=t, + ) + x = rearrange(x, "b t c -> b c t") + mask_down = rearrange(mask_down, "b t -> b 1 t") + hiddens.append(x) # Save hidden states for skip connections + x = downsample(x * mask_down) + masks.append(mask_down[:, :, ::2]) + + masks = masks[:-1] + mask_mid = masks[-1] + + for resnet, transformer_blocks in self.mid_blocks: + x = resnet(x, mask_mid, t) + x = rearrange(x, "b c t -> b t c") + mask_mid = rearrange(mask_mid, "b 1 t -> b t") + for transformer_block in transformer_blocks: + x = transformer_block( + hidden_states=x, + attention_mask=mask_mid, + timestep=t, + ) + x = rearrange(x, "b t c -> b c t") + mask_mid = rearrange(mask_mid, "b t -> b 1 t") + + for resnet, transformer_blocks, upsample in self.up_blocks: + mask_up = masks.pop() + x = resnet(pack([x, hiddens.pop()], "b * t")[0], mask_up, t) + x = rearrange(x, "b c t -> b t c") + mask_up = rearrange(mask_up, "b 1 t -> b t") + for transformer_block in transformer_blocks: + x = transformer_block( + hidden_states=x, + attention_mask=mask_up, + timestep=t, + ) + x = rearrange(x, "b t c -> b c t") + mask_up = rearrange(mask_up, "b t -> b 1 t") + x = upsample(x * mask_up) + + x = self.final_block(x, mask_up) + output = self.final_proj(x * mask_up) + + return output * mask diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/models/components/flow_matching.py b/matcha_inference_standalone/Matcha-TTS/matcha/models/components/flow_matching.py new file mode 100644 index 0000000000000000000000000000000000000000..fab3037641e0d62cbd4b6cab5d8eb009cb6551c6 --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/models/components/flow_matching.py @@ -0,0 +1,130 @@ +from abc import ABC +import torch +import torch.nn.functional as F +from matcha.models.components.decoder import Decoder + + + + + +class BASECFM(torch.nn.Module, ABC): + def __init__( + self, + n_feats, + cfm_params, + n_spks=1, + spk_emb_dim=128, + ): + super().__init__() + self.n_feats = n_feats + self.n_spks = n_spks + self.spk_emb_dim = spk_emb_dim + self.solver = cfm_params.solver + if hasattr(cfm_params, "sigma_min"): + self.sigma_min = cfm_params.sigma_min + else: + self.sigma_min = 1e-4 + + self.estimator = None + + @torch.inference_mode() + def forward(self, mu, mask, n_timesteps, temperature=1.0, spks=None, cond=None): + """Forward diffusion + + Args: + mu (torch.Tensor): output of encoder + shape: (batch_size, n_feats, mel_timesteps) + mask (torch.Tensor): output_mask + shape: (batch_size, 1, mel_timesteps) + n_timesteps (int): number of diffusion steps + temperature (float, optional): temperature for scaling noise. Defaults to 1.0. + spks (torch.Tensor, optional): speaker ids. Defaults to None. + shape: (batch_size, spk_emb_dim) + cond: Not used but kept for future purposes + + Returns: + sample: generated mel-spectrogram + shape: (batch_size, n_feats, mel_timesteps) + """ + z = torch.randn_like(mu) * temperature + t_span = torch.linspace(0, 1, n_timesteps + 1, device=mu.device) + return self.solve_euler(z, t_span=t_span, mu=mu, mask=mask, spks=spks, cond=cond) + + def solve_euler(self, x, t_span, mu, mask, spks, cond): + """ + Fixed euler solver for ODEs. + Args: + x (torch.Tensor): random noise + t_span (torch.Tensor): n_timesteps interpolated + shape: (n_timesteps + 1,) + mu (torch.Tensor): output of encoder + shape: (batch_size, n_feats, mel_timesteps) + mask (torch.Tensor): output_mask + shape: (batch_size, 1, mel_timesteps) + spks (torch.Tensor, optional): speaker ids. Defaults to None. + shape: (batch_size, spk_emb_dim) + cond: Not used but kept for future purposes + """ + t, _, dt = t_span[0], t_span[-1], t_span[1] - t_span[0] + + # I am storing this because I can later plot it by putting a debugger here and saving it to a file + # Or in future might add like a return_all_steps flag + sol = [] + + for step in range(1, len(t_span)): + dphi_dt = self.estimator(x, mask, mu, t, spks, cond) + + x = x + dt * dphi_dt + t = t + dt + sol.append(x) + if step < len(t_span) - 1: + dt = t_span[step + 1] - t + + return sol[-1] + + def compute_loss(self, x1, mask, mu, spks=None, cond=None): + """Computes diffusion loss + + Args: + x1 (torch.Tensor): Target + shape: (batch_size, n_feats, mel_timesteps) + mask (torch.Tensor): target mask + shape: (batch_size, 1, mel_timesteps) + mu (torch.Tensor): output of encoder + shape: (batch_size, n_feats, mel_timesteps) + spks (torch.Tensor, optional): speaker embedding. Defaults to None. + shape: (batch_size, spk_emb_dim) + + Returns: + loss: conditional flow matching loss + y: conditional flow + shape: (batch_size, n_feats, mel_timesteps) + """ + b, _, t = mu.shape + + # random timestep + t = torch.rand([b, 1, 1], device=mu.device, dtype=mu.dtype) + # sample noise p(x_0) + z = torch.randn_like(x1) + + y = (1 - (1 - self.sigma_min) * t) * z + t * x1 + u = x1 - (1 - self.sigma_min) * z + + loss = F.mse_loss(self.estimator(y, mask, mu, t.squeeze(), spks), u, reduction="sum") / ( + torch.sum(mask) * u.shape[1] + ) + return loss, y + + +class CFM(BASECFM): + def __init__(self, in_channels, out_channel, cfm_params, decoder_params, n_spks=1, spk_emb_dim=64): + super().__init__( + n_feats=in_channels, + cfm_params=cfm_params, + n_spks=n_spks, + spk_emb_dim=spk_emb_dim, + ) + + in_channels = in_channels + (spk_emb_dim if n_spks > 1 else 0) + # Just change the architecture of the estimator here + self.estimator = Decoder(in_channels=in_channels, out_channels=out_channel, **decoder_params) diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/models/components/text_encoder.py b/matcha_inference_standalone/Matcha-TTS/matcha/models/components/text_encoder.py new file mode 100644 index 0000000000000000000000000000000000000000..3d7d806c90fb5b3d2cc7dfceef780fbf048c6e8f --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/models/components/text_encoder.py @@ -0,0 +1,407 @@ +""" from https://github.com/jaywalnut310/glow-tts """ + +import math + +import torch +import torch.nn as nn # pylint: disable=consider-using-from-import +from einops import rearrange +from matcha.utils.model import sequence_mask + +class LayerNorm(nn.Module): + def __init__(self, channels, eps=1e-4): + super().__init__() + self.channels = channels + self.eps = eps + + self.gamma = torch.nn.Parameter(torch.ones(channels)) + self.beta = torch.nn.Parameter(torch.zeros(channels)) + + def forward(self, x): + n_dims = len(x.shape) + mean = torch.mean(x, 1, keepdim=True) + variance = torch.mean((x - mean) ** 2, 1, keepdim=True) + + x = (x - mean) * torch.rsqrt(variance + self.eps) + + shape = [1, -1] + [1] * (n_dims - 2) + x = x * self.gamma.view(*shape) + self.beta.view(*shape) + return x + + +class ConvReluNorm(nn.Module): + def __init__(self, in_channels, hidden_channels, out_channels, kernel_size, n_layers, p_dropout): + super().__init__() + self.in_channels = in_channels + self.hidden_channels = hidden_channels + self.out_channels = out_channels + self.kernel_size = kernel_size + self.n_layers = n_layers + self.p_dropout = p_dropout + + self.conv_layers = torch.nn.ModuleList() + self.norm_layers = torch.nn.ModuleList() + self.conv_layers.append(torch.nn.Conv1d(in_channels, hidden_channels, kernel_size, padding=kernel_size // 2)) + self.norm_layers.append(LayerNorm(hidden_channels)) + self.relu_drop = torch.nn.Sequential(torch.nn.ReLU(), torch.nn.Dropout(p_dropout)) + for _ in range(n_layers - 1): + self.conv_layers.append( + torch.nn.Conv1d(hidden_channels, hidden_channels, kernel_size, padding=kernel_size // 2) + ) + self.norm_layers.append(LayerNorm(hidden_channels)) + self.proj = torch.nn.Conv1d(hidden_channels, out_channels, 1) + self.proj.weight.data.zero_() + self.proj.bias.data.zero_() + + def forward(self, x, x_mask): + x_org = x + for i in range(self.n_layers): + x = self.conv_layers[i](x * x_mask) + x = self.norm_layers[i](x) + x = self.relu_drop(x) + x = x_org + self.proj(x) + return x * x_mask + + +class DurationPredictor(nn.Module): + def __init__(self, in_channels, filter_channels, kernel_size, p_dropout): + super().__init__() + self.in_channels = in_channels + self.filter_channels = filter_channels + self.p_dropout = p_dropout + + self.drop = torch.nn.Dropout(p_dropout) + self.conv_1 = torch.nn.Conv1d(in_channels, filter_channels, kernel_size, padding=kernel_size // 2) + self.norm_1 = LayerNorm(filter_channels) + self.conv_2 = torch.nn.Conv1d(filter_channels, filter_channels, kernel_size, padding=kernel_size // 2) + self.norm_2 = LayerNorm(filter_channels) + self.proj = torch.nn.Conv1d(filter_channels, 1, 1) + + def forward(self, x, x_mask): + x = self.conv_1(x * x_mask) + x = torch.relu(x) + x = self.norm_1(x) + x = self.drop(x) + x = self.conv_2(x * x_mask) + x = torch.relu(x) + x = self.norm_2(x) + x = self.drop(x) + x = self.proj(x * x_mask) + return x * x_mask + + +class RotaryPositionalEmbeddings(nn.Module): + """ + ## RoPE module + + Rotary encoding transforms pairs of features by rotating in the 2D plane. + That is, it organizes the $d$ features as $\frac{d}{2}$ pairs. + Each pair can be considered a coordinate in a 2D plane, and the encoding will rotate it + by an angle depending on the position of the token. + """ + + def __init__(self, d: int, base: int = 10_000): + r""" + * `d` is the number of features $d$ + * `base` is the constant used for calculating $\Theta$ + """ + super().__init__() + + self.base = base + self.d = int(d) + self.cos_cached = None + self.sin_cached = None + + def _build_cache(self, x: torch.Tensor): + r""" + Cache $\cos$ and $\sin$ values + """ + # Return if cache is already built and on the correct device + if (self.cos_cached is not None + and self.cos_cached.device == x.device + and x.shape[0] <= self.cos_cached.shape[0]): + return + + # Get sequence length + seq_len = x.shape[0] + + # $\Theta = {\theta_i = 10000^{-\frac{2(i-1)}{d}}, i \in [1, 2, ..., \frac{d}{2}]}$ + theta = 1.0 / (self.base ** (torch.arange(0, self.d, 2).float() / self.d)).to(x.device) + + # Create position indexes `[0, 1, ..., seq_len - 1]` + seq_idx = torch.arange(seq_len, device=x.device).float().to(x.device) + + # Calculate the product of position index and $\theta_i$ + idx_theta = torch.einsum("n,d->nd", seq_idx, theta) + + # Concatenate so that for row $m$ we have + # $[m \theta_0, m \theta_1, ..., m \theta_{\frac{d}{2}}, m \theta_0, m \theta_1, ..., m \theta_{\frac{d}{2}}]$ + idx_theta2 = torch.cat([idx_theta, idx_theta], dim=1) + + # Cache them + self.cos_cached = idx_theta2.cos()[:, None, None, :] + self.sin_cached = idx_theta2.sin()[:, None, None, :] + + def _neg_half(self, x: torch.Tensor): + # $\frac{d}{2}$ + d_2 = self.d // 2 + + # Calculate $[-x^{(\frac{d}{2} + 1)}, -x^{(\frac{d}{2} + 2)}, ..., -x^{(d)}, x^{(1)}, x^{(2)}, ..., x^{(\frac{d}{2})}]$ + return torch.cat([-x[:, :, :, d_2:], x[:, :, :, :d_2]], dim=-1) + + def forward(self, x: torch.Tensor): + """ + * `x` is the Tensor at the head of a key or a query with shape `[seq_len, batch_size, n_heads, d]` + """ + # Cache $\cos$ and $\sin$ values + x = rearrange(x, "b h t d -> t b h d") + + self._build_cache(x) + + # Split the features, we can choose to apply rotary embeddings only to a partial set of features. + x_rope, x_pass = x[..., : self.d], x[..., self.d :] + + # Calculate + # $[-x^{(\frac{d}{2} + 1)}, -x^{(\frac{d}{2} + 2)}, ..., -x^{(d)}, x^{(1)}, x^{(2)}, ..., x^{(\frac{d}{2})}]$ + neg_half_x = self._neg_half(x_rope) + + x_rope = (x_rope * self.cos_cached[: x.shape[0]]) + (neg_half_x * self.sin_cached[: x.shape[0]]) + + return rearrange(torch.cat((x_rope, x_pass), dim=-1), "t b h d -> b h t d") + + +class MultiHeadAttention(nn.Module): + def __init__( + self, + channels, + out_channels, + n_heads, + heads_share=True, + p_dropout=0.0, + proximal_bias=False, + proximal_init=False, + ): + super().__init__() + assert channels % n_heads == 0 + + self.channels = channels + self.out_channels = out_channels + self.n_heads = n_heads + self.heads_share = heads_share + self.proximal_bias = proximal_bias + self.p_dropout = p_dropout + self.attn = None + + self.k_channels = channels // n_heads + self.conv_q = torch.nn.Conv1d(channels, channels, 1) + self.conv_k = torch.nn.Conv1d(channels, channels, 1) + self.conv_v = torch.nn.Conv1d(channels, channels, 1) + + # from https://nn.labml.ai/transformers/rope/index.html + self.query_rotary_pe = RotaryPositionalEmbeddings(self.k_channels * 0.5) + self.key_rotary_pe = RotaryPositionalEmbeddings(self.k_channels * 0.5) + + self.conv_o = torch.nn.Conv1d(channels, out_channels, 1) + self.drop = torch.nn.Dropout(p_dropout) + + torch.nn.init.xavier_uniform_(self.conv_q.weight) + torch.nn.init.xavier_uniform_(self.conv_k.weight) + if proximal_init: + self.conv_k.weight.data.copy_(self.conv_q.weight.data) + self.conv_k.bias.data.copy_(self.conv_q.bias.data) + torch.nn.init.xavier_uniform_(self.conv_v.weight) + + def forward(self, x, c, attn_mask=None): + q = self.conv_q(x) + k = self.conv_k(c) + v = self.conv_v(c) + + x, self.attn = self.attention(q, k, v, mask=attn_mask) + + x = self.conv_o(x) + return x + + def attention(self, query, key, value, mask=None): + b, d, t_s, t_t = (*key.size(), query.size(2)) + query = rearrange(query, "b (h c) t-> b h t c", h=self.n_heads) + key = rearrange(key, "b (h c) t-> b h t c", h=self.n_heads) + value = rearrange(value, "b (h c) t-> b h t c", h=self.n_heads) + + query = self.query_rotary_pe(query) + key = self.key_rotary_pe(key) + + scores = torch.matmul(query, key.transpose(-2, -1)) / math.sqrt(self.k_channels) + + if self.proximal_bias: + assert t_s == t_t, "Proximal bias is only available for self-attention." + scores = scores + self._attention_bias_proximal(t_s).to(device=scores.device, dtype=scores.dtype) + if mask is not None: + scores = scores.masked_fill(mask == 0, -1e4) + p_attn = torch.nn.functional.softmax(scores, dim=-1) + p_attn = self.drop(p_attn) + output = torch.matmul(p_attn, value) + output = output.transpose(2, 3).contiguous().view(b, d, t_t) + return output, p_attn + + @staticmethod + def _attention_bias_proximal(length): + r = torch.arange(length, dtype=torch.float32) + diff = torch.unsqueeze(r, 0) - torch.unsqueeze(r, 1) + return torch.unsqueeze(torch.unsqueeze(-torch.log1p(torch.abs(diff)), 0), 0) + + +class FFN(nn.Module): + def __init__(self, in_channels, out_channels, filter_channels, kernel_size, p_dropout=0.0): + super().__init__() + self.in_channels = in_channels + self.out_channels = out_channels + self.filter_channels = filter_channels + self.kernel_size = kernel_size + self.p_dropout = p_dropout + + self.conv_1 = torch.nn.Conv1d(in_channels, filter_channels, kernel_size, padding=kernel_size // 2) + self.conv_2 = torch.nn.Conv1d(filter_channels, out_channels, kernel_size, padding=kernel_size // 2) + self.drop = torch.nn.Dropout(p_dropout) + + def forward(self, x, x_mask): + x = self.conv_1(x * x_mask) + x = torch.relu(x) + x = self.drop(x) + x = self.conv_2(x * x_mask) + return x * x_mask + + +class Encoder(nn.Module): + def __init__( + self, + hidden_channels, + filter_channels, + n_heads, + n_layers, + kernel_size=1, + p_dropout=0.0, + **kwargs, + ): + super().__init__() + self.hidden_channels = hidden_channels + self.filter_channels = filter_channels + self.n_heads = n_heads + self.n_layers = n_layers + self.kernel_size = kernel_size + self.p_dropout = p_dropout + + self.drop = torch.nn.Dropout(p_dropout) + self.attn_layers = torch.nn.ModuleList() + self.norm_layers_1 = torch.nn.ModuleList() + self.ffn_layers = torch.nn.ModuleList() + self.norm_layers_2 = torch.nn.ModuleList() + for _ in range(self.n_layers): + self.attn_layers.append(MultiHeadAttention(hidden_channels, hidden_channels, n_heads, p_dropout=p_dropout)) + self.norm_layers_1.append(LayerNorm(hidden_channels)) + self.ffn_layers.append( + FFN( + hidden_channels, + hidden_channels, + filter_channels, + kernel_size, + p_dropout=p_dropout, + ) + ) + self.norm_layers_2.append(LayerNorm(hidden_channels)) + + def forward(self, x, x_mask): + attn_mask = x_mask.unsqueeze(2) * x_mask.unsqueeze(-1) + for i in range(self.n_layers): + x = x * x_mask + y = self.attn_layers[i](x, x, attn_mask) + y = self.drop(y) + x = self.norm_layers_1[i](x + y) + y = self.ffn_layers[i](x, x_mask) + y = self.drop(y) + x = self.norm_layers_2[i](x + y) + x = x * x_mask + return x + + +class TextEncoder(nn.Module): + def __init__( + self, + encoder_type, + encoder_params, + duration_predictor_params, + n_vocab, + n_spks=1, + spk_emb_dim=128, + ): + super().__init__() + self.encoder_type = encoder_type + self.n_vocab = n_vocab + self.n_feats = encoder_params.n_feats + self.n_channels = encoder_params.n_channels + self.spk_emb_dim = spk_emb_dim + self.n_spks = n_spks + + self.emb = torch.nn.Embedding(n_vocab, self.n_channels) + torch.nn.init.normal_(self.emb.weight, 0.0, self.n_channels**-0.5) + + if encoder_params.prenet: + self.prenet = ConvReluNorm( + self.n_channels, + self.n_channels, + self.n_channels, + kernel_size=5, + n_layers=3, + p_dropout=0.5, + ) + else: + self.prenet = lambda x, x_mask: x + + self.encoder = Encoder( + encoder_params.n_channels + (spk_emb_dim if n_spks > 1 else 0), + encoder_params.filter_channels, + encoder_params.n_heads, + encoder_params.n_layers, + encoder_params.kernel_size, + encoder_params.p_dropout, + ) + + self.proj_m = torch.nn.Conv1d(self.n_channels + (spk_emb_dim if n_spks > 1 else 0), self.n_feats, 1) + self.proj_w = DurationPredictor( + self.n_channels + (spk_emb_dim if n_spks > 1 else 0), + duration_predictor_params.filter_channels_dp, + duration_predictor_params.kernel_size, + duration_predictor_params.p_dropout, + ) + + def forward(self, x, x_lengths, spks=None): + """Run forward pass to the transformer based encoder and duration predictor + + Args: + x (torch.Tensor): text input + shape: (batch_size, max_text_length) + x_lengths (torch.Tensor): text input lengths + shape: (batch_size,) + spks (torch.Tensor, optional): speaker ids. Defaults to None. + shape: (batch_size,) + + Returns: + mu (torch.Tensor): average output of the encoder + shape: (batch_size, n_feats, max_text_length) + logw (torch.Tensor): log duration predicted by the duration predictor + shape: (batch_size, 1, max_text_length) + x_mask (torch.Tensor): mask for the text input + shape: (batch_size, 1, max_text_length) + """ + x = self.emb(x) * math.sqrt(self.n_channels) + x = torch.transpose(x, 1, -1) + x_mask = torch.unsqueeze(sequence_mask(x_lengths, x.size(2)), 1).to(x.dtype) + + x = self.prenet(x, x_mask) + if self.n_spks > 1: + x = torch.cat([x, spks.unsqueeze(-1).repeat(1, 1, x.shape[-1])], dim=1) + x = self.encoder(x, x_mask) + mu = self.proj_m(x) * x_mask + + x_dp = torch.detach(x) + logw = self.proj_w(x_dp, x_mask) + + return mu, logw, x_mask diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/models/components/transformer.py b/matcha_inference_standalone/Matcha-TTS/matcha/models/components/transformer.py new file mode 100644 index 0000000000000000000000000000000000000000..4d604f56c675cf4985aa95237d9333807ba3fc85 --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/models/components/transformer.py @@ -0,0 +1,316 @@ +from typing import Any, Dict, Optional + +import torch +import torch.nn as nn # pylint: disable=consider-using-from-import +from diffusers.models.attention import ( + GEGLU, + GELU, + AdaLayerNorm, + AdaLayerNormZero, + ApproximateGELU, +) +from diffusers.models.attention_processor import Attention +from diffusers.models.lora import LoRACompatibleLinear +from diffusers.utils.torch_utils import maybe_allow_in_graph + + +class SnakeBeta(nn.Module): + """ + A modified Snake function which uses separate parameters for the magnitude of the periodic components + Shape: + - Input: (B, C, T) + - Output: (B, C, T), same shape as the input + Parameters: + - alpha - trainable parameter that controls frequency + - beta - trainable parameter that controls magnitude + References: + - This activation function is a modified version based on this paper by Liu Ziyin, Tilman Hartwig, Masahito Ueda: + https://arxiv.org/abs/2006.08195 + Examples: + >>> a1 = snakebeta(256) + >>> x = torch.randn(256) + >>> x = a1(x) + """ + + def __init__(self, in_features, out_features, alpha=1.0, alpha_trainable=True, alpha_logscale=True): + """ + Initialization. + INPUT: + - in_features: shape of the input + - alpha - trainable parameter that controls frequency + - beta - trainable parameter that controls magnitude + alpha is initialized to 1 by default, higher values = higher-frequency. + beta is initialized to 1 by default, higher values = higher-magnitude. + alpha will be trained along with the rest of your model. + """ + super().__init__() + self.in_features = out_features if isinstance(out_features, list) else [out_features] + self.proj = LoRACompatibleLinear(in_features, out_features) + + # initialize alpha + self.alpha_logscale = alpha_logscale + if self.alpha_logscale: # log scale alphas initialized to zeros + self.alpha = nn.Parameter(torch.zeros(self.in_features) * alpha) + self.beta = nn.Parameter(torch.zeros(self.in_features) * alpha) + else: # linear scale alphas initialized to ones + self.alpha = nn.Parameter(torch.ones(self.in_features) * alpha) + self.beta = nn.Parameter(torch.ones(self.in_features) * alpha) + + self.alpha.requires_grad = alpha_trainable + self.beta.requires_grad = alpha_trainable + + self.no_div_by_zero = 0.000000001 + + def forward(self, x): + """ + Forward pass of the function. + Applies the function to the input elementwise. + SnakeBeta ∶= x + 1/b * sin^2 (xa) + """ + x = self.proj(x) + if self.alpha_logscale: + alpha = torch.exp(self.alpha) + beta = torch.exp(self.beta) + else: + alpha = self.alpha + beta = self.beta + + x = x + (1.0 / (beta + self.no_div_by_zero)) * torch.pow(torch.sin(x * alpha), 2) + + return x + + +class FeedForward(nn.Module): + r""" + A feed-forward layer. + + Parameters: + dim (`int`): The number of channels in the input. + dim_out (`int`, *optional*): The number of channels in the output. If not given, defaults to `dim`. + mult (`int`, *optional*, defaults to 4): The multiplier to use for the hidden dimension. + dropout (`float`, *optional*, defaults to 0.0): The dropout probability to use. + activation_fn (`str`, *optional*, defaults to `"geglu"`): Activation function to be used in feed-forward. + final_dropout (`bool` *optional*, defaults to False): Apply a final dropout. + """ + + def __init__( + self, + dim: int, + dim_out: Optional[int] = None, + mult: int = 4, + dropout: float = 0.0, + activation_fn: str = "geglu", + final_dropout: bool = False, + ): + super().__init__() + inner_dim = int(dim * mult) + dim_out = dim_out if dim_out is not None else dim + + if activation_fn == "gelu": + act_fn = GELU(dim, inner_dim) + if activation_fn == "gelu-approximate": + act_fn = GELU(dim, inner_dim, approximate="tanh") + elif activation_fn == "geglu": + act_fn = GEGLU(dim, inner_dim) + elif activation_fn == "geglu-approximate": + act_fn = ApproximateGELU(dim, inner_dim) + elif activation_fn == "snakebeta": + act_fn = SnakeBeta(dim, inner_dim) + + self.net = nn.ModuleList([]) + # project in + self.net.append(act_fn) + # project dropout + self.net.append(nn.Dropout(dropout)) + # project out + self.net.append(LoRACompatibleLinear(inner_dim, dim_out)) + # FF as used in Vision Transformer, MLP-Mixer, etc. have a final dropout + if final_dropout: + self.net.append(nn.Dropout(dropout)) + + def forward(self, hidden_states): + for module in self.net: + hidden_states = module(hidden_states) + return hidden_states + + +@maybe_allow_in_graph +class BasicTransformerBlock(nn.Module): + r""" + A basic Transformer block. + + Parameters: + dim (`int`): The number of channels in the input and output. + num_attention_heads (`int`): The number of heads to use for multi-head attention. + attention_head_dim (`int`): The number of channels in each head. + dropout (`float`, *optional*, defaults to 0.0): The dropout probability to use. + cross_attention_dim (`int`, *optional*): The size of the encoder_hidden_states vector for cross attention. + only_cross_attention (`bool`, *optional*): + Whether to use only cross-attention layers. In this case two cross attention layers are used. + double_self_attention (`bool`, *optional*): + Whether to use two self-attention layers. In this case no cross attention layers are used. + activation_fn (`str`, *optional*, defaults to `"geglu"`): Activation function to be used in feed-forward. + num_embeds_ada_norm (: + obj: `int`, *optional*): The number of diffusion steps used during training. See `Transformer2DModel`. + attention_bias (: + obj: `bool`, *optional*, defaults to `False`): Configure if the attentions should contain a bias parameter. + """ + + def __init__( + self, + dim: int, + num_attention_heads: int, + attention_head_dim: int, + dropout=0.0, + cross_attention_dim: Optional[int] = None, + activation_fn: str = "geglu", + num_embeds_ada_norm: Optional[int] = None, + attention_bias: bool = False, + only_cross_attention: bool = False, + double_self_attention: bool = False, + upcast_attention: bool = False, + norm_elementwise_affine: bool = True, + norm_type: str = "layer_norm", + final_dropout: bool = False, + ): + super().__init__() + self.only_cross_attention = only_cross_attention + + self.use_ada_layer_norm_zero = (num_embeds_ada_norm is not None) and norm_type == "ada_norm_zero" + self.use_ada_layer_norm = (num_embeds_ada_norm is not None) and norm_type == "ada_norm" + + if norm_type in ("ada_norm", "ada_norm_zero") and num_embeds_ada_norm is None: + raise ValueError( + f"`norm_type` is set to {norm_type}, but `num_embeds_ada_norm` is not defined. Please make sure to" + f" define `num_embeds_ada_norm` if setting `norm_type` to {norm_type}." + ) + + # Define 3 blocks. Each block has its own normalization layer. + # 1. Self-Attn + if self.use_ada_layer_norm: + self.norm1 = AdaLayerNorm(dim, num_embeds_ada_norm) + elif self.use_ada_layer_norm_zero: + self.norm1 = AdaLayerNormZero(dim, num_embeds_ada_norm) + else: + self.norm1 = nn.LayerNorm(dim, elementwise_affine=norm_elementwise_affine) + self.attn1 = Attention( + query_dim=dim, + heads=num_attention_heads, + dim_head=attention_head_dim, + dropout=dropout, + bias=attention_bias, + cross_attention_dim=cross_attention_dim if only_cross_attention else None, + upcast_attention=upcast_attention, + ) + + # 2. Cross-Attn + if cross_attention_dim is not None or double_self_attention: + # We currently only use AdaLayerNormZero for self attention where there will only be one attention block. + # I.e. the number of returned modulation chunks from AdaLayerZero would not make sense if returned during + # the second cross attention block. + self.norm2 = ( + AdaLayerNorm(dim, num_embeds_ada_norm) + if self.use_ada_layer_norm + else nn.LayerNorm(dim, elementwise_affine=norm_elementwise_affine) + ) + self.attn2 = Attention( + query_dim=dim, + cross_attention_dim=cross_attention_dim if not double_self_attention else None, + heads=num_attention_heads, + dim_head=attention_head_dim, + dropout=dropout, + bias=attention_bias, + upcast_attention=upcast_attention, + # scale_qk=False, # uncomment this to not to use flash attention + ) # is self-attn if encoder_hidden_states is none + else: + self.norm2 = None + self.attn2 = None + + # 3. Feed-forward + self.norm3 = nn.LayerNorm(dim, elementwise_affine=norm_elementwise_affine) + self.ff = FeedForward(dim, dropout=dropout, activation_fn=activation_fn, final_dropout=final_dropout) + + # let chunk size default to None + self._chunk_size = None + self._chunk_dim = 0 + + def set_chunk_feed_forward(self, chunk_size: Optional[int], dim: int): + # Sets chunk feed-forward + self._chunk_size = chunk_size + self._chunk_dim = dim + + def forward( + self, + hidden_states: torch.FloatTensor, + attention_mask: Optional[torch.FloatTensor] = None, + encoder_hidden_states: Optional[torch.FloatTensor] = None, + encoder_attention_mask: Optional[torch.FloatTensor] = None, + timestep: Optional[torch.LongTensor] = None, + cross_attention_kwargs: Dict[str, Any] = None, + class_labels: Optional[torch.LongTensor] = None, + ): + # Notice that normalization is always applied before the real computation in the following blocks. + # 1. Self-Attention + if self.use_ada_layer_norm: + norm_hidden_states = self.norm1(hidden_states, timestep) + elif self.use_ada_layer_norm_zero: + norm_hidden_states, gate_msa, shift_mlp, scale_mlp, gate_mlp = self.norm1( + hidden_states, timestep, class_labels, hidden_dtype=hidden_states.dtype + ) + else: + norm_hidden_states = self.norm1(hidden_states) + + cross_attention_kwargs = cross_attention_kwargs if cross_attention_kwargs is not None else {} + + attn_output = self.attn1( + norm_hidden_states, + encoder_hidden_states=encoder_hidden_states if self.only_cross_attention else None, + attention_mask=encoder_attention_mask if self.only_cross_attention else attention_mask, + **cross_attention_kwargs, + ) + if self.use_ada_layer_norm_zero: + attn_output = gate_msa.unsqueeze(1) * attn_output + hidden_states = attn_output + hidden_states + + # 2. Cross-Attention + if self.attn2 is not None: + norm_hidden_states = ( + self.norm2(hidden_states, timestep) if self.use_ada_layer_norm else self.norm2(hidden_states) + ) + + attn_output = self.attn2( + norm_hidden_states, + encoder_hidden_states=encoder_hidden_states, + attention_mask=encoder_attention_mask, + **cross_attention_kwargs, + ) + hidden_states = attn_output + hidden_states + + # 3. Feed-forward + norm_hidden_states = self.norm3(hidden_states) + + if self.use_ada_layer_norm_zero: + norm_hidden_states = norm_hidden_states * (1 + scale_mlp[:, None]) + shift_mlp[:, None] + + if self._chunk_size is not None: + # "feed_forward_chunk_size" can be used to save memory + if norm_hidden_states.shape[self._chunk_dim] % self._chunk_size != 0: + raise ValueError( + f"`hidden_states` dimension to be chunked: {norm_hidden_states.shape[self._chunk_dim]} has to be divisible by chunk size: {self._chunk_size}. Make sure to set an appropriate `chunk_size` when calling `unet.enable_forward_chunking`." + ) + + num_chunks = norm_hidden_states.shape[self._chunk_dim] // self._chunk_size + ff_output = torch.cat( + [self.ff(hid_slice) for hid_slice in norm_hidden_states.chunk(num_chunks, dim=self._chunk_dim)], + dim=self._chunk_dim, + ) + else: + ff_output = self.ff(norm_hidden_states) + + if self.use_ada_layer_norm_zero: + ff_output = gate_mlp.unsqueeze(1) * ff_output + + hidden_states = ff_output + hidden_states + + return hidden_states diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/models/matcha_tts.py b/matcha_inference_standalone/Matcha-TTS/matcha/models/matcha_tts.py new file mode 100644 index 0000000000000000000000000000000000000000..c934e68650e0db7dddef841070a3c07796265025 --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/models/matcha_tts.py @@ -0,0 +1,241 @@ +import datetime as dt +import math +import random + +import torch + +import matcha.utils.monotonic_align as monotonic_align # pylint: disable=consider-using-from-import +from matcha import utils +from matcha.models.baselightningmodule import BaseLightningClass +from matcha.models.components.flow_matching import CFM +from matcha.models.components.text_encoder import TextEncoder +from matcha.utils.model import ( + denormalize, + duration_loss, + fix_len_compatibility, + generate_path, + sequence_mask, +) +class MatchaTTS(BaseLightningClass): # 🍵 + def __init__( + self, + n_vocab, + n_spks, + spk_emb_dim, + n_feats, + encoder, + decoder, + cfm, + data_statistics, + out_size, + optimizer=None, + scheduler=None, + prior_loss=True, + use_precomputed_durations=False, + ): + super().__init__() + + self.save_hyperparameters(logger=False) + + self.n_vocab = n_vocab + self.n_spks = n_spks + self.spk_emb_dim = spk_emb_dim + self.n_feats = n_feats + self.out_size = out_size + self.prior_loss = prior_loss + self.use_precomputed_durations = use_precomputed_durations + + if n_spks > 1: + self.spk_emb = torch.nn.Embedding(n_spks, spk_emb_dim) + + self.encoder = TextEncoder( + encoder.encoder_type, + encoder.encoder_params, + encoder.duration_predictor_params, + n_vocab, + n_spks, + spk_emb_dim, + ) + + self.decoder = CFM( + in_channels=2 * encoder.encoder_params.n_feats, + out_channel=encoder.encoder_params.n_feats, + cfm_params=cfm, + decoder_params=decoder, + n_spks=n_spks, + spk_emb_dim=spk_emb_dim, + ) + + self.update_data_statistics(data_statistics) + + @torch.inference_mode() + def synthesise(self, x, x_lengths, n_timesteps, temperature=1.0, spks=None, length_scale=1.0): + """ + Generates mel-spectrogram from text. Returns: + 1. encoder outputs + 2. decoder outputs + 3. generated alignment + + Args: + x (torch.Tensor): batch of texts, converted to a tensor with phoneme embedding ids. + shape: (batch_size, max_text_length) + x_lengths (torch.Tensor): lengths of texts in batch. + shape: (batch_size,) + n_timesteps (int): number of steps to use for reverse diffusion in decoder. + temperature (float, optional): controls variance of terminal distribution. + spks (bool, optional): speaker ids. + shape: (batch_size,) + length_scale (float, optional): controls speech pace. + Increase value to slow down generated speech and vice versa. + + Returns: + dict: { + "encoder_outputs": torch.Tensor, shape: (batch_size, n_feats, max_mel_length), + # Average mel spectrogram generated by the encoder + "decoder_outputs": torch.Tensor, shape: (batch_size, n_feats, max_mel_length), + # Refined mel spectrogram improved by the CFM + "attn": torch.Tensor, shape: (batch_size, max_text_length, max_mel_length), + # Alignment map between text and mel spectrogram + "mel": torch.Tensor, shape: (batch_size, n_feats, max_mel_length), + # Denormalized mel spectrogram + "mel_lengths": torch.Tensor, shape: (batch_size,), + # Lengths of mel spectrograms + "rtf": float, + # Real-time factor + } + """ + # For RTF computation + t = dt.datetime.now() + + if self.n_spks > 1: + # Get speaker embedding + spks = self.spk_emb(spks.long()) + + # Get encoder_outputs `mu_x` and log-scaled token durations `logw` + mu_x, logw, x_mask = self.encoder(x, x_lengths, spks) + + w = torch.exp(logw) * x_mask + w_ceil = torch.ceil(w) * length_scale + y_lengths = torch.clamp_min(torch.sum(w_ceil, [1, 2]), 1).long() + y_max_length = y_lengths.max() + y_max_length_ = fix_len_compatibility(y_max_length) + + # Using obtained durations `w` construct alignment map `attn` + y_mask = sequence_mask(y_lengths, y_max_length_).unsqueeze(1).to(x_mask.dtype) + attn_mask = x_mask.unsqueeze(-1) * y_mask.unsqueeze(2) + attn = generate_path(w_ceil.squeeze(1), attn_mask.squeeze(1)).unsqueeze(1) + + # Align encoded text and get mu_y + mu_y = torch.matmul(attn.squeeze(1).transpose(1, 2), mu_x.transpose(1, 2)) + mu_y = mu_y.transpose(1, 2) + encoder_outputs = mu_y[:, :, :y_max_length] + + # Generate sample tracing the probability flow + decoder_outputs = self.decoder(mu_y, y_mask, n_timesteps, temperature, spks) + decoder_outputs = decoder_outputs[:, :, :y_max_length] + + t = (dt.datetime.now() - t).total_seconds() + rtf = t * 22050 / (decoder_outputs.shape[-1] * 256) + + return { + "encoder_outputs": encoder_outputs, + "decoder_outputs": decoder_outputs, + "attn": attn[:, :, :y_max_length], + "mel": denormalize(decoder_outputs, self.mel_mean, self.mel_std), + "mel_lengths": y_lengths, + "rtf": rtf, + } + + def forward(self, x, x_lengths, y, y_lengths, spks=None, out_size=None, cond=None, durations=None): + """ + Computes 3 losses: + 1. duration loss: loss between predicted token durations and those extracted by Monotonic Alignment Search (MAS). + 2. prior loss: loss between mel-spectrogram and encoder outputs. + 3. flow matching loss: loss between mel-spectrogram and decoder outputs. + + Args: + x (torch.Tensor): batch of texts, converted to a tensor with phoneme embedding ids. + shape: (batch_size, max_text_length) + x_lengths (torch.Tensor): lengths of texts in batch. + shape: (batch_size,) + y (torch.Tensor): batch of corresponding mel-spectrograms. + shape: (batch_size, n_feats, max_mel_length) + y_lengths (torch.Tensor): lengths of mel-spectrograms in batch. + shape: (batch_size,) + out_size (int, optional): length (in mel's sampling rate) of segment to cut, on which decoder will be trained. + Should be divisible by 2^{num of UNet downsamplings}. Needed to increase batch size. + spks (torch.Tensor, optional): speaker ids. + shape: (batch_size,) + """ + if self.n_spks > 1: + # Get speaker embedding + spks = self.spk_emb(spks) + + # Get encoder_outputs `mu_x` and log-scaled token durations `logw` + mu_x, logw, x_mask = self.encoder(x, x_lengths, spks) + y_max_length = y.shape[-1] + + y_mask = sequence_mask(y_lengths, y_max_length).unsqueeze(1).to(x_mask) + attn_mask = x_mask.unsqueeze(-1) * y_mask.unsqueeze(2) + + if self.use_precomputed_durations: + attn = generate_path(durations.squeeze(1), attn_mask.squeeze(1)) + else: + # Use MAS to find most likely alignment `attn` between text and mel-spectrogram + with torch.no_grad(): + const = -0.5 * math.log(2 * math.pi) * self.n_feats + factor = -0.5 * torch.ones(mu_x.shape, dtype=mu_x.dtype, device=mu_x.device) + y_square = torch.matmul(factor.transpose(1, 2), y**2) + y_mu_double = torch.matmul(2.0 * (factor * mu_x).transpose(1, 2), y) + mu_square = torch.sum(factor * (mu_x**2), 1).unsqueeze(-1) + log_prior = y_square - y_mu_double + mu_square + const + + attn = monotonic_align.maximum_path(log_prior, attn_mask.squeeze(1)) + attn = attn.detach() # b, t_text, T_mel + + # Compute loss between predicted log-scaled durations and those obtained from MAS + # refered to as prior loss in the paper + logw_ = torch.log(1e-8 + torch.sum(attn.unsqueeze(1), -1)) * x_mask + dur_loss = duration_loss(logw, logw_, x_lengths) + + # Cut a small segment of mel-spectrogram in order to increase batch size + # - "Hack" taken from Grad-TTS, in case of Grad-TTS, we cannot train batch size 32 on a 24GB GPU without it + # - Do not need this hack for Matcha-TTS, but it works with it as well + if not isinstance(out_size, type(None)): + max_offset = (y_lengths - out_size).clamp(0) + offset_ranges = list(zip([0] * max_offset.shape[0], max_offset.cpu().numpy())) + out_offset = torch.LongTensor( + [torch.tensor(random.choice(range(start, end)) if end > start else 0) for start, end in offset_ranges] + ).to(y_lengths) + attn_cut = torch.zeros(attn.shape[0], attn.shape[1], out_size, dtype=attn.dtype, device=attn.device) + y_cut = torch.zeros(y.shape[0], self.n_feats, out_size, dtype=y.dtype, device=y.device) + + y_cut_lengths = [] + for i, (y_, out_offset_) in enumerate(zip(y, out_offset)): + y_cut_length = out_size + (y_lengths[i] - out_size).clamp(None, 0) + y_cut_lengths.append(y_cut_length) + cut_lower, cut_upper = out_offset_, out_offset_ + y_cut_length + y_cut[i, :, :y_cut_length] = y_[:, cut_lower:cut_upper] + attn_cut[i, :, :y_cut_length] = attn[i, :, cut_lower:cut_upper] + + y_cut_lengths = torch.LongTensor(y_cut_lengths) + y_cut_mask = sequence_mask(y_cut_lengths).unsqueeze(1).to(y_mask) + + attn = attn_cut + y = y_cut + y_mask = y_cut_mask + + # Align encoded text with mel-spectrogram and get mu_y segment + mu_y = torch.matmul(attn.squeeze(1).transpose(1, 2), mu_x.transpose(1, 2)) + mu_y = mu_y.transpose(1, 2) + + # Compute loss of the decoder + diff_loss, _ = self.decoder.compute_loss(x1=y, mask=y_mask, mu=mu_y, spks=spks, cond=cond) + + if self.prior_loss: + prior_loss = torch.sum(0.5 * ((y - mu_y) ** 2 + math.log(2 * math.pi)) * y_mask) + prior_loss = prior_loss / (torch.sum(y_mask) * self.n_feats) + else: + prior_loss = 0 + + return dur_loss, prior_loss, diff_loss, attn diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/text/__init__.py b/matcha_inference_standalone/Matcha-TTS/matcha/text/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..50d7b90bc45b527caa9a3c0709d6dde6719d8fb9 --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/text/__init__.py @@ -0,0 +1,57 @@ +""" from https://github.com/keithito/tacotron """ +from matcha.text import cleaners +from matcha.text.symbols import symbols + +# Mappings from symbol to numeric ID and vice versa: +_symbol_to_id = {s: i for i, s in enumerate(symbols)} +_id_to_symbol = {i: s for i, s in enumerate(symbols)} # pylint: disable=unnecessary-comprehension + + +class UnknownCleanerException(Exception): + pass + + +def text_to_sequence(text, cleaner_names): + """Converts a string of text to a sequence of IDs corresponding to the symbols in the text. + Args: + text: string to convert to a sequence + cleaner_names: names of the cleaner functions to run the text through + Returns: + List of integers corresponding to the symbols in the text + """ + sequence = [] + + clean_text = _clean_text(text, cleaner_names) + for symbol in clean_text: + symbol_id = _symbol_to_id[symbol] + sequence += [symbol_id] + return sequence, clean_text + + +def cleaned_text_to_sequence(cleaned_text): + """Converts a string of text to a sequence of IDs corresponding to the symbols in the text. + Args: + text: string to convert to a sequence + Returns: + List of integers corresponding to the symbols in the text + """ + sequence = [_symbol_to_id[symbol] for symbol in cleaned_text] + return sequence + + +def sequence_to_text(sequence): + """Converts a sequence of IDs back to a string""" + result = "" + for symbol_id in sequence: + s = _id_to_symbol[symbol_id] + result += s + return result + + +def _clean_text(text, cleaner_names): + for name in cleaner_names: + cleaner = getattr(cleaners, name) + if not cleaner: + raise UnknownCleanerException(f"Unknown cleaner: {name}") + text = cleaner(text) + return text diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/text/cleaners.py b/matcha_inference_standalone/Matcha-TTS/matcha/text/cleaners.py new file mode 100644 index 0000000000000000000000000000000000000000..12e5034b35884f43836332e56a30e2ebdfcf9d82 --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/text/cleaners.py @@ -0,0 +1,174 @@ +""" from https://github.com/keithito/tacotron + +Cleaners are transformations that run over the input text at both training and eval time. + +Cleaners can be selected by passing a comma-delimited list of cleaner names as the "cleaners" +hyperparameter. Some cleaners are English-specific. You'll typically want to use: + 1. "english_cleaners" for English text + 2. "transliteration_cleaners" for non-English text that can be transliterated to ASCII using + the Unidecode library (https://pypi.python.org/pypi/Unidecode) + 3. "basic_cleaners" if you do not want to transliterate (in this case, you should also update + the symbols in symbols.py to match your data). +""" + +import logging +import re +import platform +import phonemizer +from unidecode import unidecode +from underthesea import text_normalize +from num2words import num2words + +# To avoid excessive logging we set the log level of the phonemizer package to Critical +critical_logger = logging.getLogger("phonemizer") +critical_logger.setLevel(logging.CRITICAL) + +# Intializing the phonemizer globally significantly reduces the speed +global_phonemizer = phonemizer.backend.EspeakBackend( + language="en-us", + preserve_punctuation=True, + with_stress=True, + language_switch="remove-flags", + logger=critical_logger, +) + +_ESPEAK_VI = None + +# Regular expression matching whitespace: +_whitespace_re = re.compile(r"\s+") + +# Remove brackets +_brackets_re = re.compile(r"[\[\]\(\)\{\}]") + +# List of (regular expression, replacement) pairs for abbreviations: +_abbreviations = [ + (re.compile(f"\\b{x[0]}\\.", re.IGNORECASE), x[1]) + for x in [ + ("mrs", "misess"), + ("mr", "mister"), + ("dr", "doctor"), + ("st", "saint"), + ("co", "company"), + ("jr", "junior"), + ("maj", "major"), + ("gen", "general"), + ("drs", "doctors"), + ("rev", "reverend"), + ("lt", "lieutenant"), + ("hon", "honorable"), + ("sgt", "sergeant"), + ("capt", "captain"), + ("esq", "esquire"), + ("ltd", "limited"), + ("col", "colonel"), + ("ft", "fort"), + ] +] + + +def expand_abbreviations(text): + for regex, replacement in _abbreviations: + text = re.sub(regex, replacement, text) + return text + + +def lowercase(text): + return text.lower() + + +def remove_brackets(text): + return re.sub(_brackets_re, "", text) + + +def collapse_whitespace(text): + return re.sub(_whitespace_re, " ", text) + + +def convert_to_ascii(text): + return unidecode(text) + + +def basic_cleaners(text): + """Basic pipeline that lowercases and collapses whitespace without transliteration.""" + text = lowercase(text) + text = collapse_whitespace(text) + return text + + +def transliteration_cleaners(text): + """Pipeline for non-English text that transliterates to ASCII.""" + text = convert_to_ascii(text) + text = lowercase(text) + text = collapse_whitespace(text) + return text + + +def english_cleaners2(text): + """Pipeline for English text, including abbreviation expansion. + punctuation + stress""" + text = convert_to_ascii(text) + text = lowercase(text) + text = expand_abbreviations(text) + phonemes = global_phonemizer.phonemize([text], strip=True, njobs=1)[0] + # Added in some cases espeak is not removing brackets + phonemes = remove_brackets(phonemes) + phonemes = collapse_whitespace(phonemes) + return phonemes + + +def ipa_simplifier(text): + replacements = [ + ("ɐ", "ə"), + ("ˈə", "ə"), + ("ʤ", "dʒ"), + ("ʧ", "tʃ"), + ("ᵻ", "ɪ"), + ] + for replacement in replacements: + text = text.replace(replacement[0], replacement[1]) + phonemes = collapse_whitespace(text) + return phonemes + + +_NAM_20xx = re.compile(r"^20\d{2}$") +_CHU_SO = re.compile(r"^\d+$") + + +def basic_cleaners_vi_female(text: str) -> str: + """normalize then phonemize for Vietnamese female voice""" + global _ESPEAK_VI + if _ESPEAK_VI is None: + if platform.system().lower() == "windows" and not phonemizer.backend.EspeakBackend.is_available(): + from phonemizer.backend.espeak.wrapper import EspeakWrapper + EspeakWrapper.set_library(r"C:\Program Files\eSpeak NG\libespeak-ng.dll") + _ESPEAK_VI = phonemizer.backend.EspeakBackend( + "vi", + preserve_punctuation=True, + language_switch="remove-flags", + with_stress=True, + tie=True, + logger=critical_logger + ) + + txt = text_normalize(text).replace("-", " ") + text_list = [] + for word in txt.split(): + if word == "%": + text_list.extend(["phần", "trăm"]) + elif word == "&": + text_list.append("và") + elif _NAM_20xx.match(word) is not None: + num = "hai ngàn không trăm " + num2words(int(word[-2:]), lang="vi") + text_list.extend(num.split(" ")) + elif _CHU_SO.match(word) is not None: + num = num2words(int(word), lang="vi").replace("nghìn", "ngàn") + text_list.extend(num.split(" ")) + elif word in ".,;!?": + if text_list: + text_list[-1] += word + else: + text_list.append(word) + else: + text_list.append(word) + + ipa_list = _ESPEAK_VI.phonemize(text_list, strip=True) + return " ".join(ipa_list).strip() diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/text/numbers.py b/matcha_inference_standalone/Matcha-TTS/matcha/text/numbers.py new file mode 100644 index 0000000000000000000000000000000000000000..f99a8686dcb73532091122613e74bd643a8a327f --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/text/numbers.py @@ -0,0 +1,71 @@ +""" from https://github.com/keithito/tacotron """ + +import re + +import inflect + +_inflect = inflect.engine() +_comma_number_re = re.compile(r"([0-9][0-9\,]+[0-9])") +_decimal_number_re = re.compile(r"([0-9]+\.[0-9]+)") +_pounds_re = re.compile(r"£([0-9\,]*[0-9]+)") +_dollars_re = re.compile(r"\$([0-9\.\,]*[0-9]+)") +_ordinal_re = re.compile(r"[0-9]+(st|nd|rd|th)") +_number_re = re.compile(r"[0-9]+") + + +def _remove_commas(m): + return m.group(1).replace(",", "") + + +def _expand_decimal_point(m): + return m.group(1).replace(".", " point ") + + +def _expand_dollars(m): + match = m.group(1) + parts = match.split(".") + if len(parts) > 2: + return match + " dollars" + dollars = int(parts[0]) if parts[0] else 0 + cents = int(parts[1]) if len(parts) > 1 and parts[1] else 0 + if dollars and cents: + dollar_unit = "dollar" if dollars == 1 else "dollars" + cent_unit = "cent" if cents == 1 else "cents" + return f"{dollars} {dollar_unit}, {cents} {cent_unit}" + elif dollars: + dollar_unit = "dollar" if dollars == 1 else "dollars" + return f"{dollars} {dollar_unit}" + elif cents: + cent_unit = "cent" if cents == 1 else "cents" + return f"{cents} {cent_unit}" + else: + return "zero dollars" + + +def _expand_ordinal(m): + return _inflect.number_to_words(m.group(0)) + + +def _expand_number(m): + num = int(m.group(0)) + if num > 1000 and num < 3000: + if num == 2000: + return "two thousand" + elif num > 2000 and num < 2010: + return "two thousand " + _inflect.number_to_words(num % 100) + elif num % 100 == 0: + return _inflect.number_to_words(num // 100) + " hundred" + else: + return _inflect.number_to_words(num, andword="", zero="oh", group=2).replace(", ", " ") + else: + return _inflect.number_to_words(num, andword="") + + +def normalize_numbers(text): + text = re.sub(_comma_number_re, _remove_commas, text) + text = re.sub(_pounds_re, r"\1 pounds", text) + text = re.sub(_dollars_re, _expand_dollars, text) + text = re.sub(_decimal_number_re, _expand_decimal_point, text) + text = re.sub(_ordinal_re, _expand_ordinal, text) + text = re.sub(_number_re, _expand_number, text) + return text diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/text/symbols.py b/matcha_inference_standalone/Matcha-TTS/matcha/text/symbols.py new file mode 100644 index 0000000000000000000000000000000000000000..50ade0c5ee4a8e7428bdb0b4d0d8b88acabd75aa --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/text/symbols.py @@ -0,0 +1,243 @@ +"""this script, specific to vietnamese, only exist to replace Matcha-TTS/text/symbols.py""" + +_pad = "_" +_punctuation = [ + chr(59), # ; + chr(58), # : + chr(44), # , + chr(46), # . + chr(33), # ! + chr(63), # ? + chr(161), # ¡ + chr(191), # ¿ + chr(45), # - + chr(8212), # — + chr(8230), # … + chr(39), # ' + chr(34), # " + chr(171), # « + chr(187), # » + chr(8220), # “ + chr(8221), # ” + chr(32), # space +] +_letters = [ + chr(97), # a + chr(225), # á + chr(7843), # ả + chr(224), # à + chr(227), # ã + chr(7841), # ạ + chr(226), # â + chr(7845), # ấ + chr(7849), # ẩ + chr(7847), # ầ + chr(7851), # ẫ + chr(7853), # ậ + chr(259), # ă + chr(7855), # ắ + chr(7859), # ẳ + chr(7857), # ằ + chr(7861), # ẵ + chr(7863), # ặ + chr(98), # b + chr(99), # c + chr(100), # d + chr(273), # đ + chr(101), # e + chr(233), # é + chr(7867), # ẻ + chr(232), # è + chr(7869), # ẽ + chr(7865), # ẹ + chr(234), # ê + chr(7871), # ế + chr(7875), # ể + chr(7873), # ề + chr(7877), # ễ + chr(7879), # ệ + chr(102), # f + chr(103), # g + chr(104), # h + chr(105), # i + chr(237), # í + chr(7881), # ỉ + chr(236), # ì + chr(297), # ĩ + chr(7883), # ị + chr(106), # j + chr(107), # k + chr(108), # l + chr(109), # m + chr(110), # n + chr(111), # o + chr(243), # ó + chr(7887), # ỏ + chr(242), # ò + chr(245), # õ + chr(7885), # ọ + chr(244), # ô + chr(7889), # ố + chr(7893), # ổ + chr(7895), # ỗ + chr(7897), # ộ + chr(417), # ơ + chr(7899), # ớ + chr(7903), # ở + chr(7901), # ờ + chr(7905), # ỡ + chr(7907), # ợ + chr(112), # p + chr(113), # q + chr(114), # r + chr(115), # s + chr(116), # t + chr(117), # u + chr(250), # ú + chr(7911), # ủ + chr(249), # ù + chr(361), # ũ + chr(7909), # ụ + chr(432), # ư + chr(7913), # ứ + chr(7917), # ử + chr(7915), # ừ + chr(7919), # ữ + chr(7921), # ự + chr(118), # v + chr(119), # w + chr(120), # x + chr(121), # y + chr(253), # ý + chr(7927), # ỷ + chr(7923), # ỳ + chr(7929), # ỹ + chr(7925), # ỵ + chr(122), # z + chr(48), # 0 + chr(49), # 1 + chr(50), # 2 + chr(51), # 3 + chr(52), # 4 + chr(53), # 5 + chr(54), # 6 + chr(55), # 7 + chr(56), # 8 + chr(57), # 9 +] +_letters_ipa = [ + chr(593), # ɑ + chr(592), # ɐ + chr(594), # ɒ + chr(230), # æ + chr(595), # ɓ + chr(665), # ʙ + chr(946), # β + chr(596), # ɔ + chr(597), # ɕ + chr(231), # ç + chr(599), # ɗ + chr(598), # ɖ + chr(240), # ð + chr(676), # ʤ + chr(601), # ə + chr(600), # ɘ + chr(602), # ɚ + chr(603), # ɛ + chr(604), # ɜ + chr(605), # ɝ + chr(606), # ɞ + chr(607), # ɟ + chr(644), # ʄ + chr(609), # ɡ + chr(608), # ɠ + chr(610), # ɢ + chr(667), # ʛ + chr(614), # ɦ + chr(615), # ɧ + chr(295), # ħ + chr(613), # ɥ + chr(668), # ʜ + chr(616), # ɨ + chr(618), # ɪ + chr(669), # ʝ + chr(621), # ɭ + chr(620), # ɬ + chr(619), # ɫ + chr(622), # ɮ + chr(671), # ʟ + chr(625), # ɱ + chr(623), # ɯ + chr(624), # ɰ + chr(331), # ŋ + chr(627), # ɳ + chr(626), # ɲ + chr(628), # ɴ + chr(248), # ø + chr(629), # ɵ + chr(632), # ɸ + chr(952), # θ + chr(339), # œ + chr(630), # ɶ + chr(664), # ʘ + chr(633), # ɹ + chr(634), # ɺ + chr(638), # ɾ + chr(635), # ɻ + chr(640), # ʀ + chr(641), # ʁ + chr(637), # ɽ + chr(642), # ʂ + chr(643), # ʃ + chr(648), # ʈ + chr(649), # ʉ + chr(650), # ʊ + chr(651), # ʋ + chr(11377), # ⱱ + chr(652), # ʌ + chr(611), # ɣ + chr(612), # ɤ + chr(653), # ʍ + chr(967), # χ + chr(654), # ʎ + chr(655), # ʏ + chr(657), # ʑ + chr(656), # ʐ + chr(658), # ʒ + chr(660), # ʔ + chr(673), # ʡ + chr(661), # ʕ + chr(674), # ʢ + chr(448), # ǀ + chr(449), # ǁ + chr(450), # ǂ + chr(451), # ǃ + chr(712), # ˈ + chr(716), # ˌ + chr(720), # ː + chr(721), # ˑ + chr(700), # ʼ + chr(692), # ʴ + chr(688), # ʰ + chr(689), # ʱ + chr(690), # ʲ + chr(695), # ʷ + chr(736), # ˠ + chr(740), # ˤ + chr(734), # ˞ + chr(8595), # ↓ + chr(8593), # ↑ + chr(8594), # → + chr(8599), # ↗ + chr(8600), # ↘ + chr(809), # ̩ + chr(7547), # ᵻ + chr(810), # ̪ + chr(865), # ͡ +] + +# Export all symbols: +symbols = [_pad] + _punctuation + _letters + _letters_ipa + +# Special symbol ids +SPACE_ID = symbols.index(" ") diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/utils/__init__.py b/matcha_inference_standalone/Matcha-TTS/matcha/utils/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..4fc74ee841a9fdb391f107352c658ad795e4ede1 --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/utils/__init__.py @@ -0,0 +1 @@ +from matcha.utils.utils import * diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/utils/audio.py b/matcha_inference_standalone/Matcha-TTS/matcha/utils/audio.py new file mode 100644 index 0000000000000000000000000000000000000000..d257f0d652822851714c47826dc4b1b69fb09fcd --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/utils/audio.py @@ -0,0 +1,82 @@ +import numpy as np +import torch +import torch.utils.data +from librosa.filters import mel as librosa_mel_fn +from scipy.io.wavfile import read + +MAX_WAV_VALUE = 32768.0 + + +def load_wav(full_path): + sampling_rate, data = read(full_path) + return data, sampling_rate + + +def dynamic_range_compression(x, C=1, clip_val=1e-5): + return np.log(np.clip(x, a_min=clip_val, a_max=None) * C) + + +def dynamic_range_decompression(x, C=1): + return np.exp(x) / C + + +def dynamic_range_compression_torch(x, C=1, clip_val=1e-5): + return torch.log(torch.clamp(x, min=clip_val) * C) + + +def dynamic_range_decompression_torch(x, C=1): + return torch.exp(x) / C + + +def spectral_normalize_torch(magnitudes): + output = dynamic_range_compression_torch(magnitudes) + return output + + +def spectral_de_normalize_torch(magnitudes): + output = dynamic_range_decompression_torch(magnitudes) + return output + + +mel_basis = {} +hann_window = {} + + +def mel_spectrogram(y, n_fft, num_mels, sampling_rate, hop_size, win_size, fmin, fmax, center=False): + if torch.min(y) < -1.0: + print("min value is ", torch.min(y)) + if torch.max(y) > 1.0: + print("max value is ", torch.max(y)) + + global mel_basis, hann_window # pylint: disable=global-statement,global-variable-not-assigned + if f"{str(fmax)}_{str(y.device)}" not in mel_basis: + mel = librosa_mel_fn(sr=sampling_rate, n_fft=n_fft, n_mels=num_mels, fmin=fmin, fmax=fmax) + mel_basis[str(fmax) + "_" + str(y.device)] = torch.from_numpy(mel).float().to(y.device) + hann_window[str(y.device)] = torch.hann_window(win_size).to(y.device) + + y = torch.nn.functional.pad( + y.unsqueeze(1), (int((n_fft - hop_size) / 2), int((n_fft - hop_size) / 2)), mode="reflect" + ) + y = y.squeeze(1) + + spec = torch.view_as_real( + torch.stft( + y, + n_fft, + hop_length=hop_size, + win_length=win_size, + window=hann_window[str(y.device)], + center=center, + pad_mode="reflect", + normalized=False, + onesided=True, + return_complex=True, + ) + ) + + spec = torch.sqrt(spec.pow(2).sum(-1) + (1e-9)) + + spec = torch.matmul(mel_basis[str(fmax) + "_" + str(y.device)], spec) + spec = spectral_normalize_torch(spec) + + return spec diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/utils/model.py b/matcha_inference_standalone/Matcha-TTS/matcha/utils/model.py new file mode 100644 index 0000000000000000000000000000000000000000..869cc6092f5952930534c47544fae88308e96abf --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/utils/model.py @@ -0,0 +1,90 @@ +""" from https://github.com/jaywalnut310/glow-tts """ + +import numpy as np +import torch + + +def sequence_mask(length, max_length=None): + if max_length is None: + max_length = length.max() + x = torch.arange(max_length, dtype=length.dtype, device=length.device) + return x.unsqueeze(0) < length.unsqueeze(1) + + +def fix_len_compatibility(length, num_downsamplings_in_unet=2): + factor = torch.scalar_tensor(2).pow(num_downsamplings_in_unet) + length = (length / factor).ceil() * factor + if not torch.onnx.is_in_onnx_export(): + return length.int().item() + else: + return length + + +def convert_pad_shape(pad_shape): + inverted_shape = pad_shape[::-1] + pad_shape = [item for sublist in inverted_shape for item in sublist] + return pad_shape + + +def generate_path(duration, mask): + device = duration.device + + b, t_x, t_y = mask.shape + cum_duration = torch.cumsum(duration, 1) + path = torch.zeros(b, t_x, t_y, dtype=mask.dtype).to(device=device) + + cum_duration_flat = cum_duration.view(b * t_x) + path = sequence_mask(cum_duration_flat, t_y).to(mask.dtype) + path = path.view(b, t_x, t_y) + path = path - torch.nn.functional.pad(path, convert_pad_shape([[0, 0], [1, 0], [0, 0]]))[:, :-1] + path = path * mask + return path + + +def duration_loss(logw, logw_, lengths): + loss = torch.sum((logw - logw_) ** 2) / torch.sum(lengths) + return loss + + +def normalize(data, mu, std): + if not isinstance(mu, (float, int)): + if isinstance(mu, list): + mu = torch.tensor(mu, dtype=data.dtype, device=data.device) + elif isinstance(mu, torch.Tensor): + mu = mu.to(data.device) + elif isinstance(mu, np.ndarray): + mu = torch.from_numpy(mu).to(data.device) + mu = mu.unsqueeze(-1) + + if not isinstance(std, (float, int)): + if isinstance(std, list): + std = torch.tensor(std, dtype=data.dtype, device=data.device) + elif isinstance(std, torch.Tensor): + std = std.to(data.device) + elif isinstance(std, np.ndarray): + std = torch.from_numpy(std).to(data.device) + std = std.unsqueeze(-1) + + return (data - mu) / std + + +def denormalize(data, mu, std): + if not isinstance(mu, float): + if isinstance(mu, list): + mu = torch.tensor(mu, dtype=data.dtype, device=data.device) + elif isinstance(mu, torch.Tensor): + mu = mu.to(data.device) + elif isinstance(mu, np.ndarray): + mu = torch.from_numpy(mu).to(data.device) + mu = mu.unsqueeze(-1) + + if not isinstance(std, float): + if isinstance(std, list): + std = torch.tensor(std, dtype=data.dtype, device=data.device) + elif isinstance(std, torch.Tensor): + std = std.to(data.device) + elif isinstance(std, np.ndarray): + std = torch.from_numpy(std).to(data.device) + std = std.unsqueeze(-1) + + return data * std + mu diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/utils/monotonic_align/__init__.py b/matcha_inference_standalone/Matcha-TTS/matcha/utils/monotonic_align/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..eee6e0d47c2e3612ef02bc17442e6886998e5a94 --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/utils/monotonic_align/__init__.py @@ -0,0 +1,22 @@ +import numpy as np +import torch + +from matcha.utils.monotonic_align.core import maximum_path_c + + +def maximum_path(value, mask): + """Cython optimised version. + value: [b, t_x, t_y] + mask: [b, t_x, t_y] + """ + value = value * mask + device = value.device + dtype = value.dtype + value = value.data.cpu().numpy().astype(np.float32) + path = np.zeros_like(value).astype(np.int32) + mask = mask.data.cpu().numpy() + + t_x_max = mask.sum(1)[:, 0].astype(np.int32) + t_y_max = mask.sum(2)[:, 0].astype(np.int32) + maximum_path_c(path, value, t_x_max, t_y_max) + return torch.from_numpy(path).to(device=device, dtype=dtype) diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/utils/monotonic_align/core.c b/matcha_inference_standalone/Matcha-TTS/matcha/utils/monotonic_align/core.c new file mode 100644 index 0000000000000000000000000000000000000000..10afd8ed40cfc74c0884bafc55f8f41ba0e3f9b0 --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/utils/monotonic_align/core.c @@ -0,0 +1,29878 @@ +/* Generated by Cython 3.2.5 */ + +/* BEGIN: Cython Metadata +{ + "distutils": { + "depends": [], + "name": "matcha.utils.monotonic_align.core", + "sources": [ + "matcha/utils/monotonic_align/core.pyx" + ] + }, + "module_name": "matcha.utils.monotonic_align.core" +} +END: Cython Metadata */ + +#ifndef PY_SSIZE_T_CLEAN +#define PY_SSIZE_T_CLEAN +#endif /* PY_SSIZE_T_CLEAN */ +/* InitLimitedAPI */ +#if defined(Py_LIMITED_API) + #if !defined(CYTHON_LIMITED_API) + #define CYTHON_LIMITED_API 1 + #endif +#elif defined(CYTHON_LIMITED_API) + #ifdef _MSC_VER + #pragma message ("Limited API usage is enabled with 'CYTHON_LIMITED_API' but 'Py_LIMITED_API' does not define a Python target version. Consider setting 'Py_LIMITED_API' instead.") + #else + #warning Limited API usage is enabled with 'CYTHON_LIMITED_API' but 'Py_LIMITED_API' does not define a Python target version. Consider setting 'Py_LIMITED_API' instead. + #endif +#endif + +#include "Python.h" +#ifndef Py_PYTHON_H + #error Python headers needed to compile C extensions, please install development version of Python. +#elif PY_VERSION_HEX < 0x03080000 + #error Cython requires Python 3.8+. +#else +#define __PYX_ABI_VERSION "3_2_5" +#define CYTHON_HEX_VERSION 0x030205F0 +#define CYTHON_FUTURE_DIVISION 1 +/* CModulePreamble */ +#include +#ifndef offsetof + #define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) +#endif +#if !defined(_WIN32) && !defined(WIN32) && !defined(MS_WINDOWS) + #ifndef __stdcall + #define __stdcall + #endif + #ifndef __cdecl + #define __cdecl + #endif + #ifndef __fastcall + #define __fastcall + #endif +#endif +#ifndef DL_IMPORT + #define DL_IMPORT(t) t +#endif +#ifndef DL_EXPORT + #define DL_EXPORT(t) t +#endif +#define __PYX_COMMA , +#ifndef PY_LONG_LONG + #define PY_LONG_LONG LONG_LONG +#endif +#ifndef Py_HUGE_VAL + #define Py_HUGE_VAL HUGE_VAL +#endif +#define __PYX_LIMITED_VERSION_HEX PY_VERSION_HEX +#if defined(GRAALVM_PYTHON) + /* For very preliminary testing purposes. Most variables are set the same as PyPy. + The existence of this section does not imply that anything works or is even tested */ + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_LIMITED_API 0 + #define CYTHON_COMPILING_IN_GRAAL 1 + #define CYTHON_COMPILING_IN_CPYTHON_FREETHREADING 0 + #undef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 0 + #undef CYTHON_USE_TYPE_SPECS + #define CYTHON_USE_TYPE_SPECS 0 + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #undef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 0 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #undef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 1 + #undef CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS + #define CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS 0 + #undef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 0 + #undef CYTHON_ASSUME_SAFE_SIZE + #define CYTHON_ASSUME_SAFE_SIZE 0 + #undef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 0 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_GIL + #define CYTHON_FAST_GIL 0 + #undef CYTHON_METH_FASTCALL + #define CYTHON_METH_FASTCALL 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #ifndef CYTHON_PEP487_INIT_SUBCLASS + #define CYTHON_PEP487_INIT_SUBCLASS 1 + #endif + #undef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 1 + #undef CYTHON_USE_MODULE_STATE + #define CYTHON_USE_MODULE_STATE 0 + #undef CYTHON_USE_SYS_MONITORING + #define CYTHON_USE_SYS_MONITORING 0 + #undef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 0 + #undef CYTHON_USE_AM_SEND + #define CYTHON_USE_AM_SEND 0 + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 1 + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC 0 + #endif + #undef CYTHON_USE_FREELISTS + #define CYTHON_USE_FREELISTS 0 + #undef CYTHON_IMMORTAL_CONSTANTS + #define CYTHON_IMMORTAL_CONSTANTS 0 +#elif defined(PYPY_VERSION) + #define CYTHON_COMPILING_IN_PYPY 1 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_LIMITED_API 0 + #define CYTHON_COMPILING_IN_GRAAL 0 + #define CYTHON_COMPILING_IN_CPYTHON_FREETHREADING 0 + #undef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #ifndef CYTHON_USE_TYPE_SPECS + #define CYTHON_USE_TYPE_SPECS 0 + #endif + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #undef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 0 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #undef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 1 + #undef CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS + #define CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS 1 + #undef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 0 + #ifndef CYTHON_ASSUME_SAFE_SIZE + #define CYTHON_ASSUME_SAFE_SIZE 1 + #endif + #undef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 0 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_GIL + #define CYTHON_FAST_GIL 0 + #undef CYTHON_METH_FASTCALL + #define CYTHON_METH_FASTCALL 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #ifndef CYTHON_PEP487_INIT_SUBCLASS + #define CYTHON_PEP487_INIT_SUBCLASS 1 + #endif + #if PY_VERSION_HEX < 0x03090000 + #undef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 0 + #elif !defined(CYTHON_PEP489_MULTI_PHASE_INIT) + #define CYTHON_PEP489_MULTI_PHASE_INIT 1 + #endif + #undef CYTHON_USE_MODULE_STATE + #define CYTHON_USE_MODULE_STATE 0 + #undef CYTHON_USE_SYS_MONITORING + #define CYTHON_USE_SYS_MONITORING 0 + #ifndef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE (PYPY_VERSION_NUM >= 0x07030C00) + #endif + #undef CYTHON_USE_AM_SEND + #define CYTHON_USE_AM_SEND 0 + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC (PYPY_VERSION_NUM >= 0x07031100) + #endif + #undef CYTHON_USE_FREELISTS + #define CYTHON_USE_FREELISTS 0 + #undef CYTHON_IMMORTAL_CONSTANTS + #define CYTHON_IMMORTAL_CONSTANTS 0 +#elif defined(CYTHON_LIMITED_API) + #ifdef Py_LIMITED_API + #undef __PYX_LIMITED_VERSION_HEX + #define __PYX_LIMITED_VERSION_HEX Py_LIMITED_API + #endif + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_LIMITED_API 1 + #define CYTHON_COMPILING_IN_GRAAL 0 + #define CYTHON_COMPILING_IN_CPYTHON_FREETHREADING 0 + #undef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 0 + #undef CYTHON_USE_TYPE_SPECS + #define CYTHON_USE_TYPE_SPECS 1 + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #undef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 0 + #ifndef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #endif + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS + #define CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS 0 + #endif + #undef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 0 + #undef CYTHON_ASSUME_SAFE_SIZE + #define CYTHON_ASSUME_SAFE_SIZE 0 + #undef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 0 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_GIL + #define CYTHON_FAST_GIL 0 + #undef CYTHON_METH_FASTCALL + #define CYTHON_METH_FASTCALL (__PYX_LIMITED_VERSION_HEX >= 0x030C0000) + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #ifndef CYTHON_PEP487_INIT_SUBCLASS + #define CYTHON_PEP487_INIT_SUBCLASS 1 + #endif + #ifndef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 1 + #endif + #ifndef CYTHON_USE_MODULE_STATE + #define CYTHON_USE_MODULE_STATE 0 + #endif + #undef CYTHON_USE_SYS_MONITORING + #define CYTHON_USE_SYS_MONITORING 0 + #ifndef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 0 + #endif + #ifndef CYTHON_USE_AM_SEND + #define CYTHON_USE_AM_SEND (__PYX_LIMITED_VERSION_HEX >= 0x030A0000) + #endif + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC 0 + #endif + #ifndef CYTHON_USE_FREELISTS + #define CYTHON_USE_FREELISTS 1 + #endif + #undef CYTHON_IMMORTAL_CONSTANTS + #define CYTHON_IMMORTAL_CONSTANTS 0 +#else + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_CPYTHON 1 + #define CYTHON_COMPILING_IN_LIMITED_API 0 + #define CYTHON_COMPILING_IN_GRAAL 0 + #ifdef Py_GIL_DISABLED + #define CYTHON_COMPILING_IN_CPYTHON_FREETHREADING 1 + #else + #define CYTHON_COMPILING_IN_CPYTHON_FREETHREADING 0 + #endif + #if PY_VERSION_HEX < 0x030A0000 + #undef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #elif !defined(CYTHON_USE_TYPE_SLOTS) + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #ifndef CYTHON_USE_TYPE_SPECS + #define CYTHON_USE_TYPE_SPECS 0 + #endif + #ifndef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 1 + #endif + #ifndef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 1 + #endif + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #elif !defined(CYTHON_USE_PYLIST_INTERNALS) + #define CYTHON_USE_PYLIST_INTERNALS 1 + #endif + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING || PY_VERSION_HEX >= 0x030B00A2 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #elif !defined(CYTHON_USE_UNICODE_WRITER) + #define CYTHON_USE_UNICODE_WRITER 1 + #endif + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + #undef CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS + #define CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS 1 + #elif !defined(CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS) + #define CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_ASSUME_SAFE_SIZE + #define CYTHON_ASSUME_SAFE_SIZE 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #ifndef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 1 + #endif + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + #undef CYTHON_FAST_GIL + #define CYTHON_FAST_GIL 0 + #elif !defined(CYTHON_FAST_GIL) + #define CYTHON_FAST_GIL (PY_VERSION_HEX < 0x030C00A6) + #endif + #ifndef CYTHON_METH_FASTCALL + #define CYTHON_METH_FASTCALL 1 + #endif + #ifndef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 1 + #endif + #ifndef CYTHON_PEP487_INIT_SUBCLASS + #define CYTHON_PEP487_INIT_SUBCLASS 1 + #endif + #ifndef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 1 + #endif + #ifndef CYTHON_USE_MODULE_STATE + #define CYTHON_USE_MODULE_STATE 0 + #endif + #ifndef CYTHON_USE_SYS_MONITORING + #define CYTHON_USE_SYS_MONITORING (PY_VERSION_HEX >= 0x030d00B1) + #endif + #ifndef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 1 + #endif + #ifndef CYTHON_USE_AM_SEND + #define CYTHON_USE_AM_SEND 1 + #endif + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #elif !defined(CYTHON_USE_DICT_VERSIONS) + #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX < 0x030C00A5 && !CYTHON_USE_MODULE_STATE) + #endif + #ifndef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 1 + #endif + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC 1 + #endif + #ifndef CYTHON_USE_FREELISTS + #define CYTHON_USE_FREELISTS (!CYTHON_COMPILING_IN_CPYTHON_FREETHREADING) + #endif + #if defined(CYTHON_IMMORTAL_CONSTANTS) && PY_VERSION_HEX < 0x030C0000 + #undef CYTHON_IMMORTAL_CONSTANTS + #define CYTHON_IMMORTAL_CONSTANTS 0 // definitely won't work + #elif !defined(CYTHON_IMMORTAL_CONSTANTS) + #define CYTHON_IMMORTAL_CONSTANTS (PY_VERSION_HEX >= 0x030C0000 && !CYTHON_USE_MODULE_STATE && CYTHON_COMPILING_IN_CPYTHON_FREETHREADING) + #endif +#endif +#ifndef CYTHON_COMPRESS_STRINGS + #define CYTHON_COMPRESS_STRINGS 1 +#endif +#ifndef CYTHON_FAST_PYCCALL +#define CYTHON_FAST_PYCCALL CYTHON_FAST_PYCALL +#endif +#ifndef CYTHON_VECTORCALL +#if CYTHON_COMPILING_IN_LIMITED_API +#define CYTHON_VECTORCALL (__PYX_LIMITED_VERSION_HEX >= 0x030C0000) +#else +#define CYTHON_VECTORCALL (CYTHON_FAST_PYCCALL) +#endif +#endif +#if CYTHON_USE_PYLONG_INTERNALS + #undef SHIFT + #undef BASE + #undef MASK + #ifdef SIZEOF_VOID_P + enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) }; + #endif +#endif +#ifndef __has_attribute + #define __has_attribute(x) 0 +#endif +#ifndef __has_cpp_attribute + #define __has_cpp_attribute(x) 0 +#endif +#ifndef CYTHON_RESTRICT + #if defined(__GNUC__) + #define CYTHON_RESTRICT __restrict__ + #elif defined(_MSC_VER) && _MSC_VER >= 1400 + #define CYTHON_RESTRICT __restrict + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define CYTHON_RESTRICT restrict + #else + #define CYTHON_RESTRICT + #endif +#endif +#ifndef CYTHON_UNUSED + #if defined(__cplusplus) + /* for clang __has_cpp_attribute(maybe_unused) is true even before C++17 + * but leads to warnings with -pedantic, since it is a C++17 feature */ + #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) + #if __has_cpp_attribute(maybe_unused) + #define CYTHON_UNUSED [[maybe_unused]] + #endif + #endif + #endif +#endif +#ifndef CYTHON_UNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +#endif +#ifndef CYTHON_UNUSED_VAR +# if defined(__cplusplus) + template void CYTHON_UNUSED_VAR( const T& ) { } +# else +# define CYTHON_UNUSED_VAR(x) (void)(x) +# endif +#endif +#ifndef CYTHON_MAYBE_UNUSED_VAR + #define CYTHON_MAYBE_UNUSED_VAR(x) CYTHON_UNUSED_VAR(x) +#endif +#ifndef CYTHON_NCP_UNUSED +# if CYTHON_COMPILING_IN_CPYTHON && !CYTHON_COMPILING_IN_CPYTHON_FREETHREADING +# define CYTHON_NCP_UNUSED +# else +# define CYTHON_NCP_UNUSED CYTHON_UNUSED +# endif +#endif +#ifndef CYTHON_USE_CPP_STD_MOVE + #if defined(__cplusplus) && (\ + __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600)) + #define CYTHON_USE_CPP_STD_MOVE 1 + #else + #define CYTHON_USE_CPP_STD_MOVE 0 + #endif +#endif +#define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None) +#include +typedef uintptr_t __pyx_uintptr_t; +#ifndef CYTHON_FALLTHROUGH + #if defined(__cplusplus) + /* for clang __has_cpp_attribute(fallthrough) is true even before C++17 + * but leads to warnings with -pedantic, since it is a C++17 feature */ + #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) + #if __has_cpp_attribute(fallthrough) + #define CYTHON_FALLTHROUGH [[fallthrough]] + #endif + #endif + #ifndef CYTHON_FALLTHROUGH + #if __has_cpp_attribute(clang::fallthrough) + #define CYTHON_FALLTHROUGH [[clang::fallthrough]] + #elif __has_cpp_attribute(gnu::fallthrough) + #define CYTHON_FALLTHROUGH [[gnu::fallthrough]] + #endif + #endif + #endif + #ifndef CYTHON_FALLTHROUGH + #if __has_attribute(fallthrough) + #define CYTHON_FALLTHROUGH __attribute__((fallthrough)) + #else + #define CYTHON_FALLTHROUGH + #endif + #endif + #if defined(__clang__) && defined(__apple_build_version__) + #if __apple_build_version__ < 7000000 + #undef CYTHON_FALLTHROUGH + #define CYTHON_FALLTHROUGH + #endif + #endif +#endif +#ifndef Py_UNREACHABLE + #define Py_UNREACHABLE() assert(0); abort() +#endif +#ifdef __cplusplus + template + struct __PYX_IS_UNSIGNED_IMPL {static const bool value = T(0) < T(-1);}; + #define __PYX_IS_UNSIGNED(type) (__PYX_IS_UNSIGNED_IMPL::value) +#else + #define __PYX_IS_UNSIGNED(type) (((type)-1) > 0) +#endif +#if CYTHON_COMPILING_IN_PYPY == 1 + #define __PYX_NEED_TP_PRINT_SLOT (PY_VERSION_HEX < 0x030A0000) +#else + #define __PYX_NEED_TP_PRINT_SLOT (PY_VERSION_HEX < 0x03090000) +#endif +#define __PYX_REINTERPRET_FUNCION(func_pointer, other_pointer) ((func_pointer)(void(*)(void))(other_pointer)) + +/* CInitCode */ +#ifndef CYTHON_INLINE + #if defined(__clang__) + #define CYTHON_INLINE __inline__ __attribute__ ((__unused__)) + #elif defined(__GNUC__) + #define CYTHON_INLINE __inline__ + #elif defined(_MSC_VER) + #define CYTHON_INLINE __inline + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define CYTHON_INLINE inline + #else + #define CYTHON_INLINE + #endif +#endif + +/* PythonCompatibility */ +#define __PYX_BUILD_PY_SSIZE_T "n" +#define CYTHON_FORMAT_SSIZE_T "z" +#define __Pyx_BUILTIN_MODULE_NAME "builtins" +#define __Pyx_DefaultClassType PyType_Type +#if CYTHON_COMPILING_IN_LIMITED_API + #ifndef CO_OPTIMIZED + static int CO_OPTIMIZED; + #endif + #ifndef CO_NEWLOCALS + static int CO_NEWLOCALS; + #endif + #ifndef CO_VARARGS + static int CO_VARARGS; + #endif + #ifndef CO_VARKEYWORDS + static int CO_VARKEYWORDS; + #endif + #ifndef CO_ASYNC_GENERATOR + static int CO_ASYNC_GENERATOR; + #endif + #ifndef CO_GENERATOR + static int CO_GENERATOR; + #endif + #ifndef CO_COROUTINE + static int CO_COROUTINE; + #endif +#else + #ifndef CO_COROUTINE + #define CO_COROUTINE 0x80 + #endif + #ifndef CO_ASYNC_GENERATOR + #define CO_ASYNC_GENERATOR 0x200 + #endif +#endif +static int __Pyx_init_co_variables(void); +#if PY_VERSION_HEX >= 0x030900A4 || defined(Py_IS_TYPE) + #define __Pyx_IS_TYPE(ob, type) Py_IS_TYPE(ob, type) +#else + #define __Pyx_IS_TYPE(ob, type) (((const PyObject*)ob)->ob_type == (type)) +#endif +#if PY_VERSION_HEX >= 0x030A00B1 || defined(Py_Is) + #define __Pyx_Py_Is(x, y) Py_Is(x, y) +#else + #define __Pyx_Py_Is(x, y) ((x) == (y)) +#endif +#if PY_VERSION_HEX >= 0x030A00B1 || defined(Py_IsNone) + #define __Pyx_Py_IsNone(ob) Py_IsNone(ob) +#else + #define __Pyx_Py_IsNone(ob) __Pyx_Py_Is((ob), Py_None) +#endif +#if PY_VERSION_HEX >= 0x030A00B1 || defined(Py_IsTrue) + #define __Pyx_Py_IsTrue(ob) Py_IsTrue(ob) +#else + #define __Pyx_Py_IsTrue(ob) __Pyx_Py_Is((ob), Py_True) +#endif +#if PY_VERSION_HEX >= 0x030A00B1 || defined(Py_IsFalse) + #define __Pyx_Py_IsFalse(ob) Py_IsFalse(ob) +#else + #define __Pyx_Py_IsFalse(ob) __Pyx_Py_Is((ob), Py_False) +#endif +#define __Pyx_NoneAsNull(obj) (__Pyx_Py_IsNone(obj) ? NULL : (obj)) +#if PY_VERSION_HEX >= 0x030900F0 && !CYTHON_COMPILING_IN_PYPY + #define __Pyx_PyObject_GC_IsFinalized(o) PyObject_GC_IsFinalized(o) +#else + #define __Pyx_PyObject_GC_IsFinalized(o) _PyGC_FINALIZED(o) +#endif +#ifndef Py_TPFLAGS_CHECKTYPES + #define Py_TPFLAGS_CHECKTYPES 0 +#endif +#ifndef Py_TPFLAGS_HAVE_INDEX + #define Py_TPFLAGS_HAVE_INDEX 0 +#endif +#ifndef Py_TPFLAGS_HAVE_NEWBUFFER + #define Py_TPFLAGS_HAVE_NEWBUFFER 0 +#endif +#ifndef Py_TPFLAGS_HAVE_FINALIZE + #define Py_TPFLAGS_HAVE_FINALIZE 0 +#endif +#ifndef Py_TPFLAGS_SEQUENCE + #define Py_TPFLAGS_SEQUENCE 0 +#endif +#ifndef Py_TPFLAGS_MAPPING + #define Py_TPFLAGS_MAPPING 0 +#endif +#ifndef Py_TPFLAGS_IMMUTABLETYPE + #define Py_TPFLAGS_IMMUTABLETYPE (1UL << 8) +#endif +#ifndef Py_TPFLAGS_DISALLOW_INSTANTIATION + #define Py_TPFLAGS_DISALLOW_INSTANTIATION (1UL << 7) +#endif +#ifndef METH_STACKLESS + #define METH_STACKLESS 0 +#endif +#ifndef METH_FASTCALL + #ifndef METH_FASTCALL + #define METH_FASTCALL 0x80 + #endif + typedef PyObject *(*__Pyx_PyCFunctionFast) (PyObject *self, PyObject *const *args, Py_ssize_t nargs); + typedef PyObject *(*__Pyx_PyCFunctionFastWithKeywords) (PyObject *self, PyObject *const *args, + Py_ssize_t nargs, PyObject *kwnames); +#else + #if PY_VERSION_HEX >= 0x030d00A4 + # define __Pyx_PyCFunctionFast PyCFunctionFast + # define __Pyx_PyCFunctionFastWithKeywords PyCFunctionFastWithKeywords + #else + # define __Pyx_PyCFunctionFast _PyCFunctionFast + # define __Pyx_PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords + #endif +#endif +#if CYTHON_METH_FASTCALL + #define __Pyx_METH_FASTCALL METH_FASTCALL + #define __Pyx_PyCFunction_FastCall __Pyx_PyCFunctionFast + #define __Pyx_PyCFunction_FastCallWithKeywords __Pyx_PyCFunctionFastWithKeywords +#else + #define __Pyx_METH_FASTCALL METH_VARARGS + #define __Pyx_PyCFunction_FastCall PyCFunction + #define __Pyx_PyCFunction_FastCallWithKeywords PyCFunctionWithKeywords +#endif +#if CYTHON_VECTORCALL + #define __pyx_vectorcallfunc vectorcallfunc + #define __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET PY_VECTORCALL_ARGUMENTS_OFFSET + #define __Pyx_PyVectorcall_NARGS(n) PyVectorcall_NARGS((size_t)(n)) +#else + #define __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET 0 + #define __Pyx_PyVectorcall_NARGS(n) ((Py_ssize_t)(n)) +#endif +#if PY_VERSION_HEX >= 0x030900B1 +#define __Pyx_PyCFunction_CheckExact(func) PyCFunction_CheckExact(func) +#else +#define __Pyx_PyCFunction_CheckExact(func) PyCFunction_Check(func) +#endif +#define __Pyx_CyOrPyCFunction_Check(func) PyCFunction_Check(func) +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_CyOrPyCFunction_GET_FUNCTION(func) (((PyCFunctionObject*)(func))->m_ml->ml_meth) +#elif !CYTHON_COMPILING_IN_LIMITED_API +#define __Pyx_CyOrPyCFunction_GET_FUNCTION(func) PyCFunction_GET_FUNCTION(func) +#endif +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_CyOrPyCFunction_GET_FLAGS(func) (((PyCFunctionObject*)(func))->m_ml->ml_flags) +static CYTHON_INLINE PyObject* __Pyx_CyOrPyCFunction_GET_SELF(PyObject *func) { + return (__Pyx_CyOrPyCFunction_GET_FLAGS(func) & METH_STATIC) ? NULL : ((PyCFunctionObject*)func)->m_self; +} +#endif +static CYTHON_INLINE int __Pyx__IsSameCFunction(PyObject *func, void (*cfunc)(void)) { +#if CYTHON_COMPILING_IN_LIMITED_API + return PyCFunction_Check(func) && PyCFunction_GetFunction(func) == (PyCFunction) cfunc; +#else + return PyCFunction_Check(func) && PyCFunction_GET_FUNCTION(func) == (PyCFunction) cfunc; +#endif +} +#define __Pyx_IsSameCFunction(func, cfunc) __Pyx__IsSameCFunction(func, cfunc) +#if PY_VERSION_HEX < 0x03090000 || (CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030A0000) + #define __Pyx_PyType_FromModuleAndSpec(m, s, b) ((void)m, PyType_FromSpecWithBases(s, b)) + typedef PyObject *(*__Pyx_PyCMethod)(PyObject *, PyTypeObject *, PyObject *const *, size_t, PyObject *); +#else + #define __Pyx_PyType_FromModuleAndSpec(m, s, b) PyType_FromModuleAndSpec(m, s, b) + #define __Pyx_PyCMethod PyCMethod +#endif +#ifndef METH_METHOD + #define METH_METHOD 0x200 +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) + #define PyObject_Malloc(s) PyMem_Malloc(s) + #define PyObject_Free(p) PyMem_Free(p) + #define PyObject_Realloc(p) PyMem_Realloc(p) +#endif +#if CYTHON_COMPILING_IN_LIMITED_API + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) +#elif CYTHON_COMPILING_IN_GRAAL && defined(GRAALPY_VERSION_NUM) && GRAALPY_VERSION_NUM > 0x19000000 + #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) GraalPyFrame_SetLineNumber((frame), (lineno)) +#elif CYTHON_COMPILING_IN_GRAAL + #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) _PyFrame_SetLineNumber((frame), (lineno)) +#else + #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) (frame)->f_lineno = (lineno) +#endif +#if CYTHON_COMPILING_IN_LIMITED_API + #define __Pyx_PyThreadState_Current PyThreadState_Get() +#elif !CYTHON_FAST_THREAD_STATE + #define __Pyx_PyThreadState_Current PyThreadState_GET() +#elif PY_VERSION_HEX >= 0x030d00A1 + #define __Pyx_PyThreadState_Current PyThreadState_GetUnchecked() +#else + #define __Pyx_PyThreadState_Current _PyThreadState_UncheckedGet() +#endif +#if CYTHON_USE_MODULE_STATE +static CYTHON_INLINE void *__Pyx__PyModule_GetState(PyObject *op) +{ + void *result; + result = PyModule_GetState(op); + if (!result) + Py_FatalError("Couldn't find the module state"); + return result; +} +#define __Pyx_PyModule_GetState(o) (__pyx_mstatetype *)__Pyx__PyModule_GetState(o) +#else +#define __Pyx_PyModule_GetState(op) ((void)op,__pyx_mstate_global) +#endif +#define __Pyx_PyObject_GetSlot(obj, name, func_ctype) __Pyx_PyType_GetSlot(Py_TYPE((PyObject *) obj), name, func_ctype) +#define __Pyx_PyObject_TryGetSlot(obj, name, func_ctype) __Pyx_PyType_TryGetSlot(Py_TYPE(obj), name, func_ctype) +#define __Pyx_PyObject_GetSubSlot(obj, sub, name, func_ctype) __Pyx_PyType_GetSubSlot(Py_TYPE(obj), sub, name, func_ctype) +#define __Pyx_PyObject_TryGetSubSlot(obj, sub, name, func_ctype) __Pyx_PyType_TryGetSubSlot(Py_TYPE(obj), sub, name, func_ctype) +#if CYTHON_USE_TYPE_SLOTS + #define __Pyx_PyType_GetSlot(type, name, func_ctype) ((type)->name) + #define __Pyx_PyType_TryGetSlot(type, name, func_ctype) __Pyx_PyType_GetSlot(type, name, func_ctype) + #define __Pyx_PyType_GetSubSlot(type, sub, name, func_ctype) (((type)->sub) ? ((type)->sub->name) : NULL) + #define __Pyx_PyType_TryGetSubSlot(type, sub, name, func_ctype) __Pyx_PyType_GetSubSlot(type, sub, name, func_ctype) +#else + #define __Pyx_PyType_GetSlot(type, name, func_ctype) ((func_ctype) PyType_GetSlot((type), Py_##name)) + #define __Pyx_PyType_TryGetSlot(type, name, func_ctype)\ + ((__PYX_LIMITED_VERSION_HEX >= 0x030A0000 ||\ + (PyType_GetFlags(type) & Py_TPFLAGS_HEAPTYPE) || __Pyx_get_runtime_version() >= 0x030A0000) ?\ + __Pyx_PyType_GetSlot(type, name, func_ctype) : NULL) + #define __Pyx_PyType_GetSubSlot(obj, sub, name, func_ctype) __Pyx_PyType_GetSlot(obj, name, func_ctype) + #define __Pyx_PyType_TryGetSubSlot(obj, sub, name, func_ctype) __Pyx_PyType_TryGetSlot(obj, name, func_ctype) +#endif +#if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized) +#define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n)) +#else +#define __Pyx_PyDict_NewPresized(n) PyDict_New() +#endif +#define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) +#define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) +#if CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_UNICODE_INTERNALS +#define __Pyx_PyDict_GetItemStrWithError(dict, name) _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash) +static CYTHON_INLINE PyObject * __Pyx_PyDict_GetItemStr(PyObject *dict, PyObject *name) { + PyObject *res = __Pyx_PyDict_GetItemStrWithError(dict, name); + if (res == NULL) PyErr_Clear(); + return res; +} +#elif !CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07020000 +#define __Pyx_PyDict_GetItemStrWithError PyDict_GetItemWithError +#define __Pyx_PyDict_GetItemStr PyDict_GetItem +#else +static CYTHON_INLINE PyObject * __Pyx_PyDict_GetItemStrWithError(PyObject *dict, PyObject *name) { +#if CYTHON_COMPILING_IN_PYPY + return PyDict_GetItem(dict, name); +#else + PyDictEntry *ep; + PyDictObject *mp = (PyDictObject*) dict; + long hash = ((PyStringObject *) name)->ob_shash; + assert(hash != -1); + ep = (mp->ma_lookup)(mp, name, hash); + if (ep == NULL) { + return NULL; + } + return ep->me_value; +#endif +} +#define __Pyx_PyDict_GetItemStr PyDict_GetItem +#endif +#if CYTHON_USE_TYPE_SLOTS + #define __Pyx_PyType_GetFlags(tp) (((PyTypeObject *)tp)->tp_flags) + #define __Pyx_PyType_HasFeature(type, feature) ((__Pyx_PyType_GetFlags(type) & (feature)) != 0) +#else + #define __Pyx_PyType_GetFlags(tp) (PyType_GetFlags((PyTypeObject *)tp)) + #define __Pyx_PyType_HasFeature(type, feature) PyType_HasFeature(type, feature) +#endif +#define __Pyx_PyObject_GetIterNextFunc(iterator) __Pyx_PyObject_GetSlot(iterator, tp_iternext, iternextfunc) +#if CYTHON_USE_TYPE_SPECS +#define __Pyx_PyHeapTypeObject_GC_Del(obj) {\ + PyTypeObject *type = Py_TYPE((PyObject*)obj);\ + assert(__Pyx_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE));\ + PyObject_GC_Del(obj);\ + Py_DECREF(type);\ +} +#else +#define __Pyx_PyHeapTypeObject_GC_Del(obj) PyObject_GC_Del(obj) +#endif +#if CYTHON_COMPILING_IN_LIMITED_API + #define __Pyx_PyUnicode_READY(op) (0) + #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_ReadChar(u, i) + #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((void)u, 1114111U) + #define __Pyx_PyUnicode_KIND(u) ((void)u, (0)) + #define __Pyx_PyUnicode_DATA(u) ((void*)u) + #define __Pyx_PyUnicode_READ(k, d, i) ((void)k, PyUnicode_ReadChar((PyObject*)(d), i)) + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GetLength(u)) +#else + #if PY_VERSION_HEX >= 0x030C0000 + #define __Pyx_PyUnicode_READY(op) (0) + #else + #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ + 0 : _PyUnicode_Ready((PyObject *)(op))) + #endif + #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) + #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) + #define __Pyx_PyUnicode_KIND(u) ((int)PyUnicode_KIND(u)) + #define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u) + #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) + #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, (Py_UCS4) ch) + #if PY_VERSION_HEX >= 0x030C0000 + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_LENGTH(u)) + #else + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03090000 + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : ((PyCompactUnicodeObject *)(u))->wstr_length)) + #else + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) + #endif + #endif +#endif +#if CYTHON_COMPILING_IN_PYPY + #define __Pyx_PyUnicode_Concat(a, b) PyNumber_Add(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) PyNumber_Add(a, b) +#else + #define __Pyx_PyUnicode_Concat(a, b) PyUnicode_Concat(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ?\ + PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b)) +#endif +#if CYTHON_COMPILING_IN_PYPY + #if !defined(PyUnicode_DecodeUnicodeEscape) + #define PyUnicode_DecodeUnicodeEscape(s, size, errors) PyUnicode_Decode(s, size, "unicode_escape", errors) + #endif + #if !defined(PyUnicode_Contains) + #define PyUnicode_Contains(u, s) PySequence_Contains(u, s) + #endif + #if !defined(PyByteArray_Check) + #define PyByteArray_Check(obj) PyObject_TypeCheck(obj, &PyByteArray_Type) + #endif + #if !defined(PyObject_Format) + #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt) + #endif +#endif +#define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyUnicode_Check(b) && !PyUnicode_CheckExact(b)))) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b)) +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000 + #define __Pyx_PySequence_ListKeepNew(obj)\ + (likely(PyList_CheckExact(obj) && PyUnstable_Object_IsUniquelyReferenced(obj)) ? __Pyx_NewRef(obj) : PySequence_List(obj)) +#elif CYTHON_COMPILING_IN_CPYTHON + #define __Pyx_PySequence_ListKeepNew(obj)\ + (likely(PyList_CheckExact(obj) && Py_REFCNT(obj) == 1) ? __Pyx_NewRef(obj) : PySequence_List(obj)) +#else + #define __Pyx_PySequence_ListKeepNew(obj) PySequence_List(obj) +#endif +#ifndef PySet_CheckExact + #define PySet_CheckExact(obj) __Pyx_IS_TYPE(obj, &PySet_Type) +#endif +#if PY_VERSION_HEX >= 0x030900A4 + #define __Pyx_SET_REFCNT(obj, refcnt) Py_SET_REFCNT(obj, refcnt) + #define __Pyx_SET_SIZE(obj, size) Py_SET_SIZE(obj, size) +#else + #define __Pyx_SET_REFCNT(obj, refcnt) Py_REFCNT(obj) = (refcnt) + #define __Pyx_SET_SIZE(obj, size) Py_SIZE(obj) = (size) +#endif +enum __Pyx_ReferenceSharing { + __Pyx_ReferenceSharing_DefinitelyUnique, // We created it so we know it's unshared - no need to check + __Pyx_ReferenceSharing_OwnStrongReference, + __Pyx_ReferenceSharing_FunctionArgument, + __Pyx_ReferenceSharing_SharedReference, // Never trust it to be unshared because it's a global or similar +}; +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING && PY_VERSION_HEX >= 0x030E0000 +#define __Pyx_IS_UNIQUELY_REFERENCED(o, sharing)\ + (sharing == __Pyx_ReferenceSharing_DefinitelyUnique ? 1 :\ + (sharing == __Pyx_ReferenceSharing_FunctionArgument ? PyUnstable_Object_IsUniqueReferencedTemporary(o) :\ + (sharing == __Pyx_ReferenceSharing_OwnStrongReference ? PyUnstable_Object_IsUniquelyReferenced(o) : 0))) +#elif (CYTHON_COMPILING_IN_CPYTHON && !CYTHON_COMPILING_IN_CPYTHON_FREETHREADING) || CYTHON_COMPILING_IN_LIMITED_API +#define __Pyx_IS_UNIQUELY_REFERENCED(o, sharing) (((void)sharing), Py_REFCNT(o) == 1) +#else +#define __Pyx_IS_UNIQUELY_REFERENCED(o, sharing) (((void)o), ((void)sharing), 0) +#endif +#if CYTHON_AVOID_BORROWED_REFS || CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS + #if __PYX_LIMITED_VERSION_HEX >= 0x030d0000 + #define __Pyx_PyList_GetItemRef(o, i) PyList_GetItemRef(o, i) + #elif CYTHON_COMPILING_IN_LIMITED_API || !CYTHON_ASSUME_SAFE_MACROS + #define __Pyx_PyList_GetItemRef(o, i) (likely((i) >= 0) ? PySequence_GetItem(o, i) : (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL)) + #else + #define __Pyx_PyList_GetItemRef(o, i) PySequence_ITEM(o, i) + #endif +#elif CYTHON_COMPILING_IN_LIMITED_API || !CYTHON_ASSUME_SAFE_MACROS + #if __PYX_LIMITED_VERSION_HEX >= 0x030d0000 + #define __Pyx_PyList_GetItemRef(o, i) PyList_GetItemRef(o, i) + #else + #define __Pyx_PyList_GetItemRef(o, i) __Pyx_XNewRef(PyList_GetItem(o, i)) + #endif +#else + #define __Pyx_PyList_GetItemRef(o, i) __Pyx_NewRef(PyList_GET_ITEM(o, i)) +#endif +#if CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS && !CYTHON_COMPILING_IN_LIMITED_API && CYTHON_ASSUME_SAFE_MACROS + #define __Pyx_PyList_GetItemRefFast(o, i, unsafe_shared) (__Pyx_IS_UNIQUELY_REFERENCED(o, unsafe_shared) ?\ + __Pyx_NewRef(PyList_GET_ITEM(o, i)) : __Pyx_PyList_GetItemRef(o, i)) +#else + #define __Pyx_PyList_GetItemRefFast(o, i, unsafe_shared) __Pyx_PyList_GetItemRef(o, i) +#endif +#if __PYX_LIMITED_VERSION_HEX >= 0x030d0000 +#define __Pyx_PyDict_GetItemRef(dict, key, result) PyDict_GetItemRef(dict, key, result) +#elif CYTHON_AVOID_BORROWED_REFS || CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS +static CYTHON_INLINE int __Pyx_PyDict_GetItemRef(PyObject *dict, PyObject *key, PyObject **result) { + *result = PyObject_GetItem(dict, key); + if (*result == NULL) { + if (PyErr_ExceptionMatches(PyExc_KeyError)) { + PyErr_Clear(); + return 0; + } + return -1; + } + return 1; +} +#else +static CYTHON_INLINE int __Pyx_PyDict_GetItemRef(PyObject *dict, PyObject *key, PyObject **result) { + *result = PyDict_GetItemWithError(dict, key); + if (*result == NULL) { + return PyErr_Occurred() ? -1 : 0; + } + Py_INCREF(*result); + return 1; +} +#endif +#if defined(CYTHON_DEBUG_VISIT_CONST) && CYTHON_DEBUG_VISIT_CONST + #define __Pyx_VISIT_CONST(obj) Py_VISIT(obj) +#else + #define __Pyx_VISIT_CONST(obj) +#endif +#if CYTHON_ASSUME_SAFE_MACROS + #define __Pyx_PySequence_ITEM(o, i) PySequence_ITEM(o, i) + #define __Pyx_PySequence_SIZE(seq) Py_SIZE(seq) + #define __Pyx_PyTuple_SET_ITEM(o, i, v) (PyTuple_SET_ITEM(o, i, v), (0)) + #define __Pyx_PyTuple_GET_ITEM(o, i) PyTuple_GET_ITEM(o, i) + #define __Pyx_PyList_SET_ITEM(o, i, v) (PyList_SET_ITEM(o, i, v), (0)) + #define __Pyx_PyList_GET_ITEM(o, i) PyList_GET_ITEM(o, i) +#else + #define __Pyx_PySequence_ITEM(o, i) PySequence_GetItem(o, i) + #define __Pyx_PySequence_SIZE(seq) PySequence_Size(seq) + #define __Pyx_PyTuple_SET_ITEM(o, i, v) PyTuple_SetItem(o, i, v) + #define __Pyx_PyTuple_GET_ITEM(o, i) PyTuple_GetItem(o, i) + #define __Pyx_PyList_SET_ITEM(o, i, v) PyList_SetItem(o, i, v) + #define __Pyx_PyList_GET_ITEM(o, i) PyList_GetItem(o, i) +#endif +#if CYTHON_ASSUME_SAFE_SIZE + #define __Pyx_PyTuple_GET_SIZE(o) PyTuple_GET_SIZE(o) + #define __Pyx_PyList_GET_SIZE(o) PyList_GET_SIZE(o) + #define __Pyx_PySet_GET_SIZE(o) PySet_GET_SIZE(o) + #define __Pyx_PyBytes_GET_SIZE(o) PyBytes_GET_SIZE(o) + #define __Pyx_PyByteArray_GET_SIZE(o) PyByteArray_GET_SIZE(o) + #define __Pyx_PyUnicode_GET_LENGTH(o) PyUnicode_GET_LENGTH(o) +#else + #define __Pyx_PyTuple_GET_SIZE(o) PyTuple_Size(o) + #define __Pyx_PyList_GET_SIZE(o) PyList_Size(o) + #define __Pyx_PySet_GET_SIZE(o) PySet_Size(o) + #define __Pyx_PyBytes_GET_SIZE(o) PyBytes_Size(o) + #define __Pyx_PyByteArray_GET_SIZE(o) PyByteArray_Size(o) + #define __Pyx_PyUnicode_GET_LENGTH(o) PyUnicode_GetLength(o) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_InternFromString) + #define PyUnicode_InternFromString(s) PyUnicode_FromString(s) +#endif +#define __Pyx_PyLong_FromHash_t PyLong_FromSsize_t +#define __Pyx_PyLong_AsHash_t __Pyx_PyIndex_AsSsize_t +#if __PYX_LIMITED_VERSION_HEX >= 0x030A0000 + #define __Pyx_PySendResult PySendResult +#else + typedef enum { + PYGEN_RETURN = 0, + PYGEN_ERROR = -1, + PYGEN_NEXT = 1, + } __Pyx_PySendResult; +#endif +#if CYTHON_COMPILING_IN_LIMITED_API || PY_VERSION_HEX < 0x030A00A3 + typedef __Pyx_PySendResult (*__Pyx_pyiter_sendfunc)(PyObject *iter, PyObject *value, PyObject **result); +#else + #define __Pyx_pyiter_sendfunc sendfunc +#endif +#if !CYTHON_USE_AM_SEND +#define __PYX_HAS_PY_AM_SEND 0 +#elif __PYX_LIMITED_VERSION_HEX >= 0x030A0000 +#define __PYX_HAS_PY_AM_SEND 1 +#else +#define __PYX_HAS_PY_AM_SEND 2 // our own backported implementation +#endif +#if __PYX_HAS_PY_AM_SEND < 2 + #define __Pyx_PyAsyncMethodsStruct PyAsyncMethods +#else + typedef struct { + unaryfunc am_await; + unaryfunc am_aiter; + unaryfunc am_anext; + __Pyx_pyiter_sendfunc am_send; + } __Pyx_PyAsyncMethodsStruct; + #define __Pyx_SlotTpAsAsync(s) ((PyAsyncMethods*)(s)) +#endif +#if CYTHON_USE_AM_SEND && PY_VERSION_HEX < 0x030A00F0 + #define __Pyx_TPFLAGS_HAVE_AM_SEND (1UL << 21) +#else + #define __Pyx_TPFLAGS_HAVE_AM_SEND (0) +#endif +#if PY_VERSION_HEX >= 0x03090000 +#define __Pyx_PyInterpreterState_Get() PyInterpreterState_Get() +#else +#define __Pyx_PyInterpreterState_Get() PyThreadState_Get()->interp +#endif +#if CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX < 0x030A0000 +#ifdef __cplusplus +extern "C" +#endif +PyAPI_FUNC(void *) PyMem_Calloc(size_t nelem, size_t elsize); +#endif +#if CYTHON_COMPILING_IN_LIMITED_API +static int __Pyx_init_co_variable(PyObject *inspect, const char* name, int *write_to) { + int value; + PyObject *py_value = PyObject_GetAttrString(inspect, name); + if (!py_value) return 0; + value = (int) PyLong_AsLong(py_value); + Py_DECREF(py_value); + *write_to = value; + return value != -1 || !PyErr_Occurred(); +} +static int __Pyx_init_co_variables(void) { + PyObject *inspect; + int result; + inspect = PyImport_ImportModule("inspect"); + result = +#if !defined(CO_OPTIMIZED) + __Pyx_init_co_variable(inspect, "CO_OPTIMIZED", &CO_OPTIMIZED) && +#endif +#if !defined(CO_NEWLOCALS) + __Pyx_init_co_variable(inspect, "CO_NEWLOCALS", &CO_NEWLOCALS) && +#endif +#if !defined(CO_VARARGS) + __Pyx_init_co_variable(inspect, "CO_VARARGS", &CO_VARARGS) && +#endif +#if !defined(CO_VARKEYWORDS) + __Pyx_init_co_variable(inspect, "CO_VARKEYWORDS", &CO_VARKEYWORDS) && +#endif +#if !defined(CO_ASYNC_GENERATOR) + __Pyx_init_co_variable(inspect, "CO_ASYNC_GENERATOR", &CO_ASYNC_GENERATOR) && +#endif +#if !defined(CO_GENERATOR) + __Pyx_init_co_variable(inspect, "CO_GENERATOR", &CO_GENERATOR) && +#endif +#if !defined(CO_COROUTINE) + __Pyx_init_co_variable(inspect, "CO_COROUTINE", &CO_COROUTINE) && +#endif + 1; + Py_DECREF(inspect); + return result ? 0 : -1; +} +#else +static int __Pyx_init_co_variables(void) { + return 0; // It's a limited API-only feature +} +#endif + +/* MathInitCode */ +#if defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS) + #ifndef _USE_MATH_DEFINES + #define _USE_MATH_DEFINES + #endif +#endif +#include +#if defined(__CYGWIN__) && defined(_LDBL_EQ_DBL) +#define __Pyx_truncl trunc +#else +#define __Pyx_truncl truncl +#endif + +#ifndef CYTHON_CLINE_IN_TRACEBACK_RUNTIME +#define CYTHON_CLINE_IN_TRACEBACK_RUNTIME 0 +#endif +#ifndef CYTHON_CLINE_IN_TRACEBACK +#define CYTHON_CLINE_IN_TRACEBACK CYTHON_CLINE_IN_TRACEBACK_RUNTIME +#endif +#if CYTHON_CLINE_IN_TRACEBACK +#define __PYX_MARK_ERR_POS(f_index, lineno) { __pyx_filename = __pyx_f[f_index]; (void) __pyx_filename; __pyx_lineno = lineno; (void) __pyx_lineno; __pyx_clineno = __LINE__; (void) __pyx_clineno; } +#else +#define __PYX_MARK_ERR_POS(f_index, lineno) { __pyx_filename = __pyx_f[f_index]; (void) __pyx_filename; __pyx_lineno = lineno; (void) __pyx_lineno; (void) __pyx_clineno; } +#endif +#define __PYX_ERR(f_index, lineno, Ln_error) \ + { __PYX_MARK_ERR_POS(f_index, lineno) goto Ln_error; } + +#ifdef CYTHON_EXTERN_C + #undef __PYX_EXTERN_C + #define __PYX_EXTERN_C CYTHON_EXTERN_C +#elif defined(__PYX_EXTERN_C) + #ifdef _MSC_VER + #pragma message ("Please do not define the '__PYX_EXTERN_C' macro externally. Use 'CYTHON_EXTERN_C' instead.") + #else + #warning Please do not define the '__PYX_EXTERN_C' macro externally. Use 'CYTHON_EXTERN_C' instead. + #endif +#else + #ifdef __cplusplus + #define __PYX_EXTERN_C extern "C" + #else + #define __PYX_EXTERN_C extern + #endif +#endif + +#define __PYX_HAVE__matcha__utils__monotonic_align__core +#define __PYX_HAVE_API__matcha__utils__monotonic_align__core +/* Early includes */ +#include +#include + + /* Using NumPy API declarations from "numpy/__init__.cython-30.pxd" */ + +#include "numpy/arrayobject.h" +#include "numpy/ndarrayobject.h" +#include "numpy/ndarraytypes.h" +#include "numpy/arrayscalars.h" +#include "numpy/ufuncobject.h" +#include "pythread.h" +#include +#ifdef _OPENMP +#include +#endif /* _OPENMP */ + +#if defined(PYREX_WITHOUT_ASSERTIONS) && !defined(CYTHON_WITHOUT_ASSERTIONS) +#define CYTHON_WITHOUT_ASSERTIONS +#endif + +#ifdef CYTHON_FREETHREADING_COMPATIBLE +#if CYTHON_FREETHREADING_COMPATIBLE +#define __Pyx_FREETHREADING_COMPATIBLE Py_MOD_GIL_NOT_USED +#else +#define __Pyx_FREETHREADING_COMPATIBLE Py_MOD_GIL_USED +#endif +#else +#define __Pyx_FREETHREADING_COMPATIBLE Py_MOD_GIL_USED +#endif +#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0 +#define __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 0 +#define __PYX_DEFAULT_STRING_ENCODING "" +#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString +#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize +#define __Pyx_uchar_cast(c) ((unsigned char)c) +#define __Pyx_long_cast(x) ((long)x) +#define __Pyx_fits_Py_ssize_t(v, type, is_signed) (\ + (sizeof(type) < sizeof(Py_ssize_t)) ||\ + (sizeof(type) > sizeof(Py_ssize_t) &&\ + likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX) &&\ + (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||\ + v == (type)PY_SSIZE_T_MIN))) ||\ + (sizeof(type) == sizeof(Py_ssize_t) &&\ + (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX))) ) +static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { + return (size_t) i < (size_t) limit; +} +#if defined (__cplusplus) && __cplusplus >= 201103L + #include + #define __Pyx_sst_abs(value) std::abs(value) +#elif SIZEOF_INT >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) abs(value) +#elif SIZEOF_LONG >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) labs(value) +#elif defined (_MSC_VER) + #define __Pyx_sst_abs(value) ((Py_ssize_t)_abs64(value)) +#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define __Pyx_sst_abs(value) llabs(value) +#elif defined (__GNUC__) + #define __Pyx_sst_abs(value) __builtin_llabs(value) +#else + #define __Pyx_sst_abs(value) ((value<0) ? -value : value) +#endif +static CYTHON_INLINE Py_ssize_t __Pyx_ssize_strlen(const char *s); +static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject*); +static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length); +static CYTHON_INLINE PyObject* __Pyx_PyByteArray_FromString(const char*); +#define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l) +#define __Pyx_PyBytes_FromString PyBytes_FromString +#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*); +#if CYTHON_ASSUME_SAFE_MACROS + #define __Pyx_PyBytes_AsWritableString(s) ((char*) PyBytes_AS_STRING(s)) + #define __Pyx_PyBytes_AsWritableSString(s) ((signed char*) PyBytes_AS_STRING(s)) + #define __Pyx_PyBytes_AsWritableUString(s) ((unsigned char*) PyBytes_AS_STRING(s)) + #define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AS_STRING(s)) + #define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AS_STRING(s)) + #define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AS_STRING(s)) + #define __Pyx_PyByteArray_AsString(s) PyByteArray_AS_STRING(s) +#else + #define __Pyx_PyBytes_AsWritableString(s) ((char*) PyBytes_AsString(s)) + #define __Pyx_PyBytes_AsWritableSString(s) ((signed char*) PyBytes_AsString(s)) + #define __Pyx_PyBytes_AsWritableUString(s) ((unsigned char*) PyBytes_AsString(s)) + #define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AsString(s)) + #define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AsString(s)) + #define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AsString(s)) + #define __Pyx_PyByteArray_AsString(s) PyByteArray_AsString(s) +#endif +#define __Pyx_PyObject_AsWritableString(s) ((char*)(__pyx_uintptr_t) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsWritableSString(s) ((signed char*)(__pyx_uintptr_t) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*)(__pyx_uintptr_t) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsSString(s) ((const signed char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsUString(s) ((const unsigned char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s) +#define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s) +#define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s) +#define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s) +#define __Pyx_PyUnicode_FromOrdinal(o) PyUnicode_FromOrdinal((int)o) +#define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode +static CYTHON_INLINE PyObject *__Pyx_NewRef(PyObject *obj) { +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030a0000 || defined(Py_NewRef) + return Py_NewRef(obj); +#else + Py_INCREF(obj); + return obj; +#endif +} +static CYTHON_INLINE PyObject *__Pyx_XNewRef(PyObject *obj) { +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030a0000 || defined(Py_XNewRef) + return Py_XNewRef(obj); +#else + Py_XINCREF(obj); + return obj; +#endif +} +static CYTHON_INLINE PyObject *__Pyx_Owned_Py_None(int b); +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b); +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); +static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject*); +static CYTHON_INLINE PyObject* __Pyx_PyNumber_Long(PyObject* x); +#define __Pyx_PySequence_Tuple(obj)\ + (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); +static CYTHON_INLINE PyObject * __Pyx_PyLong_FromSize_t(size_t); +static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject*); +#if CYTHON_ASSUME_SAFE_MACROS +#define __Pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) +#define __Pyx_PyFloat_AS_DOUBLE(x) PyFloat_AS_DOUBLE(x) +#else +#define __Pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x) +#define __Pyx_PyFloat_AS_DOUBLE(x) PyFloat_AsDouble(x) +#endif +#define __Pyx_PyFloat_AsFloat(x) ((float) __Pyx_PyFloat_AsDouble(x)) +#define __Pyx_PyNumber_Int(x) (PyLong_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Long(x)) +#if CYTHON_USE_PYLONG_INTERNALS + #if PY_VERSION_HEX >= 0x030C00A7 + #ifndef _PyLong_SIGN_MASK + #define _PyLong_SIGN_MASK 3 + #endif + #ifndef _PyLong_NON_SIZE_BITS + #define _PyLong_NON_SIZE_BITS 3 + #endif + #define __Pyx_PyLong_Sign(x) (((PyLongObject*)x)->long_value.lv_tag & _PyLong_SIGN_MASK) + #define __Pyx_PyLong_IsNeg(x) ((__Pyx_PyLong_Sign(x) & 2) != 0) + #define __Pyx_PyLong_IsNonNeg(x) (!__Pyx_PyLong_IsNeg(x)) + #define __Pyx_PyLong_IsZero(x) (__Pyx_PyLong_Sign(x) & 1) + #define __Pyx_PyLong_IsPos(x) (__Pyx_PyLong_Sign(x) == 0) + #define __Pyx_PyLong_CompactValueUnsigned(x) (__Pyx_PyLong_Digits(x)[0]) + #define __Pyx_PyLong_DigitCount(x) ((Py_ssize_t) (((PyLongObject*)x)->long_value.lv_tag >> _PyLong_NON_SIZE_BITS)) + #define __Pyx_PyLong_SignedDigitCount(x)\ + ((1 - (Py_ssize_t) __Pyx_PyLong_Sign(x)) * __Pyx_PyLong_DigitCount(x)) + #if defined(PyUnstable_Long_IsCompact) && defined(PyUnstable_Long_CompactValue) + #define __Pyx_PyLong_IsCompact(x) PyUnstable_Long_IsCompact((PyLongObject*) x) + #define __Pyx_PyLong_CompactValue(x) PyUnstable_Long_CompactValue((PyLongObject*) x) + #else + #define __Pyx_PyLong_IsCompact(x) (((PyLongObject*)x)->long_value.lv_tag < (2 << _PyLong_NON_SIZE_BITS)) + #define __Pyx_PyLong_CompactValue(x) ((1 - (Py_ssize_t) __Pyx_PyLong_Sign(x)) * (Py_ssize_t) __Pyx_PyLong_Digits(x)[0]) + #endif + typedef Py_ssize_t __Pyx_compact_pylong; + typedef size_t __Pyx_compact_upylong; + #else + #define __Pyx_PyLong_IsNeg(x) (Py_SIZE(x) < 0) + #define __Pyx_PyLong_IsNonNeg(x) (Py_SIZE(x) >= 0) + #define __Pyx_PyLong_IsZero(x) (Py_SIZE(x) == 0) + #define __Pyx_PyLong_IsPos(x) (Py_SIZE(x) > 0) + #define __Pyx_PyLong_CompactValueUnsigned(x) ((Py_SIZE(x) == 0) ? 0 : __Pyx_PyLong_Digits(x)[0]) + #define __Pyx_PyLong_DigitCount(x) __Pyx_sst_abs(Py_SIZE(x)) + #define __Pyx_PyLong_SignedDigitCount(x) Py_SIZE(x) + #define __Pyx_PyLong_IsCompact(x) (Py_SIZE(x) == 0 || Py_SIZE(x) == 1 || Py_SIZE(x) == -1) + #define __Pyx_PyLong_CompactValue(x)\ + ((Py_SIZE(x) == 0) ? (sdigit) 0 : ((Py_SIZE(x) < 0) ? -(sdigit)__Pyx_PyLong_Digits(x)[0] : (sdigit)__Pyx_PyLong_Digits(x)[0])) + typedef sdigit __Pyx_compact_pylong; + typedef digit __Pyx_compact_upylong; + #endif + #if PY_VERSION_HEX >= 0x030C00A5 + #define __Pyx_PyLong_Digits(x) (((PyLongObject*)x)->long_value.ob_digit) + #else + #define __Pyx_PyLong_Digits(x) (((PyLongObject*)x)->ob_digit) + #endif +#endif +#if __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 + #define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL) +#elif __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + #define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeASCII(c_str, size, NULL) +#else + #define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL) +#endif + + +/* Test for GCC > 2.95 */ +#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))) + #define likely(x) __builtin_expect(!!(x), 1) + #define unlikely(x) __builtin_expect(!!(x), 0) +#else /* !__GNUC__ or GCC < 2.95 */ + #define likely(x) (x) + #define unlikely(x) (x) +#endif /* __GNUC__ */ +/* PretendToInitialize */ +#ifdef __cplusplus +#if __cplusplus > 201103L +#include +#endif +template +static void __Pyx_pretend_to_initialize(T* ptr) { +#if __cplusplus > 201103L + if ((std::is_trivially_default_constructible::value)) +#endif + *ptr = T(); + (void)ptr; +} +#else +static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; } +#endif + + +#if !CYTHON_USE_MODULE_STATE +static PyObject *__pyx_m = NULL; +#endif +static int __pyx_lineno; +static int __pyx_clineno = 0; +static const char * const __pyx_cfilenm = __FILE__; +static const char *__pyx_filename; + +/* Header.proto */ +#if !defined(CYTHON_CCOMPLEX) + #if defined(__cplusplus) + #define CYTHON_CCOMPLEX 1 + #elif (defined(_Complex_I) && !defined(_MSC_VER)) || ((defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) && !defined(__STDC_NO_COMPLEX__) && !defined(_MSC_VER)) + #define CYTHON_CCOMPLEX 1 + #else + #define CYTHON_CCOMPLEX 0 + #endif +#endif +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + #include + #else + #include + #endif +#endif +#if CYTHON_CCOMPLEX && !defined(__cplusplus) && defined(__sun__) && defined(__GNUC__) + #undef _Complex_I + #define _Complex_I 1.0fj +#endif + +/* #### Code section: filename_table ### */ + +static const char* const __pyx_f[] = { + "matcha/utils/monotonic_align/core.pyx", + "", + "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd", + "cpython/type.pxd", +}; +/* #### Code section: utility_code_proto_before_types ### */ +/* Atomics.proto (used by UnpackUnboundCMethod) */ +#include +#ifndef CYTHON_ATOMICS + #define CYTHON_ATOMICS 1 +#endif +#define __PYX_CYTHON_ATOMICS_ENABLED() CYTHON_ATOMICS +#define __PYX_GET_CYTHON_COMPILING_IN_CPYTHON_FREETHREADING() CYTHON_COMPILING_IN_CPYTHON_FREETHREADING +#define __pyx_atomic_int_type int +#define __pyx_nonatomic_int_type int +#if CYTHON_ATOMICS && (defined(__STDC_VERSION__) &&\ + (__STDC_VERSION__ >= 201112L) &&\ + !defined(__STDC_NO_ATOMICS__)) + #include +#elif CYTHON_ATOMICS && (defined(__cplusplus) && (\ + (__cplusplus >= 201103L) ||\ + (defined(_MSC_VER) && _MSC_VER >= 1700))) + #include +#endif +#if CYTHON_ATOMICS && (defined(__STDC_VERSION__) &&\ + (__STDC_VERSION__ >= 201112L) &&\ + !defined(__STDC_NO_ATOMICS__) &&\ + ATOMIC_INT_LOCK_FREE == 2) + #undef __pyx_atomic_int_type + #define __pyx_atomic_int_type atomic_int + #define __pyx_atomic_ptr_type atomic_uintptr_t + #define __pyx_nonatomic_ptr_type uintptr_t + #define __pyx_atomic_incr_relaxed(value) atomic_fetch_add_explicit(value, 1, memory_order_relaxed) + #define __pyx_atomic_incr_acq_rel(value) atomic_fetch_add_explicit(value, 1, memory_order_acq_rel) + #define __pyx_atomic_decr_acq_rel(value) atomic_fetch_sub_explicit(value, 1, memory_order_acq_rel) + #define __pyx_atomic_sub(value, arg) atomic_fetch_sub(value, arg) + #define __pyx_atomic_int_cmp_exchange(value, expected, desired) atomic_compare_exchange_strong(value, expected, desired) + #define __pyx_atomic_load(value) atomic_load(value) + #define __pyx_atomic_store(value, new_value) atomic_store(value, new_value) + #define __pyx_atomic_pointer_load_relaxed(value) atomic_load_explicit(value, memory_order_relaxed) + #define __pyx_atomic_pointer_load_acquire(value) atomic_load_explicit(value, memory_order_acquire) + #define __pyx_atomic_pointer_exchange(value, new_value) atomic_exchange(value, (__pyx_nonatomic_ptr_type)new_value) + #define __pyx_atomic_pointer_cmp_exchange(value, expected, desired) atomic_compare_exchange_strong(value, expected, desired) + #if defined(__PYX_DEBUG_ATOMICS) && defined(_MSC_VER) + #pragma message ("Using standard C atomics") + #elif defined(__PYX_DEBUG_ATOMICS) + #warning "Using standard C atomics" + #endif +#elif CYTHON_ATOMICS && (defined(__cplusplus) && (\ + (__cplusplus >= 201103L) ||\ +\ + (defined(_MSC_VER) && _MSC_VER >= 1700)) &&\ + ATOMIC_INT_LOCK_FREE == 2) + #undef __pyx_atomic_int_type + #define __pyx_atomic_int_type std::atomic_int + #define __pyx_atomic_ptr_type std::atomic_uintptr_t + #define __pyx_nonatomic_ptr_type uintptr_t + #define __pyx_atomic_incr_relaxed(value) std::atomic_fetch_add_explicit(value, 1, std::memory_order_relaxed) + #define __pyx_atomic_incr_acq_rel(value) std::atomic_fetch_add_explicit(value, 1, std::memory_order_acq_rel) + #define __pyx_atomic_decr_acq_rel(value) std::atomic_fetch_sub_explicit(value, 1, std::memory_order_acq_rel) + #define __pyx_atomic_sub(value, arg) std::atomic_fetch_sub(value, arg) + #define __pyx_atomic_int_cmp_exchange(value, expected, desired) std::atomic_compare_exchange_strong(value, expected, desired) + #define __pyx_atomic_load(value) std::atomic_load(value) + #define __pyx_atomic_store(value, new_value) std::atomic_store(value, new_value) + #define __pyx_atomic_pointer_load_relaxed(value) std::atomic_load_explicit(value, std::memory_order_relaxed) + #define __pyx_atomic_pointer_load_acquire(value) std::atomic_load_explicit(value, std::memory_order_acquire) + #define __pyx_atomic_pointer_exchange(value, new_value) std::atomic_exchange(value, (__pyx_nonatomic_ptr_type)new_value) + #define __pyx_atomic_pointer_cmp_exchange(value, expected, desired) std::atomic_compare_exchange_strong(value, expected, desired) + #if defined(__PYX_DEBUG_ATOMICS) && defined(_MSC_VER) + #pragma message ("Using standard C++ atomics") + #elif defined(__PYX_DEBUG_ATOMICS) + #warning "Using standard C++ atomics" + #endif +#elif CYTHON_ATOMICS && (__GNUC__ >= 5 || (__GNUC__ == 4 &&\ + (__GNUC_MINOR__ > 1 ||\ + (__GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ >= 2)))) + #define __pyx_atomic_ptr_type void* + #define __pyx_nonatomic_ptr_type void* + #define __pyx_atomic_incr_relaxed(value) __sync_fetch_and_add(value, 1) + #define __pyx_atomic_incr_acq_rel(value) __sync_fetch_and_add(value, 1) + #define __pyx_atomic_decr_acq_rel(value) __sync_fetch_and_sub(value, 1) + #define __pyx_atomic_sub(value, arg) __sync_fetch_and_sub(value, arg) + static CYTHON_INLINE int __pyx_atomic_int_cmp_exchange(__pyx_atomic_int_type* value, __pyx_nonatomic_int_type* expected, __pyx_nonatomic_int_type desired) { + __pyx_nonatomic_int_type old = __sync_val_compare_and_swap(value, *expected, desired); + int result = old == *expected; + *expected = old; + return result; + } + #define __pyx_atomic_load(value) __sync_fetch_and_add(value, 0) + #define __pyx_atomic_store(value, new_value) __sync_lock_test_and_set(value, new_value) + #define __pyx_atomic_pointer_load_relaxed(value) __sync_fetch_and_add(value, 0) + #define __pyx_atomic_pointer_load_acquire(value) __sync_fetch_and_add(value, 0) + #define __pyx_atomic_pointer_exchange(value, new_value) __sync_lock_test_and_set(value, (__pyx_atomic_ptr_type)new_value) + static CYTHON_INLINE int __pyx_atomic_pointer_cmp_exchange(__pyx_atomic_ptr_type* value, __pyx_nonatomic_ptr_type* expected, __pyx_nonatomic_ptr_type desired) { + __pyx_nonatomic_ptr_type old = __sync_val_compare_and_swap(value, *expected, desired); + int result = old == *expected; + *expected = old; + return result; + } + #ifdef __PYX_DEBUG_ATOMICS + #warning "Using GNU atomics" + #endif +#elif CYTHON_ATOMICS && defined(_MSC_VER) + #include + #undef __pyx_atomic_int_type + #define __pyx_atomic_int_type long + #define __pyx_atomic_ptr_type void* + #undef __pyx_nonatomic_int_type + #define __pyx_nonatomic_int_type long + #define __pyx_nonatomic_ptr_type void* + #pragma intrinsic (_InterlockedExchangeAdd, _InterlockedExchange, _InterlockedCompareExchange, _InterlockedCompareExchangePointer, _InterlockedExchangePointer) + #define __pyx_atomic_incr_relaxed(value) _InterlockedExchangeAdd(value, 1) + #define __pyx_atomic_incr_acq_rel(value) _InterlockedExchangeAdd(value, 1) + #define __pyx_atomic_decr_acq_rel(value) _InterlockedExchangeAdd(value, -1) + #define __pyx_atomic_sub(value, arg) _InterlockedExchangeAdd(value, -arg) + static CYTHON_INLINE int __pyx_atomic_int_cmp_exchange(__pyx_atomic_int_type* value, __pyx_nonatomic_int_type* expected, __pyx_nonatomic_int_type desired) { + __pyx_nonatomic_int_type old = _InterlockedCompareExchange(value, desired, *expected); + int result = old == *expected; + *expected = old; + return result; + } + #define __pyx_atomic_load(value) _InterlockedExchangeAdd(value, 0) + #define __pyx_atomic_store(value, new_value) _InterlockedExchange(value, new_value) + #define __pyx_atomic_pointer_load_relaxed(value) *(void * volatile *)value + #define __pyx_atomic_pointer_load_acquire(value) _InterlockedCompareExchangePointer(value, 0, 0) + #define __pyx_atomic_pointer_exchange(value, new_value) _InterlockedExchangePointer(value, (__pyx_atomic_ptr_type)new_value) + static CYTHON_INLINE int __pyx_atomic_pointer_cmp_exchange(__pyx_atomic_ptr_type* value, __pyx_nonatomic_ptr_type* expected, __pyx_nonatomic_ptr_type desired) { + __pyx_atomic_ptr_type old = _InterlockedCompareExchangePointer(value, desired, *expected); + int result = old == *expected; + *expected = old; + return result; + } + #ifdef __PYX_DEBUG_ATOMICS + #pragma message ("Using MSVC atomics") + #endif +#else + #undef CYTHON_ATOMICS + #define CYTHON_ATOMICS 0 + #ifdef __PYX_DEBUG_ATOMICS + #warning "Not using atomics" + #endif +#endif + +/* CriticalSectionsDefinition.proto (used by CriticalSections) */ +#if !CYTHON_COMPILING_IN_CPYTHON_FREETHREADING +#define __Pyx_PyCriticalSection void* +#define __Pyx_PyCriticalSection2 void* +#define __Pyx_PyCriticalSection_End(cs) +#define __Pyx_PyCriticalSection2_End(cs) +#else +#define __Pyx_PyCriticalSection PyCriticalSection +#define __Pyx_PyCriticalSection2 PyCriticalSection2 +#define __Pyx_PyCriticalSection_End PyCriticalSection_End +#define __Pyx_PyCriticalSection2_End PyCriticalSection2_End +#endif + +/* CriticalSections.proto (used by ParseKeywordsImpl) */ +#if !CYTHON_COMPILING_IN_CPYTHON_FREETHREADING +#define __Pyx_PyCriticalSection_Begin(cs, arg) (void)(cs) +#define __Pyx_PyCriticalSection2_Begin(cs, arg1, arg2) (void)(cs) +#else +#define __Pyx_PyCriticalSection_Begin PyCriticalSection_Begin +#define __Pyx_PyCriticalSection2_Begin PyCriticalSection2_Begin +#endif +#if PY_VERSION_HEX < 0x030d0000 || CYTHON_COMPILING_IN_LIMITED_API +#define __Pyx_BEGIN_CRITICAL_SECTION(o) { +#define __Pyx_END_CRITICAL_SECTION() } +#else +#define __Pyx_BEGIN_CRITICAL_SECTION Py_BEGIN_CRITICAL_SECTION +#define __Pyx_END_CRITICAL_SECTION Py_END_CRITICAL_SECTION +#endif + +/* ForceInitThreads.proto */ +#ifndef __PYX_FORCE_INIT_THREADS + #define __PYX_FORCE_INIT_THREADS 0 +#endif + +/* NoFastGil.proto */ +#define __Pyx_PyGILState_Ensure PyGILState_Ensure +#define __Pyx_PyGILState_Release PyGILState_Release +#define __Pyx_FastGIL_Remember() +#define __Pyx_FastGIL_Forget() +#define __Pyx_FastGilFuncInit() + +/* IncludeStructmemberH.proto (used by FixUpExtensionType) */ +#include + +/* BufferFormatStructs.proto */ +struct __Pyx_StructField_; +#define __PYX_BUF_FLAGS_PACKED_STRUCT (1 << 0) +typedef struct { + const char* name; + const struct __Pyx_StructField_* fields; + size_t size; + size_t arraysize[8]; + int ndim; + char typegroup; + char is_unsigned; + int flags; +} __Pyx_TypeInfo; +typedef struct __Pyx_StructField_ { + const __Pyx_TypeInfo* type; + const char* name; + size_t offset; +} __Pyx_StructField; +typedef struct { + const __Pyx_StructField* field; + size_t parent_offset; +} __Pyx_BufFmt_StackElem; +typedef struct { + __Pyx_StructField root; + __Pyx_BufFmt_StackElem* head; + size_t fmt_offset; + size_t new_count, enc_count; + size_t struct_alignment; + int is_complex; + char enc_type; + char new_packmode; + char enc_packmode; + char is_valid_array; +} __Pyx_BufFmt_Context; + +/* MemviewSliceStruct.proto */ +struct __pyx_memoryview_obj; +typedef struct { + struct __pyx_memoryview_obj *memview; + char *data; + Py_ssize_t shape[8]; + Py_ssize_t strides[8]; + Py_ssize_t suboffsets[8]; +} __Pyx_memviewslice; +#define __Pyx_MemoryView_Len(m) (m.shape[0]) +#define __Pyx_MEMVIEW_DIRECT 1 +#define __Pyx_MEMVIEW_PTR 2 +#define __Pyx_MEMVIEW_FULL 4 +#define __Pyx_MEMVIEW_CONTIG 8 +#define __Pyx_MEMVIEW_STRIDED 16 +#define __Pyx_MEMVIEW_FOLLOW 32 +#define __Pyx_IS_C_CONTIG 1 +#define __Pyx_IS_F_CONTIG 2 +#define __Pyx_MEMSLICE_INIT { 0, 0, { 0 }, { 0 }, { 0 } } +#if CYTHON_ATOMICS + #define __pyx_add_acquisition_count(memview)\ + __pyx_atomic_incr_relaxed(__pyx_get_slice_count_pointer(memview)) + #define __pyx_sub_acquisition_count(memview)\ + __pyx_atomic_decr_acq_rel(__pyx_get_slice_count_pointer(memview)) +#else + #define __pyx_add_acquisition_count(memview)\ + __pyx_add_acquisition_count_locked(__pyx_get_slice_count_pointer(memview), memview->lock) + #define __pyx_sub_acquisition_count(memview)\ + __pyx_sub_acquisition_count_locked(__pyx_get_slice_count_pointer(memview), memview->lock) +#endif + +/* #### Code section: numeric_typedefs ### */ + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":744 + * # in Cython to enable them only on the right systems. + * + * ctypedef npy_int8 int8_t # <<<<<<<<<<<<<< + * ctypedef npy_int16 int16_t + * ctypedef npy_int32 int32_t +*/ +typedef npy_int8 __pyx_t_5numpy_int8_t; + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":745 + * + * ctypedef npy_int8 int8_t + * ctypedef npy_int16 int16_t # <<<<<<<<<<<<<< + * ctypedef npy_int32 int32_t + * ctypedef npy_int64 int64_t +*/ +typedef npy_int16 __pyx_t_5numpy_int16_t; + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":746 + * ctypedef npy_int8 int8_t + * ctypedef npy_int16 int16_t + * ctypedef npy_int32 int32_t # <<<<<<<<<<<<<< + * ctypedef npy_int64 int64_t + * +*/ +typedef npy_int32 __pyx_t_5numpy_int32_t; + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":747 + * ctypedef npy_int16 int16_t + * ctypedef npy_int32 int32_t + * ctypedef npy_int64 int64_t # <<<<<<<<<<<<<< + * + * ctypedef npy_uint8 uint8_t +*/ +typedef npy_int64 __pyx_t_5numpy_int64_t; + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":749 + * ctypedef npy_int64 int64_t + * + * ctypedef npy_uint8 uint8_t # <<<<<<<<<<<<<< + * ctypedef npy_uint16 uint16_t + * ctypedef npy_uint32 uint32_t +*/ +typedef npy_uint8 __pyx_t_5numpy_uint8_t; + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":750 + * + * ctypedef npy_uint8 uint8_t + * ctypedef npy_uint16 uint16_t # <<<<<<<<<<<<<< + * ctypedef npy_uint32 uint32_t + * ctypedef npy_uint64 uint64_t +*/ +typedef npy_uint16 __pyx_t_5numpy_uint16_t; + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":751 + * ctypedef npy_uint8 uint8_t + * ctypedef npy_uint16 uint16_t + * ctypedef npy_uint32 uint32_t # <<<<<<<<<<<<<< + * ctypedef npy_uint64 uint64_t + * +*/ +typedef npy_uint32 __pyx_t_5numpy_uint32_t; + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":752 + * ctypedef npy_uint16 uint16_t + * ctypedef npy_uint32 uint32_t + * ctypedef npy_uint64 uint64_t # <<<<<<<<<<<<<< + * + * ctypedef npy_float32 float32_t +*/ +typedef npy_uint64 __pyx_t_5numpy_uint64_t; + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":754 + * ctypedef npy_uint64 uint64_t + * + * ctypedef npy_float32 float32_t # <<<<<<<<<<<<<< + * ctypedef npy_float64 float64_t + * #ctypedef npy_float80 float80_t +*/ +typedef npy_float32 __pyx_t_5numpy_float32_t; + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":755 + * + * ctypedef npy_float32 float32_t + * ctypedef npy_float64 float64_t # <<<<<<<<<<<<<< + * #ctypedef npy_float80 float80_t + * #ctypedef npy_float128 float128_t +*/ +typedef npy_float64 __pyx_t_5numpy_float64_t; + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":762 + * ctypedef double complex complex128_t + * + * ctypedef npy_longlong longlong_t # <<<<<<<<<<<<<< + * ctypedef npy_ulonglong ulonglong_t + * +*/ +typedef npy_longlong __pyx_t_5numpy_longlong_t; + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":763 + * + * ctypedef npy_longlong longlong_t + * ctypedef npy_ulonglong ulonglong_t # <<<<<<<<<<<<<< + * + * ctypedef npy_intp intp_t +*/ +typedef npy_ulonglong __pyx_t_5numpy_ulonglong_t; + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":765 + * ctypedef npy_ulonglong ulonglong_t + * + * ctypedef npy_intp intp_t # <<<<<<<<<<<<<< + * ctypedef npy_uintp uintp_t + * +*/ +typedef npy_intp __pyx_t_5numpy_intp_t; + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":766 + * + * ctypedef npy_intp intp_t + * ctypedef npy_uintp uintp_t # <<<<<<<<<<<<<< + * + * ctypedef npy_double float_t +*/ +typedef npy_uintp __pyx_t_5numpy_uintp_t; + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":768 + * ctypedef npy_uintp uintp_t + * + * ctypedef npy_double float_t # <<<<<<<<<<<<<< + * ctypedef npy_double double_t + * ctypedef npy_longdouble longdouble_t +*/ +typedef npy_double __pyx_t_5numpy_float_t; + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":769 + * + * ctypedef npy_double float_t + * ctypedef npy_double double_t # <<<<<<<<<<<<<< + * ctypedef npy_longdouble longdouble_t + * +*/ +typedef npy_double __pyx_t_5numpy_double_t; + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":770 + * ctypedef npy_double float_t + * ctypedef npy_double double_t + * ctypedef npy_longdouble longdouble_t # <<<<<<<<<<<<<< + * + * ctypedef float complex cfloat_t +*/ +typedef npy_longdouble __pyx_t_5numpy_longdouble_t; +/* #### Code section: complex_type_declarations ### */ +/* Declarations.proto */ +#if CYTHON_CCOMPLEX && (1) && (!0 || __cplusplus) + #ifdef __cplusplus + typedef ::std::complex< float > __pyx_t_float_complex; + #else + typedef float _Complex __pyx_t_float_complex; + #endif +#else + typedef struct { float real, imag; } __pyx_t_float_complex; +#endif +static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float, float); + +/* Declarations.proto */ +#if CYTHON_CCOMPLEX && (1) && (!0 || __cplusplus) + #ifdef __cplusplus + typedef ::std::complex< double > __pyx_t_double_complex; + #else + typedef double _Complex __pyx_t_double_complex; + #endif +#else + typedef struct { double real, imag; } __pyx_t_double_complex; +#endif +static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double, double); + +/* Declarations.proto */ +#if CYTHON_CCOMPLEX && (1) && (!0 || __cplusplus) + #ifdef __cplusplus + typedef ::std::complex< long double > __pyx_t_long_double_complex; + #else + typedef long double _Complex __pyx_t_long_double_complex; + #endif +#else + typedef struct { long double real, imag; } __pyx_t_long_double_complex; +#endif +static CYTHON_INLINE __pyx_t_long_double_complex __pyx_t_long_double_complex_from_parts(long double, long double); + +/* #### Code section: type_declarations ### */ + +/*--- Type declarations ---*/ +struct __pyx_array_obj; +struct __pyx_MemviewEnum_obj; +struct __pyx_memoryview_obj; +struct __pyx_memoryviewslice_obj; +struct __pyx_opt_args_6matcha_5utils_15monotonic_align_4core_maximum_path_c; + +/* "matcha/utils/monotonic_align/core.pyx":42 + * @cython.boundscheck(False) + * @cython.wraparound(False) + * cpdef void maximum_path_c(int[:,:,::1] paths, float[:,:,::1] values, int[::1] t_xs, int[::1] t_ys, float max_neg_val=-1e9) nogil: # <<<<<<<<<<<<<< + * cdef int b = values.shape[0] + * +*/ +struct __pyx_opt_args_6matcha_5utils_15monotonic_align_4core_maximum_path_c { + int __pyx_n; + float max_neg_val; +}; + +/* "View.MemoryView":118 + * + * + * @cython.collection_type("sequence") # <<<<<<<<<<<<<< + * @cname("__pyx_array") + * cdef class array: +*/ +struct __pyx_array_obj { + PyObject_HEAD + struct __pyx_vtabstruct_array *__pyx_vtab; + char *data; + Py_ssize_t len; + char *format; + int ndim; + Py_ssize_t *_shape; + Py_ssize_t *_strides; + Py_ssize_t itemsize; + PyObject *mode; + PyObject *_format; + void (*callback_free_data)(void *); + int free_data; + int dtype_is_object; +}; + + +/* "View.MemoryView":307 + * + * + * @cname('__pyx_MemviewEnum') # <<<<<<<<<<<<<< + * cdef class Enum(object): + * cdef object name +*/ +struct __pyx_MemviewEnum_obj { + PyObject_HEAD + PyObject *name; +}; + + +/* "View.MemoryView":342 + * + * + * @cname('__pyx_memoryview') # <<<<<<<<<<<<<< + * cdef class memoryview: + * +*/ +struct __pyx_memoryview_obj { + PyObject_HEAD + struct __pyx_vtabstruct_memoryview *__pyx_vtab; + PyObject *obj; + PyObject *_size; + void *_unused; + PyThread_type_lock lock; + __pyx_atomic_int_type acquisition_count; + Py_buffer view; + int flags; + int dtype_is_object; + __Pyx_TypeInfo const *typeinfo; +}; + + +/* "View.MemoryView":856 + * + * + * @cython.collection_type("sequence") # <<<<<<<<<<<<<< + * @cname('__pyx_memoryviewslice') + * cdef class _memoryviewslice(memoryview): +*/ +struct __pyx_memoryviewslice_obj { + struct __pyx_memoryview_obj __pyx_base; + __Pyx_memviewslice from_slice; + PyObject *from_object; + PyObject *(*to_object_func)(char *); + int (*to_dtype_func)(char *, PyObject *); +}; + + + +/* "View.MemoryView":118 + * + * + * @cython.collection_type("sequence") # <<<<<<<<<<<<<< + * @cname("__pyx_array") + * cdef class array: +*/ + +struct __pyx_vtabstruct_array { + PyObject *(*get_memview)(struct __pyx_array_obj *); +}; +static struct __pyx_vtabstruct_array *__pyx_vtabptr_array; + + +/* "View.MemoryView":342 + * + * + * @cname('__pyx_memoryview') # <<<<<<<<<<<<<< + * cdef class memoryview: + * +*/ + +struct __pyx_vtabstruct_memoryview { + char *(*get_item_pointer)(struct __pyx_memoryview_obj *, PyObject *); + PyObject *(*is_slice)(struct __pyx_memoryview_obj *, PyObject *); + PyObject *(*setitem_slice_assignment)(struct __pyx_memoryview_obj *, PyObject *, PyObject *); + PyObject *(*setitem_slice_assign_scalar)(struct __pyx_memoryview_obj *, struct __pyx_memoryview_obj *, PyObject *); + PyObject *(*setitem_indexed)(struct __pyx_memoryview_obj *, PyObject *, PyObject *); + PyObject *(*convert_item_to_object)(struct __pyx_memoryview_obj *, char *); + PyObject *(*assign_item_from_object)(struct __pyx_memoryview_obj *, char *, PyObject *); + PyObject *(*_get_base)(struct __pyx_memoryview_obj *); +}; +static struct __pyx_vtabstruct_memoryview *__pyx_vtabptr_memoryview; + + +/* "View.MemoryView":856 + * + * + * @cython.collection_type("sequence") # <<<<<<<<<<<<<< + * @cname('__pyx_memoryviewslice') + * cdef class _memoryviewslice(memoryview): +*/ + +struct __pyx_vtabstruct__memoryviewslice { + struct __pyx_vtabstruct_memoryview __pyx_base; +}; +static struct __pyx_vtabstruct__memoryviewslice *__pyx_vtabptr__memoryviewslice; +/* #### Code section: utility_code_proto ### */ + +/* --- Runtime support code (head) --- */ +/* Refnanny.proto */ +#ifndef CYTHON_REFNANNY + #define CYTHON_REFNANNY 0 +#endif +#if CYTHON_REFNANNY + typedef struct { + void (*INCREF)(void*, PyObject*, Py_ssize_t); + void (*DECREF)(void*, PyObject*, Py_ssize_t); + void (*GOTREF)(void*, PyObject*, Py_ssize_t); + void (*GIVEREF)(void*, PyObject*, Py_ssize_t); + void* (*SetupContext)(const char*, Py_ssize_t, const char*); + void (*FinishContext)(void**); + } __Pyx_RefNannyAPIStruct; + static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; + static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); + #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL; + #define __Pyx_RefNannySetupContext(name, acquire_gil)\ + if (acquire_gil) {\ + PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), (__LINE__), (__FILE__));\ + PyGILState_Release(__pyx_gilstate_save);\ + } else {\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), (__LINE__), (__FILE__));\ + } + #define __Pyx_RefNannyFinishContextNogil() {\ + PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ + __Pyx_RefNannyFinishContext();\ + PyGILState_Release(__pyx_gilstate_save);\ + } + #define __Pyx_RefNannyFinishContextNogil() {\ + PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ + __Pyx_RefNannyFinishContext();\ + PyGILState_Release(__pyx_gilstate_save);\ + } + #define __Pyx_RefNannyFinishContext()\ + __Pyx_RefNanny->FinishContext(&__pyx_refnanny) + #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), (__LINE__)) + #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), (__LINE__)) + #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), (__LINE__)) + #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), (__LINE__)) + #define __Pyx_XINCREF(r) do { if((r) == NULL); else {__Pyx_INCREF(r); }} while(0) + #define __Pyx_XDECREF(r) do { if((r) == NULL); else {__Pyx_DECREF(r); }} while(0) + #define __Pyx_XGOTREF(r) do { if((r) == NULL); else {__Pyx_GOTREF(r); }} while(0) + #define __Pyx_XGIVEREF(r) do { if((r) == NULL); else {__Pyx_GIVEREF(r);}} while(0) +#else + #define __Pyx_RefNannyDeclarations + #define __Pyx_RefNannySetupContext(name, acquire_gil) + #define __Pyx_RefNannyFinishContextNogil() + #define __Pyx_RefNannyFinishContext() + #define __Pyx_INCREF(r) Py_INCREF(r) + #define __Pyx_DECREF(r) Py_DECREF(r) + #define __Pyx_GOTREF(r) + #define __Pyx_GIVEREF(r) + #define __Pyx_XINCREF(r) Py_XINCREF(r) + #define __Pyx_XDECREF(r) Py_XDECREF(r) + #define __Pyx_XGOTREF(r) + #define __Pyx_XGIVEREF(r) +#endif +#define __Pyx_Py_XDECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; Py_XDECREF(tmp);\ + } while (0) +#define __Pyx_XDECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_XDECREF(tmp);\ + } while (0) +#define __Pyx_DECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_DECREF(tmp);\ + } while (0) +#define __Pyx_CLEAR(r) do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0) +#define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0) + +/* TupleAndListFromArray.proto (used by fastcall) */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyList_FromArray(PyObject *const *src, Py_ssize_t n); +#endif +#if CYTHON_COMPILING_IN_CPYTHON || CYTHON_METH_FASTCALL +static CYTHON_INLINE PyObject* __Pyx_PyTuple_FromArray(PyObject *const *src, Py_ssize_t n); +#endif + +/* IncludeStringH.proto (used by BytesEquals) */ +#include + +/* BytesEquals.proto (used by UnicodeEquals) */ +static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int equals); + +/* UnicodeEquals.proto (used by fastcall) */ +static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int equals); + +/* fastcall.proto */ +#if CYTHON_AVOID_BORROWED_REFS + #define __Pyx_ArgRef_VARARGS(args, i) __Pyx_PySequence_ITEM(args, i) +#elif CYTHON_ASSUME_SAFE_MACROS + #define __Pyx_ArgRef_VARARGS(args, i) __Pyx_NewRef(__Pyx_PyTuple_GET_ITEM(args, i)) +#else + #define __Pyx_ArgRef_VARARGS(args, i) __Pyx_XNewRef(PyTuple_GetItem(args, i)) +#endif +#define __Pyx_NumKwargs_VARARGS(kwds) PyDict_Size(kwds) +#define __Pyx_KwValues_VARARGS(args, nargs) NULL +#define __Pyx_GetKwValue_VARARGS(kw, kwvalues, s) __Pyx_PyDict_GetItemStrWithError(kw, s) +#define __Pyx_KwargsAsDict_VARARGS(kw, kwvalues) PyDict_Copy(kw) +#if CYTHON_METH_FASTCALL + #define __Pyx_ArgRef_FASTCALL(args, i) __Pyx_NewRef(args[i]) + #define __Pyx_NumKwargs_FASTCALL(kwds) __Pyx_PyTuple_GET_SIZE(kwds) + #define __Pyx_KwValues_FASTCALL(args, nargs) ((args) + (nargs)) + static CYTHON_INLINE PyObject * __Pyx_GetKwValue_FASTCALL(PyObject *kwnames, PyObject *const *kwvalues, PyObject *s); + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030d0000 || CYTHON_COMPILING_IN_LIMITED_API + CYTHON_UNUSED static PyObject *__Pyx_KwargsAsDict_FASTCALL(PyObject *kwnames, PyObject *const *kwvalues); + #else + #define __Pyx_KwargsAsDict_FASTCALL(kw, kwvalues) _PyStack_AsDict(kwvalues, kw) + #endif +#else + #define __Pyx_ArgRef_FASTCALL __Pyx_ArgRef_VARARGS + #define __Pyx_NumKwargs_FASTCALL __Pyx_NumKwargs_VARARGS + #define __Pyx_KwValues_FASTCALL __Pyx_KwValues_VARARGS + #define __Pyx_GetKwValue_FASTCALL __Pyx_GetKwValue_VARARGS + #define __Pyx_KwargsAsDict_FASTCALL __Pyx_KwargsAsDict_VARARGS +#endif +#define __Pyx_ArgsSlice_VARARGS(args, start, stop) PyTuple_GetSlice(args, start, stop) +#if CYTHON_METH_FASTCALL || (CYTHON_COMPILING_IN_CPYTHON && CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS) +#define __Pyx_ArgsSlice_FASTCALL(args, start, stop) __Pyx_PyTuple_FromArray(args + start, stop - start) +#else +#define __Pyx_ArgsSlice_FASTCALL(args, start, stop) PyTuple_GetSlice(args, start, stop) +#endif + +/* py_dict_items.proto (used by OwnedDictNext) */ +static CYTHON_INLINE PyObject* __Pyx_PyDict_Items(PyObject* d); + +/* CallCFunction.proto (used by CallUnboundCMethod0) */ +#define __Pyx_CallCFunction(cfunc, self, args)\ + ((PyCFunction)(void(*)(void))(cfunc)->func)(self, args) +#define __Pyx_CallCFunctionWithKeywords(cfunc, self, args, kwargs)\ + ((PyCFunctionWithKeywords)(void(*)(void))(cfunc)->func)(self, args, kwargs) +#define __Pyx_CallCFunctionFast(cfunc, self, args, nargs)\ + ((__Pyx_PyCFunctionFast)(void(*)(void))(PyCFunction)(cfunc)->func)(self, args, nargs) +#define __Pyx_CallCFunctionFastWithKeywords(cfunc, self, args, nargs, kwnames)\ + ((__Pyx_PyCFunctionFastWithKeywords)(void(*)(void))(PyCFunction)(cfunc)->func)(self, args, nargs, kwnames) + +/* PyObjectCall.proto (used by PyObjectFastCall) */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw); +#else +#define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw) +#endif + +/* PyObjectCallMethO.proto (used by PyObjectFastCall) */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg); +#endif + +/* PyObjectFastCall.proto (used by PyObjectCallOneArg) */ +#define __Pyx_PyObject_FastCall(func, args, nargs) __Pyx_PyObject_FastCallDict(func, args, (size_t)(nargs), NULL) +static CYTHON_INLINE PyObject* __Pyx_PyObject_FastCallDict(PyObject *func, PyObject * const*args, size_t nargs, PyObject *kwargs); + +/* PyObjectCallOneArg.proto (used by CallUnboundCMethod0) */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg); + +/* PyObjectGetAttrStr.proto (used by UnpackUnboundCMethod) */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name); +#else +#define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n) +#endif + +/* UnpackUnboundCMethod.proto (used by CallUnboundCMethod0) */ +typedef struct { + PyObject *type; + PyObject **method_name; +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING && CYTHON_ATOMICS + __pyx_atomic_int_type initialized; +#endif + PyCFunction func; + PyObject *method; + int flag; +} __Pyx_CachedCFunction; +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING +static CYTHON_INLINE int __Pyx_CachedCFunction_GetAndSetInitializing(__Pyx_CachedCFunction *cfunc) { +#if !CYTHON_ATOMICS + return 1; +#else + __pyx_nonatomic_int_type expected = 0; + if (__pyx_atomic_int_cmp_exchange(&cfunc->initialized, &expected, 1)) { + return 0; + } + return expected; +#endif +} +static CYTHON_INLINE void __Pyx_CachedCFunction_SetFinishedInitializing(__Pyx_CachedCFunction *cfunc) { +#if CYTHON_ATOMICS + __pyx_atomic_store(&cfunc->initialized, 2); +#endif +} +#else +#define __Pyx_CachedCFunction_GetAndSetInitializing(cfunc) 2 +#define __Pyx_CachedCFunction_SetFinishedInitializing(cfunc) +#endif + +/* CallUnboundCMethod0.proto */ +CYTHON_UNUSED +static PyObject* __Pyx__CallUnboundCMethod0(__Pyx_CachedCFunction* cfunc, PyObject* self); +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_CallUnboundCMethod0(__Pyx_CachedCFunction* cfunc, PyObject* self); +#else +#define __Pyx_CallUnboundCMethod0(cfunc, self) __Pyx__CallUnboundCMethod0(cfunc, self) +#endif + +/* py_dict_values.proto (used by OwnedDictNext) */ +static CYTHON_INLINE PyObject* __Pyx_PyDict_Values(PyObject* d); + +/* OwnedDictNext.proto (used by ParseKeywordsImpl) */ +#if CYTHON_AVOID_BORROWED_REFS +static int __Pyx_PyDict_NextRef(PyObject *p, PyObject **ppos, PyObject **pkey, PyObject **pvalue); +#else +CYTHON_INLINE +static int __Pyx_PyDict_NextRef(PyObject *p, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue); +#endif + +/* RaiseDoubleKeywords.proto (used by ParseKeywordsImpl) */ +static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); + +/* ParseKeywordsImpl.export */ +static int __Pyx_ParseKeywordsTuple( + PyObject *kwds, + PyObject * const *kwvalues, + PyObject ** const argnames[], + PyObject *kwds2, + PyObject *values[], + Py_ssize_t num_pos_args, + Py_ssize_t num_kwargs, + const char* function_name, + int ignore_unknown_kwargs +); +static int __Pyx_ParseKeywordDictToDict( + PyObject *kwds, + PyObject ** const argnames[], + PyObject *kwds2, + PyObject *values[], + Py_ssize_t num_pos_args, + const char* function_name +); +static int __Pyx_ParseKeywordDict( + PyObject *kwds, + PyObject ** const argnames[], + PyObject *values[], + Py_ssize_t num_pos_args, + Py_ssize_t num_kwargs, + const char* function_name, + int ignore_unknown_kwargs +); + +/* CallUnboundCMethod2.proto */ +CYTHON_UNUSED +static PyObject* __Pyx__CallUnboundCMethod2(__Pyx_CachedCFunction* cfunc, PyObject* self, PyObject* arg1, PyObject* arg2); +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject *__Pyx_CallUnboundCMethod2(__Pyx_CachedCFunction *cfunc, PyObject *self, PyObject *arg1, PyObject *arg2); +#else +#define __Pyx_CallUnboundCMethod2(cfunc, self, arg1, arg2) __Pyx__CallUnboundCMethod2(cfunc, self, arg1, arg2) +#endif + +/* ParseKeywords.proto */ +static CYTHON_INLINE int __Pyx_ParseKeywords( + PyObject *kwds, PyObject *const *kwvalues, PyObject ** const argnames[], + PyObject *kwds2, PyObject *values[], + Py_ssize_t num_pos_args, Py_ssize_t num_kwargs, + const char* function_name, + int ignore_unknown_kwargs +); + +/* RaiseArgTupleInvalid.proto */ +static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, + Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); + +/* ArgTypeTestFunc.export */ +static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *name, int exact); + +/* ArgTypeTest.proto */ +#define __Pyx_ArgTypeTest(obj, type, none_allowed, name, exact)\ + ((likely(__Pyx_IS_TYPE(obj, type) | (none_allowed && (obj == Py_None)))) ? 1 :\ + __Pyx__ArgTypeTest(obj, type, name, exact)) + +/* PyErrExceptionMatches.proto (used by PyObjectGetAttrStrNoError) */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyErr_ExceptionMatches(err) __Pyx_PyErr_ExceptionMatchesInState(__pyx_tstate, err) +static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tstate, PyObject* err); +#else +#define __Pyx_PyErr_ExceptionMatches(err) PyErr_ExceptionMatches(err) +#endif + +/* PyThreadStateGet.proto (used by PyErrFetchRestore) */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate; +#define __Pyx_PyThreadState_assign __pyx_tstate = __Pyx_PyThreadState_Current; +#if PY_VERSION_HEX >= 0x030C00A6 +#define __Pyx_PyErr_Occurred() (__pyx_tstate->current_exception != NULL) +#define __Pyx_PyErr_CurrentExceptionType() (__pyx_tstate->current_exception ? (PyObject*) Py_TYPE(__pyx_tstate->current_exception) : (PyObject*) NULL) +#else +#define __Pyx_PyErr_Occurred() (__pyx_tstate->curexc_type != NULL) +#define __Pyx_PyErr_CurrentExceptionType() (__pyx_tstate->curexc_type) +#endif +#else +#define __Pyx_PyThreadState_declare +#define __Pyx_PyThreadState_assign +#define __Pyx_PyErr_Occurred() (PyErr_Occurred() != NULL) +#define __Pyx_PyErr_CurrentExceptionType() PyErr_Occurred() +#endif + +/* PyErrFetchRestore.proto (used by PyObjectGetAttrStrNoError) */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyErr_Clear() __Pyx_ErrRestore(NULL, NULL, NULL) +#define __Pyx_ErrRestoreWithState(type, value, tb) __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) __Pyx_ErrRestoreInState(__pyx_tstate, type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) __Pyx_ErrFetchInState(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030C00A6 +#define __Pyx_PyErr_SetNone(exc) (Py_INCREF(exc), __Pyx_ErrRestore((exc), NULL, NULL)) +#else +#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) +#endif +#else +#define __Pyx_PyErr_Clear() PyErr_Clear() +#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) +#define __Pyx_ErrRestoreWithState(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestoreInState(tstate, type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchInState(tstate, type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) PyErr_Fetch(type, value, tb) +#endif + +/* PyObjectGetAttrStrNoError.proto (used by GetBuiltinName) */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name); + +/* GetBuiltinName.proto */ +static PyObject *__Pyx_GetBuiltinName(PyObject *name); + +/* PyValueError_Check.proto */ +#define __Pyx_PyExc_ValueError_Check(obj) __Pyx_TypeCheck(obj, PyExc_ValueError) + +/* RaiseException.export */ +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause); + +/* PyObjectFastCallMethod.proto */ +#if CYTHON_VECTORCALL && PY_VERSION_HEX >= 0x03090000 +#define __Pyx_PyObject_FastCallMethod(name, args, nargsf) PyObject_VectorcallMethod(name, args, nargsf, NULL) +#else +static PyObject *__Pyx_PyObject_FastCallMethod(PyObject *name, PyObject *const *args, size_t nargsf); +#endif + +/* RaiseUnexpectedTypeError.proto */ +static int __Pyx_RaiseUnexpectedTypeError(const char *expected, PyObject *obj); + +/* PyMemoryError_Check.proto */ +#define __Pyx_PyExc_MemoryError_Check(obj) __Pyx_TypeCheck(obj, PyExc_MemoryError) + +/* BuildPyUnicode.proto (used by COrdinalToPyUnicode) */ +static PyObject* __Pyx_PyUnicode_BuildFromAscii(Py_ssize_t ulength, const char* chars, int clength, + int prepend_sign, char padding_char); + +/* COrdinalToPyUnicode.proto (used by CIntToPyUnicode) */ +static CYTHON_INLINE int __Pyx_CheckUnicodeValue(int value); +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromOrdinal_Padded(int value, Py_ssize_t width, char padding_char); + +/* GCCDiagnostics.proto (used by CIntToPyUnicode) */ +#if !defined(__INTEL_COMPILER) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +#define __Pyx_HAS_GCC_DIAGNOSTIC +#endif + +/* IncludeStdlibH.proto (used by CIntToPyUnicode) */ +#include + +/* CIntToPyUnicode.proto */ +#define __Pyx_PyUnicode_From_int(value, width, padding_char, format_char) (\ + ((format_char) == ('c')) ?\ + __Pyx_uchar___Pyx_PyUnicode_From_int(value, width, padding_char) :\ + __Pyx____Pyx_PyUnicode_From_int(value, width, padding_char, format_char)\ + ) +static CYTHON_INLINE PyObject* __Pyx_uchar___Pyx_PyUnicode_From_int(int value, Py_ssize_t width, char padding_char); +static CYTHON_INLINE PyObject* __Pyx____Pyx_PyUnicode_From_int(int value, Py_ssize_t width, char padding_char, char format_char); + +/* CIntToPyUnicode.proto */ +#define __Pyx_PyUnicode_From_Py_ssize_t(value, width, padding_char, format_char) (\ + ((format_char) == ('c')) ?\ + __Pyx_uchar___Pyx_PyUnicode_From_Py_ssize_t(value, width, padding_char) :\ + __Pyx____Pyx_PyUnicode_From_Py_ssize_t(value, width, padding_char, format_char)\ + ) +static CYTHON_INLINE PyObject* __Pyx_uchar___Pyx_PyUnicode_From_Py_ssize_t(Py_ssize_t value, Py_ssize_t width, char padding_char); +static CYTHON_INLINE PyObject* __Pyx____Pyx_PyUnicode_From_Py_ssize_t(Py_ssize_t value, Py_ssize_t width, char padding_char, char format_char); + +/* JoinPyUnicode.export */ +static PyObject* __Pyx_PyUnicode_Join(PyObject** values, Py_ssize_t value_count, Py_ssize_t result_ulength, + Py_UCS4 max_char); + +/* PyObjectFormatSimple.proto */ +#if CYTHON_COMPILING_IN_PYPY + #define __Pyx_PyObject_FormatSimple(s, f) (\ + likely(PyUnicode_CheckExact(s)) ? (Py_INCREF(s), s) :\ + PyObject_Format(s, f)) +#elif CYTHON_USE_TYPE_SLOTS + #define __Pyx_PyObject_FormatSimple(s, f) (\ + likely(PyUnicode_CheckExact(s)) ? (Py_INCREF(s), s) :\ + likely(PyLong_CheckExact(s)) ? PyLong_Type.tp_repr(s) :\ + likely(PyFloat_CheckExact(s)) ? PyFloat_Type.tp_repr(s) :\ + PyObject_Format(s, f)) +#else + #define __Pyx_PyObject_FormatSimple(s, f) (\ + likely(PyUnicode_CheckExact(s)) ? (Py_INCREF(s), s) :\ + PyObject_Format(s, f)) +#endif + +CYTHON_UNUSED static int __pyx_array_getbuffer(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /*proto*/ +static PyObject *__pyx_array_get_memview(struct __pyx_array_obj *); /*proto*/ +/* GetAttr.proto */ +static CYTHON_INLINE PyObject *__Pyx_GetAttr(PyObject *, PyObject *); + +/* GetItemInt.proto */ +#define __Pyx_GetItemInt(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck, has_gil, unsafe_shared)\ + (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ + __Pyx_GetItemInt_Fast(o, (Py_ssize_t)i, is_list, wraparound, boundscheck, unsafe_shared) :\ + (is_list ? (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL) :\ + __Pyx_GetItemInt_Generic(o, to_py_func(i)))) +#define __Pyx_GetItemInt_List(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck, has_gil, unsafe_shared)\ + (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ + __Pyx_GetItemInt_List_Fast(o, (Py_ssize_t)i, wraparound, boundscheck, unsafe_shared) :\ + (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL)) +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, + int wraparound, int boundscheck, int unsafe_shared); +#define __Pyx_GetItemInt_Tuple(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck, has_gil, unsafe_shared)\ + (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ + __Pyx_GetItemInt_Tuple_Fast(o, (Py_ssize_t)i, wraparound, boundscheck, unsafe_shared) :\ + (PyErr_SetString(PyExc_IndexError, "tuple index out of range"), (PyObject*)NULL)) +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, + int wraparound, int boundscheck, int unsafe_shared); +static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j); +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, + int is_list, int wraparound, int boundscheck, int unsafe_shared); + +/* ObjectGetItem.proto */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject *key); +#else +#define __Pyx_PyObject_GetItem(obj, key) PyObject_GetItem(obj, key) +#endif + +/* RejectKeywords.export */ +static void __Pyx_RejectKeywords(const char* function_name, PyObject *kwds); + +/* PyTypeError_Check.proto */ +#define __Pyx_PyExc_TypeError_Check(obj) __Pyx_TypeCheck(obj, PyExc_TypeError) + +/* DivInt[Py_ssize_t].proto */ +static CYTHON_INLINE Py_ssize_t __Pyx_div_Py_ssize_t(Py_ssize_t, Py_ssize_t, int b_is_constant); + +/* UnaryNegOverflows.proto */ +#define __Pyx_UNARY_NEG_WOULD_OVERFLOW(x)\ + (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x))) + +/* GetAttr3.proto */ +static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *, PyObject *, PyObject *); + +/* PyDictVersioning.proto (used by GetModuleGlobalName) */ +#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS +#define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1) +#define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag) +#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\ + (version_var) = __PYX_GET_DICT_VERSION(dict);\ + (cache_var) = (value); +#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\ + static PY_UINT64_T __pyx_dict_version = 0;\ + static PyObject *__pyx_dict_cached_value = NULL;\ + if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\ + (VAR) = __Pyx_XNewRef(__pyx_dict_cached_value);\ + } else {\ + (VAR) = __pyx_dict_cached_value = (LOOKUP);\ + __pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\ + }\ +} +static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj); +static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj); +static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version); +#else +#define __PYX_GET_DICT_VERSION(dict) (0) +#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) +#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP); +#endif + +/* GetModuleGlobalName.proto */ +#if CYTHON_USE_DICT_VERSIONS +#define __Pyx_GetModuleGlobalName(var, name) do {\ + static PY_UINT64_T __pyx_dict_version = 0;\ + static PyObject *__pyx_dict_cached_value = NULL;\ + (var) = (likely(__pyx_dict_version == __PYX_GET_DICT_VERSION(__pyx_mstate_global->__pyx_d))) ?\ + (likely(__pyx_dict_cached_value) ? __Pyx_NewRef(__pyx_dict_cached_value) : __Pyx_GetBuiltinName(name)) :\ + __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ +} while(0) +#define __Pyx_GetModuleGlobalNameUncached(var, name) do {\ + PY_UINT64_T __pyx_dict_version;\ + PyObject *__pyx_dict_cached_value;\ + (var) = __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ +} while(0) +static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value); +#else +#define __Pyx_GetModuleGlobalName(var, name) (var) = __Pyx__GetModuleGlobalName(name) +#define __Pyx_GetModuleGlobalNameUncached(var, name) (var) = __Pyx__GetModuleGlobalName(name) +static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name); +#endif + +/* AssertionsEnabled.proto */ +#if CYTHON_COMPILING_IN_LIMITED_API || PY_VERSION_HEX >= 0x030C0000 + static int __pyx_assertions_enabled_flag; + #define __pyx_assertions_enabled() (__pyx_assertions_enabled_flag) + #if __clang__ || __GNUC__ + __attribute__((no_sanitize("thread"))) + #endif + static int __Pyx_init_assertions_enabled(void) { + PyObject *builtins, *debug, *debug_str; + int flag; + builtins = PyEval_GetBuiltins(); + if (!builtins) goto bad; + debug_str = PyUnicode_FromStringAndSize("__debug__", 9); + if (!debug_str) goto bad; + debug = PyObject_GetItem(builtins, debug_str); + Py_DECREF(debug_str); + if (!debug) goto bad; + flag = PyObject_IsTrue(debug); + Py_DECREF(debug); + if (flag == -1) goto bad; + __pyx_assertions_enabled_flag = flag; + return 0; + bad: + __pyx_assertions_enabled_flag = 1; + return -1; + } +#else + #define __Pyx_init_assertions_enabled() (0) + #define __pyx_assertions_enabled() (!Py_OptimizeFlag) +#endif + +/* PyAssertionError_Check.proto */ +#define __Pyx_PyExc_AssertionError_Check(obj) __Pyx_TypeCheck(obj, PyExc_AssertionError) + +/* RaiseTooManyValuesToUnpack.proto */ +static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected); + +/* RaiseNeedMoreValuesToUnpack.proto */ +static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index); + +/* RaiseNoneIterError.proto */ +static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void); + +/* ExtTypeTest.proto */ +static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); + +/* GetTopmostException.proto (used by SaveResetException) */ +#if CYTHON_USE_EXC_INFO_STACK && CYTHON_FAST_THREAD_STATE +static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate); +#endif + +/* SaveResetException.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_ExceptionSave(type, value, tb) __Pyx__ExceptionSave(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#define __Pyx_ExceptionReset(type, value, tb) __Pyx__ExceptionReset(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); +#else +#define __Pyx_ExceptionSave(type, value, tb) PyErr_GetExcInfo(type, value, tb) +#define __Pyx_ExceptionReset(type, value, tb) PyErr_SetExcInfo(type, value, tb) +#endif + +/* GetException.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_GetException(type, value, tb) __Pyx__GetException(__pyx_tstate, type, value, tb) +static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#else +static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); +#endif + +/* SwapException.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_ExceptionSwap(type, value, tb) __Pyx__ExceptionSwap(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#else +static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value, PyObject **tb); +#endif + +/* HasAttr.proto (used by ImportImpl) */ +#if __PYX_LIMITED_VERSION_HEX >= 0x030d0000 +#define __Pyx_HasAttr(o, n) PyObject_HasAttrWithError(o, n) +#else +static CYTHON_INLINE int __Pyx_HasAttr(PyObject *, PyObject *); +#endif + +/* ImportImpl.export */ +static PyObject *__Pyx__Import(PyObject *name, PyObject *const *imported_names, Py_ssize_t len_imported_names, PyObject *qualname, PyObject *moddict, int level); + +/* Import.proto */ +static CYTHON_INLINE PyObject *__Pyx_Import(PyObject *name, PyObject *const *imported_names, Py_ssize_t len_imported_names, PyObject *qualname, int level); + +/* FastTypeChecks.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type) +#define __Pyx_TypeCheck2(obj, type1, type2) __Pyx_IsAnySubtype2(Py_TYPE(obj), (PyTypeObject *)type1, (PyTypeObject *)type2) +static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b); +static CYTHON_INLINE int __Pyx_IsAnySubtype2(PyTypeObject *cls, PyTypeObject *a, PyTypeObject *b); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2); +#else +#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) +#define __Pyx_TypeCheck2(obj, type1, type2) (PyObject_TypeCheck(obj, (PyTypeObject *)type1) || PyObject_TypeCheck(obj, (PyTypeObject *)type2)) +#define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type) +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2) { + return PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2); +} +#endif +#define __Pyx_PyErr_ExceptionMatches2(err1, err2) __Pyx_PyErr_GivenExceptionMatches2(__Pyx_PyErr_CurrentExceptionType(), err1, err2) +#define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception) +#ifdef PyExceptionInstance_Check + #define __Pyx_PyBaseException_Check(obj) PyExceptionInstance_Check(obj) +#else + #define __Pyx_PyBaseException_Check(obj) __Pyx_TypeCheck(obj, PyExc_BaseException) +#endif + +CYTHON_UNUSED static int __pyx_memoryview_getbuffer(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /*proto*/ +/* ListCompAppend.proto */ +#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS +static CYTHON_INLINE int __Pyx_ListComp_Append(PyObject* list, PyObject* x) { + PyListObject* L = (PyListObject*) list; + Py_ssize_t len = Py_SIZE(list); + if (likely(L->allocated > len)) { + Py_INCREF(x); + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030d0000 + L->ob_item[len] = x; + #else + PyList_SET_ITEM(list, len, x); + #endif + __Pyx_SET_SIZE(list, len + 1); + return 0; + } + return PyList_Append(list, x); +} +#else +#define __Pyx_ListComp_Append(L,x) PyList_Append(L,x) +#endif + +/* PySequenceMultiply.proto */ +#define __Pyx_PySequence_Multiply_Left(mul, seq) __Pyx_PySequence_Multiply(seq, mul) +#if !CYTHON_USE_TYPE_SLOTS +#define __Pyx_PySequence_Multiply PySequence_Repeat +#else +static CYTHON_INLINE PyObject* __Pyx_PySequence_Multiply(PyObject *seq, Py_ssize_t mul); +#endif + +/* PyObjectFormatAndDecref.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_FormatSimpleAndDecref(PyObject* s, PyObject* f); +static CYTHON_INLINE PyObject* __Pyx_PyObject_FormatAndDecref(PyObject* s, PyObject* f); + +/* PyObjectFormat.proto */ +#if CYTHON_USE_UNICODE_WRITER +static PyObject* __Pyx_PyObject_Format(PyObject* s, PyObject* f); +#else +#define __Pyx_PyObject_Format(s, f) PyObject_Format(s, f) +#endif + +/* SetItemInt.proto */ +#define __Pyx_SetItemInt(o, i, v, type, is_signed, to_py_func, is_list, wraparound, boundscheck, has_gil, unsafe_shared)\ + (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ + __Pyx_SetItemInt_Fast(o, (Py_ssize_t)i, v, is_list, wraparound, boundscheck, unsafe_shared) :\ + (is_list ? (PyErr_SetString(PyExc_IndexError, "list assignment index out of range"), -1) :\ + __Pyx_SetItemInt_Generic(o, to_py_func(i), v))) +static int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v); +static CYTHON_INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v, + int is_list, int wraparound, int boundscheck, int unsafe_shared); + +/* RaiseUnboundLocalError.proto */ +static void __Pyx_RaiseUnboundLocalError(const char *varname); + +/* PyIndexError_Check.proto */ +#define __Pyx_PyExc_IndexError_Check(obj) __Pyx_TypeCheck(obj, PyExc_IndexError) + +/* DivInt[long].proto */ +static CYTHON_INLINE long __Pyx_div_long(long, long, int b_is_constant); + +/* PyImportError_Check.proto */ +#define __Pyx_PyExc_ImportError_Check(obj) __Pyx_TypeCheck(obj, PyExc_ImportError) + +/* ReleaseUnknownGil.proto */ +#if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030d0000 +typedef struct { + PyThreadState* ts; + PyGILState_STATE gil_state; +} __Pyx_UnknownThreadState; +#else +#define __Pyx_UnknownThreadState PyThreadState* +#endif +static __Pyx_UnknownThreadState __Pyx_SaveUnknownThread(void); +static void __Pyx_RestoreUnknownThread(__Pyx_UnknownThreadState state); +static CYTHON_INLINE int __Pyx_UnknownThreadStateDefinitelyHadGil(__Pyx_UnknownThreadState state); +static CYTHON_INLINE int __Pyx_UnknownThreadStateMayHaveHadGil(__Pyx_UnknownThreadState state); + +/* ErrOccurredWithGIL.proto */ +static CYTHON_INLINE int __Pyx_ErrOccurredWithGIL(void); + +/* SharedInFreeThreading.proto */ +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING +#define __Pyx_shared_in_cpython_freethreading(x) shared(x) +#else +#define __Pyx_shared_in_cpython_freethreading(x) +#endif + +/* AllocateExtensionType.proto */ +static PyObject *__Pyx_AllocateExtensionType(PyTypeObject *t, int is_final); + +/* CallTypeTraverse.proto */ +#if !CYTHON_USE_TYPE_SPECS || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX < 0x03090000) +#define __Pyx_call_type_traverse(o, always_call, visit, arg) 0 +#else +static int __Pyx_call_type_traverse(PyObject *o, int always_call, visitproc visit, void *arg); +#endif + +/* LimitedApiGetTypeDict.proto (used by SetItemOnTypeDict) */ +#if CYTHON_COMPILING_IN_LIMITED_API +static PyObject *__Pyx_GetTypeDict(PyTypeObject *tp); +#endif + +/* SetItemOnTypeDict.proto (used by FixUpExtensionType) */ +static int __Pyx__SetItemOnTypeDict(PyTypeObject *tp, PyObject *k, PyObject *v); +#define __Pyx_SetItemOnTypeDict(tp, k, v) __Pyx__SetItemOnTypeDict((PyTypeObject*)tp, k, v) + +/* FixUpExtensionType.proto */ +static CYTHON_INLINE int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject *type); + +/* PyObjectCallNoArg.proto (used by PyObjectCallMethod0) */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func); + +/* PyObjectGetMethod.proto (used by PyObjectCallMethod0) */ +#if !(CYTHON_VECTORCALL && (__PYX_LIMITED_VERSION_HEX >= 0x030C0000 || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x03090000))) +static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method); +#endif + +/* PyObjectCallMethod0.proto (used by PyType_Ready) */ +static PyObject* __Pyx_PyObject_CallMethod0(PyObject* obj, PyObject* method_name); + +/* ValidateBasesTuple.proto (used by PyType_Ready) */ +#if CYTHON_COMPILING_IN_CPYTHON || CYTHON_COMPILING_IN_LIMITED_API || CYTHON_USE_TYPE_SPECS +static int __Pyx_validate_bases_tuple(const char *type_name, Py_ssize_t dictoffset, PyObject *bases); +#endif + +/* PyType_Ready.proto */ +CYTHON_UNUSED static int __Pyx_PyType_Ready(PyTypeObject *t); + +/* SetVTable.proto */ +static int __Pyx_SetVtable(PyTypeObject* typeptr , void* vtable); + +/* GetVTable.proto (used by MergeVTables) */ +static void* __Pyx_GetVtable(PyTypeObject *type); + +/* MergeVTables.proto */ +static int __Pyx_MergeVtables(PyTypeObject *type); + +/* DelItemOnTypeDict.proto (used by SetupReduce) */ +static int __Pyx__DelItemOnTypeDict(PyTypeObject *tp, PyObject *k); +#define __Pyx_DelItemOnTypeDict(tp, k) __Pyx__DelItemOnTypeDict((PyTypeObject*)tp, k) + +/* SetupReduce.proto */ +static int __Pyx_setup_reduce(PyObject* type_obj); + +/* TypeImport.proto */ +#ifndef __PYX_HAVE_RT_ImportType_proto_3_2_5 +#define __PYX_HAVE_RT_ImportType_proto_3_2_5 +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +#include +#endif +#if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || __cplusplus >= 201103L +#define __PYX_GET_STRUCT_ALIGNMENT_3_2_5(s) alignof(s) +#else +#define __PYX_GET_STRUCT_ALIGNMENT_3_2_5(s) sizeof(void*) +#endif +enum __Pyx_ImportType_CheckSize_3_2_5 { + __Pyx_ImportType_CheckSize_Error_3_2_5 = 0, + __Pyx_ImportType_CheckSize_Warn_3_2_5 = 1, + __Pyx_ImportType_CheckSize_Ignore_3_2_5 = 2 +}; +static PyTypeObject *__Pyx_ImportType_3_2_5(PyObject* module, const char *module_name, const char *class_name, size_t size, size_t alignment, enum __Pyx_ImportType_CheckSize_3_2_5 check_size); +#endif + +/* dict_setdefault.proto (used by FetchCommonType) */ +static CYTHON_INLINE PyObject *__Pyx_PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *default_value); + +/* AddModuleRef.proto (used by FetchSharedCythonModule) */ +#if ((CYTHON_COMPILING_IN_CPYTHON_FREETHREADING ) ||\ + __PYX_LIMITED_VERSION_HEX < 0x030d0000) + static PyObject *__Pyx_PyImport_AddModuleRef(const char *name); +#else + #define __Pyx_PyImport_AddModuleRef(name) PyImport_AddModuleRef(name) +#endif + +/* FetchSharedCythonModule.proto (used by FetchCommonType) */ +static PyObject *__Pyx_FetchSharedCythonABIModule(void); + +/* FetchCommonType.proto (used by CommonTypesMetaclass) */ +static PyTypeObject* __Pyx_FetchCommonTypeFromSpec(PyTypeObject *metaclass, PyObject *module, PyType_Spec *spec, PyObject *bases); + +/* CommonTypesMetaclass.proto (used by CythonFunctionShared) */ +static int __pyx_CommonTypesMetaclass_init(PyObject *module); +#define __Pyx_CommonTypesMetaclass_USED + +/* PyMethodNew.proto (used by CythonFunctionShared) */ +static PyObject *__Pyx_PyMethod_New(PyObject *func, PyObject *self, PyObject *typ); + +/* PyVectorcallFastCallDict.proto (used by CythonFunctionShared) */ +#if CYTHON_METH_FASTCALL && CYTHON_VECTORCALL +static CYTHON_INLINE PyObject *__Pyx_PyVectorcall_FastCallDict(PyObject *func, __pyx_vectorcallfunc vc, PyObject *const *args, size_t nargs, PyObject *kw); +#endif + +/* CythonFunctionShared.proto (used by CythonFunction) */ +#define __Pyx_CyFunction_USED +#define __Pyx_CYFUNCTION_STATICMETHOD 0x01 +#define __Pyx_CYFUNCTION_CLASSMETHOD 0x02 +#define __Pyx_CYFUNCTION_CCLASS 0x04 +#define __Pyx_CYFUNCTION_COROUTINE 0x08 +#define __Pyx_CyFunction_GetClosure(f)\ + (((__pyx_CyFunctionObject *) (f))->func_closure) +#if PY_VERSION_HEX < 0x030900B1 || CYTHON_COMPILING_IN_LIMITED_API + #define __Pyx_CyFunction_GetClassObj(f)\ + (((__pyx_CyFunctionObject *) (f))->func_classobj) +#else + #define __Pyx_CyFunction_GetClassObj(f)\ + ((PyObject*) ((PyCMethodObject *) (f))->mm_class) +#endif +#define __Pyx_CyFunction_SetClassObj(f, classobj)\ + __Pyx__CyFunction_SetClassObj((__pyx_CyFunctionObject *) (f), (classobj)) +#define __Pyx_CyFunction_Defaults(type, f)\ + ((type *)(((__pyx_CyFunctionObject *) (f))->defaults)) +#define __Pyx_CyFunction_SetDefaultsGetter(f, g)\ + ((__pyx_CyFunctionObject *) (f))->defaults_getter = (g) +typedef struct { +#if CYTHON_COMPILING_IN_LIMITED_API + PyObject_HEAD + PyObject *func; +#elif PY_VERSION_HEX < 0x030900B1 + PyCFunctionObject func; +#else + PyCMethodObject func; +#endif +#if CYTHON_COMPILING_IN_LIMITED_API && CYTHON_METH_FASTCALL + __pyx_vectorcallfunc func_vectorcall; +#endif +#if CYTHON_COMPILING_IN_LIMITED_API + PyObject *func_weakreflist; +#endif +#if PY_VERSION_HEX < 0x030C0000 || CYTHON_COMPILING_IN_LIMITED_API + PyObject *func_dict; +#endif + PyObject *func_name; + PyObject *func_qualname; + PyObject *func_doc; + PyObject *func_globals; + PyObject *func_code; + PyObject *func_closure; +#if PY_VERSION_HEX < 0x030900B1 || CYTHON_COMPILING_IN_LIMITED_API + PyObject *func_classobj; +#endif + PyObject *defaults; + int flags; + PyObject *defaults_tuple; + PyObject *defaults_kwdict; + PyObject *(*defaults_getter)(PyObject *); + PyObject *func_annotations; + PyObject *func_is_coroutine; +} __pyx_CyFunctionObject; +#undef __Pyx_CyOrPyCFunction_Check +#define __Pyx_CyFunction_Check(obj) __Pyx_TypeCheck(obj, __pyx_mstate_global->__pyx_CyFunctionType) +#define __Pyx_CyOrPyCFunction_Check(obj) __Pyx_TypeCheck2(obj, __pyx_mstate_global->__pyx_CyFunctionType, &PyCFunction_Type) +#define __Pyx_CyFunction_CheckExact(obj) __Pyx_IS_TYPE(obj, __pyx_mstate_global->__pyx_CyFunctionType) +static CYTHON_INLINE int __Pyx__IsSameCyOrCFunction(PyObject *func, void (*cfunc)(void)); +#undef __Pyx_IsSameCFunction +#define __Pyx_IsSameCFunction(func, cfunc) __Pyx__IsSameCyOrCFunction(func, cfunc) +static PyObject *__Pyx_CyFunction_Init(__pyx_CyFunctionObject* op, PyMethodDef *ml, + int flags, PyObject* qualname, + PyObject *closure, + PyObject *module, PyObject *globals, + PyObject* code); +static CYTHON_INLINE void __Pyx__CyFunction_SetClassObj(__pyx_CyFunctionObject* f, PyObject* classobj); +static CYTHON_INLINE PyObject *__Pyx_CyFunction_InitDefaults(PyObject *func, + PyTypeObject *defaults_type); +static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsTuple(PyObject *m, + PyObject *tuple); +static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsKwDict(PyObject *m, + PyObject *dict); +static CYTHON_INLINE void __Pyx_CyFunction_SetAnnotationsDict(PyObject *m, + PyObject *dict); +static int __pyx_CyFunction_init(PyObject *module); +#if CYTHON_METH_FASTCALL +static PyObject * __Pyx_CyFunction_Vectorcall_NOARGS(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); +static PyObject * __Pyx_CyFunction_Vectorcall_O(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); +static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); +static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS_METHOD(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); +#if CYTHON_COMPILING_IN_LIMITED_API +#define __Pyx_CyFunction_func_vectorcall(f) (((__pyx_CyFunctionObject*)f)->func_vectorcall) +#else +#define __Pyx_CyFunction_func_vectorcall(f) (((PyCFunctionObject*)f)->vectorcall) +#endif +#endif + +/* CythonFunction.proto */ +static PyObject *__Pyx_CyFunction_New(PyMethodDef *ml, + int flags, PyObject* qualname, + PyObject *closure, + PyObject *module, PyObject *globals, + PyObject* code); + +/* CLineInTraceback.proto (used by AddTraceback) */ +#if CYTHON_CLINE_IN_TRACEBACK && CYTHON_CLINE_IN_TRACEBACK_RUNTIME +static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line); +#else +#define __Pyx_CLineForTraceback(tstate, c_line) (((CYTHON_CLINE_IN_TRACEBACK)) ? c_line : 0) +#endif + +/* CodeObjectCache.proto (used by AddTraceback) */ +#if CYTHON_COMPILING_IN_LIMITED_API +typedef PyObject __Pyx_CachedCodeObjectType; +#else +typedef PyCodeObject __Pyx_CachedCodeObjectType; +#endif +typedef struct { + __Pyx_CachedCodeObjectType* code_object; + int code_line; +} __Pyx_CodeObjectCacheEntry; +struct __Pyx_CodeObjectCache { + int count; + int max_count; + __Pyx_CodeObjectCacheEntry* entries; + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + __pyx_atomic_int_type accessor_count; + #endif +}; +static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line); +static __Pyx_CachedCodeObjectType *__pyx_find_code_object(int code_line); +static void __pyx_insert_code_object(int code_line, __Pyx_CachedCodeObjectType* code_object); + +/* AddTraceback.proto */ +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename); + +/* BufferStructDeclare.proto */ +typedef struct { + Py_ssize_t shape, strides, suboffsets; +} __Pyx_Buf_DimInfo; +typedef struct { + size_t refcount; + Py_buffer pybuffer; +} __Pyx_Buffer; +typedef struct { + __Pyx_Buffer *rcbuffer; + char *data; + __Pyx_Buf_DimInfo diminfo[8]; +} __Pyx_LocalBuf_ND; + +/* MemviewRefcount.proto */ +static CYTHON_INLINE int __pyx_add_acquisition_count_locked( + __pyx_atomic_int_type *acquisition_count, PyThread_type_lock lock); +static CYTHON_INLINE int __pyx_sub_acquisition_count_locked( + __pyx_atomic_int_type *acquisition_count, PyThread_type_lock lock); +#define __pyx_get_slice_count_pointer(memview) (&memview->acquisition_count) +#define __PYX_INC_MEMVIEW(slice, have_gil) __Pyx_INC_MEMVIEW(slice, have_gil, __LINE__) +#define __PYX_XCLEAR_MEMVIEW(slice, have_gil) __Pyx_XCLEAR_MEMVIEW(slice, have_gil, __LINE__) +static CYTHON_INLINE void __Pyx_INC_MEMVIEW(__Pyx_memviewslice *, int, int); +static CYTHON_INLINE void __Pyx_XCLEAR_MEMVIEW(__Pyx_memviewslice *, int, int); + +/* MemviewSliceIsContig.proto */ +static int __pyx_memviewslice_is_contig(const __Pyx_memviewslice mvs, char order, int ndim); + +/* OverlappingSlices.proto */ +static int __pyx_slices_overlap(__Pyx_memviewslice *slice1, + __Pyx_memviewslice *slice2, + int ndim, size_t itemsize); + +/* MemviewSliceInit.proto */ +static int __Pyx_init_memviewslice( + struct __pyx_memoryview_obj *memview, + int ndim, + __Pyx_memviewslice *memviewslice, + int memview_is_new_reference); + +/* SliceMemoryviewSlice.proto */ +static CYTHON_INLINE int __pyx_memoryview_slice_memviewslice( + __Pyx_memviewslice *dst, + Py_ssize_t shape, Py_ssize_t stride, Py_ssize_t suboffset, + int dim, int new_ndim, int *suboffset_dim, + Py_ssize_t start, Py_ssize_t stop, Py_ssize_t step, + int have_start, int have_stop, int have_step, + int is_slice); + +/* IsLittleEndian.proto (used by BufferFormatCheck) */ +static CYTHON_INLINE int __Pyx_Is_Little_Endian(void); + +/* BufferFormatCheck.proto (used by MemviewSliceValidateAndInit) */ +static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts); +static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx, + __Pyx_BufFmt_StackElem* stack, + const __Pyx_TypeInfo* type); + +/* TypeInfoCompare.proto (used by MemviewSliceValidateAndInit) */ +static int __pyx_typeinfo_cmp(const __Pyx_TypeInfo *a, const __Pyx_TypeInfo *b); + +/* MemviewSliceValidateAndInit.export */ +static int __Pyx_ValidateAndInit_memviewslice( + int *axes_specs, + int c_or_f_flag, + int buf_flags, + int ndim, + const __Pyx_TypeInfo *dtype, + __Pyx_BufFmt_StackElem stack[], + __Pyx_memviewslice *memviewslice, + PyObject *original_obj); + +/* ObjectToMemviewSlice.proto */ +static CYTHON_INLINE __Pyx_memviewslice __Pyx_PyObject_to_MemoryviewSlice_d_d_dc_int(PyObject *, int writable_flag); + +/* ObjectToMemviewSlice.proto */ +static CYTHON_INLINE __Pyx_memviewslice __Pyx_PyObject_to_MemoryviewSlice_d_d_dc_float(PyObject *, int writable_flag); + +/* ObjectToMemviewSlice.proto */ +static CYTHON_INLINE __Pyx_memviewslice __Pyx_PyObject_to_MemoryviewSlice_dc_int(PyObject *, int writable_flag); + +/* RealImag.proto */ +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + #define __Pyx_CREAL(z) ((z).real()) + #define __Pyx_CIMAG(z) ((z).imag()) + #else + #define __Pyx_CREAL(z) (__real__(z)) + #define __Pyx_CIMAG(z) (__imag__(z)) + #endif +#else + #define __Pyx_CREAL(z) ((z).real) + #define __Pyx_CIMAG(z) ((z).imag) +#endif +#if defined(__cplusplus) && CYTHON_CCOMPLEX\ + && (defined(_WIN32) || defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 5 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4 )) || __cplusplus >= 201103) + #define __Pyx_SET_CREAL(z,x) ((z).real(x)) + #define __Pyx_SET_CIMAG(z,y) ((z).imag(y)) +#else + #define __Pyx_SET_CREAL(z,x) __Pyx_CREAL(z) = (x) + #define __Pyx_SET_CIMAG(z,y) __Pyx_CIMAG(z) = (y) +#endif + +/* Arithmetic.proto */ +#if CYTHON_CCOMPLEX && (1) && (!0 || __cplusplus) + #define __Pyx_c_eq_float(a, b) ((a)==(b)) + #define __Pyx_c_sum_float(a, b) ((a)+(b)) + #define __Pyx_c_diff_float(a, b) ((a)-(b)) + #define __Pyx_c_prod_float(a, b) ((a)*(b)) + #define __Pyx_c_quot_float(a, b) ((a)/(b)) + #define __Pyx_c_neg_float(a) (-(a)) + #ifdef __cplusplus + #define __Pyx_c_is_zero_float(z) ((z)==(float)0) + #define __Pyx_c_conj_float(z) (::std::conj(z)) + #if 1 + #define __Pyx_c_abs_float(z) (::std::abs(z)) + #define __Pyx_c_pow_float(a, b) (::std::pow(a, b)) + #endif + #else + #define __Pyx_c_is_zero_float(z) ((z)==0) + #define __Pyx_c_conj_float(z) (conjf(z)) + #if 1 + #define __Pyx_c_abs_float(z) (cabsf(z)) + #define __Pyx_c_pow_float(a, b) (cpowf(a, b)) + #endif + #endif +#else + static CYTHON_INLINE int __Pyx_c_eq_float(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sum_float(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_diff_float(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prod_float(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_neg_float(__pyx_t_float_complex); + static CYTHON_INLINE int __Pyx_c_is_zero_float(__pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conj_float(__pyx_t_float_complex); + #if 1 + static CYTHON_INLINE float __Pyx_c_abs_float(__pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_pow_float(__pyx_t_float_complex, __pyx_t_float_complex); + #endif +#endif + +/* Arithmetic.proto */ +#if CYTHON_CCOMPLEX && (1) && (!0 || __cplusplus) + #define __Pyx_c_eq_double(a, b) ((a)==(b)) + #define __Pyx_c_sum_double(a, b) ((a)+(b)) + #define __Pyx_c_diff_double(a, b) ((a)-(b)) + #define __Pyx_c_prod_double(a, b) ((a)*(b)) + #define __Pyx_c_quot_double(a, b) ((a)/(b)) + #define __Pyx_c_neg_double(a) (-(a)) + #ifdef __cplusplus + #define __Pyx_c_is_zero_double(z) ((z)==(double)0) + #define __Pyx_c_conj_double(z) (::std::conj(z)) + #if 1 + #define __Pyx_c_abs_double(z) (::std::abs(z)) + #define __Pyx_c_pow_double(a, b) (::std::pow(a, b)) + #endif + #else + #define __Pyx_c_is_zero_double(z) ((z)==0) + #define __Pyx_c_conj_double(z) (conj(z)) + #if 1 + #define __Pyx_c_abs_double(z) (cabs(z)) + #define __Pyx_c_pow_double(a, b) (cpow(a, b)) + #endif + #endif +#else + static CYTHON_INLINE int __Pyx_c_eq_double(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum_double(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff_double(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod_double(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg_double(__pyx_t_double_complex); + static CYTHON_INLINE int __Pyx_c_is_zero_double(__pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj_double(__pyx_t_double_complex); + #if 1 + static CYTHON_INLINE double __Pyx_c_abs_double(__pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_pow_double(__pyx_t_double_complex, __pyx_t_double_complex); + #endif +#endif + +/* Arithmetic.proto */ +#if CYTHON_CCOMPLEX && (1) && (!0 || __cplusplus) + #define __Pyx_c_eq_long__double(a, b) ((a)==(b)) + #define __Pyx_c_sum_long__double(a, b) ((a)+(b)) + #define __Pyx_c_diff_long__double(a, b) ((a)-(b)) + #define __Pyx_c_prod_long__double(a, b) ((a)*(b)) + #define __Pyx_c_quot_long__double(a, b) ((a)/(b)) + #define __Pyx_c_neg_long__double(a) (-(a)) + #ifdef __cplusplus + #define __Pyx_c_is_zero_long__double(z) ((z)==(long double)0) + #define __Pyx_c_conj_long__double(z) (::std::conj(z)) + #if 1 + #define __Pyx_c_abs_long__double(z) (::std::abs(z)) + #define __Pyx_c_pow_long__double(a, b) (::std::pow(a, b)) + #endif + #else + #define __Pyx_c_is_zero_long__double(z) ((z)==0) + #define __Pyx_c_conj_long__double(z) (conjl(z)) + #if 1 + #define __Pyx_c_abs_long__double(z) (cabsl(z)) + #define __Pyx_c_pow_long__double(a, b) (cpowl(a, b)) + #endif + #endif +#else + static CYTHON_INLINE int __Pyx_c_eq_long__double(__pyx_t_long_double_complex, __pyx_t_long_double_complex); + static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_sum_long__double(__pyx_t_long_double_complex, __pyx_t_long_double_complex); + static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_diff_long__double(__pyx_t_long_double_complex, __pyx_t_long_double_complex); + static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_prod_long__double(__pyx_t_long_double_complex, __pyx_t_long_double_complex); + static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_quot_long__double(__pyx_t_long_double_complex, __pyx_t_long_double_complex); + static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_neg_long__double(__pyx_t_long_double_complex); + static CYTHON_INLINE int __Pyx_c_is_zero_long__double(__pyx_t_long_double_complex); + static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_conj_long__double(__pyx_t_long_double_complex); + #if 1 + static CYTHON_INLINE long double __Pyx_c_abs_long__double(__pyx_t_long_double_complex); + static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_pow_long__double(__pyx_t_long_double_complex, __pyx_t_long_double_complex); + #endif +#endif + +/* MemviewSliceCopy.proto */ +static __Pyx_memviewslice +__pyx_memoryview_copy_new_contig(const __Pyx_memviewslice *from_mvs, + const char *mode, int ndim, + size_t sizeof_dtype, int contig_flag, + int dtype_is_object); + +/* PyObjectVectorCallKwBuilder.proto (used by CIntToPy) */ +CYTHON_UNUSED static int __Pyx_VectorcallBuilder_AddArg_Check(PyObject *key, PyObject *value, PyObject *builder, PyObject **args, int n); +#if CYTHON_VECTORCALL +#if PY_VERSION_HEX >= 0x03090000 +#define __Pyx_Object_Vectorcall_CallFromBuilder PyObject_Vectorcall +#else +#define __Pyx_Object_Vectorcall_CallFromBuilder _PyObject_Vectorcall +#endif +#define __Pyx_MakeVectorcallBuilderKwds(n) PyTuple_New(n) +static int __Pyx_VectorcallBuilder_AddArg(PyObject *key, PyObject *value, PyObject *builder, PyObject **args, int n); +static int __Pyx_VectorcallBuilder_AddArgStr(const char *key, PyObject *value, PyObject *builder, PyObject **args, int n); +#else +#define __Pyx_Object_Vectorcall_CallFromBuilder __Pyx_PyObject_FastCallDict +#define __Pyx_MakeVectorcallBuilderKwds(n) __Pyx_PyDict_NewPresized(n) +#define __Pyx_VectorcallBuilder_AddArg(key, value, builder, args, n) PyDict_SetItem(builder, key, value) +#define __Pyx_VectorcallBuilder_AddArgStr(key, value, builder, args, n) PyDict_SetItemString(builder, key, value) +#endif + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyLong_From_int(int value); + +/* CIntFromPy.proto */ +static CYTHON_INLINE int __Pyx_PyLong_As_int(PyObject *); + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyLong_From_long(long value); + +/* PyObjectCall2Args.proto (used by PyObjectCallMethod1) */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2); + +/* PyObjectCallMethod1.proto (used by UpdateUnpickledDict) */ +static PyObject* __Pyx_PyObject_CallMethod1(PyObject* obj, PyObject* method_name, PyObject* arg); + +/* UpdateUnpickledDict.proto */ +static int __Pyx_UpdateUnpickledDict(PyObject *obj, PyObject *state, Py_ssize_t index); + +/* CheckUnpickleChecksum.proto */ +static CYTHON_INLINE int __Pyx_CheckUnpickleChecksum(long checksum, long checksum1, long checksum2, long checksum3, const char *members); + +/* CIntFromPy.proto */ +static CYTHON_INLINE long __Pyx_PyLong_As_long(PyObject *); + +/* CIntFromPy.proto */ +static CYTHON_INLINE char __Pyx_PyLong_As_char(PyObject *); + +/* FormatTypeName.proto */ +#if CYTHON_COMPILING_IN_LIMITED_API +typedef PyObject *__Pyx_TypeName; +#define __Pyx_FMT_TYPENAME "%U" +#define __Pyx_DECREF_TypeName(obj) Py_XDECREF(obj) +#if __PYX_LIMITED_VERSION_HEX >= 0x030d0000 +#define __Pyx_PyType_GetFullyQualifiedName PyType_GetFullyQualifiedName +#else +static __Pyx_TypeName __Pyx_PyType_GetFullyQualifiedName(PyTypeObject* tp); +#endif +#else // !LIMITED_API +typedef const char *__Pyx_TypeName; +#define __Pyx_FMT_TYPENAME "%.200s" +#define __Pyx_PyType_GetFullyQualifiedName(tp) ((tp)->tp_name) +#define __Pyx_DECREF_TypeName(obj) +#endif + +/* GetRuntimeVersion.proto */ +#if __PYX_LIMITED_VERSION_HEX < 0x030b0000 +static unsigned long __Pyx_cached_runtime_version = 0; +static void __Pyx_init_runtime_version(void); +#else +#define __Pyx_init_runtime_version() +#endif +static unsigned long __Pyx_get_runtime_version(void); + +/* CheckBinaryVersion.proto */ +static int __Pyx_check_binary_version(unsigned long ct_version, unsigned long rt_version, int allow_newer); + +/* DecompressString.proto */ +static PyObject *__Pyx_DecompressString(const char *s, Py_ssize_t length, int algo); + +/* MultiPhaseInitModuleState.proto */ +#if CYTHON_PEP489_MULTI_PHASE_INIT && CYTHON_USE_MODULE_STATE +static PyObject *__Pyx_State_FindModule(void*); +static int __Pyx_State_AddModule(PyObject* module, void*); +static int __Pyx_State_RemoveModule(void*); +#elif CYTHON_USE_MODULE_STATE +#define __Pyx_State_FindModule PyState_FindModule +#define __Pyx_State_AddModule PyState_AddModule +#define __Pyx_State_RemoveModule PyState_RemoveModule +#endif + +/* #### Code section: module_declarations ### */ +/* CythonABIVersion.proto */ +#if CYTHON_COMPILING_IN_LIMITED_API + #if CYTHON_METH_FASTCALL + #define __PYX_FASTCALL_ABI_SUFFIX "_fastcall" + #else + #define __PYX_FASTCALL_ABI_SUFFIX + #endif + #define __PYX_LIMITED_ABI_SUFFIX "limited" __PYX_FASTCALL_ABI_SUFFIX __PYX_AM_SEND_ABI_SUFFIX +#else + #define __PYX_LIMITED_ABI_SUFFIX +#endif +#if __PYX_HAS_PY_AM_SEND == 1 + #define __PYX_AM_SEND_ABI_SUFFIX +#elif __PYX_HAS_PY_AM_SEND == 2 + #define __PYX_AM_SEND_ABI_SUFFIX "amsendbackport" +#else + #define __PYX_AM_SEND_ABI_SUFFIX "noamsend" +#endif +#ifndef __PYX_MONITORING_ABI_SUFFIX + #define __PYX_MONITORING_ABI_SUFFIX +#endif +#if CYTHON_USE_TP_FINALIZE + #define __PYX_TP_FINALIZE_ABI_SUFFIX +#else + #define __PYX_TP_FINALIZE_ABI_SUFFIX "nofinalize" +#endif +#if CYTHON_USE_FREELISTS || !defined(__Pyx_AsyncGen_USED) + #define __PYX_FREELISTS_ABI_SUFFIX +#else + #define __PYX_FREELISTS_ABI_SUFFIX "nofreelists" +#endif +#define CYTHON_ABI __PYX_ABI_VERSION __PYX_LIMITED_ABI_SUFFIX __PYX_MONITORING_ABI_SUFFIX __PYX_TP_FINALIZE_ABI_SUFFIX __PYX_FREELISTS_ABI_SUFFIX __PYX_AM_SEND_ABI_SUFFIX +#define __PYX_ABI_MODULE_NAME "_cython_" CYTHON_ABI +#define __PYX_TYPE_MODULE_PREFIX __PYX_ABI_MODULE_NAME "." + +static PyObject *__pyx_array_get_memview(struct __pyx_array_obj *__pyx_v_self); /* proto*/ +static char *__pyx_memoryview_get_item_pointer(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_index); /* proto*/ +static PyObject *__pyx_memoryview_is_slice(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_obj); /* proto*/ +static PyObject *__pyx_memoryview_setitem_slice_assignment(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_dst, PyObject *__pyx_v_src); /* proto*/ +static PyObject *__pyx_memoryview_setitem_slice_assign_scalar(struct __pyx_memoryview_obj *__pyx_v_self, struct __pyx_memoryview_obj *__pyx_v_dst, PyObject *__pyx_v_value); /* proto*/ +static PyObject *__pyx_memoryview_setitem_indexed(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_index, PyObject *__pyx_v_value); /* proto*/ +static PyObject *__pyx_memoryview_convert_item_to_object(struct __pyx_memoryview_obj *__pyx_v_self, char *__pyx_v_itemp); /* proto*/ +static PyObject *__pyx_memoryview_assign_item_from_object(struct __pyx_memoryview_obj *__pyx_v_self, char *__pyx_v_itemp, PyObject *__pyx_v_value); /* proto*/ +static PyObject *__pyx_memoryview__get_base(struct __pyx_memoryview_obj *__pyx_v_self); /* proto*/ +static PyObject *__pyx_memoryviewslice_convert_item_to_object(struct __pyx_memoryviewslice_obj *__pyx_v_self, char *__pyx_v_itemp); /* proto*/ +static PyObject *__pyx_memoryviewslice_assign_item_from_object(struct __pyx_memoryviewslice_obj *__pyx_v_self, char *__pyx_v_itemp, PyObject *__pyx_v_value); /* proto*/ +static PyObject *__pyx_memoryviewslice__get_base(struct __pyx_memoryviewslice_obj *__pyx_v_self); /* proto*/ +static CYTHON_INLINE npy_intp __pyx_f_5numpy_5dtype_8itemsize_itemsize(PyArray_Descr *__pyx_v_self); /* proto*/ +static CYTHON_INLINE npy_intp __pyx_f_5numpy_5dtype_9alignment_alignment(PyArray_Descr *__pyx_v_self); /* proto*/ +static CYTHON_INLINE PyObject *__pyx_f_5numpy_5dtype_6fields_fields(PyArray_Descr *__pyx_v_self); /* proto*/ +static CYTHON_INLINE PyObject *__pyx_f_5numpy_5dtype_5names_names(PyArray_Descr *__pyx_v_self); /* proto*/ +static CYTHON_INLINE PyArray_ArrayDescr *__pyx_f_5numpy_5dtype_8subarray_subarray(PyArray_Descr *__pyx_v_self); /* proto*/ +static CYTHON_INLINE npy_uint64 __pyx_f_5numpy_5dtype_5flags_flags(PyArray_Descr *__pyx_v_self); /* proto*/ +static CYTHON_INLINE int __pyx_f_5numpy_9broadcast_7numiter_numiter(PyArrayMultiIterObject *__pyx_v_self); /* proto*/ +static CYTHON_INLINE npy_intp __pyx_f_5numpy_9broadcast_4size_size(PyArrayMultiIterObject *__pyx_v_self); /* proto*/ +static CYTHON_INLINE npy_intp __pyx_f_5numpy_9broadcast_5index_index(PyArrayMultiIterObject *__pyx_v_self); /* proto*/ +static CYTHON_INLINE int __pyx_f_5numpy_9broadcast_2nd_nd(PyArrayMultiIterObject *__pyx_v_self); /* proto*/ +static CYTHON_INLINE npy_intp *__pyx_f_5numpy_9broadcast_10dimensions_dimensions(PyArrayMultiIterObject *__pyx_v_self); /* proto*/ +static CYTHON_INLINE void **__pyx_f_5numpy_9broadcast_5iters_iters(PyArrayMultiIterObject *__pyx_v_self); /* proto*/ +static CYTHON_INLINE PyObject *__pyx_f_5numpy_7ndarray_4base_base(PyArrayObject *__pyx_v_self); /* proto*/ +static CYTHON_INLINE PyArray_Descr *__pyx_f_5numpy_7ndarray_5descr_descr(PyArrayObject *__pyx_v_self); /* proto*/ +static CYTHON_INLINE int __pyx_f_5numpy_7ndarray_4ndim_ndim(PyArrayObject *__pyx_v_self); /* proto*/ +static CYTHON_INLINE npy_intp *__pyx_f_5numpy_7ndarray_5shape_shape(PyArrayObject *__pyx_v_self); /* proto*/ +static CYTHON_INLINE npy_intp *__pyx_f_5numpy_7ndarray_7strides_strides(PyArrayObject *__pyx_v_self); /* proto*/ +static CYTHON_INLINE npy_intp __pyx_f_5numpy_7ndarray_4size_size(PyArrayObject *__pyx_v_self); /* proto*/ +static CYTHON_INLINE char *__pyx_f_5numpy_7ndarray_4data_data(PyArrayObject *__pyx_v_self); /* proto*/ + +/* Module declarations from "cython.view" */ + +/* Module declarations from "cython.dataclasses" */ + +/* Module declarations from "cython" */ + +/* Module declarations from "libc.string" */ + +/* Module declarations from "libc.stdio" */ + +/* Module declarations from "__builtin__" */ + +/* Module declarations from "cpython.type" */ + +/* Module declarations from "cpython" */ + +/* Module declarations from "cpython.object" */ + +/* Module declarations from "cpython.ref" */ + +/* Module declarations from "numpy" */ + +/* Module declarations from "numpy" */ + +/* Module declarations from "matcha.utils.monotonic_align.core" */ +static PyObject *__pyx_collections_abc_Sequence = 0; +static PyObject *generic = 0; +static PyObject *strided = 0; +static PyObject *indirect = 0; +static PyObject *contiguous = 0; +static PyObject *indirect_contiguous = 0; +static int __pyx_memoryview_thread_locks_used; +static PyThread_type_lock __pyx_memoryview_thread_locks[8]; +static void __pyx_f_6matcha_5utils_15monotonic_align_4core_maximum_path_each(__Pyx_memviewslice, __Pyx_memviewslice, int, int, float); /*proto*/ +static void __pyx_f_6matcha_5utils_15monotonic_align_4core_maximum_path_c(__Pyx_memviewslice, __Pyx_memviewslice, __Pyx_memviewslice, __Pyx_memviewslice, int __pyx_skip_dispatch, struct __pyx_opt_args_6matcha_5utils_15monotonic_align_4core_maximum_path_c *__pyx_optional_args); /*proto*/ +static int __pyx_array_allocate_buffer(struct __pyx_array_obj *); /*proto*/ +static struct __pyx_array_obj *__pyx_array_new(PyObject *, Py_ssize_t, char *, char const *, char *); /*proto*/ +static PyObject *__pyx_memoryview_new(PyObject *, int, int, __Pyx_TypeInfo const *); /*proto*/ +static CYTHON_INLINE int __pyx_memoryview_check(PyObject *); /*proto*/ +static PyObject *_unellipsify(PyObject *, int); /*proto*/ +static int assert_direct_dimensions(Py_ssize_t *, int); /*proto*/ +static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_obj *, PyObject *); /*proto*/ +static char *__pyx_pybuffer_index(Py_buffer *, char *, Py_ssize_t, Py_ssize_t); /*proto*/ +static int __pyx_memslice_transpose(__Pyx_memviewslice *); /*proto*/ +static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice, int, PyObject *(*)(char *), int (*)(char *, PyObject *), int); /*proto*/ +static __Pyx_memviewslice *__pyx_memoryview_get_slice_from_memoryview(struct __pyx_memoryview_obj *, __Pyx_memviewslice *); /*proto*/ +static void __pyx_memoryview_slice_copy(struct __pyx_memoryview_obj *, __Pyx_memviewslice *); /*proto*/ +static PyObject *__pyx_memoryview_copy_object(struct __pyx_memoryview_obj *); /*proto*/ +static PyObject *__pyx_memoryview_copy_object_from_slice(struct __pyx_memoryview_obj *, __Pyx_memviewslice *); /*proto*/ +static Py_ssize_t abs_py_ssize_t(Py_ssize_t); /*proto*/ +static char __pyx_get_best_slice_order(__Pyx_memviewslice *, int); /*proto*/ +static void _copy_strided_to_strided(char *, Py_ssize_t *, char *, Py_ssize_t *, Py_ssize_t *, Py_ssize_t *, int, size_t); /*proto*/ +static void copy_strided_to_strided(__Pyx_memviewslice *, __Pyx_memviewslice *, int, size_t); /*proto*/ +static Py_ssize_t __pyx_memoryview_slice_get_size(__Pyx_memviewslice *, int); /*proto*/ +static Py_ssize_t __pyx_fill_contig_strides_array(Py_ssize_t *, Py_ssize_t *, Py_ssize_t, int, char); /*proto*/ +static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *, __Pyx_memviewslice *, char, int); /*proto*/ +static int __pyx_memoryview_err_extents(int, Py_ssize_t, Py_ssize_t); /*proto*/ +static int __pyx_memoryview_err_dim(PyObject *, PyObject *, int); /*proto*/ +static int __pyx_memoryview_err(PyObject *, PyObject *); /*proto*/ +static int __pyx_memoryview_err_no_memory(void); /*proto*/ +static int __pyx_memoryview_copy_contents(__Pyx_memviewslice, __Pyx_memviewslice, int, int, int); /*proto*/ +static void __pyx_memoryview_broadcast_leading(__Pyx_memviewslice *, int, int); /*proto*/ +static void __pyx_memoryview_refcount_copying(__Pyx_memviewslice *, int, int, int); /*proto*/ +static void __pyx_memoryview_refcount_objects_in_slice_with_gil(char *, Py_ssize_t *, Py_ssize_t *, int, int); /*proto*/ +static void __pyx_memoryview_refcount_objects_in_slice(char *, Py_ssize_t *, Py_ssize_t *, int, int); /*proto*/ +static void __pyx_memoryview_slice_assign_scalar(__Pyx_memviewslice *, int, size_t, void *, int); /*proto*/ +static void __pyx_memoryview__slice_assign_scalar(char *, Py_ssize_t *, Py_ssize_t *, int, size_t, void *); /*proto*/ +static PyObject *__pyx_unpickle_Enum__set_state(struct __pyx_MemviewEnum_obj *, PyObject *); /*proto*/ +/* #### Code section: typeinfo ### */ +static const __Pyx_TypeInfo __Pyx_TypeInfo_int = { "int", NULL, sizeof(int), { 0 }, 0, __PYX_IS_UNSIGNED(int) ? 'U' : 'I', __PYX_IS_UNSIGNED(int), 0 }; +static const __Pyx_TypeInfo __Pyx_TypeInfo_float = { "float", NULL, sizeof(float), { 0 }, 0, 'R', 0, 0 }; +/* #### Code section: before_global_var ### */ +#define __Pyx_MODULE_NAME "matcha.utils.monotonic_align.core" +extern int __pyx_module_is_main_matcha__utils__monotonic_align__core; +int __pyx_module_is_main_matcha__utils__monotonic_align__core = 0; + +/* Implementation of "matcha.utils.monotonic_align.core" */ +/* #### Code section: global_var ### */ +static PyObject *__pyx_builtin___import__; +static PyObject *__pyx_builtin_enumerate; +static PyObject *__pyx_builtin_Ellipsis; +static PyObject *__pyx_builtin_id; +/* #### Code section: string_decls ### */ +static const char __pyx_k_c[] = "c"; +static const char __pyx_k_name[] = "name"; +static const char __pyx_k_fortran[] = "fortran"; +/* #### Code section: decls ### */ +static int __pyx_array___pyx_pf_15View_dot_MemoryView_5array___cinit__(struct __pyx_array_obj *__pyx_v_self, PyObject *__pyx_v_shape, Py_ssize_t __pyx_v_itemsize, PyObject *__pyx_v_format, PyObject *__pyx_v_mode, int __pyx_v_allocate_buffer); /* proto */ +static int __pyx_array___pyx_pf_15View_dot_MemoryView_5array_2__getbuffer__(struct __pyx_array_obj *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /* proto */ +static void __pyx_array___pyx_pf_15View_dot_MemoryView_5array_4__dealloc__(struct __pyx_array_obj *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_15View_dot_MemoryView_5array_7memview___get__(struct __pyx_array_obj *__pyx_v_self); /* proto */ +static Py_ssize_t __pyx_array___pyx_pf_15View_dot_MemoryView_5array_6__len__(struct __pyx_array_obj *__pyx_v_self); /* proto */ +static PyObject *__pyx_array___pyx_pf_15View_dot_MemoryView_5array_8__getattr__(struct __pyx_array_obj *__pyx_v_self, PyObject *__pyx_v_attr); /* proto */ +static PyObject *__pyx_array___pyx_pf_15View_dot_MemoryView_5array_10__getitem__(struct __pyx_array_obj *__pyx_v_self, PyObject *__pyx_v_item); /* proto */ +static int __pyx_array___pyx_pf_15View_dot_MemoryView_5array_12__setitem__(struct __pyx_array_obj *__pyx_v_self, PyObject *__pyx_v_item, PyObject *__pyx_v_value); /* proto */ +static PyObject *__pyx_pf___pyx_array___reduce_cython__(CYTHON_UNUSED struct __pyx_array_obj *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf___pyx_array_2__setstate_cython__(CYTHON_UNUSED struct __pyx_array_obj *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */ +static int __pyx_MemviewEnum___pyx_pf_15View_dot_MemoryView_4Enum___init__(struct __pyx_MemviewEnum_obj *__pyx_v_self, PyObject *__pyx_v_name); /* proto */ +static PyObject *__pyx_MemviewEnum___pyx_pf_15View_dot_MemoryView_4Enum_2__repr__(struct __pyx_MemviewEnum_obj *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf___pyx_MemviewEnum___reduce_cython__(struct __pyx_MemviewEnum_obj *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf___pyx_MemviewEnum_2__setstate_cython__(struct __pyx_MemviewEnum_obj *__pyx_v_self, PyObject *__pyx_v___pyx_state); /* proto */ +static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview___cinit__(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_obj, int __pyx_v_flags, int __pyx_v_dtype_is_object); /* proto */ +static void __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_2__dealloc__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ +static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_4__getitem__(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_index); /* proto */ +static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_6__setitem__(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_index, PyObject *__pyx_v_value); /* proto */ +static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbuffer__(struct __pyx_memoryview_obj *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /* proto */ +static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_1T___get__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4base___get__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_5shape___get__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_7strides___get__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_10suboffsets___get__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4ndim___get__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_8itemsize___get__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_6nbytes___get__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4size___get__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ +static Py_ssize_t __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_10__len__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ +static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_12__repr__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ +static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_14__str__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ +static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_16is_c_contig(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ +static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_18is_f_contig(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ +static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_20copy(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ +static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_22copy_fortran(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf___pyx_memoryview___reduce_cython__(CYTHON_UNUSED struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf___pyx_memoryview_2__setstate_cython__(CYTHON_UNUSED struct __pyx_memoryview_obj *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */ +static void __pyx_memoryviewslice___pyx_pf_15View_dot_MemoryView_16_memoryviewslice___dealloc__(struct __pyx_memoryviewslice_obj *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf___pyx_memoryviewslice___reduce_cython__(CYTHON_UNUSED struct __pyx_memoryviewslice_obj *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf___pyx_memoryviewslice_2__setstate_cython__(CYTHON_UNUSED struct __pyx_memoryviewslice_obj *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */ +static PyObject *__pyx_pf_15View_dot_MemoryView___pyx_unpickle_Enum(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state); /* proto */ +static PyObject *__pyx_pf_6matcha_5utils_15monotonic_align_4core_maximum_path_c(CYTHON_UNUSED PyObject *__pyx_self, __Pyx_memviewslice __pyx_v_paths, __Pyx_memviewslice __pyx_v_values, __Pyx_memviewslice __pyx_v_t_xs, __Pyx_memviewslice __pyx_v_t_ys, float __pyx_v_max_neg_val); /* proto */ +static PyObject *__pyx_tp_new_array(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ +static PyObject *__pyx_tp_new_Enum(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ +static PyObject *__pyx_tp_new_memoryview(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ +static PyObject *__pyx_tp_new__memoryviewslice(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ +/* #### Code section: late_includes ### */ +/* #### Code section: module_state ### */ +/* SmallCodeConfig */ +#ifndef CYTHON_SMALL_CODE +#if defined(__clang__) + #define CYTHON_SMALL_CODE +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) + #define CYTHON_SMALL_CODE __attribute__((cold)) +#else + #define CYTHON_SMALL_CODE +#endif +#endif + +typedef struct { + PyObject *__pyx_d; + PyObject *__pyx_b; + PyObject *__pyx_cython_runtime; + PyObject *__pyx_empty_tuple; + PyObject *__pyx_empty_bytes; + PyObject *__pyx_empty_unicode; + PyTypeObject *__pyx_ptype_7cpython_4type_type; + PyTypeObject *__pyx_ptype_5numpy_dtype; + PyTypeObject *__pyx_ptype_5numpy_flatiter; + PyTypeObject *__pyx_ptype_5numpy_broadcast; + PyTypeObject *__pyx_ptype_5numpy_ndarray; + PyTypeObject *__pyx_ptype_5numpy_generic; + PyTypeObject *__pyx_ptype_5numpy_number; + PyTypeObject *__pyx_ptype_5numpy_integer; + PyTypeObject *__pyx_ptype_5numpy_signedinteger; + PyTypeObject *__pyx_ptype_5numpy_unsignedinteger; + PyTypeObject *__pyx_ptype_5numpy_inexact; + PyTypeObject *__pyx_ptype_5numpy_floating; + PyTypeObject *__pyx_ptype_5numpy_complexfloating; + PyTypeObject *__pyx_ptype_5numpy_flexible; + PyTypeObject *__pyx_ptype_5numpy_character; + PyTypeObject *__pyx_ptype_5numpy_ufunc; + PyObject *__pyx_type___pyx_array; + PyObject *__pyx_type___pyx_MemviewEnum; + PyObject *__pyx_type___pyx_memoryview; + PyObject *__pyx_type___pyx_memoryviewslice; + PyTypeObject *__pyx_array_type; + PyTypeObject *__pyx_MemviewEnum_type; + PyTypeObject *__pyx_memoryview_type; + PyTypeObject *__pyx_memoryviewslice_type; + __Pyx_CachedCFunction __pyx_umethod_PyDict_Type_items; + __Pyx_CachedCFunction __pyx_umethod_PyDict_Type_pop; + __Pyx_CachedCFunction __pyx_umethod_PyDict_Type_values; + float __pyx_k__6; + PyObject *__pyx_slice[1]; + PyObject *__pyx_tuple[1]; + PyObject *__pyx_codeobj_tab[1]; + PyObject *__pyx_string_tab[120]; + PyObject *__pyx_number_tab[4]; +/* #### Code section: module_state_contents ### */ +/* CommonTypesMetaclass.module_state_decls */ +PyTypeObject *__pyx_CommonTypesMetaclassType; + +/* CachedMethodType.module_state_decls */ +#if CYTHON_COMPILING_IN_LIMITED_API +PyObject *__Pyx_CachedMethodType; +#endif + +/* CythonFunctionShared.module_state_decls */ +PyTypeObject *__pyx_CyFunctionType; + +/* CodeObjectCache.module_state_decls */ +struct __Pyx_CodeObjectCache __pyx_code_cache; + +/* #### Code section: module_state_end ### */ +} __pyx_mstatetype; + +#if CYTHON_USE_MODULE_STATE +#ifdef __cplusplus +namespace { +extern struct PyModuleDef __pyx_moduledef; +} /* anonymous namespace */ +#else +static struct PyModuleDef __pyx_moduledef; +#endif + +#define __pyx_mstate_global (__Pyx_PyModule_GetState(__Pyx_State_FindModule(&__pyx_moduledef))) + +#define __pyx_m (__Pyx_State_FindModule(&__pyx_moduledef)) +#else +static __pyx_mstatetype __pyx_mstate_global_static = +#ifdef __cplusplus + {}; +#else + {0}; +#endif +static __pyx_mstatetype * const __pyx_mstate_global = &__pyx_mstate_global_static; +#endif +/* #### Code section: constant_name_defines ### */ +#define __pyx_kp_u_ __pyx_string_tab[0] +#define __pyx_kp_u_Buffer_view_does_not_expose_stri __pyx_string_tab[1] +#define __pyx_kp_u_Can_only_create_a_buffer_that_is __pyx_string_tab[2] +#define __pyx_kp_u_Cannot_assign_to_read_only_memor __pyx_string_tab[3] +#define __pyx_kp_u_Cannot_create_writable_memory_vi __pyx_string_tab[4] +#define __pyx_kp_u_Cannot_index_with_type __pyx_string_tab[5] +#define __pyx_kp_u_Cannot_transpose_memoryview_with __pyx_string_tab[6] +#define __pyx_kp_u_Dimension_d_is_not_direct __pyx_string_tab[7] +#define __pyx_kp_u_Empty_shape_tuple_for_cython_arr __pyx_string_tab[8] +#define __pyx_kp_u_Indirect_dimensions_not_supporte __pyx_string_tab[9] +#define __pyx_kp_u_Invalid_mode_expected_c_or_fortr __pyx_string_tab[10] +#define __pyx_kp_u_Invalid_shape_in_axis __pyx_string_tab[11] +#define __pyx_kp_u_MemoryView_of __pyx_string_tab[12] +#define __pyx_kp_u_Note_that_Cython_is_deliberately __pyx_string_tab[13] +#define __pyx_kp_u_Out_of_bounds_on_buffer_access_a __pyx_string_tab[14] +#define __pyx_kp_u_Unable_to_convert_item_to_object __pyx_string_tab[15] +#define __pyx_kp_u__2 __pyx_string_tab[16] +#define __pyx_kp_u__3 __pyx_string_tab[17] +#define __pyx_kp_u__4 __pyx_string_tab[18] +#define __pyx_kp_u__5 __pyx_string_tab[19] +#define __pyx_kp_u__7 __pyx_string_tab[20] +#define __pyx_kp_u_add_note __pyx_string_tab[21] +#define __pyx_kp_u_and __pyx_string_tab[22] +#define __pyx_kp_u_at_0x __pyx_string_tab[23] +#define __pyx_kp_u_collections_abc __pyx_string_tab[24] +#define __pyx_kp_u_contiguous_and_direct __pyx_string_tab[25] +#define __pyx_kp_u_contiguous_and_indirect __pyx_string_tab[26] +#define __pyx_kp_u_disable __pyx_string_tab[27] +#define __pyx_kp_u_enable __pyx_string_tab[28] +#define __pyx_kp_u_gc __pyx_string_tab[29] +#define __pyx_kp_u_got __pyx_string_tab[30] +#define __pyx_kp_u_got_differing_extents_in_dimensi __pyx_string_tab[31] +#define __pyx_kp_u_isenabled __pyx_string_tab[32] +#define __pyx_kp_u_itemsize_0_for_cython_array __pyx_string_tab[33] +#define __pyx_kp_u_matcha_utils_monotonic_align_cor_2 __pyx_string_tab[34] +#define __pyx_kp_u_no_default___reduce___due_to_non __pyx_string_tab[35] +#define __pyx_kp_u_numpy__core_multiarray_failed_to __pyx_string_tab[36] +#define __pyx_kp_u_numpy__core_umath_failed_to_impo __pyx_string_tab[37] +#define __pyx_kp_u_object __pyx_string_tab[38] +#define __pyx_kp_u_strided_and_direct __pyx_string_tab[39] +#define __pyx_kp_u_strided_and_direct_or_indirect __pyx_string_tab[40] +#define __pyx_kp_u_strided_and_indirect __pyx_string_tab[41] +#define __pyx_kp_u_unable_to_allocate_array_data __pyx_string_tab[42] +#define __pyx_kp_u_unable_to_allocate_shape_and_str __pyx_string_tab[43] +#define __pyx_n_u_ASCII __pyx_string_tab[44] +#define __pyx_n_u_Ellipsis __pyx_string_tab[45] +#define __pyx_n_u_Pyx_PyDict_NextRef __pyx_string_tab[46] +#define __pyx_n_u_Sequence __pyx_string_tab[47] +#define __pyx_n_u_View_MemoryView __pyx_string_tab[48] +#define __pyx_n_u_abc __pyx_string_tab[49] +#define __pyx_n_u_allocate_buffer __pyx_string_tab[50] +#define __pyx_n_u_asyncio_coroutines __pyx_string_tab[51] +#define __pyx_n_u_base __pyx_string_tab[52] +#define __pyx_n_u_c __pyx_string_tab[53] +#define __pyx_n_u_class __pyx_string_tab[54] +#define __pyx_n_u_class_getitem __pyx_string_tab[55] +#define __pyx_n_u_cline_in_traceback __pyx_string_tab[56] +#define __pyx_n_u_count __pyx_string_tab[57] +#define __pyx_n_u_dict __pyx_string_tab[58] +#define __pyx_n_u_dtype_is_object __pyx_string_tab[59] +#define __pyx_n_u_encode __pyx_string_tab[60] +#define __pyx_n_u_enumerate __pyx_string_tab[61] +#define __pyx_n_u_error __pyx_string_tab[62] +#define __pyx_n_u_flags __pyx_string_tab[63] +#define __pyx_n_u_format __pyx_string_tab[64] +#define __pyx_n_u_fortran __pyx_string_tab[65] +#define __pyx_n_u_func __pyx_string_tab[66] +#define __pyx_n_u_getstate __pyx_string_tab[67] +#define __pyx_n_u_id __pyx_string_tab[68] +#define __pyx_n_u_import __pyx_string_tab[69] +#define __pyx_n_u_index __pyx_string_tab[70] +#define __pyx_n_u_is_coroutine __pyx_string_tab[71] +#define __pyx_n_u_items __pyx_string_tab[72] +#define __pyx_n_u_itemsize __pyx_string_tab[73] +#define __pyx_n_u_main __pyx_string_tab[74] +#define __pyx_n_u_matcha_utils_monotonic_align_cor __pyx_string_tab[75] +#define __pyx_n_u_max_neg_val __pyx_string_tab[76] +#define __pyx_n_u_maximum_path_c __pyx_string_tab[77] +#define __pyx_n_u_memview __pyx_string_tab[78] +#define __pyx_n_u_mode __pyx_string_tab[79] +#define __pyx_n_u_module __pyx_string_tab[80] +#define __pyx_n_u_name __pyx_string_tab[81] +#define __pyx_n_u_name_2 __pyx_string_tab[82] +#define __pyx_n_u_ndim __pyx_string_tab[83] +#define __pyx_n_u_new __pyx_string_tab[84] +#define __pyx_n_u_np __pyx_string_tab[85] +#define __pyx_n_u_numpy __pyx_string_tab[86] +#define __pyx_n_u_obj __pyx_string_tab[87] +#define __pyx_n_u_pack __pyx_string_tab[88] +#define __pyx_n_u_paths __pyx_string_tab[89] +#define __pyx_n_u_pop __pyx_string_tab[90] +#define __pyx_n_u_pyx_checksum __pyx_string_tab[91] +#define __pyx_n_u_pyx_state __pyx_string_tab[92] +#define __pyx_n_u_pyx_type __pyx_string_tab[93] +#define __pyx_n_u_pyx_unpickle_Enum __pyx_string_tab[94] +#define __pyx_n_u_pyx_vtable __pyx_string_tab[95] +#define __pyx_n_u_qualname __pyx_string_tab[96] +#define __pyx_n_u_reduce __pyx_string_tab[97] +#define __pyx_n_u_reduce_cython __pyx_string_tab[98] +#define __pyx_n_u_reduce_ex __pyx_string_tab[99] +#define __pyx_n_u_register __pyx_string_tab[100] +#define __pyx_n_u_set_name __pyx_string_tab[101] +#define __pyx_n_u_setdefault __pyx_string_tab[102] +#define __pyx_n_u_setstate __pyx_string_tab[103] +#define __pyx_n_u_setstate_cython __pyx_string_tab[104] +#define __pyx_n_u_shape __pyx_string_tab[105] +#define __pyx_n_u_size __pyx_string_tab[106] +#define __pyx_n_u_start __pyx_string_tab[107] +#define __pyx_n_u_step __pyx_string_tab[108] +#define __pyx_n_u_stop __pyx_string_tab[109] +#define __pyx_n_u_struct __pyx_string_tab[110] +#define __pyx_n_u_t_xs __pyx_string_tab[111] +#define __pyx_n_u_t_ys __pyx_string_tab[112] +#define __pyx_n_u_test __pyx_string_tab[113] +#define __pyx_n_u_unpack __pyx_string_tab[114] +#define __pyx_n_u_update __pyx_string_tab[115] +#define __pyx_n_u_values __pyx_string_tab[116] +#define __pyx_n_u_x __pyx_string_tab[117] +#define __pyx_kp_b_iso88591_uvvw_vV1A_Qe1D_at4q_D_Q __pyx_string_tab[118] +#define __pyx_n_b_O __pyx_string_tab[119] +#define __pyx_int_0 __pyx_number_tab[0] +#define __pyx_int_neg_1 __pyx_number_tab[1] +#define __pyx_int_1 __pyx_number_tab[2] +#define __pyx_int_136983863 __pyx_number_tab[3] +/* #### Code section: module_state_clear ### */ +#if CYTHON_USE_MODULE_STATE +static CYTHON_SMALL_CODE int __pyx_m_clear(PyObject *m) { + __pyx_mstatetype *clear_module_state = __Pyx_PyModule_GetState(m); + if (!clear_module_state) return 0; + Py_CLEAR(clear_module_state->__pyx_d); + Py_CLEAR(clear_module_state->__pyx_b); + Py_CLEAR(clear_module_state->__pyx_cython_runtime); + Py_CLEAR(clear_module_state->__pyx_empty_tuple); + Py_CLEAR(clear_module_state->__pyx_empty_bytes); + Py_CLEAR(clear_module_state->__pyx_empty_unicode); + #if CYTHON_PEP489_MULTI_PHASE_INIT + __Pyx_State_RemoveModule(NULL); + #endif + Py_CLEAR(clear_module_state->__pyx_ptype_7cpython_4type_type); + Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_dtype); + Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_flatiter); + Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_broadcast); + Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_ndarray); + Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_generic); + Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_number); + Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_integer); + Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_signedinteger); + Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_unsignedinteger); + Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_inexact); + Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_floating); + Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_complexfloating); + Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_flexible); + Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_character); + Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_ufunc); + Py_CLEAR(clear_module_state->__pyx_array_type); + Py_CLEAR(clear_module_state->__pyx_type___pyx_array); + Py_CLEAR(clear_module_state->__pyx_MemviewEnum_type); + Py_CLEAR(clear_module_state->__pyx_type___pyx_MemviewEnum); + Py_CLEAR(clear_module_state->__pyx_memoryview_type); + Py_CLEAR(clear_module_state->__pyx_type___pyx_memoryview); + Py_CLEAR(clear_module_state->__pyx_memoryviewslice_type); + Py_CLEAR(clear_module_state->__pyx_type___pyx_memoryviewslice); + for (int i=0; i<1; ++i) { Py_CLEAR(clear_module_state->__pyx_slice[i]); } + for (int i=0; i<1; ++i) { Py_CLEAR(clear_module_state->__pyx_tuple[i]); } + for (int i=0; i<1; ++i) { Py_CLEAR(clear_module_state->__pyx_codeobj_tab[i]); } + for (int i=0; i<120; ++i) { Py_CLEAR(clear_module_state->__pyx_string_tab[i]); } + for (int i=0; i<4; ++i) { Py_CLEAR(clear_module_state->__pyx_number_tab[i]); } +/* #### Code section: module_state_clear_contents ### */ +/* CommonTypesMetaclass.module_state_clear */ +Py_CLEAR(clear_module_state->__pyx_CommonTypesMetaclassType); + +/* CythonFunctionShared.module_state_clear */ +Py_CLEAR(clear_module_state->__pyx_CyFunctionType); + +/* #### Code section: module_state_clear_end ### */ +return 0; +} +#endif +/* #### Code section: module_state_traverse ### */ +#if CYTHON_USE_MODULE_STATE +static CYTHON_SMALL_CODE int __pyx_m_traverse(PyObject *m, visitproc visit, void *arg) { + __pyx_mstatetype *traverse_module_state = __Pyx_PyModule_GetState(m); + if (!traverse_module_state) return 0; + Py_VISIT(traverse_module_state->__pyx_d); + Py_VISIT(traverse_module_state->__pyx_b); + Py_VISIT(traverse_module_state->__pyx_cython_runtime); + __Pyx_VISIT_CONST(traverse_module_state->__pyx_empty_tuple); + __Pyx_VISIT_CONST(traverse_module_state->__pyx_empty_bytes); + __Pyx_VISIT_CONST(traverse_module_state->__pyx_empty_unicode); + Py_VISIT(traverse_module_state->__pyx_ptype_7cpython_4type_type); + Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_dtype); + Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_flatiter); + Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_broadcast); + Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_ndarray); + Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_generic); + Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_number); + Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_integer); + Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_signedinteger); + Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_unsignedinteger); + Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_inexact); + Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_floating); + Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_complexfloating); + Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_flexible); + Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_character); + Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_ufunc); + Py_VISIT(traverse_module_state->__pyx_array_type); + Py_VISIT(traverse_module_state->__pyx_type___pyx_array); + Py_VISIT(traverse_module_state->__pyx_MemviewEnum_type); + Py_VISIT(traverse_module_state->__pyx_type___pyx_MemviewEnum); + Py_VISIT(traverse_module_state->__pyx_memoryview_type); + Py_VISIT(traverse_module_state->__pyx_type___pyx_memoryview); + Py_VISIT(traverse_module_state->__pyx_memoryviewslice_type); + Py_VISIT(traverse_module_state->__pyx_type___pyx_memoryviewslice); + for (int i=0; i<1; ++i) { __Pyx_VISIT_CONST(traverse_module_state->__pyx_slice[i]); } + for (int i=0; i<1; ++i) { __Pyx_VISIT_CONST(traverse_module_state->__pyx_tuple[i]); } + for (int i=0; i<1; ++i) { __Pyx_VISIT_CONST(traverse_module_state->__pyx_codeobj_tab[i]); } + for (int i=0; i<120; ++i) { __Pyx_VISIT_CONST(traverse_module_state->__pyx_string_tab[i]); } + for (int i=0; i<4; ++i) { __Pyx_VISIT_CONST(traverse_module_state->__pyx_number_tab[i]); } +/* #### Code section: module_state_traverse_contents ### */ +/* CommonTypesMetaclass.module_state_traverse */ +Py_VISIT(traverse_module_state->__pyx_CommonTypesMetaclassType); + +/* CythonFunctionShared.module_state_traverse */ +Py_VISIT(traverse_module_state->__pyx_CyFunctionType); + +/* #### Code section: module_state_traverse_end ### */ +return 0; +} +#endif +/* #### Code section: module_code ### */ + +/* "View.MemoryView":137 + * cdef bint dtype_is_object + * + * def __cinit__(array self, tuple shape, Py_ssize_t itemsize, format not None, # <<<<<<<<<<<<<< + * mode="c", bint allocate_buffer=True): + * +*/ + +/* Python wrapper */ +static int __pyx_array___cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static int __pyx_array___cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_shape = 0; + Py_ssize_t __pyx_v_itemsize; + PyObject *__pyx_v_format = 0; + PyObject *__pyx_v_mode = 0; + int __pyx_v_allocate_buffer; + CYTHON_UNUSED Py_ssize_t __pyx_nargs; + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject* values[5] = {0,0,0,0,0}; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0); + #if CYTHON_ASSUME_SAFE_SIZE + __pyx_nargs = PyTuple_GET_SIZE(__pyx_args); + #else + __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return -1; + #endif + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + { + PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_shape,&__pyx_mstate_global->__pyx_n_u_itemsize,&__pyx_mstate_global->__pyx_n_u_format,&__pyx_mstate_global->__pyx_n_u_mode,&__pyx_mstate_global->__pyx_n_u_allocate_buffer,0}; + const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_VARARGS(__pyx_kwds) : 0; + if (unlikely(__pyx_kwds_len < 0)) __PYX_ERR(1, 137, __pyx_L3_error) + if (__pyx_kwds_len > 0) { + switch (__pyx_nargs) { + case 5: + values[4] = __Pyx_ArgRef_VARARGS(__pyx_args, 4); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[4])) __PYX_ERR(1, 137, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 4: + values[3] = __Pyx_ArgRef_VARARGS(__pyx_args, 3); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(1, 137, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 3: + values[2] = __Pyx_ArgRef_VARARGS(__pyx_args, 2); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(1, 137, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 2: + values[1] = __Pyx_ArgRef_VARARGS(__pyx_args, 1); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(1, 137, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 1: + values[0] = __Pyx_ArgRef_VARARGS(__pyx_args, 0); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(1, 137, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + const Py_ssize_t kwd_pos_args = __pyx_nargs; + if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "__cinit__", 0) < (0)) __PYX_ERR(1, 137, __pyx_L3_error) + if (!values[3]) values[3] = __Pyx_NewRef(((PyObject *)__pyx_mstate_global->__pyx_n_u_c)); + for (Py_ssize_t i = __pyx_nargs; i < 3; i++) { + if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 3, 5, i); __PYX_ERR(1, 137, __pyx_L3_error) } + } + } else { + switch (__pyx_nargs) { + case 5: + values[4] = __Pyx_ArgRef_VARARGS(__pyx_args, 4); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[4])) __PYX_ERR(1, 137, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 4: + values[3] = __Pyx_ArgRef_VARARGS(__pyx_args, 3); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(1, 137, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 3: + values[2] = __Pyx_ArgRef_VARARGS(__pyx_args, 2); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(1, 137, __pyx_L3_error) + values[1] = __Pyx_ArgRef_VARARGS(__pyx_args, 1); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(1, 137, __pyx_L3_error) + values[0] = __Pyx_ArgRef_VARARGS(__pyx_args, 0); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(1, 137, __pyx_L3_error) + break; + default: goto __pyx_L5_argtuple_error; + } + if (!values[3]) values[3] = __Pyx_NewRef(((PyObject *)__pyx_mstate_global->__pyx_n_u_c)); + } + __pyx_v_shape = ((PyObject*)values[0]); + __pyx_v_itemsize = __Pyx_PyIndex_AsSsize_t(values[1]); if (unlikely((__pyx_v_itemsize == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(1, 137, __pyx_L3_error) + __pyx_v_format = values[2]; + __pyx_v_mode = values[3]; + if (values[4]) { + __pyx_v_allocate_buffer = __Pyx_PyObject_IsTrue(values[4]); if (unlikely((__pyx_v_allocate_buffer == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 138, __pyx_L3_error) + } else { + + /* "View.MemoryView":138 + * + * def __cinit__(array self, tuple shape, Py_ssize_t itemsize, format not None, + * mode="c", bint allocate_buffer=True): # <<<<<<<<<<<<<< + * + * cdef int idx +*/ + __pyx_v_allocate_buffer = ((int)1); + } + } + goto __pyx_L6_skip; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 3, 5, __pyx_nargs); __PYX_ERR(1, 137, __pyx_L3_error) + __pyx_L6_skip:; + goto __pyx_L4_argument_unpacking_done; + __pyx_L3_error:; + for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { + Py_XDECREF(values[__pyx_temp]); + } + __Pyx_AddTraceback("View.MemoryView.array.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return -1; + __pyx_L4_argument_unpacking_done:; + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_shape), (&PyTuple_Type), 1, "shape", 1))) __PYX_ERR(1, 137, __pyx_L1_error) + if (unlikely(((PyObject *)__pyx_v_format) == Py_None)) { + PyErr_Format(PyExc_TypeError, "Argument '%.200s' must not be None", "format"); __PYX_ERR(1, 137, __pyx_L1_error) + } + __pyx_r = __pyx_array___pyx_pf_15View_dot_MemoryView_5array___cinit__(((struct __pyx_array_obj *)__pyx_v_self), __pyx_v_shape, __pyx_v_itemsize, __pyx_v_format, __pyx_v_mode, __pyx_v_allocate_buffer); + + /* "View.MemoryView":137 + * cdef bint dtype_is_object + * + * def __cinit__(array self, tuple shape, Py_ssize_t itemsize, format not None, # <<<<<<<<<<<<<< + * mode="c", bint allocate_buffer=True): + * +*/ + + /* function exit code */ + goto __pyx_L0; + __pyx_L1_error:; + __pyx_r = -1; + for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { + Py_XDECREF(values[__pyx_temp]); + } + goto __pyx_L7_cleaned_up; + __pyx_L0:; + for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { + Py_XDECREF(values[__pyx_temp]); + } + __pyx_L7_cleaned_up:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_array___pyx_pf_15View_dot_MemoryView_5array___cinit__(struct __pyx_array_obj *__pyx_v_self, PyObject *__pyx_v_shape, Py_ssize_t __pyx_v_itemsize, PyObject *__pyx_v_format, PyObject *__pyx_v_mode, int __pyx_v_allocate_buffer) { + int __pyx_v_idx; + Py_ssize_t __pyx_v_dim; + char __pyx_v_order; + int __pyx_r; + __Pyx_RefNannyDeclarations + Py_ssize_t __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + size_t __pyx_t_6; + char *__pyx_t_7; + int __pyx_t_8; + Py_ssize_t __pyx_t_9; + PyObject *__pyx_t_10 = NULL; + PyObject *__pyx_t_11[5]; + PyObject *__pyx_t_12 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__cinit__", 0); + __Pyx_INCREF(__pyx_v_format); + + /* "View.MemoryView":143 + * cdef Py_ssize_t dim + * + * self.ndim = len(shape) # <<<<<<<<<<<<<< + * self.itemsize = itemsize + * +*/ + if (unlikely(__pyx_v_shape == Py_None)) { + PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); + __PYX_ERR(1, 143, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_PyTuple_GET_SIZE(__pyx_v_shape); if (unlikely(__pyx_t_1 == ((Py_ssize_t)-1))) __PYX_ERR(1, 143, __pyx_L1_error) + __pyx_v_self->ndim = ((int)__pyx_t_1); + + /* "View.MemoryView":144 + * + * self.ndim = len(shape) + * self.itemsize = itemsize # <<<<<<<<<<<<<< + * + * if not self.ndim: +*/ + __pyx_v_self->itemsize = __pyx_v_itemsize; + + /* "View.MemoryView":146 + * self.itemsize = itemsize + * + * if not self.ndim: # <<<<<<<<<<<<<< + * raise ValueError, "Empty shape tuple for cython.array" + * +*/ + __pyx_t_2 = (!(__pyx_v_self->ndim != 0)); + if (unlikely(__pyx_t_2)) { + + /* "View.MemoryView":147 + * + * if not self.ndim: + * raise ValueError, "Empty shape tuple for cython.array" # <<<<<<<<<<<<<< + * + * if itemsize <= 0: +*/ + __Pyx_Raise(((PyObject *)(((PyTypeObject*)PyExc_ValueError))), __pyx_mstate_global->__pyx_kp_u_Empty_shape_tuple_for_cython_arr, 0, 0); + __PYX_ERR(1, 147, __pyx_L1_error) + + /* "View.MemoryView":146 + * self.itemsize = itemsize + * + * if not self.ndim: # <<<<<<<<<<<<<< + * raise ValueError, "Empty shape tuple for cython.array" + * +*/ + } + + /* "View.MemoryView":149 + * raise ValueError, "Empty shape tuple for cython.array" + * + * if itemsize <= 0: # <<<<<<<<<<<<<< + * raise ValueError, "itemsize <= 0 for cython.array" + * +*/ + __pyx_t_2 = (__pyx_v_itemsize <= 0); + if (unlikely(__pyx_t_2)) { + + /* "View.MemoryView":150 + * + * if itemsize <= 0: + * raise ValueError, "itemsize <= 0 for cython.array" # <<<<<<<<<<<<<< + * + * if not isinstance(format, bytes): +*/ + __Pyx_Raise(((PyObject *)(((PyTypeObject*)PyExc_ValueError))), __pyx_mstate_global->__pyx_kp_u_itemsize_0_for_cython_array, 0, 0); + __PYX_ERR(1, 150, __pyx_L1_error) + + /* "View.MemoryView":149 + * raise ValueError, "Empty shape tuple for cython.array" + * + * if itemsize <= 0: # <<<<<<<<<<<<<< + * raise ValueError, "itemsize <= 0 for cython.array" + * +*/ + } + + /* "View.MemoryView":152 + * raise ValueError, "itemsize <= 0 for cython.array" + * + * if not isinstance(format, bytes): # <<<<<<<<<<<<<< + * format = format.encode('ASCII') + * self._format = format # keep a reference to the byte string +*/ + __pyx_t_2 = PyBytes_Check(__pyx_v_format); + __pyx_t_3 = (!__pyx_t_2); + if (__pyx_t_3) { + + /* "View.MemoryView":153 + * + * if not isinstance(format, bytes): + * format = format.encode('ASCII') # <<<<<<<<<<<<<< + * self._format = format # keep a reference to the byte string + * self.format = self._format +*/ + __pyx_t_5 = __pyx_v_format; + __Pyx_INCREF(__pyx_t_5); + __pyx_t_6 = 0; + { + PyObject *__pyx_callargs[2] = {__pyx_t_5, __pyx_mstate_global->__pyx_n_u_ASCII}; + __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_6, (2-__pyx_t_6) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 153, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + } + __Pyx_DECREF_SET(__pyx_v_format, __pyx_t_4); + __pyx_t_4 = 0; + + /* "View.MemoryView":152 + * raise ValueError, "itemsize <= 0 for cython.array" + * + * if not isinstance(format, bytes): # <<<<<<<<<<<<<< + * format = format.encode('ASCII') + * self._format = format # keep a reference to the byte string +*/ + } + + /* "View.MemoryView":154 + * if not isinstance(format, bytes): + * format = format.encode('ASCII') + * self._format = format # keep a reference to the byte string # <<<<<<<<<<<<<< + * self.format = self._format + * +*/ + __pyx_t_4 = __pyx_v_format; + __Pyx_INCREF(__pyx_t_4); + if (!(likely(PyBytes_CheckExact(__pyx_t_4))||((__pyx_t_4) == Py_None) || __Pyx_RaiseUnexpectedTypeError("bytes", __pyx_t_4))) __PYX_ERR(1, 154, __pyx_L1_error) + __Pyx_GIVEREF(__pyx_t_4); + __Pyx_GOTREF(__pyx_v_self->_format); + __Pyx_DECREF(__pyx_v_self->_format); + __pyx_v_self->_format = ((PyObject*)__pyx_t_4); + __pyx_t_4 = 0; + + /* "View.MemoryView":155 + * format = format.encode('ASCII') + * self._format = format # keep a reference to the byte string + * self.format = self._format # <<<<<<<<<<<<<< + * + * +*/ + if (unlikely(__pyx_v_self->_format == Py_None)) { + PyErr_SetString(PyExc_TypeError, "expected bytes, NoneType found"); + __PYX_ERR(1, 155, __pyx_L1_error) + } + __pyx_t_7 = __Pyx_PyBytes_AsWritableString(__pyx_v_self->_format); if (unlikely((!__pyx_t_7) && PyErr_Occurred())) __PYX_ERR(1, 155, __pyx_L1_error) + __pyx_v_self->format = __pyx_t_7; + + /* "View.MemoryView":158 + * + * + * self._shape = PyObject_Malloc(sizeof(Py_ssize_t)*self.ndim*2) # <<<<<<<<<<<<<< + * self._strides = self._shape + self.ndim + * +*/ + __pyx_v_self->_shape = ((Py_ssize_t *)PyObject_Malloc((((sizeof(Py_ssize_t)) * __pyx_v_self->ndim) * 2))); + + /* "View.MemoryView":159 + * + * self._shape = PyObject_Malloc(sizeof(Py_ssize_t)*self.ndim*2) + * self._strides = self._shape + self.ndim # <<<<<<<<<<<<<< + * + * if not self._shape: +*/ + __pyx_v_self->_strides = (__pyx_v_self->_shape + __pyx_v_self->ndim); + + /* "View.MemoryView":161 + * self._strides = self._shape + self.ndim + * + * if not self._shape: # <<<<<<<<<<<<<< + * raise MemoryError, "unable to allocate shape and strides." + * +*/ + __pyx_t_3 = (!(__pyx_v_self->_shape != 0)); + if (unlikely(__pyx_t_3)) { + + /* "View.MemoryView":162 + * + * if not self._shape: + * raise MemoryError, "unable to allocate shape and strides." # <<<<<<<<<<<<<< + * + * +*/ + __Pyx_Raise(((PyObject *)(((PyTypeObject*)PyExc_MemoryError))), __pyx_mstate_global->__pyx_kp_u_unable_to_allocate_shape_and_str, 0, 0); + __PYX_ERR(1, 162, __pyx_L1_error) + + /* "View.MemoryView":161 + * self._strides = self._shape + self.ndim + * + * if not self._shape: # <<<<<<<<<<<<<< + * raise MemoryError, "unable to allocate shape and strides." + * +*/ + } + + /* "View.MemoryView":165 + * + * + * for idx, dim in enumerate(shape): # <<<<<<<<<<<<<< + * if dim <= 0: + * raise ValueError, f"Invalid shape in axis {idx}: {dim}." +*/ + __pyx_t_8 = 0; + __pyx_t_4 = __pyx_v_shape; __Pyx_INCREF(__pyx_t_4); + __pyx_t_1 = 0; + for (;;) { + { + Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_4); + #if !CYTHON_ASSUME_SAFE_SIZE + if (unlikely((__pyx_temp < 0))) __PYX_ERR(1, 165, __pyx_L1_error) + #endif + if (__pyx_t_1 >= __pyx_temp) break; + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_5 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_1)); + #else + __pyx_t_5 = __Pyx_PySequence_ITEM(__pyx_t_4, __pyx_t_1); + #endif + ++__pyx_t_1; + if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 165, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_9 = __Pyx_PyIndex_AsSsize_t(__pyx_t_5); if (unlikely((__pyx_t_9 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(1, 165, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_v_dim = __pyx_t_9; + __pyx_v_idx = __pyx_t_8; + __pyx_t_8 = (__pyx_t_8 + 1); + + /* "View.MemoryView":166 + * + * for idx, dim in enumerate(shape): + * if dim <= 0: # <<<<<<<<<<<<<< + * raise ValueError, f"Invalid shape in axis {idx}: {dim}." + * self._shape[idx] = dim +*/ + __pyx_t_3 = (__pyx_v_dim <= 0); + if (unlikely(__pyx_t_3)) { + + /* "View.MemoryView":167 + * for idx, dim in enumerate(shape): + * if dim <= 0: + * raise ValueError, f"Invalid shape in axis {idx}: {dim}." # <<<<<<<<<<<<<< + * self._shape[idx] = dim + * +*/ + __pyx_t_5 = __Pyx_PyUnicode_From_int(__pyx_v_idx, 0, ' ', 'd'); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 167, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_10 = __Pyx_PyUnicode_From_Py_ssize_t(__pyx_v_dim, 0, ' ', 'd'); if (unlikely(!__pyx_t_10)) __PYX_ERR(1, 167, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_10); + __pyx_t_11[0] = __pyx_mstate_global->__pyx_kp_u_Invalid_shape_in_axis; + __pyx_t_11[1] = __pyx_t_5; + __pyx_t_11[2] = __pyx_mstate_global->__pyx_kp_u_; + __pyx_t_11[3] = __pyx_t_10; + __pyx_t_11[4] = __pyx_mstate_global->__pyx_kp_u__2; + __pyx_t_12 = __Pyx_PyUnicode_Join(__pyx_t_11, 5, 22 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_5) + 2 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_10) + 1, 127); + if (unlikely(!__pyx_t_12)) __PYX_ERR(1, 167, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_12); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __Pyx_Raise(((PyObject *)(((PyTypeObject*)PyExc_ValueError))), __pyx_t_12, 0, 0); + __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0; + __PYX_ERR(1, 167, __pyx_L1_error) + + /* "View.MemoryView":166 + * + * for idx, dim in enumerate(shape): + * if dim <= 0: # <<<<<<<<<<<<<< + * raise ValueError, f"Invalid shape in axis {idx}: {dim}." + * self._shape[idx] = dim +*/ + } + + /* "View.MemoryView":168 + * if dim <= 0: + * raise ValueError, f"Invalid shape in axis {idx}: {dim}." + * self._shape[idx] = dim # <<<<<<<<<<<<<< + * + * cdef char order +*/ + (__pyx_v_self->_shape[__pyx_v_idx]) = __pyx_v_dim; + + /* "View.MemoryView":165 + * + * + * for idx, dim in enumerate(shape): # <<<<<<<<<<<<<< + * if dim <= 0: + * raise ValueError, f"Invalid shape in axis {idx}: {dim}." +*/ + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "View.MemoryView":171 + * + * cdef char order + * if mode == 'c': # <<<<<<<<<<<<<< + * order = b'C' + * self.mode = u'c' +*/ + __pyx_t_3 = (__Pyx_PyUnicode_Equals(__pyx_v_mode, __pyx_mstate_global->__pyx_n_u_c, Py_EQ)); if (unlikely((__pyx_t_3 < 0))) __PYX_ERR(1, 171, __pyx_L1_error) + if (__pyx_t_3) { + + /* "View.MemoryView":172 + * cdef char order + * if mode == 'c': + * order = b'C' # <<<<<<<<<<<<<< + * self.mode = u'c' + * elif mode == 'fortran': +*/ + __pyx_v_order = 'C'; + + /* "View.MemoryView":173 + * if mode == 'c': + * order = b'C' + * self.mode = u'c' # <<<<<<<<<<<<<< + * elif mode == 'fortran': + * order = b'F' +*/ + __Pyx_INCREF(__pyx_mstate_global->__pyx_n_u_c); + __Pyx_GIVEREF(__pyx_mstate_global->__pyx_n_u_c); + __Pyx_GOTREF(__pyx_v_self->mode); + __Pyx_DECREF(__pyx_v_self->mode); + __pyx_v_self->mode = __pyx_mstate_global->__pyx_n_u_c; + + /* "View.MemoryView":171 + * + * cdef char order + * if mode == 'c': # <<<<<<<<<<<<<< + * order = b'C' + * self.mode = u'c' +*/ + goto __pyx_L11; + } + + /* "View.MemoryView":174 + * order = b'C' + * self.mode = u'c' + * elif mode == 'fortran': # <<<<<<<<<<<<<< + * order = b'F' + * self.mode = u'fortran' +*/ + __pyx_t_3 = (__Pyx_PyUnicode_Equals(__pyx_v_mode, __pyx_mstate_global->__pyx_n_u_fortran, Py_EQ)); if (unlikely((__pyx_t_3 < 0))) __PYX_ERR(1, 174, __pyx_L1_error) + if (likely(__pyx_t_3)) { + + /* "View.MemoryView":175 + * self.mode = u'c' + * elif mode == 'fortran': + * order = b'F' # <<<<<<<<<<<<<< + * self.mode = u'fortran' + * else: +*/ + __pyx_v_order = 'F'; + + /* "View.MemoryView":176 + * elif mode == 'fortran': + * order = b'F' + * self.mode = u'fortran' # <<<<<<<<<<<<<< + * else: + * raise ValueError, f"Invalid mode, expected 'c' or 'fortran', got {mode}" +*/ + __Pyx_INCREF(__pyx_mstate_global->__pyx_n_u_fortran); + __Pyx_GIVEREF(__pyx_mstate_global->__pyx_n_u_fortran); + __Pyx_GOTREF(__pyx_v_self->mode); + __Pyx_DECREF(__pyx_v_self->mode); + __pyx_v_self->mode = __pyx_mstate_global->__pyx_n_u_fortran; + + /* "View.MemoryView":174 + * order = b'C' + * self.mode = u'c' + * elif mode == 'fortran': # <<<<<<<<<<<<<< + * order = b'F' + * self.mode = u'fortran' +*/ + goto __pyx_L11; + } + + /* "View.MemoryView":178 + * self.mode = u'fortran' + * else: + * raise ValueError, f"Invalid mode, expected 'c' or 'fortran', got {mode}" # <<<<<<<<<<<<<< + * + * self.len = fill_contig_strides_array(self._shape, self._strides, itemsize, self.ndim, order) +*/ + /*else*/ { + __pyx_t_4 = __Pyx_PyObject_FormatSimple(__pyx_v_mode, __pyx_mstate_global->__pyx_empty_unicode); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 178, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_12 = __Pyx_PyUnicode_Concat(__pyx_mstate_global->__pyx_kp_u_Invalid_mode_expected_c_or_fortr, __pyx_t_4); if (unlikely(!__pyx_t_12)) __PYX_ERR(1, 178, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_12); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_Raise(((PyObject *)(((PyTypeObject*)PyExc_ValueError))), __pyx_t_12, 0, 0); + __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0; + __PYX_ERR(1, 178, __pyx_L1_error) + } + __pyx_L11:; + + /* "View.MemoryView":180 + * raise ValueError, f"Invalid mode, expected 'c' or 'fortran', got {mode}" + * + * self.len = fill_contig_strides_array(self._shape, self._strides, itemsize, self.ndim, order) # <<<<<<<<<<<<<< + * + * self.free_data = allocate_buffer +*/ + __pyx_v_self->len = __pyx_fill_contig_strides_array(__pyx_v_self->_shape, __pyx_v_self->_strides, __pyx_v_itemsize, __pyx_v_self->ndim, __pyx_v_order); + + /* "View.MemoryView":182 + * self.len = fill_contig_strides_array(self._shape, self._strides, itemsize, self.ndim, order) + * + * self.free_data = allocate_buffer # <<<<<<<<<<<<<< + * self.dtype_is_object = format == b'O' + * +*/ + __pyx_v_self->free_data = __pyx_v_allocate_buffer; + + /* "View.MemoryView":183 + * + * self.free_data = allocate_buffer + * self.dtype_is_object = format == b'O' # <<<<<<<<<<<<<< + * + * if allocate_buffer: +*/ + __pyx_t_12 = PyObject_RichCompare(__pyx_v_format, __pyx_mstate_global->__pyx_n_b_O, Py_EQ); __Pyx_XGOTREF(__pyx_t_12); if (unlikely(!__pyx_t_12)) __PYX_ERR(1, 183, __pyx_L1_error) + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_12); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 183, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0; + __pyx_v_self->dtype_is_object = __pyx_t_3; + + /* "View.MemoryView":185 + * self.dtype_is_object = format == b'O' + * + * if allocate_buffer: # <<<<<<<<<<<<<< + * _allocate_buffer(self) + * +*/ + if (__pyx_v_allocate_buffer) { + + /* "View.MemoryView":186 + * + * if allocate_buffer: + * _allocate_buffer(self) # <<<<<<<<<<<<<< + * + * @cname('getbuffer') +*/ + __pyx_t_8 = __pyx_array_allocate_buffer(__pyx_v_self); if (unlikely(__pyx_t_8 == ((int)-1))) __PYX_ERR(1, 186, __pyx_L1_error) + + /* "View.MemoryView":185 + * self.dtype_is_object = format == b'O' + * + * if allocate_buffer: # <<<<<<<<<<<<<< + * _allocate_buffer(self) + * +*/ + } + + /* "View.MemoryView":137 + * cdef bint dtype_is_object + * + * def __cinit__(array self, tuple shape, Py_ssize_t itemsize, format not None, # <<<<<<<<<<<<<< + * mode="c", bint allocate_buffer=True): + * +*/ + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_10); + __Pyx_XDECREF(__pyx_t_12); + __Pyx_AddTraceback("View.MemoryView.array.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_format); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":188 + * _allocate_buffer(self) + * + * @cname('getbuffer') # <<<<<<<<<<<<<< + * def __getbuffer__(self, Py_buffer *info, int flags): + * cdef int bufmode = -1 +*/ + +/* Python wrapper */ +CYTHON_UNUSED static int __pyx_array_getbuffer(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /*proto*/ +CYTHON_UNUSED static int __pyx_array_getbuffer(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__getbuffer__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_r = __pyx_array___pyx_pf_15View_dot_MemoryView_5array_2__getbuffer__(((struct __pyx_array_obj *)__pyx_v_self), ((Py_buffer *)__pyx_v_info), ((int)__pyx_v_flags)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_array___pyx_pf_15View_dot_MemoryView_5array_2__getbuffer__(struct __pyx_array_obj *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) { + int __pyx_v_bufmode; + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + char *__pyx_t_2; + Py_ssize_t __pyx_t_3; + int __pyx_t_4; + Py_ssize_t *__pyx_t_5; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + if (unlikely(__pyx_v_info == NULL)) { + PyErr_SetString(PyExc_BufferError, "PyObject_GetBuffer: view==NULL argument is obsolete"); + return -1; + } + __Pyx_RefNannySetupContext("__getbuffer__", 0); + __pyx_v_info->obj = Py_None; __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(__pyx_v_info->obj); + + /* "View.MemoryView":190 + * @cname('getbuffer') + * def __getbuffer__(self, Py_buffer *info, int flags): + * cdef int bufmode = -1 # <<<<<<<<<<<<<< + * if flags & (PyBUF_C_CONTIGUOUS | PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS): + * if self.mode == u"c": +*/ + __pyx_v_bufmode = -1; + + /* "View.MemoryView":191 + * def __getbuffer__(self, Py_buffer *info, int flags): + * cdef int bufmode = -1 + * if flags & (PyBUF_C_CONTIGUOUS | PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS): # <<<<<<<<<<<<<< + * if self.mode == u"c": + * bufmode = PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS +*/ + __pyx_t_1 = ((__pyx_v_flags & ((PyBUF_C_CONTIGUOUS | PyBUF_F_CONTIGUOUS) | PyBUF_ANY_CONTIGUOUS)) != 0); + if (__pyx_t_1) { + + /* "View.MemoryView":192 + * cdef int bufmode = -1 + * if flags & (PyBUF_C_CONTIGUOUS | PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS): + * if self.mode == u"c": # <<<<<<<<<<<<<< + * bufmode = PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS + * elif self.mode == u"fortran": +*/ + __pyx_t_1 = (__Pyx_PyUnicode_Equals(__pyx_v_self->mode, __pyx_mstate_global->__pyx_n_u_c, Py_EQ)); if (unlikely((__pyx_t_1 < 0))) __PYX_ERR(1, 192, __pyx_L1_error) + if (__pyx_t_1) { + + /* "View.MemoryView":193 + * if flags & (PyBUF_C_CONTIGUOUS | PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS): + * if self.mode == u"c": + * bufmode = PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS # <<<<<<<<<<<<<< + * elif self.mode == u"fortran": + * bufmode = PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS +*/ + __pyx_v_bufmode = (PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS); + + /* "View.MemoryView":192 + * cdef int bufmode = -1 + * if flags & (PyBUF_C_CONTIGUOUS | PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS): + * if self.mode == u"c": # <<<<<<<<<<<<<< + * bufmode = PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS + * elif self.mode == u"fortran": +*/ + goto __pyx_L4; + } + + /* "View.MemoryView":194 + * if self.mode == u"c": + * bufmode = PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS + * elif self.mode == u"fortran": # <<<<<<<<<<<<<< + * bufmode = PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS + * if not (flags & bufmode): +*/ + __pyx_t_1 = (__Pyx_PyUnicode_Equals(__pyx_v_self->mode, __pyx_mstate_global->__pyx_n_u_fortran, Py_EQ)); if (unlikely((__pyx_t_1 < 0))) __PYX_ERR(1, 194, __pyx_L1_error) + if (__pyx_t_1) { + + /* "View.MemoryView":195 + * bufmode = PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS + * elif self.mode == u"fortran": + * bufmode = PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS # <<<<<<<<<<<<<< + * if not (flags & bufmode): + * raise ValueError, "Can only create a buffer that is contiguous in memory." +*/ + __pyx_v_bufmode = (PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS); + + /* "View.MemoryView":194 + * if self.mode == u"c": + * bufmode = PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS + * elif self.mode == u"fortran": # <<<<<<<<<<<<<< + * bufmode = PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS + * if not (flags & bufmode): +*/ + } + __pyx_L4:; + + /* "View.MemoryView":196 + * elif self.mode == u"fortran": + * bufmode = PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS + * if not (flags & bufmode): # <<<<<<<<<<<<<< + * raise ValueError, "Can only create a buffer that is contiguous in memory." + * info.buf = self.data +*/ + __pyx_t_1 = (!((__pyx_v_flags & __pyx_v_bufmode) != 0)); + if (unlikely(__pyx_t_1)) { + + /* "View.MemoryView":197 + * bufmode = PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS + * if not (flags & bufmode): + * raise ValueError, "Can only create a buffer that is contiguous in memory." # <<<<<<<<<<<<<< + * info.buf = self.data + * info.len = self.len +*/ + __Pyx_Raise(((PyObject *)(((PyTypeObject*)PyExc_ValueError))), __pyx_mstate_global->__pyx_kp_u_Can_only_create_a_buffer_that_is, 0, 0); + __PYX_ERR(1, 197, __pyx_L1_error) + + /* "View.MemoryView":196 + * elif self.mode == u"fortran": + * bufmode = PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS + * if not (flags & bufmode): # <<<<<<<<<<<<<< + * raise ValueError, "Can only create a buffer that is contiguous in memory." + * info.buf = self.data +*/ + } + + /* "View.MemoryView":191 + * def __getbuffer__(self, Py_buffer *info, int flags): + * cdef int bufmode = -1 + * if flags & (PyBUF_C_CONTIGUOUS | PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS): # <<<<<<<<<<<<<< + * if self.mode == u"c": + * bufmode = PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS +*/ + } + + /* "View.MemoryView":198 + * if not (flags & bufmode): + * raise ValueError, "Can only create a buffer that is contiguous in memory." + * info.buf = self.data # <<<<<<<<<<<<<< + * info.len = self.len + * +*/ + __pyx_t_2 = __pyx_v_self->data; + __pyx_v_info->buf = __pyx_t_2; + + /* "View.MemoryView":199 + * raise ValueError, "Can only create a buffer that is contiguous in memory." + * info.buf = self.data + * info.len = self.len # <<<<<<<<<<<<<< + * + * if flags & PyBUF_STRIDES: +*/ + __pyx_t_3 = __pyx_v_self->len; + __pyx_v_info->len = __pyx_t_3; + + /* "View.MemoryView":201 + * info.len = self.len + * + * if flags & PyBUF_STRIDES: # <<<<<<<<<<<<<< + * info.ndim = self.ndim + * info.shape = self._shape +*/ + __pyx_t_1 = ((__pyx_v_flags & PyBUF_STRIDES) != 0); + if (__pyx_t_1) { + + /* "View.MemoryView":202 + * + * if flags & PyBUF_STRIDES: + * info.ndim = self.ndim # <<<<<<<<<<<<<< + * info.shape = self._shape + * info.strides = self._strides +*/ + __pyx_t_4 = __pyx_v_self->ndim; + __pyx_v_info->ndim = __pyx_t_4; + + /* "View.MemoryView":203 + * if flags & PyBUF_STRIDES: + * info.ndim = self.ndim + * info.shape = self._shape # <<<<<<<<<<<<<< + * info.strides = self._strides + * else: +*/ + __pyx_t_5 = __pyx_v_self->_shape; + __pyx_v_info->shape = __pyx_t_5; + + /* "View.MemoryView":204 + * info.ndim = self.ndim + * info.shape = self._shape + * info.strides = self._strides # <<<<<<<<<<<<<< + * else: + * info.ndim = 1 +*/ + __pyx_t_5 = __pyx_v_self->_strides; + __pyx_v_info->strides = __pyx_t_5; + + /* "View.MemoryView":201 + * info.len = self.len + * + * if flags & PyBUF_STRIDES: # <<<<<<<<<<<<<< + * info.ndim = self.ndim + * info.shape = self._shape +*/ + goto __pyx_L6; + } + + /* "View.MemoryView":206 + * info.strides = self._strides + * else: + * info.ndim = 1 # <<<<<<<<<<<<<< + * info.shape = &self.len if flags & PyBUF_ND else NULL + * info.strides = NULL +*/ + /*else*/ { + __pyx_v_info->ndim = 1; + + /* "View.MemoryView":207 + * else: + * info.ndim = 1 + * info.shape = &self.len if flags & PyBUF_ND else NULL # <<<<<<<<<<<<<< + * info.strides = NULL + * +*/ + __pyx_t_1 = ((__pyx_v_flags & PyBUF_ND) != 0); + if (__pyx_t_1) { + __pyx_t_5 = (&__pyx_v_self->len); + } else { + __pyx_t_5 = NULL; + } + __pyx_v_info->shape = __pyx_t_5; + + /* "View.MemoryView":208 + * info.ndim = 1 + * info.shape = &self.len if flags & PyBUF_ND else NULL + * info.strides = NULL # <<<<<<<<<<<<<< + * + * info.suboffsets = NULL +*/ + __pyx_v_info->strides = NULL; + } + __pyx_L6:; + + /* "View.MemoryView":210 + * info.strides = NULL + * + * info.suboffsets = NULL # <<<<<<<<<<<<<< + * info.itemsize = self.itemsize + * info.readonly = 0 +*/ + __pyx_v_info->suboffsets = NULL; + + /* "View.MemoryView":211 + * + * info.suboffsets = NULL + * info.itemsize = self.itemsize # <<<<<<<<<<<<<< + * info.readonly = 0 + * info.format = self.format if flags & PyBUF_FORMAT else NULL +*/ + __pyx_t_3 = __pyx_v_self->itemsize; + __pyx_v_info->itemsize = __pyx_t_3; + + /* "View.MemoryView":212 + * info.suboffsets = NULL + * info.itemsize = self.itemsize + * info.readonly = 0 # <<<<<<<<<<<<<< + * info.format = self.format if flags & PyBUF_FORMAT else NULL + * info.obj = self +*/ + __pyx_v_info->readonly = 0; + + /* "View.MemoryView":213 + * info.itemsize = self.itemsize + * info.readonly = 0 + * info.format = self.format if flags & PyBUF_FORMAT else NULL # <<<<<<<<<<<<<< + * info.obj = self + * +*/ + __pyx_t_1 = ((__pyx_v_flags & PyBUF_FORMAT) != 0); + if (__pyx_t_1) { + __pyx_t_2 = __pyx_v_self->format; + } else { + __pyx_t_2 = NULL; + } + __pyx_v_info->format = __pyx_t_2; + + /* "View.MemoryView":214 + * info.readonly = 0 + * info.format = self.format if flags & PyBUF_FORMAT else NULL + * info.obj = self # <<<<<<<<<<<<<< + * + * def __dealloc__(array self): +*/ + __Pyx_INCREF((PyObject *)__pyx_v_self); + __Pyx_GIVEREF((PyObject *)__pyx_v_self); + __Pyx_GOTREF(__pyx_v_info->obj); + __Pyx_DECREF(__pyx_v_info->obj); + __pyx_v_info->obj = ((PyObject *)__pyx_v_self); + + /* "View.MemoryView":188 + * _allocate_buffer(self) + * + * @cname('getbuffer') # <<<<<<<<<<<<<< + * def __getbuffer__(self, Py_buffer *info, int flags): + * cdef int bufmode = -1 +*/ + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("View.MemoryView.array.__getbuffer__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + if (__pyx_v_info->obj != NULL) { + __Pyx_GOTREF(__pyx_v_info->obj); + __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = 0; + } + goto __pyx_L2; + __pyx_L0:; + if (__pyx_v_info->obj == Py_None) { + __Pyx_GOTREF(__pyx_v_info->obj); + __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = 0; + } + __pyx_L2:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":216 + * info.obj = self + * + * def __dealloc__(array self): # <<<<<<<<<<<<<< + * if self.callback_free_data != NULL: + * self.callback_free_data(self.data) +*/ + +/* Python wrapper */ +static void __pyx_array___dealloc__(PyObject *__pyx_v_self); /*proto*/ +static void __pyx_array___dealloc__(PyObject *__pyx_v_self) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__dealloc__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_array___pyx_pf_15View_dot_MemoryView_5array_4__dealloc__(((struct __pyx_array_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); +} + +static void __pyx_array___pyx_pf_15View_dot_MemoryView_5array_4__dealloc__(struct __pyx_array_obj *__pyx_v_self) { + int __pyx_t_1; + int __pyx_t_2; + + /* "View.MemoryView":217 + * + * def __dealloc__(array self): + * if self.callback_free_data != NULL: # <<<<<<<<<<<<<< + * self.callback_free_data(self.data) + * elif self.free_data and self.data is not NULL: +*/ + __pyx_t_1 = (__pyx_v_self->callback_free_data != NULL); + if (__pyx_t_1) { + + /* "View.MemoryView":218 + * def __dealloc__(array self): + * if self.callback_free_data != NULL: + * self.callback_free_data(self.data) # <<<<<<<<<<<<<< + * elif self.free_data and self.data is not NULL: + * if self.dtype_is_object: +*/ + __pyx_v_self->callback_free_data(__pyx_v_self->data); + + /* "View.MemoryView":217 + * + * def __dealloc__(array self): + * if self.callback_free_data != NULL: # <<<<<<<<<<<<<< + * self.callback_free_data(self.data) + * elif self.free_data and self.data is not NULL: +*/ + goto __pyx_L3; + } + + /* "View.MemoryView":219 + * if self.callback_free_data != NULL: + * self.callback_free_data(self.data) + * elif self.free_data and self.data is not NULL: # <<<<<<<<<<<<<< + * if self.dtype_is_object: + * refcount_objects_in_slice(self.data, self._shape, self._strides, self.ndim, inc=False) +*/ + if (__pyx_v_self->free_data) { + } else { + __pyx_t_1 = __pyx_v_self->free_data; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_2 = (__pyx_v_self->data != NULL); + __pyx_t_1 = __pyx_t_2; + __pyx_L4_bool_binop_done:; + if (__pyx_t_1) { + + /* "View.MemoryView":220 + * self.callback_free_data(self.data) + * elif self.free_data and self.data is not NULL: + * if self.dtype_is_object: # <<<<<<<<<<<<<< + * refcount_objects_in_slice(self.data, self._shape, self._strides, self.ndim, inc=False) + * free(self.data) +*/ + if (__pyx_v_self->dtype_is_object) { + + /* "View.MemoryView":221 + * elif self.free_data and self.data is not NULL: + * if self.dtype_is_object: + * refcount_objects_in_slice(self.data, self._shape, self._strides, self.ndim, inc=False) # <<<<<<<<<<<<<< + * free(self.data) + * PyObject_Free(self._shape) +*/ + __pyx_memoryview_refcount_objects_in_slice(__pyx_v_self->data, __pyx_v_self->_shape, __pyx_v_self->_strides, __pyx_v_self->ndim, 0); + + /* "View.MemoryView":220 + * self.callback_free_data(self.data) + * elif self.free_data and self.data is not NULL: + * if self.dtype_is_object: # <<<<<<<<<<<<<< + * refcount_objects_in_slice(self.data, self._shape, self._strides, self.ndim, inc=False) + * free(self.data) +*/ + } + + /* "View.MemoryView":222 + * if self.dtype_is_object: + * refcount_objects_in_slice(self.data, self._shape, self._strides, self.ndim, inc=False) + * free(self.data) # <<<<<<<<<<<<<< + * PyObject_Free(self._shape) + * +*/ + free(__pyx_v_self->data); + + /* "View.MemoryView":219 + * if self.callback_free_data != NULL: + * self.callback_free_data(self.data) + * elif self.free_data and self.data is not NULL: # <<<<<<<<<<<<<< + * if self.dtype_is_object: + * refcount_objects_in_slice(self.data, self._shape, self._strides, self.ndim, inc=False) +*/ + } + __pyx_L3:; + + /* "View.MemoryView":223 + * refcount_objects_in_slice(self.data, self._shape, self._strides, self.ndim, inc=False) + * free(self.data) + * PyObject_Free(self._shape) # <<<<<<<<<<<<<< + * + * @property +*/ + PyObject_Free(__pyx_v_self->_shape); + + /* "View.MemoryView":216 + * info.obj = self + * + * def __dealloc__(array self): # <<<<<<<<<<<<<< + * if self.callback_free_data != NULL: + * self.callback_free_data(self.data) +*/ + + /* function exit code */ +} + +/* "View.MemoryView":225 + * PyObject_Free(self._shape) + * + * @property # <<<<<<<<<<<<<< + * def memview(self): + * return self.get_memview() +*/ + +/* Python wrapper */ +static PyObject *__pyx_pw_15View_dot_MemoryView_5array_7memview_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_15View_dot_MemoryView_5array_7memview_1__get__(PyObject *__pyx_v_self) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_r = __pyx_pf_15View_dot_MemoryView_5array_7memview___get__(((struct __pyx_array_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_15View_dot_MemoryView_5array_7memview___get__(struct __pyx_array_obj *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + + /* "View.MemoryView":227 + * @property + * def memview(self): + * return self.get_memview() # <<<<<<<<<<<<<< + * + * @cname('get_memview') +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = ((struct __pyx_vtabstruct_array *)__pyx_v_self->__pyx_vtab)->get_memview(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 227, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "View.MemoryView":225 + * PyObject_Free(self._shape) + * + * @property # <<<<<<<<<<<<<< + * def memview(self): + * return self.get_memview() +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("View.MemoryView.array.memview.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":229 + * return self.get_memview() + * + * @cname('get_memview') # <<<<<<<<<<<<<< + * cdef get_memview(self): + * flags = PyBUF_ANY_CONTIGUOUS|PyBUF_FORMAT|PyBUF_WRITABLE +*/ + +static PyObject *__pyx_array_get_memview(struct __pyx_array_obj *__pyx_v_self) { + int __pyx_v_flags; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + size_t __pyx_t_5; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("get_memview", 0); + + /* "View.MemoryView":231 + * @cname('get_memview') + * cdef get_memview(self): + * flags = PyBUF_ANY_CONTIGUOUS|PyBUF_FORMAT|PyBUF_WRITABLE # <<<<<<<<<<<<<< + * return memoryview(self, flags, self.dtype_is_object) + * +*/ + __pyx_v_flags = ((PyBUF_ANY_CONTIGUOUS | PyBUF_FORMAT) | PyBUF_WRITABLE); + + /* "View.MemoryView":232 + * cdef get_memview(self): + * flags = PyBUF_ANY_CONTIGUOUS|PyBUF_FORMAT|PyBUF_WRITABLE + * return memoryview(self, flags, self.dtype_is_object) # <<<<<<<<<<<<<< + * + * def __len__(self): +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_2 = NULL; + __pyx_t_3 = __Pyx_PyLong_From_int(__pyx_v_flags); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 232, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = __Pyx_PyBool_FromLong(__pyx_v_self->dtype_is_object); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 232, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = 1; + { + PyObject *__pyx_callargs[4] = {__pyx_t_2, ((PyObject *)__pyx_v_self), __pyx_t_3, __pyx_t_4}; + __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_mstate_global->__pyx_memoryview_type, __pyx_callargs+__pyx_t_5, (4-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 232, __pyx_L1_error) + __Pyx_GOTREF((PyObject *)__pyx_t_1); + } + __pyx_r = ((PyObject *)__pyx_t_1); + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "View.MemoryView":229 + * return self.get_memview() + * + * @cname('get_memview') # <<<<<<<<<<<<<< + * cdef get_memview(self): + * flags = PyBUF_ANY_CONTIGUOUS|PyBUF_FORMAT|PyBUF_WRITABLE +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_AddTraceback("View.MemoryView.array.get_memview", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":234 + * return memoryview(self, flags, self.dtype_is_object) + * + * def __len__(self): # <<<<<<<<<<<<<< + * return self._shape[0] + * +*/ + +/* Python wrapper */ +static Py_ssize_t __pyx_array___len__(PyObject *__pyx_v_self); /*proto*/ +static Py_ssize_t __pyx_array___len__(PyObject *__pyx_v_self) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + Py_ssize_t __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__len__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_r = __pyx_array___pyx_pf_15View_dot_MemoryView_5array_6__len__(((struct __pyx_array_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static Py_ssize_t __pyx_array___pyx_pf_15View_dot_MemoryView_5array_6__len__(struct __pyx_array_obj *__pyx_v_self) { + Py_ssize_t __pyx_r; + + /* "View.MemoryView":235 + * + * def __len__(self): + * return self._shape[0] # <<<<<<<<<<<<<< + * + * def __getattr__(self, attr): +*/ + __pyx_r = (__pyx_v_self->_shape[0]); + goto __pyx_L0; + + /* "View.MemoryView":234 + * return memoryview(self, flags, self.dtype_is_object) + * + * def __len__(self): # <<<<<<<<<<<<<< + * return self._shape[0] + * +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "View.MemoryView":237 + * return self._shape[0] + * + * def __getattr__(self, attr): # <<<<<<<<<<<<<< + * return getattr(self.memview, attr) + * +*/ + +/* Python wrapper */ +static PyObject *__pyx_array___getattr__(PyObject *__pyx_v_self, PyObject *__pyx_v_attr); /*proto*/ +static PyObject *__pyx_array___getattr__(PyObject *__pyx_v_self, PyObject *__pyx_v_attr) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__getattr__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_r = __pyx_array___pyx_pf_15View_dot_MemoryView_5array_8__getattr__(((struct __pyx_array_obj *)__pyx_v_self), ((PyObject *)__pyx_v_attr)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_array___pyx_pf_15View_dot_MemoryView_5array_8__getattr__(struct __pyx_array_obj *__pyx_v_self, PyObject *__pyx_v_attr) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__getattr__", 0); + + /* "View.MemoryView":238 + * + * def __getattr__(self, attr): + * return getattr(self.memview, attr) # <<<<<<<<<<<<<< + * + * def __getitem__(self, item): +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_mstate_global->__pyx_n_u_memview); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 238, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_GetAttr(__pyx_t_1, __pyx_v_attr); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 238, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + goto __pyx_L0; + + /* "View.MemoryView":237 + * return self._shape[0] + * + * def __getattr__(self, attr): # <<<<<<<<<<<<<< + * return getattr(self.memview, attr) + * +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("View.MemoryView.array.__getattr__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":240 + * return getattr(self.memview, attr) + * + * def __getitem__(self, item): # <<<<<<<<<<<<<< + * return self.memview[item] + * +*/ + +/* Python wrapper */ +static PyObject *__pyx_array___getitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_item); /*proto*/ +static PyObject *__pyx_array___getitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_item) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__getitem__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_r = __pyx_array___pyx_pf_15View_dot_MemoryView_5array_10__getitem__(((struct __pyx_array_obj *)__pyx_v_self), ((PyObject *)__pyx_v_item)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_array___pyx_pf_15View_dot_MemoryView_5array_10__getitem__(struct __pyx_array_obj *__pyx_v_self, PyObject *__pyx_v_item) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__getitem__", 0); + + /* "View.MemoryView":241 + * + * def __getitem__(self, item): + * return self.memview[item] # <<<<<<<<<<<<<< + * + * def __setitem__(self, item, value): +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_mstate_global->__pyx_n_u_memview); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 241, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_GetItem(__pyx_t_1, __pyx_v_item); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 241, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + goto __pyx_L0; + + /* "View.MemoryView":240 + * return getattr(self.memview, attr) + * + * def __getitem__(self, item): # <<<<<<<<<<<<<< + * return self.memview[item] + * +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("View.MemoryView.array.__getitem__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":243 + * return self.memview[item] + * + * def __setitem__(self, item, value): # <<<<<<<<<<<<<< + * self.memview[item] = value + * +*/ + +/* Python wrapper */ +static int __pyx_array___setitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_item, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_array___setitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_item, PyObject *__pyx_v_value) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__setitem__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_r = __pyx_array___pyx_pf_15View_dot_MemoryView_5array_12__setitem__(((struct __pyx_array_obj *)__pyx_v_self), ((PyObject *)__pyx_v_item), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_array___pyx_pf_15View_dot_MemoryView_5array_12__setitem__(struct __pyx_array_obj *__pyx_v_self, PyObject *__pyx_v_item, PyObject *__pyx_v_value) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__setitem__", 0); + + /* "View.MemoryView":244 + * + * def __setitem__(self, item, value): + * self.memview[item] = value # <<<<<<<<<<<<<< + * + * +*/ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_mstate_global->__pyx_n_u_memview); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 244, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (unlikely((PyObject_SetItem(__pyx_t_1, __pyx_v_item, __pyx_v_value) < 0))) __PYX_ERR(1, 244, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "View.MemoryView":243 + * return self.memview[item] + * + * def __setitem__(self, item, value): # <<<<<<<<<<<<<< + * self.memview[item] = value + * +*/ + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("View.MemoryView.array.__setitem__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" + * def __setstate_cython__(self, __pyx_state): +*/ + +/* Python wrapper */ +static PyObject *__pyx_pw___pyx_array_1__reduce_cython__(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +); /*proto*/ +static PyObject *__pyx_pw___pyx_array_1__reduce_cython__(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +) { + #if !CYTHON_METH_FASTCALL + CYTHON_UNUSED Py_ssize_t __pyx_nargs; + #endif + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); + #if !CYTHON_METH_FASTCALL + #if CYTHON_ASSUME_SAFE_SIZE + __pyx_nargs = PyTuple_GET_SIZE(__pyx_args); + #else + __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL; + #endif + #endif + __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs); + if (unlikely(__pyx_nargs > 0)) { __Pyx_RaiseArgtupleInvalid("__reduce_cython__", 1, 0, 0, __pyx_nargs); return NULL; } + const Py_ssize_t __pyx_kwds_len = unlikely(__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0; + if (unlikely(__pyx_kwds_len < 0)) return NULL; + if (unlikely(__pyx_kwds_len > 0)) {__Pyx_RejectKeywords("__reduce_cython__", __pyx_kwds); return NULL;} + __pyx_r = __pyx_pf___pyx_array___reduce_cython__(((struct __pyx_array_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf___pyx_array___reduce_cython__(CYTHON_UNUSED struct __pyx_array_obj *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__reduce_cython__", 0); + + /* "(tree fragment)":2 + * def __reduce_cython__(self): + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" # <<<<<<<<<<<<<< + * def __setstate_cython__(self, __pyx_state): + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" +*/ + __Pyx_Raise(((PyObject *)(((PyTypeObject*)PyExc_TypeError))), __pyx_mstate_global->__pyx_kp_u_no_default___reduce___due_to_non, 0, 0); + __PYX_ERR(1, 2, __pyx_L1_error) + + /* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" + * def __setstate_cython__(self, __pyx_state): +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_AddTraceback("View.MemoryView.array.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":3 + * def __reduce_cython__(self): + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" +*/ + +/* Python wrapper */ +static PyObject *__pyx_pw___pyx_array_3__setstate_cython__(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +); /*proto*/ +static PyObject *__pyx_pw___pyx_array_3__setstate_cython__(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +) { + CYTHON_UNUSED PyObject *__pyx_v___pyx_state = 0; + #if !CYTHON_METH_FASTCALL + CYTHON_UNUSED Py_ssize_t __pyx_nargs; + #endif + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject* values[1] = {0}; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); + #if !CYTHON_METH_FASTCALL + #if CYTHON_ASSUME_SAFE_SIZE + __pyx_nargs = PyTuple_GET_SIZE(__pyx_args); + #else + __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL; + #endif + #endif + __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs); + { + PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_pyx_state,0}; + const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0; + if (unlikely(__pyx_kwds_len < 0)) __PYX_ERR(1, 3, __pyx_L3_error) + if (__pyx_kwds_len > 0) { + switch (__pyx_nargs) { + case 1: + values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(1, 3, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + const Py_ssize_t kwd_pos_args = __pyx_nargs; + if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "__setstate_cython__", 0) < (0)) __PYX_ERR(1, 3, __pyx_L3_error) + for (Py_ssize_t i = __pyx_nargs; i < 1; i++) { + if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("__setstate_cython__", 1, 1, 1, i); __PYX_ERR(1, 3, __pyx_L3_error) } + } + } else if (unlikely(__pyx_nargs != 1)) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(1, 3, __pyx_L3_error) + } + __pyx_v___pyx_state = values[0]; + } + goto __pyx_L6_skip; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__setstate_cython__", 1, 1, 1, __pyx_nargs); __PYX_ERR(1, 3, __pyx_L3_error) + __pyx_L6_skip:; + goto __pyx_L4_argument_unpacking_done; + __pyx_L3_error:; + for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { + Py_XDECREF(values[__pyx_temp]); + } + __Pyx_AddTraceback("View.MemoryView.array.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf___pyx_array_2__setstate_cython__(((struct __pyx_array_obj *)__pyx_v_self), __pyx_v___pyx_state); + + /* function exit code */ + for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { + Py_XDECREF(values[__pyx_temp]); + } + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf___pyx_array_2__setstate_cython__(CYTHON_UNUSED struct __pyx_array_obj *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__setstate_cython__", 0); + + /* "(tree fragment)":4 + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" + * def __setstate_cython__(self, __pyx_state): + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" # <<<<<<<<<<<<<< +*/ + __Pyx_Raise(((PyObject *)(((PyTypeObject*)PyExc_TypeError))), __pyx_mstate_global->__pyx_kp_u_no_default___reduce___due_to_non, 0, 0); + __PYX_ERR(1, 4, __pyx_L1_error) + + /* "(tree fragment)":3 + * def __reduce_cython__(self): + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_AddTraceback("View.MemoryView.array.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":253 + * pass + * + * @cname("__pyx_array_allocate_buffer") # <<<<<<<<<<<<<< + * cdef int _allocate_buffer(array self) except -1: + * +*/ + +static int __pyx_array_allocate_buffer(struct __pyx_array_obj *__pyx_v_self) { + Py_ssize_t __pyx_v_i; + PyObject **__pyx_v_p; + int __pyx_r; + int __pyx_t_1; + Py_ssize_t __pyx_t_2; + Py_ssize_t __pyx_t_3; + Py_ssize_t __pyx_t_4; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + + /* "View.MemoryView":260 + * cdef PyObject **p + * + * self.free_data = True # <<<<<<<<<<<<<< + * self.data = malloc(self.len) + * if not self.data: +*/ + __pyx_v_self->free_data = 1; + + /* "View.MemoryView":261 + * + * self.free_data = True + * self.data = malloc(self.len) # <<<<<<<<<<<<<< + * if not self.data: + * raise MemoryError, "unable to allocate array data." +*/ + __pyx_v_self->data = ((char *)malloc(__pyx_v_self->len)); + + /* "View.MemoryView":262 + * self.free_data = True + * self.data = malloc(self.len) + * if not self.data: # <<<<<<<<<<<<<< + * raise MemoryError, "unable to allocate array data." + * +*/ + __pyx_t_1 = (!(__pyx_v_self->data != 0)); + if (unlikely(__pyx_t_1)) { + + /* "View.MemoryView":263 + * self.data = malloc(self.len) + * if not self.data: + * raise MemoryError, "unable to allocate array data." # <<<<<<<<<<<<<< + * + * if self.dtype_is_object: +*/ + __Pyx_Raise(((PyObject *)(((PyTypeObject*)PyExc_MemoryError))), __pyx_mstate_global->__pyx_kp_u_unable_to_allocate_array_data, 0, 0); + __PYX_ERR(1, 263, __pyx_L1_error) + + /* "View.MemoryView":262 + * self.free_data = True + * self.data = malloc(self.len) + * if not self.data: # <<<<<<<<<<<<<< + * raise MemoryError, "unable to allocate array data." + * +*/ + } + + /* "View.MemoryView":265 + * raise MemoryError, "unable to allocate array data." + * + * if self.dtype_is_object: # <<<<<<<<<<<<<< + * p = self.data + * for i in range(self.len // self.itemsize): +*/ + if (__pyx_v_self->dtype_is_object) { + + /* "View.MemoryView":266 + * + * if self.dtype_is_object: + * p = self.data # <<<<<<<<<<<<<< + * for i in range(self.len // self.itemsize): + * p[i] = Py_None +*/ + __pyx_v_p = ((PyObject **)__pyx_v_self->data); + + /* "View.MemoryView":267 + * if self.dtype_is_object: + * p = self.data + * for i in range(self.len // self.itemsize): # <<<<<<<<<<<<<< + * p[i] = Py_None + * Py_INCREF(Py_None) +*/ + if (unlikely(__pyx_v_self->itemsize == 0)) { + PyErr_SetString(PyExc_ZeroDivisionError, "integer division or modulo by zero"); + __PYX_ERR(1, 267, __pyx_L1_error) + } + else if (sizeof(Py_ssize_t) == sizeof(long) && (!(((Py_ssize_t)-1) > 0)) && unlikely(__pyx_v_self->itemsize == (Py_ssize_t)-1) && unlikely(__Pyx_UNARY_NEG_WOULD_OVERFLOW(__pyx_v_self->len))) { + PyErr_SetString(PyExc_OverflowError, "value too large to perform division"); + __PYX_ERR(1, 267, __pyx_L1_error) + } + __pyx_t_2 = __Pyx_div_Py_ssize_t(__pyx_v_self->len, __pyx_v_self->itemsize, 0); + __pyx_t_3 = __pyx_t_2; + for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { + __pyx_v_i = __pyx_t_4; + + /* "View.MemoryView":268 + * p = self.data + * for i in range(self.len // self.itemsize): + * p[i] = Py_None # <<<<<<<<<<<<<< + * Py_INCREF(Py_None) + * return 0 +*/ + (__pyx_v_p[__pyx_v_i]) = Py_None; + + /* "View.MemoryView":269 + * for i in range(self.len // self.itemsize): + * p[i] = Py_None + * Py_INCREF(Py_None) # <<<<<<<<<<<<<< + * return 0 + * +*/ + Py_INCREF(Py_None); + } + + /* "View.MemoryView":265 + * raise MemoryError, "unable to allocate array data." + * + * if self.dtype_is_object: # <<<<<<<<<<<<<< + * p = self.data + * for i in range(self.len // self.itemsize): +*/ + } + + /* "View.MemoryView":270 + * p[i] = Py_None + * Py_INCREF(Py_None) + * return 0 # <<<<<<<<<<<<<< + * + * +*/ + __pyx_r = 0; + goto __pyx_L0; + + /* "View.MemoryView":253 + * pass + * + * @cname("__pyx_array_allocate_buffer") # <<<<<<<<<<<<<< + * cdef int _allocate_buffer(array self) except -1: + * +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_AddTraceback("View.MemoryView._allocate_buffer", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + return __pyx_r; +} + +/* "View.MemoryView":273 + * + * + * @cname("__pyx_array_new") # <<<<<<<<<<<<<< + * cdef array array_cwrapper(tuple shape, Py_ssize_t itemsize, char *format, const char *c_mode, char *buf): + * cdef array result +*/ + +static struct __pyx_array_obj *__pyx_array_new(PyObject *__pyx_v_shape, Py_ssize_t __pyx_v_itemsize, char *__pyx_v_format, char const *__pyx_v_c_mode, char *__pyx_v_buf) { + struct __pyx_array_obj *__pyx_v_result = 0; + PyObject *__pyx_v_mode = 0; + struct __pyx_array_obj *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("array_cwrapper", 0); + + /* "View.MemoryView":276 + * cdef array array_cwrapper(tuple shape, Py_ssize_t itemsize, char *format, const char *c_mode, char *buf): + * cdef array result + * cdef str mode = "fortran" if c_mode[0] == b'f' else "c" # this often comes from a constant C string. # <<<<<<<<<<<<<< + * + * if buf is NULL: +*/ + __pyx_t_2 = ((__pyx_v_c_mode[0]) == 'f'); + if (__pyx_t_2) { + __Pyx_INCREF(__pyx_mstate_global->__pyx_n_u_fortran); + __pyx_t_1 = __pyx_mstate_global->__pyx_n_u_fortran; + } else { + __Pyx_INCREF(__pyx_mstate_global->__pyx_n_u_c); + __pyx_t_1 = __pyx_mstate_global->__pyx_n_u_c; + } + __pyx_v_mode = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "View.MemoryView":278 + * cdef str mode = "fortran" if c_mode[0] == b'f' else "c" # this often comes from a constant C string. + * + * if buf is NULL: # <<<<<<<<<<<<<< + * result = array.__new__(array, shape, itemsize, format, mode) + * else: +*/ + __pyx_t_2 = (__pyx_v_buf == NULL); + if (__pyx_t_2) { + + /* "View.MemoryView":279 + * + * if buf is NULL: + * result = array.__new__(array, shape, itemsize, format, mode) # <<<<<<<<<<<<<< + * else: + * result = array.__new__(array, shape, itemsize, format, mode, allocate_buffer=False) +*/ + __pyx_t_1 = PyLong_FromSsize_t(__pyx_v_itemsize); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 279, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = __Pyx_PyBytes_FromString(__pyx_v_format); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 279, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = PyTuple_New(4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 279, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(__pyx_v_shape); + __Pyx_GIVEREF(__pyx_v_shape); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_shape) != (0)) __PYX_ERR(1, 279, __pyx_L1_error); + __Pyx_GIVEREF(__pyx_t_1); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_1) != (0)) __PYX_ERR(1, 279, __pyx_L1_error); + __Pyx_GIVEREF(__pyx_t_3); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_t_3) != (0)) __PYX_ERR(1, 279, __pyx_L1_error); + __Pyx_INCREF(__pyx_v_mode); + __Pyx_GIVEREF(__pyx_v_mode); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 3, __pyx_v_mode) != (0)) __PYX_ERR(1, 279, __pyx_L1_error); + __pyx_t_1 = 0; + __pyx_t_3 = 0; + __pyx_t_3 = ((PyObject *)__pyx_tp_new_array(((PyTypeObject *)__pyx_mstate_global->__pyx_array_type), __pyx_t_4, NULL)); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 279, __pyx_L1_error) + __Pyx_GOTREF((PyObject *)__pyx_t_3); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_v_result = ((struct __pyx_array_obj *)__pyx_t_3); + __pyx_t_3 = 0; + + /* "View.MemoryView":278 + * cdef str mode = "fortran" if c_mode[0] == b'f' else "c" # this often comes from a constant C string. + * + * if buf is NULL: # <<<<<<<<<<<<<< + * result = array.__new__(array, shape, itemsize, format, mode) + * else: +*/ + goto __pyx_L3; + } + + /* "View.MemoryView":281 + * result = array.__new__(array, shape, itemsize, format, mode) + * else: + * result = array.__new__(array, shape, itemsize, format, mode, allocate_buffer=False) # <<<<<<<<<<<<<< + * result.data = buf + * +*/ + /*else*/ { + __pyx_t_3 = PyLong_FromSsize_t(__pyx_v_itemsize); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 281, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = __Pyx_PyBytes_FromString(__pyx_v_format); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 281, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = PyTuple_New(4); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 281, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_shape); + __Pyx_GIVEREF(__pyx_v_shape); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_shape) != (0)) __PYX_ERR(1, 281, __pyx_L1_error); + __Pyx_GIVEREF(__pyx_t_3); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_3) != (0)) __PYX_ERR(1, 281, __pyx_L1_error); + __Pyx_GIVEREF(__pyx_t_4); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_t_4) != (0)) __PYX_ERR(1, 281, __pyx_L1_error); + __Pyx_INCREF(__pyx_v_mode); + __Pyx_GIVEREF(__pyx_v_mode); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 3, __pyx_v_mode) != (0)) __PYX_ERR(1, 281, __pyx_L1_error); + __pyx_t_3 = 0; + __pyx_t_4 = 0; + __pyx_t_4 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 281, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + if (PyDict_SetItem(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_allocate_buffer, Py_False) < (0)) __PYX_ERR(1, 281, __pyx_L1_error) + __pyx_t_3 = ((PyObject *)__pyx_tp_new_array(((PyTypeObject *)__pyx_mstate_global->__pyx_array_type), __pyx_t_1, __pyx_t_4)); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 281, __pyx_L1_error) + __Pyx_GOTREF((PyObject *)__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_v_result = ((struct __pyx_array_obj *)__pyx_t_3); + __pyx_t_3 = 0; + + /* "View.MemoryView":282 + * else: + * result = array.__new__(array, shape, itemsize, format, mode, allocate_buffer=False) + * result.data = buf # <<<<<<<<<<<<<< + * + * return result +*/ + __pyx_v_result->data = __pyx_v_buf; + } + __pyx_L3:; + + /* "View.MemoryView":284 + * result.data = buf + * + * return result # <<<<<<<<<<<<<< + * + * +*/ + __Pyx_XDECREF((PyObject *)__pyx_r); + __Pyx_INCREF((PyObject *)__pyx_v_result); + __pyx_r = __pyx_v_result; + goto __pyx_L0; + + /* "View.MemoryView":273 + * + * + * @cname("__pyx_array_new") # <<<<<<<<<<<<<< + * cdef array array_cwrapper(tuple shape, Py_ssize_t itemsize, char *format, const char *c_mode, char *buf): + * cdef array result +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_AddTraceback("View.MemoryView.array_cwrapper", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF((PyObject *)__pyx_v_result); + __Pyx_XDECREF(__pyx_v_mode); + __Pyx_XGIVEREF((PyObject *)__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":310 + * cdef class Enum(object): + * cdef object name + * def __init__(self, name): # <<<<<<<<<<<<<< + * self.name = name + * def __repr__(self): +*/ + +/* Python wrapper */ +static int __pyx_MemviewEnum___init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static int __pyx_MemviewEnum___init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_name = 0; + CYTHON_UNUSED Py_ssize_t __pyx_nargs; + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject* values[1] = {0}; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__init__ (wrapper)", 0); + #if CYTHON_ASSUME_SAFE_SIZE + __pyx_nargs = PyTuple_GET_SIZE(__pyx_args); + #else + __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return -1; + #endif + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + { + PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_name,0}; + const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_VARARGS(__pyx_kwds) : 0; + if (unlikely(__pyx_kwds_len < 0)) __PYX_ERR(1, 310, __pyx_L3_error) + if (__pyx_kwds_len > 0) { + switch (__pyx_nargs) { + case 1: + values[0] = __Pyx_ArgRef_VARARGS(__pyx_args, 0); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(1, 310, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + const Py_ssize_t kwd_pos_args = __pyx_nargs; + if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "__init__", 0) < (0)) __PYX_ERR(1, 310, __pyx_L3_error) + for (Py_ssize_t i = __pyx_nargs; i < 1; i++) { + if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("__init__", 1, 1, 1, i); __PYX_ERR(1, 310, __pyx_L3_error) } + } + } else if (unlikely(__pyx_nargs != 1)) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = __Pyx_ArgRef_VARARGS(__pyx_args, 0); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(1, 310, __pyx_L3_error) + } + __pyx_v_name = values[0]; + } + goto __pyx_L6_skip; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__init__", 1, 1, 1, __pyx_nargs); __PYX_ERR(1, 310, __pyx_L3_error) + __pyx_L6_skip:; + goto __pyx_L4_argument_unpacking_done; + __pyx_L3_error:; + for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { + Py_XDECREF(values[__pyx_temp]); + } + __Pyx_AddTraceback("View.MemoryView.Enum.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return -1; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_MemviewEnum___pyx_pf_15View_dot_MemoryView_4Enum___init__(((struct __pyx_MemviewEnum_obj *)__pyx_v_self), __pyx_v_name); + + /* function exit code */ + for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { + Py_XDECREF(values[__pyx_temp]); + } + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_MemviewEnum___pyx_pf_15View_dot_MemoryView_4Enum___init__(struct __pyx_MemviewEnum_obj *__pyx_v_self, PyObject *__pyx_v_name) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__init__", 0); + + /* "View.MemoryView":311 + * cdef object name + * def __init__(self, name): + * self.name = name # <<<<<<<<<<<<<< + * def __repr__(self): + * return self.name +*/ + __Pyx_INCREF(__pyx_v_name); + __Pyx_GIVEREF(__pyx_v_name); + __Pyx_GOTREF(__pyx_v_self->name); + __Pyx_DECREF(__pyx_v_self->name); + __pyx_v_self->name = __pyx_v_name; + + /* "View.MemoryView":310 + * cdef class Enum(object): + * cdef object name + * def __init__(self, name): # <<<<<<<<<<<<<< + * self.name = name + * def __repr__(self): +*/ + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":312 + * def __init__(self, name): + * self.name = name + * def __repr__(self): # <<<<<<<<<<<<<< + * return self.name + * +*/ + +/* Python wrapper */ +static PyObject *__pyx_MemviewEnum___repr__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_MemviewEnum___repr__(PyObject *__pyx_v_self) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__repr__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_r = __pyx_MemviewEnum___pyx_pf_15View_dot_MemoryView_4Enum_2__repr__(((struct __pyx_MemviewEnum_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_MemviewEnum___pyx_pf_15View_dot_MemoryView_4Enum_2__repr__(struct __pyx_MemviewEnum_obj *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__repr__", 0); + + /* "View.MemoryView":313 + * self.name = name + * def __repr__(self): + * return self.name # <<<<<<<<<<<<<< + * + * cdef generic = Enum("") +*/ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->name); + __pyx_r = __pyx_v_self->name; + goto __pyx_L0; + + /* "View.MemoryView":312 + * def __init__(self, name): + * self.name = name + * def __repr__(self): # <<<<<<<<<<<<<< + * return self.name + * +*/ + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * cdef tuple state + * cdef object _dict +*/ + +/* Python wrapper */ +static PyObject *__pyx_pw___pyx_MemviewEnum_1__reduce_cython__(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +); /*proto*/ +static PyObject *__pyx_pw___pyx_MemviewEnum_1__reduce_cython__(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +) { + #if !CYTHON_METH_FASTCALL + CYTHON_UNUSED Py_ssize_t __pyx_nargs; + #endif + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); + #if !CYTHON_METH_FASTCALL + #if CYTHON_ASSUME_SAFE_SIZE + __pyx_nargs = PyTuple_GET_SIZE(__pyx_args); + #else + __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL; + #endif + #endif + __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs); + if (unlikely(__pyx_nargs > 0)) { __Pyx_RaiseArgtupleInvalid("__reduce_cython__", 1, 0, 0, __pyx_nargs); return NULL; } + const Py_ssize_t __pyx_kwds_len = unlikely(__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0; + if (unlikely(__pyx_kwds_len < 0)) return NULL; + if (unlikely(__pyx_kwds_len > 0)) {__Pyx_RejectKeywords("__reduce_cython__", __pyx_kwds); return NULL;} + __pyx_r = __pyx_pf___pyx_MemviewEnum___reduce_cython__(((struct __pyx_MemviewEnum_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf___pyx_MemviewEnum___reduce_cython__(struct __pyx_MemviewEnum_obj *__pyx_v_self) { + PyObject *__pyx_v_state = 0; + PyObject *__pyx_v__dict = 0; + int __pyx_v_use_setstate; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__reduce_cython__", 0); + + /* "(tree fragment)":5 + * cdef object _dict + * cdef bint use_setstate + * state = (self.name,) # <<<<<<<<<<<<<< + * _dict = getattr(self, '__dict__', None) + * if _dict is not None and _dict: +*/ + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_self->name); + __Pyx_GIVEREF(__pyx_v_self->name); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_self->name) != (0)) __PYX_ERR(1, 5, __pyx_L1_error); + __pyx_v_state = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "(tree fragment)":6 + * cdef bint use_setstate + * state = (self.name,) + * _dict = getattr(self, '__dict__', None) # <<<<<<<<<<<<<< + * if _dict is not None and _dict: + * state += (_dict,) +*/ + __pyx_t_1 = __Pyx_GetAttr3(((PyObject *)__pyx_v_self), __pyx_mstate_global->__pyx_n_u_dict, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v__dict = __pyx_t_1; + __pyx_t_1 = 0; + + /* "(tree fragment)":7 + * state = (self.name,) + * _dict = getattr(self, '__dict__', None) + * if _dict is not None and _dict: # <<<<<<<<<<<<<< + * state += (_dict,) + * use_setstate = True +*/ + __pyx_t_3 = (__pyx_v__dict != Py_None); + if (__pyx_t_3) { + } else { + __pyx_t_2 = __pyx_t_3; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_v__dict); if (unlikely((__pyx_t_3 < 0))) __PYX_ERR(1, 7, __pyx_L1_error) + __pyx_t_2 = __pyx_t_3; + __pyx_L4_bool_binop_done:; + if (__pyx_t_2) { + + /* "(tree fragment)":8 + * _dict = getattr(self, '__dict__', None) + * if _dict is not None and _dict: + * state += (_dict,) # <<<<<<<<<<<<<< + * use_setstate = True + * else: +*/ + __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v__dict); + __Pyx_GIVEREF(__pyx_v__dict); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v__dict) != (0)) __PYX_ERR(1, 8, __pyx_L1_error); + __pyx_t_4 = PyNumber_InPlaceAdd(__pyx_v_state, __pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF_SET(__pyx_v_state, ((PyObject*)__pyx_t_4)); + __pyx_t_4 = 0; + + /* "(tree fragment)":9 + * if _dict is not None and _dict: + * state += (_dict,) + * use_setstate = True # <<<<<<<<<<<<<< + * else: + * use_setstate = self.name is not None +*/ + __pyx_v_use_setstate = 1; + + /* "(tree fragment)":7 + * state = (self.name,) + * _dict = getattr(self, '__dict__', None) + * if _dict is not None and _dict: # <<<<<<<<<<<<<< + * state += (_dict,) + * use_setstate = True +*/ + goto __pyx_L3; + } + + /* "(tree fragment)":11 + * use_setstate = True + * else: + * use_setstate = self.name is not None # <<<<<<<<<<<<<< + * if use_setstate: + * return __pyx_unpickle_Enum, (type(self), 0x82a3537, None), state +*/ + /*else*/ { + __pyx_t_2 = (__pyx_v_self->name != Py_None); + __pyx_v_use_setstate = __pyx_t_2; + } + __pyx_L3:; + + /* "(tree fragment)":12 + * else: + * use_setstate = self.name is not None + * if use_setstate: # <<<<<<<<<<<<<< + * return __pyx_unpickle_Enum, (type(self), 0x82a3537, None), state + * else: +*/ + if (__pyx_v_use_setstate) { + + /* "(tree fragment)":13 + * use_setstate = self.name is not None + * if use_setstate: + * return __pyx_unpickle_Enum, (type(self), 0x82a3537, None), state # <<<<<<<<<<<<<< + * else: + * return __pyx_unpickle_Enum, (type(self), 0x82a3537, state) +*/ + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_pyx_unpickle_Enum); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))) != (0)) __PYX_ERR(1, 13, __pyx_L1_error); + __Pyx_INCREF(__pyx_mstate_global->__pyx_int_136983863); + __Pyx_GIVEREF(__pyx_mstate_global->__pyx_int_136983863); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_mstate_global->__pyx_int_136983863) != (0)) __PYX_ERR(1, 13, __pyx_L1_error); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 2, Py_None) != (0)) __PYX_ERR(1, 13, __pyx_L1_error); + __pyx_t_5 = PyTuple_New(3); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_GIVEREF(__pyx_t_4); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4) != (0)) __PYX_ERR(1, 13, __pyx_L1_error); + __Pyx_GIVEREF(__pyx_t_1); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_1) != (0)) __PYX_ERR(1, 13, __pyx_L1_error); + __Pyx_INCREF(__pyx_v_state); + __Pyx_GIVEREF(__pyx_v_state); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_5, 2, __pyx_v_state) != (0)) __PYX_ERR(1, 13, __pyx_L1_error); + __pyx_t_4 = 0; + __pyx_t_1 = 0; + __pyx_r = __pyx_t_5; + __pyx_t_5 = 0; + goto __pyx_L0; + + /* "(tree fragment)":12 + * else: + * use_setstate = self.name is not None + * if use_setstate: # <<<<<<<<<<<<<< + * return __pyx_unpickle_Enum, (type(self), 0x82a3537, None), state + * else: +*/ + } + + /* "(tree fragment)":15 + * return __pyx_unpickle_Enum, (type(self), 0x82a3537, None), state + * else: + * return __pyx_unpickle_Enum, (type(self), 0x82a3537, state) # <<<<<<<<<<<<<< + * def __setstate_cython__(self, __pyx_state): + * __pyx_unpickle_Enum__set_state(self, __pyx_state) +*/ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_mstate_global->__pyx_n_u_pyx_unpickle_Enum); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))) != (0)) __PYX_ERR(1, 15, __pyx_L1_error); + __Pyx_INCREF(__pyx_mstate_global->__pyx_int_136983863); + __Pyx_GIVEREF(__pyx_mstate_global->__pyx_int_136983863); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_mstate_global->__pyx_int_136983863) != (0)) __PYX_ERR(1, 15, __pyx_L1_error); + __Pyx_INCREF(__pyx_v_state); + __Pyx_GIVEREF(__pyx_v_state); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_state) != (0)) __PYX_ERR(1, 15, __pyx_L1_error); + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GIVEREF(__pyx_t_5); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_5) != (0)) __PYX_ERR(1, 15, __pyx_L1_error); + __Pyx_GIVEREF(__pyx_t_1); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_1) != (0)) __PYX_ERR(1, 15, __pyx_L1_error); + __pyx_t_5 = 0; + __pyx_t_1 = 0; + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; + goto __pyx_L0; + } + + /* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * cdef tuple state + * cdef object _dict +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("View.MemoryView.Enum.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_state); + __Pyx_XDECREF(__pyx_v__dict); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":16 + * else: + * return __pyx_unpickle_Enum, (type(self), 0x82a3537, state) + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * __pyx_unpickle_Enum__set_state(self, __pyx_state) +*/ + +/* Python wrapper */ +static PyObject *__pyx_pw___pyx_MemviewEnum_3__setstate_cython__(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +); /*proto*/ +static PyObject *__pyx_pw___pyx_MemviewEnum_3__setstate_cython__(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +) { + PyObject *__pyx_v___pyx_state = 0; + #if !CYTHON_METH_FASTCALL + CYTHON_UNUSED Py_ssize_t __pyx_nargs; + #endif + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject* values[1] = {0}; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); + #if !CYTHON_METH_FASTCALL + #if CYTHON_ASSUME_SAFE_SIZE + __pyx_nargs = PyTuple_GET_SIZE(__pyx_args); + #else + __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL; + #endif + #endif + __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs); + { + PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_pyx_state,0}; + const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0; + if (unlikely(__pyx_kwds_len < 0)) __PYX_ERR(1, 16, __pyx_L3_error) + if (__pyx_kwds_len > 0) { + switch (__pyx_nargs) { + case 1: + values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(1, 16, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + const Py_ssize_t kwd_pos_args = __pyx_nargs; + if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "__setstate_cython__", 0) < (0)) __PYX_ERR(1, 16, __pyx_L3_error) + for (Py_ssize_t i = __pyx_nargs; i < 1; i++) { + if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("__setstate_cython__", 1, 1, 1, i); __PYX_ERR(1, 16, __pyx_L3_error) } + } + } else if (unlikely(__pyx_nargs != 1)) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(1, 16, __pyx_L3_error) + } + __pyx_v___pyx_state = values[0]; + } + goto __pyx_L6_skip; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__setstate_cython__", 1, 1, 1, __pyx_nargs); __PYX_ERR(1, 16, __pyx_L3_error) + __pyx_L6_skip:; + goto __pyx_L4_argument_unpacking_done; + __pyx_L3_error:; + for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { + Py_XDECREF(values[__pyx_temp]); + } + __Pyx_AddTraceback("View.MemoryView.Enum.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf___pyx_MemviewEnum_2__setstate_cython__(((struct __pyx_MemviewEnum_obj *)__pyx_v_self), __pyx_v___pyx_state); + + /* function exit code */ + for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { + Py_XDECREF(values[__pyx_temp]); + } + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf___pyx_MemviewEnum_2__setstate_cython__(struct __pyx_MemviewEnum_obj *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__setstate_cython__", 0); + + /* "(tree fragment)":17 + * return __pyx_unpickle_Enum, (type(self), 0x82a3537, state) + * def __setstate_cython__(self, __pyx_state): + * __pyx_unpickle_Enum__set_state(self, __pyx_state) # <<<<<<<<<<<<<< +*/ + __pyx_t_1 = __pyx_v___pyx_state; + __Pyx_INCREF(__pyx_t_1); + if (!(likely(PyTuple_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None) || __Pyx_RaiseUnexpectedTypeError("tuple", __pyx_t_1))) __PYX_ERR(1, 17, __pyx_L1_error) + if (unlikely(__pyx_t_1 == Py_None)) { + PyErr_SetString(PyExc_TypeError, "cannot pass None into a C function argument that is declared 'not None'"); + __PYX_ERR(1, 17, __pyx_L1_error) + } + __pyx_t_2 = __pyx_unpickle_Enum__set_state(__pyx_v_self, ((PyObject*)__pyx_t_1)); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 17, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "(tree fragment)":16 + * else: + * return __pyx_unpickle_Enum, (type(self), 0x82a3537, state) + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * __pyx_unpickle_Enum__set_state(self, __pyx_state) +*/ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("View.MemoryView.Enum.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":356 + * cdef const __Pyx_TypeInfo *typeinfo + * + * def __cinit__(memoryview self, object obj, int flags, bint dtype_is_object=False): # <<<<<<<<<<<<<< + * self.obj = obj + * self.flags = flags +*/ + +/* Python wrapper */ +static int __pyx_memoryview___cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static int __pyx_memoryview___cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_obj = 0; + int __pyx_v_flags; + int __pyx_v_dtype_is_object; + CYTHON_UNUSED Py_ssize_t __pyx_nargs; + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject* values[3] = {0,0,0}; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0); + #if CYTHON_ASSUME_SAFE_SIZE + __pyx_nargs = PyTuple_GET_SIZE(__pyx_args); + #else + __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return -1; + #endif + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + { + PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_obj,&__pyx_mstate_global->__pyx_n_u_flags,&__pyx_mstate_global->__pyx_n_u_dtype_is_object,0}; + const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_VARARGS(__pyx_kwds) : 0; + if (unlikely(__pyx_kwds_len < 0)) __PYX_ERR(1, 356, __pyx_L3_error) + if (__pyx_kwds_len > 0) { + switch (__pyx_nargs) { + case 3: + values[2] = __Pyx_ArgRef_VARARGS(__pyx_args, 2); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(1, 356, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 2: + values[1] = __Pyx_ArgRef_VARARGS(__pyx_args, 1); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(1, 356, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 1: + values[0] = __Pyx_ArgRef_VARARGS(__pyx_args, 0); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(1, 356, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + const Py_ssize_t kwd_pos_args = __pyx_nargs; + if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "__cinit__", 0) < (0)) __PYX_ERR(1, 356, __pyx_L3_error) + for (Py_ssize_t i = __pyx_nargs; i < 2; i++) { + if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 2, 3, i); __PYX_ERR(1, 356, __pyx_L3_error) } + } + } else { + switch (__pyx_nargs) { + case 3: + values[2] = __Pyx_ArgRef_VARARGS(__pyx_args, 2); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(1, 356, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 2: + values[1] = __Pyx_ArgRef_VARARGS(__pyx_args, 1); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(1, 356, __pyx_L3_error) + values[0] = __Pyx_ArgRef_VARARGS(__pyx_args, 0); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(1, 356, __pyx_L3_error) + break; + default: goto __pyx_L5_argtuple_error; + } + } + __pyx_v_obj = values[0]; + __pyx_v_flags = __Pyx_PyLong_As_int(values[1]); if (unlikely((__pyx_v_flags == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 356, __pyx_L3_error) + if (values[2]) { + __pyx_v_dtype_is_object = __Pyx_PyObject_IsTrue(values[2]); if (unlikely((__pyx_v_dtype_is_object == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 356, __pyx_L3_error) + } else { + __pyx_v_dtype_is_object = ((int)0); + } + } + goto __pyx_L6_skip; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 2, 3, __pyx_nargs); __PYX_ERR(1, 356, __pyx_L3_error) + __pyx_L6_skip:; + goto __pyx_L4_argument_unpacking_done; + __pyx_L3_error:; + for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { + Py_XDECREF(values[__pyx_temp]); + } + __Pyx_AddTraceback("View.MemoryView.memoryview.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return -1; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview___cinit__(((struct __pyx_memoryview_obj *)__pyx_v_self), __pyx_v_obj, __pyx_v_flags, __pyx_v_dtype_is_object); + + /* function exit code */ + for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { + Py_XDECREF(values[__pyx_temp]); + } + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview___cinit__(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_obj, int __pyx_v_flags, int __pyx_v_dtype_is_object) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__cinit__", 0); + + /* "View.MemoryView":357 + * + * def __cinit__(memoryview self, object obj, int flags, bint dtype_is_object=False): + * self.obj = obj # <<<<<<<<<<<<<< + * self.flags = flags + * if type(self) is memoryview or obj is not None: +*/ + __Pyx_INCREF(__pyx_v_obj); + __Pyx_GIVEREF(__pyx_v_obj); + __Pyx_GOTREF(__pyx_v_self->obj); + __Pyx_DECREF(__pyx_v_self->obj); + __pyx_v_self->obj = __pyx_v_obj; + + /* "View.MemoryView":358 + * def __cinit__(memoryview self, object obj, int flags, bint dtype_is_object=False): + * self.obj = obj + * self.flags = flags # <<<<<<<<<<<<<< + * if type(self) is memoryview or obj is not None: + * PyObject_GetBuffer(obj, &self.view, flags) +*/ + __pyx_v_self->flags = __pyx_v_flags; + + /* "View.MemoryView":359 + * self.obj = obj + * self.flags = flags + * if type(self) is memoryview or obj is not None: # <<<<<<<<<<<<<< + * PyObject_GetBuffer(obj, &self.view, flags) + * if self.view.obj == NULL: +*/ + __pyx_t_2 = (((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))) == ((PyObject *)__pyx_mstate_global->__pyx_memoryview_type)); + if (!__pyx_t_2) { + } else { + __pyx_t_1 = __pyx_t_2; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_2 = (__pyx_v_obj != Py_None); + __pyx_t_1 = __pyx_t_2; + __pyx_L4_bool_binop_done:; + if (__pyx_t_1) { + + /* "View.MemoryView":360 + * self.flags = flags + * if type(self) is memoryview or obj is not None: + * PyObject_GetBuffer(obj, &self.view, flags) # <<<<<<<<<<<<<< + * if self.view.obj == NULL: + * (<__pyx_buffer *> &self.view).obj = Py_None +*/ + __pyx_t_3 = PyObject_GetBuffer(__pyx_v_obj, (&__pyx_v_self->view), __pyx_v_flags); if (unlikely(__pyx_t_3 == ((int)-1))) __PYX_ERR(1, 360, __pyx_L1_error) + + /* "View.MemoryView":361 + * if type(self) is memoryview or obj is not None: + * PyObject_GetBuffer(obj, &self.view, flags) + * if self.view.obj == NULL: # <<<<<<<<<<<<<< + * (<__pyx_buffer *> &self.view).obj = Py_None + * Py_INCREF(Py_None) +*/ + __pyx_t_1 = (((PyObject *)__pyx_v_self->view.obj) == NULL); + if (__pyx_t_1) { + + /* "View.MemoryView":362 + * PyObject_GetBuffer(obj, &self.view, flags) + * if self.view.obj == NULL: + * (<__pyx_buffer *> &self.view).obj = Py_None # <<<<<<<<<<<<<< + * Py_INCREF(Py_None) + * +*/ + ((Py_buffer *)(&__pyx_v_self->view))->obj = Py_None; + + /* "View.MemoryView":363 + * if self.view.obj == NULL: + * (<__pyx_buffer *> &self.view).obj = Py_None + * Py_INCREF(Py_None) # <<<<<<<<<<<<<< + * + * if not __PYX_CYTHON_ATOMICS_ENABLED(): +*/ + Py_INCREF(Py_None); + + /* "View.MemoryView":361 + * if type(self) is memoryview or obj is not None: + * PyObject_GetBuffer(obj, &self.view, flags) + * if self.view.obj == NULL: # <<<<<<<<<<<<<< + * (<__pyx_buffer *> &self.view).obj = Py_None + * Py_INCREF(Py_None) +*/ + } + + /* "View.MemoryView":359 + * self.obj = obj + * self.flags = flags + * if type(self) is memoryview or obj is not None: # <<<<<<<<<<<<<< + * PyObject_GetBuffer(obj, &self.view, flags) + * if self.view.obj == NULL: +*/ + } + + /* "View.MemoryView":365 + * Py_INCREF(Py_None) + * + * if not __PYX_CYTHON_ATOMICS_ENABLED(): # <<<<<<<<<<<<<< + * global __pyx_memoryview_thread_locks_used + * if (__pyx_memoryview_thread_locks_used < 8 and +*/ + __pyx_t_1 = (!__PYX_CYTHON_ATOMICS_ENABLED()); + if (__pyx_t_1) { + + /* "View.MemoryView":367 + * if not __PYX_CYTHON_ATOMICS_ENABLED(): + * global __pyx_memoryview_thread_locks_used + * if (__pyx_memoryview_thread_locks_used < 8 and # <<<<<<<<<<<<<< + * + * not __PYX_GET_CYTHON_COMPILING_IN_CPYTHON_FREETHREADING()): +*/ + __pyx_t_2 = (__pyx_memoryview_thread_locks_used < 8); + if (__pyx_t_2) { + } else { + __pyx_t_1 = __pyx_t_2; + goto __pyx_L9_bool_binop_done; + } + + /* "View.MemoryView":369 + * if (__pyx_memoryview_thread_locks_used < 8 and + * + * not __PYX_GET_CYTHON_COMPILING_IN_CPYTHON_FREETHREADING()): # <<<<<<<<<<<<<< + * self.lock = __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] + * __pyx_memoryview_thread_locks_used += 1 +*/ + __pyx_t_2 = (!__PYX_GET_CYTHON_COMPILING_IN_CPYTHON_FREETHREADING()); + __pyx_t_1 = __pyx_t_2; + __pyx_L9_bool_binop_done:; + + /* "View.MemoryView":367 + * if not __PYX_CYTHON_ATOMICS_ENABLED(): + * global __pyx_memoryview_thread_locks_used + * if (__pyx_memoryview_thread_locks_used < 8 and # <<<<<<<<<<<<<< + * + * not __PYX_GET_CYTHON_COMPILING_IN_CPYTHON_FREETHREADING()): +*/ + if (__pyx_t_1) { + + /* "View.MemoryView":370 + * + * not __PYX_GET_CYTHON_COMPILING_IN_CPYTHON_FREETHREADING()): + * self.lock = __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] # <<<<<<<<<<<<<< + * __pyx_memoryview_thread_locks_used += 1 + * if self.lock is NULL: +*/ + __pyx_v_self->lock = (__pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used]); + + /* "View.MemoryView":371 + * not __PYX_GET_CYTHON_COMPILING_IN_CPYTHON_FREETHREADING()): + * self.lock = __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] + * __pyx_memoryview_thread_locks_used += 1 # <<<<<<<<<<<<<< + * if self.lock is NULL: + * self.lock = PyThread_allocate_lock() +*/ + __pyx_memoryview_thread_locks_used = (__pyx_memoryview_thread_locks_used + 1); + + /* "View.MemoryView":367 + * if not __PYX_CYTHON_ATOMICS_ENABLED(): + * global __pyx_memoryview_thread_locks_used + * if (__pyx_memoryview_thread_locks_used < 8 and # <<<<<<<<<<<<<< + * + * not __PYX_GET_CYTHON_COMPILING_IN_CPYTHON_FREETHREADING()): +*/ + } + + /* "View.MemoryView":372 + * self.lock = __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] + * __pyx_memoryview_thread_locks_used += 1 + * if self.lock is NULL: # <<<<<<<<<<<<<< + * self.lock = PyThread_allocate_lock() + * if self.lock is NULL: +*/ + __pyx_t_1 = (__pyx_v_self->lock == NULL); + if (__pyx_t_1) { + + /* "View.MemoryView":373 + * __pyx_memoryview_thread_locks_used += 1 + * if self.lock is NULL: + * self.lock = PyThread_allocate_lock() # <<<<<<<<<<<<<< + * if self.lock is NULL: + * raise MemoryError +*/ + __pyx_v_self->lock = PyThread_allocate_lock(); + + /* "View.MemoryView":374 + * if self.lock is NULL: + * self.lock = PyThread_allocate_lock() + * if self.lock is NULL: # <<<<<<<<<<<<<< + * raise MemoryError + * +*/ + __pyx_t_1 = (__pyx_v_self->lock == NULL); + if (unlikely(__pyx_t_1)) { + + /* "View.MemoryView":375 + * self.lock = PyThread_allocate_lock() + * if self.lock is NULL: + * raise MemoryError # <<<<<<<<<<<<<< + * + * if flags & PyBUF_FORMAT: +*/ + PyErr_NoMemory(); __PYX_ERR(1, 375, __pyx_L1_error) + + /* "View.MemoryView":374 + * if self.lock is NULL: + * self.lock = PyThread_allocate_lock() + * if self.lock is NULL: # <<<<<<<<<<<<<< + * raise MemoryError + * +*/ + } + + /* "View.MemoryView":372 + * self.lock = __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] + * __pyx_memoryview_thread_locks_used += 1 + * if self.lock is NULL: # <<<<<<<<<<<<<< + * self.lock = PyThread_allocate_lock() + * if self.lock is NULL: +*/ + } + + /* "View.MemoryView":365 + * Py_INCREF(Py_None) + * + * if not __PYX_CYTHON_ATOMICS_ENABLED(): # <<<<<<<<<<<<<< + * global __pyx_memoryview_thread_locks_used + * if (__pyx_memoryview_thread_locks_used < 8 and +*/ + } + + /* "View.MemoryView":377 + * raise MemoryError + * + * if flags & PyBUF_FORMAT: # <<<<<<<<<<<<<< + * self.dtype_is_object = (self.view.format[0] == b'O' and self.view.format[1] == b'\0') + * else: +*/ + __pyx_t_1 = ((__pyx_v_flags & PyBUF_FORMAT) != 0); + if (__pyx_t_1) { + + /* "View.MemoryView":378 + * + * if flags & PyBUF_FORMAT: + * self.dtype_is_object = (self.view.format[0] == b'O' and self.view.format[1] == b'\0') # <<<<<<<<<<<<<< + * else: + * self.dtype_is_object = dtype_is_object +*/ + __pyx_t_2 = ((__pyx_v_self->view.format[0]) == 'O'); + if (__pyx_t_2) { + } else { + __pyx_t_1 = __pyx_t_2; + goto __pyx_L14_bool_binop_done; + } + __pyx_t_2 = ((__pyx_v_self->view.format[1]) == '\x00'); + __pyx_t_1 = __pyx_t_2; + __pyx_L14_bool_binop_done:; + __pyx_v_self->dtype_is_object = __pyx_t_1; + + /* "View.MemoryView":377 + * raise MemoryError + * + * if flags & PyBUF_FORMAT: # <<<<<<<<<<<<<< + * self.dtype_is_object = (self.view.format[0] == b'O' and self.view.format[1] == b'\0') + * else: +*/ + goto __pyx_L13; + } + + /* "View.MemoryView":380 + * self.dtype_is_object = (self.view.format[0] == b'O' and self.view.format[1] == b'\0') + * else: + * self.dtype_is_object = dtype_is_object # <<<<<<<<<<<<<< + * + * with cython.cdivision(True): +*/ + /*else*/ { + __pyx_v_self->dtype_is_object = __pyx_v_dtype_is_object; + } + __pyx_L13:; + + /* "View.MemoryView":383 + * + * with cython.cdivision(True): + * assert (&self.acquisition_count) % sizeof(__pyx_atomic_int_type) == 0 # <<<<<<<<<<<<<< + * self.typeinfo = NULL + * +*/ + #ifndef CYTHON_WITHOUT_ASSERTIONS + if (unlikely(__pyx_assertions_enabled())) { + __pyx_t_1 = ((((Py_intptr_t)(&__pyx_v_self->acquisition_count)) % (sizeof(__pyx_atomic_int_type))) == 0); + if (unlikely(!__pyx_t_1)) { + __Pyx_Raise(((PyObject *)(((PyTypeObject*)PyExc_AssertionError))), 0, 0, 0); + __PYX_ERR(1, 383, __pyx_L1_error) + } + } + #else + if ((1)); else __PYX_ERR(1, 383, __pyx_L1_error) + #endif + + /* "View.MemoryView":384 + * with cython.cdivision(True): + * assert (&self.acquisition_count) % sizeof(__pyx_atomic_int_type) == 0 + * self.typeinfo = NULL # <<<<<<<<<<<<<< + * + * def __dealloc__(memoryview self): +*/ + __pyx_v_self->typeinfo = NULL; + + /* "View.MemoryView":356 + * cdef const __Pyx_TypeInfo *typeinfo + * + * def __cinit__(memoryview self, object obj, int flags, bint dtype_is_object=False): # <<<<<<<<<<<<<< + * self.obj = obj + * self.flags = flags +*/ + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("View.MemoryView.memoryview.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":386 + * self.typeinfo = NULL + * + * def __dealloc__(memoryview self): # <<<<<<<<<<<<<< + * if self.obj is not None: + * PyBuffer_Release(&self.view) +*/ + +/* Python wrapper */ +static void __pyx_memoryview___dealloc__(PyObject *__pyx_v_self); /*proto*/ +static void __pyx_memoryview___dealloc__(PyObject *__pyx_v_self) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__dealloc__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_2__dealloc__(((struct __pyx_memoryview_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); +} + +static void __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_2__dealloc__(struct __pyx_memoryview_obj *__pyx_v_self) { + int __pyx_v_i; + int __pyx_t_1; + Py_ssize_t __pyx_t_2; + Py_ssize_t __pyx_t_3; + int __pyx_t_4; + PyThread_type_lock __pyx_t_5; + PyThread_type_lock __pyx_t_6; + + /* "View.MemoryView":387 + * + * def __dealloc__(memoryview self): + * if self.obj is not None: # <<<<<<<<<<<<<< + * PyBuffer_Release(&self.view) + * elif (<__pyx_buffer *> &self.view).obj == Py_None: +*/ + __pyx_t_1 = (__pyx_v_self->obj != Py_None); + if (__pyx_t_1) { + + /* "View.MemoryView":388 + * def __dealloc__(memoryview self): + * if self.obj is not None: + * PyBuffer_Release(&self.view) # <<<<<<<<<<<<<< + * elif (<__pyx_buffer *> &self.view).obj == Py_None: + * +*/ + PyBuffer_Release((&__pyx_v_self->view)); + + /* "View.MemoryView":387 + * + * def __dealloc__(memoryview self): + * if self.obj is not None: # <<<<<<<<<<<<<< + * PyBuffer_Release(&self.view) + * elif (<__pyx_buffer *> &self.view).obj == Py_None: +*/ + goto __pyx_L3; + } + + /* "View.MemoryView":389 + * if self.obj is not None: + * PyBuffer_Release(&self.view) + * elif (<__pyx_buffer *> &self.view).obj == Py_None: # <<<<<<<<<<<<<< + * + * (<__pyx_buffer *> &self.view).obj = NULL +*/ + __pyx_t_1 = (((Py_buffer *)(&__pyx_v_self->view))->obj == Py_None); + if (__pyx_t_1) { + + /* "View.MemoryView":391 + * elif (<__pyx_buffer *> &self.view).obj == Py_None: + * + * (<__pyx_buffer *> &self.view).obj = NULL # <<<<<<<<<<<<<< + * Py_DECREF(Py_None) + * +*/ + ((Py_buffer *)(&__pyx_v_self->view))->obj = NULL; + + /* "View.MemoryView":392 + * + * (<__pyx_buffer *> &self.view).obj = NULL + * Py_DECREF(Py_None) # <<<<<<<<<<<<<< + * + * cdef int i +*/ + Py_DECREF(Py_None); + + /* "View.MemoryView":389 + * if self.obj is not None: + * PyBuffer_Release(&self.view) + * elif (<__pyx_buffer *> &self.view).obj == Py_None: # <<<<<<<<<<<<<< + * + * (<__pyx_buffer *> &self.view).obj = NULL +*/ + } + __pyx_L3:; + + /* "View.MemoryView":396 + * cdef int i + * global __pyx_memoryview_thread_locks_used + * if self.lock != NULL: # <<<<<<<<<<<<<< + * for i in range(0 if __PYX_GET_CYTHON_COMPILING_IN_CPYTHON_FREETHREADING() else __pyx_memoryview_thread_locks_used): + * if __pyx_memoryview_thread_locks[i] is self.lock: +*/ + __pyx_t_1 = (__pyx_v_self->lock != NULL); + if (__pyx_t_1) { + + /* "View.MemoryView":397 + * global __pyx_memoryview_thread_locks_used + * if self.lock != NULL: + * for i in range(0 if __PYX_GET_CYTHON_COMPILING_IN_CPYTHON_FREETHREADING() else __pyx_memoryview_thread_locks_used): # <<<<<<<<<<<<<< + * if __pyx_memoryview_thread_locks[i] is self.lock: + * __pyx_memoryview_thread_locks_used -= 1 +*/ + __pyx_t_1 = __PYX_GET_CYTHON_COMPILING_IN_CPYTHON_FREETHREADING(); + if (__pyx_t_1) { + __pyx_t_2 = 0; + } else { + __pyx_t_2 = __pyx_memoryview_thread_locks_used; + } + __pyx_t_3 = __pyx_t_2; + for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { + __pyx_v_i = __pyx_t_4; + + /* "View.MemoryView":398 + * if self.lock != NULL: + * for i in range(0 if __PYX_GET_CYTHON_COMPILING_IN_CPYTHON_FREETHREADING() else __pyx_memoryview_thread_locks_used): + * if __pyx_memoryview_thread_locks[i] is self.lock: # <<<<<<<<<<<<<< + * __pyx_memoryview_thread_locks_used -= 1 + * if i != __pyx_memoryview_thread_locks_used: +*/ + __pyx_t_1 = ((__pyx_memoryview_thread_locks[__pyx_v_i]) == __pyx_v_self->lock); + if (__pyx_t_1) { + + /* "View.MemoryView":399 + * for i in range(0 if __PYX_GET_CYTHON_COMPILING_IN_CPYTHON_FREETHREADING() else __pyx_memoryview_thread_locks_used): + * if __pyx_memoryview_thread_locks[i] is self.lock: + * __pyx_memoryview_thread_locks_used -= 1 # <<<<<<<<<<<<<< + * if i != __pyx_memoryview_thread_locks_used: + * __pyx_memoryview_thread_locks[i], __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] = ( +*/ + __pyx_memoryview_thread_locks_used = (__pyx_memoryview_thread_locks_used - 1); + + /* "View.MemoryView":400 + * if __pyx_memoryview_thread_locks[i] is self.lock: + * __pyx_memoryview_thread_locks_used -= 1 + * if i != __pyx_memoryview_thread_locks_used: # <<<<<<<<<<<<<< + * __pyx_memoryview_thread_locks[i], __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] = ( + * __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used], __pyx_memoryview_thread_locks[i]) +*/ + __pyx_t_1 = (__pyx_v_i != __pyx_memoryview_thread_locks_used); + if (__pyx_t_1) { + + /* "View.MemoryView":402 + * if i != __pyx_memoryview_thread_locks_used: + * __pyx_memoryview_thread_locks[i], __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] = ( + * __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used], __pyx_memoryview_thread_locks[i]) # <<<<<<<<<<<<<< + * break + * else: +*/ + __pyx_t_5 = (__pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used]); + __pyx_t_6 = (__pyx_memoryview_thread_locks[__pyx_v_i]); + + /* "View.MemoryView":401 + * __pyx_memoryview_thread_locks_used -= 1 + * if i != __pyx_memoryview_thread_locks_used: + * __pyx_memoryview_thread_locks[i], __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] = ( # <<<<<<<<<<<<<< + * __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used], __pyx_memoryview_thread_locks[i]) + * break +*/ + (__pyx_memoryview_thread_locks[__pyx_v_i]) = __pyx_t_5; + (__pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used]) = __pyx_t_6; + + /* "View.MemoryView":400 + * if __pyx_memoryview_thread_locks[i] is self.lock: + * __pyx_memoryview_thread_locks_used -= 1 + * if i != __pyx_memoryview_thread_locks_used: # <<<<<<<<<<<<<< + * __pyx_memoryview_thread_locks[i], __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] = ( + * __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used], __pyx_memoryview_thread_locks[i]) +*/ + } + + /* "View.MemoryView":403 + * __pyx_memoryview_thread_locks[i], __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] = ( + * __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used], __pyx_memoryview_thread_locks[i]) + * break # <<<<<<<<<<<<<< + * else: + * PyThread_free_lock(self.lock) +*/ + goto __pyx_L6_break; + + /* "View.MemoryView":398 + * if self.lock != NULL: + * for i in range(0 if __PYX_GET_CYTHON_COMPILING_IN_CPYTHON_FREETHREADING() else __pyx_memoryview_thread_locks_used): + * if __pyx_memoryview_thread_locks[i] is self.lock: # <<<<<<<<<<<<<< + * __pyx_memoryview_thread_locks_used -= 1 + * if i != __pyx_memoryview_thread_locks_used: +*/ + } + } + /*else*/ { + + /* "View.MemoryView":405 + * break + * else: + * PyThread_free_lock(self.lock) # <<<<<<<<<<<<<< + * + * cdef char *get_item_pointer(memoryview self, object index) except NULL: +*/ + PyThread_free_lock(__pyx_v_self->lock); + } + __pyx_L6_break:; + + /* "View.MemoryView":396 + * cdef int i + * global __pyx_memoryview_thread_locks_used + * if self.lock != NULL: # <<<<<<<<<<<<<< + * for i in range(0 if __PYX_GET_CYTHON_COMPILING_IN_CPYTHON_FREETHREADING() else __pyx_memoryview_thread_locks_used): + * if __pyx_memoryview_thread_locks[i] is self.lock: +*/ + } + + /* "View.MemoryView":386 + * self.typeinfo = NULL + * + * def __dealloc__(memoryview self): # <<<<<<<<<<<<<< + * if self.obj is not None: + * PyBuffer_Release(&self.view) +*/ + + /* function exit code */ +} + +/* "View.MemoryView":407 + * PyThread_free_lock(self.lock) + * + * cdef char *get_item_pointer(memoryview self, object index) except NULL: # <<<<<<<<<<<<<< + * cdef Py_ssize_t dim + * cdef char *itemp = self.view.buf +*/ + +static char *__pyx_memoryview_get_item_pointer(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_index) { + Py_ssize_t __pyx_v_dim; + char *__pyx_v_itemp; + PyObject *__pyx_v_idx = NULL; + char *__pyx_r; + __Pyx_RefNannyDeclarations + Py_ssize_t __pyx_t_1; + PyObject *__pyx_t_2 = NULL; + Py_ssize_t __pyx_t_3; + PyObject *(*__pyx_t_4)(PyObject *); + PyObject *__pyx_t_5 = NULL; + Py_ssize_t __pyx_t_6; + char *__pyx_t_7; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("get_item_pointer", 0); + + /* "View.MemoryView":409 + * cdef char *get_item_pointer(memoryview self, object index) except NULL: + * cdef Py_ssize_t dim + * cdef char *itemp = self.view.buf # <<<<<<<<<<<<<< + * + * for dim, idx in enumerate(index): +*/ + __pyx_v_itemp = ((char *)__pyx_v_self->view.buf); + + /* "View.MemoryView":411 + * cdef char *itemp = self.view.buf + * + * for dim, idx in enumerate(index): # <<<<<<<<<<<<<< + * itemp = pybuffer_index(&self.view, itemp, idx, dim) + * +*/ + __pyx_t_1 = 0; + if (likely(PyList_CheckExact(__pyx_v_index)) || PyTuple_CheckExact(__pyx_v_index)) { + __pyx_t_2 = __pyx_v_index; __Pyx_INCREF(__pyx_t_2); + __pyx_t_3 = 0; + __pyx_t_4 = NULL; + } else { + __pyx_t_3 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_v_index); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 411, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_2); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 411, __pyx_L1_error) + } + for (;;) { + if (likely(!__pyx_t_4)) { + if (likely(PyList_CheckExact(__pyx_t_2))) { + { + Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_2); + #if !CYTHON_ASSUME_SAFE_SIZE + if (unlikely((__pyx_temp < 0))) __PYX_ERR(1, 411, __pyx_L1_error) + #endif + if (__pyx_t_3 >= __pyx_temp) break; + } + __pyx_t_5 = __Pyx_PyList_GetItemRefFast(__pyx_t_2, __pyx_t_3, __Pyx_ReferenceSharing_OwnStrongReference); + ++__pyx_t_3; + } else { + { + Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_2); + #if !CYTHON_ASSUME_SAFE_SIZE + if (unlikely((__pyx_temp < 0))) __PYX_ERR(1, 411, __pyx_L1_error) + #endif + if (__pyx_t_3 >= __pyx_temp) break; + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_5 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_3)); + #else + __pyx_t_5 = __Pyx_PySequence_ITEM(__pyx_t_2, __pyx_t_3); + #endif + ++__pyx_t_3; + } + if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 411, __pyx_L1_error) + } else { + __pyx_t_5 = __pyx_t_4(__pyx_t_2); + if (unlikely(!__pyx_t_5)) { + PyObject* exc_type = PyErr_Occurred(); + if (exc_type) { + if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(1, 411, __pyx_L1_error) + PyErr_Clear(); + } + break; + } + } + __Pyx_GOTREF(__pyx_t_5); + __Pyx_XDECREF_SET(__pyx_v_idx, __pyx_t_5); + __pyx_t_5 = 0; + __pyx_v_dim = __pyx_t_1; + __pyx_t_1 = (__pyx_t_1 + 1); + + /* "View.MemoryView":412 + * + * for dim, idx in enumerate(index): + * itemp = pybuffer_index(&self.view, itemp, idx, dim) # <<<<<<<<<<<<<< + * + * return itemp +*/ + __pyx_t_6 = __Pyx_PyIndex_AsSsize_t(__pyx_v_idx); if (unlikely((__pyx_t_6 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(1, 412, __pyx_L1_error) + __pyx_t_7 = __pyx_pybuffer_index((&__pyx_v_self->view), __pyx_v_itemp, __pyx_t_6, __pyx_v_dim); if (unlikely(__pyx_t_7 == ((void *)NULL))) __PYX_ERR(1, 412, __pyx_L1_error) + __pyx_v_itemp = __pyx_t_7; + + /* "View.MemoryView":411 + * cdef char *itemp = self.view.buf + * + * for dim, idx in enumerate(index): # <<<<<<<<<<<<<< + * itemp = pybuffer_index(&self.view, itemp, idx, dim) + * +*/ + } + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "View.MemoryView":414 + * itemp = pybuffer_index(&self.view, itemp, idx, dim) + * + * return itemp # <<<<<<<<<<<<<< + * + * +*/ + __pyx_r = __pyx_v_itemp; + goto __pyx_L0; + + /* "View.MemoryView":407 + * PyThread_free_lock(self.lock) + * + * cdef char *get_item_pointer(memoryview self, object index) except NULL: # <<<<<<<<<<<<<< + * cdef Py_ssize_t dim + * cdef char *itemp = self.view.buf +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("View.MemoryView.memoryview.get_item_pointer", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_idx); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":417 + * + * + * def __getitem__(memoryview self, object index): # <<<<<<<<<<<<<< + * if index is Ellipsis: + * return self +*/ + +/* Python wrapper */ +static PyObject *__pyx_memoryview___getitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_index); /*proto*/ +static PyObject *__pyx_memoryview___getitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_index) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__getitem__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_r = __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_4__getitem__(((struct __pyx_memoryview_obj *)__pyx_v_self), ((PyObject *)__pyx_v_index)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_4__getitem__(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_index) { + PyObject *__pyx_v_have_slices = NULL; + PyObject *__pyx_v_indices = NULL; + char *__pyx_v_itemp; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + char *__pyx_t_5; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__getitem__", 0); + + /* "View.MemoryView":418 + * + * def __getitem__(memoryview self, object index): + * if index is Ellipsis: # <<<<<<<<<<<<<< + * return self + * +*/ + __pyx_t_1 = (__pyx_v_index == __pyx_builtin_Ellipsis); + if (__pyx_t_1) { + + /* "View.MemoryView":419 + * def __getitem__(memoryview self, object index): + * if index is Ellipsis: + * return self # <<<<<<<<<<<<<< + * + * have_slices, indices = _unellipsify(index, self.view.ndim) +*/ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF((PyObject *)__pyx_v_self); + __pyx_r = ((PyObject *)__pyx_v_self); + goto __pyx_L0; + + /* "View.MemoryView":418 + * + * def __getitem__(memoryview self, object index): + * if index is Ellipsis: # <<<<<<<<<<<<<< + * return self + * +*/ + } + + /* "View.MemoryView":421 + * return self + * + * have_slices, indices = _unellipsify(index, self.view.ndim) # <<<<<<<<<<<<<< + * + * cdef char *itemp +*/ + __pyx_t_2 = _unellipsify(__pyx_v_index, __pyx_v_self->view.ndim); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 421, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (likely(__pyx_t_2 != Py_None)) { + PyObject* sequence = __pyx_t_2; + Py_ssize_t size = __Pyx_PyTuple_GET_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(1, 421, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); + __Pyx_INCREF(__pyx_t_3); + __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); + __Pyx_INCREF(__pyx_t_4); + #else + __pyx_t_3 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 421, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 421, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + #endif + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + } else { + __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(1, 421, __pyx_L1_error) + } + __pyx_v_have_slices = __pyx_t_3; + __pyx_t_3 = 0; + __pyx_v_indices = __pyx_t_4; + __pyx_t_4 = 0; + + /* "View.MemoryView":424 + * + * cdef char *itemp + * if have_slices: # <<<<<<<<<<<<<< + * return memview_slice(self, indices) + * else: +*/ + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_have_slices); if (unlikely((__pyx_t_1 < 0))) __PYX_ERR(1, 424, __pyx_L1_error) + if (__pyx_t_1) { + + /* "View.MemoryView":425 + * cdef char *itemp + * if have_slices: + * return memview_slice(self, indices) # <<<<<<<<<<<<<< + * else: + * itemp = self.get_item_pointer(indices) +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_2 = ((PyObject *)__pyx_memview_slice(__pyx_v_self, __pyx_v_indices)); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 425, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + goto __pyx_L0; + + /* "View.MemoryView":424 + * + * cdef char *itemp + * if have_slices: # <<<<<<<<<<<<<< + * return memview_slice(self, indices) + * else: +*/ + } + + /* "View.MemoryView":427 + * return memview_slice(self, indices) + * else: + * itemp = self.get_item_pointer(indices) # <<<<<<<<<<<<<< + * return self.convert_item_to_object(itemp) + * +*/ + /*else*/ { + __pyx_t_5 = ((struct __pyx_vtabstruct_memoryview *)__pyx_v_self->__pyx_vtab)->get_item_pointer(__pyx_v_self, __pyx_v_indices); if (unlikely(__pyx_t_5 == ((void *)NULL))) __PYX_ERR(1, 427, __pyx_L1_error) + __pyx_v_itemp = __pyx_t_5; + + /* "View.MemoryView":428 + * else: + * itemp = self.get_item_pointer(indices) + * return self.convert_item_to_object(itemp) # <<<<<<<<<<<<<< + * + * def __setitem__(memoryview self, object index, object value): +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_2 = ((struct __pyx_vtabstruct_memoryview *)__pyx_v_self->__pyx_vtab)->convert_item_to_object(__pyx_v_self, __pyx_v_itemp); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 428, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + goto __pyx_L0; + } + + /* "View.MemoryView":417 + * + * + * def __getitem__(memoryview self, object index): # <<<<<<<<<<<<<< + * if index is Ellipsis: + * return self +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_AddTraceback("View.MemoryView.memoryview.__getitem__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_have_slices); + __Pyx_XDECREF(__pyx_v_indices); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":430 + * return self.convert_item_to_object(itemp) + * + * def __setitem__(memoryview self, object index, object value): # <<<<<<<<<<<<<< + * if self.view.readonly: + * raise TypeError, "Cannot assign to read-only memoryview" +*/ + +/* Python wrapper */ +static int __pyx_memoryview___setitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_index, PyObject *__pyx_v_value); /*proto*/ +static int __pyx_memoryview___setitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_index, PyObject *__pyx_v_value) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__setitem__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_r = __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_6__setitem__(((struct __pyx_memoryview_obj *)__pyx_v_self), ((PyObject *)__pyx_v_index), ((PyObject *)__pyx_v_value)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_6__setitem__(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_index, PyObject *__pyx_v_value) { + PyObject *__pyx_v_have_slices = NULL; + PyObject *__pyx_v_obj = NULL; + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_t_4; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__setitem__", 0); + __Pyx_INCREF(__pyx_v_index); + + /* "View.MemoryView":431 + * + * def __setitem__(memoryview self, object index, object value): + * if self.view.readonly: # <<<<<<<<<<<<<< + * raise TypeError, "Cannot assign to read-only memoryview" + * +*/ + if (unlikely(__pyx_v_self->view.readonly)) { + + /* "View.MemoryView":432 + * def __setitem__(memoryview self, object index, object value): + * if self.view.readonly: + * raise TypeError, "Cannot assign to read-only memoryview" # <<<<<<<<<<<<<< + * + * have_slices, index = _unellipsify(index, self.view.ndim) +*/ + __Pyx_Raise(((PyObject *)(((PyTypeObject*)PyExc_TypeError))), __pyx_mstate_global->__pyx_kp_u_Cannot_assign_to_read_only_memor, 0, 0); + __PYX_ERR(1, 432, __pyx_L1_error) + + /* "View.MemoryView":431 + * + * def __setitem__(memoryview self, object index, object value): + * if self.view.readonly: # <<<<<<<<<<<<<< + * raise TypeError, "Cannot assign to read-only memoryview" + * +*/ + } + + /* "View.MemoryView":434 + * raise TypeError, "Cannot assign to read-only memoryview" + * + * have_slices, index = _unellipsify(index, self.view.ndim) # <<<<<<<<<<<<<< + * + * if have_slices: +*/ + __pyx_t_1 = _unellipsify(__pyx_v_index, __pyx_v_self->view.ndim); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 434, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (likely(__pyx_t_1 != Py_None)) { + PyObject* sequence = __pyx_t_1; + Py_ssize_t size = __Pyx_PyTuple_GET_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(1, 434, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0); + __Pyx_INCREF(__pyx_t_2); + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); + __Pyx_INCREF(__pyx_t_3); + #else + __pyx_t_2 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 434, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 434, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + #endif + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + } else { + __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(1, 434, __pyx_L1_error) + } + __pyx_v_have_slices = __pyx_t_2; + __pyx_t_2 = 0; + __Pyx_DECREF_SET(__pyx_v_index, __pyx_t_3); + __pyx_t_3 = 0; + + /* "View.MemoryView":436 + * have_slices, index = _unellipsify(index, self.view.ndim) + * + * if have_slices: # <<<<<<<<<<<<<< + * obj = self.is_slice(value) + * if obj is not None: +*/ + __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_v_have_slices); if (unlikely((__pyx_t_4 < 0))) __PYX_ERR(1, 436, __pyx_L1_error) + if (__pyx_t_4) { + + /* "View.MemoryView":437 + * + * if have_slices: + * obj = self.is_slice(value) # <<<<<<<<<<<<<< + * if obj is not None: + * self.setitem_slice_assignment(self[index], obj) +*/ + __pyx_t_1 = ((struct __pyx_vtabstruct_memoryview *)__pyx_v_self->__pyx_vtab)->is_slice(__pyx_v_self, __pyx_v_value); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 437, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_obj = __pyx_t_1; + __pyx_t_1 = 0; + + /* "View.MemoryView":438 + * if have_slices: + * obj = self.is_slice(value) + * if obj is not None: # <<<<<<<<<<<<<< + * self.setitem_slice_assignment(self[index], obj) + * else: +*/ + __pyx_t_4 = (__pyx_v_obj != Py_None); + if (__pyx_t_4) { + + /* "View.MemoryView":439 + * obj = self.is_slice(value) + * if obj is not None: + * self.setitem_slice_assignment(self[index], obj) # <<<<<<<<<<<<<< + * else: + * self.setitem_slice_assign_scalar(self[index], value) +*/ + __pyx_t_1 = __Pyx_PyObject_GetItem(((PyObject *)__pyx_v_self), __pyx_v_index); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 439, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = ((struct __pyx_vtabstruct_memoryview *)__pyx_v_self->__pyx_vtab)->setitem_slice_assignment(__pyx_v_self, __pyx_t_1, __pyx_v_obj); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 439, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + /* "View.MemoryView":438 + * if have_slices: + * obj = self.is_slice(value) + * if obj is not None: # <<<<<<<<<<<<<< + * self.setitem_slice_assignment(self[index], obj) + * else: +*/ + goto __pyx_L5; + } + + /* "View.MemoryView":441 + * self.setitem_slice_assignment(self[index], obj) + * else: + * self.setitem_slice_assign_scalar(self[index], value) # <<<<<<<<<<<<<< + * else: + * self.setitem_indexed(index, value) +*/ + /*else*/ { + __pyx_t_3 = __Pyx_PyObject_GetItem(((PyObject *)__pyx_v_self), __pyx_v_index); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 441, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_mstate_global->__pyx_memoryview_type))))) __PYX_ERR(1, 441, __pyx_L1_error) + __pyx_t_1 = ((struct __pyx_vtabstruct_memoryview *)__pyx_v_self->__pyx_vtab)->setitem_slice_assign_scalar(__pyx_v_self, ((struct __pyx_memoryview_obj *)__pyx_t_3), __pyx_v_value); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 441, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + } + __pyx_L5:; + + /* "View.MemoryView":436 + * have_slices, index = _unellipsify(index, self.view.ndim) + * + * if have_slices: # <<<<<<<<<<<<<< + * obj = self.is_slice(value) + * if obj is not None: +*/ + goto __pyx_L4; + } + + /* "View.MemoryView":443 + * self.setitem_slice_assign_scalar(self[index], value) + * else: + * self.setitem_indexed(index, value) # <<<<<<<<<<<<<< + * + * cdef is_slice(self, obj): +*/ + /*else*/ { + __pyx_t_1 = ((struct __pyx_vtabstruct_memoryview *)__pyx_v_self->__pyx_vtab)->setitem_indexed(__pyx_v_self, __pyx_v_index, __pyx_v_value); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 443, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + } + __pyx_L4:; + + /* "View.MemoryView":430 + * return self.convert_item_to_object(itemp) + * + * def __setitem__(memoryview self, object index, object value): # <<<<<<<<<<<<<< + * if self.view.readonly: + * raise TypeError, "Cannot assign to read-only memoryview" +*/ + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_AddTraceback("View.MemoryView.memoryview.__setitem__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_have_slices); + __Pyx_XDECREF(__pyx_v_obj); + __Pyx_XDECREF(__pyx_v_index); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":445 + * self.setitem_indexed(index, value) + * + * cdef is_slice(self, obj): # <<<<<<<<<<<<<< + * if not isinstance(obj, memoryview): + * try: +*/ + +static PyObject *__pyx_memoryview_is_slice(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_obj) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_t_2; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + size_t __pyx_t_10; + int __pyx_t_11; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("is_slice", 0); + __Pyx_INCREF(__pyx_v_obj); + + /* "View.MemoryView":446 + * + * cdef is_slice(self, obj): + * if not isinstance(obj, memoryview): # <<<<<<<<<<<<<< + * try: + * obj = memoryview(obj, self.flags & ~PyBUF_WRITABLE | PyBUF_ANY_CONTIGUOUS, +*/ + __pyx_t_1 = __Pyx_TypeCheck(__pyx_v_obj, __pyx_mstate_global->__pyx_memoryview_type); + __pyx_t_2 = (!__pyx_t_1); + if (__pyx_t_2) { + + /* "View.MemoryView":447 + * cdef is_slice(self, obj): + * if not isinstance(obj, memoryview): + * try: # <<<<<<<<<<<<<< + * obj = memoryview(obj, self.flags & ~PyBUF_WRITABLE | PyBUF_ANY_CONTIGUOUS, + * self.dtype_is_object) +*/ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_3, &__pyx_t_4, &__pyx_t_5); + __Pyx_XGOTREF(__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_4); + __Pyx_XGOTREF(__pyx_t_5); + /*try:*/ { + + /* "View.MemoryView":448 + * if not isinstance(obj, memoryview): + * try: + * obj = memoryview(obj, self.flags & ~PyBUF_WRITABLE | PyBUF_ANY_CONTIGUOUS, # <<<<<<<<<<<<<< + * self.dtype_is_object) + * except TypeError: +*/ + __pyx_t_7 = NULL; + __pyx_t_8 = __Pyx_PyLong_From_int(((__pyx_v_self->flags & (~PyBUF_WRITABLE)) | PyBUF_ANY_CONTIGUOUS)); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 448, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_8); + + /* "View.MemoryView":449 + * try: + * obj = memoryview(obj, self.flags & ~PyBUF_WRITABLE | PyBUF_ANY_CONTIGUOUS, + * self.dtype_is_object) # <<<<<<<<<<<<<< + * except TypeError: + * return None +*/ + __pyx_t_9 = __Pyx_PyBool_FromLong(__pyx_v_self->dtype_is_object); if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 449, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_9); + __pyx_t_10 = 1; + { + PyObject *__pyx_callargs[4] = {__pyx_t_7, __pyx_v_obj, __pyx_t_8, __pyx_t_9}; + __pyx_t_6 = __Pyx_PyObject_FastCall((PyObject*)__pyx_mstate_global->__pyx_memoryview_type, __pyx_callargs+__pyx_t_10, (4-__pyx_t_10) | (__pyx_t_10*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 448, __pyx_L4_error) + __Pyx_GOTREF((PyObject *)__pyx_t_6); + } + __Pyx_DECREF_SET(__pyx_v_obj, ((PyObject *)__pyx_t_6)); + __pyx_t_6 = 0; + + /* "View.MemoryView":447 + * cdef is_slice(self, obj): + * if not isinstance(obj, memoryview): + * try: # <<<<<<<<<<<<<< + * obj = memoryview(obj, self.flags & ~PyBUF_WRITABLE | PyBUF_ANY_CONTIGUOUS, + * self.dtype_is_object) +*/ + } + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + goto __pyx_L9_try_end; + __pyx_L4_error:; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + + /* "View.MemoryView":450 + * obj = memoryview(obj, self.flags & ~PyBUF_WRITABLE | PyBUF_ANY_CONTIGUOUS, + * self.dtype_is_object) + * except TypeError: # <<<<<<<<<<<<<< + * return None + * +*/ + __pyx_t_11 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(((PyTypeObject*)PyExc_TypeError)))); + if (__pyx_t_11) { + __Pyx_ErrRestore(0,0,0); + + /* "View.MemoryView":451 + * self.dtype_is_object) + * except TypeError: + * return None # <<<<<<<<<<<<<< + * + * return obj +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L7_except_return; + } + goto __pyx_L6_except_error; + + /* "View.MemoryView":447 + * cdef is_slice(self, obj): + * if not isinstance(obj, memoryview): + * try: # <<<<<<<<<<<<<< + * obj = memoryview(obj, self.flags & ~PyBUF_WRITABLE | PyBUF_ANY_CONTIGUOUS, + * self.dtype_is_object) +*/ + __pyx_L6_except_error:; + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_XGIVEREF(__pyx_t_5); + __Pyx_ExceptionReset(__pyx_t_3, __pyx_t_4, __pyx_t_5); + goto __pyx_L1_error; + __pyx_L7_except_return:; + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_XGIVEREF(__pyx_t_5); + __Pyx_ExceptionReset(__pyx_t_3, __pyx_t_4, __pyx_t_5); + goto __pyx_L0; + __pyx_L9_try_end:; + } + + /* "View.MemoryView":446 + * + * cdef is_slice(self, obj): + * if not isinstance(obj, memoryview): # <<<<<<<<<<<<<< + * try: + * obj = memoryview(obj, self.flags & ~PyBUF_WRITABLE | PyBUF_ANY_CONTIGUOUS, +*/ + } + + /* "View.MemoryView":453 + * return None + * + * return obj # <<<<<<<<<<<<<< + * + * cdef setitem_slice_assignment(self, dst, src): +*/ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_obj); + __pyx_r = __pyx_v_obj; + goto __pyx_L0; + + /* "View.MemoryView":445 + * self.setitem_indexed(index, value) + * + * cdef is_slice(self, obj): # <<<<<<<<<<<<<< + * if not isinstance(obj, memoryview): + * try: +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_AddTraceback("View.MemoryView.memoryview.is_slice", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_obj); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":455 + * return obj + * + * cdef setitem_slice_assignment(self, dst, src): # <<<<<<<<<<<<<< + * cdef __Pyx_memviewslice dst_slice + * cdef __Pyx_memviewslice src_slice +*/ + +static PyObject *__pyx_memoryview_setitem_slice_assignment(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_dst, PyObject *__pyx_v_src) { + __Pyx_memviewslice __pyx_v_dst_slice; + __Pyx_memviewslice __pyx_v_src_slice; + __Pyx_memviewslice __pyx_v_msrc; + __Pyx_memviewslice __pyx_v_mdst; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_memviewslice *__pyx_t_1; + PyObject *__pyx_t_2 = NULL; + int __pyx_t_3; + int __pyx_t_4; + int __pyx_t_5; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("setitem_slice_assignment", 0); + + /* "View.MemoryView":458 + * cdef __Pyx_memviewslice dst_slice + * cdef __Pyx_memviewslice src_slice + * cdef __Pyx_memviewslice msrc = get_slice_from_memview(src, &src_slice)[0] # <<<<<<<<<<<<<< + * cdef __Pyx_memviewslice mdst = get_slice_from_memview(dst, &dst_slice)[0] + * +*/ + if (!(likely(((__pyx_v_src) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_src, __pyx_mstate_global->__pyx_memoryview_type))))) __PYX_ERR(1, 458, __pyx_L1_error) + __pyx_t_1 = __pyx_memoryview_get_slice_from_memoryview(((struct __pyx_memoryview_obj *)__pyx_v_src), (&__pyx_v_src_slice)); if (unlikely(__pyx_t_1 == ((void *)NULL))) __PYX_ERR(1, 458, __pyx_L1_error) + __pyx_v_msrc = (__pyx_t_1[0]); + + /* "View.MemoryView":459 + * cdef __Pyx_memviewslice src_slice + * cdef __Pyx_memviewslice msrc = get_slice_from_memview(src, &src_slice)[0] + * cdef __Pyx_memviewslice mdst = get_slice_from_memview(dst, &dst_slice)[0] # <<<<<<<<<<<<<< + * + * memoryview_copy_contents(msrc, mdst, src.ndim, dst.ndim, self.dtype_is_object) +*/ + if (!(likely(((__pyx_v_dst) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_dst, __pyx_mstate_global->__pyx_memoryview_type))))) __PYX_ERR(1, 459, __pyx_L1_error) + __pyx_t_1 = __pyx_memoryview_get_slice_from_memoryview(((struct __pyx_memoryview_obj *)__pyx_v_dst), (&__pyx_v_dst_slice)); if (unlikely(__pyx_t_1 == ((void *)NULL))) __PYX_ERR(1, 459, __pyx_L1_error) + __pyx_v_mdst = (__pyx_t_1[0]); + + /* "View.MemoryView":461 + * cdef __Pyx_memviewslice mdst = get_slice_from_memview(dst, &dst_slice)[0] + * + * memoryview_copy_contents(msrc, mdst, src.ndim, dst.ndim, self.dtype_is_object) # <<<<<<<<<<<<<< + * + * cdef setitem_slice_assign_scalar(self, memoryview dst, value): +*/ + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_src, __pyx_mstate_global->__pyx_n_u_ndim); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 461, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = __Pyx_PyLong_As_int(__pyx_t_2); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 461, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_dst, __pyx_mstate_global->__pyx_n_u_ndim); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 461, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = __Pyx_PyLong_As_int(__pyx_t_2); if (unlikely((__pyx_t_4 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 461, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_5 = __pyx_memoryview_copy_contents(__pyx_v_msrc, __pyx_v_mdst, __pyx_t_3, __pyx_t_4, __pyx_v_self->dtype_is_object); if (unlikely(__pyx_t_5 == ((int)-1))) __PYX_ERR(1, 461, __pyx_L1_error) + + /* "View.MemoryView":455 + * return obj + * + * cdef setitem_slice_assignment(self, dst, src): # <<<<<<<<<<<<<< + * cdef __Pyx_memviewslice dst_slice + * cdef __Pyx_memviewslice src_slice +*/ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("View.MemoryView.memoryview.setitem_slice_assignment", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":463 + * memoryview_copy_contents(msrc, mdst, src.ndim, dst.ndim, self.dtype_is_object) + * + * cdef setitem_slice_assign_scalar(self, memoryview dst, value): # <<<<<<<<<<<<<< + * cdef int array[128] + * cdef void *tmp = NULL +*/ + +static PyObject *__pyx_memoryview_setitem_slice_assign_scalar(struct __pyx_memoryview_obj *__pyx_v_self, struct __pyx_memoryview_obj *__pyx_v_dst, PyObject *__pyx_v_value) { + int __pyx_v_array[128]; + void *__pyx_v_tmp; + void *__pyx_v_item; + __Pyx_memviewslice *__pyx_v_dst_slice; + __Pyx_memviewslice __pyx_v_tmp_slice; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_memviewslice *__pyx_t_1; + int __pyx_t_2; + PyObject *__pyx_t_3 = NULL; + int __pyx_t_4; + int __pyx_t_5; + char const *__pyx_t_6; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + PyObject *__pyx_t_10 = NULL; + PyObject *__pyx_t_11 = NULL; + PyObject *__pyx_t_12 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("setitem_slice_assign_scalar", 0); + + /* "View.MemoryView":465 + * cdef setitem_slice_assign_scalar(self, memoryview dst, value): + * cdef int array[128] + * cdef void *tmp = NULL # <<<<<<<<<<<<<< + * cdef void *item + * +*/ + __pyx_v_tmp = NULL; + + /* "View.MemoryView":470 + * cdef __Pyx_memviewslice *dst_slice + * cdef __Pyx_memviewslice tmp_slice + * dst_slice = get_slice_from_memview(dst, &tmp_slice) # <<<<<<<<<<<<<< + * + * if self.view.itemsize > sizeof(array): +*/ + __pyx_t_1 = __pyx_memoryview_get_slice_from_memoryview(__pyx_v_dst, (&__pyx_v_tmp_slice)); if (unlikely(__pyx_t_1 == ((void *)NULL))) __PYX_ERR(1, 470, __pyx_L1_error) + __pyx_v_dst_slice = __pyx_t_1; + + /* "View.MemoryView":472 + * dst_slice = get_slice_from_memview(dst, &tmp_slice) + * + * if self.view.itemsize > sizeof(array): # <<<<<<<<<<<<<< + * tmp = PyMem_Malloc(self.view.itemsize) + * if tmp == NULL: +*/ + __pyx_t_2 = (((size_t)__pyx_v_self->view.itemsize) > (sizeof(__pyx_v_array))); + if (__pyx_t_2) { + + /* "View.MemoryView":473 + * + * if self.view.itemsize > sizeof(array): + * tmp = PyMem_Malloc(self.view.itemsize) # <<<<<<<<<<<<<< + * if tmp == NULL: + * raise MemoryError +*/ + __pyx_v_tmp = PyMem_Malloc(__pyx_v_self->view.itemsize); + + /* "View.MemoryView":474 + * if self.view.itemsize > sizeof(array): + * tmp = PyMem_Malloc(self.view.itemsize) + * if tmp == NULL: # <<<<<<<<<<<<<< + * raise MemoryError + * item = tmp +*/ + __pyx_t_2 = (__pyx_v_tmp == NULL); + if (unlikely(__pyx_t_2)) { + + /* "View.MemoryView":475 + * tmp = PyMem_Malloc(self.view.itemsize) + * if tmp == NULL: + * raise MemoryError # <<<<<<<<<<<<<< + * item = tmp + * else: +*/ + PyErr_NoMemory(); __PYX_ERR(1, 475, __pyx_L1_error) + + /* "View.MemoryView":474 + * if self.view.itemsize > sizeof(array): + * tmp = PyMem_Malloc(self.view.itemsize) + * if tmp == NULL: # <<<<<<<<<<<<<< + * raise MemoryError + * item = tmp +*/ + } + + /* "View.MemoryView":476 + * if tmp == NULL: + * raise MemoryError + * item = tmp # <<<<<<<<<<<<<< + * else: + * item = array +*/ + __pyx_v_item = __pyx_v_tmp; + + /* "View.MemoryView":472 + * dst_slice = get_slice_from_memview(dst, &tmp_slice) + * + * if self.view.itemsize > sizeof(array): # <<<<<<<<<<<<<< + * tmp = PyMem_Malloc(self.view.itemsize) + * if tmp == NULL: +*/ + goto __pyx_L3; + } + + /* "View.MemoryView":478 + * item = tmp + * else: + * item = array # <<<<<<<<<<<<<< + * + * try: +*/ + /*else*/ { + __pyx_v_item = ((void *)__pyx_v_array); + } + __pyx_L3:; + + /* "View.MemoryView":480 + * item = array + * + * try: # <<<<<<<<<<<<<< + * if self.dtype_is_object: + * ( item)[0] = value +*/ + /*try:*/ { + + /* "View.MemoryView":481 + * + * try: + * if self.dtype_is_object: # <<<<<<<<<<<<<< + * ( item)[0] = value + * else: +*/ + if (__pyx_v_self->dtype_is_object) { + + /* "View.MemoryView":482 + * try: + * if self.dtype_is_object: + * ( item)[0] = value # <<<<<<<<<<<<<< + * else: + * self.assign_item_from_object( item, value) +*/ + (((PyObject **)__pyx_v_item)[0]) = ((PyObject *)__pyx_v_value); + + /* "View.MemoryView":481 + * + * try: + * if self.dtype_is_object: # <<<<<<<<<<<<<< + * ( item)[0] = value + * else: +*/ + goto __pyx_L8; + } + + /* "View.MemoryView":484 + * ( item)[0] = value + * else: + * self.assign_item_from_object( item, value) # <<<<<<<<<<<<<< + * + * +*/ + /*else*/ { + __pyx_t_3 = ((struct __pyx_vtabstruct_memoryview *)__pyx_v_self->__pyx_vtab)->assign_item_from_object(__pyx_v_self, ((char *)__pyx_v_item), __pyx_v_value); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 484, __pyx_L6_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } + __pyx_L8:; + + /* "View.MemoryView":488 + * + * + * if self.view.suboffsets != NULL: # <<<<<<<<<<<<<< + * assert_direct_dimensions(self.view.suboffsets, self.view.ndim) + * slice_assign_scalar(dst_slice, dst.view.ndim, self.view.itemsize, +*/ + __pyx_t_2 = (__pyx_v_self->view.suboffsets != NULL); + if (__pyx_t_2) { + + /* "View.MemoryView":489 + * + * if self.view.suboffsets != NULL: + * assert_direct_dimensions(self.view.suboffsets, self.view.ndim) # <<<<<<<<<<<<<< + * slice_assign_scalar(dst_slice, dst.view.ndim, self.view.itemsize, + * item, self.dtype_is_object) +*/ + __pyx_t_4 = assert_direct_dimensions(__pyx_v_self->view.suboffsets, __pyx_v_self->view.ndim); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 489, __pyx_L6_error) + + /* "View.MemoryView":488 + * + * + * if self.view.suboffsets != NULL: # <<<<<<<<<<<<<< + * assert_direct_dimensions(self.view.suboffsets, self.view.ndim) + * slice_assign_scalar(dst_slice, dst.view.ndim, self.view.itemsize, +*/ + } + + /* "View.MemoryView":490 + * if self.view.suboffsets != NULL: + * assert_direct_dimensions(self.view.suboffsets, self.view.ndim) + * slice_assign_scalar(dst_slice, dst.view.ndim, self.view.itemsize, # <<<<<<<<<<<<<< + * item, self.dtype_is_object) + * finally: +*/ + __pyx_memoryview_slice_assign_scalar(__pyx_v_dst_slice, __pyx_v_dst->view.ndim, __pyx_v_self->view.itemsize, __pyx_v_item, __pyx_v_self->dtype_is_object); + } + + /* "View.MemoryView":493 + * item, self.dtype_is_object) + * finally: + * PyMem_Free(tmp) # <<<<<<<<<<<<<< + * + * cdef setitem_indexed(self, index, value): +*/ + /*finally:*/ { + /*normal exit:*/{ + PyMem_Free(__pyx_v_tmp); + goto __pyx_L7; + } + __pyx_L6_error:; + /*exception exit:*/{ + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __pyx_t_7 = 0; __pyx_t_8 = 0; __pyx_t_9 = 0; __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_ExceptionSwap(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12); + if ( unlikely(__Pyx_GetException(&__pyx_t_7, &__pyx_t_8, &__pyx_t_9) < 0)) __Pyx_ErrFetch(&__pyx_t_7, &__pyx_t_8, &__pyx_t_9); + __Pyx_XGOTREF(__pyx_t_7); + __Pyx_XGOTREF(__pyx_t_8); + __Pyx_XGOTREF(__pyx_t_9); + __Pyx_XGOTREF(__pyx_t_10); + __Pyx_XGOTREF(__pyx_t_11); + __Pyx_XGOTREF(__pyx_t_12); + __pyx_t_4 = __pyx_lineno; __pyx_t_5 = __pyx_clineno; __pyx_t_6 = __pyx_filename; + { + PyMem_Free(__pyx_v_tmp); + } + __Pyx_XGIVEREF(__pyx_t_10); + __Pyx_XGIVEREF(__pyx_t_11); + __Pyx_XGIVEREF(__pyx_t_12); + __Pyx_ExceptionReset(__pyx_t_10, __pyx_t_11, __pyx_t_12); + __Pyx_XGIVEREF(__pyx_t_7); + __Pyx_XGIVEREF(__pyx_t_8); + __Pyx_XGIVEREF(__pyx_t_9); + __Pyx_ErrRestore(__pyx_t_7, __pyx_t_8, __pyx_t_9); + __pyx_t_7 = 0; __pyx_t_8 = 0; __pyx_t_9 = 0; __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; + __pyx_lineno = __pyx_t_4; __pyx_clineno = __pyx_t_5; __pyx_filename = __pyx_t_6; + goto __pyx_L1_error; + } + __pyx_L7:; + } + + /* "View.MemoryView":463 + * memoryview_copy_contents(msrc, mdst, src.ndim, dst.ndim, self.dtype_is_object) + * + * cdef setitem_slice_assign_scalar(self, memoryview dst, value): # <<<<<<<<<<<<<< + * cdef int array[128] + * cdef void *tmp = NULL +*/ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_3); + __Pyx_AddTraceback("View.MemoryView.memoryview.setitem_slice_assign_scalar", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":495 + * PyMem_Free(tmp) + * + * cdef setitem_indexed(self, index, value): # <<<<<<<<<<<<<< + * cdef char *itemp = self.get_item_pointer(index) + * self.assign_item_from_object(itemp, value) +*/ + +static PyObject *__pyx_memoryview_setitem_indexed(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_index, PyObject *__pyx_v_value) { + char *__pyx_v_itemp; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + char *__pyx_t_1; + PyObject *__pyx_t_2 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("setitem_indexed", 0); + + /* "View.MemoryView":496 + * + * cdef setitem_indexed(self, index, value): + * cdef char *itemp = self.get_item_pointer(index) # <<<<<<<<<<<<<< + * self.assign_item_from_object(itemp, value) + * +*/ + __pyx_t_1 = ((struct __pyx_vtabstruct_memoryview *)__pyx_v_self->__pyx_vtab)->get_item_pointer(__pyx_v_self, __pyx_v_index); if (unlikely(__pyx_t_1 == ((void *)NULL))) __PYX_ERR(1, 496, __pyx_L1_error) + __pyx_v_itemp = __pyx_t_1; + + /* "View.MemoryView":497 + * cdef setitem_indexed(self, index, value): + * cdef char *itemp = self.get_item_pointer(index) + * self.assign_item_from_object(itemp, value) # <<<<<<<<<<<<<< + * + * cdef convert_item_to_object(self, char *itemp): +*/ + __pyx_t_2 = ((struct __pyx_vtabstruct_memoryview *)__pyx_v_self->__pyx_vtab)->assign_item_from_object(__pyx_v_self, __pyx_v_itemp, __pyx_v_value); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 497, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "View.MemoryView":495 + * PyMem_Free(tmp) + * + * cdef setitem_indexed(self, index, value): # <<<<<<<<<<<<<< + * cdef char *itemp = self.get_item_pointer(index) + * self.assign_item_from_object(itemp, value) +*/ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("View.MemoryView.memoryview.setitem_indexed", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":499 + * self.assign_item_from_object(itemp, value) + * + * cdef convert_item_to_object(self, char *itemp): # <<<<<<<<<<<<<< + * """Only used if instantiated manually by the user, or if Cython doesn't + * know how to convert the type""" +*/ + +static PyObject *__pyx_memoryview_convert_item_to_object(struct __pyx_memoryview_obj *__pyx_v_self, char *__pyx_v_itemp) { + PyObject *__pyx_v_struct = NULL; + PyObject *__pyx_v_bytesitem = 0; + PyObject *__pyx_v_result = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + size_t __pyx_t_7; + Py_ssize_t __pyx_t_8; + int __pyx_t_9; + PyObject *__pyx_t_10 = NULL; + int __pyx_t_11; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("convert_item_to_object", 0); + + /* "View.MemoryView":502 + * """Only used if instantiated manually by the user, or if Cython doesn't + * know how to convert the type""" + * import struct # <<<<<<<<<<<<<< + * cdef bytes bytesitem + * +*/ + __pyx_t_2 = __Pyx_Import(__pyx_mstate_global->__pyx_n_u_struct, 0, 0, NULL, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 502, __pyx_L1_error) + __pyx_t_1 = __pyx_t_2; + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_struct = __pyx_t_1; + __pyx_t_1 = 0; + + /* "View.MemoryView":505 + * cdef bytes bytesitem + * + * bytesitem = itemp[:self.view.itemsize] # <<<<<<<<<<<<<< + * try: + * result = struct.unpack(self.view.format, bytesitem) +*/ + __pyx_t_1 = __Pyx_PyBytes_FromStringAndSize(__pyx_v_itemp + 0, __pyx_v_self->view.itemsize - 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 505, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_bytesitem = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "View.MemoryView":506 + * + * bytesitem = itemp[:self.view.itemsize] + * try: # <<<<<<<<<<<<<< + * result = struct.unpack(self.view.format, bytesitem) + * except struct.error: +*/ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_2, &__pyx_t_3, &__pyx_t_4); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_4); + /*try:*/ { + + /* "View.MemoryView":507 + * bytesitem = itemp[:self.view.itemsize] + * try: + * result = struct.unpack(self.view.format, bytesitem) # <<<<<<<<<<<<<< + * except struct.error: + * raise ValueError, "Unable to convert item to object" +*/ + __pyx_t_5 = __pyx_v_struct; + __Pyx_INCREF(__pyx_t_5); + __pyx_t_6 = __Pyx_PyBytes_FromString(__pyx_v_self->view.format); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 507, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_7 = 0; + { + PyObject *__pyx_callargs[3] = {__pyx_t_5, __pyx_t_6, __pyx_v_bytesitem}; + __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_unpack, __pyx_callargs+__pyx_t_7, (3-__pyx_t_7) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 507, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_1); + } + __pyx_v_result = __pyx_t_1; + __pyx_t_1 = 0; + + /* "View.MemoryView":506 + * + * bytesitem = itemp[:self.view.itemsize] + * try: # <<<<<<<<<<<<<< + * result = struct.unpack(self.view.format, bytesitem) + * except struct.error: +*/ + } + + /* "View.MemoryView":511 + * raise ValueError, "Unable to convert item to object" + * else: + * if len(self.view.format) == 1: # <<<<<<<<<<<<<< + * return result[0] + * return result +*/ + /*else:*/ { + __pyx_t_8 = __Pyx_ssize_strlen(__pyx_v_self->view.format); if (unlikely(__pyx_t_8 == ((Py_ssize_t)-1))) __PYX_ERR(1, 511, __pyx_L5_except_error) + __pyx_t_9 = (__pyx_t_8 == 1); + if (__pyx_t_9) { + + /* "View.MemoryView":512 + * else: + * if len(self.view.format) == 1: + * return result[0] # <<<<<<<<<<<<<< + * return result + * +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_result, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_OwnStrongReference); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 512, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L6_except_return; + + /* "View.MemoryView":511 + * raise ValueError, "Unable to convert item to object" + * else: + * if len(self.view.format) == 1: # <<<<<<<<<<<<<< + * return result[0] + * return result +*/ + } + + /* "View.MemoryView":513 + * if len(self.view.format) == 1: + * return result[0] + * return result # <<<<<<<<<<<<<< + * + * cdef assign_item_from_object(self, char *itemp, object value): +*/ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_result); + __pyx_r = __pyx_v_result; + goto __pyx_L6_except_return; + } + __pyx_L3_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + + /* "View.MemoryView":508 + * try: + * result = struct.unpack(self.view.format, bytesitem) + * except struct.error: # <<<<<<<<<<<<<< + * raise ValueError, "Unable to convert item to object" + * else: +*/ + __Pyx_ErrFetch(&__pyx_t_1, &__pyx_t_6, &__pyx_t_5); + __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_v_struct, __pyx_mstate_global->__pyx_n_u_error); if (unlikely(!__pyx_t_10)) __PYX_ERR(1, 508, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_10); + __pyx_t_11 = __Pyx_PyErr_GivenExceptionMatches(__pyx_t_1, __pyx_t_10); + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __Pyx_ErrRestore(__pyx_t_1, __pyx_t_6, __pyx_t_5); + __pyx_t_1 = 0; __pyx_t_6 = 0; __pyx_t_5 = 0; + if (__pyx_t_11) { + __Pyx_AddTraceback("View.MemoryView.memoryview.convert_item_to_object", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_1) < 0) __PYX_ERR(1, 508, __pyx_L5_except_error) + __Pyx_XGOTREF(__pyx_t_5); + __Pyx_XGOTREF(__pyx_t_6); + __Pyx_XGOTREF(__pyx_t_1); + + /* "View.MemoryView":509 + * result = struct.unpack(self.view.format, bytesitem) + * except struct.error: + * raise ValueError, "Unable to convert item to object" # <<<<<<<<<<<<<< + * else: + * if len(self.view.format) == 1: +*/ + __Pyx_Raise(((PyObject *)(((PyTypeObject*)PyExc_ValueError))), __pyx_mstate_global->__pyx_kp_u_Unable_to_convert_item_to_object, 0, 0); + __PYX_ERR(1, 509, __pyx_L5_except_error) + } + goto __pyx_L5_except_error; + + /* "View.MemoryView":506 + * + * bytesitem = itemp[:self.view.itemsize] + * try: # <<<<<<<<<<<<<< + * result = struct.unpack(self.view.format, bytesitem) + * except struct.error: +*/ + __pyx_L5_except_error:; + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L1_error; + __pyx_L6_except_return:; + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L0; + } + + /* "View.MemoryView":499 + * self.assign_item_from_object(itemp, value) + * + * cdef convert_item_to_object(self, char *itemp): # <<<<<<<<<<<<<< + * """Only used if instantiated manually by the user, or if Cython doesn't + * know how to convert the type""" +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_10); + __Pyx_AddTraceback("View.MemoryView.memoryview.convert_item_to_object", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_struct); + __Pyx_XDECREF(__pyx_v_bytesitem); + __Pyx_XDECREF(__pyx_v_result); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":515 + * return result + * + * cdef assign_item_from_object(self, char *itemp, object value): # <<<<<<<<<<<<<< + * """Only used if instantiated manually by the user, or if Cython doesn't + * know how to convert the type""" +*/ + +static PyObject *__pyx_memoryview_assign_item_from_object(struct __pyx_memoryview_obj *__pyx_v_self, char *__pyx_v_itemp, PyObject *__pyx_v_value) { + PyObject *__pyx_v_struct = NULL; + char __pyx_v_c; + PyObject *__pyx_v_bytesvalue = 0; + Py_ssize_t __pyx_v_i; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + size_t __pyx_t_7; + Py_ssize_t __pyx_t_8; + PyObject *__pyx_t_9 = NULL; + char *__pyx_t_10; + char *__pyx_t_11; + Py_ssize_t __pyx_t_12; + char *__pyx_t_13; + char *__pyx_t_14; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("assign_item_from_object", 0); + + /* "View.MemoryView":518 + * """Only used if instantiated manually by the user, or if Cython doesn't + * know how to convert the type""" + * import struct # <<<<<<<<<<<<<< + * cdef char c + * cdef bytes bytesvalue +*/ + __pyx_t_2 = __Pyx_Import(__pyx_mstate_global->__pyx_n_u_struct, 0, 0, NULL, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 518, __pyx_L1_error) + __pyx_t_1 = __pyx_t_2; + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_struct = __pyx_t_1; + __pyx_t_1 = 0; + + /* "View.MemoryView":523 + * cdef Py_ssize_t i + * + * if isinstance(value, tuple): # <<<<<<<<<<<<<< + * bytesvalue = struct.pack(self.view.format, *value) + * else: +*/ + __pyx_t_3 = PyTuple_Check(__pyx_v_value); + if (__pyx_t_3) { + + /* "View.MemoryView":524 + * + * if isinstance(value, tuple): + * bytesvalue = struct.pack(self.view.format, *value) # <<<<<<<<<<<<<< + * else: + * bytesvalue = struct.pack(self.view.format, value) +*/ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_struct, __pyx_mstate_global->__pyx_n_u_pack); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 524, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = __Pyx_PyBytes_FromString(__pyx_v_self->view.format); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 524, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 524, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_GIVEREF(__pyx_t_4); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4) != (0)) __PYX_ERR(1, 524, __pyx_L1_error); + __pyx_t_4 = 0; + __pyx_t_4 = __Pyx_PySequence_Tuple(__pyx_v_value); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 524, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_6 = PyNumber_Add(__pyx_t_5, __pyx_t_4); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 524, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_6, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 524, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (!(likely(PyBytes_CheckExact(__pyx_t_4))||((__pyx_t_4) == Py_None) || __Pyx_RaiseUnexpectedTypeError("bytes", __pyx_t_4))) __PYX_ERR(1, 524, __pyx_L1_error) + __pyx_v_bytesvalue = ((PyObject*)__pyx_t_4); + __pyx_t_4 = 0; + + /* "View.MemoryView":523 + * cdef Py_ssize_t i + * + * if isinstance(value, tuple): # <<<<<<<<<<<<<< + * bytesvalue = struct.pack(self.view.format, *value) + * else: +*/ + goto __pyx_L3; + } + + /* "View.MemoryView":526 + * bytesvalue = struct.pack(self.view.format, *value) + * else: + * bytesvalue = struct.pack(self.view.format, value) # <<<<<<<<<<<<<< + * + * for i, c in enumerate(bytesvalue): +*/ + /*else*/ { + __pyx_t_6 = __pyx_v_struct; + __Pyx_INCREF(__pyx_t_6); + __pyx_t_1 = __Pyx_PyBytes_FromString(__pyx_v_self->view.format); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 526, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_7 = 0; + { + PyObject *__pyx_callargs[3] = {__pyx_t_6, __pyx_t_1, __pyx_v_value}; + __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_pack, __pyx_callargs+__pyx_t_7, (3-__pyx_t_7) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 526, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + } + if (!(likely(PyBytes_CheckExact(__pyx_t_4))||((__pyx_t_4) == Py_None) || __Pyx_RaiseUnexpectedTypeError("bytes", __pyx_t_4))) __PYX_ERR(1, 526, __pyx_L1_error) + __pyx_v_bytesvalue = ((PyObject*)__pyx_t_4); + __pyx_t_4 = 0; + } + __pyx_L3:; + + /* "View.MemoryView":528 + * bytesvalue = struct.pack(self.view.format, value) + * + * for i, c in enumerate(bytesvalue): # <<<<<<<<<<<<<< + * itemp[i] = c + * +*/ + __pyx_t_8 = 0; + if (unlikely(__pyx_v_bytesvalue == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' is not iterable"); + __PYX_ERR(1, 528, __pyx_L1_error) + } + __Pyx_INCREF(__pyx_v_bytesvalue); + __pyx_t_9 = __pyx_v_bytesvalue; + __pyx_t_11 = __Pyx_PyBytes_AsWritableString(__pyx_t_9); if (unlikely(__pyx_t_11 == ((char *)NULL))) __PYX_ERR(1, 528, __pyx_L1_error) + __pyx_t_12 = __Pyx_PyBytes_GET_SIZE(__pyx_t_9); if (unlikely(__pyx_t_12 == ((Py_ssize_t)-1))) __PYX_ERR(1, 528, __pyx_L1_error) + __pyx_t_13 = (__pyx_t_11 + __pyx_t_12); + for (__pyx_t_14 = __pyx_t_11; __pyx_t_14 < __pyx_t_13; __pyx_t_14++) { + __pyx_t_10 = __pyx_t_14; + __pyx_v_c = (__pyx_t_10[0]); + + /* "View.MemoryView":529 + * + * for i, c in enumerate(bytesvalue): + * itemp[i] = c # <<<<<<<<<<<<<< + * + * @cname('getbuffer') +*/ + __pyx_v_i = __pyx_t_8; + + /* "View.MemoryView":528 + * bytesvalue = struct.pack(self.view.format, value) + * + * for i, c in enumerate(bytesvalue): # <<<<<<<<<<<<<< + * itemp[i] = c + * +*/ + __pyx_t_8 = (__pyx_t_8 + 1); + + /* "View.MemoryView":529 + * + * for i, c in enumerate(bytesvalue): + * itemp[i] = c # <<<<<<<<<<<<<< + * + * @cname('getbuffer') +*/ + (__pyx_v_itemp[__pyx_v_i]) = __pyx_v_c; + } + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + + /* "View.MemoryView":515 + * return result + * + * cdef assign_item_from_object(self, char *itemp, object value): # <<<<<<<<<<<<<< + * """Only used if instantiated manually by the user, or if Cython doesn't + * know how to convert the type""" +*/ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_AddTraceback("View.MemoryView.memoryview.assign_item_from_object", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_struct); + __Pyx_XDECREF(__pyx_v_bytesvalue); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":531 + * itemp[i] = c + * + * @cname('getbuffer') # <<<<<<<<<<<<<< + * def __getbuffer__(self, Py_buffer *info, int flags): + * if flags & PyBUF_WRITABLE and self.view.readonly: +*/ + +/* Python wrapper */ +CYTHON_UNUSED static int __pyx_memoryview_getbuffer(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /*proto*/ +CYTHON_UNUSED static int __pyx_memoryview_getbuffer(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__getbuffer__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_r = __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbuffer__(((struct __pyx_memoryview_obj *)__pyx_v_self), ((Py_buffer *)__pyx_v_info), ((int)__pyx_v_flags)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbuffer__(struct __pyx_memoryview_obj *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_t_2; + Py_ssize_t *__pyx_t_3; + char *__pyx_t_4; + void *__pyx_t_5; + int __pyx_t_6; + Py_ssize_t __pyx_t_7; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + if (unlikely(__pyx_v_info == NULL)) { + PyErr_SetString(PyExc_BufferError, "PyObject_GetBuffer: view==NULL argument is obsolete"); + return -1; + } + __Pyx_RefNannySetupContext("__getbuffer__", 0); + __pyx_v_info->obj = Py_None; __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(__pyx_v_info->obj); + + /* "View.MemoryView":533 + * @cname('getbuffer') + * def __getbuffer__(self, Py_buffer *info, int flags): + * if flags & PyBUF_WRITABLE and self.view.readonly: # <<<<<<<<<<<<<< + * raise ValueError, "Cannot create writable memory view from read-only memoryview" + * +*/ + __pyx_t_2 = ((__pyx_v_flags & PyBUF_WRITABLE) != 0); + if (__pyx_t_2) { + } else { + __pyx_t_1 = __pyx_t_2; + goto __pyx_L4_bool_binop_done; + } + __pyx_t_1 = __pyx_v_self->view.readonly; + __pyx_L4_bool_binop_done:; + if (unlikely(__pyx_t_1)) { + + /* "View.MemoryView":534 + * def __getbuffer__(self, Py_buffer *info, int flags): + * if flags & PyBUF_WRITABLE and self.view.readonly: + * raise ValueError, "Cannot create writable memory view from read-only memoryview" # <<<<<<<<<<<<<< + * + * if flags & PyBUF_ND: +*/ + __Pyx_Raise(((PyObject *)(((PyTypeObject*)PyExc_ValueError))), __pyx_mstate_global->__pyx_kp_u_Cannot_create_writable_memory_vi, 0, 0); + __PYX_ERR(1, 534, __pyx_L1_error) + + /* "View.MemoryView":533 + * @cname('getbuffer') + * def __getbuffer__(self, Py_buffer *info, int flags): + * if flags & PyBUF_WRITABLE and self.view.readonly: # <<<<<<<<<<<<<< + * raise ValueError, "Cannot create writable memory view from read-only memoryview" + * +*/ + } + + /* "View.MemoryView":536 + * raise ValueError, "Cannot create writable memory view from read-only memoryview" + * + * if flags & PyBUF_ND: # <<<<<<<<<<<<<< + * info.shape = self.view.shape + * else: +*/ + __pyx_t_1 = ((__pyx_v_flags & PyBUF_ND) != 0); + if (__pyx_t_1) { + + /* "View.MemoryView":537 + * + * if flags & PyBUF_ND: + * info.shape = self.view.shape # <<<<<<<<<<<<<< + * else: + * info.shape = NULL +*/ + __pyx_t_3 = __pyx_v_self->view.shape; + __pyx_v_info->shape = __pyx_t_3; + + /* "View.MemoryView":536 + * raise ValueError, "Cannot create writable memory view from read-only memoryview" + * + * if flags & PyBUF_ND: # <<<<<<<<<<<<<< + * info.shape = self.view.shape + * else: +*/ + goto __pyx_L6; + } + + /* "View.MemoryView":539 + * info.shape = self.view.shape + * else: + * info.shape = NULL # <<<<<<<<<<<<<< + * + * if flags & PyBUF_STRIDES: +*/ + /*else*/ { + __pyx_v_info->shape = NULL; + } + __pyx_L6:; + + /* "View.MemoryView":541 + * info.shape = NULL + * + * if flags & PyBUF_STRIDES: # <<<<<<<<<<<<<< + * info.strides = self.view.strides + * else: +*/ + __pyx_t_1 = ((__pyx_v_flags & PyBUF_STRIDES) != 0); + if (__pyx_t_1) { + + /* "View.MemoryView":542 + * + * if flags & PyBUF_STRIDES: + * info.strides = self.view.strides # <<<<<<<<<<<<<< + * else: + * info.strides = NULL +*/ + __pyx_t_3 = __pyx_v_self->view.strides; + __pyx_v_info->strides = __pyx_t_3; + + /* "View.MemoryView":541 + * info.shape = NULL + * + * if flags & PyBUF_STRIDES: # <<<<<<<<<<<<<< + * info.strides = self.view.strides + * else: +*/ + goto __pyx_L7; + } + + /* "View.MemoryView":544 + * info.strides = self.view.strides + * else: + * info.strides = NULL # <<<<<<<<<<<<<< + * + * if flags & PyBUF_INDIRECT: +*/ + /*else*/ { + __pyx_v_info->strides = NULL; + } + __pyx_L7:; + + /* "View.MemoryView":546 + * info.strides = NULL + * + * if flags & PyBUF_INDIRECT: # <<<<<<<<<<<<<< + * info.suboffsets = self.view.suboffsets + * else: +*/ + __pyx_t_1 = ((__pyx_v_flags & PyBUF_INDIRECT) != 0); + if (__pyx_t_1) { + + /* "View.MemoryView":547 + * + * if flags & PyBUF_INDIRECT: + * info.suboffsets = self.view.suboffsets # <<<<<<<<<<<<<< + * else: + * info.suboffsets = NULL +*/ + __pyx_t_3 = __pyx_v_self->view.suboffsets; + __pyx_v_info->suboffsets = __pyx_t_3; + + /* "View.MemoryView":546 + * info.strides = NULL + * + * if flags & PyBUF_INDIRECT: # <<<<<<<<<<<<<< + * info.suboffsets = self.view.suboffsets + * else: +*/ + goto __pyx_L8; + } + + /* "View.MemoryView":549 + * info.suboffsets = self.view.suboffsets + * else: + * info.suboffsets = NULL # <<<<<<<<<<<<<< + * + * if flags & PyBUF_FORMAT: +*/ + /*else*/ { + __pyx_v_info->suboffsets = NULL; + } + __pyx_L8:; + + /* "View.MemoryView":551 + * info.suboffsets = NULL + * + * if flags & PyBUF_FORMAT: # <<<<<<<<<<<<<< + * info.format = self.view.format + * else: +*/ + __pyx_t_1 = ((__pyx_v_flags & PyBUF_FORMAT) != 0); + if (__pyx_t_1) { + + /* "View.MemoryView":552 + * + * if flags & PyBUF_FORMAT: + * info.format = self.view.format # <<<<<<<<<<<<<< + * else: + * info.format = NULL +*/ + __pyx_t_4 = __pyx_v_self->view.format; + __pyx_v_info->format = __pyx_t_4; + + /* "View.MemoryView":551 + * info.suboffsets = NULL + * + * if flags & PyBUF_FORMAT: # <<<<<<<<<<<<<< + * info.format = self.view.format + * else: +*/ + goto __pyx_L9; + } + + /* "View.MemoryView":554 + * info.format = self.view.format + * else: + * info.format = NULL # <<<<<<<<<<<<<< + * + * info.buf = self.view.buf +*/ + /*else*/ { + __pyx_v_info->format = NULL; + } + __pyx_L9:; + + /* "View.MemoryView":556 + * info.format = NULL + * + * info.buf = self.view.buf # <<<<<<<<<<<<<< + * info.ndim = self.view.ndim + * info.itemsize = self.view.itemsize +*/ + __pyx_t_5 = __pyx_v_self->view.buf; + __pyx_v_info->buf = __pyx_t_5; + + /* "View.MemoryView":557 + * + * info.buf = self.view.buf + * info.ndim = self.view.ndim # <<<<<<<<<<<<<< + * info.itemsize = self.view.itemsize + * info.len = self.view.len +*/ + __pyx_t_6 = __pyx_v_self->view.ndim; + __pyx_v_info->ndim = __pyx_t_6; + + /* "View.MemoryView":558 + * info.buf = self.view.buf + * info.ndim = self.view.ndim + * info.itemsize = self.view.itemsize # <<<<<<<<<<<<<< + * info.len = self.view.len + * info.readonly = self.view.readonly +*/ + __pyx_t_7 = __pyx_v_self->view.itemsize; + __pyx_v_info->itemsize = __pyx_t_7; + + /* "View.MemoryView":559 + * info.ndim = self.view.ndim + * info.itemsize = self.view.itemsize + * info.len = self.view.len # <<<<<<<<<<<<<< + * info.readonly = self.view.readonly + * info.obj = self +*/ + __pyx_t_7 = __pyx_v_self->view.len; + __pyx_v_info->len = __pyx_t_7; + + /* "View.MemoryView":560 + * info.itemsize = self.view.itemsize + * info.len = self.view.len + * info.readonly = self.view.readonly # <<<<<<<<<<<<<< + * info.obj = self + * +*/ + __pyx_t_1 = __pyx_v_self->view.readonly; + __pyx_v_info->readonly = __pyx_t_1; + + /* "View.MemoryView":561 + * info.len = self.view.len + * info.readonly = self.view.readonly + * info.obj = self # <<<<<<<<<<<<<< + * + * +*/ + __Pyx_INCREF((PyObject *)__pyx_v_self); + __Pyx_GIVEREF((PyObject *)__pyx_v_self); + __Pyx_GOTREF(__pyx_v_info->obj); + __Pyx_DECREF(__pyx_v_info->obj); + __pyx_v_info->obj = ((PyObject *)__pyx_v_self); + + /* "View.MemoryView":531 + * itemp[i] = c + * + * @cname('getbuffer') # <<<<<<<<<<<<<< + * def __getbuffer__(self, Py_buffer *info, int flags): + * if flags & PyBUF_WRITABLE and self.view.readonly: +*/ + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("View.MemoryView.memoryview.__getbuffer__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + if (__pyx_v_info->obj != NULL) { + __Pyx_GOTREF(__pyx_v_info->obj); + __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = 0; + } + goto __pyx_L2; + __pyx_L0:; + if (__pyx_v_info->obj == Py_None) { + __Pyx_GOTREF(__pyx_v_info->obj); + __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = 0; + } + __pyx_L2:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":564 + * + * + * @property # <<<<<<<<<<<<<< + * def T(self): + * cdef _memoryviewslice result = memoryview_copy(self) +*/ + +/* Python wrapper */ +static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_1T_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_1T_1__get__(PyObject *__pyx_v_self) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_r = __pyx_pf_15View_dot_MemoryView_10memoryview_1T___get__(((struct __pyx_memoryview_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_1T___get__(struct __pyx_memoryview_obj *__pyx_v_self) { + struct __pyx_memoryviewslice_obj *__pyx_v_result = 0; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + + /* "View.MemoryView":566 + * @property + * def T(self): + * cdef _memoryviewslice result = memoryview_copy(self) # <<<<<<<<<<<<<< + * transpose_memslice(&result.from_slice) + * return result +*/ + __pyx_t_1 = __pyx_memoryview_copy_object(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 566, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_mstate_global->__pyx_memoryviewslice_type))))) __PYX_ERR(1, 566, __pyx_L1_error) + __pyx_v_result = ((struct __pyx_memoryviewslice_obj *)__pyx_t_1); + __pyx_t_1 = 0; + + /* "View.MemoryView":567 + * def T(self): + * cdef _memoryviewslice result = memoryview_copy(self) + * transpose_memslice(&result.from_slice) # <<<<<<<<<<<<<< + * return result + * +*/ + __pyx_t_2 = __pyx_memslice_transpose((&__pyx_v_result->from_slice)); if (unlikely(__pyx_t_2 == ((int)-1))) __PYX_ERR(1, 567, __pyx_L1_error) + + /* "View.MemoryView":568 + * cdef _memoryviewslice result = memoryview_copy(self) + * transpose_memslice(&result.from_slice) + * return result # <<<<<<<<<<<<<< + * + * @property +*/ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF((PyObject *)__pyx_v_result); + __pyx_r = ((PyObject *)__pyx_v_result); + goto __pyx_L0; + + /* "View.MemoryView":564 + * + * + * @property # <<<<<<<<<<<<<< + * def T(self): + * cdef _memoryviewslice result = memoryview_copy(self) +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("View.MemoryView.memoryview.T.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF((PyObject *)__pyx_v_result); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":570 + * return result + * + * @property # <<<<<<<<<<<<<< + * def base(self): + * return self._get_base() +*/ + +/* Python wrapper */ +static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_4base_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_4base_1__get__(PyObject *__pyx_v_self) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_r = __pyx_pf_15View_dot_MemoryView_10memoryview_4base___get__(((struct __pyx_memoryview_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4base___get__(struct __pyx_memoryview_obj *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + + /* "View.MemoryView":572 + * @property + * def base(self): + * return self._get_base() # <<<<<<<<<<<<<< + * + * cdef _get_base(self): +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = ((struct __pyx_vtabstruct_memoryview *)__pyx_v_self->__pyx_vtab)->_get_base(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 572, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "View.MemoryView":570 + * return result + * + * @property # <<<<<<<<<<<<<< + * def base(self): + * return self._get_base() +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("View.MemoryView.memoryview.base.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":574 + * return self._get_base() + * + * cdef _get_base(self): # <<<<<<<<<<<<<< + * return self.obj + * +*/ + +static PyObject *__pyx_memoryview__get_base(struct __pyx_memoryview_obj *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("_get_base", 0); + + /* "View.MemoryView":575 + * + * cdef _get_base(self): + * return self.obj # <<<<<<<<<<<<<< + * + * @property +*/ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->obj); + __pyx_r = __pyx_v_self->obj; + goto __pyx_L0; + + /* "View.MemoryView":574 + * return self._get_base() + * + * cdef _get_base(self): # <<<<<<<<<<<<<< + * return self.obj + * +*/ + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":577 + * return self.obj + * + * @property # <<<<<<<<<<<<<< + * def shape(self): + * return tuple([length for length in self.view.shape[:self.view.ndim]]) +*/ + +/* Python wrapper */ +static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_5shape_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_5shape_1__get__(PyObject *__pyx_v_self) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_r = __pyx_pf_15View_dot_MemoryView_10memoryview_5shape___get__(((struct __pyx_memoryview_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_5shape___get__(struct __pyx_memoryview_obj *__pyx_v_self) { + Py_ssize_t __pyx_7genexpr__pyx_v_length; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + Py_ssize_t *__pyx_t_2; + Py_ssize_t *__pyx_t_3; + Py_ssize_t *__pyx_t_4; + PyObject *__pyx_t_5 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + + /* "View.MemoryView":579 + * @property + * def shape(self): + * return tuple([length for length in self.view.shape[:self.view.ndim]]) # <<<<<<<<<<<<<< + * + * @property +*/ + __Pyx_XDECREF(__pyx_r); + { /* enter inner scope */ + __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 579, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = (__pyx_v_self->view.shape + __pyx_v_self->view.ndim); + for (__pyx_t_4 = __pyx_v_self->view.shape; __pyx_t_4 < __pyx_t_3; __pyx_t_4++) { + __pyx_t_2 = __pyx_t_4; + __pyx_7genexpr__pyx_v_length = (__pyx_t_2[0]); + __pyx_t_5 = PyLong_FromSsize_t(__pyx_7genexpr__pyx_v_length); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 579, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + if (unlikely(__Pyx_ListComp_Append(__pyx_t_1, (PyObject*)__pyx_t_5))) __PYX_ERR(1, 579, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + } + } /* exit inner scope */ + __pyx_t_5 = PyList_AsTuple(((PyObject*)__pyx_t_1)); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 579, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_r = __pyx_t_5; + __pyx_t_5 = 0; + goto __pyx_L0; + + /* "View.MemoryView":577 + * return self.obj + * + * @property # <<<<<<<<<<<<<< + * def shape(self): + * return tuple([length for length in self.view.shape[:self.view.ndim]]) +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("View.MemoryView.memoryview.shape.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":581 + * return tuple([length for length in self.view.shape[:self.view.ndim]]) + * + * @property # <<<<<<<<<<<<<< + * def strides(self): + * if self.view.strides == NULL: +*/ + +/* Python wrapper */ +static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_7strides_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_7strides_1__get__(PyObject *__pyx_v_self) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_r = __pyx_pf_15View_dot_MemoryView_10memoryview_7strides___get__(((struct __pyx_memoryview_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_7strides___get__(struct __pyx_memoryview_obj *__pyx_v_self) { + Py_ssize_t __pyx_8genexpr1__pyx_v_stride; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + PyObject *__pyx_t_2 = NULL; + Py_ssize_t *__pyx_t_3; + Py_ssize_t *__pyx_t_4; + Py_ssize_t *__pyx_t_5; + PyObject *__pyx_t_6 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + + /* "View.MemoryView":583 + * @property + * def strides(self): + * if self.view.strides == NULL: # <<<<<<<<<<<<<< + * + * raise ValueError, "Buffer view does not expose strides" +*/ + __pyx_t_1 = (__pyx_v_self->view.strides == NULL); + if (unlikely(__pyx_t_1)) { + + /* "View.MemoryView":585 + * if self.view.strides == NULL: + * + * raise ValueError, "Buffer view does not expose strides" # <<<<<<<<<<<<<< + * + * return tuple([stride for stride in self.view.strides[:self.view.ndim]]) +*/ + __Pyx_Raise(((PyObject *)(((PyTypeObject*)PyExc_ValueError))), __pyx_mstate_global->__pyx_kp_u_Buffer_view_does_not_expose_stri, 0, 0); + __PYX_ERR(1, 585, __pyx_L1_error) + + /* "View.MemoryView":583 + * @property + * def strides(self): + * if self.view.strides == NULL: # <<<<<<<<<<<<<< + * + * raise ValueError, "Buffer view does not expose strides" +*/ + } + + /* "View.MemoryView":587 + * raise ValueError, "Buffer view does not expose strides" + * + * return tuple([stride for stride in self.view.strides[:self.view.ndim]]) # <<<<<<<<<<<<<< + * + * @property +*/ + __Pyx_XDECREF(__pyx_r); + { /* enter inner scope */ + __pyx_t_2 = PyList_New(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 587, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = (__pyx_v_self->view.strides + __pyx_v_self->view.ndim); + for (__pyx_t_5 = __pyx_v_self->view.strides; __pyx_t_5 < __pyx_t_4; __pyx_t_5++) { + __pyx_t_3 = __pyx_t_5; + __pyx_8genexpr1__pyx_v_stride = (__pyx_t_3[0]); + __pyx_t_6 = PyLong_FromSsize_t(__pyx_8genexpr1__pyx_v_stride); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 587, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + if (unlikely(__Pyx_ListComp_Append(__pyx_t_2, (PyObject*)__pyx_t_6))) __PYX_ERR(1, 587, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + } + } /* exit inner scope */ + __pyx_t_6 = PyList_AsTuple(((PyObject*)__pyx_t_2)); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 587, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_r = __pyx_t_6; + __pyx_t_6 = 0; + goto __pyx_L0; + + /* "View.MemoryView":581 + * return tuple([length for length in self.view.shape[:self.view.ndim]]) + * + * @property # <<<<<<<<<<<<<< + * def strides(self): + * if self.view.strides == NULL: +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("View.MemoryView.memoryview.strides.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":589 + * return tuple([stride for stride in self.view.strides[:self.view.ndim]]) + * + * @property # <<<<<<<<<<<<<< + * def suboffsets(self): + * if self.view.suboffsets == NULL: +*/ + +/* Python wrapper */ +static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_10suboffsets_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_10suboffsets_1__get__(PyObject *__pyx_v_self) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_r = __pyx_pf_15View_dot_MemoryView_10memoryview_10suboffsets___get__(((struct __pyx_memoryview_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_10suboffsets___get__(struct __pyx_memoryview_obj *__pyx_v_self) { + Py_ssize_t __pyx_8genexpr2__pyx_v_suboffset; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + PyObject *__pyx_t_2 = NULL; + Py_ssize_t *__pyx_t_3; + Py_ssize_t *__pyx_t_4; + Py_ssize_t *__pyx_t_5; + PyObject *__pyx_t_6 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + + /* "View.MemoryView":591 + * @property + * def suboffsets(self): + * if self.view.suboffsets == NULL: # <<<<<<<<<<<<<< + * return (-1,) * self.view.ndim + * +*/ + __pyx_t_1 = (__pyx_v_self->view.suboffsets == NULL); + if (__pyx_t_1) { + + /* "View.MemoryView":592 + * def suboffsets(self): + * if self.view.suboffsets == NULL: + * return (-1,) * self.view.ndim # <<<<<<<<<<<<<< + * + * return tuple([suboffset for suboffset in self.view.suboffsets[:self.view.ndim]]) +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_2 = __Pyx_PySequence_Multiply(__pyx_mstate_global->__pyx_tuple[0], __pyx_v_self->view.ndim); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 592, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + goto __pyx_L0; + + /* "View.MemoryView":591 + * @property + * def suboffsets(self): + * if self.view.suboffsets == NULL: # <<<<<<<<<<<<<< + * return (-1,) * self.view.ndim + * +*/ + } + + /* "View.MemoryView":594 + * return (-1,) * self.view.ndim + * + * return tuple([suboffset for suboffset in self.view.suboffsets[:self.view.ndim]]) # <<<<<<<<<<<<<< + * + * @property +*/ + __Pyx_XDECREF(__pyx_r); + { /* enter inner scope */ + __pyx_t_2 = PyList_New(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 594, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_4 = (__pyx_v_self->view.suboffsets + __pyx_v_self->view.ndim); + for (__pyx_t_5 = __pyx_v_self->view.suboffsets; __pyx_t_5 < __pyx_t_4; __pyx_t_5++) { + __pyx_t_3 = __pyx_t_5; + __pyx_8genexpr2__pyx_v_suboffset = (__pyx_t_3[0]); + __pyx_t_6 = PyLong_FromSsize_t(__pyx_8genexpr2__pyx_v_suboffset); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 594, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + if (unlikely(__Pyx_ListComp_Append(__pyx_t_2, (PyObject*)__pyx_t_6))) __PYX_ERR(1, 594, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + } + } /* exit inner scope */ + __pyx_t_6 = PyList_AsTuple(((PyObject*)__pyx_t_2)); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 594, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_r = __pyx_t_6; + __pyx_t_6 = 0; + goto __pyx_L0; + + /* "View.MemoryView":589 + * return tuple([stride for stride in self.view.strides[:self.view.ndim]]) + * + * @property # <<<<<<<<<<<<<< + * def suboffsets(self): + * if self.view.suboffsets == NULL: +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("View.MemoryView.memoryview.suboffsets.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":596 + * return tuple([suboffset for suboffset in self.view.suboffsets[:self.view.ndim]]) + * + * @property # <<<<<<<<<<<<<< + * def ndim(self): + * return self.view.ndim +*/ + +/* Python wrapper */ +static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_4ndim_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_4ndim_1__get__(PyObject *__pyx_v_self) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_r = __pyx_pf_15View_dot_MemoryView_10memoryview_4ndim___get__(((struct __pyx_memoryview_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4ndim___get__(struct __pyx_memoryview_obj *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + + /* "View.MemoryView":598 + * @property + * def ndim(self): + * return self.view.ndim # <<<<<<<<<<<<<< + * + * @property +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyLong_From_int(__pyx_v_self->view.ndim); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 598, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "View.MemoryView":596 + * return tuple([suboffset for suboffset in self.view.suboffsets[:self.view.ndim]]) + * + * @property # <<<<<<<<<<<<<< + * def ndim(self): + * return self.view.ndim +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("View.MemoryView.memoryview.ndim.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":600 + * return self.view.ndim + * + * @property # <<<<<<<<<<<<<< + * def itemsize(self): + * return self.view.itemsize +*/ + +/* Python wrapper */ +static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_8itemsize_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_8itemsize_1__get__(PyObject *__pyx_v_self) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_r = __pyx_pf_15View_dot_MemoryView_10memoryview_8itemsize___get__(((struct __pyx_memoryview_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_8itemsize___get__(struct __pyx_memoryview_obj *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + + /* "View.MemoryView":602 + * @property + * def itemsize(self): + * return self.view.itemsize # <<<<<<<<<<<<<< + * + * @property +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyLong_FromSsize_t(__pyx_v_self->view.itemsize); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 602, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "View.MemoryView":600 + * return self.view.ndim + * + * @property # <<<<<<<<<<<<<< + * def itemsize(self): + * return self.view.itemsize +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("View.MemoryView.memoryview.itemsize.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":604 + * return self.view.itemsize + * + * @property # <<<<<<<<<<<<<< + * def nbytes(self): + * return self.size * self.view.itemsize +*/ + +/* Python wrapper */ +static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_6nbytes_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_6nbytes_1__get__(PyObject *__pyx_v_self) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_r = __pyx_pf_15View_dot_MemoryView_10memoryview_6nbytes___get__(((struct __pyx_memoryview_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_6nbytes___get__(struct __pyx_memoryview_obj *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + + /* "View.MemoryView":606 + * @property + * def nbytes(self): + * return self.size * self.view.itemsize # <<<<<<<<<<<<<< + * + * @property +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_mstate_global->__pyx_n_u_size); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 606, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = PyLong_FromSsize_t(__pyx_v_self->view.itemsize); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 606, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = PyNumber_Multiply(__pyx_t_1, __pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 606, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_r = __pyx_t_3; + __pyx_t_3 = 0; + goto __pyx_L0; + + /* "View.MemoryView":604 + * return self.view.itemsize + * + * @property # <<<<<<<<<<<<<< + * def nbytes(self): + * return self.size * self.view.itemsize +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_AddTraceback("View.MemoryView.memoryview.nbytes.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":608 + * return self.size * self.view.itemsize + * + * @property # <<<<<<<<<<<<<< + * def size(self): + * if self._size is None: +*/ + +/* Python wrapper */ +static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_4size_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_4size_1__get__(PyObject *__pyx_v_self) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_r = __pyx_pf_15View_dot_MemoryView_10memoryview_4size___get__(((struct __pyx_memoryview_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4size___get__(struct __pyx_memoryview_obj *__pyx_v_self) { + PyObject *__pyx_v_result = NULL; + PyObject *__pyx_v_length = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + Py_ssize_t *__pyx_t_2; + Py_ssize_t *__pyx_t_3; + Py_ssize_t *__pyx_t_4; + PyObject *__pyx_t_5 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__get__", 0); + + /* "View.MemoryView":610 + * @property + * def size(self): + * if self._size is None: # <<<<<<<<<<<<<< + * result = 1 + * +*/ + __pyx_t_1 = (__pyx_v_self->_size == Py_None); + if (__pyx_t_1) { + + /* "View.MemoryView":611 + * def size(self): + * if self._size is None: + * result = 1 # <<<<<<<<<<<<<< + * + * for length in self.view.shape[:self.view.ndim]: +*/ + __Pyx_INCREF(__pyx_mstate_global->__pyx_int_1); + __pyx_v_result = __pyx_mstate_global->__pyx_int_1; + + /* "View.MemoryView":613 + * result = 1 + * + * for length in self.view.shape[:self.view.ndim]: # <<<<<<<<<<<<<< + * result *= length + * +*/ + __pyx_t_3 = (__pyx_v_self->view.shape + __pyx_v_self->view.ndim); + for (__pyx_t_4 = __pyx_v_self->view.shape; __pyx_t_4 < __pyx_t_3; __pyx_t_4++) { + __pyx_t_2 = __pyx_t_4; + __pyx_t_5 = PyLong_FromSsize_t((__pyx_t_2[0])); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 613, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_XDECREF_SET(__pyx_v_length, __pyx_t_5); + __pyx_t_5 = 0; + + /* "View.MemoryView":614 + * + * for length in self.view.shape[:self.view.ndim]: + * result *= length # <<<<<<<<<<<<<< + * + * self._size = result +*/ + __pyx_t_5 = PyNumber_InPlaceMultiply(__pyx_v_result, __pyx_v_length); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 614, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF_SET(__pyx_v_result, __pyx_t_5); + __pyx_t_5 = 0; + } + + /* "View.MemoryView":616 + * result *= length + * + * self._size = result # <<<<<<<<<<<<<< + * + * return self._size +*/ + __Pyx_INCREF(__pyx_v_result); + __Pyx_GIVEREF(__pyx_v_result); + __Pyx_GOTREF(__pyx_v_self->_size); + __Pyx_DECREF(__pyx_v_self->_size); + __pyx_v_self->_size = __pyx_v_result; + + /* "View.MemoryView":610 + * @property + * def size(self): + * if self._size is None: # <<<<<<<<<<<<<< + * result = 1 + * +*/ + } + + /* "View.MemoryView":618 + * self._size = result + * + * return self._size # <<<<<<<<<<<<<< + * + * def __len__(self): +*/ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->_size); + __pyx_r = __pyx_v_self->_size; + goto __pyx_L0; + + /* "View.MemoryView":608 + * return self.size * self.view.itemsize + * + * @property # <<<<<<<<<<<<<< + * def size(self): + * if self._size is None: +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("View.MemoryView.memoryview.size.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_result); + __Pyx_XDECREF(__pyx_v_length); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":620 + * return self._size + * + * def __len__(self): # <<<<<<<<<<<<<< + * if self.view.ndim >= 1: + * return self.view.shape[0] +*/ + +/* Python wrapper */ +static Py_ssize_t __pyx_memoryview___len__(PyObject *__pyx_v_self); /*proto*/ +static Py_ssize_t __pyx_memoryview___len__(PyObject *__pyx_v_self) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + Py_ssize_t __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__len__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_r = __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_10__len__(((struct __pyx_memoryview_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static Py_ssize_t __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_10__len__(struct __pyx_memoryview_obj *__pyx_v_self) { + Py_ssize_t __pyx_r; + int __pyx_t_1; + + /* "View.MemoryView":621 + * + * def __len__(self): + * if self.view.ndim >= 1: # <<<<<<<<<<<<<< + * return self.view.shape[0] + * +*/ + __pyx_t_1 = (__pyx_v_self->view.ndim >= 1); + if (__pyx_t_1) { + + /* "View.MemoryView":622 + * def __len__(self): + * if self.view.ndim >= 1: + * return self.view.shape[0] # <<<<<<<<<<<<<< + * + * return 0 +*/ + __pyx_r = (__pyx_v_self->view.shape[0]); + goto __pyx_L0; + + /* "View.MemoryView":621 + * + * def __len__(self): + * if self.view.ndim >= 1: # <<<<<<<<<<<<<< + * return self.view.shape[0] + * +*/ + } + + /* "View.MemoryView":624 + * return self.view.shape[0] + * + * return 0 # <<<<<<<<<<<<<< + * + * def __repr__(self): +*/ + __pyx_r = 0; + goto __pyx_L0; + + /* "View.MemoryView":620 + * return self._size + * + * def __len__(self): # <<<<<<<<<<<<<< + * if self.view.ndim >= 1: + * return self.view.shape[0] +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "View.MemoryView":626 + * return 0 + * + * def __repr__(self): # <<<<<<<<<<<<<< + * return "" % (self.base.__class__.__name__, + * id(self)) +*/ + +/* Python wrapper */ +static PyObject *__pyx_memoryview___repr__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_memoryview___repr__(PyObject *__pyx_v_self) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__repr__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_r = __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_12__repr__(((struct __pyx_memoryview_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_12__repr__(struct __pyx_memoryview_obj *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4[5]; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__repr__", 0); + + /* "View.MemoryView":627 + * + * def __repr__(self): + * return "" % (self.base.__class__.__name__, # <<<<<<<<<<<<<< + * id(self)) + * +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_mstate_global->__pyx_n_u_base); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 627, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_class); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 627, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_name_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 627, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_PyObject_FormatSimpleAndDecref(PyObject_Repr(__pyx_t_1), __pyx_mstate_global->__pyx_empty_unicode); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 627, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "View.MemoryView":628 + * def __repr__(self): + * return "" % (self.base.__class__.__name__, + * id(self)) # <<<<<<<<<<<<<< + * + * def __str__(self): +*/ + __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 628, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = __Pyx_PyObject_Format(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_x); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 628, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_4[0] = __pyx_mstate_global->__pyx_kp_u_MemoryView_of; + __pyx_t_4[1] = __pyx_t_2; + __pyx_t_4[2] = __pyx_mstate_global->__pyx_kp_u_at_0x; + __pyx_t_4[3] = __pyx_t_3; + __pyx_t_4[4] = __pyx_mstate_global->__pyx_kp_u__3; + + /* "View.MemoryView":627 + * + * def __repr__(self): + * return "" % (self.base.__class__.__name__, # <<<<<<<<<<<<<< + * id(self)) + * +*/ + __pyx_t_1 = __Pyx_PyUnicode_Join(__pyx_t_4, 5, 15 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_2) + 6 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_3) + 1, 127 | __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_2) | __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_3)); + if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 627, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "View.MemoryView":626 + * return 0 + * + * def __repr__(self): # <<<<<<<<<<<<<< + * return "" % (self.base.__class__.__name__, + * id(self)) +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_AddTraceback("View.MemoryView.memoryview.__repr__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":630 + * id(self)) + * + * def __str__(self): # <<<<<<<<<<<<<< + * return "" % (self.base.__class__.__name__,) + * +*/ + +/* Python wrapper */ +static PyObject *__pyx_memoryview___str__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_memoryview___str__(PyObject *__pyx_v_self) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__str__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_r = __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_14__str__(((struct __pyx_memoryview_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_14__str__(struct __pyx_memoryview_obj *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3[3]; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__str__", 0); + + /* "View.MemoryView":631 + * + * def __str__(self): + * return "" % (self.base.__class__.__name__,) # <<<<<<<<<<<<<< + * + * +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_mstate_global->__pyx_n_u_base); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 631, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_class); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 631, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_name_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 631, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_PyObject_FormatSimpleAndDecref(PyObject_Repr(__pyx_t_1), __pyx_mstate_global->__pyx_empty_unicode); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 631, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_3[0] = __pyx_mstate_global->__pyx_kp_u_MemoryView_of; + __pyx_t_3[1] = __pyx_t_2; + __pyx_t_3[2] = __pyx_mstate_global->__pyx_kp_u_object; + __pyx_t_1 = __Pyx_PyUnicode_Join(__pyx_t_3, 3, 15 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_2) + 8, 127 | __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_2)); + if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 631, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "View.MemoryView":630 + * id(self)) + * + * def __str__(self): # <<<<<<<<<<<<<< + * return "" % (self.base.__class__.__name__,) + * +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("View.MemoryView.memoryview.__str__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":634 + * + * + * def is_c_contig(self): # <<<<<<<<<<<<<< + * cdef __Pyx_memviewslice *mslice + * cdef __Pyx_memviewslice tmp +*/ + +/* Python wrapper */ +static PyObject *__pyx_memoryview_is_c_contig(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +); /*proto*/ +static PyObject *__pyx_memoryview_is_c_contig(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +) { + #if !CYTHON_METH_FASTCALL + CYTHON_UNUSED Py_ssize_t __pyx_nargs; + #endif + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("is_c_contig (wrapper)", 0); + #if !CYTHON_METH_FASTCALL + #if CYTHON_ASSUME_SAFE_SIZE + __pyx_nargs = PyTuple_GET_SIZE(__pyx_args); + #else + __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL; + #endif + #endif + __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs); + if (unlikely(__pyx_nargs > 0)) { __Pyx_RaiseArgtupleInvalid("is_c_contig", 1, 0, 0, __pyx_nargs); return NULL; } + const Py_ssize_t __pyx_kwds_len = unlikely(__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0; + if (unlikely(__pyx_kwds_len < 0)) return NULL; + if (unlikely(__pyx_kwds_len > 0)) {__Pyx_RejectKeywords("is_c_contig", __pyx_kwds); return NULL;} + __pyx_r = __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_16is_c_contig(((struct __pyx_memoryview_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_16is_c_contig(struct __pyx_memoryview_obj *__pyx_v_self) { + __Pyx_memviewslice *__pyx_v_mslice; + __Pyx_memviewslice __pyx_v_tmp; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_memviewslice *__pyx_t_1; + PyObject *__pyx_t_2 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("is_c_contig", 0); + + /* "View.MemoryView":637 + * cdef __Pyx_memviewslice *mslice + * cdef __Pyx_memviewslice tmp + * mslice = get_slice_from_memview(self, &tmp) # <<<<<<<<<<<<<< + * return slice_is_contig(mslice[0], 'C', self.view.ndim) + * +*/ + __pyx_t_1 = __pyx_memoryview_get_slice_from_memoryview(__pyx_v_self, (&__pyx_v_tmp)); if (unlikely(__pyx_t_1 == ((void *)NULL))) __PYX_ERR(1, 637, __pyx_L1_error) + __pyx_v_mslice = __pyx_t_1; + + /* "View.MemoryView":638 + * cdef __Pyx_memviewslice tmp + * mslice = get_slice_from_memview(self, &tmp) + * return slice_is_contig(mslice[0], 'C', self.view.ndim) # <<<<<<<<<<<<<< + * + * def is_f_contig(self): +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_2 = __Pyx_PyBool_FromLong(__pyx_memviewslice_is_contig((__pyx_v_mslice[0]), 'C', __pyx_v_self->view.ndim)); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 638, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + goto __pyx_L0; + + /* "View.MemoryView":634 + * + * + * def is_c_contig(self): # <<<<<<<<<<<<<< + * cdef __Pyx_memviewslice *mslice + * cdef __Pyx_memviewslice tmp +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("View.MemoryView.memoryview.is_c_contig", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":640 + * return slice_is_contig(mslice[0], 'C', self.view.ndim) + * + * def is_f_contig(self): # <<<<<<<<<<<<<< + * cdef __Pyx_memviewslice *mslice + * cdef __Pyx_memviewslice tmp +*/ + +/* Python wrapper */ +static PyObject *__pyx_memoryview_is_f_contig(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +); /*proto*/ +static PyObject *__pyx_memoryview_is_f_contig(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +) { + #if !CYTHON_METH_FASTCALL + CYTHON_UNUSED Py_ssize_t __pyx_nargs; + #endif + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("is_f_contig (wrapper)", 0); + #if !CYTHON_METH_FASTCALL + #if CYTHON_ASSUME_SAFE_SIZE + __pyx_nargs = PyTuple_GET_SIZE(__pyx_args); + #else + __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL; + #endif + #endif + __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs); + if (unlikely(__pyx_nargs > 0)) { __Pyx_RaiseArgtupleInvalid("is_f_contig", 1, 0, 0, __pyx_nargs); return NULL; } + const Py_ssize_t __pyx_kwds_len = unlikely(__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0; + if (unlikely(__pyx_kwds_len < 0)) return NULL; + if (unlikely(__pyx_kwds_len > 0)) {__Pyx_RejectKeywords("is_f_contig", __pyx_kwds); return NULL;} + __pyx_r = __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_18is_f_contig(((struct __pyx_memoryview_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_18is_f_contig(struct __pyx_memoryview_obj *__pyx_v_self) { + __Pyx_memviewslice *__pyx_v_mslice; + __Pyx_memviewslice __pyx_v_tmp; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_memviewslice *__pyx_t_1; + PyObject *__pyx_t_2 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("is_f_contig", 0); + + /* "View.MemoryView":643 + * cdef __Pyx_memviewslice *mslice + * cdef __Pyx_memviewslice tmp + * mslice = get_slice_from_memview(self, &tmp) # <<<<<<<<<<<<<< + * return slice_is_contig(mslice[0], 'F', self.view.ndim) + * +*/ + __pyx_t_1 = __pyx_memoryview_get_slice_from_memoryview(__pyx_v_self, (&__pyx_v_tmp)); if (unlikely(__pyx_t_1 == ((void *)NULL))) __PYX_ERR(1, 643, __pyx_L1_error) + __pyx_v_mslice = __pyx_t_1; + + /* "View.MemoryView":644 + * cdef __Pyx_memviewslice tmp + * mslice = get_slice_from_memview(self, &tmp) + * return slice_is_contig(mslice[0], 'F', self.view.ndim) # <<<<<<<<<<<<<< + * + * def copy(self): +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_2 = __Pyx_PyBool_FromLong(__pyx_memviewslice_is_contig((__pyx_v_mslice[0]), 'F', __pyx_v_self->view.ndim)); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 644, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + goto __pyx_L0; + + /* "View.MemoryView":640 + * return slice_is_contig(mslice[0], 'C', self.view.ndim) + * + * def is_f_contig(self): # <<<<<<<<<<<<<< + * cdef __Pyx_memviewslice *mslice + * cdef __Pyx_memviewslice tmp +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("View.MemoryView.memoryview.is_f_contig", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":646 + * return slice_is_contig(mslice[0], 'F', self.view.ndim) + * + * def copy(self): # <<<<<<<<<<<<<< + * cdef __Pyx_memviewslice mslice + * cdef int flags = self.flags & ~PyBUF_F_CONTIGUOUS +*/ + +/* Python wrapper */ +static PyObject *__pyx_memoryview_copy(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +); /*proto*/ +static PyObject *__pyx_memoryview_copy(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +) { + #if !CYTHON_METH_FASTCALL + CYTHON_UNUSED Py_ssize_t __pyx_nargs; + #endif + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("copy (wrapper)", 0); + #if !CYTHON_METH_FASTCALL + #if CYTHON_ASSUME_SAFE_SIZE + __pyx_nargs = PyTuple_GET_SIZE(__pyx_args); + #else + __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL; + #endif + #endif + __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs); + if (unlikely(__pyx_nargs > 0)) { __Pyx_RaiseArgtupleInvalid("copy", 1, 0, 0, __pyx_nargs); return NULL; } + const Py_ssize_t __pyx_kwds_len = unlikely(__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0; + if (unlikely(__pyx_kwds_len < 0)) return NULL; + if (unlikely(__pyx_kwds_len > 0)) {__Pyx_RejectKeywords("copy", __pyx_kwds); return NULL;} + __pyx_r = __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_20copy(((struct __pyx_memoryview_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_20copy(struct __pyx_memoryview_obj *__pyx_v_self) { + __Pyx_memviewslice __pyx_v_mslice; + int __pyx_v_flags; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_memviewslice __pyx_t_1; + PyObject *__pyx_t_2 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("copy", 0); + + /* "View.MemoryView":648 + * def copy(self): + * cdef __Pyx_memviewslice mslice + * cdef int flags = self.flags & ~PyBUF_F_CONTIGUOUS # <<<<<<<<<<<<<< + * + * slice_copy(self, &mslice) +*/ + __pyx_v_flags = (__pyx_v_self->flags & (~PyBUF_F_CONTIGUOUS)); + + /* "View.MemoryView":650 + * cdef int flags = self.flags & ~PyBUF_F_CONTIGUOUS + * + * slice_copy(self, &mslice) # <<<<<<<<<<<<<< + * mslice = slice_copy_contig(&mslice, "c", self.view.ndim, + * self.view.itemsize, +*/ + __pyx_memoryview_slice_copy(__pyx_v_self, (&__pyx_v_mslice)); + + /* "View.MemoryView":651 + * + * slice_copy(self, &mslice) + * mslice = slice_copy_contig(&mslice, "c", self.view.ndim, # <<<<<<<<<<<<<< + * self.view.itemsize, + * flags|PyBUF_C_CONTIGUOUS, +*/ + __pyx_t_1 = __pyx_memoryview_copy_new_contig((&__pyx_v_mslice), __pyx_k_c, __pyx_v_self->view.ndim, __pyx_v_self->view.itemsize, (__pyx_v_flags | PyBUF_C_CONTIGUOUS), __pyx_v_self->dtype_is_object); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 651, __pyx_L1_error) + __pyx_v_mslice = __pyx_t_1; + + /* "View.MemoryView":656 + * self.dtype_is_object) + * + * return memoryview_copy_from_slice(self, &mslice) # <<<<<<<<<<<<<< + * + * def copy_fortran(self): +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_2 = __pyx_memoryview_copy_object_from_slice(__pyx_v_self, (&__pyx_v_mslice)); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 656, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + goto __pyx_L0; + + /* "View.MemoryView":646 + * return slice_is_contig(mslice[0], 'F', self.view.ndim) + * + * def copy(self): # <<<<<<<<<<<<<< + * cdef __Pyx_memviewslice mslice + * cdef int flags = self.flags & ~PyBUF_F_CONTIGUOUS +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("View.MemoryView.memoryview.copy", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":658 + * return memoryview_copy_from_slice(self, &mslice) + * + * def copy_fortran(self): # <<<<<<<<<<<<<< + * cdef __Pyx_memviewslice src, dst + * cdef int flags = self.flags & ~PyBUF_C_CONTIGUOUS +*/ + +/* Python wrapper */ +static PyObject *__pyx_memoryview_copy_fortran(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +); /*proto*/ +static PyObject *__pyx_memoryview_copy_fortran(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +) { + #if !CYTHON_METH_FASTCALL + CYTHON_UNUSED Py_ssize_t __pyx_nargs; + #endif + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("copy_fortran (wrapper)", 0); + #if !CYTHON_METH_FASTCALL + #if CYTHON_ASSUME_SAFE_SIZE + __pyx_nargs = PyTuple_GET_SIZE(__pyx_args); + #else + __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL; + #endif + #endif + __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs); + if (unlikely(__pyx_nargs > 0)) { __Pyx_RaiseArgtupleInvalid("copy_fortran", 1, 0, 0, __pyx_nargs); return NULL; } + const Py_ssize_t __pyx_kwds_len = unlikely(__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0; + if (unlikely(__pyx_kwds_len < 0)) return NULL; + if (unlikely(__pyx_kwds_len > 0)) {__Pyx_RejectKeywords("copy_fortran", __pyx_kwds); return NULL;} + __pyx_r = __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_22copy_fortran(((struct __pyx_memoryview_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_22copy_fortran(struct __pyx_memoryview_obj *__pyx_v_self) { + __Pyx_memviewslice __pyx_v_src; + __Pyx_memviewslice __pyx_v_dst; + int __pyx_v_flags; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_memviewslice __pyx_t_1; + PyObject *__pyx_t_2 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("copy_fortran", 0); + + /* "View.MemoryView":660 + * def copy_fortran(self): + * cdef __Pyx_memviewslice src, dst + * cdef int flags = self.flags & ~PyBUF_C_CONTIGUOUS # <<<<<<<<<<<<<< + * + * slice_copy(self, &src) +*/ + __pyx_v_flags = (__pyx_v_self->flags & (~PyBUF_C_CONTIGUOUS)); + + /* "View.MemoryView":662 + * cdef int flags = self.flags & ~PyBUF_C_CONTIGUOUS + * + * slice_copy(self, &src) # <<<<<<<<<<<<<< + * dst = slice_copy_contig(&src, "fortran", self.view.ndim, + * self.view.itemsize, +*/ + __pyx_memoryview_slice_copy(__pyx_v_self, (&__pyx_v_src)); + + /* "View.MemoryView":663 + * + * slice_copy(self, &src) + * dst = slice_copy_contig(&src, "fortran", self.view.ndim, # <<<<<<<<<<<<<< + * self.view.itemsize, + * flags|PyBUF_F_CONTIGUOUS, +*/ + __pyx_t_1 = __pyx_memoryview_copy_new_contig((&__pyx_v_src), __pyx_k_fortran, __pyx_v_self->view.ndim, __pyx_v_self->view.itemsize, (__pyx_v_flags | PyBUF_F_CONTIGUOUS), __pyx_v_self->dtype_is_object); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 663, __pyx_L1_error) + __pyx_v_dst = __pyx_t_1; + + /* "View.MemoryView":668 + * self.dtype_is_object) + * + * return memoryview_copy_from_slice(self, &dst) # <<<<<<<<<<<<<< + * + * +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_2 = __pyx_memoryview_copy_object_from_slice(__pyx_v_self, (&__pyx_v_dst)); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 668, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + goto __pyx_L0; + + /* "View.MemoryView":658 + * return memoryview_copy_from_slice(self, &mslice) + * + * def copy_fortran(self): # <<<<<<<<<<<<<< + * cdef __Pyx_memviewslice src, dst + * cdef int flags = self.flags & ~PyBUF_C_CONTIGUOUS +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("View.MemoryView.memoryview.copy_fortran", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" + * def __setstate_cython__(self, __pyx_state): +*/ + +/* Python wrapper */ +static PyObject *__pyx_pw___pyx_memoryview_1__reduce_cython__(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +); /*proto*/ +static PyObject *__pyx_pw___pyx_memoryview_1__reduce_cython__(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +) { + #if !CYTHON_METH_FASTCALL + CYTHON_UNUSED Py_ssize_t __pyx_nargs; + #endif + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); + #if !CYTHON_METH_FASTCALL + #if CYTHON_ASSUME_SAFE_SIZE + __pyx_nargs = PyTuple_GET_SIZE(__pyx_args); + #else + __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL; + #endif + #endif + __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs); + if (unlikely(__pyx_nargs > 0)) { __Pyx_RaiseArgtupleInvalid("__reduce_cython__", 1, 0, 0, __pyx_nargs); return NULL; } + const Py_ssize_t __pyx_kwds_len = unlikely(__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0; + if (unlikely(__pyx_kwds_len < 0)) return NULL; + if (unlikely(__pyx_kwds_len > 0)) {__Pyx_RejectKeywords("__reduce_cython__", __pyx_kwds); return NULL;} + __pyx_r = __pyx_pf___pyx_memoryview___reduce_cython__(((struct __pyx_memoryview_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf___pyx_memoryview___reduce_cython__(CYTHON_UNUSED struct __pyx_memoryview_obj *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__reduce_cython__", 0); + + /* "(tree fragment)":2 + * def __reduce_cython__(self): + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" # <<<<<<<<<<<<<< + * def __setstate_cython__(self, __pyx_state): + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" +*/ + __Pyx_Raise(((PyObject *)(((PyTypeObject*)PyExc_TypeError))), __pyx_mstate_global->__pyx_kp_u_no_default___reduce___due_to_non, 0, 0); + __PYX_ERR(1, 2, __pyx_L1_error) + + /* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" + * def __setstate_cython__(self, __pyx_state): +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_AddTraceback("View.MemoryView.memoryview.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":3 + * def __reduce_cython__(self): + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" +*/ + +/* Python wrapper */ +static PyObject *__pyx_pw___pyx_memoryview_3__setstate_cython__(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +); /*proto*/ +static PyObject *__pyx_pw___pyx_memoryview_3__setstate_cython__(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +) { + CYTHON_UNUSED PyObject *__pyx_v___pyx_state = 0; + #if !CYTHON_METH_FASTCALL + CYTHON_UNUSED Py_ssize_t __pyx_nargs; + #endif + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject* values[1] = {0}; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); + #if !CYTHON_METH_FASTCALL + #if CYTHON_ASSUME_SAFE_SIZE + __pyx_nargs = PyTuple_GET_SIZE(__pyx_args); + #else + __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL; + #endif + #endif + __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs); + { + PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_pyx_state,0}; + const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0; + if (unlikely(__pyx_kwds_len < 0)) __PYX_ERR(1, 3, __pyx_L3_error) + if (__pyx_kwds_len > 0) { + switch (__pyx_nargs) { + case 1: + values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(1, 3, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + const Py_ssize_t kwd_pos_args = __pyx_nargs; + if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "__setstate_cython__", 0) < (0)) __PYX_ERR(1, 3, __pyx_L3_error) + for (Py_ssize_t i = __pyx_nargs; i < 1; i++) { + if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("__setstate_cython__", 1, 1, 1, i); __PYX_ERR(1, 3, __pyx_L3_error) } + } + } else if (unlikely(__pyx_nargs != 1)) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(1, 3, __pyx_L3_error) + } + __pyx_v___pyx_state = values[0]; + } + goto __pyx_L6_skip; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__setstate_cython__", 1, 1, 1, __pyx_nargs); __PYX_ERR(1, 3, __pyx_L3_error) + __pyx_L6_skip:; + goto __pyx_L4_argument_unpacking_done; + __pyx_L3_error:; + for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { + Py_XDECREF(values[__pyx_temp]); + } + __Pyx_AddTraceback("View.MemoryView.memoryview.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf___pyx_memoryview_2__setstate_cython__(((struct __pyx_memoryview_obj *)__pyx_v_self), __pyx_v___pyx_state); + + /* function exit code */ + for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { + Py_XDECREF(values[__pyx_temp]); + } + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf___pyx_memoryview_2__setstate_cython__(CYTHON_UNUSED struct __pyx_memoryview_obj *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__setstate_cython__", 0); + + /* "(tree fragment)":4 + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" + * def __setstate_cython__(self, __pyx_state): + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" # <<<<<<<<<<<<<< +*/ + __Pyx_Raise(((PyObject *)(((PyTypeObject*)PyExc_TypeError))), __pyx_mstate_global->__pyx_kp_u_no_default___reduce___due_to_non, 0, 0); + __PYX_ERR(1, 4, __pyx_L1_error) + + /* "(tree fragment)":3 + * def __reduce_cython__(self): + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_AddTraceback("View.MemoryView.memoryview.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":671 + * + * + * @cname('__pyx_memoryview_new') # <<<<<<<<<<<<<< + * cdef memoryview_cwrapper(object o, int flags, bint dtype_is_object, const __Pyx_TypeInfo *typeinfo): + * cdef memoryview result = memoryview(o, flags, dtype_is_object) +*/ + +static PyObject *__pyx_memoryview_new(PyObject *__pyx_v_o, int __pyx_v_flags, int __pyx_v_dtype_is_object, __Pyx_TypeInfo const *__pyx_v_typeinfo) { + struct __pyx_memoryview_obj *__pyx_v_result = 0; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + size_t __pyx_t_5; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("memoryview_cwrapper", 0); + + /* "View.MemoryView":673 + * @cname('__pyx_memoryview_new') + * cdef memoryview_cwrapper(object o, int flags, bint dtype_is_object, const __Pyx_TypeInfo *typeinfo): + * cdef memoryview result = memoryview(o, flags, dtype_is_object) # <<<<<<<<<<<<<< + * result.typeinfo = typeinfo + * return result +*/ + __pyx_t_2 = NULL; + __pyx_t_3 = __Pyx_PyLong_From_int(__pyx_v_flags); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 673, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = __Pyx_PyBool_FromLong(__pyx_v_dtype_is_object); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 673, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = 1; + { + PyObject *__pyx_callargs[4] = {__pyx_t_2, __pyx_v_o, __pyx_t_3, __pyx_t_4}; + __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_mstate_global->__pyx_memoryview_type, __pyx_callargs+__pyx_t_5, (4-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 673, __pyx_L1_error) + __Pyx_GOTREF((PyObject *)__pyx_t_1); + } + __pyx_v_result = ((struct __pyx_memoryview_obj *)__pyx_t_1); + __pyx_t_1 = 0; + + /* "View.MemoryView":674 + * cdef memoryview_cwrapper(object o, int flags, bint dtype_is_object, const __Pyx_TypeInfo *typeinfo): + * cdef memoryview result = memoryview(o, flags, dtype_is_object) + * result.typeinfo = typeinfo # <<<<<<<<<<<<<< + * return result + * +*/ + __pyx_v_result->typeinfo = __pyx_v_typeinfo; + + /* "View.MemoryView":675 + * cdef memoryview result = memoryview(o, flags, dtype_is_object) + * result.typeinfo = typeinfo + * return result # <<<<<<<<<<<<<< + * + * @cname('__pyx_memoryview_check') +*/ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF((PyObject *)__pyx_v_result); + __pyx_r = ((PyObject *)__pyx_v_result); + goto __pyx_L0; + + /* "View.MemoryView":671 + * + * + * @cname('__pyx_memoryview_new') # <<<<<<<<<<<<<< + * cdef memoryview_cwrapper(object o, int flags, bint dtype_is_object, const __Pyx_TypeInfo *typeinfo): + * cdef memoryview result = memoryview(o, flags, dtype_is_object) +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_AddTraceback("View.MemoryView.memoryview_cwrapper", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF((PyObject *)__pyx_v_result); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":677 + * return result + * + * @cname('__pyx_memoryview_check') # <<<<<<<<<<<<<< + * cdef inline bint memoryview_check(object o) noexcept: + * return isinstance(o, memoryview) +*/ + +static CYTHON_INLINE int __pyx_memoryview_check(PyObject *__pyx_v_o) { + int __pyx_r; + int __pyx_t_1; + + /* "View.MemoryView":679 + * @cname('__pyx_memoryview_check') + * cdef inline bint memoryview_check(object o) noexcept: + * return isinstance(o, memoryview) # <<<<<<<<<<<<<< + * + * cdef tuple _unellipsify(object index, int ndim): +*/ + __pyx_t_1 = __Pyx_TypeCheck(__pyx_v_o, __pyx_mstate_global->__pyx_memoryview_type); + __pyx_r = __pyx_t_1; + goto __pyx_L0; + + /* "View.MemoryView":677 + * return result + * + * @cname('__pyx_memoryview_check') # <<<<<<<<<<<<<< + * cdef inline bint memoryview_check(object o) noexcept: + * return isinstance(o, memoryview) +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "View.MemoryView":681 + * return isinstance(o, memoryview) + * + * cdef tuple _unellipsify(object index, int ndim): # <<<<<<<<<<<<<< + * """ + * Replace all ellipses with full slices and fill incomplete indices with +*/ + +static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { + Py_ssize_t __pyx_v_idx; + PyObject *__pyx_v_tup = NULL; + PyObject *__pyx_v_result = NULL; + int __pyx_v_have_slices; + int __pyx_v_seen_ellipsis; + PyObject *__pyx_v_item = NULL; + Py_ssize_t __pyx_v_nslices; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + PyObject *__pyx_t_3 = NULL; + Py_ssize_t __pyx_t_4; + Py_ssize_t __pyx_t_5; + PyObject *__pyx_t_6[3]; + PyObject *__pyx_t_7 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("_unellipsify", 0); + + /* "View.MemoryView":687 + * """ + * cdef Py_ssize_t idx + * tup = index if isinstance(index, tuple) else (index,) # <<<<<<<<<<<<<< + * + * result = [slice(None)] * ndim +*/ + __pyx_t_2 = PyTuple_Check(__pyx_v_index); + if (__pyx_t_2) { + __Pyx_INCREF(((PyObject*)__pyx_v_index)); + __pyx_t_1 = __pyx_v_index; + } else { + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 687, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(__pyx_v_index); + __Pyx_GIVEREF(__pyx_v_index); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_index) != (0)) __PYX_ERR(1, 687, __pyx_L1_error); + __pyx_t_1 = __pyx_t_3; + __pyx_t_3 = 0; + } + __pyx_v_tup = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "View.MemoryView":689 + * tup = index if isinstance(index, tuple) else (index,) + * + * result = [slice(None)] * ndim # <<<<<<<<<<<<<< + * have_slices = False + * seen_ellipsis = False +*/ + __pyx_t_1 = PyList_New(1 * ((__pyx_v_ndim<0) ? 0:__pyx_v_ndim)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 689, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + { Py_ssize_t __pyx_temp; + for (__pyx_temp=0; __pyx_temp < __pyx_v_ndim; __pyx_temp++) { + __Pyx_INCREF(__pyx_mstate_global->__pyx_slice[0]); + __Pyx_GIVEREF(__pyx_mstate_global->__pyx_slice[0]); + if (__Pyx_PyList_SET_ITEM(__pyx_t_1, __pyx_temp, __pyx_mstate_global->__pyx_slice[0]) != (0)) __PYX_ERR(1, 689, __pyx_L1_error); + } + } + __pyx_v_result = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "View.MemoryView":690 + * + * result = [slice(None)] * ndim + * have_slices = False # <<<<<<<<<<<<<< + * seen_ellipsis = False + * idx = 0 +*/ + __pyx_v_have_slices = 0; + + /* "View.MemoryView":691 + * result = [slice(None)] * ndim + * have_slices = False + * seen_ellipsis = False # <<<<<<<<<<<<<< + * idx = 0 + * for item in tup: +*/ + __pyx_v_seen_ellipsis = 0; + + /* "View.MemoryView":692 + * have_slices = False + * seen_ellipsis = False + * idx = 0 # <<<<<<<<<<<<<< + * for item in tup: + * if item is Ellipsis: +*/ + __pyx_v_idx = 0; + + /* "View.MemoryView":693 + * seen_ellipsis = False + * idx = 0 + * for item in tup: # <<<<<<<<<<<<<< + * if item is Ellipsis: + * if not seen_ellipsis: +*/ + if (unlikely(__pyx_v_tup == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); + __PYX_ERR(1, 693, __pyx_L1_error) + } + __pyx_t_1 = __pyx_v_tup; __Pyx_INCREF(__pyx_t_1); + __pyx_t_4 = 0; + for (;;) { + { + Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_1); + #if !CYTHON_ASSUME_SAFE_SIZE + if (unlikely((__pyx_temp < 0))) __PYX_ERR(1, 693, __pyx_L1_error) + #endif + if (__pyx_t_4 >= __pyx_temp) break; + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_3 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_4)); + #else + __pyx_t_3 = __Pyx_PySequence_ITEM(__pyx_t_1, __pyx_t_4); + #endif + ++__pyx_t_4; + if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 693, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_XDECREF_SET(__pyx_v_item, __pyx_t_3); + __pyx_t_3 = 0; + + /* "View.MemoryView":694 + * idx = 0 + * for item in tup: + * if item is Ellipsis: # <<<<<<<<<<<<<< + * if not seen_ellipsis: + * idx += ndim - len(tup) +*/ + __pyx_t_2 = (__pyx_v_item == __pyx_builtin_Ellipsis); + if (__pyx_t_2) { + + /* "View.MemoryView":695 + * for item in tup: + * if item is Ellipsis: + * if not seen_ellipsis: # <<<<<<<<<<<<<< + * idx += ndim - len(tup) + * seen_ellipsis = True +*/ + __pyx_t_2 = (!__pyx_v_seen_ellipsis); + if (__pyx_t_2) { + + /* "View.MemoryView":696 + * if item is Ellipsis: + * if not seen_ellipsis: + * idx += ndim - len(tup) # <<<<<<<<<<<<<< + * seen_ellipsis = True + * have_slices = True +*/ + if (unlikely(__pyx_v_tup == Py_None)) { + PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); + __PYX_ERR(1, 696, __pyx_L1_error) + } + __pyx_t_5 = __Pyx_PyTuple_GET_SIZE(__pyx_v_tup); if (unlikely(__pyx_t_5 == ((Py_ssize_t)-1))) __PYX_ERR(1, 696, __pyx_L1_error) + __pyx_v_idx = (__pyx_v_idx + (__pyx_v_ndim - __pyx_t_5)); + + /* "View.MemoryView":697 + * if not seen_ellipsis: + * idx += ndim - len(tup) + * seen_ellipsis = True # <<<<<<<<<<<<<< + * have_slices = True + * else: +*/ + __pyx_v_seen_ellipsis = 1; + + /* "View.MemoryView":695 + * for item in tup: + * if item is Ellipsis: + * if not seen_ellipsis: # <<<<<<<<<<<<<< + * idx += ndim - len(tup) + * seen_ellipsis = True +*/ + } + + /* "View.MemoryView":698 + * idx += ndim - len(tup) + * seen_ellipsis = True + * have_slices = True # <<<<<<<<<<<<<< + * else: + * if isinstance(item, slice): +*/ + __pyx_v_have_slices = 1; + + /* "View.MemoryView":694 + * idx = 0 + * for item in tup: + * if item is Ellipsis: # <<<<<<<<<<<<<< + * if not seen_ellipsis: + * idx += ndim - len(tup) +*/ + goto __pyx_L5; + } + + /* "View.MemoryView":700 + * have_slices = True + * else: + * if isinstance(item, slice): # <<<<<<<<<<<<<< + * have_slices = True + * elif not PyIndex_Check(item): +*/ + /*else*/ { + __pyx_t_2 = PySlice_Check(__pyx_v_item); + if (__pyx_t_2) { + + /* "View.MemoryView":701 + * else: + * if isinstance(item, slice): + * have_slices = True # <<<<<<<<<<<<<< + * elif not PyIndex_Check(item): + * raise TypeError, f"Cannot index with type '{type(item)}'" +*/ + __pyx_v_have_slices = 1; + + /* "View.MemoryView":700 + * have_slices = True + * else: + * if isinstance(item, slice): # <<<<<<<<<<<<<< + * have_slices = True + * elif not PyIndex_Check(item): +*/ + goto __pyx_L7; + } + + /* "View.MemoryView":702 + * if isinstance(item, slice): + * have_slices = True + * elif not PyIndex_Check(item): # <<<<<<<<<<<<<< + * raise TypeError, f"Cannot index with type '{type(item)}'" + * result[idx] = item +*/ + __pyx_t_2 = (!(PyIndex_Check(__pyx_v_item) != 0)); + if (unlikely(__pyx_t_2)) { + + /* "View.MemoryView":703 + * have_slices = True + * elif not PyIndex_Check(item): + * raise TypeError, f"Cannot index with type '{type(item)}'" # <<<<<<<<<<<<<< + * result[idx] = item + * idx += 1 +*/ + __pyx_t_3 = __Pyx_PyObject_FormatSimple(((PyObject *)Py_TYPE(__pyx_v_item)), __pyx_mstate_global->__pyx_empty_unicode); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 703, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_6[0] = __pyx_mstate_global->__pyx_kp_u_Cannot_index_with_type; + __pyx_t_6[1] = __pyx_t_3; + __pyx_t_6[2] = __pyx_mstate_global->__pyx_kp_u__4; + __pyx_t_7 = __Pyx_PyUnicode_Join(__pyx_t_6, 3, 24 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_3) + 1, 127 | __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_3)); + if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 703, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_Raise(((PyObject *)(((PyTypeObject*)PyExc_TypeError))), __pyx_t_7, 0, 0); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __PYX_ERR(1, 703, __pyx_L1_error) + + /* "View.MemoryView":702 + * if isinstance(item, slice): + * have_slices = True + * elif not PyIndex_Check(item): # <<<<<<<<<<<<<< + * raise TypeError, f"Cannot index with type '{type(item)}'" + * result[idx] = item +*/ + } + __pyx_L7:; + + /* "View.MemoryView":704 + * elif not PyIndex_Check(item): + * raise TypeError, f"Cannot index with type '{type(item)}'" + * result[idx] = item # <<<<<<<<<<<<<< + * idx += 1 + * +*/ + if (unlikely((__Pyx_SetItemInt(__pyx_v_result, __pyx_v_idx, __pyx_v_item, Py_ssize_t, 1, PyLong_FromSsize_t, 1, 1, 1, 1, __Pyx_ReferenceSharing_OwnStrongReference) < 0))) __PYX_ERR(1, 704, __pyx_L1_error) + } + __pyx_L5:; + + /* "View.MemoryView":705 + * raise TypeError, f"Cannot index with type '{type(item)}'" + * result[idx] = item + * idx += 1 # <<<<<<<<<<<<<< + * + * nslices = ndim - idx +*/ + __pyx_v_idx = (__pyx_v_idx + 1); + + /* "View.MemoryView":693 + * seen_ellipsis = False + * idx = 0 + * for item in tup: # <<<<<<<<<<<<<< + * if item is Ellipsis: + * if not seen_ellipsis: +*/ + } + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "View.MemoryView":707 + * idx += 1 + * + * nslices = ndim - idx # <<<<<<<<<<<<<< + * return have_slices or nslices, tuple(result) + * +*/ + __pyx_v_nslices = (__pyx_v_ndim - __pyx_v_idx); + + /* "View.MemoryView":708 + * + * nslices = ndim - idx + * return have_slices or nslices, tuple(result) # <<<<<<<<<<<<<< + * + * cdef int assert_direct_dimensions(Py_ssize_t *suboffsets, int ndim) except -1: +*/ + __Pyx_XDECREF(__pyx_r); + if (!__pyx_v_have_slices) { + } else { + __pyx_t_7 = __Pyx_PyBool_FromLong(__pyx_v_have_slices); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 708, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_1 = __pyx_t_7; + __pyx_t_7 = 0; + goto __pyx_L9_bool_binop_done; + } + __pyx_t_7 = PyLong_FromSsize_t(__pyx_v_nslices); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 708, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_1 = __pyx_t_7; + __pyx_t_7 = 0; + __pyx_L9_bool_binop_done:; + __pyx_t_7 = PyList_AsTuple(__pyx_v_result); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 708, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 708, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_GIVEREF(__pyx_t_1); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1) != (0)) __PYX_ERR(1, 708, __pyx_L1_error); + __Pyx_GIVEREF(__pyx_t_7); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_7) != (0)) __PYX_ERR(1, 708, __pyx_L1_error); + __pyx_t_1 = 0; + __pyx_t_7 = 0; + __pyx_r = ((PyObject*)__pyx_t_3); + __pyx_t_3 = 0; + goto __pyx_L0; + + /* "View.MemoryView":681 + * return isinstance(o, memoryview) + * + * cdef tuple _unellipsify(object index, int ndim): # <<<<<<<<<<<<<< + * """ + * Replace all ellipses with full slices and fill incomplete indices with +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_AddTraceback("View.MemoryView._unellipsify", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_tup); + __Pyx_XDECREF(__pyx_v_result); + __Pyx_XDECREF(__pyx_v_item); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":710 + * return have_slices or nslices, tuple(result) + * + * cdef int assert_direct_dimensions(Py_ssize_t *suboffsets, int ndim) except -1: # <<<<<<<<<<<<<< + * for suboffset in suboffsets[:ndim]: + * if suboffset >= 0: +*/ + +static int assert_direct_dimensions(Py_ssize_t *__pyx_v_suboffsets, int __pyx_v_ndim) { + Py_ssize_t __pyx_v_suboffset; + int __pyx_r; + Py_ssize_t *__pyx_t_1; + Py_ssize_t *__pyx_t_2; + Py_ssize_t *__pyx_t_3; + int __pyx_t_4; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + + /* "View.MemoryView":711 + * + * cdef int assert_direct_dimensions(Py_ssize_t *suboffsets, int ndim) except -1: + * for suboffset in suboffsets[:ndim]: # <<<<<<<<<<<<<< + * if suboffset >= 0: + * raise ValueError, "Indirect dimensions not supported" +*/ + __pyx_t_2 = (__pyx_v_suboffsets + __pyx_v_ndim); + for (__pyx_t_3 = __pyx_v_suboffsets; __pyx_t_3 < __pyx_t_2; __pyx_t_3++) { + __pyx_t_1 = __pyx_t_3; + __pyx_v_suboffset = (__pyx_t_1[0]); + + /* "View.MemoryView":712 + * cdef int assert_direct_dimensions(Py_ssize_t *suboffsets, int ndim) except -1: + * for suboffset in suboffsets[:ndim]: + * if suboffset >= 0: # <<<<<<<<<<<<<< + * raise ValueError, "Indirect dimensions not supported" + * return 0 # return type just used as an error flag +*/ + __pyx_t_4 = (__pyx_v_suboffset >= 0); + if (unlikely(__pyx_t_4)) { + + /* "View.MemoryView":713 + * for suboffset in suboffsets[:ndim]: + * if suboffset >= 0: + * raise ValueError, "Indirect dimensions not supported" # <<<<<<<<<<<<<< + * return 0 # return type just used as an error flag + * +*/ + __Pyx_Raise(((PyObject *)(((PyTypeObject*)PyExc_ValueError))), __pyx_mstate_global->__pyx_kp_u_Indirect_dimensions_not_supporte, 0, 0); + __PYX_ERR(1, 713, __pyx_L1_error) + + /* "View.MemoryView":712 + * cdef int assert_direct_dimensions(Py_ssize_t *suboffsets, int ndim) except -1: + * for suboffset in suboffsets[:ndim]: + * if suboffset >= 0: # <<<<<<<<<<<<<< + * raise ValueError, "Indirect dimensions not supported" + * return 0 # return type just used as an error flag +*/ + } + } + + /* "View.MemoryView":714 + * if suboffset >= 0: + * raise ValueError, "Indirect dimensions not supported" + * return 0 # return type just used as an error flag # <<<<<<<<<<<<<< + * + * +*/ + __pyx_r = 0; + goto __pyx_L0; + + /* "View.MemoryView":710 + * return have_slices or nslices, tuple(result) + * + * cdef int assert_direct_dimensions(Py_ssize_t *suboffsets, int ndim) except -1: # <<<<<<<<<<<<<< + * for suboffset in suboffsets[:ndim]: + * if suboffset >= 0: +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_AddTraceback("View.MemoryView.assert_direct_dimensions", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + return __pyx_r; +} + +/* "View.MemoryView":720 + * + * + * @cname('__pyx_memview_slice') # <<<<<<<<<<<<<< + * cdef memoryview memview_slice(memoryview memview, object indices): + * cdef int new_ndim = 0, suboffset_dim = -1, dim +*/ + +static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_obj *__pyx_v_memview, PyObject *__pyx_v_indices) { + int __pyx_v_new_ndim; + int __pyx_v_suboffset_dim; + int __pyx_v_dim; + __Pyx_memviewslice __pyx_v_src; + __Pyx_memviewslice __pyx_v_dst; + __Pyx_memviewslice *__pyx_v_p_src; + struct __pyx_memoryviewslice_obj *__pyx_v_memviewsliceobj = 0; + __Pyx_memviewslice *__pyx_v_p_dst; + int *__pyx_v_p_suboffset_dim; + Py_ssize_t __pyx_v_start; + Py_ssize_t __pyx_v_stop; + Py_ssize_t __pyx_v_step; + Py_ssize_t __pyx_v_cindex; + int __pyx_v_have_start; + int __pyx_v_have_stop; + int __pyx_v_have_step; + PyObject *__pyx_v_index = NULL; + struct __pyx_memoryview_obj *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + PyObject *__pyx_t_2 = NULL; + struct __pyx_memoryview_obj *__pyx_t_3; + char *__pyx_t_4; + int __pyx_t_5; + Py_ssize_t __pyx_t_6; + PyObject *(*__pyx_t_7)(PyObject *); + PyObject *__pyx_t_8 = NULL; + Py_ssize_t __pyx_t_9; + int __pyx_t_10; + Py_ssize_t __pyx_t_11; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("memview_slice", 0); + + /* "View.MemoryView":722 + * @cname('__pyx_memview_slice') + * cdef memoryview memview_slice(memoryview memview, object indices): + * cdef int new_ndim = 0, suboffset_dim = -1, dim # <<<<<<<<<<<<<< + * cdef bint negative_step + * cdef __Pyx_memviewslice src, dst +*/ + __pyx_v_new_ndim = 0; + __pyx_v_suboffset_dim = -1; + + /* "View.MemoryView":729 + * + * + * memset(&dst, 0, sizeof(dst)) # <<<<<<<<<<<<<< + * + * cdef _memoryviewslice memviewsliceobj +*/ + (void)(memset((&__pyx_v_dst), 0, (sizeof(__pyx_v_dst)))); + + /* "View.MemoryView":733 + * cdef _memoryviewslice memviewsliceobj + * + * assert memview.view.ndim > 0 # <<<<<<<<<<<<<< + * + * if isinstance(memview, _memoryviewslice): +*/ + #ifndef CYTHON_WITHOUT_ASSERTIONS + if (unlikely(__pyx_assertions_enabled())) { + __pyx_t_1 = (__pyx_v_memview->view.ndim > 0); + if (unlikely(!__pyx_t_1)) { + __Pyx_Raise(((PyObject *)(((PyTypeObject*)PyExc_AssertionError))), 0, 0, 0); + __PYX_ERR(1, 733, __pyx_L1_error) + } + } + #else + if ((1)); else __PYX_ERR(1, 733, __pyx_L1_error) + #endif + + /* "View.MemoryView":735 + * assert memview.view.ndim > 0 + * + * if isinstance(memview, _memoryviewslice): # <<<<<<<<<<<<<< + * memviewsliceobj = memview + * p_src = &memviewsliceobj.from_slice +*/ + __pyx_t_1 = __Pyx_TypeCheck(((PyObject *)__pyx_v_memview), __pyx_mstate_global->__pyx_memoryviewslice_type); + if (__pyx_t_1) { + + /* "View.MemoryView":736 + * + * if isinstance(memview, _memoryviewslice): + * memviewsliceobj = memview # <<<<<<<<<<<<<< + * p_src = &memviewsliceobj.from_slice + * else: +*/ + __pyx_t_2 = ((PyObject *)__pyx_v_memview); + __Pyx_INCREF(__pyx_t_2); + if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_mstate_global->__pyx_memoryviewslice_type))))) __PYX_ERR(1, 736, __pyx_L1_error) + __pyx_v_memviewsliceobj = ((struct __pyx_memoryviewslice_obj *)__pyx_t_2); + __pyx_t_2 = 0; + + /* "View.MemoryView":737 + * if isinstance(memview, _memoryviewslice): + * memviewsliceobj = memview + * p_src = &memviewsliceobj.from_slice # <<<<<<<<<<<<<< + * else: + * slice_copy(memview, &src) +*/ + __pyx_v_p_src = (&__pyx_v_memviewsliceobj->from_slice); + + /* "View.MemoryView":735 + * assert memview.view.ndim > 0 + * + * if isinstance(memview, _memoryviewslice): # <<<<<<<<<<<<<< + * memviewsliceobj = memview + * p_src = &memviewsliceobj.from_slice +*/ + goto __pyx_L3; + } + + /* "View.MemoryView":739 + * p_src = &memviewsliceobj.from_slice + * else: + * slice_copy(memview, &src) # <<<<<<<<<<<<<< + * p_src = &src + * +*/ + /*else*/ { + __pyx_memoryview_slice_copy(__pyx_v_memview, (&__pyx_v_src)); + + /* "View.MemoryView":740 + * else: + * slice_copy(memview, &src) + * p_src = &src # <<<<<<<<<<<<<< + * + * +*/ + __pyx_v_p_src = (&__pyx_v_src); + } + __pyx_L3:; + + /* "View.MemoryView":746 + * + * + * dst.memview = p_src.memview # <<<<<<<<<<<<<< + * dst.data = p_src.data + * +*/ + __pyx_t_3 = __pyx_v_p_src->memview; + __pyx_v_dst.memview = __pyx_t_3; + + /* "View.MemoryView":747 + * + * dst.memview = p_src.memview + * dst.data = p_src.data # <<<<<<<<<<<<<< + * + * +*/ + __pyx_t_4 = __pyx_v_p_src->data; + __pyx_v_dst.data = __pyx_t_4; + + /* "View.MemoryView":752 + * + * + * cdef __Pyx_memviewslice *p_dst = &dst # <<<<<<<<<<<<<< + * cdef int *p_suboffset_dim = &suboffset_dim + * cdef Py_ssize_t start, stop, step, cindex +*/ + __pyx_v_p_dst = (&__pyx_v_dst); + + /* "View.MemoryView":753 + * + * cdef __Pyx_memviewslice *p_dst = &dst + * cdef int *p_suboffset_dim = &suboffset_dim # <<<<<<<<<<<<<< + * cdef Py_ssize_t start, stop, step, cindex + * cdef bint have_start, have_stop, have_step +*/ + __pyx_v_p_suboffset_dim = (&__pyx_v_suboffset_dim); + + /* "View.MemoryView":757 + * cdef bint have_start, have_stop, have_step + * + * for dim, index in enumerate(indices): # <<<<<<<<<<<<<< + * if PyIndex_Check(index): + * cindex = index +*/ + __pyx_t_5 = 0; + if (likely(PyList_CheckExact(__pyx_v_indices)) || PyTuple_CheckExact(__pyx_v_indices)) { + __pyx_t_2 = __pyx_v_indices; __Pyx_INCREF(__pyx_t_2); + __pyx_t_6 = 0; + __pyx_t_7 = NULL; + } else { + __pyx_t_6 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_v_indices); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 757, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_7 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_2); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 757, __pyx_L1_error) + } + for (;;) { + if (likely(!__pyx_t_7)) { + if (likely(PyList_CheckExact(__pyx_t_2))) { + { + Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_2); + #if !CYTHON_ASSUME_SAFE_SIZE + if (unlikely((__pyx_temp < 0))) __PYX_ERR(1, 757, __pyx_L1_error) + #endif + if (__pyx_t_6 >= __pyx_temp) break; + } + __pyx_t_8 = __Pyx_PyList_GetItemRefFast(__pyx_t_2, __pyx_t_6, __Pyx_ReferenceSharing_OwnStrongReference); + ++__pyx_t_6; + } else { + { + Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_2); + #if !CYTHON_ASSUME_SAFE_SIZE + if (unlikely((__pyx_temp < 0))) __PYX_ERR(1, 757, __pyx_L1_error) + #endif + if (__pyx_t_6 >= __pyx_temp) break; + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_8 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_6)); + #else + __pyx_t_8 = __Pyx_PySequence_ITEM(__pyx_t_2, __pyx_t_6); + #endif + ++__pyx_t_6; + } + if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 757, __pyx_L1_error) + } else { + __pyx_t_8 = __pyx_t_7(__pyx_t_2); + if (unlikely(!__pyx_t_8)) { + PyObject* exc_type = PyErr_Occurred(); + if (exc_type) { + if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(1, 757, __pyx_L1_error) + PyErr_Clear(); + } + break; + } + } + __Pyx_GOTREF(__pyx_t_8); + __Pyx_XDECREF_SET(__pyx_v_index, __pyx_t_8); + __pyx_t_8 = 0; + __pyx_v_dim = __pyx_t_5; + __pyx_t_5 = (__pyx_t_5 + 1); + + /* "View.MemoryView":758 + * + * for dim, index in enumerate(indices): + * if PyIndex_Check(index): # <<<<<<<<<<<<<< + * cindex = index + * slice_memviewslice( +*/ + __pyx_t_1 = (PyIndex_Check(__pyx_v_index) != 0); + if (__pyx_t_1) { + + /* "View.MemoryView":759 + * for dim, index in enumerate(indices): + * if PyIndex_Check(index): + * cindex = index # <<<<<<<<<<<<<< + * slice_memviewslice( + * p_dst, p_src.shape[dim], p_src.strides[dim], p_src.suboffsets[dim], +*/ + __pyx_t_9 = __Pyx_PyIndex_AsSsize_t(__pyx_v_index); if (unlikely((__pyx_t_9 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(1, 759, __pyx_L1_error) + __pyx_v_cindex = __pyx_t_9; + + /* "View.MemoryView":760 + * if PyIndex_Check(index): + * cindex = index + * slice_memviewslice( # <<<<<<<<<<<<<< + * p_dst, p_src.shape[dim], p_src.strides[dim], p_src.suboffsets[dim], + * dim, new_ndim, p_suboffset_dim, +*/ + __pyx_t_10 = __pyx_memoryview_slice_memviewslice(__pyx_v_p_dst, (__pyx_v_p_src->shape[__pyx_v_dim]), (__pyx_v_p_src->strides[__pyx_v_dim]), (__pyx_v_p_src->suboffsets[__pyx_v_dim]), __pyx_v_dim, __pyx_v_new_ndim, __pyx_v_p_suboffset_dim, __pyx_v_cindex, 0, 0, 0, 0, 0, 0); if (unlikely(__pyx_t_10 == ((int)-1))) __PYX_ERR(1, 760, __pyx_L1_error) + + /* "View.MemoryView":758 + * + * for dim, index in enumerate(indices): + * if PyIndex_Check(index): # <<<<<<<<<<<<<< + * cindex = index + * slice_memviewslice( +*/ + goto __pyx_L6; + } + + /* "View.MemoryView":766 + * 0, 0, 0, # have_{start,stop,step} + * False) + * elif index is None: # <<<<<<<<<<<<<< + * p_dst.shape[new_ndim] = 1 + * p_dst.strides[new_ndim] = 0 +*/ + __pyx_t_1 = (__pyx_v_index == Py_None); + if (__pyx_t_1) { + + /* "View.MemoryView":767 + * False) + * elif index is None: + * p_dst.shape[new_ndim] = 1 # <<<<<<<<<<<<<< + * p_dst.strides[new_ndim] = 0 + * p_dst.suboffsets[new_ndim] = -1 +*/ + (__pyx_v_p_dst->shape[__pyx_v_new_ndim]) = 1; + + /* "View.MemoryView":768 + * elif index is None: + * p_dst.shape[new_ndim] = 1 + * p_dst.strides[new_ndim] = 0 # <<<<<<<<<<<<<< + * p_dst.suboffsets[new_ndim] = -1 + * new_ndim += 1 +*/ + (__pyx_v_p_dst->strides[__pyx_v_new_ndim]) = 0; + + /* "View.MemoryView":769 + * p_dst.shape[new_ndim] = 1 + * p_dst.strides[new_ndim] = 0 + * p_dst.suboffsets[new_ndim] = -1 # <<<<<<<<<<<<<< + * new_ndim += 1 + * else: +*/ + (__pyx_v_p_dst->suboffsets[__pyx_v_new_ndim]) = -1L; + + /* "View.MemoryView":770 + * p_dst.strides[new_ndim] = 0 + * p_dst.suboffsets[new_ndim] = -1 + * new_ndim += 1 # <<<<<<<<<<<<<< + * else: + * start = index.start or 0 +*/ + __pyx_v_new_ndim = (__pyx_v_new_ndim + 1); + + /* "View.MemoryView":766 + * 0, 0, 0, # have_{start,stop,step} + * False) + * elif index is None: # <<<<<<<<<<<<<< + * p_dst.shape[new_ndim] = 1 + * p_dst.strides[new_ndim] = 0 +*/ + goto __pyx_L6; + } + + /* "View.MemoryView":772 + * new_ndim += 1 + * else: + * start = index.start or 0 # <<<<<<<<<<<<<< + * stop = index.stop or 0 + * step = index.step or 0 +*/ + /*else*/ { + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_index, __pyx_mstate_global->__pyx_n_u_start); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 772, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely((__pyx_t_1 < 0))) __PYX_ERR(1, 772, __pyx_L1_error) + if (!__pyx_t_1) { + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + } else { + __pyx_t_11 = __Pyx_PyIndex_AsSsize_t(__pyx_t_8); if (unlikely((__pyx_t_11 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(1, 772, __pyx_L1_error) + __pyx_t_9 = __pyx_t_11; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + goto __pyx_L7_bool_binop_done; + } + __pyx_t_9 = 0; + __pyx_L7_bool_binop_done:; + __pyx_v_start = __pyx_t_9; + + /* "View.MemoryView":773 + * else: + * start = index.start or 0 + * stop = index.stop or 0 # <<<<<<<<<<<<<< + * step = index.step or 0 + * +*/ + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_index, __pyx_mstate_global->__pyx_n_u_stop); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 773, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely((__pyx_t_1 < 0))) __PYX_ERR(1, 773, __pyx_L1_error) + if (!__pyx_t_1) { + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + } else { + __pyx_t_11 = __Pyx_PyIndex_AsSsize_t(__pyx_t_8); if (unlikely((__pyx_t_11 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(1, 773, __pyx_L1_error) + __pyx_t_9 = __pyx_t_11; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + goto __pyx_L9_bool_binop_done; + } + __pyx_t_9 = 0; + __pyx_L9_bool_binop_done:; + __pyx_v_stop = __pyx_t_9; + + /* "View.MemoryView":774 + * start = index.start or 0 + * stop = index.stop or 0 + * step = index.step or 0 # <<<<<<<<<<<<<< + * + * have_start = index.start is not None +*/ + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_index, __pyx_mstate_global->__pyx_n_u_step); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 774, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely((__pyx_t_1 < 0))) __PYX_ERR(1, 774, __pyx_L1_error) + if (!__pyx_t_1) { + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + } else { + __pyx_t_11 = __Pyx_PyIndex_AsSsize_t(__pyx_t_8); if (unlikely((__pyx_t_11 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(1, 774, __pyx_L1_error) + __pyx_t_9 = __pyx_t_11; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + goto __pyx_L11_bool_binop_done; + } + __pyx_t_9 = 0; + __pyx_L11_bool_binop_done:; + __pyx_v_step = __pyx_t_9; + + /* "View.MemoryView":776 + * step = index.step or 0 + * + * have_start = index.start is not None # <<<<<<<<<<<<<< + * have_stop = index.stop is not None + * have_step = index.step is not None +*/ + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_index, __pyx_mstate_global->__pyx_n_u_start); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 776, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_1 = (__pyx_t_8 != Py_None); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_v_have_start = __pyx_t_1; + + /* "View.MemoryView":777 + * + * have_start = index.start is not None + * have_stop = index.stop is not None # <<<<<<<<<<<<<< + * have_step = index.step is not None + * +*/ + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_index, __pyx_mstate_global->__pyx_n_u_stop); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 777, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_1 = (__pyx_t_8 != Py_None); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_v_have_stop = __pyx_t_1; + + /* "View.MemoryView":778 + * have_start = index.start is not None + * have_stop = index.stop is not None + * have_step = index.step is not None # <<<<<<<<<<<<<< + * + * slice_memviewslice( +*/ + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_index, __pyx_mstate_global->__pyx_n_u_step); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 778, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_1 = (__pyx_t_8 != Py_None); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_v_have_step = __pyx_t_1; + + /* "View.MemoryView":780 + * have_step = index.step is not None + * + * slice_memviewslice( # <<<<<<<<<<<<<< + * p_dst, p_src.shape[dim], p_src.strides[dim], p_src.suboffsets[dim], + * dim, new_ndim, p_suboffset_dim, +*/ + __pyx_t_10 = __pyx_memoryview_slice_memviewslice(__pyx_v_p_dst, (__pyx_v_p_src->shape[__pyx_v_dim]), (__pyx_v_p_src->strides[__pyx_v_dim]), (__pyx_v_p_src->suboffsets[__pyx_v_dim]), __pyx_v_dim, __pyx_v_new_ndim, __pyx_v_p_suboffset_dim, __pyx_v_start, __pyx_v_stop, __pyx_v_step, __pyx_v_have_start, __pyx_v_have_stop, __pyx_v_have_step, 1); if (unlikely(__pyx_t_10 == ((int)-1))) __PYX_ERR(1, 780, __pyx_L1_error) + + /* "View.MemoryView":786 + * have_start, have_stop, have_step, + * True) + * new_ndim += 1 # <<<<<<<<<<<<<< + * + * if isinstance(memview, _memoryviewslice): +*/ + __pyx_v_new_ndim = (__pyx_v_new_ndim + 1); + } + __pyx_L6:; + + /* "View.MemoryView":757 + * cdef bint have_start, have_stop, have_step + * + * for dim, index in enumerate(indices): # <<<<<<<<<<<<<< + * if PyIndex_Check(index): + * cindex = index +*/ + } + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "View.MemoryView":788 + * new_ndim += 1 + * + * if isinstance(memview, _memoryviewslice): # <<<<<<<<<<<<<< + * return memoryview_fromslice(dst, new_ndim, + * memviewsliceobj.to_object_func, +*/ + __pyx_t_1 = __Pyx_TypeCheck(((PyObject *)__pyx_v_memview), __pyx_mstate_global->__pyx_memoryviewslice_type); + if (__pyx_t_1) { + + /* "View.MemoryView":789 + * + * if isinstance(memview, _memoryviewslice): + * return memoryview_fromslice(dst, new_ndim, # <<<<<<<<<<<<<< + * memviewsliceobj.to_object_func, + * memviewsliceobj.to_dtype_func, +*/ + __Pyx_XDECREF((PyObject *)__pyx_r); + + /* "View.MemoryView":790 + * if isinstance(memview, _memoryviewslice): + * return memoryview_fromslice(dst, new_ndim, + * memviewsliceobj.to_object_func, # <<<<<<<<<<<<<< + * memviewsliceobj.to_dtype_func, + * memview.dtype_is_object) +*/ + if (unlikely(!__pyx_v_memviewsliceobj)) { __Pyx_RaiseUnboundLocalError("memviewsliceobj"); __PYX_ERR(1, 790, __pyx_L1_error) } + + /* "View.MemoryView":791 + * return memoryview_fromslice(dst, new_ndim, + * memviewsliceobj.to_object_func, + * memviewsliceobj.to_dtype_func, # <<<<<<<<<<<<<< + * memview.dtype_is_object) + * else: +*/ + if (unlikely(!__pyx_v_memviewsliceobj)) { __Pyx_RaiseUnboundLocalError("memviewsliceobj"); __PYX_ERR(1, 791, __pyx_L1_error) } + + /* "View.MemoryView":789 + * + * if isinstance(memview, _memoryviewslice): + * return memoryview_fromslice(dst, new_ndim, # <<<<<<<<<<<<<< + * memviewsliceobj.to_object_func, + * memviewsliceobj.to_dtype_func, +*/ + __pyx_t_2 = __pyx_memoryview_fromslice(__pyx_v_dst, __pyx_v_new_ndim, __pyx_v_memviewsliceobj->to_object_func, __pyx_v_memviewsliceobj->to_dtype_func, __pyx_v_memview->dtype_is_object); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 789, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_mstate_global->__pyx_memoryview_type))))) __PYX_ERR(1, 789, __pyx_L1_error) + __pyx_r = ((struct __pyx_memoryview_obj *)__pyx_t_2); + __pyx_t_2 = 0; + goto __pyx_L0; + + /* "View.MemoryView":788 + * new_ndim += 1 + * + * if isinstance(memview, _memoryviewslice): # <<<<<<<<<<<<<< + * return memoryview_fromslice(dst, new_ndim, + * memviewsliceobj.to_object_func, +*/ + } + + /* "View.MemoryView":794 + * memview.dtype_is_object) + * else: + * return memoryview_fromslice(dst, new_ndim, NULL, NULL, # <<<<<<<<<<<<<< + * memview.dtype_is_object) + * +*/ + /*else*/ { + __Pyx_XDECREF((PyObject *)__pyx_r); + + /* "View.MemoryView":795 + * else: + * return memoryview_fromslice(dst, new_ndim, NULL, NULL, + * memview.dtype_is_object) # <<<<<<<<<<<<<< + * + * +*/ + __pyx_t_2 = __pyx_memoryview_fromslice(__pyx_v_dst, __pyx_v_new_ndim, NULL, NULL, __pyx_v_memview->dtype_is_object); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 794, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + + /* "View.MemoryView":794 + * memview.dtype_is_object) + * else: + * return memoryview_fromslice(dst, new_ndim, NULL, NULL, # <<<<<<<<<<<<<< + * memview.dtype_is_object) + * +*/ + if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_mstate_global->__pyx_memoryview_type))))) __PYX_ERR(1, 794, __pyx_L1_error) + __pyx_r = ((struct __pyx_memoryview_obj *)__pyx_t_2); + __pyx_t_2 = 0; + goto __pyx_L0; + } + + /* "View.MemoryView":720 + * + * + * @cname('__pyx_memview_slice') # <<<<<<<<<<<<<< + * cdef memoryview memview_slice(memoryview memview, object indices): + * cdef int new_ndim = 0, suboffset_dim = -1, dim +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_AddTraceback("View.MemoryView.memview_slice", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF((PyObject *)__pyx_v_memviewsliceobj); + __Pyx_XDECREF(__pyx_v_index); + __Pyx_XGIVEREF((PyObject *)__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":801 + * + * + * @cname('__pyx_pybuffer_index') # <<<<<<<<<<<<<< + * cdef char *pybuffer_index(Py_buffer *view, char *bufp, Py_ssize_t index, + * Py_ssize_t dim) except NULL: +*/ + +static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, Py_ssize_t __pyx_v_index, Py_ssize_t __pyx_v_dim) { + Py_ssize_t __pyx_v_shape; + Py_ssize_t __pyx_v_stride; + Py_ssize_t __pyx_v_suboffset; + Py_ssize_t __pyx_v_itemsize; + char *__pyx_v_resultp; + char *__pyx_r; + __Pyx_RefNannyDeclarations + Py_ssize_t __pyx_t_1; + int __pyx_t_2; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4[3]; + PyObject *__pyx_t_5 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("pybuffer_index", 0); + + /* "View.MemoryView":804 + * cdef char *pybuffer_index(Py_buffer *view, char *bufp, Py_ssize_t index, + * Py_ssize_t dim) except NULL: + * cdef Py_ssize_t shape, stride, suboffset = -1 # <<<<<<<<<<<<<< + * cdef Py_ssize_t itemsize = view.itemsize + * cdef char *resultp +*/ + __pyx_v_suboffset = -1L; + + /* "View.MemoryView":805 + * Py_ssize_t dim) except NULL: + * cdef Py_ssize_t shape, stride, suboffset = -1 + * cdef Py_ssize_t itemsize = view.itemsize # <<<<<<<<<<<<<< + * cdef char *resultp + * +*/ + __pyx_t_1 = __pyx_v_view->itemsize; + __pyx_v_itemsize = __pyx_t_1; + + /* "View.MemoryView":808 + * cdef char *resultp + * + * if view.ndim == 0: # <<<<<<<<<<<<<< + * shape = view.len // itemsize + * stride = itemsize +*/ + __pyx_t_2 = (__pyx_v_view->ndim == 0); + if (__pyx_t_2) { + + /* "View.MemoryView":809 + * + * if view.ndim == 0: + * shape = view.len // itemsize # <<<<<<<<<<<<<< + * stride = itemsize + * else: +*/ + if (unlikely(__pyx_v_itemsize == 0)) { + PyErr_SetString(PyExc_ZeroDivisionError, "integer division or modulo by zero"); + __PYX_ERR(1, 809, __pyx_L1_error) + } + else if (sizeof(Py_ssize_t) == sizeof(long) && (!(((Py_ssize_t)-1) > 0)) && unlikely(__pyx_v_itemsize == (Py_ssize_t)-1) && unlikely(__Pyx_UNARY_NEG_WOULD_OVERFLOW(__pyx_v_view->len))) { + PyErr_SetString(PyExc_OverflowError, "value too large to perform division"); + __PYX_ERR(1, 809, __pyx_L1_error) + } + __pyx_v_shape = __Pyx_div_Py_ssize_t(__pyx_v_view->len, __pyx_v_itemsize, 0); + + /* "View.MemoryView":810 + * if view.ndim == 0: + * shape = view.len // itemsize + * stride = itemsize # <<<<<<<<<<<<<< + * else: + * shape = view.shape[dim] +*/ + __pyx_v_stride = __pyx_v_itemsize; + + /* "View.MemoryView":808 + * cdef char *resultp + * + * if view.ndim == 0: # <<<<<<<<<<<<<< + * shape = view.len // itemsize + * stride = itemsize +*/ + goto __pyx_L3; + } + + /* "View.MemoryView":812 + * stride = itemsize + * else: + * shape = view.shape[dim] # <<<<<<<<<<<<<< + * stride = view.strides[dim] + * if view.suboffsets != NULL: +*/ + /*else*/ { + __pyx_v_shape = (__pyx_v_view->shape[__pyx_v_dim]); + + /* "View.MemoryView":813 + * else: + * shape = view.shape[dim] + * stride = view.strides[dim] # <<<<<<<<<<<<<< + * if view.suboffsets != NULL: + * suboffset = view.suboffsets[dim] +*/ + __pyx_v_stride = (__pyx_v_view->strides[__pyx_v_dim]); + + /* "View.MemoryView":814 + * shape = view.shape[dim] + * stride = view.strides[dim] + * if view.suboffsets != NULL: # <<<<<<<<<<<<<< + * suboffset = view.suboffsets[dim] + * +*/ + __pyx_t_2 = (__pyx_v_view->suboffsets != NULL); + if (__pyx_t_2) { + + /* "View.MemoryView":815 + * stride = view.strides[dim] + * if view.suboffsets != NULL: + * suboffset = view.suboffsets[dim] # <<<<<<<<<<<<<< + * + * if index < 0: +*/ + __pyx_v_suboffset = (__pyx_v_view->suboffsets[__pyx_v_dim]); + + /* "View.MemoryView":814 + * shape = view.shape[dim] + * stride = view.strides[dim] + * if view.suboffsets != NULL: # <<<<<<<<<<<<<< + * suboffset = view.suboffsets[dim] + * +*/ + } + } + __pyx_L3:; + + /* "View.MemoryView":817 + * suboffset = view.suboffsets[dim] + * + * if index < 0: # <<<<<<<<<<<<<< + * index += view.shape[dim] + * if index < 0: +*/ + __pyx_t_2 = (__pyx_v_index < 0); + if (__pyx_t_2) { + + /* "View.MemoryView":818 + * + * if index < 0: + * index += view.shape[dim] # <<<<<<<<<<<<<< + * if index < 0: + * raise IndexError, f"Out of bounds on buffer access (axis {dim})" +*/ + __pyx_v_index = (__pyx_v_index + (__pyx_v_view->shape[__pyx_v_dim])); + + /* "View.MemoryView":819 + * if index < 0: + * index += view.shape[dim] + * if index < 0: # <<<<<<<<<<<<<< + * raise IndexError, f"Out of bounds on buffer access (axis {dim})" + * +*/ + __pyx_t_2 = (__pyx_v_index < 0); + if (unlikely(__pyx_t_2)) { + + /* "View.MemoryView":820 + * index += view.shape[dim] + * if index < 0: + * raise IndexError, f"Out of bounds on buffer access (axis {dim})" # <<<<<<<<<<<<<< + * + * if index >= shape: +*/ + __pyx_t_3 = __Pyx_PyUnicode_From_Py_ssize_t(__pyx_v_dim, 0, ' ', 'd'); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 820, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4[0] = __pyx_mstate_global->__pyx_kp_u_Out_of_bounds_on_buffer_access_a; + __pyx_t_4[1] = __pyx_t_3; + __pyx_t_4[2] = __pyx_mstate_global->__pyx_kp_u__5; + __pyx_t_5 = __Pyx_PyUnicode_Join(__pyx_t_4, 3, 37 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_3) + 1, 127); + if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 820, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_Raise(((PyObject *)(((PyTypeObject*)PyExc_IndexError))), __pyx_t_5, 0, 0); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __PYX_ERR(1, 820, __pyx_L1_error) + + /* "View.MemoryView":819 + * if index < 0: + * index += view.shape[dim] + * if index < 0: # <<<<<<<<<<<<<< + * raise IndexError, f"Out of bounds on buffer access (axis {dim})" + * +*/ + } + + /* "View.MemoryView":817 + * suboffset = view.suboffsets[dim] + * + * if index < 0: # <<<<<<<<<<<<<< + * index += view.shape[dim] + * if index < 0: +*/ + } + + /* "View.MemoryView":822 + * raise IndexError, f"Out of bounds on buffer access (axis {dim})" + * + * if index >= shape: # <<<<<<<<<<<<<< + * raise IndexError, f"Out of bounds on buffer access (axis {dim})" + * +*/ + __pyx_t_2 = (__pyx_v_index >= __pyx_v_shape); + if (unlikely(__pyx_t_2)) { + + /* "View.MemoryView":823 + * + * if index >= shape: + * raise IndexError, f"Out of bounds on buffer access (axis {dim})" # <<<<<<<<<<<<<< + * + * resultp = bufp + index * stride +*/ + __pyx_t_5 = __Pyx_PyUnicode_From_Py_ssize_t(__pyx_v_dim, 0, ' ', 'd'); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 823, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_4[0] = __pyx_mstate_global->__pyx_kp_u_Out_of_bounds_on_buffer_access_a; + __pyx_t_4[1] = __pyx_t_5; + __pyx_t_4[2] = __pyx_mstate_global->__pyx_kp_u__5; + __pyx_t_3 = __Pyx_PyUnicode_Join(__pyx_t_4, 3, 37 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_5) + 1, 127); + if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 823, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_Raise(((PyObject *)(((PyTypeObject*)PyExc_IndexError))), __pyx_t_3, 0, 0); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __PYX_ERR(1, 823, __pyx_L1_error) + + /* "View.MemoryView":822 + * raise IndexError, f"Out of bounds on buffer access (axis {dim})" + * + * if index >= shape: # <<<<<<<<<<<<<< + * raise IndexError, f"Out of bounds on buffer access (axis {dim})" + * +*/ + } + + /* "View.MemoryView":825 + * raise IndexError, f"Out of bounds on buffer access (axis {dim})" + * + * resultp = bufp + index * stride # <<<<<<<<<<<<<< + * if suboffset >= 0: + * resultp = ( resultp)[0] + suboffset +*/ + __pyx_v_resultp = (__pyx_v_bufp + (__pyx_v_index * __pyx_v_stride)); + + /* "View.MemoryView":826 + * + * resultp = bufp + index * stride + * if suboffset >= 0: # <<<<<<<<<<<<<< + * resultp = ( resultp)[0] + suboffset + * +*/ + __pyx_t_2 = (__pyx_v_suboffset >= 0); + if (__pyx_t_2) { + + /* "View.MemoryView":827 + * resultp = bufp + index * stride + * if suboffset >= 0: + * resultp = ( resultp)[0] + suboffset # <<<<<<<<<<<<<< + * + * return resultp +*/ + __pyx_v_resultp = ((((char **)__pyx_v_resultp)[0]) + __pyx_v_suboffset); + + /* "View.MemoryView":826 + * + * resultp = bufp + index * stride + * if suboffset >= 0: # <<<<<<<<<<<<<< + * resultp = ( resultp)[0] + suboffset + * +*/ + } + + /* "View.MemoryView":829 + * resultp = ( resultp)[0] + suboffset + * + * return resultp # <<<<<<<<<<<<<< + * + * +*/ + __pyx_r = __pyx_v_resultp; + goto __pyx_L0; + + /* "View.MemoryView":801 + * + * + * @cname('__pyx_pybuffer_index') # <<<<<<<<<<<<<< + * cdef char *pybuffer_index(Py_buffer *view, char *bufp, Py_ssize_t index, + * Py_ssize_t dim) except NULL: +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("View.MemoryView.pybuffer_index", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":834 + * + * + * @cname('__pyx_memslice_transpose') # <<<<<<<<<<<<<< + * cdef int transpose_memslice(__Pyx_memviewslice *memslice) except -1 nogil: + * cdef int ndim = memslice.memview.view.ndim +*/ + +static int __pyx_memslice_transpose(__Pyx_memviewslice *__pyx_v_memslice) { + int __pyx_v_ndim; + Py_ssize_t *__pyx_v_shape; + Py_ssize_t *__pyx_v_strides; + int __pyx_v_i; + int __pyx_v_j; + int __pyx_r; + int __pyx_t_1; + Py_ssize_t *__pyx_t_2; + long __pyx_t_3; + long __pyx_t_4; + Py_ssize_t __pyx_t_5; + Py_ssize_t __pyx_t_6; + int __pyx_t_7; + int __pyx_t_8; + int __pyx_t_9; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyGILState_STATE __pyx_gilstate_save; + + /* "View.MemoryView":836 + * @cname('__pyx_memslice_transpose') + * cdef int transpose_memslice(__Pyx_memviewslice *memslice) except -1 nogil: + * cdef int ndim = memslice.memview.view.ndim # <<<<<<<<<<<<<< + * + * cdef Py_ssize_t *shape = memslice.shape +*/ + __pyx_t_1 = __pyx_v_memslice->memview->view.ndim; + __pyx_v_ndim = __pyx_t_1; + + /* "View.MemoryView":838 + * cdef int ndim = memslice.memview.view.ndim + * + * cdef Py_ssize_t *shape = memslice.shape # <<<<<<<<<<<<<< + * cdef Py_ssize_t *strides = memslice.strides + * +*/ + __pyx_t_2 = __pyx_v_memslice->shape; + __pyx_v_shape = __pyx_t_2; + + /* "View.MemoryView":839 + * + * cdef Py_ssize_t *shape = memslice.shape + * cdef Py_ssize_t *strides = memslice.strides # <<<<<<<<<<<<<< + * + * +*/ + __pyx_t_2 = __pyx_v_memslice->strides; + __pyx_v_strides = __pyx_t_2; + + /* "View.MemoryView":843 + * + * cdef int i, j + * for i in range(ndim // 2): # <<<<<<<<<<<<<< + * j = ndim - 1 - i + * strides[i], strides[j] = strides[j], strides[i] +*/ + __pyx_t_3 = __Pyx_div_long(__pyx_v_ndim, 2, 1); + __pyx_t_4 = __pyx_t_3; + for (__pyx_t_1 = 0; __pyx_t_1 < __pyx_t_4; __pyx_t_1+=1) { + __pyx_v_i = __pyx_t_1; + + /* "View.MemoryView":844 + * cdef int i, j + * for i in range(ndim // 2): + * j = ndim - 1 - i # <<<<<<<<<<<<<< + * strides[i], strides[j] = strides[j], strides[i] + * shape[i], shape[j] = shape[j], shape[i] +*/ + __pyx_v_j = ((__pyx_v_ndim - 1) - __pyx_v_i); + + /* "View.MemoryView":845 + * for i in range(ndim // 2): + * j = ndim - 1 - i + * strides[i], strides[j] = strides[j], strides[i] # <<<<<<<<<<<<<< + * shape[i], shape[j] = shape[j], shape[i] + * +*/ + __pyx_t_5 = (__pyx_v_strides[__pyx_v_j]); + __pyx_t_6 = (__pyx_v_strides[__pyx_v_i]); + (__pyx_v_strides[__pyx_v_i]) = __pyx_t_5; + (__pyx_v_strides[__pyx_v_j]) = __pyx_t_6; + + /* "View.MemoryView":846 + * j = ndim - 1 - i + * strides[i], strides[j] = strides[j], strides[i] + * shape[i], shape[j] = shape[j], shape[i] # <<<<<<<<<<<<<< + * + * if memslice.suboffsets[i] >= 0 or memslice.suboffsets[j] >= 0: +*/ + __pyx_t_6 = (__pyx_v_shape[__pyx_v_j]); + __pyx_t_5 = (__pyx_v_shape[__pyx_v_i]); + (__pyx_v_shape[__pyx_v_i]) = __pyx_t_6; + (__pyx_v_shape[__pyx_v_j]) = __pyx_t_5; + + /* "View.MemoryView":848 + * shape[i], shape[j] = shape[j], shape[i] + * + * if memslice.suboffsets[i] >= 0 or memslice.suboffsets[j] >= 0: # <<<<<<<<<<<<<< + * _err(PyExc_ValueError, "Cannot transpose memoryview with indirect dimensions") + * +*/ + __pyx_t_8 = ((__pyx_v_memslice->suboffsets[__pyx_v_i]) >= 0); + if (!__pyx_t_8) { + } else { + __pyx_t_7 = __pyx_t_8; + goto __pyx_L6_bool_binop_done; + } + __pyx_t_8 = ((__pyx_v_memslice->suboffsets[__pyx_v_j]) >= 0); + __pyx_t_7 = __pyx_t_8; + __pyx_L6_bool_binop_done:; + if (__pyx_t_7) { + + /* "View.MemoryView":849 + * + * if memslice.suboffsets[i] >= 0 or memslice.suboffsets[j] >= 0: + * _err(PyExc_ValueError, "Cannot transpose memoryview with indirect dimensions") # <<<<<<<<<<<<<< + * + * return 0 +*/ + __pyx_t_9 = __pyx_memoryview_err(PyExc_ValueError, __pyx_mstate_global->__pyx_kp_u_Cannot_transpose_memoryview_with); if (unlikely(__pyx_t_9 == ((int)-1))) __PYX_ERR(1, 849, __pyx_L1_error) + + /* "View.MemoryView":848 + * shape[i], shape[j] = shape[j], shape[i] + * + * if memslice.suboffsets[i] >= 0 or memslice.suboffsets[j] >= 0: # <<<<<<<<<<<<<< + * _err(PyExc_ValueError, "Cannot transpose memoryview with indirect dimensions") + * +*/ + } + } + + /* "View.MemoryView":851 + * _err(PyExc_ValueError, "Cannot transpose memoryview with indirect dimensions") + * + * return 0 # <<<<<<<<<<<<<< + * + * +*/ + __pyx_r = 0; + goto __pyx_L0; + + /* "View.MemoryView":834 + * + * + * @cname('__pyx_memslice_transpose') # <<<<<<<<<<<<<< + * cdef int transpose_memslice(__Pyx_memviewslice *memslice) except -1 nogil: + * cdef int ndim = memslice.memview.view.ndim +*/ + + /* function exit code */ + __pyx_L1_error:; + __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); + __Pyx_AddTraceback("View.MemoryView.transpose_memslice", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __Pyx_PyGILState_Release(__pyx_gilstate_save); + __pyx_L0:; + return __pyx_r; +} + +/* "View.MemoryView":869 + * cdef int (*to_dtype_func)(char *, object) except 0 + * + * def __dealloc__(self): # <<<<<<<<<<<<<< + * __PYX_XCLEAR_MEMVIEW(&self.from_slice, 1) + * +*/ + +/* Python wrapper */ +static void __pyx_memoryviewslice___dealloc__(PyObject *__pyx_v_self); /*proto*/ +static void __pyx_memoryviewslice___dealloc__(PyObject *__pyx_v_self) { + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__dealloc__ (wrapper)", 0); + __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs); + __pyx_memoryviewslice___pyx_pf_15View_dot_MemoryView_16_memoryviewslice___dealloc__(((struct __pyx_memoryviewslice_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); +} + +static void __pyx_memoryviewslice___pyx_pf_15View_dot_MemoryView_16_memoryviewslice___dealloc__(struct __pyx_memoryviewslice_obj *__pyx_v_self) { + + /* "View.MemoryView":870 + * + * def __dealloc__(self): + * __PYX_XCLEAR_MEMVIEW(&self.from_slice, 1) # <<<<<<<<<<<<<< + * + * cdef convert_item_to_object(self, char *itemp): +*/ + __PYX_XCLEAR_MEMVIEW((&__pyx_v_self->from_slice), 1); + + /* "View.MemoryView":869 + * cdef int (*to_dtype_func)(char *, object) except 0 + * + * def __dealloc__(self): # <<<<<<<<<<<<<< + * __PYX_XCLEAR_MEMVIEW(&self.from_slice, 1) + * +*/ + + /* function exit code */ +} + +/* "View.MemoryView":872 + * __PYX_XCLEAR_MEMVIEW(&self.from_slice, 1) + * + * cdef convert_item_to_object(self, char *itemp): # <<<<<<<<<<<<<< + * if self.to_object_func != NULL: + * return self.to_object_func(itemp) +*/ + +static PyObject *__pyx_memoryviewslice_convert_item_to_object(struct __pyx_memoryviewslice_obj *__pyx_v_self, char *__pyx_v_itemp) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + PyObject *__pyx_t_2 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("convert_item_to_object", 0); + + /* "View.MemoryView":873 + * + * cdef convert_item_to_object(self, char *itemp): + * if self.to_object_func != NULL: # <<<<<<<<<<<<<< + * return self.to_object_func(itemp) + * else: +*/ + __pyx_t_1 = (__pyx_v_self->to_object_func != NULL); + if (__pyx_t_1) { + + /* "View.MemoryView":874 + * cdef convert_item_to_object(self, char *itemp): + * if self.to_object_func != NULL: + * return self.to_object_func(itemp) # <<<<<<<<<<<<<< + * else: + * return memoryview.convert_item_to_object(self, itemp) +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_2 = __pyx_v_self->to_object_func(__pyx_v_itemp); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 874, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + goto __pyx_L0; + + /* "View.MemoryView":873 + * + * cdef convert_item_to_object(self, char *itemp): + * if self.to_object_func != NULL: # <<<<<<<<<<<<<< + * return self.to_object_func(itemp) + * else: +*/ + } + + /* "View.MemoryView":876 + * return self.to_object_func(itemp) + * else: + * return memoryview.convert_item_to_object(self, itemp) # <<<<<<<<<<<<<< + * + * cdef assign_item_from_object(self, char *itemp, object value): +*/ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + __pyx_t_2 = __pyx_memoryview_convert_item_to_object(((struct __pyx_memoryview_obj *)__pyx_v_self), __pyx_v_itemp); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 876, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + goto __pyx_L0; + } + + /* "View.MemoryView":872 + * __PYX_XCLEAR_MEMVIEW(&self.from_slice, 1) + * + * cdef convert_item_to_object(self, char *itemp): # <<<<<<<<<<<<<< + * if self.to_object_func != NULL: + * return self.to_object_func(itemp) +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("View.MemoryView._memoryviewslice.convert_item_to_object", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":878 + * return memoryview.convert_item_to_object(self, itemp) + * + * cdef assign_item_from_object(self, char *itemp, object value): # <<<<<<<<<<<<<< + * if self.to_dtype_func != NULL: + * self.to_dtype_func(itemp, value) +*/ + +static PyObject *__pyx_memoryviewslice_assign_item_from_object(struct __pyx_memoryviewslice_obj *__pyx_v_self, char *__pyx_v_itemp, PyObject *__pyx_v_value) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_t_2; + PyObject *__pyx_t_3 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("assign_item_from_object", 0); + + /* "View.MemoryView":879 + * + * cdef assign_item_from_object(self, char *itemp, object value): + * if self.to_dtype_func != NULL: # <<<<<<<<<<<<<< + * self.to_dtype_func(itemp, value) + * else: +*/ + __pyx_t_1 = (__pyx_v_self->to_dtype_func != NULL); + if (__pyx_t_1) { + + /* "View.MemoryView":880 + * cdef assign_item_from_object(self, char *itemp, object value): + * if self.to_dtype_func != NULL: + * self.to_dtype_func(itemp, value) # <<<<<<<<<<<<<< + * else: + * memoryview.assign_item_from_object(self, itemp, value) +*/ + __pyx_t_2 = __pyx_v_self->to_dtype_func(__pyx_v_itemp, __pyx_v_value); if (unlikely(__pyx_t_2 == ((int)0))) __PYX_ERR(1, 880, __pyx_L1_error) + + /* "View.MemoryView":879 + * + * cdef assign_item_from_object(self, char *itemp, object value): + * if self.to_dtype_func != NULL: # <<<<<<<<<<<<<< + * self.to_dtype_func(itemp, value) + * else: +*/ + goto __pyx_L3; + } + + /* "View.MemoryView":882 + * self.to_dtype_func(itemp, value) + * else: + * memoryview.assign_item_from_object(self, itemp, value) # <<<<<<<<<<<<<< + * + * cdef _get_base(self): +*/ + /*else*/ { + __pyx_t_3 = __pyx_memoryview_assign_item_from_object(((struct __pyx_memoryview_obj *)__pyx_v_self), __pyx_v_itemp, __pyx_v_value); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 882, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } + __pyx_L3:; + + /* "View.MemoryView":878 + * return memoryview.convert_item_to_object(self, itemp) + * + * cdef assign_item_from_object(self, char *itemp, object value): # <<<<<<<<<<<<<< + * if self.to_dtype_func != NULL: + * self.to_dtype_func(itemp, value) +*/ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_3); + __Pyx_AddTraceback("View.MemoryView._memoryviewslice.assign_item_from_object", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":884 + * memoryview.assign_item_from_object(self, itemp, value) + * + * cdef _get_base(self): # <<<<<<<<<<<<<< + * return self.from_object + * +*/ + +static PyObject *__pyx_memoryviewslice__get_base(struct __pyx_memoryviewslice_obj *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("_get_base", 0); + + /* "View.MemoryView":885 + * + * cdef _get_base(self): + * return self.from_object # <<<<<<<<<<<<<< + * + * +*/ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->from_object); + __pyx_r = __pyx_v_self->from_object; + goto __pyx_L0; + + /* "View.MemoryView":884 + * memoryview.assign_item_from_object(self, itemp, value) + * + * cdef _get_base(self): # <<<<<<<<<<<<<< + * return self.from_object + * +*/ + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" + * def __setstate_cython__(self, __pyx_state): +*/ + +/* Python wrapper */ +static PyObject *__pyx_pw___pyx_memoryviewslice_1__reduce_cython__(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +); /*proto*/ +static PyObject *__pyx_pw___pyx_memoryviewslice_1__reduce_cython__(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +) { + #if !CYTHON_METH_FASTCALL + CYTHON_UNUSED Py_ssize_t __pyx_nargs; + #endif + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); + #if !CYTHON_METH_FASTCALL + #if CYTHON_ASSUME_SAFE_SIZE + __pyx_nargs = PyTuple_GET_SIZE(__pyx_args); + #else + __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL; + #endif + #endif + __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs); + if (unlikely(__pyx_nargs > 0)) { __Pyx_RaiseArgtupleInvalid("__reduce_cython__", 1, 0, 0, __pyx_nargs); return NULL; } + const Py_ssize_t __pyx_kwds_len = unlikely(__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0; + if (unlikely(__pyx_kwds_len < 0)) return NULL; + if (unlikely(__pyx_kwds_len > 0)) {__Pyx_RejectKeywords("__reduce_cython__", __pyx_kwds); return NULL;} + __pyx_r = __pyx_pf___pyx_memoryviewslice___reduce_cython__(((struct __pyx_memoryviewslice_obj *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf___pyx_memoryviewslice___reduce_cython__(CYTHON_UNUSED struct __pyx_memoryviewslice_obj *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__reduce_cython__", 0); + + /* "(tree fragment)":2 + * def __reduce_cython__(self): + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" # <<<<<<<<<<<<<< + * def __setstate_cython__(self, __pyx_state): + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" +*/ + __Pyx_Raise(((PyObject *)(((PyTypeObject*)PyExc_TypeError))), __pyx_mstate_global->__pyx_kp_u_no_default___reduce___due_to_non, 0, 0); + __PYX_ERR(1, 2, __pyx_L1_error) + + /* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" + * def __setstate_cython__(self, __pyx_state): +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_AddTraceback("View.MemoryView._memoryviewslice.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":3 + * def __reduce_cython__(self): + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" +*/ + +/* Python wrapper */ +static PyObject *__pyx_pw___pyx_memoryviewslice_3__setstate_cython__(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +); /*proto*/ +static PyObject *__pyx_pw___pyx_memoryviewslice_3__setstate_cython__(PyObject *__pyx_v_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +) { + CYTHON_UNUSED PyObject *__pyx_v___pyx_state = 0; + #if !CYTHON_METH_FASTCALL + CYTHON_UNUSED Py_ssize_t __pyx_nargs; + #endif + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject* values[1] = {0}; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); + #if !CYTHON_METH_FASTCALL + #if CYTHON_ASSUME_SAFE_SIZE + __pyx_nargs = PyTuple_GET_SIZE(__pyx_args); + #else + __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL; + #endif + #endif + __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs); + { + PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_pyx_state,0}; + const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0; + if (unlikely(__pyx_kwds_len < 0)) __PYX_ERR(1, 3, __pyx_L3_error) + if (__pyx_kwds_len > 0) { + switch (__pyx_nargs) { + case 1: + values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(1, 3, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + const Py_ssize_t kwd_pos_args = __pyx_nargs; + if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "__setstate_cython__", 0) < (0)) __PYX_ERR(1, 3, __pyx_L3_error) + for (Py_ssize_t i = __pyx_nargs; i < 1; i++) { + if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("__setstate_cython__", 1, 1, 1, i); __PYX_ERR(1, 3, __pyx_L3_error) } + } + } else if (unlikely(__pyx_nargs != 1)) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(1, 3, __pyx_L3_error) + } + __pyx_v___pyx_state = values[0]; + } + goto __pyx_L6_skip; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__setstate_cython__", 1, 1, 1, __pyx_nargs); __PYX_ERR(1, 3, __pyx_L3_error) + __pyx_L6_skip:; + goto __pyx_L4_argument_unpacking_done; + __pyx_L3_error:; + for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { + Py_XDECREF(values[__pyx_temp]); + } + __Pyx_AddTraceback("View.MemoryView._memoryviewslice.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf___pyx_memoryviewslice_2__setstate_cython__(((struct __pyx_memoryviewslice_obj *)__pyx_v_self), __pyx_v___pyx_state); + + /* function exit code */ + for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { + Py_XDECREF(values[__pyx_temp]); + } + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf___pyx_memoryviewslice_2__setstate_cython__(CYTHON_UNUSED struct __pyx_memoryviewslice_obj *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__setstate_cython__", 0); + + /* "(tree fragment)":4 + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" + * def __setstate_cython__(self, __pyx_state): + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" # <<<<<<<<<<<<<< +*/ + __Pyx_Raise(((PyObject *)(((PyTypeObject*)PyExc_TypeError))), __pyx_mstate_global->__pyx_kp_u_no_default___reduce___due_to_non, 0, 0); + __PYX_ERR(1, 4, __pyx_L1_error) + + /* "(tree fragment)":3 + * def __reduce_cython__(self): + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * raise TypeError, "no default __reduce__ due to non-trivial __cinit__" +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_AddTraceback("View.MemoryView._memoryviewslice.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":904 + * pass # ignore failure, it's a minor issue + * + * @cname('__pyx_memoryview_fromslice') # <<<<<<<<<<<<<< + * cdef memoryview_fromslice(__Pyx_memviewslice memviewslice, + * int ndim, +*/ + +static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewslice, int __pyx_v_ndim, PyObject *(*__pyx_v_to_object_func)(char *), int (*__pyx_v_to_dtype_func)(char *, PyObject *), int __pyx_v_dtype_is_object) { + struct __pyx_memoryviewslice_obj *__pyx_v_result = 0; + Py_ssize_t __pyx_v_suboffset; + PyObject *__pyx_v_length = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + __Pyx_TypeInfo const *__pyx_t_4; + Py_buffer __pyx_t_5; + Py_ssize_t *__pyx_t_6; + Py_ssize_t *__pyx_t_7; + Py_ssize_t *__pyx_t_8; + Py_ssize_t __pyx_t_9; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("memoryview_fromslice", 0); + + /* "View.MemoryView":913 + * cdef _memoryviewslice result + * + * if memviewslice.memview == Py_None: # <<<<<<<<<<<<<< + * return None + * +*/ + __pyx_t_1 = (((PyObject *)__pyx_v_memviewslice.memview) == Py_None); + if (__pyx_t_1) { + + /* "View.MemoryView":914 + * + * if memviewslice.memview == Py_None: + * return None # <<<<<<<<<<<<<< + * + * +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + + /* "View.MemoryView":913 + * cdef _memoryviewslice result + * + * if memviewslice.memview == Py_None: # <<<<<<<<<<<<<< + * return None + * +*/ + } + + /* "View.MemoryView":919 + * + * + * result = _memoryviewslice.__new__(_memoryviewslice, None, 0, dtype_is_object) # <<<<<<<<<<<<<< + * + * result.from_slice = memviewslice +*/ + __pyx_t_2 = __Pyx_PyBool_FromLong(__pyx_v_dtype_is_object); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 919, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 919, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_3, 0, Py_None) != (0)) __PYX_ERR(1, 919, __pyx_L1_error); + __Pyx_INCREF(__pyx_mstate_global->__pyx_int_0); + __Pyx_GIVEREF(__pyx_mstate_global->__pyx_int_0); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_mstate_global->__pyx_int_0) != (0)) __PYX_ERR(1, 919, __pyx_L1_error); + __Pyx_GIVEREF(__pyx_t_2); + if (__Pyx_PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_t_2) != (0)) __PYX_ERR(1, 919, __pyx_L1_error); + __pyx_t_2 = 0; + __pyx_t_2 = ((PyObject *)__pyx_tp_new__memoryviewslice(((PyTypeObject *)__pyx_mstate_global->__pyx_memoryviewslice_type), __pyx_t_3, NULL)); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 919, __pyx_L1_error) + __Pyx_GOTREF((PyObject *)__pyx_t_2); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_v_result = ((struct __pyx_memoryviewslice_obj *)__pyx_t_2); + __pyx_t_2 = 0; + + /* "View.MemoryView":921 + * result = _memoryviewslice.__new__(_memoryviewslice, None, 0, dtype_is_object) + * + * result.from_slice = memviewslice # <<<<<<<<<<<<<< + * __PYX_INC_MEMVIEW(&memviewslice, 1) + * +*/ + __pyx_v_result->from_slice = __pyx_v_memviewslice; + + /* "View.MemoryView":922 + * + * result.from_slice = memviewslice + * __PYX_INC_MEMVIEW(&memviewslice, 1) # <<<<<<<<<<<<<< + * + * result.from_object = ( memviewslice.memview)._get_base() +*/ + __PYX_INC_MEMVIEW((&__pyx_v_memviewslice), 1); + + /* "View.MemoryView":924 + * __PYX_INC_MEMVIEW(&memviewslice, 1) + * + * result.from_object = ( memviewslice.memview)._get_base() # <<<<<<<<<<<<<< + * result.typeinfo = memviewslice.memview.typeinfo + * +*/ + __pyx_t_2 = ((struct __pyx_vtabstruct_memoryview *)((struct __pyx_memoryview_obj *)__pyx_v_memviewslice.memview)->__pyx_vtab)->_get_base(((struct __pyx_memoryview_obj *)__pyx_v_memviewslice.memview)); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 924, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_GIVEREF(__pyx_t_2); + __Pyx_GOTREF(__pyx_v_result->from_object); + __Pyx_DECREF(__pyx_v_result->from_object); + __pyx_v_result->from_object = __pyx_t_2; + __pyx_t_2 = 0; + + /* "View.MemoryView":925 + * + * result.from_object = ( memviewslice.memview)._get_base() + * result.typeinfo = memviewslice.memview.typeinfo # <<<<<<<<<<<<<< + * + * result.view = memviewslice.memview.view +*/ + __pyx_t_4 = __pyx_v_memviewslice.memview->typeinfo; + __pyx_v_result->__pyx_base.typeinfo = __pyx_t_4; + + /* "View.MemoryView":927 + * result.typeinfo = memviewslice.memview.typeinfo + * + * result.view = memviewslice.memview.view # <<<<<<<<<<<<<< + * result.view.buf = memviewslice.data + * result.view.ndim = ndim +*/ + __pyx_t_5 = __pyx_v_memviewslice.memview->view; + __pyx_v_result->__pyx_base.view = __pyx_t_5; + + /* "View.MemoryView":928 + * + * result.view = memviewslice.memview.view + * result.view.buf = memviewslice.data # <<<<<<<<<<<<<< + * result.view.ndim = ndim + * (<__pyx_buffer *> &result.view).obj = Py_None +*/ + __pyx_v_result->__pyx_base.view.buf = ((void *)__pyx_v_memviewslice.data); + + /* "View.MemoryView":929 + * result.view = memviewslice.memview.view + * result.view.buf = memviewslice.data + * result.view.ndim = ndim # <<<<<<<<<<<<<< + * (<__pyx_buffer *> &result.view).obj = Py_None + * Py_INCREF(Py_None) +*/ + __pyx_v_result->__pyx_base.view.ndim = __pyx_v_ndim; + + /* "View.MemoryView":930 + * result.view.buf = memviewslice.data + * result.view.ndim = ndim + * (<__pyx_buffer *> &result.view).obj = Py_None # <<<<<<<<<<<<<< + * Py_INCREF(Py_None) + * +*/ + ((Py_buffer *)(&__pyx_v_result->__pyx_base.view))->obj = Py_None; + + /* "View.MemoryView":931 + * result.view.ndim = ndim + * (<__pyx_buffer *> &result.view).obj = Py_None + * Py_INCREF(Py_None) # <<<<<<<<<<<<<< + * + * if (memviewslice.memview).flags & PyBUF_WRITABLE: +*/ + Py_INCREF(Py_None); + + /* "View.MemoryView":933 + * Py_INCREF(Py_None) + * + * if (memviewslice.memview).flags & PyBUF_WRITABLE: # <<<<<<<<<<<<<< + * result.flags = PyBUF_RECORDS + * else: +*/ + __pyx_t_1 = ((((struct __pyx_memoryview_obj *)__pyx_v_memviewslice.memview)->flags & PyBUF_WRITABLE) != 0); + if (__pyx_t_1) { + + /* "View.MemoryView":934 + * + * if (memviewslice.memview).flags & PyBUF_WRITABLE: + * result.flags = PyBUF_RECORDS # <<<<<<<<<<<<<< + * else: + * result.flags = PyBUF_RECORDS_RO +*/ + __pyx_v_result->__pyx_base.flags = PyBUF_RECORDS; + + /* "View.MemoryView":933 + * Py_INCREF(Py_None) + * + * if (memviewslice.memview).flags & PyBUF_WRITABLE: # <<<<<<<<<<<<<< + * result.flags = PyBUF_RECORDS + * else: +*/ + goto __pyx_L4; + } + + /* "View.MemoryView":936 + * result.flags = PyBUF_RECORDS + * else: + * result.flags = PyBUF_RECORDS_RO # <<<<<<<<<<<<<< + * + * result.view.shape = result.from_slice.shape +*/ + /*else*/ { + __pyx_v_result->__pyx_base.flags = PyBUF_RECORDS_RO; + } + __pyx_L4:; + + /* "View.MemoryView":938 + * result.flags = PyBUF_RECORDS_RO + * + * result.view.shape = result.from_slice.shape # <<<<<<<<<<<<<< + * result.view.strides = result.from_slice.strides + * +*/ + __pyx_v_result->__pyx_base.view.shape = ((Py_ssize_t *)__pyx_v_result->from_slice.shape); + + /* "View.MemoryView":939 + * + * result.view.shape = result.from_slice.shape + * result.view.strides = result.from_slice.strides # <<<<<<<<<<<<<< + * + * +*/ + __pyx_v_result->__pyx_base.view.strides = ((Py_ssize_t *)__pyx_v_result->from_slice.strides); + + /* "View.MemoryView":942 + * + * + * result.view.suboffsets = NULL # <<<<<<<<<<<<<< + * for suboffset in result.from_slice.suboffsets[:ndim]: + * if suboffset >= 0: +*/ + __pyx_v_result->__pyx_base.view.suboffsets = NULL; + + /* "View.MemoryView":943 + * + * result.view.suboffsets = NULL + * for suboffset in result.from_slice.suboffsets[:ndim]: # <<<<<<<<<<<<<< + * if suboffset >= 0: + * result.view.suboffsets = result.from_slice.suboffsets +*/ + __pyx_t_7 = (__pyx_v_result->from_slice.suboffsets + __pyx_v_ndim); + for (__pyx_t_8 = __pyx_v_result->from_slice.suboffsets; __pyx_t_8 < __pyx_t_7; __pyx_t_8++) { + __pyx_t_6 = __pyx_t_8; + __pyx_v_suboffset = (__pyx_t_6[0]); + + /* "View.MemoryView":944 + * result.view.suboffsets = NULL + * for suboffset in result.from_slice.suboffsets[:ndim]: + * if suboffset >= 0: # <<<<<<<<<<<<<< + * result.view.suboffsets = result.from_slice.suboffsets + * break +*/ + __pyx_t_1 = (__pyx_v_suboffset >= 0); + if (__pyx_t_1) { + + /* "View.MemoryView":945 + * for suboffset in result.from_slice.suboffsets[:ndim]: + * if suboffset >= 0: + * result.view.suboffsets = result.from_slice.suboffsets # <<<<<<<<<<<<<< + * break + * +*/ + __pyx_v_result->__pyx_base.view.suboffsets = ((Py_ssize_t *)__pyx_v_result->from_slice.suboffsets); + + /* "View.MemoryView":946 + * if suboffset >= 0: + * result.view.suboffsets = result.from_slice.suboffsets + * break # <<<<<<<<<<<<<< + * + * result.view.len = result.view.itemsize +*/ + goto __pyx_L6_break; + + /* "View.MemoryView":944 + * result.view.suboffsets = NULL + * for suboffset in result.from_slice.suboffsets[:ndim]: + * if suboffset >= 0: # <<<<<<<<<<<<<< + * result.view.suboffsets = result.from_slice.suboffsets + * break +*/ + } + } + __pyx_L6_break:; + + /* "View.MemoryView":948 + * break + * + * result.view.len = result.view.itemsize # <<<<<<<<<<<<<< + * for length in result.view.shape[:ndim]: + * result.view.len *= length +*/ + __pyx_t_9 = __pyx_v_result->__pyx_base.view.itemsize; + __pyx_v_result->__pyx_base.view.len = __pyx_t_9; + + /* "View.MemoryView":949 + * + * result.view.len = result.view.itemsize + * for length in result.view.shape[:ndim]: # <<<<<<<<<<<<<< + * result.view.len *= length + * +*/ + __pyx_t_7 = (__pyx_v_result->__pyx_base.view.shape + __pyx_v_ndim); + for (__pyx_t_8 = __pyx_v_result->__pyx_base.view.shape; __pyx_t_8 < __pyx_t_7; __pyx_t_8++) { + __pyx_t_6 = __pyx_t_8; + __pyx_t_2 = PyLong_FromSsize_t((__pyx_t_6[0])); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 949, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_XDECREF_SET(__pyx_v_length, __pyx_t_2); + __pyx_t_2 = 0; + + /* "View.MemoryView":950 + * result.view.len = result.view.itemsize + * for length in result.view.shape[:ndim]: + * result.view.len *= length # <<<<<<<<<<<<<< + * + * result.to_object_func = to_object_func +*/ + __pyx_t_2 = PyLong_FromSsize_t(__pyx_v_result->__pyx_base.view.len); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 950, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = PyNumber_InPlaceMultiply(__pyx_t_2, __pyx_v_length); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 950, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_9 = __Pyx_PyIndex_AsSsize_t(__pyx_t_3); if (unlikely((__pyx_t_9 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(1, 950, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_v_result->__pyx_base.view.len = __pyx_t_9; + } + + /* "View.MemoryView":952 + * result.view.len *= length + * + * result.to_object_func = to_object_func # <<<<<<<<<<<<<< + * result.to_dtype_func = to_dtype_func + * +*/ + __pyx_v_result->to_object_func = __pyx_v_to_object_func; + + /* "View.MemoryView":953 + * + * result.to_object_func = to_object_func + * result.to_dtype_func = to_dtype_func # <<<<<<<<<<<<<< + * + * return result +*/ + __pyx_v_result->to_dtype_func = __pyx_v_to_dtype_func; + + /* "View.MemoryView":955 + * result.to_dtype_func = to_dtype_func + * + * return result # <<<<<<<<<<<<<< + * + * @cname('__pyx_memoryview_get_slice_from_memoryview') +*/ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF((PyObject *)__pyx_v_result); + __pyx_r = ((PyObject *)__pyx_v_result); + goto __pyx_L0; + + /* "View.MemoryView":904 + * pass # ignore failure, it's a minor issue + * + * @cname('__pyx_memoryview_fromslice') # <<<<<<<<<<<<<< + * cdef memoryview_fromslice(__Pyx_memviewslice memviewslice, + * int ndim, +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_AddTraceback("View.MemoryView.memoryview_fromslice", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF((PyObject *)__pyx_v_result); + __Pyx_XDECREF(__pyx_v_length); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":957 + * return result + * + * @cname('__pyx_memoryview_get_slice_from_memoryview') # <<<<<<<<<<<<<< + * cdef __Pyx_memviewslice *get_slice_from_memview(memoryview memview, + * __Pyx_memviewslice *mslice) except NULL: +*/ + +static __Pyx_memviewslice *__pyx_memoryview_get_slice_from_memoryview(struct __pyx_memoryview_obj *__pyx_v_memview, __Pyx_memviewslice *__pyx_v_mslice) { + struct __pyx_memoryviewslice_obj *__pyx_v_obj = 0; + __Pyx_memviewslice *__pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + PyObject *__pyx_t_2 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("get_slice_from_memview", 0); + + /* "View.MemoryView":961 + * __Pyx_memviewslice *mslice) except NULL: + * cdef _memoryviewslice obj + * if isinstance(memview, _memoryviewslice): # <<<<<<<<<<<<<< + * obj = memview + * return &obj.from_slice +*/ + __pyx_t_1 = __Pyx_TypeCheck(((PyObject *)__pyx_v_memview), __pyx_mstate_global->__pyx_memoryviewslice_type); + if (__pyx_t_1) { + + /* "View.MemoryView":962 + * cdef _memoryviewslice obj + * if isinstance(memview, _memoryviewslice): + * obj = memview # <<<<<<<<<<<<<< + * return &obj.from_slice + * else: +*/ + __pyx_t_2 = ((PyObject *)__pyx_v_memview); + __Pyx_INCREF(__pyx_t_2); + if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_mstate_global->__pyx_memoryviewslice_type))))) __PYX_ERR(1, 962, __pyx_L1_error) + __pyx_v_obj = ((struct __pyx_memoryviewslice_obj *)__pyx_t_2); + __pyx_t_2 = 0; + + /* "View.MemoryView":963 + * if isinstance(memview, _memoryviewslice): + * obj = memview + * return &obj.from_slice # <<<<<<<<<<<<<< + * else: + * slice_copy(memview, mslice) +*/ + __pyx_r = (&__pyx_v_obj->from_slice); + goto __pyx_L0; + + /* "View.MemoryView":961 + * __Pyx_memviewslice *mslice) except NULL: + * cdef _memoryviewslice obj + * if isinstance(memview, _memoryviewslice): # <<<<<<<<<<<<<< + * obj = memview + * return &obj.from_slice +*/ + } + + /* "View.MemoryView":965 + * return &obj.from_slice + * else: + * slice_copy(memview, mslice) # <<<<<<<<<<<<<< + * return mslice + * +*/ + /*else*/ { + __pyx_memoryview_slice_copy(__pyx_v_memview, __pyx_v_mslice); + + /* "View.MemoryView":966 + * else: + * slice_copy(memview, mslice) + * return mslice # <<<<<<<<<<<<<< + * + * @cname('__pyx_memoryview_slice_copy') +*/ + __pyx_r = __pyx_v_mslice; + goto __pyx_L0; + } + + /* "View.MemoryView":957 + * return result + * + * @cname('__pyx_memoryview_get_slice_from_memoryview') # <<<<<<<<<<<<<< + * cdef __Pyx_memviewslice *get_slice_from_memview(memoryview memview, + * __Pyx_memviewslice *mslice) except NULL: +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("View.MemoryView.get_slice_from_memview", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF((PyObject *)__pyx_v_obj); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":968 + * return mslice + * + * @cname('__pyx_memoryview_slice_copy') # <<<<<<<<<<<<<< + * cdef void slice_copy(memoryview memview, __Pyx_memviewslice *dst) noexcept: + * cdef int dim +*/ + +static void __pyx_memoryview_slice_copy(struct __pyx_memoryview_obj *__pyx_v_memview, __Pyx_memviewslice *__pyx_v_dst) { + int __pyx_v_dim; + Py_ssize_t *__pyx_v_shape; + Py_ssize_t *__pyx_v_strides; + Py_ssize_t *__pyx_v_suboffsets; + Py_ssize_t *__pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + int __pyx_t_4; + Py_ssize_t __pyx_t_5; + int __pyx_t_6; + + /* "View.MemoryView":973 + * cdef (Py_ssize_t*) shape, strides, suboffsets + * + * shape = memview.view.shape # <<<<<<<<<<<<<< + * strides = memview.view.strides + * suboffsets = memview.view.suboffsets +*/ + __pyx_t_1 = __pyx_v_memview->view.shape; + __pyx_v_shape = __pyx_t_1; + + /* "View.MemoryView":974 + * + * shape = memview.view.shape + * strides = memview.view.strides # <<<<<<<<<<<<<< + * suboffsets = memview.view.suboffsets + * +*/ + __pyx_t_1 = __pyx_v_memview->view.strides; + __pyx_v_strides = __pyx_t_1; + + /* "View.MemoryView":975 + * shape = memview.view.shape + * strides = memview.view.strides + * suboffsets = memview.view.suboffsets # <<<<<<<<<<<<<< + * + * dst.memview = <__pyx_memoryview *> memview +*/ + __pyx_t_1 = __pyx_v_memview->view.suboffsets; + __pyx_v_suboffsets = __pyx_t_1; + + /* "View.MemoryView":977 + * suboffsets = memview.view.suboffsets + * + * dst.memview = <__pyx_memoryview *> memview # <<<<<<<<<<<<<< + * dst.data = memview.view.buf + * +*/ + __pyx_v_dst->memview = ((struct __pyx_memoryview_obj *)__pyx_v_memview); + + /* "View.MemoryView":978 + * + * dst.memview = <__pyx_memoryview *> memview + * dst.data = memview.view.buf # <<<<<<<<<<<<<< + * + * for dim in range(memview.view.ndim): +*/ + __pyx_v_dst->data = ((char *)__pyx_v_memview->view.buf); + + /* "View.MemoryView":980 + * dst.data = memview.view.buf + * + * for dim in range(memview.view.ndim): # <<<<<<<<<<<<<< + * dst.shape[dim] = shape[dim] + * dst.strides[dim] = strides[dim] +*/ + __pyx_t_2 = __pyx_v_memview->view.ndim; + __pyx_t_3 = __pyx_t_2; + for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { + __pyx_v_dim = __pyx_t_4; + + /* "View.MemoryView":981 + * + * for dim in range(memview.view.ndim): + * dst.shape[dim] = shape[dim] # <<<<<<<<<<<<<< + * dst.strides[dim] = strides[dim] + * dst.suboffsets[dim] = suboffsets[dim] if suboffsets else -1 +*/ + (__pyx_v_dst->shape[__pyx_v_dim]) = (__pyx_v_shape[__pyx_v_dim]); + + /* "View.MemoryView":982 + * for dim in range(memview.view.ndim): + * dst.shape[dim] = shape[dim] + * dst.strides[dim] = strides[dim] # <<<<<<<<<<<<<< + * dst.suboffsets[dim] = suboffsets[dim] if suboffsets else -1 + * +*/ + (__pyx_v_dst->strides[__pyx_v_dim]) = (__pyx_v_strides[__pyx_v_dim]); + + /* "View.MemoryView":983 + * dst.shape[dim] = shape[dim] + * dst.strides[dim] = strides[dim] + * dst.suboffsets[dim] = suboffsets[dim] if suboffsets else -1 # <<<<<<<<<<<<<< + * + * @cname('__pyx_memoryview_copy_object') +*/ + __pyx_t_6 = (__pyx_v_suboffsets != 0); + if (__pyx_t_6) { + __pyx_t_5 = (__pyx_v_suboffsets[__pyx_v_dim]); + } else { + __pyx_t_5 = -1L; + } + (__pyx_v_dst->suboffsets[__pyx_v_dim]) = __pyx_t_5; + } + + /* "View.MemoryView":968 + * return mslice + * + * @cname('__pyx_memoryview_slice_copy') # <<<<<<<<<<<<<< + * cdef void slice_copy(memoryview memview, __Pyx_memviewslice *dst) noexcept: + * cdef int dim +*/ + + /* function exit code */ +} + +/* "View.MemoryView":985 + * dst.suboffsets[dim] = suboffsets[dim] if suboffsets else -1 + * + * @cname('__pyx_memoryview_copy_object') # <<<<<<<<<<<<<< + * cdef memoryview_copy(memoryview memview): + * "Create a new memoryview object" +*/ + +static PyObject *__pyx_memoryview_copy_object(struct __pyx_memoryview_obj *__pyx_v_memview) { + __Pyx_memviewslice __pyx_v_memviewslice; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("memoryview_copy", 0); + + /* "View.MemoryView":989 + * "Create a new memoryview object" + * cdef __Pyx_memviewslice memviewslice + * slice_copy(memview, &memviewslice) # <<<<<<<<<<<<<< + * return memoryview_copy_from_slice(memview, &memviewslice) + * +*/ + __pyx_memoryview_slice_copy(__pyx_v_memview, (&__pyx_v_memviewslice)); + + /* "View.MemoryView":990 + * cdef __Pyx_memviewslice memviewslice + * slice_copy(memview, &memviewslice) + * return memoryview_copy_from_slice(memview, &memviewslice) # <<<<<<<<<<<<<< + * + * @cname('__pyx_memoryview_copy_object_from_slice') +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __pyx_memoryview_copy_object_from_slice(__pyx_v_memview, (&__pyx_v_memviewslice)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 990, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "View.MemoryView":985 + * dst.suboffsets[dim] = suboffsets[dim] if suboffsets else -1 + * + * @cname('__pyx_memoryview_copy_object') # <<<<<<<<<<<<<< + * cdef memoryview_copy(memoryview memview): + * "Create a new memoryview object" +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("View.MemoryView.memoryview_copy", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":992 + * return memoryview_copy_from_slice(memview, &memviewslice) + * + * @cname('__pyx_memoryview_copy_object_from_slice') # <<<<<<<<<<<<<< + * cdef memoryview_copy_from_slice(memoryview memview, __Pyx_memviewslice *memviewslice): + * """ +*/ + +static PyObject *__pyx_memoryview_copy_object_from_slice(struct __pyx_memoryview_obj *__pyx_v_memview, __Pyx_memviewslice *__pyx_v_memviewslice) { + PyObject *(*__pyx_v_to_object_func)(char *); + int (*__pyx_v_to_dtype_func)(char *, PyObject *); + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + PyObject *(*__pyx_t_2)(char *); + int (*__pyx_t_3)(char *, PyObject *); + PyObject *__pyx_t_4 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("memoryview_copy_from_slice", 0); + + /* "View.MemoryView":1000 + * cdef int (*to_dtype_func)(char *, object) except 0 + * + * if isinstance(memview, _memoryviewslice): # <<<<<<<<<<<<<< + * to_object_func = (<_memoryviewslice> memview).to_object_func + * to_dtype_func = (<_memoryviewslice> memview).to_dtype_func +*/ + __pyx_t_1 = __Pyx_TypeCheck(((PyObject *)__pyx_v_memview), __pyx_mstate_global->__pyx_memoryviewslice_type); + if (__pyx_t_1) { + + /* "View.MemoryView":1001 + * + * if isinstance(memview, _memoryviewslice): + * to_object_func = (<_memoryviewslice> memview).to_object_func # <<<<<<<<<<<<<< + * to_dtype_func = (<_memoryviewslice> memview).to_dtype_func + * else: +*/ + __pyx_t_2 = ((struct __pyx_memoryviewslice_obj *)__pyx_v_memview)->to_object_func; + __pyx_v_to_object_func = __pyx_t_2; + + /* "View.MemoryView":1002 + * if isinstance(memview, _memoryviewslice): + * to_object_func = (<_memoryviewslice> memview).to_object_func + * to_dtype_func = (<_memoryviewslice> memview).to_dtype_func # <<<<<<<<<<<<<< + * else: + * to_object_func = NULL +*/ + __pyx_t_3 = ((struct __pyx_memoryviewslice_obj *)__pyx_v_memview)->to_dtype_func; + __pyx_v_to_dtype_func = __pyx_t_3; + + /* "View.MemoryView":1000 + * cdef int (*to_dtype_func)(char *, object) except 0 + * + * if isinstance(memview, _memoryviewslice): # <<<<<<<<<<<<<< + * to_object_func = (<_memoryviewslice> memview).to_object_func + * to_dtype_func = (<_memoryviewslice> memview).to_dtype_func +*/ + goto __pyx_L3; + } + + /* "View.MemoryView":1004 + * to_dtype_func = (<_memoryviewslice> memview).to_dtype_func + * else: + * to_object_func = NULL # <<<<<<<<<<<<<< + * to_dtype_func = NULL + * +*/ + /*else*/ { + __pyx_v_to_object_func = NULL; + + /* "View.MemoryView":1005 + * else: + * to_object_func = NULL + * to_dtype_func = NULL # <<<<<<<<<<<<<< + * + * return memoryview_fromslice(memviewslice[0], memview.view.ndim, +*/ + __pyx_v_to_dtype_func = NULL; + } + __pyx_L3:; + + /* "View.MemoryView":1007 + * to_dtype_func = NULL + * + * return memoryview_fromslice(memviewslice[0], memview.view.ndim, # <<<<<<<<<<<<<< + * to_object_func, to_dtype_func, + * memview.dtype_is_object) +*/ + __Pyx_XDECREF(__pyx_r); + + /* "View.MemoryView":1009 + * return memoryview_fromslice(memviewslice[0], memview.view.ndim, + * to_object_func, to_dtype_func, + * memview.dtype_is_object) # <<<<<<<<<<<<<< + * + * +*/ + __pyx_t_4 = __pyx_memoryview_fromslice((__pyx_v_memviewslice[0]), __pyx_v_memview->view.ndim, __pyx_v_to_object_func, __pyx_v_to_dtype_func, __pyx_v_memview->dtype_is_object); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 1007, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_r = __pyx_t_4; + __pyx_t_4 = 0; + goto __pyx_L0; + + /* "View.MemoryView":992 + * return memoryview_copy_from_slice(memview, &memviewslice) + * + * @cname('__pyx_memoryview_copy_object_from_slice') # <<<<<<<<<<<<<< + * cdef memoryview_copy_from_slice(memoryview memview, __Pyx_memviewslice *memviewslice): + * """ +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_4); + __Pyx_AddTraceback("View.MemoryView.memoryview_copy_from_slice", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "View.MemoryView":1015 + * + * + * cdef Py_ssize_t abs_py_ssize_t(Py_ssize_t arg) noexcept nogil: # <<<<<<<<<<<<<< + * return -arg if arg < 0 else arg + * +*/ + +static Py_ssize_t abs_py_ssize_t(Py_ssize_t __pyx_v_arg) { + Py_ssize_t __pyx_r; + Py_ssize_t __pyx_t_1; + int __pyx_t_2; + + /* "View.MemoryView":1016 + * + * cdef Py_ssize_t abs_py_ssize_t(Py_ssize_t arg) noexcept nogil: + * return -arg if arg < 0 else arg # <<<<<<<<<<<<<< + * + * @cname('__pyx_get_best_slice_order') +*/ + __pyx_t_2 = (__pyx_v_arg < 0); + if (__pyx_t_2) { + __pyx_t_1 = (-__pyx_v_arg); + } else { + __pyx_t_1 = __pyx_v_arg; + } + __pyx_r = __pyx_t_1; + goto __pyx_L0; + + /* "View.MemoryView":1015 + * + * + * cdef Py_ssize_t abs_py_ssize_t(Py_ssize_t arg) noexcept nogil: # <<<<<<<<<<<<<< + * return -arg if arg < 0 else arg + * +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "View.MemoryView":1018 + * return -arg if arg < 0 else arg + * + * @cname('__pyx_get_best_slice_order') # <<<<<<<<<<<<<< + * cdef char get_best_order(__Pyx_memviewslice *mslice, int ndim) noexcept nogil: + * """ +*/ + +static char __pyx_get_best_slice_order(__Pyx_memviewslice *__pyx_v_mslice, int __pyx_v_ndim) { + int __pyx_v_i; + Py_ssize_t __pyx_v_c_stride; + Py_ssize_t __pyx_v_f_stride; + char __pyx_r; + int __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + int __pyx_t_4; + + /* "View.MemoryView":1024 + * """ + * cdef int i + * cdef Py_ssize_t c_stride = 0 # <<<<<<<<<<<<<< + * cdef Py_ssize_t f_stride = 0 + * +*/ + __pyx_v_c_stride = 0; + + /* "View.MemoryView":1025 + * cdef int i + * cdef Py_ssize_t c_stride = 0 + * cdef Py_ssize_t f_stride = 0 # <<<<<<<<<<<<<< + * + * for i in range(ndim - 1, -1, -1): +*/ + __pyx_v_f_stride = 0; + + /* "View.MemoryView":1027 + * cdef Py_ssize_t f_stride = 0 + * + * for i in range(ndim - 1, -1, -1): # <<<<<<<<<<<<<< + * if mslice.shape[i] > 1: + * c_stride = mslice.strides[i] +*/ + for (__pyx_t_1 = (__pyx_v_ndim - 1); __pyx_t_1 > -1; __pyx_t_1-=1) { + __pyx_v_i = __pyx_t_1; + + /* "View.MemoryView":1028 + * + * for i in range(ndim - 1, -1, -1): + * if mslice.shape[i] > 1: # <<<<<<<<<<<<<< + * c_stride = mslice.strides[i] + * break +*/ + __pyx_t_2 = ((__pyx_v_mslice->shape[__pyx_v_i]) > 1); + if (__pyx_t_2) { + + /* "View.MemoryView":1029 + * for i in range(ndim - 1, -1, -1): + * if mslice.shape[i] > 1: + * c_stride = mslice.strides[i] # <<<<<<<<<<<<<< + * break + * +*/ + __pyx_v_c_stride = (__pyx_v_mslice->strides[__pyx_v_i]); + + /* "View.MemoryView":1030 + * if mslice.shape[i] > 1: + * c_stride = mslice.strides[i] + * break # <<<<<<<<<<<<<< + * + * for i in range(ndim): +*/ + goto __pyx_L4_break; + + /* "View.MemoryView":1028 + * + * for i in range(ndim - 1, -1, -1): + * if mslice.shape[i] > 1: # <<<<<<<<<<<<<< + * c_stride = mslice.strides[i] + * break +*/ + } + } + __pyx_L4_break:; + + /* "View.MemoryView":1032 + * break + * + * for i in range(ndim): # <<<<<<<<<<<<<< + * if mslice.shape[i] > 1: + * f_stride = mslice.strides[i] +*/ + __pyx_t_1 = __pyx_v_ndim; + __pyx_t_3 = __pyx_t_1; + for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { + __pyx_v_i = __pyx_t_4; + + /* "View.MemoryView":1033 + * + * for i in range(ndim): + * if mslice.shape[i] > 1: # <<<<<<<<<<<<<< + * f_stride = mslice.strides[i] + * break +*/ + __pyx_t_2 = ((__pyx_v_mslice->shape[__pyx_v_i]) > 1); + if (__pyx_t_2) { + + /* "View.MemoryView":1034 + * for i in range(ndim): + * if mslice.shape[i] > 1: + * f_stride = mslice.strides[i] # <<<<<<<<<<<<<< + * break + * +*/ + __pyx_v_f_stride = (__pyx_v_mslice->strides[__pyx_v_i]); + + /* "View.MemoryView":1035 + * if mslice.shape[i] > 1: + * f_stride = mslice.strides[i] + * break # <<<<<<<<<<<<<< + * + * if abs_py_ssize_t(c_stride) <= abs_py_ssize_t(f_stride): +*/ + goto __pyx_L7_break; + + /* "View.MemoryView":1033 + * + * for i in range(ndim): + * if mslice.shape[i] > 1: # <<<<<<<<<<<<<< + * f_stride = mslice.strides[i] + * break +*/ + } + } + __pyx_L7_break:; + + /* "View.MemoryView":1037 + * break + * + * if abs_py_ssize_t(c_stride) <= abs_py_ssize_t(f_stride): # <<<<<<<<<<<<<< + * return 'C' + * else: +*/ + __pyx_t_2 = (abs_py_ssize_t(__pyx_v_c_stride) <= abs_py_ssize_t(__pyx_v_f_stride)); + if (__pyx_t_2) { + + /* "View.MemoryView":1038 + * + * if abs_py_ssize_t(c_stride) <= abs_py_ssize_t(f_stride): + * return 'C' # <<<<<<<<<<<<<< + * else: + * return 'F' +*/ + __pyx_r = 'C'; + goto __pyx_L0; + + /* "View.MemoryView":1037 + * break + * + * if abs_py_ssize_t(c_stride) <= abs_py_ssize_t(f_stride): # <<<<<<<<<<<<<< + * return 'C' + * else: +*/ + } + + /* "View.MemoryView":1040 + * return 'C' + * else: + * return 'F' # <<<<<<<<<<<<<< + * + * @cython.cdivision(True) +*/ + /*else*/ { + __pyx_r = 'F'; + goto __pyx_L0; + } + + /* "View.MemoryView":1018 + * return -arg if arg < 0 else arg + * + * @cname('__pyx_get_best_slice_order') # <<<<<<<<<<<<<< + * cdef char get_best_order(__Pyx_memviewslice *mslice, int ndim) noexcept nogil: + * """ +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "View.MemoryView":1042 + * return 'F' + * + * @cython.cdivision(True) # <<<<<<<<<<<<<< + * cdef void _copy_strided_to_strided(char *src_data, Py_ssize_t *src_strides, + * char *dst_data, Py_ssize_t *dst_strides, +*/ + +static void _copy_strided_to_strided(char *__pyx_v_src_data, Py_ssize_t *__pyx_v_src_strides, char *__pyx_v_dst_data, Py_ssize_t *__pyx_v_dst_strides, Py_ssize_t *__pyx_v_src_shape, Py_ssize_t *__pyx_v_dst_shape, int __pyx_v_ndim, size_t __pyx_v_itemsize) { + CYTHON_UNUSED Py_ssize_t __pyx_v_i; + CYTHON_UNUSED Py_ssize_t __pyx_v_src_extent; + Py_ssize_t __pyx_v_dst_extent; + Py_ssize_t __pyx_v_src_stride; + Py_ssize_t __pyx_v_dst_stride; + int __pyx_t_1; + int __pyx_t_2; + Py_ssize_t __pyx_t_3; + Py_ssize_t __pyx_t_4; + Py_ssize_t __pyx_t_5; + + /* "View.MemoryView":1050 + * + * cdef Py_ssize_t i + * cdef Py_ssize_t src_extent = src_shape[0] # <<<<<<<<<<<<<< + * cdef Py_ssize_t dst_extent = dst_shape[0] + * cdef Py_ssize_t src_stride = src_strides[0] +*/ + __pyx_v_src_extent = (__pyx_v_src_shape[0]); + + /* "View.MemoryView":1051 + * cdef Py_ssize_t i + * cdef Py_ssize_t src_extent = src_shape[0] + * cdef Py_ssize_t dst_extent = dst_shape[0] # <<<<<<<<<<<<<< + * cdef Py_ssize_t src_stride = src_strides[0] + * cdef Py_ssize_t dst_stride = dst_strides[0] +*/ + __pyx_v_dst_extent = (__pyx_v_dst_shape[0]); + + /* "View.MemoryView":1052 + * cdef Py_ssize_t src_extent = src_shape[0] + * cdef Py_ssize_t dst_extent = dst_shape[0] + * cdef Py_ssize_t src_stride = src_strides[0] # <<<<<<<<<<<<<< + * cdef Py_ssize_t dst_stride = dst_strides[0] + * +*/ + __pyx_v_src_stride = (__pyx_v_src_strides[0]); + + /* "View.MemoryView":1053 + * cdef Py_ssize_t dst_extent = dst_shape[0] + * cdef Py_ssize_t src_stride = src_strides[0] + * cdef Py_ssize_t dst_stride = dst_strides[0] # <<<<<<<<<<<<<< + * + * if ndim == 1: +*/ + __pyx_v_dst_stride = (__pyx_v_dst_strides[0]); + + /* "View.MemoryView":1055 + * cdef Py_ssize_t dst_stride = dst_strides[0] + * + * if ndim == 1: # <<<<<<<<<<<<<< + * if (src_stride > 0 and dst_stride > 0 and + * src_stride == itemsize == dst_stride): +*/ + __pyx_t_1 = (__pyx_v_ndim == 1); + if (__pyx_t_1) { + + /* "View.MemoryView":1056 + * + * if ndim == 1: + * if (src_stride > 0 and dst_stride > 0 and # <<<<<<<<<<<<<< + * src_stride == itemsize == dst_stride): + * memcpy(dst_data, src_data, itemsize * dst_extent) +*/ + __pyx_t_2 = (__pyx_v_src_stride > 0); + if (__pyx_t_2) { + } else { + __pyx_t_1 = __pyx_t_2; + goto __pyx_L5_bool_binop_done; + } + __pyx_t_2 = (__pyx_v_dst_stride > 0); + if (__pyx_t_2) { + } else { + __pyx_t_1 = __pyx_t_2; + goto __pyx_L5_bool_binop_done; + } + + /* "View.MemoryView":1057 + * if ndim == 1: + * if (src_stride > 0 and dst_stride > 0 and + * src_stride == itemsize == dst_stride): # <<<<<<<<<<<<<< + * memcpy(dst_data, src_data, itemsize * dst_extent) + * else: +*/ + __pyx_t_2 = (((size_t)__pyx_v_src_stride) == __pyx_v_itemsize); + if (__pyx_t_2) { + __pyx_t_2 = (__pyx_v_itemsize == ((size_t)__pyx_v_dst_stride)); + } + __pyx_t_1 = __pyx_t_2; + __pyx_L5_bool_binop_done:; + + /* "View.MemoryView":1056 + * + * if ndim == 1: + * if (src_stride > 0 and dst_stride > 0 and # <<<<<<<<<<<<<< + * src_stride == itemsize == dst_stride): + * memcpy(dst_data, src_data, itemsize * dst_extent) +*/ + if (__pyx_t_1) { + + /* "View.MemoryView":1058 + * if (src_stride > 0 and dst_stride > 0 and + * src_stride == itemsize == dst_stride): + * memcpy(dst_data, src_data, itemsize * dst_extent) # <<<<<<<<<<<<<< + * else: + * for i in range(dst_extent): +*/ + (void)(memcpy(__pyx_v_dst_data, __pyx_v_src_data, (__pyx_v_itemsize * __pyx_v_dst_extent))); + + /* "View.MemoryView":1056 + * + * if ndim == 1: + * if (src_stride > 0 and dst_stride > 0 and # <<<<<<<<<<<<<< + * src_stride == itemsize == dst_stride): + * memcpy(dst_data, src_data, itemsize * dst_extent) +*/ + goto __pyx_L4; + } + + /* "View.MemoryView":1060 + * memcpy(dst_data, src_data, itemsize * dst_extent) + * else: + * for i in range(dst_extent): # <<<<<<<<<<<<<< + * memcpy(dst_data, src_data, itemsize) + * src_data += src_stride +*/ + /*else*/ { + __pyx_t_3 = __pyx_v_dst_extent; + __pyx_t_4 = __pyx_t_3; + for (__pyx_t_5 = 0; __pyx_t_5 < __pyx_t_4; __pyx_t_5+=1) { + __pyx_v_i = __pyx_t_5; + + /* "View.MemoryView":1061 + * else: + * for i in range(dst_extent): + * memcpy(dst_data, src_data, itemsize) # <<<<<<<<<<<<<< + * src_data += src_stride + * dst_data += dst_stride +*/ + (void)(memcpy(__pyx_v_dst_data, __pyx_v_src_data, __pyx_v_itemsize)); + + /* "View.MemoryView":1062 + * for i in range(dst_extent): + * memcpy(dst_data, src_data, itemsize) + * src_data += src_stride # <<<<<<<<<<<<<< + * dst_data += dst_stride + * else: +*/ + __pyx_v_src_data = (__pyx_v_src_data + __pyx_v_src_stride); + + /* "View.MemoryView":1063 + * memcpy(dst_data, src_data, itemsize) + * src_data += src_stride + * dst_data += dst_stride # <<<<<<<<<<<<<< + * else: + * for i in range(dst_extent): +*/ + __pyx_v_dst_data = (__pyx_v_dst_data + __pyx_v_dst_stride); + } + } + __pyx_L4:; + + /* "View.MemoryView":1055 + * cdef Py_ssize_t dst_stride = dst_strides[0] + * + * if ndim == 1: # <<<<<<<<<<<<<< + * if (src_stride > 0 and dst_stride > 0 and + * src_stride == itemsize == dst_stride): +*/ + goto __pyx_L3; + } + + /* "View.MemoryView":1065 + * dst_data += dst_stride + * else: + * for i in range(dst_extent): # <<<<<<<<<<<<<< + * _copy_strided_to_strided(src_data, src_strides + 1, + * dst_data, dst_strides + 1, +*/ + /*else*/ { + __pyx_t_3 = __pyx_v_dst_extent; + __pyx_t_4 = __pyx_t_3; + for (__pyx_t_5 = 0; __pyx_t_5 < __pyx_t_4; __pyx_t_5+=1) { + __pyx_v_i = __pyx_t_5; + + /* "View.MemoryView":1066 + * else: + * for i in range(dst_extent): + * _copy_strided_to_strided(src_data, src_strides + 1, # <<<<<<<<<<<<<< + * dst_data, dst_strides + 1, + * src_shape + 1, dst_shape + 1, +*/ + _copy_strided_to_strided(__pyx_v_src_data, (__pyx_v_src_strides + 1), __pyx_v_dst_data, (__pyx_v_dst_strides + 1), (__pyx_v_src_shape + 1), (__pyx_v_dst_shape + 1), (__pyx_v_ndim - 1), __pyx_v_itemsize); + + /* "View.MemoryView":1070 + * src_shape + 1, dst_shape + 1, + * ndim - 1, itemsize) + * src_data += src_stride # <<<<<<<<<<<<<< + * dst_data += dst_stride + * +*/ + __pyx_v_src_data = (__pyx_v_src_data + __pyx_v_src_stride); + + /* "View.MemoryView":1071 + * ndim - 1, itemsize) + * src_data += src_stride + * dst_data += dst_stride # <<<<<<<<<<<<<< + * + * cdef void copy_strided_to_strided(__Pyx_memviewslice *src, +*/ + __pyx_v_dst_data = (__pyx_v_dst_data + __pyx_v_dst_stride); + } + } + __pyx_L3:; + + /* "View.MemoryView":1042 + * return 'F' + * + * @cython.cdivision(True) # <<<<<<<<<<<<<< + * cdef void _copy_strided_to_strided(char *src_data, Py_ssize_t *src_strides, + * char *dst_data, Py_ssize_t *dst_strides, +*/ + + /* function exit code */ +} + +/* "View.MemoryView":1073 + * dst_data += dst_stride + * + * cdef void copy_strided_to_strided(__Pyx_memviewslice *src, # <<<<<<<<<<<<<< + * __Pyx_memviewslice *dst, + * int ndim, size_t itemsize) noexcept nogil: +*/ + +static void copy_strided_to_strided(__Pyx_memviewslice *__pyx_v_src, __Pyx_memviewslice *__pyx_v_dst, int __pyx_v_ndim, size_t __pyx_v_itemsize) { + + /* "View.MemoryView":1076 + * __Pyx_memviewslice *dst, + * int ndim, size_t itemsize) noexcept nogil: + * _copy_strided_to_strided(src.data, src.strides, dst.data, dst.strides, # <<<<<<<<<<<<<< + * src.shape, dst.shape, ndim, itemsize) + * +*/ + _copy_strided_to_strided(__pyx_v_src->data, __pyx_v_src->strides, __pyx_v_dst->data, __pyx_v_dst->strides, __pyx_v_src->shape, __pyx_v_dst->shape, __pyx_v_ndim, __pyx_v_itemsize); + + /* "View.MemoryView":1073 + * dst_data += dst_stride + * + * cdef void copy_strided_to_strided(__Pyx_memviewslice *src, # <<<<<<<<<<<<<< + * __Pyx_memviewslice *dst, + * int ndim, size_t itemsize) noexcept nogil: +*/ + + /* function exit code */ +} + +/* "View.MemoryView":1079 + * src.shape, dst.shape, ndim, itemsize) + * + * @cname('__pyx_memoryview_slice_get_size') # <<<<<<<<<<<<<< + * cdef Py_ssize_t slice_get_size(__Pyx_memviewslice *src, int ndim) noexcept nogil: + * "Return the size of the memory occupied by the slice in number of bytes" +*/ + +static Py_ssize_t __pyx_memoryview_slice_get_size(__Pyx_memviewslice *__pyx_v_src, int __pyx_v_ndim) { + Py_ssize_t __pyx_v_shape; + Py_ssize_t __pyx_v_size; + Py_ssize_t __pyx_r; + Py_ssize_t __pyx_t_1; + Py_ssize_t *__pyx_t_2; + Py_ssize_t *__pyx_t_3; + Py_ssize_t *__pyx_t_4; + + /* "View.MemoryView":1082 + * cdef Py_ssize_t slice_get_size(__Pyx_memviewslice *src, int ndim) noexcept nogil: + * "Return the size of the memory occupied by the slice in number of bytes" + * cdef Py_ssize_t shape, size = src.memview.view.itemsize # <<<<<<<<<<<<<< + * + * for shape in src.shape[:ndim]: +*/ + __pyx_t_1 = __pyx_v_src->memview->view.itemsize; + __pyx_v_size = __pyx_t_1; + + /* "View.MemoryView":1084 + * cdef Py_ssize_t shape, size = src.memview.view.itemsize + * + * for shape in src.shape[:ndim]: # <<<<<<<<<<<<<< + * size *= shape + * +*/ + __pyx_t_3 = (__pyx_v_src->shape + __pyx_v_ndim); + for (__pyx_t_4 = __pyx_v_src->shape; __pyx_t_4 < __pyx_t_3; __pyx_t_4++) { + __pyx_t_2 = __pyx_t_4; + __pyx_v_shape = (__pyx_t_2[0]); + + /* "View.MemoryView":1085 + * + * for shape in src.shape[:ndim]: + * size *= shape # <<<<<<<<<<<<<< + * + * return size +*/ + __pyx_v_size = (__pyx_v_size * __pyx_v_shape); + } + + /* "View.MemoryView":1087 + * size *= shape + * + * return size # <<<<<<<<<<<<<< + * + * @cname('__pyx_fill_contig_strides_array') +*/ + __pyx_r = __pyx_v_size; + goto __pyx_L0; + + /* "View.MemoryView":1079 + * src.shape, dst.shape, ndim, itemsize) + * + * @cname('__pyx_memoryview_slice_get_size') # <<<<<<<<<<<<<< + * cdef Py_ssize_t slice_get_size(__Pyx_memviewslice *src, int ndim) noexcept nogil: + * "Return the size of the memory occupied by the slice in number of bytes" +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "View.MemoryView":1089 + * return size + * + * @cname('__pyx_fill_contig_strides_array') # <<<<<<<<<<<<<< + * cdef Py_ssize_t fill_contig_strides_array( + * Py_ssize_t *shape, Py_ssize_t *strides, Py_ssize_t stride, +*/ + +static Py_ssize_t __pyx_fill_contig_strides_array(Py_ssize_t *__pyx_v_shape, Py_ssize_t *__pyx_v_strides, Py_ssize_t __pyx_v_stride, int __pyx_v_ndim, char __pyx_v_order) { + int __pyx_v_idx; + Py_ssize_t __pyx_r; + int __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + int __pyx_t_4; + + /* "View.MemoryView":1099 + * cdef int idx + * + * if order == 'F': # <<<<<<<<<<<<<< + * for idx in range(ndim): + * strides[idx] = stride +*/ + __pyx_t_1 = (__pyx_v_order == 'F'); + if (__pyx_t_1) { + + /* "View.MemoryView":1100 + * + * if order == 'F': + * for idx in range(ndim): # <<<<<<<<<<<<<< + * strides[idx] = stride + * stride *= shape[idx] +*/ + __pyx_t_2 = __pyx_v_ndim; + __pyx_t_3 = __pyx_t_2; + for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { + __pyx_v_idx = __pyx_t_4; + + /* "View.MemoryView":1101 + * if order == 'F': + * for idx in range(ndim): + * strides[idx] = stride # <<<<<<<<<<<<<< + * stride *= shape[idx] + * else: +*/ + (__pyx_v_strides[__pyx_v_idx]) = __pyx_v_stride; + + /* "View.MemoryView":1102 + * for idx in range(ndim): + * strides[idx] = stride + * stride *= shape[idx] # <<<<<<<<<<<<<< + * else: + * for idx in range(ndim - 1, -1, -1): +*/ + __pyx_v_stride = (__pyx_v_stride * (__pyx_v_shape[__pyx_v_idx])); + } + + /* "View.MemoryView":1099 + * cdef int idx + * + * if order == 'F': # <<<<<<<<<<<<<< + * for idx in range(ndim): + * strides[idx] = stride +*/ + goto __pyx_L3; + } + + /* "View.MemoryView":1104 + * stride *= shape[idx] + * else: + * for idx in range(ndim - 1, -1, -1): # <<<<<<<<<<<<<< + * strides[idx] = stride + * stride *= shape[idx] +*/ + /*else*/ { + for (__pyx_t_2 = (__pyx_v_ndim - 1); __pyx_t_2 > -1; __pyx_t_2-=1) { + __pyx_v_idx = __pyx_t_2; + + /* "View.MemoryView":1105 + * else: + * for idx in range(ndim - 1, -1, -1): + * strides[idx] = stride # <<<<<<<<<<<<<< + * stride *= shape[idx] + * +*/ + (__pyx_v_strides[__pyx_v_idx]) = __pyx_v_stride; + + /* "View.MemoryView":1106 + * for idx in range(ndim - 1, -1, -1): + * strides[idx] = stride + * stride *= shape[idx] # <<<<<<<<<<<<<< + * + * return stride +*/ + __pyx_v_stride = (__pyx_v_stride * (__pyx_v_shape[__pyx_v_idx])); + } + } + __pyx_L3:; + + /* "View.MemoryView":1108 + * stride *= shape[idx] + * + * return stride # <<<<<<<<<<<<<< + * + * @cname('__pyx_memoryview_copy_data_to_temp') +*/ + __pyx_r = __pyx_v_stride; + goto __pyx_L0; + + /* "View.MemoryView":1089 + * return size + * + * @cname('__pyx_fill_contig_strides_array') # <<<<<<<<<<<<<< + * cdef Py_ssize_t fill_contig_strides_array( + * Py_ssize_t *shape, Py_ssize_t *strides, Py_ssize_t stride, +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "View.MemoryView":1110 + * return stride + * + * @cname('__pyx_memoryview_copy_data_to_temp') # <<<<<<<<<<<<<< + * cdef void *copy_data_to_temp(__Pyx_memviewslice *src, + * __Pyx_memviewslice *tmpslice, +*/ + +static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src, __Pyx_memviewslice *__pyx_v_tmpslice, char __pyx_v_order, int __pyx_v_ndim) { + int __pyx_v_i; + void *__pyx_v_result; + size_t __pyx_v_itemsize; + size_t __pyx_v_size; + void *__pyx_r; + Py_ssize_t __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + struct __pyx_memoryview_obj *__pyx_t_4; + int __pyx_t_5; + int __pyx_t_6; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyGILState_STATE __pyx_gilstate_save; + + /* "View.MemoryView":1122 + * cdef void *result + * + * cdef size_t itemsize = src.memview.view.itemsize # <<<<<<<<<<<<<< + * cdef size_t size = slice_get_size(src, ndim) + * +*/ + __pyx_t_1 = __pyx_v_src->memview->view.itemsize; + __pyx_v_itemsize = __pyx_t_1; + + /* "View.MemoryView":1123 + * + * cdef size_t itemsize = src.memview.view.itemsize + * cdef size_t size = slice_get_size(src, ndim) # <<<<<<<<<<<<<< + * + * result = malloc(size) +*/ + __pyx_v_size = __pyx_memoryview_slice_get_size(__pyx_v_src, __pyx_v_ndim); + + /* "View.MemoryView":1125 + * cdef size_t size = slice_get_size(src, ndim) + * + * result = malloc(size) # <<<<<<<<<<<<<< + * if not result: + * _err_no_memory() +*/ + __pyx_v_result = malloc(__pyx_v_size); + + /* "View.MemoryView":1126 + * + * result = malloc(size) + * if not result: # <<<<<<<<<<<<<< + * _err_no_memory() + * +*/ + __pyx_t_2 = (!(__pyx_v_result != 0)); + if (__pyx_t_2) { + + /* "View.MemoryView":1127 + * result = malloc(size) + * if not result: + * _err_no_memory() # <<<<<<<<<<<<<< + * + * +*/ + __pyx_t_3 = __pyx_memoryview_err_no_memory(); if (unlikely(__pyx_t_3 == ((int)-1))) __PYX_ERR(1, 1127, __pyx_L1_error) + + /* "View.MemoryView":1126 + * + * result = malloc(size) + * if not result: # <<<<<<<<<<<<<< + * _err_no_memory() + * +*/ + } + + /* "View.MemoryView":1130 + * + * + * tmpslice.data = result # <<<<<<<<<<<<<< + * tmpslice.memview = src.memview + * for i in range(ndim): +*/ + __pyx_v_tmpslice->data = ((char *)__pyx_v_result); + + /* "View.MemoryView":1131 + * + * tmpslice.data = result + * tmpslice.memview = src.memview # <<<<<<<<<<<<<< + * for i in range(ndim): + * tmpslice.shape[i] = src.shape[i] +*/ + __pyx_t_4 = __pyx_v_src->memview; + __pyx_v_tmpslice->memview = __pyx_t_4; + + /* "View.MemoryView":1132 + * tmpslice.data = result + * tmpslice.memview = src.memview + * for i in range(ndim): # <<<<<<<<<<<<<< + * tmpslice.shape[i] = src.shape[i] + * tmpslice.suboffsets[i] = -1 +*/ + __pyx_t_3 = __pyx_v_ndim; + __pyx_t_5 = __pyx_t_3; + for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) { + __pyx_v_i = __pyx_t_6; + + /* "View.MemoryView":1133 + * tmpslice.memview = src.memview + * for i in range(ndim): + * tmpslice.shape[i] = src.shape[i] # <<<<<<<<<<<<<< + * tmpslice.suboffsets[i] = -1 + * +*/ + (__pyx_v_tmpslice->shape[__pyx_v_i]) = (__pyx_v_src->shape[__pyx_v_i]); + + /* "View.MemoryView":1134 + * for i in range(ndim): + * tmpslice.shape[i] = src.shape[i] + * tmpslice.suboffsets[i] = -1 # <<<<<<<<<<<<<< + * + * fill_contig_strides_array(&tmpslice.shape[0], &tmpslice.strides[0], itemsize, ndim, order) +*/ + (__pyx_v_tmpslice->suboffsets[__pyx_v_i]) = -1L; + } + + /* "View.MemoryView":1136 + * tmpslice.suboffsets[i] = -1 + * + * fill_contig_strides_array(&tmpslice.shape[0], &tmpslice.strides[0], itemsize, ndim, order) # <<<<<<<<<<<<<< + * + * +*/ + (void)(__pyx_fill_contig_strides_array((&(__pyx_v_tmpslice->shape[0])), (&(__pyx_v_tmpslice->strides[0])), __pyx_v_itemsize, __pyx_v_ndim, __pyx_v_order)); + + /* "View.MemoryView":1139 + * + * + * for i in range(ndim): # <<<<<<<<<<<<<< + * if tmpslice.shape[i] == 1: + * tmpslice.strides[i] = 0 +*/ + __pyx_t_3 = __pyx_v_ndim; + __pyx_t_5 = __pyx_t_3; + for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) { + __pyx_v_i = __pyx_t_6; + + /* "View.MemoryView":1140 + * + * for i in range(ndim): + * if tmpslice.shape[i] == 1: # <<<<<<<<<<<<<< + * tmpslice.strides[i] = 0 + * +*/ + __pyx_t_2 = ((__pyx_v_tmpslice->shape[__pyx_v_i]) == 1); + if (__pyx_t_2) { + + /* "View.MemoryView":1141 + * for i in range(ndim): + * if tmpslice.shape[i] == 1: + * tmpslice.strides[i] = 0 # <<<<<<<<<<<<<< + * + * if slice_is_contig(src[0], order, ndim): +*/ + (__pyx_v_tmpslice->strides[__pyx_v_i]) = 0; + + /* "View.MemoryView":1140 + * + * for i in range(ndim): + * if tmpslice.shape[i] == 1: # <<<<<<<<<<<<<< + * tmpslice.strides[i] = 0 + * +*/ + } + } + + /* "View.MemoryView":1143 + * tmpslice.strides[i] = 0 + * + * if slice_is_contig(src[0], order, ndim): # <<<<<<<<<<<<<< + * memcpy(result, src.data, size) + * else: +*/ + __pyx_t_2 = __pyx_memviewslice_is_contig((__pyx_v_src[0]), __pyx_v_order, __pyx_v_ndim); + if (__pyx_t_2) { + + /* "View.MemoryView":1144 + * + * if slice_is_contig(src[0], order, ndim): + * memcpy(result, src.data, size) # <<<<<<<<<<<<<< + * else: + * copy_strided_to_strided(src, tmpslice, ndim, itemsize) +*/ + (void)(memcpy(__pyx_v_result, __pyx_v_src->data, __pyx_v_size)); + + /* "View.MemoryView":1143 + * tmpslice.strides[i] = 0 + * + * if slice_is_contig(src[0], order, ndim): # <<<<<<<<<<<<<< + * memcpy(result, src.data, size) + * else: +*/ + goto __pyx_L9; + } + + /* "View.MemoryView":1146 + * memcpy(result, src.data, size) + * else: + * copy_strided_to_strided(src, tmpslice, ndim, itemsize) # <<<<<<<<<<<<<< + * + * return result +*/ + /*else*/ { + copy_strided_to_strided(__pyx_v_src, __pyx_v_tmpslice, __pyx_v_ndim, __pyx_v_itemsize); + } + __pyx_L9:; + + /* "View.MemoryView":1148 + * copy_strided_to_strided(src, tmpslice, ndim, itemsize) + * + * return result # <<<<<<<<<<<<<< + * + * +*/ + __pyx_r = __pyx_v_result; + goto __pyx_L0; + + /* "View.MemoryView":1110 + * return stride + * + * @cname('__pyx_memoryview_copy_data_to_temp') # <<<<<<<<<<<<<< + * cdef void *copy_data_to_temp(__Pyx_memviewslice *src, + * __Pyx_memviewslice *tmpslice, +*/ + + /* function exit code */ + __pyx_L1_error:; + __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); + __Pyx_AddTraceback("View.MemoryView.copy_data_to_temp", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __Pyx_PyGILState_Release(__pyx_gilstate_save); + __pyx_L0:; + return __pyx_r; +} + +/* "View.MemoryView":1152 + * + * + * @cname('__pyx_memoryview_err_extents') # <<<<<<<<<<<<<< + * cdef int _err_extents(int i, Py_ssize_t extent1, + * Py_ssize_t extent2) except -1 with gil: +*/ + +static int __pyx_memoryview_err_extents(int __pyx_v_i, Py_ssize_t __pyx_v_extent1, Py_ssize_t __pyx_v_extent2) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4[7]; + PyObject *__pyx_t_5 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); + __Pyx_RefNannySetupContext("_err_extents", 0); + + /* "View.MemoryView":1155 + * cdef int _err_extents(int i, Py_ssize_t extent1, + * Py_ssize_t extent2) except -1 with gil: + * raise ValueError, f"got differing extents in dimension {i} (got {extent1} and {extent2})" # <<<<<<<<<<<<<< + * + * @cname('__pyx_memoryview_err_dim') +*/ + __pyx_t_1 = __Pyx_PyUnicode_From_int(__pyx_v_i, 0, ' ', 'd'); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 1155, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyUnicode_From_Py_ssize_t(__pyx_v_extent1, 0, ' ', 'd'); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1155, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = __Pyx_PyUnicode_From_Py_ssize_t(__pyx_v_extent2, 0, ' ', 'd'); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 1155, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4[0] = __pyx_mstate_global->__pyx_kp_u_got_differing_extents_in_dimensi; + __pyx_t_4[1] = __pyx_t_1; + __pyx_t_4[2] = __pyx_mstate_global->__pyx_kp_u_got; + __pyx_t_4[3] = __pyx_t_2; + __pyx_t_4[4] = __pyx_mstate_global->__pyx_kp_u_and; + __pyx_t_4[5] = __pyx_t_3; + __pyx_t_4[6] = __pyx_mstate_global->__pyx_kp_u__5; + __pyx_t_5 = __Pyx_PyUnicode_Join(__pyx_t_4, 7, 35 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_1) + 6 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_2) + 5 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_3) + 1, 127); + if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 1155, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_Raise(((PyObject *)(((PyTypeObject*)PyExc_ValueError))), __pyx_t_5, 0, 0); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __PYX_ERR(1, 1155, __pyx_L1_error) + + /* "View.MemoryView":1152 + * + * + * @cname('__pyx_memoryview_err_extents') # <<<<<<<<<<<<<< + * cdef int _err_extents(int i, Py_ssize_t extent1, + * Py_ssize_t extent2) except -1 with gil: +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("View.MemoryView._err_extents", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __Pyx_RefNannyFinishContext(); + __Pyx_PyGILState_Release(__pyx_gilstate_save); + return __pyx_r; +} + +/* "View.MemoryView":1157 + * raise ValueError, f"got differing extents in dimension {i} (got {extent1} and {extent2})" + * + * @cname('__pyx_memoryview_err_dim') # <<<<<<<<<<<<<< + * cdef int _err_dim(PyObject *error, str msg, int dim) except -1 with gil: + * raise error, msg % dim +*/ + +static int __pyx_memoryview_err_dim(PyObject *__pyx_v_error, PyObject *__pyx_v_msg, int __pyx_v_dim) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); + __Pyx_RefNannySetupContext("_err_dim", 0); + __Pyx_INCREF(__pyx_v_msg); + + /* "View.MemoryView":1159 + * @cname('__pyx_memoryview_err_dim') + * cdef int _err_dim(PyObject *error, str msg, int dim) except -1 with gil: + * raise error, msg % dim # <<<<<<<<<<<<<< + * + * @cname('__pyx_memoryview_err') +*/ + __pyx_t_1 = __Pyx_PyLong_From_int(__pyx_v_dim); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 1159, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyUnicode_FormatSafe(__pyx_v_msg, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1159, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_Raise(((PyObject *)__pyx_v_error), __pyx_t_2, 0, 0); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __PYX_ERR(1, 1159, __pyx_L1_error) + + /* "View.MemoryView":1157 + * raise ValueError, f"got differing extents in dimension {i} (got {extent1} and {extent2})" + * + * @cname('__pyx_memoryview_err_dim') # <<<<<<<<<<<<<< + * cdef int _err_dim(PyObject *error, str msg, int dim) except -1 with gil: + * raise error, msg % dim +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("View.MemoryView._err_dim", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __Pyx_XDECREF(__pyx_v_msg); + __Pyx_RefNannyFinishContext(); + __Pyx_PyGILState_Release(__pyx_gilstate_save); + return __pyx_r; +} + +/* "View.MemoryView":1161 + * raise error, msg % dim + * + * @cname('__pyx_memoryview_err') # <<<<<<<<<<<<<< + * cdef int _err(PyObject *error, str msg) except -1 with gil: + * raise error, msg +*/ + +static int __pyx_memoryview_err(PyObject *__pyx_v_error, PyObject *__pyx_v_msg) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); + __Pyx_RefNannySetupContext("_err", 0); + __Pyx_INCREF(__pyx_v_msg); + + /* "View.MemoryView":1163 + * @cname('__pyx_memoryview_err') + * cdef int _err(PyObject *error, str msg) except -1 with gil: + * raise error, msg # <<<<<<<<<<<<<< + * + * @cname('__pyx_memoryview_err_no_memory') +*/ + __Pyx_Raise(((PyObject *)__pyx_v_error), __pyx_v_msg, 0, 0); + __PYX_ERR(1, 1163, __pyx_L1_error) + + /* "View.MemoryView":1161 + * raise error, msg % dim + * + * @cname('__pyx_memoryview_err') # <<<<<<<<<<<<<< + * cdef int _err(PyObject *error, str msg) except -1 with gil: + * raise error, msg +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_AddTraceback("View.MemoryView._err", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __Pyx_XDECREF(__pyx_v_msg); + __Pyx_RefNannyFinishContext(); + __Pyx_PyGILState_Release(__pyx_gilstate_save); + return __pyx_r; +} + +/* "View.MemoryView":1165 + * raise error, msg + * + * @cname('__pyx_memoryview_err_no_memory') # <<<<<<<<<<<<<< + * cdef int _err_no_memory() except -1 with gil: + * raise MemoryError +*/ + +static int __pyx_memoryview_err_no_memory(void) { + int __pyx_r; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); + + /* "View.MemoryView":1167 + * @cname('__pyx_memoryview_err_no_memory') + * cdef int _err_no_memory() except -1 with gil: + * raise MemoryError # <<<<<<<<<<<<<< + * + * +*/ + PyErr_NoMemory(); __PYX_ERR(1, 1167, __pyx_L1_error) + + /* "View.MemoryView":1165 + * raise error, msg + * + * @cname('__pyx_memoryview_err_no_memory') # <<<<<<<<<<<<<< + * cdef int _err_no_memory() except -1 with gil: + * raise MemoryError +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_AddTraceback("View.MemoryView._err_no_memory", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __Pyx_PyGILState_Release(__pyx_gilstate_save); + return __pyx_r; +} + +/* "View.MemoryView":1170 + * + * + * @cname('__pyx_memoryview_copy_contents') # <<<<<<<<<<<<<< + * cdef int memoryview_copy_contents(__Pyx_memviewslice src, + * __Pyx_memviewslice dst, +*/ + +static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_memviewslice __pyx_v_dst, int __pyx_v_src_ndim, int __pyx_v_dst_ndim, int __pyx_v_dtype_is_object) { + void *__pyx_v_tmpdata; + size_t __pyx_v_itemsize; + int __pyx_v_i; + char __pyx_v_order; + int __pyx_v_broadcasting; + int __pyx_v_direct_copy; + __Pyx_memviewslice __pyx_v_tmp; + int __pyx_v_ndim; + int __pyx_r; + Py_ssize_t __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + int __pyx_t_4; + int __pyx_t_5; + int __pyx_t_6; + void *__pyx_t_7; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyGILState_STATE __pyx_gilstate_save; + + /* "View.MemoryView":1179 + * Check for overlapping memory and verify the shapes. + * """ + * cdef void *tmpdata = NULL # <<<<<<<<<<<<<< + * cdef size_t itemsize = src.memview.view.itemsize + * cdef int i +*/ + __pyx_v_tmpdata = NULL; + + /* "View.MemoryView":1180 + * """ + * cdef void *tmpdata = NULL + * cdef size_t itemsize = src.memview.view.itemsize # <<<<<<<<<<<<<< + * cdef int i + * cdef char order = get_best_order(&src, src_ndim) +*/ + __pyx_t_1 = __pyx_v_src.memview->view.itemsize; + __pyx_v_itemsize = __pyx_t_1; + + /* "View.MemoryView":1182 + * cdef size_t itemsize = src.memview.view.itemsize + * cdef int i + * cdef char order = get_best_order(&src, src_ndim) # <<<<<<<<<<<<<< + * cdef bint broadcasting = False + * cdef bint direct_copy = False +*/ + __pyx_v_order = __pyx_get_best_slice_order((&__pyx_v_src), __pyx_v_src_ndim); + + /* "View.MemoryView":1183 + * cdef int i + * cdef char order = get_best_order(&src, src_ndim) + * cdef bint broadcasting = False # <<<<<<<<<<<<<< + * cdef bint direct_copy = False + * cdef __Pyx_memviewslice tmp +*/ + __pyx_v_broadcasting = 0; + + /* "View.MemoryView":1184 + * cdef char order = get_best_order(&src, src_ndim) + * cdef bint broadcasting = False + * cdef bint direct_copy = False # <<<<<<<<<<<<<< + * cdef __Pyx_memviewslice tmp + * +*/ + __pyx_v_direct_copy = 0; + + /* "View.MemoryView":1187 + * cdef __Pyx_memviewslice tmp + * + * if src_ndim < dst_ndim: # <<<<<<<<<<<<<< + * broadcast_leading(&src, src_ndim, dst_ndim) + * elif dst_ndim < src_ndim: +*/ + __pyx_t_2 = (__pyx_v_src_ndim < __pyx_v_dst_ndim); + if (__pyx_t_2) { + + /* "View.MemoryView":1188 + * + * if src_ndim < dst_ndim: + * broadcast_leading(&src, src_ndim, dst_ndim) # <<<<<<<<<<<<<< + * elif dst_ndim < src_ndim: + * broadcast_leading(&dst, dst_ndim, src_ndim) +*/ + __pyx_memoryview_broadcast_leading((&__pyx_v_src), __pyx_v_src_ndim, __pyx_v_dst_ndim); + + /* "View.MemoryView":1187 + * cdef __Pyx_memviewslice tmp + * + * if src_ndim < dst_ndim: # <<<<<<<<<<<<<< + * broadcast_leading(&src, src_ndim, dst_ndim) + * elif dst_ndim < src_ndim: +*/ + goto __pyx_L3; + } + + /* "View.MemoryView":1189 + * if src_ndim < dst_ndim: + * broadcast_leading(&src, src_ndim, dst_ndim) + * elif dst_ndim < src_ndim: # <<<<<<<<<<<<<< + * broadcast_leading(&dst, dst_ndim, src_ndim) + * +*/ + __pyx_t_2 = (__pyx_v_dst_ndim < __pyx_v_src_ndim); + if (__pyx_t_2) { + + /* "View.MemoryView":1190 + * broadcast_leading(&src, src_ndim, dst_ndim) + * elif dst_ndim < src_ndim: + * broadcast_leading(&dst, dst_ndim, src_ndim) # <<<<<<<<<<<<<< + * + * cdef int ndim = max(src_ndim, dst_ndim) +*/ + __pyx_memoryview_broadcast_leading((&__pyx_v_dst), __pyx_v_dst_ndim, __pyx_v_src_ndim); + + /* "View.MemoryView":1189 + * if src_ndim < dst_ndim: + * broadcast_leading(&src, src_ndim, dst_ndim) + * elif dst_ndim < src_ndim: # <<<<<<<<<<<<<< + * broadcast_leading(&dst, dst_ndim, src_ndim) + * +*/ + } + __pyx_L3:; + + /* "View.MemoryView":1192 + * broadcast_leading(&dst, dst_ndim, src_ndim) + * + * cdef int ndim = max(src_ndim, dst_ndim) # <<<<<<<<<<<<<< + * + * for i in range(ndim): +*/ + __pyx_t_3 = __pyx_v_dst_ndim; + __pyx_t_4 = __pyx_v_src_ndim; + __pyx_t_2 = (__pyx_t_3 > __pyx_t_4); + if (__pyx_t_2) { + __pyx_t_5 = __pyx_t_3; + } else { + __pyx_t_5 = __pyx_t_4; + } + __pyx_v_ndim = __pyx_t_5; + + /* "View.MemoryView":1194 + * cdef int ndim = max(src_ndim, dst_ndim) + * + * for i in range(ndim): # <<<<<<<<<<<<<< + * if src.shape[i] != dst.shape[i]: + * if src.shape[i] == 1: +*/ + __pyx_t_5 = __pyx_v_ndim; + __pyx_t_3 = __pyx_t_5; + for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { + __pyx_v_i = __pyx_t_4; + + /* "View.MemoryView":1195 + * + * for i in range(ndim): + * if src.shape[i] != dst.shape[i]: # <<<<<<<<<<<<<< + * if src.shape[i] == 1: + * broadcasting = True +*/ + __pyx_t_2 = ((__pyx_v_src.shape[__pyx_v_i]) != (__pyx_v_dst.shape[__pyx_v_i])); + if (__pyx_t_2) { + + /* "View.MemoryView":1196 + * for i in range(ndim): + * if src.shape[i] != dst.shape[i]: + * if src.shape[i] == 1: # <<<<<<<<<<<<<< + * broadcasting = True + * src.strides[i] = 0 +*/ + __pyx_t_2 = ((__pyx_v_src.shape[__pyx_v_i]) == 1); + if (__pyx_t_2) { + + /* "View.MemoryView":1197 + * if src.shape[i] != dst.shape[i]: + * if src.shape[i] == 1: + * broadcasting = True # <<<<<<<<<<<<<< + * src.strides[i] = 0 + * else: +*/ + __pyx_v_broadcasting = 1; + + /* "View.MemoryView":1198 + * if src.shape[i] == 1: + * broadcasting = True + * src.strides[i] = 0 # <<<<<<<<<<<<<< + * else: + * _err_extents(i, dst.shape[i], src.shape[i]) +*/ + (__pyx_v_src.strides[__pyx_v_i]) = 0; + + /* "View.MemoryView":1196 + * for i in range(ndim): + * if src.shape[i] != dst.shape[i]: + * if src.shape[i] == 1: # <<<<<<<<<<<<<< + * broadcasting = True + * src.strides[i] = 0 +*/ + goto __pyx_L7; + } + + /* "View.MemoryView":1200 + * src.strides[i] = 0 + * else: + * _err_extents(i, dst.shape[i], src.shape[i]) # <<<<<<<<<<<<<< + * + * if src.suboffsets[i] >= 0: +*/ + /*else*/ { + __pyx_t_6 = __pyx_memoryview_err_extents(__pyx_v_i, (__pyx_v_dst.shape[__pyx_v_i]), (__pyx_v_src.shape[__pyx_v_i])); if (unlikely(__pyx_t_6 == ((int)-1))) __PYX_ERR(1, 1200, __pyx_L1_error) + } + __pyx_L7:; + + /* "View.MemoryView":1195 + * + * for i in range(ndim): + * if src.shape[i] != dst.shape[i]: # <<<<<<<<<<<<<< + * if src.shape[i] == 1: + * broadcasting = True +*/ + } + + /* "View.MemoryView":1202 + * _err_extents(i, dst.shape[i], src.shape[i]) + * + * if src.suboffsets[i] >= 0: # <<<<<<<<<<<<<< + * _err_dim(PyExc_ValueError, "Dimension %d is not direct", i) + * +*/ + __pyx_t_2 = ((__pyx_v_src.suboffsets[__pyx_v_i]) >= 0); + if (__pyx_t_2) { + + /* "View.MemoryView":1203 + * + * if src.suboffsets[i] >= 0: + * _err_dim(PyExc_ValueError, "Dimension %d is not direct", i) # <<<<<<<<<<<<<< + * + * if slices_overlap(&src, &dst, ndim, itemsize): +*/ + __pyx_t_6 = __pyx_memoryview_err_dim(PyExc_ValueError, __pyx_mstate_global->__pyx_kp_u_Dimension_d_is_not_direct, __pyx_v_i); if (unlikely(__pyx_t_6 == ((int)-1))) __PYX_ERR(1, 1203, __pyx_L1_error) + + /* "View.MemoryView":1202 + * _err_extents(i, dst.shape[i], src.shape[i]) + * + * if src.suboffsets[i] >= 0: # <<<<<<<<<<<<<< + * _err_dim(PyExc_ValueError, "Dimension %d is not direct", i) + * +*/ + } + } + + /* "View.MemoryView":1205 + * _err_dim(PyExc_ValueError, "Dimension %d is not direct", i) + * + * if slices_overlap(&src, &dst, ndim, itemsize): # <<<<<<<<<<<<<< + * + * if not slice_is_contig(src, order, ndim): +*/ + __pyx_t_2 = __pyx_slices_overlap((&__pyx_v_src), (&__pyx_v_dst), __pyx_v_ndim, __pyx_v_itemsize); + if (__pyx_t_2) { + + /* "View.MemoryView":1207 + * if slices_overlap(&src, &dst, ndim, itemsize): + * + * if not slice_is_contig(src, order, ndim): # <<<<<<<<<<<<<< + * order = get_best_order(&dst, ndim) + * +*/ + __pyx_t_2 = (!__pyx_memviewslice_is_contig(__pyx_v_src, __pyx_v_order, __pyx_v_ndim)); + if (__pyx_t_2) { + + /* "View.MemoryView":1208 + * + * if not slice_is_contig(src, order, ndim): + * order = get_best_order(&dst, ndim) # <<<<<<<<<<<<<< + * + * tmpdata = copy_data_to_temp(&src, &tmp, order, ndim) +*/ + __pyx_v_order = __pyx_get_best_slice_order((&__pyx_v_dst), __pyx_v_ndim); + + /* "View.MemoryView":1207 + * if slices_overlap(&src, &dst, ndim, itemsize): + * + * if not slice_is_contig(src, order, ndim): # <<<<<<<<<<<<<< + * order = get_best_order(&dst, ndim) + * +*/ + } + + /* "View.MemoryView":1210 + * order = get_best_order(&dst, ndim) + * + * tmpdata = copy_data_to_temp(&src, &tmp, order, ndim) # <<<<<<<<<<<<<< + * src = tmp + * +*/ + __pyx_t_7 = __pyx_memoryview_copy_data_to_temp((&__pyx_v_src), (&__pyx_v_tmp), __pyx_v_order, __pyx_v_ndim); if (unlikely(__pyx_t_7 == ((void *)NULL))) __PYX_ERR(1, 1210, __pyx_L1_error) + __pyx_v_tmpdata = __pyx_t_7; + + /* "View.MemoryView":1211 + * + * tmpdata = copy_data_to_temp(&src, &tmp, order, ndim) + * src = tmp # <<<<<<<<<<<<<< + * + * if not broadcasting: +*/ + __pyx_v_src = __pyx_v_tmp; + + /* "View.MemoryView":1205 + * _err_dim(PyExc_ValueError, "Dimension %d is not direct", i) + * + * if slices_overlap(&src, &dst, ndim, itemsize): # <<<<<<<<<<<<<< + * + * if not slice_is_contig(src, order, ndim): +*/ + } + + /* "View.MemoryView":1213 + * src = tmp + * + * if not broadcasting: # <<<<<<<<<<<<<< + * + * +*/ + __pyx_t_2 = (!__pyx_v_broadcasting); + if (__pyx_t_2) { + + /* "View.MemoryView":1216 + * + * + * if slice_is_contig(src, 'C', ndim): # <<<<<<<<<<<<<< + * direct_copy = slice_is_contig(dst, 'C', ndim) + * elif slice_is_contig(src, 'F', ndim): +*/ + __pyx_t_2 = __pyx_memviewslice_is_contig(__pyx_v_src, 'C', __pyx_v_ndim); + if (__pyx_t_2) { + + /* "View.MemoryView":1217 + * + * if slice_is_contig(src, 'C', ndim): + * direct_copy = slice_is_contig(dst, 'C', ndim) # <<<<<<<<<<<<<< + * elif slice_is_contig(src, 'F', ndim): + * direct_copy = slice_is_contig(dst, 'F', ndim) +*/ + __pyx_v_direct_copy = __pyx_memviewslice_is_contig(__pyx_v_dst, 'C', __pyx_v_ndim); + + /* "View.MemoryView":1216 + * + * + * if slice_is_contig(src, 'C', ndim): # <<<<<<<<<<<<<< + * direct_copy = slice_is_contig(dst, 'C', ndim) + * elif slice_is_contig(src, 'F', ndim): +*/ + goto __pyx_L12; + } + + /* "View.MemoryView":1218 + * if slice_is_contig(src, 'C', ndim): + * direct_copy = slice_is_contig(dst, 'C', ndim) + * elif slice_is_contig(src, 'F', ndim): # <<<<<<<<<<<<<< + * direct_copy = slice_is_contig(dst, 'F', ndim) + * +*/ + __pyx_t_2 = __pyx_memviewslice_is_contig(__pyx_v_src, 'F', __pyx_v_ndim); + if (__pyx_t_2) { + + /* "View.MemoryView":1219 + * direct_copy = slice_is_contig(dst, 'C', ndim) + * elif slice_is_contig(src, 'F', ndim): + * direct_copy = slice_is_contig(dst, 'F', ndim) # <<<<<<<<<<<<<< + * + * if direct_copy: +*/ + __pyx_v_direct_copy = __pyx_memviewslice_is_contig(__pyx_v_dst, 'F', __pyx_v_ndim); + + /* "View.MemoryView":1218 + * if slice_is_contig(src, 'C', ndim): + * direct_copy = slice_is_contig(dst, 'C', ndim) + * elif slice_is_contig(src, 'F', ndim): # <<<<<<<<<<<<<< + * direct_copy = slice_is_contig(dst, 'F', ndim) + * +*/ + } + __pyx_L12:; + + /* "View.MemoryView":1221 + * direct_copy = slice_is_contig(dst, 'F', ndim) + * + * if direct_copy: # <<<<<<<<<<<<<< + * + * refcount_copying(&dst, dtype_is_object, ndim, inc=False) +*/ + if (__pyx_v_direct_copy) { + + /* "View.MemoryView":1223 + * if direct_copy: + * + * refcount_copying(&dst, dtype_is_object, ndim, inc=False) # <<<<<<<<<<<<<< + * memcpy(dst.data, src.data, slice_get_size(&src, ndim)) + * refcount_copying(&dst, dtype_is_object, ndim, inc=True) +*/ + __pyx_memoryview_refcount_copying((&__pyx_v_dst), __pyx_v_dtype_is_object, __pyx_v_ndim, 0); + + /* "View.MemoryView":1224 + * + * refcount_copying(&dst, dtype_is_object, ndim, inc=False) + * memcpy(dst.data, src.data, slice_get_size(&src, ndim)) # <<<<<<<<<<<<<< + * refcount_copying(&dst, dtype_is_object, ndim, inc=True) + * free(tmpdata) +*/ + (void)(memcpy(__pyx_v_dst.data, __pyx_v_src.data, __pyx_memoryview_slice_get_size((&__pyx_v_src), __pyx_v_ndim))); + + /* "View.MemoryView":1225 + * refcount_copying(&dst, dtype_is_object, ndim, inc=False) + * memcpy(dst.data, src.data, slice_get_size(&src, ndim)) + * refcount_copying(&dst, dtype_is_object, ndim, inc=True) # <<<<<<<<<<<<<< + * free(tmpdata) + * return 0 +*/ + __pyx_memoryview_refcount_copying((&__pyx_v_dst), __pyx_v_dtype_is_object, __pyx_v_ndim, 1); + + /* "View.MemoryView":1226 + * memcpy(dst.data, src.data, slice_get_size(&src, ndim)) + * refcount_copying(&dst, dtype_is_object, ndim, inc=True) + * free(tmpdata) # <<<<<<<<<<<<<< + * return 0 + * +*/ + free(__pyx_v_tmpdata); + + /* "View.MemoryView":1227 + * refcount_copying(&dst, dtype_is_object, ndim, inc=True) + * free(tmpdata) + * return 0 # <<<<<<<<<<<<<< + * + * if order == 'F' == get_best_order(&dst, ndim): +*/ + __pyx_r = 0; + goto __pyx_L0; + + /* "View.MemoryView":1221 + * direct_copy = slice_is_contig(dst, 'F', ndim) + * + * if direct_copy: # <<<<<<<<<<<<<< + * + * refcount_copying(&dst, dtype_is_object, ndim, inc=False) +*/ + } + + /* "View.MemoryView":1213 + * src = tmp + * + * if not broadcasting: # <<<<<<<<<<<<<< + * + * +*/ + } + + /* "View.MemoryView":1229 + * return 0 + * + * if order == 'F' == get_best_order(&dst, ndim): # <<<<<<<<<<<<<< + * + * +*/ + __pyx_t_2 = (__pyx_v_order == 'F'); + if (__pyx_t_2) { + __pyx_t_2 = ('F' == __pyx_get_best_slice_order((&__pyx_v_dst), __pyx_v_ndim)); + } + if (__pyx_t_2) { + + /* "View.MemoryView":1232 + * + * + * transpose_memslice(&src) # <<<<<<<<<<<<<< + * transpose_memslice(&dst) + * +*/ + __pyx_t_5 = __pyx_memslice_transpose((&__pyx_v_src)); if (unlikely(__pyx_t_5 == ((int)-1))) __PYX_ERR(1, 1232, __pyx_L1_error) + + /* "View.MemoryView":1233 + * + * transpose_memslice(&src) + * transpose_memslice(&dst) # <<<<<<<<<<<<<< + * + * refcount_copying(&dst, dtype_is_object, ndim, inc=False) +*/ + __pyx_t_5 = __pyx_memslice_transpose((&__pyx_v_dst)); if (unlikely(__pyx_t_5 == ((int)-1))) __PYX_ERR(1, 1233, __pyx_L1_error) + + /* "View.MemoryView":1229 + * return 0 + * + * if order == 'F' == get_best_order(&dst, ndim): # <<<<<<<<<<<<<< + * + * +*/ + } + + /* "View.MemoryView":1235 + * transpose_memslice(&dst) + * + * refcount_copying(&dst, dtype_is_object, ndim, inc=False) # <<<<<<<<<<<<<< + * copy_strided_to_strided(&src, &dst, ndim, itemsize) + * refcount_copying(&dst, dtype_is_object, ndim, inc=True) +*/ + __pyx_memoryview_refcount_copying((&__pyx_v_dst), __pyx_v_dtype_is_object, __pyx_v_ndim, 0); + + /* "View.MemoryView":1236 + * + * refcount_copying(&dst, dtype_is_object, ndim, inc=False) + * copy_strided_to_strided(&src, &dst, ndim, itemsize) # <<<<<<<<<<<<<< + * refcount_copying(&dst, dtype_is_object, ndim, inc=True) + * +*/ + copy_strided_to_strided((&__pyx_v_src), (&__pyx_v_dst), __pyx_v_ndim, __pyx_v_itemsize); + + /* "View.MemoryView":1237 + * refcount_copying(&dst, dtype_is_object, ndim, inc=False) + * copy_strided_to_strided(&src, &dst, ndim, itemsize) + * refcount_copying(&dst, dtype_is_object, ndim, inc=True) # <<<<<<<<<<<<<< + * + * free(tmpdata) +*/ + __pyx_memoryview_refcount_copying((&__pyx_v_dst), __pyx_v_dtype_is_object, __pyx_v_ndim, 1); + + /* "View.MemoryView":1239 + * refcount_copying(&dst, dtype_is_object, ndim, inc=True) + * + * free(tmpdata) # <<<<<<<<<<<<<< + * return 0 + * +*/ + free(__pyx_v_tmpdata); + + /* "View.MemoryView":1240 + * + * free(tmpdata) + * return 0 # <<<<<<<<<<<<<< + * + * @cname('__pyx_memoryview_broadcast_leading') +*/ + __pyx_r = 0; + goto __pyx_L0; + + /* "View.MemoryView":1170 + * + * + * @cname('__pyx_memoryview_copy_contents') # <<<<<<<<<<<<<< + * cdef int memoryview_copy_contents(__Pyx_memviewslice src, + * __Pyx_memviewslice dst, +*/ + + /* function exit code */ + __pyx_L1_error:; + __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); + __Pyx_AddTraceback("View.MemoryView.memoryview_copy_contents", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __Pyx_PyGILState_Release(__pyx_gilstate_save); + __pyx_L0:; + return __pyx_r; +} + +/* "View.MemoryView":1242 + * return 0 + * + * @cname('__pyx_memoryview_broadcast_leading') # <<<<<<<<<<<<<< + * cdef void broadcast_leading(__Pyx_memviewslice *mslice, + * int ndim, +*/ + +static void __pyx_memoryview_broadcast_leading(__Pyx_memviewslice *__pyx_v_mslice, int __pyx_v_ndim, int __pyx_v_ndim_other) { + int __pyx_v_i; + int __pyx_v_offset; + int __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + + /* "View.MemoryView":1247 + * int ndim_other) noexcept nogil: + * cdef int i + * cdef int offset = ndim_other - ndim # <<<<<<<<<<<<<< + * + * for i in range(ndim - 1, -1, -1): +*/ + __pyx_v_offset = (__pyx_v_ndim_other - __pyx_v_ndim); + + /* "View.MemoryView":1249 + * cdef int offset = ndim_other - ndim + * + * for i in range(ndim - 1, -1, -1): # <<<<<<<<<<<<<< + * mslice.shape[i + offset] = mslice.shape[i] + * mslice.strides[i + offset] = mslice.strides[i] +*/ + for (__pyx_t_1 = (__pyx_v_ndim - 1); __pyx_t_1 > -1; __pyx_t_1-=1) { + __pyx_v_i = __pyx_t_1; + + /* "View.MemoryView":1250 + * + * for i in range(ndim - 1, -1, -1): + * mslice.shape[i + offset] = mslice.shape[i] # <<<<<<<<<<<<<< + * mslice.strides[i + offset] = mslice.strides[i] + * mslice.suboffsets[i + offset] = mslice.suboffsets[i] +*/ + (__pyx_v_mslice->shape[(__pyx_v_i + __pyx_v_offset)]) = (__pyx_v_mslice->shape[__pyx_v_i]); + + /* "View.MemoryView":1251 + * for i in range(ndim - 1, -1, -1): + * mslice.shape[i + offset] = mslice.shape[i] + * mslice.strides[i + offset] = mslice.strides[i] # <<<<<<<<<<<<<< + * mslice.suboffsets[i + offset] = mslice.suboffsets[i] + * +*/ + (__pyx_v_mslice->strides[(__pyx_v_i + __pyx_v_offset)]) = (__pyx_v_mslice->strides[__pyx_v_i]); + + /* "View.MemoryView":1252 + * mslice.shape[i + offset] = mslice.shape[i] + * mslice.strides[i + offset] = mslice.strides[i] + * mslice.suboffsets[i + offset] = mslice.suboffsets[i] # <<<<<<<<<<<<<< + * + * for i in range(offset): +*/ + (__pyx_v_mslice->suboffsets[(__pyx_v_i + __pyx_v_offset)]) = (__pyx_v_mslice->suboffsets[__pyx_v_i]); + } + + /* "View.MemoryView":1254 + * mslice.suboffsets[i + offset] = mslice.suboffsets[i] + * + * for i in range(offset): # <<<<<<<<<<<<<< + * mslice.shape[i] = 1 + * mslice.strides[i] = mslice.strides[0] +*/ + __pyx_t_1 = __pyx_v_offset; + __pyx_t_2 = __pyx_t_1; + for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) { + __pyx_v_i = __pyx_t_3; + + /* "View.MemoryView":1255 + * + * for i in range(offset): + * mslice.shape[i] = 1 # <<<<<<<<<<<<<< + * mslice.strides[i] = mslice.strides[0] + * mslice.suboffsets[i] = -1 +*/ + (__pyx_v_mslice->shape[__pyx_v_i]) = 1; + + /* "View.MemoryView":1256 + * for i in range(offset): + * mslice.shape[i] = 1 + * mslice.strides[i] = mslice.strides[0] # <<<<<<<<<<<<<< + * mslice.suboffsets[i] = -1 + * +*/ + (__pyx_v_mslice->strides[__pyx_v_i]) = (__pyx_v_mslice->strides[0]); + + /* "View.MemoryView":1257 + * mslice.shape[i] = 1 + * mslice.strides[i] = mslice.strides[0] + * mslice.suboffsets[i] = -1 # <<<<<<<<<<<<<< + * + * +*/ + (__pyx_v_mslice->suboffsets[__pyx_v_i]) = -1L; + } + + /* "View.MemoryView":1242 + * return 0 + * + * @cname('__pyx_memoryview_broadcast_leading') # <<<<<<<<<<<<<< + * cdef void broadcast_leading(__Pyx_memviewslice *mslice, + * int ndim, +*/ + + /* function exit code */ +} + +/* "View.MemoryView":1264 + * + * + * @cname('__pyx_memoryview_refcount_copying') # <<<<<<<<<<<<<< + * cdef void refcount_copying(__Pyx_memviewslice *dst, bint dtype_is_object, int ndim, bint inc) noexcept nogil: + * +*/ + +static void __pyx_memoryview_refcount_copying(__Pyx_memviewslice *__pyx_v_dst, int __pyx_v_dtype_is_object, int __pyx_v_ndim, int __pyx_v_inc) { + + /* "View.MemoryView":1267 + * cdef void refcount_copying(__Pyx_memviewslice *dst, bint dtype_is_object, int ndim, bint inc) noexcept nogil: + * + * if dtype_is_object: # <<<<<<<<<<<<<< + * refcount_objects_in_slice_with_gil(dst.data, dst.shape, dst.strides, ndim, inc) + * +*/ + if (__pyx_v_dtype_is_object) { + + /* "View.MemoryView":1268 + * + * if dtype_is_object: + * refcount_objects_in_slice_with_gil(dst.data, dst.shape, dst.strides, ndim, inc) # <<<<<<<<<<<<<< + * + * @cname('__pyx_memoryview_refcount_objects_in_slice_with_gil') +*/ + __pyx_memoryview_refcount_objects_in_slice_with_gil(__pyx_v_dst->data, __pyx_v_dst->shape, __pyx_v_dst->strides, __pyx_v_ndim, __pyx_v_inc); + + /* "View.MemoryView":1267 + * cdef void refcount_copying(__Pyx_memviewslice *dst, bint dtype_is_object, int ndim, bint inc) noexcept nogil: + * + * if dtype_is_object: # <<<<<<<<<<<<<< + * refcount_objects_in_slice_with_gil(dst.data, dst.shape, dst.strides, ndim, inc) + * +*/ + } + + /* "View.MemoryView":1264 + * + * + * @cname('__pyx_memoryview_refcount_copying') # <<<<<<<<<<<<<< + * cdef void refcount_copying(__Pyx_memviewslice *dst, bint dtype_is_object, int ndim, bint inc) noexcept nogil: + * +*/ + + /* function exit code */ +} + +/* "View.MemoryView":1270 + * refcount_objects_in_slice_with_gil(dst.data, dst.shape, dst.strides, ndim, inc) + * + * @cname('__pyx_memoryview_refcount_objects_in_slice_with_gil') # <<<<<<<<<<<<<< + * cdef void refcount_objects_in_slice_with_gil(char *data, Py_ssize_t *shape, + * Py_ssize_t *strides, int ndim, +*/ + +static void __pyx_memoryview_refcount_objects_in_slice_with_gil(char *__pyx_v_data, Py_ssize_t *__pyx_v_shape, Py_ssize_t *__pyx_v_strides, int __pyx_v_ndim, int __pyx_v_inc) { + PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); + + /* "View.MemoryView":1274 + * Py_ssize_t *strides, int ndim, + * bint inc) noexcept with gil: + * refcount_objects_in_slice(data, shape, strides, ndim, inc) # <<<<<<<<<<<<<< + * + * @cname('__pyx_memoryview_refcount_objects_in_slice') +*/ + __pyx_memoryview_refcount_objects_in_slice(__pyx_v_data, __pyx_v_shape, __pyx_v_strides, __pyx_v_ndim, __pyx_v_inc); + + /* "View.MemoryView":1270 + * refcount_objects_in_slice_with_gil(dst.data, dst.shape, dst.strides, ndim, inc) + * + * @cname('__pyx_memoryview_refcount_objects_in_slice_with_gil') # <<<<<<<<<<<<<< + * cdef void refcount_objects_in_slice_with_gil(char *data, Py_ssize_t *shape, + * Py_ssize_t *strides, int ndim, +*/ + + /* function exit code */ + __Pyx_PyGILState_Release(__pyx_gilstate_save); +} + +/* "View.MemoryView":1276 + * refcount_objects_in_slice(data, shape, strides, ndim, inc) + * + * @cname('__pyx_memoryview_refcount_objects_in_slice') # <<<<<<<<<<<<<< + * cdef void refcount_objects_in_slice(char *data, Py_ssize_t *shape, + * Py_ssize_t *strides, int ndim, bint inc) noexcept: +*/ + +static void __pyx_memoryview_refcount_objects_in_slice(char *__pyx_v_data, Py_ssize_t *__pyx_v_shape, Py_ssize_t *__pyx_v_strides, int __pyx_v_ndim, int __pyx_v_inc) { + CYTHON_UNUSED Py_ssize_t __pyx_v_i; + Py_ssize_t __pyx_v_stride; + Py_ssize_t __pyx_t_1; + Py_ssize_t __pyx_t_2; + Py_ssize_t __pyx_t_3; + int __pyx_t_4; + + /* "View.MemoryView":1280 + * Py_ssize_t *strides, int ndim, bint inc) noexcept: + * cdef Py_ssize_t i + * cdef Py_ssize_t stride = strides[0] # <<<<<<<<<<<<<< + * + * for i in range(shape[0]): +*/ + __pyx_v_stride = (__pyx_v_strides[0]); + + /* "View.MemoryView":1282 + * cdef Py_ssize_t stride = strides[0] + * + * for i in range(shape[0]): # <<<<<<<<<<<<<< + * if ndim == 1: + * if inc: +*/ + __pyx_t_1 = (__pyx_v_shape[0]); + __pyx_t_2 = __pyx_t_1; + for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) { + __pyx_v_i = __pyx_t_3; + + /* "View.MemoryView":1283 + * + * for i in range(shape[0]): + * if ndim == 1: # <<<<<<<<<<<<<< + * if inc: + * Py_INCREF(( data)[0]) +*/ + __pyx_t_4 = (__pyx_v_ndim == 1); + if (__pyx_t_4) { + + /* "View.MemoryView":1284 + * for i in range(shape[0]): + * if ndim == 1: + * if inc: # <<<<<<<<<<<<<< + * Py_INCREF(( data)[0]) + * else: +*/ + if (__pyx_v_inc) { + + /* "View.MemoryView":1285 + * if ndim == 1: + * if inc: + * Py_INCREF(( data)[0]) # <<<<<<<<<<<<<< + * else: + * Py_DECREF(( data)[0]) +*/ + Py_INCREF((((PyObject **)__pyx_v_data)[0])); + + /* "View.MemoryView":1284 + * for i in range(shape[0]): + * if ndim == 1: + * if inc: # <<<<<<<<<<<<<< + * Py_INCREF(( data)[0]) + * else: +*/ + goto __pyx_L6; + } + + /* "View.MemoryView":1287 + * Py_INCREF(( data)[0]) + * else: + * Py_DECREF(( data)[0]) # <<<<<<<<<<<<<< + * else: + * refcount_objects_in_slice(data, shape + 1, strides + 1, ndim - 1, inc) +*/ + /*else*/ { + Py_DECREF((((PyObject **)__pyx_v_data)[0])); + } + __pyx_L6:; + + /* "View.MemoryView":1283 + * + * for i in range(shape[0]): + * if ndim == 1: # <<<<<<<<<<<<<< + * if inc: + * Py_INCREF(( data)[0]) +*/ + goto __pyx_L5; + } + + /* "View.MemoryView":1289 + * Py_DECREF(( data)[0]) + * else: + * refcount_objects_in_slice(data, shape + 1, strides + 1, ndim - 1, inc) # <<<<<<<<<<<<<< + * + * data += stride +*/ + /*else*/ { + __pyx_memoryview_refcount_objects_in_slice(__pyx_v_data, (__pyx_v_shape + 1), (__pyx_v_strides + 1), (__pyx_v_ndim - 1), __pyx_v_inc); + } + __pyx_L5:; + + /* "View.MemoryView":1291 + * refcount_objects_in_slice(data, shape + 1, strides + 1, ndim - 1, inc) + * + * data += stride # <<<<<<<<<<<<<< + * + * +*/ + __pyx_v_data = (__pyx_v_data + __pyx_v_stride); + } + + /* "View.MemoryView":1276 + * refcount_objects_in_slice(data, shape, strides, ndim, inc) + * + * @cname('__pyx_memoryview_refcount_objects_in_slice') # <<<<<<<<<<<<<< + * cdef void refcount_objects_in_slice(char *data, Py_ssize_t *shape, + * Py_ssize_t *strides, int ndim, bint inc) noexcept: +*/ + + /* function exit code */ +} + +/* "View.MemoryView":1296 + * + * + * @cname('__pyx_memoryview_slice_assign_scalar') # <<<<<<<<<<<<<< + * cdef void slice_assign_scalar(__Pyx_memviewslice *dst, int ndim, + * size_t itemsize, void *item, +*/ + +static void __pyx_memoryview_slice_assign_scalar(__Pyx_memviewslice *__pyx_v_dst, int __pyx_v_ndim, size_t __pyx_v_itemsize, void *__pyx_v_item, int __pyx_v_dtype_is_object) { + + /* "View.MemoryView":1300 + * size_t itemsize, void *item, + * bint dtype_is_object) noexcept nogil: + * refcount_copying(dst, dtype_is_object, ndim, inc=False) # <<<<<<<<<<<<<< + * _slice_assign_scalar(dst.data, dst.shape, dst.strides, ndim, itemsize, item) + * refcount_copying(dst, dtype_is_object, ndim, inc=True) +*/ + __pyx_memoryview_refcount_copying(__pyx_v_dst, __pyx_v_dtype_is_object, __pyx_v_ndim, 0); + + /* "View.MemoryView":1301 + * bint dtype_is_object) noexcept nogil: + * refcount_copying(dst, dtype_is_object, ndim, inc=False) + * _slice_assign_scalar(dst.data, dst.shape, dst.strides, ndim, itemsize, item) # <<<<<<<<<<<<<< + * refcount_copying(dst, dtype_is_object, ndim, inc=True) + * +*/ + __pyx_memoryview__slice_assign_scalar(__pyx_v_dst->data, __pyx_v_dst->shape, __pyx_v_dst->strides, __pyx_v_ndim, __pyx_v_itemsize, __pyx_v_item); + + /* "View.MemoryView":1302 + * refcount_copying(dst, dtype_is_object, ndim, inc=False) + * _slice_assign_scalar(dst.data, dst.shape, dst.strides, ndim, itemsize, item) + * refcount_copying(dst, dtype_is_object, ndim, inc=True) # <<<<<<<<<<<<<< + * + * +*/ + __pyx_memoryview_refcount_copying(__pyx_v_dst, __pyx_v_dtype_is_object, __pyx_v_ndim, 1); + + /* "View.MemoryView":1296 + * + * + * @cname('__pyx_memoryview_slice_assign_scalar') # <<<<<<<<<<<<<< + * cdef void slice_assign_scalar(__Pyx_memviewslice *dst, int ndim, + * size_t itemsize, void *item, +*/ + + /* function exit code */ +} + +/* "View.MemoryView":1305 + * + * + * @cname('__pyx_memoryview__slice_assign_scalar') # <<<<<<<<<<<<<< + * cdef void _slice_assign_scalar(char *data, Py_ssize_t *shape, + * Py_ssize_t *strides, int ndim, +*/ + +static void __pyx_memoryview__slice_assign_scalar(char *__pyx_v_data, Py_ssize_t *__pyx_v_shape, Py_ssize_t *__pyx_v_strides, int __pyx_v_ndim, size_t __pyx_v_itemsize, void *__pyx_v_item) { + CYTHON_UNUSED Py_ssize_t __pyx_v_i; + Py_ssize_t __pyx_v_stride; + Py_ssize_t __pyx_v_extent; + int __pyx_t_1; + Py_ssize_t __pyx_t_2; + Py_ssize_t __pyx_t_3; + Py_ssize_t __pyx_t_4; + + /* "View.MemoryView":1310 + * size_t itemsize, void *item) noexcept nogil: + * cdef Py_ssize_t i + * cdef Py_ssize_t stride = strides[0] # <<<<<<<<<<<<<< + * cdef Py_ssize_t extent = shape[0] + * +*/ + __pyx_v_stride = (__pyx_v_strides[0]); + + /* "View.MemoryView":1311 + * cdef Py_ssize_t i + * cdef Py_ssize_t stride = strides[0] + * cdef Py_ssize_t extent = shape[0] # <<<<<<<<<<<<<< + * + * if ndim == 1: +*/ + __pyx_v_extent = (__pyx_v_shape[0]); + + /* "View.MemoryView":1313 + * cdef Py_ssize_t extent = shape[0] + * + * if ndim == 1: # <<<<<<<<<<<<<< + * for i in range(extent): + * memcpy(data, item, itemsize) +*/ + __pyx_t_1 = (__pyx_v_ndim == 1); + if (__pyx_t_1) { + + /* "View.MemoryView":1314 + * + * if ndim == 1: + * for i in range(extent): # <<<<<<<<<<<<<< + * memcpy(data, item, itemsize) + * data += stride +*/ + __pyx_t_2 = __pyx_v_extent; + __pyx_t_3 = __pyx_t_2; + for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { + __pyx_v_i = __pyx_t_4; + + /* "View.MemoryView":1315 + * if ndim == 1: + * for i in range(extent): + * memcpy(data, item, itemsize) # <<<<<<<<<<<<<< + * data += stride + * else: +*/ + (void)(memcpy(__pyx_v_data, __pyx_v_item, __pyx_v_itemsize)); + + /* "View.MemoryView":1316 + * for i in range(extent): + * memcpy(data, item, itemsize) + * data += stride # <<<<<<<<<<<<<< + * else: + * for i in range(extent): +*/ + __pyx_v_data = (__pyx_v_data + __pyx_v_stride); + } + + /* "View.MemoryView":1313 + * cdef Py_ssize_t extent = shape[0] + * + * if ndim == 1: # <<<<<<<<<<<<<< + * for i in range(extent): + * memcpy(data, item, itemsize) +*/ + goto __pyx_L3; + } + + /* "View.MemoryView":1318 + * data += stride + * else: + * for i in range(extent): # <<<<<<<<<<<<<< + * _slice_assign_scalar(data, shape + 1, strides + 1, ndim - 1, itemsize, item) + * data += stride +*/ + /*else*/ { + __pyx_t_2 = __pyx_v_extent; + __pyx_t_3 = __pyx_t_2; + for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { + __pyx_v_i = __pyx_t_4; + + /* "View.MemoryView":1319 + * else: + * for i in range(extent): + * _slice_assign_scalar(data, shape + 1, strides + 1, ndim - 1, itemsize, item) # <<<<<<<<<<<<<< + * data += stride + * +*/ + __pyx_memoryview__slice_assign_scalar(__pyx_v_data, (__pyx_v_shape + 1), (__pyx_v_strides + 1), (__pyx_v_ndim - 1), __pyx_v_itemsize, __pyx_v_item); + + /* "View.MemoryView":1320 + * for i in range(extent): + * _slice_assign_scalar(data, shape + 1, strides + 1, ndim - 1, itemsize, item) + * data += stride # <<<<<<<<<<<<<< + * +*/ + __pyx_v_data = (__pyx_v_data + __pyx_v_stride); + } + } + __pyx_L3:; + + /* "View.MemoryView":1305 + * + * + * @cname('__pyx_memoryview__slice_assign_scalar') # <<<<<<<<<<<<<< + * cdef void _slice_assign_scalar(char *data, Py_ssize_t *shape, + * Py_ssize_t *strides, int ndim, +*/ + + /* function exit code */ +} + +/* "(tree fragment)":4 + * int __Pyx_CheckUnpickleChecksum(long, long, long, long, const char*) except -1 + * int __Pyx_UpdateUnpickledDict(object, object, Py_ssize_t) except -1 + * def __pyx_unpickle_Enum(__pyx_type, long __pyx_checksum, tuple __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_result + * __Pyx_CheckUnpickleChecksum(__pyx_checksum, 0x82a3537, 0x6ae9995, 0xb068931, b'name') +*/ + +/* Python wrapper */ +static PyObject *__pyx_pw_15View_dot_MemoryView_1__pyx_unpickle_Enum(PyObject *__pyx_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +); /*proto*/ +static PyMethodDef __pyx_mdef_15View_dot_MemoryView_1__pyx_unpickle_Enum = {"__pyx_unpickle_Enum", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_15View_dot_MemoryView_1__pyx_unpickle_Enum, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_15View_dot_MemoryView_1__pyx_unpickle_Enum(PyObject *__pyx_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +) { + PyObject *__pyx_v___pyx_type = 0; + long __pyx_v___pyx_checksum; + PyObject *__pyx_v___pyx_state = 0; + #if !CYTHON_METH_FASTCALL + CYTHON_UNUSED Py_ssize_t __pyx_nargs; + #endif + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject* values[3] = {0,0,0}; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__pyx_unpickle_Enum (wrapper)", 0); + #if !CYTHON_METH_FASTCALL + #if CYTHON_ASSUME_SAFE_SIZE + __pyx_nargs = PyTuple_GET_SIZE(__pyx_args); + #else + __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL; + #endif + #endif + __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs); + { + PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_pyx_type,&__pyx_mstate_global->__pyx_n_u_pyx_checksum,&__pyx_mstate_global->__pyx_n_u_pyx_state,0}; + const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0; + if (unlikely(__pyx_kwds_len < 0)) __PYX_ERR(1, 4, __pyx_L3_error) + if (__pyx_kwds_len > 0) { + switch (__pyx_nargs) { + case 3: + values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(1, 4, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 2: + values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(1, 4, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 1: + values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(1, 4, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + const Py_ssize_t kwd_pos_args = __pyx_nargs; + if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "__pyx_unpickle_Enum", 0) < (0)) __PYX_ERR(1, 4, __pyx_L3_error) + for (Py_ssize_t i = __pyx_nargs; i < 3; i++) { + if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_Enum", 1, 3, 3, i); __PYX_ERR(1, 4, __pyx_L3_error) } + } + } else if (unlikely(__pyx_nargs != 3)) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(1, 4, __pyx_L3_error) + values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(1, 4, __pyx_L3_error) + values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(1, 4, __pyx_L3_error) + } + __pyx_v___pyx_type = values[0]; + __pyx_v___pyx_checksum = __Pyx_PyLong_As_long(values[1]); if (unlikely((__pyx_v___pyx_checksum == (long)-1) && PyErr_Occurred())) __PYX_ERR(1, 4, __pyx_L3_error) + __pyx_v___pyx_state = ((PyObject*)values[2]); + } + goto __pyx_L6_skip; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_Enum", 1, 3, 3, __pyx_nargs); __PYX_ERR(1, 4, __pyx_L3_error) + __pyx_L6_skip:; + goto __pyx_L4_argument_unpacking_done; + __pyx_L3_error:; + for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { + Py_XDECREF(values[__pyx_temp]); + } + __Pyx_AddTraceback("View.MemoryView.__pyx_unpickle_Enum", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v___pyx_state), (&PyTuple_Type), 1, "__pyx_state", 1))) __PYX_ERR(1, 4, __pyx_L1_error) + __pyx_r = __pyx_pf_15View_dot_MemoryView___pyx_unpickle_Enum(__pyx_self, __pyx_v___pyx_type, __pyx_v___pyx_checksum, __pyx_v___pyx_state); + + /* function exit code */ + goto __pyx_L0; + __pyx_L1_error:; + __pyx_r = NULL; + for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { + Py_XDECREF(values[__pyx_temp]); + } + goto __pyx_L7_cleaned_up; + __pyx_L0:; + for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { + Py_XDECREF(values[__pyx_temp]); + } + __pyx_L7_cleaned_up:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_15View_dot_MemoryView___pyx_unpickle_Enum(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_v___pyx_result = 0; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + size_t __pyx_t_4; + int __pyx_t_5; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__pyx_unpickle_Enum", 0); + + /* "(tree fragment)":6 + * def __pyx_unpickle_Enum(__pyx_type, long __pyx_checksum, tuple __pyx_state): + * cdef object __pyx_result + * __Pyx_CheckUnpickleChecksum(__pyx_checksum, 0x82a3537, 0x6ae9995, 0xb068931, b'name') # <<<<<<<<<<<<<< + * __pyx_result = Enum.__new__(__pyx_type) + * if __pyx_state is not None: +*/ + __pyx_t_1 = __Pyx_CheckUnpickleChecksum(__pyx_v___pyx_checksum, 0x82a3537, 0x6ae9995, 0xb068931, __pyx_k_name); if (unlikely(__pyx_t_1 == ((int)-1))) __PYX_ERR(1, 6, __pyx_L1_error) + + /* "(tree fragment)":7 + * cdef object __pyx_result + * __Pyx_CheckUnpickleChecksum(__pyx_checksum, 0x82a3537, 0x6ae9995, 0xb068931, b'name') + * __pyx_result = Enum.__new__(__pyx_type) # <<<<<<<<<<<<<< + * if __pyx_state is not None: + * __pyx_unpickle_Enum__set_state( __pyx_result, __pyx_state) +*/ + __pyx_t_3 = ((PyObject *)__pyx_mstate_global->__pyx_MemviewEnum_type); + __Pyx_INCREF(__pyx_t_3); + __pyx_t_4 = 0; + { + PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_v___pyx_type}; + __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_new, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + } + __pyx_v___pyx_result = __pyx_t_2; + __pyx_t_2 = 0; + + /* "(tree fragment)":8 + * __Pyx_CheckUnpickleChecksum(__pyx_checksum, 0x82a3537, 0x6ae9995, 0xb068931, b'name') + * __pyx_result = Enum.__new__(__pyx_type) + * if __pyx_state is not None: # <<<<<<<<<<<<<< + * __pyx_unpickle_Enum__set_state( __pyx_result, __pyx_state) + * return __pyx_result +*/ + __pyx_t_5 = (__pyx_v___pyx_state != ((PyObject*)Py_None)); + if (__pyx_t_5) { + + /* "(tree fragment)":9 + * __pyx_result = Enum.__new__(__pyx_type) + * if __pyx_state is not None: + * __pyx_unpickle_Enum__set_state( __pyx_result, __pyx_state) # <<<<<<<<<<<<<< + * return __pyx_result + * cdef __pyx_unpickle_Enum__set_state(Enum __pyx_result, __pyx_state: tuple): +*/ + if (unlikely(__pyx_v___pyx_state == Py_None)) { + PyErr_SetString(PyExc_TypeError, "cannot pass None into a C function argument that is declared 'not None'"); + __PYX_ERR(1, 9, __pyx_L1_error) + } + __pyx_t_2 = __pyx_unpickle_Enum__set_state(((struct __pyx_MemviewEnum_obj *)__pyx_v___pyx_result), __pyx_v___pyx_state); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "(tree fragment)":8 + * __Pyx_CheckUnpickleChecksum(__pyx_checksum, 0x82a3537, 0x6ae9995, 0xb068931, b'name') + * __pyx_result = Enum.__new__(__pyx_type) + * if __pyx_state is not None: # <<<<<<<<<<<<<< + * __pyx_unpickle_Enum__set_state( __pyx_result, __pyx_state) + * return __pyx_result +*/ + } + + /* "(tree fragment)":10 + * if __pyx_state is not None: + * __pyx_unpickle_Enum__set_state( __pyx_result, __pyx_state) + * return __pyx_result # <<<<<<<<<<<<<< + * cdef __pyx_unpickle_Enum__set_state(Enum __pyx_result, __pyx_state: tuple): + * __pyx_result.name = __pyx_state[0] +*/ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v___pyx_result); + __pyx_r = __pyx_v___pyx_result; + goto __pyx_L0; + + /* "(tree fragment)":4 + * int __Pyx_CheckUnpickleChecksum(long, long, long, long, const char*) except -1 + * int __Pyx_UpdateUnpickledDict(object, object, Py_ssize_t) except -1 + * def __pyx_unpickle_Enum(__pyx_type, long __pyx_checksum, tuple __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_result + * __Pyx_CheckUnpickleChecksum(__pyx_checksum, 0x82a3537, 0x6ae9995, 0xb068931, b'name') +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_AddTraceback("View.MemoryView.__pyx_unpickle_Enum", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v___pyx_result); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":11 + * __pyx_unpickle_Enum__set_state( __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle_Enum__set_state(Enum __pyx_result, __pyx_state: tuple): # <<<<<<<<<<<<<< + * __pyx_result.name = __pyx_state[0] + * __Pyx_UpdateUnpickledDict(__pyx_result, __pyx_state, 1) +*/ + +static PyObject *__pyx_unpickle_Enum__set_state(struct __pyx_MemviewEnum_obj *__pyx_v___pyx_result, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__pyx_unpickle_Enum__set_state", 0); + + /* "(tree fragment)":12 + * return __pyx_result + * cdef __pyx_unpickle_Enum__set_state(Enum __pyx_result, __pyx_state: tuple): + * __pyx_result.name = __pyx_state[0] # <<<<<<<<<<<<<< + * __Pyx_UpdateUnpickledDict(__pyx_result, __pyx_state, 1) +*/ + __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v___pyx_result->name); + __Pyx_DECREF(__pyx_v___pyx_result->name); + __pyx_v___pyx_result->name = __pyx_t_1; + __pyx_t_1 = 0; + + /* "(tree fragment)":13 + * cdef __pyx_unpickle_Enum__set_state(Enum __pyx_result, __pyx_state: tuple): + * __pyx_result.name = __pyx_state[0] + * __Pyx_UpdateUnpickledDict(__pyx_result, __pyx_state, 1) # <<<<<<<<<<<<<< +*/ + __pyx_t_2 = __Pyx_UpdateUnpickledDict(((PyObject *)__pyx_v___pyx_result), __pyx_v___pyx_state, 1); if (unlikely(__pyx_t_2 == ((int)-1))) __PYX_ERR(1, 13, __pyx_L1_error) + + /* "(tree fragment)":11 + * __pyx_unpickle_Enum__set_state( __pyx_result, __pyx_state) + * return __pyx_result + * cdef __pyx_unpickle_Enum__set_state(Enum __pyx_result, __pyx_state: tuple): # <<<<<<<<<<<<<< + * __pyx_result.name = __pyx_state[0] + * __Pyx_UpdateUnpickledDict(__pyx_result, __pyx_state, 1) +*/ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("View.MemoryView.__pyx_unpickle_Enum__set_state", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":243 + * cdef int type_num + * + * @property # <<<<<<<<<<<<<< + * cdef inline npy_intp itemsize(self) noexcept nogil: + * return PyDataType_ELSIZE(self) +*/ + +static CYTHON_INLINE npy_intp __pyx_f_5numpy_5dtype_8itemsize_itemsize(PyArray_Descr *__pyx_v_self) { + npy_intp __pyx_r; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":245 + * @property + * cdef inline npy_intp itemsize(self) noexcept nogil: + * return PyDataType_ELSIZE(self) # <<<<<<<<<<<<<< + * + * @property +*/ + __pyx_r = PyDataType_ELSIZE(__pyx_v_self); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":243 + * cdef int type_num + * + * @property # <<<<<<<<<<<<<< + * cdef inline npy_intp itemsize(self) noexcept nogil: + * return PyDataType_ELSIZE(self) +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":247 + * return PyDataType_ELSIZE(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline npy_intp alignment(self) noexcept nogil: + * return PyDataType_ALIGNMENT(self) +*/ + +static CYTHON_INLINE npy_intp __pyx_f_5numpy_5dtype_9alignment_alignment(PyArray_Descr *__pyx_v_self) { + npy_intp __pyx_r; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":249 + * @property + * cdef inline npy_intp alignment(self) noexcept nogil: + * return PyDataType_ALIGNMENT(self) # <<<<<<<<<<<<<< + * + * # Use fields/names with care as they may be NULL. You must check +*/ + __pyx_r = PyDataType_ALIGNMENT(__pyx_v_self); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":247 + * return PyDataType_ELSIZE(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline npy_intp alignment(self) noexcept nogil: + * return PyDataType_ALIGNMENT(self) +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":253 + * # Use fields/names with care as they may be NULL. You must check + * # for this using PyDataType_HASFIELDS. + * @property # <<<<<<<<<<<<<< + * cdef inline object fields(self): + * return PyDataType_FIELDS(self) +*/ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_5dtype_6fields_fields(PyArray_Descr *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1; + __Pyx_RefNannySetupContext("fields", 0); + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":255 + * @property + * cdef inline object fields(self): + * return PyDataType_FIELDS(self) # <<<<<<<<<<<<<< + * + * @property +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyDataType_FIELDS(__pyx_v_self); + __Pyx_INCREF(((PyObject *)__pyx_t_1)); + __pyx_r = ((PyObject *)__pyx_t_1); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":253 + * # Use fields/names with care as they may be NULL. You must check + * # for this using PyDataType_HASFIELDS. + * @property # <<<<<<<<<<<<<< + * cdef inline object fields(self): + * return PyDataType_FIELDS(self) +*/ + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":257 + * return PyDataType_FIELDS(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline tuple names(self): + * return PyDataType_NAMES(self) +*/ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_5dtype_5names_names(PyArray_Descr *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1; + __Pyx_RefNannySetupContext("names", 0); + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":259 + * @property + * cdef inline tuple names(self): + * return PyDataType_NAMES(self) # <<<<<<<<<<<<<< + * + * # Use PyDataType_HASSUBARRAY to test whether this field is +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyDataType_NAMES(__pyx_v_self); + __Pyx_INCREF(((PyObject*)__pyx_t_1)); + __pyx_r = ((PyObject*)__pyx_t_1); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":257 + * return PyDataType_FIELDS(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline tuple names(self): + * return PyDataType_NAMES(self) +*/ + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":264 + * # valid (the pointer can be NULL). Most users should access + * # this field via the inline helper method PyDataType_SHAPE. + * @property # <<<<<<<<<<<<<< + * cdef inline PyArray_ArrayDescr* subarray(self) noexcept nogil: + * return PyDataType_SUBARRAY(self) +*/ + +static CYTHON_INLINE PyArray_ArrayDescr *__pyx_f_5numpy_5dtype_8subarray_subarray(PyArray_Descr *__pyx_v_self) { + PyArray_ArrayDescr *__pyx_r; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":266 + * @property + * cdef inline PyArray_ArrayDescr* subarray(self) noexcept nogil: + * return PyDataType_SUBARRAY(self) # <<<<<<<<<<<<<< + * + * @property +*/ + __pyx_r = PyDataType_SUBARRAY(__pyx_v_self); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":264 + * # valid (the pointer can be NULL). Most users should access + * # this field via the inline helper method PyDataType_SHAPE. + * @property # <<<<<<<<<<<<<< + * cdef inline PyArray_ArrayDescr* subarray(self) noexcept nogil: + * return PyDataType_SUBARRAY(self) +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":268 + * return PyDataType_SUBARRAY(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline npy_uint64 flags(self) noexcept nogil: + * """The data types flags.""" +*/ + +static CYTHON_INLINE npy_uint64 __pyx_f_5numpy_5dtype_5flags_flags(PyArray_Descr *__pyx_v_self) { + npy_uint64 __pyx_r; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":271 + * cdef inline npy_uint64 flags(self) noexcept nogil: + * """The data types flags.""" + * return PyDataType_FLAGS(self) # <<<<<<<<<<<<<< + * + * +*/ + __pyx_r = PyDataType_FLAGS(__pyx_v_self); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":268 + * return PyDataType_SUBARRAY(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline npy_uint64 flags(self) noexcept nogil: + * """The data types flags.""" +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":280 + * ctypedef class numpy.broadcast [object PyArrayMultiIterObject, check_size ignore]: + * + * @property # <<<<<<<<<<<<<< + * cdef inline int numiter(self) noexcept nogil: + * """The number of arrays that need to be broadcast to the same shape.""" +*/ + +static CYTHON_INLINE int __pyx_f_5numpy_9broadcast_7numiter_numiter(PyArrayMultiIterObject *__pyx_v_self) { + int __pyx_r; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":283 + * cdef inline int numiter(self) noexcept nogil: + * """The number of arrays that need to be broadcast to the same shape.""" + * return PyArray_MultiIter_NUMITER(self) # <<<<<<<<<<<<<< + * + * @property +*/ + __pyx_r = PyArray_MultiIter_NUMITER(__pyx_v_self); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":280 + * ctypedef class numpy.broadcast [object PyArrayMultiIterObject, check_size ignore]: + * + * @property # <<<<<<<<<<<<<< + * cdef inline int numiter(self) noexcept nogil: + * """The number of arrays that need to be broadcast to the same shape.""" +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":285 + * return PyArray_MultiIter_NUMITER(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline npy_intp size(self) noexcept nogil: + * """The total broadcasted size.""" +*/ + +static CYTHON_INLINE npy_intp __pyx_f_5numpy_9broadcast_4size_size(PyArrayMultiIterObject *__pyx_v_self) { + npy_intp __pyx_r; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":288 + * cdef inline npy_intp size(self) noexcept nogil: + * """The total broadcasted size.""" + * return PyArray_MultiIter_SIZE(self) # <<<<<<<<<<<<<< + * + * @property +*/ + __pyx_r = PyArray_MultiIter_SIZE(__pyx_v_self); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":285 + * return PyArray_MultiIter_NUMITER(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline npy_intp size(self) noexcept nogil: + * """The total broadcasted size.""" +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":290 + * return PyArray_MultiIter_SIZE(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline npy_intp index(self) noexcept nogil: + * """The current (1-d) index into the broadcasted result.""" +*/ + +static CYTHON_INLINE npy_intp __pyx_f_5numpy_9broadcast_5index_index(PyArrayMultiIterObject *__pyx_v_self) { + npy_intp __pyx_r; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":293 + * cdef inline npy_intp index(self) noexcept nogil: + * """The current (1-d) index into the broadcasted result.""" + * return PyArray_MultiIter_INDEX(self) # <<<<<<<<<<<<<< + * + * @property +*/ + __pyx_r = PyArray_MultiIter_INDEX(__pyx_v_self); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":290 + * return PyArray_MultiIter_SIZE(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline npy_intp index(self) noexcept nogil: + * """The current (1-d) index into the broadcasted result.""" +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":295 + * return PyArray_MultiIter_INDEX(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline int nd(self) noexcept nogil: + * """The number of dimensions in the broadcasted result.""" +*/ + +static CYTHON_INLINE int __pyx_f_5numpy_9broadcast_2nd_nd(PyArrayMultiIterObject *__pyx_v_self) { + int __pyx_r; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":298 + * cdef inline int nd(self) noexcept nogil: + * """The number of dimensions in the broadcasted result.""" + * return PyArray_MultiIter_NDIM(self) # <<<<<<<<<<<<<< + * + * @property +*/ + __pyx_r = PyArray_MultiIter_NDIM(__pyx_v_self); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":295 + * return PyArray_MultiIter_INDEX(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline int nd(self) noexcept nogil: + * """The number of dimensions in the broadcasted result.""" +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":300 + * return PyArray_MultiIter_NDIM(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline npy_intp* dimensions(self) noexcept nogil: + * """The shape of the broadcasted result.""" +*/ + +static CYTHON_INLINE npy_intp *__pyx_f_5numpy_9broadcast_10dimensions_dimensions(PyArrayMultiIterObject *__pyx_v_self) { + npy_intp *__pyx_r; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":303 + * cdef inline npy_intp* dimensions(self) noexcept nogil: + * """The shape of the broadcasted result.""" + * return PyArray_MultiIter_DIMS(self) # <<<<<<<<<<<<<< + * + * @property +*/ + __pyx_r = PyArray_MultiIter_DIMS(__pyx_v_self); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":300 + * return PyArray_MultiIter_NDIM(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline npy_intp* dimensions(self) noexcept nogil: + * """The shape of the broadcasted result.""" +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":305 + * return PyArray_MultiIter_DIMS(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline void** iters(self) noexcept nogil: + * """An array of iterator objects that holds the iterators for the arrays to be broadcast together. +*/ + +static CYTHON_INLINE void **__pyx_f_5numpy_9broadcast_5iters_iters(PyArrayMultiIterObject *__pyx_v_self) { + void **__pyx_r; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":309 + * """An array of iterator objects that holds the iterators for the arrays to be broadcast together. + * On return, the iterators are adjusted for broadcasting.""" + * return PyArray_MultiIter_ITERS(self) # <<<<<<<<<<<<<< + * + * +*/ + __pyx_r = PyArray_MultiIter_ITERS(__pyx_v_self); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":305 + * return PyArray_MultiIter_DIMS(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline void** iters(self) noexcept nogil: + * """An array of iterator objects that holds the iterators for the arrays to be broadcast together. +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":323 + * # Instead, we use properties that map to the corresponding C-API functions. + * + * @property # <<<<<<<<<<<<<< + * cdef inline PyObject* base(self) noexcept nogil: + * """Returns a borrowed reference to the object owning the data/memory. +*/ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_7ndarray_4base_base(PyArrayObject *__pyx_v_self) { + PyObject *__pyx_r; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":327 + * """Returns a borrowed reference to the object owning the data/memory. + * """ + * return PyArray_BASE(self) # <<<<<<<<<<<<<< + * + * @property +*/ + __pyx_r = PyArray_BASE(__pyx_v_self); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":323 + * # Instead, we use properties that map to the corresponding C-API functions. + * + * @property # <<<<<<<<<<<<<< + * cdef inline PyObject* base(self) noexcept nogil: + * """Returns a borrowed reference to the object owning the data/memory. +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":329 + * return PyArray_BASE(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline dtype descr(self): + * """Returns an owned reference to the dtype of the array. +*/ + +static CYTHON_INLINE PyArray_Descr *__pyx_f_5numpy_7ndarray_5descr_descr(PyArrayObject *__pyx_v_self) { + PyArray_Descr *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyArray_Descr *__pyx_t_1; + __Pyx_RefNannySetupContext("descr", 0); + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":333 + * """Returns an owned reference to the dtype of the array. + * """ + * return PyArray_DESCR(self) # <<<<<<<<<<<<<< + * + * @property +*/ + __Pyx_XDECREF((PyObject *)__pyx_r); + __pyx_t_1 = PyArray_DESCR(__pyx_v_self); + __Pyx_INCREF((PyObject *)((PyArray_Descr *)__pyx_t_1)); + __pyx_r = ((PyArray_Descr *)__pyx_t_1); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":329 + * return PyArray_BASE(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline dtype descr(self): + * """Returns an owned reference to the dtype of the array. +*/ + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF((PyObject *)__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":335 + * return PyArray_DESCR(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline int ndim(self) noexcept nogil: + * """Returns the number of dimensions in the array. +*/ + +static CYTHON_INLINE int __pyx_f_5numpy_7ndarray_4ndim_ndim(PyArrayObject *__pyx_v_self) { + int __pyx_r; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":339 + * """Returns the number of dimensions in the array. + * """ + * return PyArray_NDIM(self) # <<<<<<<<<<<<<< + * + * @property +*/ + __pyx_r = PyArray_NDIM(__pyx_v_self); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":335 + * return PyArray_DESCR(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline int ndim(self) noexcept nogil: + * """Returns the number of dimensions in the array. +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":341 + * return PyArray_NDIM(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline npy_intp *shape(self) noexcept nogil: + * """Returns a pointer to the dimensions/shape of the array. +*/ + +static CYTHON_INLINE npy_intp *__pyx_f_5numpy_7ndarray_5shape_shape(PyArrayObject *__pyx_v_self) { + npy_intp *__pyx_r; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":347 + * Can return NULL for 0-dimensional arrays. + * """ + * return PyArray_DIMS(self) # <<<<<<<<<<<<<< + * + * @property +*/ + __pyx_r = PyArray_DIMS(__pyx_v_self); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":341 + * return PyArray_NDIM(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline npy_intp *shape(self) noexcept nogil: + * """Returns a pointer to the dimensions/shape of the array. +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":349 + * return PyArray_DIMS(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline npy_intp *strides(self) noexcept nogil: + * """Returns a pointer to the strides of the array. +*/ + +static CYTHON_INLINE npy_intp *__pyx_f_5numpy_7ndarray_7strides_strides(PyArrayObject *__pyx_v_self) { + npy_intp *__pyx_r; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":354 + * The number of elements matches the number of dimensions of the array (ndim). + * """ + * return PyArray_STRIDES(self) # <<<<<<<<<<<<<< + * + * @property +*/ + __pyx_r = PyArray_STRIDES(__pyx_v_self); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":349 + * return PyArray_DIMS(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline npy_intp *strides(self) noexcept nogil: + * """Returns a pointer to the strides of the array. +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":356 + * return PyArray_STRIDES(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline npy_intp size(self) noexcept nogil: + * """Returns the total size (in number of elements) of the array. +*/ + +static CYTHON_INLINE npy_intp __pyx_f_5numpy_7ndarray_4size_size(PyArrayObject *__pyx_v_self) { + npy_intp __pyx_r; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":360 + * """Returns the total size (in number of elements) of the array. + * """ + * return PyArray_SIZE(self) # <<<<<<<<<<<<<< + * + * @property +*/ + __pyx_r = PyArray_SIZE(__pyx_v_self); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":356 + * return PyArray_STRIDES(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline npy_intp size(self) noexcept nogil: + * """Returns the total size (in number of elements) of the array. +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":362 + * return PyArray_SIZE(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline char* data(self) noexcept nogil: + * """The pointer to the data buffer as a char*. +*/ + +static CYTHON_INLINE char *__pyx_f_5numpy_7ndarray_4data_data(PyArrayObject *__pyx_v_self) { + char *__pyx_r; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":369 + * of `PyArray_DATA()` instead, which returns a 'void*'. + * """ + * return PyArray_BYTES(self) # <<<<<<<<<<<<<< + * + * +*/ + __pyx_r = PyArray_BYTES(__pyx_v_self); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":362 + * return PyArray_SIZE(self) + * + * @property # <<<<<<<<<<<<<< + * cdef inline char* data(self) noexcept nogil: + * """The pointer to the data buffer as a char*. +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":777 + * ctypedef long double complex clongdouble_t + * + * cdef inline object PyArray_MultiIterNew1(a): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(1, a) + * +*/ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__pyx_v_a) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew1", 0); + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":778 + * + * cdef inline object PyArray_MultiIterNew1(a): + * return PyArray_MultiIterNew(1, a) # <<<<<<<<<<<<<< + * + * cdef inline object PyArray_MultiIterNew2(a, b): +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(1, ((void *)__pyx_v_a)); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 778, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":777 + * ctypedef long double complex clongdouble_t + * + * cdef inline object PyArray_MultiIterNew1(a): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(1, a) + * +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew1", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":780 + * return PyArray_MultiIterNew(1, a) + * + * cdef inline object PyArray_MultiIterNew2(a, b): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(2, a, b) + * +*/ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__pyx_v_a, PyObject *__pyx_v_b) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew2", 0); + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":781 + * + * cdef inline object PyArray_MultiIterNew2(a, b): + * return PyArray_MultiIterNew(2, a, b) # <<<<<<<<<<<<<< + * + * cdef inline object PyArray_MultiIterNew3(a, b, c): +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(2, ((void *)__pyx_v_a), ((void *)__pyx_v_b)); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 781, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":780 + * return PyArray_MultiIterNew(1, a) + * + * cdef inline object PyArray_MultiIterNew2(a, b): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(2, a, b) + * +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew2", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":783 + * return PyArray_MultiIterNew(2, a, b) + * + * cdef inline object PyArray_MultiIterNew3(a, b, c): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(3, a, b, c) + * +*/ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew3", 0); + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":784 + * + * cdef inline object PyArray_MultiIterNew3(a, b, c): + * return PyArray_MultiIterNew(3, a, b, c) # <<<<<<<<<<<<<< + * + * cdef inline object PyArray_MultiIterNew4(a, b, c, d): +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(3, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c)); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 784, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":783 + * return PyArray_MultiIterNew(2, a, b) + * + * cdef inline object PyArray_MultiIterNew3(a, b, c): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(3, a, b, c) + * +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew3", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":786 + * return PyArray_MultiIterNew(3, a, b, c) + * + * cdef inline object PyArray_MultiIterNew4(a, b, c, d): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(4, a, b, c, d) + * +*/ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew4", 0); + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":787 + * + * cdef inline object PyArray_MultiIterNew4(a, b, c, d): + * return PyArray_MultiIterNew(4, a, b, c, d) # <<<<<<<<<<<<<< + * + * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(4, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d)); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 787, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":786 + * return PyArray_MultiIterNew(3, a, b, c) + * + * cdef inline object PyArray_MultiIterNew4(a, b, c, d): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(4, a, b, c, d) + * +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew4", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":789 + * return PyArray_MultiIterNew(4, a, b, c, d) + * + * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(5, a, b, c, d, e) + * +*/ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d, PyObject *__pyx_v_e) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew5", 0); + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":790 + * + * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): + * return PyArray_MultiIterNew(5, a, b, c, d, e) # <<<<<<<<<<<<<< + * + * cdef inline tuple PyDataType_SHAPE(dtype d): +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(5, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d), ((void *)__pyx_v_e)); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 790, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":789 + * return PyArray_MultiIterNew(4, a, b, c, d) + * + * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(5, a, b, c, d, e) + * +*/ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew5", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":792 + * return PyArray_MultiIterNew(5, a, b, c, d, e) + * + * cdef inline tuple PyDataType_SHAPE(dtype d): # <<<<<<<<<<<<<< + * if PyDataType_HASSUBARRAY(d): + * return d.subarray.shape +*/ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyDataType_SHAPE(PyArray_Descr *__pyx_v_d) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + PyObject *__pyx_t_2; + __Pyx_RefNannySetupContext("PyDataType_SHAPE", 0); + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":793 + * + * cdef inline tuple PyDataType_SHAPE(dtype d): + * if PyDataType_HASSUBARRAY(d): # <<<<<<<<<<<<<< + * return d.subarray.shape + * else: +*/ + __pyx_t_1 = PyDataType_HASSUBARRAY(__pyx_v_d); + if (__pyx_t_1) { + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":794 + * cdef inline tuple PyDataType_SHAPE(dtype d): + * if PyDataType_HASSUBARRAY(d): + * return d.subarray.shape # <<<<<<<<<<<<<< + * else: + * return () +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_t_2 = __pyx_f_5numpy_5dtype_8subarray_subarray(__pyx_v_d)->shape; + __Pyx_INCREF(((PyObject*)__pyx_t_2)); + __pyx_r = ((PyObject*)__pyx_t_2); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":793 + * + * cdef inline tuple PyDataType_SHAPE(dtype d): + * if PyDataType_HASSUBARRAY(d): # <<<<<<<<<<<<<< + * return d.subarray.shape + * else: +*/ + } + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":796 + * return d.subarray.shape + * else: + * return () # <<<<<<<<<<<<<< + * + * +*/ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_mstate_global->__pyx_empty_tuple); + __pyx_r = __pyx_mstate_global->__pyx_empty_tuple; + goto __pyx_L0; + } + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":792 + * return PyArray_MultiIterNew(5, a, b, c, d, e) + * + * cdef inline tuple PyDataType_SHAPE(dtype d): # <<<<<<<<<<<<<< + * if PyDataType_HASSUBARRAY(d): + * return d.subarray.shape +*/ + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":995 + * int _import_umath() except -1 + * + * cdef inline void set_array_base(ndarray arr, object base) except *: # <<<<<<<<<<<<<< + * Py_INCREF(base) # important to do this before stealing the reference below! + * PyArray_SetBaseObject(arr, base) +*/ + +static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_arr, PyObject *__pyx_v_base) { + int __pyx_t_1; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":996 + * + * cdef inline void set_array_base(ndarray arr, object base) except *: + * Py_INCREF(base) # important to do this before stealing the reference below! # <<<<<<<<<<<<<< + * PyArray_SetBaseObject(arr, base) + * +*/ + Py_INCREF(__pyx_v_base); + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":997 + * cdef inline void set_array_base(ndarray arr, object base) except *: + * Py_INCREF(base) # important to do this before stealing the reference below! + * PyArray_SetBaseObject(arr, base) # <<<<<<<<<<<<<< + * + * cdef inline object get_array_base(ndarray arr): +*/ + __pyx_t_1 = PyArray_SetBaseObject(__pyx_v_arr, __pyx_v_base); if (unlikely(__pyx_t_1 == ((int)-1))) __PYX_ERR(2, 997, __pyx_L1_error) + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":995 + * int _import_umath() except -1 + * + * cdef inline void set_array_base(ndarray arr, object base) except *: # <<<<<<<<<<<<<< + * Py_INCREF(base) # important to do this before stealing the reference below! + * PyArray_SetBaseObject(arr, base) +*/ + + /* function exit code */ + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("numpy.set_array_base", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_L0:; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":999 + * PyArray_SetBaseObject(arr, base) + * + * cdef inline object get_array_base(ndarray arr): # <<<<<<<<<<<<<< + * base = PyArray_BASE(arr) + * if base is NULL: +*/ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__pyx_v_arr) { + PyObject *__pyx_v_base; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + __Pyx_RefNannySetupContext("get_array_base", 0); + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1000 + * + * cdef inline object get_array_base(ndarray arr): + * base = PyArray_BASE(arr) # <<<<<<<<<<<<<< + * if base is NULL: + * return None +*/ + __pyx_v_base = PyArray_BASE(__pyx_v_arr); + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1001 + * cdef inline object get_array_base(ndarray arr): + * base = PyArray_BASE(arr) + * if base is NULL: # <<<<<<<<<<<<<< + * return None + * return base +*/ + __pyx_t_1 = (__pyx_v_base == NULL); + if (__pyx_t_1) { + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1002 + * base = PyArray_BASE(arr) + * if base is NULL: + * return None # <<<<<<<<<<<<<< + * return base + * +*/ + __Pyx_XDECREF(__pyx_r); + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1001 + * cdef inline object get_array_base(ndarray arr): + * base = PyArray_BASE(arr) + * if base is NULL: # <<<<<<<<<<<<<< + * return None + * return base +*/ + } + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1003 + * if base is NULL: + * return None + * return base # <<<<<<<<<<<<<< + * + * # Versions of the import_* functions which are more suitable for +*/ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(((PyObject *)__pyx_v_base)); + __pyx_r = ((PyObject *)__pyx_v_base); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":999 + * PyArray_SetBaseObject(arr, base) + * + * cdef inline object get_array_base(ndarray arr): # <<<<<<<<<<<<<< + * base = PyArray_BASE(arr) + * if base is NULL: +*/ + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1007 + * # Versions of the import_* functions which are more suitable for + * # Cython code. + * cdef inline int import_array() except -1: # <<<<<<<<<<<<<< + * try: + * __pyx_import_array() +*/ + +static CYTHON_INLINE int __pyx_f_5numpy_import_array(void) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_t_4; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + size_t __pyx_t_10; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("import_array", 0); + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1008 + * # Cython code. + * cdef inline int import_array() except -1: + * try: # <<<<<<<<<<<<<< + * __pyx_import_array() + * except Exception: +*/ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_1); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + /*try:*/ { + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1009 + * cdef inline int import_array() except -1: + * try: + * __pyx_import_array() # <<<<<<<<<<<<<< + * except Exception: + * raise ImportError("numpy._core.multiarray failed to import") +*/ + __pyx_t_4 = _import_array(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(2, 1009, __pyx_L3_error) + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1008 + * # Cython code. + * cdef inline int import_array() except -1: + * try: # <<<<<<<<<<<<<< + * __pyx_import_array() + * except Exception: +*/ + } + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + goto __pyx_L8_try_end; + __pyx_L3_error:; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1010 + * try: + * __pyx_import_array() + * except Exception: # <<<<<<<<<<<<<< + * raise ImportError("numpy._core.multiarray failed to import") + * +*/ + __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(((PyTypeObject*)PyExc_Exception)))); + if (__pyx_t_4) { + __Pyx_AddTraceback("numpy.import_array", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(2, 1010, __pyx_L5_except_error) + __Pyx_XGOTREF(__pyx_t_5); + __Pyx_XGOTREF(__pyx_t_6); + __Pyx_XGOTREF(__pyx_t_7); + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1011 + * __pyx_import_array() + * except Exception: + * raise ImportError("numpy._core.multiarray failed to import") # <<<<<<<<<<<<<< + * + * cdef inline int import_umath() except -1: +*/ + __pyx_t_9 = NULL; + __pyx_t_10 = 1; + { + PyObject *__pyx_callargs[2] = {__pyx_t_9, __pyx_mstate_global->__pyx_kp_u_numpy__core_multiarray_failed_to}; + __pyx_t_8 = __Pyx_PyObject_FastCall((PyObject*)(((PyTypeObject*)PyExc_ImportError)), __pyx_callargs+__pyx_t_10, (2-__pyx_t_10) | (__pyx_t_10*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + if (unlikely(!__pyx_t_8)) __PYX_ERR(2, 1011, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_8); + } + __Pyx_Raise(__pyx_t_8, 0, 0, 0); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __PYX_ERR(2, 1011, __pyx_L5_except_error) + } + goto __pyx_L5_except_error; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1008 + * # Cython code. + * cdef inline int import_array() except -1: + * try: # <<<<<<<<<<<<<< + * __pyx_import_array() + * except Exception: +*/ + __pyx_L5_except_error:; + __Pyx_XGIVEREF(__pyx_t_1); + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); + goto __pyx_L1_error; + __pyx_L8_try_end:; + } + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1007 + * # Versions of the import_* functions which are more suitable for + * # Cython code. + * cdef inline int import_array() except -1: # <<<<<<<<<<<<<< + * try: + * __pyx_import_array() +*/ + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_AddTraceback("numpy.import_array", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1013 + * raise ImportError("numpy._core.multiarray failed to import") + * + * cdef inline int import_umath() except -1: # <<<<<<<<<<<<<< + * try: + * _import_umath() +*/ + +static CYTHON_INLINE int __pyx_f_5numpy_import_umath(void) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_t_4; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + size_t __pyx_t_10; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("import_umath", 0); + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1014 + * + * cdef inline int import_umath() except -1: + * try: # <<<<<<<<<<<<<< + * _import_umath() + * except Exception: +*/ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_1); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + /*try:*/ { + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1015 + * cdef inline int import_umath() except -1: + * try: + * _import_umath() # <<<<<<<<<<<<<< + * except Exception: + * raise ImportError("numpy._core.umath failed to import") +*/ + __pyx_t_4 = _import_umath(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(2, 1015, __pyx_L3_error) + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1014 + * + * cdef inline int import_umath() except -1: + * try: # <<<<<<<<<<<<<< + * _import_umath() + * except Exception: +*/ + } + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + goto __pyx_L8_try_end; + __pyx_L3_error:; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1016 + * try: + * _import_umath() + * except Exception: # <<<<<<<<<<<<<< + * raise ImportError("numpy._core.umath failed to import") + * +*/ + __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(((PyTypeObject*)PyExc_Exception)))); + if (__pyx_t_4) { + __Pyx_AddTraceback("numpy.import_umath", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(2, 1016, __pyx_L5_except_error) + __Pyx_XGOTREF(__pyx_t_5); + __Pyx_XGOTREF(__pyx_t_6); + __Pyx_XGOTREF(__pyx_t_7); + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1017 + * _import_umath() + * except Exception: + * raise ImportError("numpy._core.umath failed to import") # <<<<<<<<<<<<<< + * + * cdef inline int import_ufunc() except -1: +*/ + __pyx_t_9 = NULL; + __pyx_t_10 = 1; + { + PyObject *__pyx_callargs[2] = {__pyx_t_9, __pyx_mstate_global->__pyx_kp_u_numpy__core_umath_failed_to_impo}; + __pyx_t_8 = __Pyx_PyObject_FastCall((PyObject*)(((PyTypeObject*)PyExc_ImportError)), __pyx_callargs+__pyx_t_10, (2-__pyx_t_10) | (__pyx_t_10*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + if (unlikely(!__pyx_t_8)) __PYX_ERR(2, 1017, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_8); + } + __Pyx_Raise(__pyx_t_8, 0, 0, 0); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __PYX_ERR(2, 1017, __pyx_L5_except_error) + } + goto __pyx_L5_except_error; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1014 + * + * cdef inline int import_umath() except -1: + * try: # <<<<<<<<<<<<<< + * _import_umath() + * except Exception: +*/ + __pyx_L5_except_error:; + __Pyx_XGIVEREF(__pyx_t_1); + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); + goto __pyx_L1_error; + __pyx_L8_try_end:; + } + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1013 + * raise ImportError("numpy._core.multiarray failed to import") + * + * cdef inline int import_umath() except -1: # <<<<<<<<<<<<<< + * try: + * _import_umath() +*/ + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_AddTraceback("numpy.import_umath", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1019 + * raise ImportError("numpy._core.umath failed to import") + * + * cdef inline int import_ufunc() except -1: # <<<<<<<<<<<<<< + * try: + * _import_umath() +*/ + +static CYTHON_INLINE int __pyx_f_5numpy_import_ufunc(void) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_t_4; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + size_t __pyx_t_10; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("import_ufunc", 0); + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1020 + * + * cdef inline int import_ufunc() except -1: + * try: # <<<<<<<<<<<<<< + * _import_umath() + * except Exception: +*/ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_1); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + /*try:*/ { + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1021 + * cdef inline int import_ufunc() except -1: + * try: + * _import_umath() # <<<<<<<<<<<<<< + * except Exception: + * raise ImportError("numpy._core.umath failed to import") +*/ + __pyx_t_4 = _import_umath(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(2, 1021, __pyx_L3_error) + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1020 + * + * cdef inline int import_ufunc() except -1: + * try: # <<<<<<<<<<<<<< + * _import_umath() + * except Exception: +*/ + } + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + goto __pyx_L8_try_end; + __pyx_L3_error:; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1022 + * try: + * _import_umath() + * except Exception: # <<<<<<<<<<<<<< + * raise ImportError("numpy._core.umath failed to import") + * +*/ + __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(((PyTypeObject*)PyExc_Exception)))); + if (__pyx_t_4) { + __Pyx_AddTraceback("numpy.import_ufunc", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(2, 1022, __pyx_L5_except_error) + __Pyx_XGOTREF(__pyx_t_5); + __Pyx_XGOTREF(__pyx_t_6); + __Pyx_XGOTREF(__pyx_t_7); + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1023 + * _import_umath() + * except Exception: + * raise ImportError("numpy._core.umath failed to import") # <<<<<<<<<<<<<< + * + * +*/ + __pyx_t_9 = NULL; + __pyx_t_10 = 1; + { + PyObject *__pyx_callargs[2] = {__pyx_t_9, __pyx_mstate_global->__pyx_kp_u_numpy__core_umath_failed_to_impo}; + __pyx_t_8 = __Pyx_PyObject_FastCall((PyObject*)(((PyTypeObject*)PyExc_ImportError)), __pyx_callargs+__pyx_t_10, (2-__pyx_t_10) | (__pyx_t_10*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; + if (unlikely(!__pyx_t_8)) __PYX_ERR(2, 1023, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_8); + } + __Pyx_Raise(__pyx_t_8, 0, 0, 0); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __PYX_ERR(2, 1023, __pyx_L5_except_error) + } + goto __pyx_L5_except_error; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1020 + * + * cdef inline int import_ufunc() except -1: + * try: # <<<<<<<<<<<<<< + * _import_umath() + * except Exception: +*/ + __pyx_L5_except_error:; + __Pyx_XGIVEREF(__pyx_t_1); + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); + goto __pyx_L1_error; + __pyx_L8_try_end:; + } + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1019 + * raise ImportError("numpy._core.umath failed to import") + * + * cdef inline int import_ufunc() except -1: # <<<<<<<<<<<<<< + * try: + * _import_umath() +*/ + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_AddTraceback("numpy.import_ufunc", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1026 + * + * + * cdef inline bint is_timedelta64_object(object obj) noexcept: # <<<<<<<<<<<<<< + * """ + * Cython equivalent of `isinstance(obj, np.timedelta64)` +*/ + +static CYTHON_INLINE int __pyx_f_5numpy_is_timedelta64_object(PyObject *__pyx_v_obj) { + int __pyx_r; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1038 + * bool + * """ + * return PyObject_TypeCheck(obj, &PyTimedeltaArrType_Type) # <<<<<<<<<<<<<< + * + * +*/ + __pyx_r = PyObject_TypeCheck(__pyx_v_obj, (&PyTimedeltaArrType_Type)); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1026 + * + * + * cdef inline bint is_timedelta64_object(object obj) noexcept: # <<<<<<<<<<<<<< + * """ + * Cython equivalent of `isinstance(obj, np.timedelta64)` +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1041 + * + * + * cdef inline bint is_datetime64_object(object obj) noexcept: # <<<<<<<<<<<<<< + * """ + * Cython equivalent of `isinstance(obj, np.datetime64)` +*/ + +static CYTHON_INLINE int __pyx_f_5numpy_is_datetime64_object(PyObject *__pyx_v_obj) { + int __pyx_r; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1053 + * bool + * """ + * return PyObject_TypeCheck(obj, &PyDatetimeArrType_Type) # <<<<<<<<<<<<<< + * + * +*/ + __pyx_r = PyObject_TypeCheck(__pyx_v_obj, (&PyDatetimeArrType_Type)); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1041 + * + * + * cdef inline bint is_datetime64_object(object obj) noexcept: # <<<<<<<<<<<<<< + * """ + * Cython equivalent of `isinstance(obj, np.datetime64)` +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1056 + * + * + * cdef inline npy_datetime get_datetime64_value(object obj) noexcept nogil: # <<<<<<<<<<<<<< + * """ + * returns the int64 value underlying scalar numpy datetime64 object +*/ + +static CYTHON_INLINE npy_datetime __pyx_f_5numpy_get_datetime64_value(PyObject *__pyx_v_obj) { + npy_datetime __pyx_r; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1063 + * also needed. That can be found using `get_datetime64_unit`. + * """ + * return (obj).obval # <<<<<<<<<<<<<< + * + * +*/ + __pyx_r = ((PyDatetimeScalarObject *)__pyx_v_obj)->obval; + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1056 + * + * + * cdef inline npy_datetime get_datetime64_value(object obj) noexcept nogil: # <<<<<<<<<<<<<< + * """ + * returns the int64 value underlying scalar numpy datetime64 object +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1066 + * + * + * cdef inline npy_timedelta get_timedelta64_value(object obj) noexcept nogil: # <<<<<<<<<<<<<< + * """ + * returns the int64 value underlying scalar numpy timedelta64 object +*/ + +static CYTHON_INLINE npy_timedelta __pyx_f_5numpy_get_timedelta64_value(PyObject *__pyx_v_obj) { + npy_timedelta __pyx_r; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1070 + * returns the int64 value underlying scalar numpy timedelta64 object + * """ + * return (obj).obval # <<<<<<<<<<<<<< + * + * +*/ + __pyx_r = ((PyTimedeltaScalarObject *)__pyx_v_obj)->obval; + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1066 + * + * + * cdef inline npy_timedelta get_timedelta64_value(object obj) noexcept nogil: # <<<<<<<<<<<<<< + * """ + * returns the int64 value underlying scalar numpy timedelta64 object +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1073 + * + * + * cdef inline NPY_DATETIMEUNIT get_datetime64_unit(object obj) noexcept nogil: # <<<<<<<<<<<<<< + * """ + * returns the unit part of the dtype for a numpy datetime64 object. +*/ + +static CYTHON_INLINE NPY_DATETIMEUNIT __pyx_f_5numpy_get_datetime64_unit(PyObject *__pyx_v_obj) { + NPY_DATETIMEUNIT __pyx_r; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1077 + * returns the unit part of the dtype for a numpy datetime64 object. + * """ + * return (obj).obmeta.base # <<<<<<<<<<<<<< + * + * +*/ + __pyx_r = ((NPY_DATETIMEUNIT)((PyDatetimeScalarObject *)__pyx_v_obj)->obmeta.base); + goto __pyx_L0; + + /* "../../../../../../../tmp/pip-build-env-1iiesr3w/overlay/local/lib/python3.12/dist-packages/numpy/__init__.cython-30.pxd":1073 + * + * + * cdef inline NPY_DATETIMEUNIT get_datetime64_unit(object obj) noexcept nogil: # <<<<<<<<<<<<<< + * """ + * returns the unit part of the dtype for a numpy datetime64 object. +*/ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "matcha/utils/monotonic_align/core.pyx":9 + * + * + * @cython.boundscheck(False) # <<<<<<<<<<<<<< + * @cython.wraparound(False) + * cdef void maximum_path_each(int[:,::1] path, float[:,::1] value, int t_x, int t_y, float max_neg_val) nogil: +*/ + +static void __pyx_f_6matcha_5utils_15monotonic_align_4core_maximum_path_each(__Pyx_memviewslice __pyx_v_path, __Pyx_memviewslice __pyx_v_value, int __pyx_v_t_x, int __pyx_v_t_y, float __pyx_v_max_neg_val) { + int __pyx_v_x; + int __pyx_v_y; + float __pyx_v_v_prev; + float __pyx_v_v_cur; + int __pyx_v_index; + int __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + long __pyx_t_4; + int __pyx_t_5; + long __pyx_t_6; + int __pyx_t_7; + long __pyx_t_8; + Py_ssize_t __pyx_t_9; + Py_ssize_t __pyx_t_10; + float __pyx_t_11; + float __pyx_t_12; + float __pyx_t_13; + Py_ssize_t __pyx_t_14; + Py_ssize_t __pyx_t_15; + int __pyx_t_16; + + /* "matcha/utils/monotonic_align/core.pyx":17 + * cdef float v_cur + * cdef float tmp + * cdef int index = t_x - 1 # <<<<<<<<<<<<<< + * + * for y in range(t_y): +*/ + __pyx_v_index = (__pyx_v_t_x - 1); + + /* "matcha/utils/monotonic_align/core.pyx":19 + * cdef int index = t_x - 1 + * + * for y in range(t_y): # <<<<<<<<<<<<<< + * for x in range(max(0, t_x + y - t_y), min(t_x, y + 1)): + * if x == y: +*/ + __pyx_t_1 = __pyx_v_t_y; + __pyx_t_2 = __pyx_t_1; + for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) { + __pyx_v_y = __pyx_t_3; + + /* "matcha/utils/monotonic_align/core.pyx":20 + * + * for y in range(t_y): + * for x in range(max(0, t_x + y - t_y), min(t_x, y + 1)): # <<<<<<<<<<<<<< + * if x == y: + * v_cur = max_neg_val +*/ + __pyx_t_4 = (__pyx_v_y + 1); + __pyx_t_5 = __pyx_v_t_x; + __pyx_t_7 = (__pyx_t_4 < __pyx_t_5); + if (__pyx_t_7) { + __pyx_t_6 = __pyx_t_4; + } else { + __pyx_t_6 = __pyx_t_5; + } + __pyx_t_4 = __pyx_t_6; + __pyx_t_5 = ((__pyx_v_t_x + __pyx_v_y) - __pyx_v_t_y); + __pyx_t_6 = 0; + __pyx_t_7 = (__pyx_t_5 > __pyx_t_6); + if (__pyx_t_7) { + __pyx_t_8 = __pyx_t_5; + } else { + __pyx_t_8 = __pyx_t_6; + } + __pyx_t_6 = __pyx_t_4; + for (__pyx_t_5 = __pyx_t_8; __pyx_t_5 < __pyx_t_6; __pyx_t_5+=1) { + __pyx_v_x = __pyx_t_5; + + /* "matcha/utils/monotonic_align/core.pyx":21 + * for y in range(t_y): + * for x in range(max(0, t_x + y - t_y), min(t_x, y + 1)): + * if x == y: # <<<<<<<<<<<<<< + * v_cur = max_neg_val + * else: +*/ + __pyx_t_7 = (__pyx_v_x == __pyx_v_y); + if (__pyx_t_7) { + + /* "matcha/utils/monotonic_align/core.pyx":22 + * for x in range(max(0, t_x + y - t_y), min(t_x, y + 1)): + * if x == y: + * v_cur = max_neg_val # <<<<<<<<<<<<<< + * else: + * v_cur = value[x, y-1] +*/ + __pyx_v_v_cur = __pyx_v_max_neg_val; + + /* "matcha/utils/monotonic_align/core.pyx":21 + * for y in range(t_y): + * for x in range(max(0, t_x + y - t_y), min(t_x, y + 1)): + * if x == y: # <<<<<<<<<<<<<< + * v_cur = max_neg_val + * else: +*/ + goto __pyx_L7; + } + + /* "matcha/utils/monotonic_align/core.pyx":24 + * v_cur = max_neg_val + * else: + * v_cur = value[x, y-1] # <<<<<<<<<<<<<< + * if x == 0: + * if y == 0: +*/ + /*else*/ { + __pyx_t_9 = __pyx_v_x; + __pyx_t_10 = (__pyx_v_y - 1); + __pyx_v_v_cur = (*((float *) ( /* dim=1 */ ((char *) (((float *) ( /* dim=0 */ (__pyx_v_value.data + __pyx_t_9 * __pyx_v_value.strides[0]) )) + __pyx_t_10)) ))); + } + __pyx_L7:; + + /* "matcha/utils/monotonic_align/core.pyx":25 + * else: + * v_cur = value[x, y-1] + * if x == 0: # <<<<<<<<<<<<<< + * if y == 0: + * v_prev = 0. +*/ + __pyx_t_7 = (__pyx_v_x == 0); + if (__pyx_t_7) { + + /* "matcha/utils/monotonic_align/core.pyx":26 + * v_cur = value[x, y-1] + * if x == 0: + * if y == 0: # <<<<<<<<<<<<<< + * v_prev = 0. + * else: +*/ + __pyx_t_7 = (__pyx_v_y == 0); + if (__pyx_t_7) { + + /* "matcha/utils/monotonic_align/core.pyx":27 + * if x == 0: + * if y == 0: + * v_prev = 0. # <<<<<<<<<<<<<< + * else: + * v_prev = max_neg_val +*/ + __pyx_v_v_prev = 0.; + + /* "matcha/utils/monotonic_align/core.pyx":26 + * v_cur = value[x, y-1] + * if x == 0: + * if y == 0: # <<<<<<<<<<<<<< + * v_prev = 0. + * else: +*/ + goto __pyx_L9; + } + + /* "matcha/utils/monotonic_align/core.pyx":29 + * v_prev = 0. + * else: + * v_prev = max_neg_val # <<<<<<<<<<<<<< + * else: + * v_prev = value[x-1, y-1] +*/ + /*else*/ { + __pyx_v_v_prev = __pyx_v_max_neg_val; + } + __pyx_L9:; + + /* "matcha/utils/monotonic_align/core.pyx":25 + * else: + * v_cur = value[x, y-1] + * if x == 0: # <<<<<<<<<<<<<< + * if y == 0: + * v_prev = 0. +*/ + goto __pyx_L8; + } + + /* "matcha/utils/monotonic_align/core.pyx":31 + * v_prev = max_neg_val + * else: + * v_prev = value[x-1, y-1] # <<<<<<<<<<<<<< + * value[x, y] = max(v_cur, v_prev) + value[x, y] + * +*/ + /*else*/ { + __pyx_t_10 = (__pyx_v_x - 1); + __pyx_t_9 = (__pyx_v_y - 1); + __pyx_v_v_prev = (*((float *) ( /* dim=1 */ ((char *) (((float *) ( /* dim=0 */ (__pyx_v_value.data + __pyx_t_10 * __pyx_v_value.strides[0]) )) + __pyx_t_9)) ))); + } + __pyx_L8:; + + /* "matcha/utils/monotonic_align/core.pyx":32 + * else: + * v_prev = value[x-1, y-1] + * value[x, y] = max(v_cur, v_prev) + value[x, y] # <<<<<<<<<<<<<< + * + * for y in range(t_y - 1, -1, -1): +*/ + __pyx_t_11 = __pyx_v_v_prev; + __pyx_t_12 = __pyx_v_v_cur; + __pyx_t_7 = (__pyx_t_11 > __pyx_t_12); + if (__pyx_t_7) { + __pyx_t_13 = __pyx_t_11; + } else { + __pyx_t_13 = __pyx_t_12; + } + __pyx_t_9 = __pyx_v_x; + __pyx_t_10 = __pyx_v_y; + __pyx_t_14 = __pyx_v_x; + __pyx_t_15 = __pyx_v_y; + *((float *) ( /* dim=1 */ ((char *) (((float *) ( /* dim=0 */ (__pyx_v_value.data + __pyx_t_14 * __pyx_v_value.strides[0]) )) + __pyx_t_15)) )) = (__pyx_t_13 + (*((float *) ( /* dim=1 */ ((char *) (((float *) ( /* dim=0 */ (__pyx_v_value.data + __pyx_t_9 * __pyx_v_value.strides[0]) )) + __pyx_t_10)) )))); + } + } + + /* "matcha/utils/monotonic_align/core.pyx":34 + * value[x, y] = max(v_cur, v_prev) + value[x, y] + * + * for y in range(t_y - 1, -1, -1): # <<<<<<<<<<<<<< + * path[index, y] = 1 + * if index != 0 and (index == y or value[index, y-1] < value[index-1, y-1]): +*/ + for (__pyx_t_1 = (__pyx_v_t_y - 1); __pyx_t_1 > -1; __pyx_t_1-=1) { + __pyx_v_y = __pyx_t_1; + + /* "matcha/utils/monotonic_align/core.pyx":35 + * + * for y in range(t_y - 1, -1, -1): + * path[index, y] = 1 # <<<<<<<<<<<<<< + * if index != 0 and (index == y or value[index, y-1] < value[index-1, y-1]): + * index = index - 1 +*/ + __pyx_t_10 = __pyx_v_index; + __pyx_t_9 = __pyx_v_y; + *((int *) ( /* dim=1 */ ((char *) (((int *) ( /* dim=0 */ (__pyx_v_path.data + __pyx_t_10 * __pyx_v_path.strides[0]) )) + __pyx_t_9)) )) = 1; + + /* "matcha/utils/monotonic_align/core.pyx":36 + * for y in range(t_y - 1, -1, -1): + * path[index, y] = 1 + * if index != 0 and (index == y or value[index, y-1] < value[index-1, y-1]): # <<<<<<<<<<<<<< + * index = index - 1 + * +*/ + __pyx_t_16 = (__pyx_v_index != 0); + if (__pyx_t_16) { + } else { + __pyx_t_7 = __pyx_t_16; + goto __pyx_L13_bool_binop_done; + } + __pyx_t_16 = (__pyx_v_index == __pyx_v_y); + if (!__pyx_t_16) { + } else { + __pyx_t_7 = __pyx_t_16; + goto __pyx_L13_bool_binop_done; + } + __pyx_t_9 = __pyx_v_index; + __pyx_t_10 = (__pyx_v_y - 1); + __pyx_t_15 = (__pyx_v_index - 1); + __pyx_t_14 = (__pyx_v_y - 1); + __pyx_t_16 = ((*((float *) ( /* dim=1 */ ((char *) (((float *) ( /* dim=0 */ (__pyx_v_value.data + __pyx_t_9 * __pyx_v_value.strides[0]) )) + __pyx_t_10)) ))) < (*((float *) ( /* dim=1 */ ((char *) (((float *) ( /* dim=0 */ (__pyx_v_value.data + __pyx_t_15 * __pyx_v_value.strides[0]) )) + __pyx_t_14)) )))); + __pyx_t_7 = __pyx_t_16; + __pyx_L13_bool_binop_done:; + if (__pyx_t_7) { + + /* "matcha/utils/monotonic_align/core.pyx":37 + * path[index, y] = 1 + * if index != 0 and (index == y or value[index, y-1] < value[index-1, y-1]): + * index = index - 1 # <<<<<<<<<<<<<< + * + * +*/ + __pyx_v_index = (__pyx_v_index - 1); + + /* "matcha/utils/monotonic_align/core.pyx":36 + * for y in range(t_y - 1, -1, -1): + * path[index, y] = 1 + * if index != 0 and (index == y or value[index, y-1] < value[index-1, y-1]): # <<<<<<<<<<<<<< + * index = index - 1 + * +*/ + } + } + + /* "matcha/utils/monotonic_align/core.pyx":9 + * + * + * @cython.boundscheck(False) # <<<<<<<<<<<<<< + * @cython.wraparound(False) + * cdef void maximum_path_each(int[:,::1] path, float[:,::1] value, int t_x, int t_y, float max_neg_val) nogil: +*/ + + /* function exit code */ +} + +/* "matcha/utils/monotonic_align/core.pyx":40 + * + * + * @cython.boundscheck(False) # <<<<<<<<<<<<<< + * @cython.wraparound(False) + * cpdef void maximum_path_c(int[:,:,::1] paths, float[:,:,::1] values, int[::1] t_xs, int[::1] t_ys, float max_neg_val=-1e9) nogil: +*/ + +static PyObject *__pyx_pw_6matcha_5utils_15monotonic_align_4core_1maximum_path_c(PyObject *__pyx_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +); /*proto*/ +static void __pyx_f_6matcha_5utils_15monotonic_align_4core_maximum_path_c(__Pyx_memviewslice __pyx_v_paths, __Pyx_memviewslice __pyx_v_values, __Pyx_memviewslice __pyx_v_t_xs, __Pyx_memviewslice __pyx_v_t_ys, CYTHON_UNUSED int __pyx_skip_dispatch, struct __pyx_opt_args_6matcha_5utils_15monotonic_align_4core_maximum_path_c *__pyx_optional_args) { + float __pyx_v_max_neg_val = __pyx_mstate_global->__pyx_k__6; + int __pyx_v_b; + int __pyx_v_i; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + __Pyx_memviewslice __pyx_t_4 = { 0, 0, { 0 }, { 0 }, { 0 } }; + __Pyx_memviewslice __pyx_t_5 = { 0, 0, { 0 }, { 0 }, { 0 } }; + Py_ssize_t __pyx_t_6; + Py_ssize_t __pyx_t_7; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyGILState_STATE __pyx_gilstate_save; + __Pyx_RefNannySetupContext("maximum_path_c", 1); + if (__pyx_optional_args) { + if (__pyx_optional_args->__pyx_n > 0) { + __pyx_v_max_neg_val = __pyx_optional_args->max_neg_val; + } + } + + /* "matcha/utils/monotonic_align/core.pyx":43 + * @cython.wraparound(False) + * cpdef void maximum_path_c(int[:,:,::1] paths, float[:,:,::1] values, int[::1] t_xs, int[::1] t_ys, float max_neg_val=-1e9) nogil: + * cdef int b = values.shape[0] # <<<<<<<<<<<<<< + * + * cdef int i +*/ + __pyx_v_b = (__pyx_v_values.shape[0]); + + /* "matcha/utils/monotonic_align/core.pyx":46 + * + * cdef int i + * for i in prange(b, nogil=True): # <<<<<<<<<<<<<< + * maximum_path_each(paths[i], values[i], t_xs[i], t_ys[i], max_neg_val) +*/ + { + __Pyx_UnknownThreadState _save; + _save = __Pyx_SaveUnknownThread(); + __Pyx_FastGIL_Remember(); + /*try:*/ { + __pyx_t_1 = __pyx_v_b; + { + const char *__pyx_parallel_filename = NULL; int __pyx_parallel_lineno = 0, __pyx_parallel_clineno = 0; + PyObject *__pyx_parallel_exc_type = NULL, *__pyx_parallel_exc_value = NULL, *__pyx_parallel_exc_tb = NULL; + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + PyMutex __pyx_parallel_freethreading_mutex = {0}; + #endif + int __pyx_parallel_why; + __pyx_parallel_why = 0; + #if ((defined(__APPLE__) || defined(__OSX__)) && (defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))))) + #undef likely + #undef unlikely + #define likely(x) (x) + #define unlikely(x) (x) + #endif + __pyx_t_3 = (__pyx_t_1 - 0 + 1 - 1/abs(1)) / 1; + if (__pyx_t_3 > 0) + { + #ifdef _OPENMP + #pragma omp parallel private(__pyx_t_6, __pyx_t_7) firstprivate(__pyx_t_4, __pyx_t_5) __Pyx_shared_in_cpython_freethreading(__pyx_parallel_freethreading_mutex) private(__pyx_filename, __pyx_lineno, __pyx_clineno) shared(__pyx_parallel_why, __pyx_parallel_exc_type, __pyx_parallel_exc_value, __pyx_parallel_exc_tb) + #endif /* _OPENMP */ + { + #ifdef _OPENMP + PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); + Py_BEGIN_ALLOW_THREADS + #endif /* _OPENMP */ + #ifdef _OPENMP + #pragma omp for firstprivate(__pyx_v_i) lastprivate(__pyx_v_i) + #endif /* _OPENMP */ + for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_3; __pyx_t_2++){ + if (__pyx_parallel_why < 2) + { + __pyx_v_i = (int)(0 + 1 * __pyx_t_2); + + /* "matcha/utils/monotonic_align/core.pyx":47 + * cdef int i + * for i in prange(b, nogil=True): + * maximum_path_each(paths[i], values[i], t_xs[i], t_ys[i], max_neg_val) # <<<<<<<<<<<<<< +*/ + __pyx_t_4.data = __pyx_v_paths.data; + __pyx_t_4.memview = __pyx_v_paths.memview; + __PYX_INC_MEMVIEW(&__pyx_t_4, 0); + { + Py_ssize_t __pyx_tmp_idx = __pyx_v_i; + Py_ssize_t __pyx_tmp_stride = __pyx_v_paths.strides[0]; + __pyx_t_4.data += __pyx_tmp_idx * __pyx_tmp_stride; +} + +__pyx_t_4.shape[0] = __pyx_v_paths.shape[1]; +__pyx_t_4.strides[0] = __pyx_v_paths.strides[1]; + __pyx_t_4.suboffsets[0] = -1; + +__pyx_t_4.shape[1] = __pyx_v_paths.shape[2]; +__pyx_t_4.strides[1] = __pyx_v_paths.strides[2]; + __pyx_t_4.suboffsets[1] = -1; + +__pyx_t_5.data = __pyx_v_values.data; + __pyx_t_5.memview = __pyx_v_values.memview; + __PYX_INC_MEMVIEW(&__pyx_t_5, 0); + { + Py_ssize_t __pyx_tmp_idx = __pyx_v_i; + Py_ssize_t __pyx_tmp_stride = __pyx_v_values.strides[0]; + __pyx_t_5.data += __pyx_tmp_idx * __pyx_tmp_stride; +} + +__pyx_t_5.shape[0] = __pyx_v_values.shape[1]; +__pyx_t_5.strides[0] = __pyx_v_values.strides[1]; + __pyx_t_5.suboffsets[0] = -1; + +__pyx_t_5.shape[1] = __pyx_v_values.shape[2]; +__pyx_t_5.strides[1] = __pyx_v_values.strides[2]; + __pyx_t_5.suboffsets[1] = -1; + +__pyx_t_6 = __pyx_v_i; + __pyx_t_7 = __pyx_v_i; + __pyx_f_6matcha_5utils_15monotonic_align_4core_maximum_path_each(__pyx_t_4, __pyx_t_5, (*((int *) ( /* dim=0 */ ((char *) (((int *) __pyx_v_t_xs.data) + __pyx_t_6)) ))), (*((int *) ( /* dim=0 */ ((char *) (((int *) __pyx_v_t_ys.data) + __pyx_t_7)) ))), __pyx_v_max_neg_val); if (unlikely(__Pyx_ErrOccurredWithGIL())) __PYX_ERR(0, 47, __pyx_L8_error) + __PYX_XCLEAR_MEMVIEW(&__pyx_t_4, 0); + __pyx_t_4.memview = NULL; __pyx_t_4.data = NULL; + __PYX_XCLEAR_MEMVIEW(&__pyx_t_5, 0); + __pyx_t_5.memview = NULL; __pyx_t_5.data = NULL; + goto __pyx_L11; + __pyx_L8_error:; + { + PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + PyMutex_Lock(&__pyx_parallel_freethreading_mutex); + #endif + #ifdef _OPENMP + #pragma omp flush(__pyx_parallel_exc_type) + #endif /* _OPENMP */ + if (!__pyx_parallel_exc_type) { + __Pyx_ErrFetchWithState(&__pyx_parallel_exc_type, &__pyx_parallel_exc_value, &__pyx_parallel_exc_tb); + __pyx_parallel_filename = __pyx_filename; __pyx_parallel_lineno = __pyx_lineno; __pyx_parallel_clineno = __pyx_clineno; + __Pyx_GOTREF(__pyx_parallel_exc_type); + } + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + PyMutex_Unlock(&__pyx_parallel_freethreading_mutex); + #endif + __Pyx_PyGILState_Release(__pyx_gilstate_save); + } + __pyx_parallel_why = 4; + goto __pyx_L11; + __pyx_L11:; + #ifdef _OPENMP + #pragma omp flush(__pyx_parallel_why) + #endif /* _OPENMP */ + } + } + #ifdef _OPENMP + Py_END_ALLOW_THREADS + #else +{ +PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); + #endif /* _OPENMP */ + /* Clean up any temporaries */ + __PYX_XCLEAR_MEMVIEW(&__pyx_t_4, 1); + __pyx_t_4.memview = NULL; __pyx_t_4.data = NULL; + __PYX_XCLEAR_MEMVIEW(&__pyx_t_5, 1); + __pyx_t_5.memview = NULL; __pyx_t_5.data = NULL; + __Pyx_PyGILState_Release(__pyx_gilstate_save); + #ifndef _OPENMP +} +#endif /* _OPENMP */ + } + } + if (__pyx_parallel_exc_type) { + /* This may have been overridden by a continue, break or return in another thread. Prefer the error. */ + __pyx_parallel_why = 4; + } + if (__pyx_parallel_why) { + switch (__pyx_parallel_why) { + case 4: + { + PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + PyMutex_Lock(&__pyx_parallel_freethreading_mutex); + #endif + __Pyx_GIVEREF(__pyx_parallel_exc_type); + __Pyx_ErrRestoreWithState(__pyx_parallel_exc_type, __pyx_parallel_exc_value, __pyx_parallel_exc_tb); + __pyx_filename = __pyx_parallel_filename; __pyx_lineno = __pyx_parallel_lineno; __pyx_clineno = __pyx_parallel_clineno; + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + PyMutex_Unlock(&__pyx_parallel_freethreading_mutex); + #endif + __Pyx_PyGILState_Release(__pyx_gilstate_save); + } + goto __pyx_L4_error; + } + } + } + #if ((defined(__APPLE__) || defined(__OSX__)) && (defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))))) + #undef likely + #undef unlikely + #define likely(x) __builtin_expect(!!(x), 1) + #define unlikely(x) __builtin_expect(!!(x), 0) + #endif + } + + /* "matcha/utils/monotonic_align/core.pyx":46 + * + * cdef int i + * for i in prange(b, nogil=True): # <<<<<<<<<<<<<< + * maximum_path_each(paths[i], values[i], t_xs[i], t_ys[i], max_neg_val) +*/ + /*finally:*/ { + /*normal exit:*/{ + __Pyx_FastGIL_Forget(); + __Pyx_RestoreUnknownThread(_save); + goto __pyx_L5; + } + __pyx_L4_error: { + __Pyx_FastGIL_Forget(); + __Pyx_RestoreUnknownThread(_save); + goto __pyx_L1_error; + } + __pyx_L5:; + } + } + + /* "matcha/utils/monotonic_align/core.pyx":40 + * + * + * @cython.boundscheck(False) # <<<<<<<<<<<<<< + * @cython.wraparound(False) + * cpdef void maximum_path_c(int[:,:,::1] paths, float[:,:,::1] values, int[::1] t_xs, int[::1] t_ys, float max_neg_val=-1e9) nogil: +*/ + + /* function exit code */ + goto __pyx_L0; + __pyx_L1_error:; + __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); + __PYX_XCLEAR_MEMVIEW(&__pyx_t_4, 1); + __PYX_XCLEAR_MEMVIEW(&__pyx_t_5, 1); + __Pyx_AddTraceback("matcha.utils.monotonic_align.core.maximum_path_c", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_PyGILState_Release(__pyx_gilstate_save); + __pyx_L0:; + __Pyx_RefNannyFinishContextNogil() +} + +/* Python wrapper */ +static PyObject *__pyx_pw_6matcha_5utils_15monotonic_align_4core_1maximum_path_c(PyObject *__pyx_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +); /*proto*/ +static PyMethodDef __pyx_mdef_6matcha_5utils_15monotonic_align_4core_1maximum_path_c = {"maximum_path_c", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_6matcha_5utils_15monotonic_align_4core_1maximum_path_c, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_6matcha_5utils_15monotonic_align_4core_1maximum_path_c(PyObject *__pyx_self, +#if CYTHON_METH_FASTCALL +PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds +#else +PyObject *__pyx_args, PyObject *__pyx_kwds +#endif +) { + __Pyx_memviewslice __pyx_v_paths = { 0, 0, { 0 }, { 0 }, { 0 } }; + __Pyx_memviewslice __pyx_v_values = { 0, 0, { 0 }, { 0 }, { 0 } }; + __Pyx_memviewslice __pyx_v_t_xs = { 0, 0, { 0 }, { 0 }, { 0 } }; + __Pyx_memviewslice __pyx_v_t_ys = { 0, 0, { 0 }, { 0 }, { 0 } }; + float __pyx_v_max_neg_val; + #if !CYTHON_METH_FASTCALL + CYTHON_UNUSED Py_ssize_t __pyx_nargs; + #endif + CYTHON_UNUSED PyObject *const *__pyx_kwvalues; + PyObject* values[5] = {0,0,0,0,0}; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("maximum_path_c (wrapper)", 0); + #if !CYTHON_METH_FASTCALL + #if CYTHON_ASSUME_SAFE_SIZE + __pyx_nargs = PyTuple_GET_SIZE(__pyx_args); + #else + __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL; + #endif + #endif + __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs); + { + PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_paths,&__pyx_mstate_global->__pyx_n_u_values,&__pyx_mstate_global->__pyx_n_u_t_xs,&__pyx_mstate_global->__pyx_n_u_t_ys,&__pyx_mstate_global->__pyx_n_u_max_neg_val,0}; + const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0; + if (unlikely(__pyx_kwds_len < 0)) __PYX_ERR(0, 40, __pyx_L3_error) + if (__pyx_kwds_len > 0) { + switch (__pyx_nargs) { + case 5: + values[4] = __Pyx_ArgRef_FASTCALL(__pyx_args, 4); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[4])) __PYX_ERR(0, 40, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 4: + values[3] = __Pyx_ArgRef_FASTCALL(__pyx_args, 3); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(0, 40, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 3: + values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 40, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 2: + values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 40, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 1: + values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 40, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + const Py_ssize_t kwd_pos_args = __pyx_nargs; + if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "maximum_path_c", 0) < (0)) __PYX_ERR(0, 40, __pyx_L3_error) + for (Py_ssize_t i = __pyx_nargs; i < 4; i++) { + if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("maximum_path_c", 0, 4, 5, i); __PYX_ERR(0, 40, __pyx_L3_error) } + } + } else { + switch (__pyx_nargs) { + case 5: + values[4] = __Pyx_ArgRef_FASTCALL(__pyx_args, 4); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[4])) __PYX_ERR(0, 40, __pyx_L3_error) + CYTHON_FALLTHROUGH; + case 4: + values[3] = __Pyx_ArgRef_FASTCALL(__pyx_args, 3); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(0, 40, __pyx_L3_error) + values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 40, __pyx_L3_error) + values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 40, __pyx_L3_error) + values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0); + if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 40, __pyx_L3_error) + break; + default: goto __pyx_L5_argtuple_error; + } + } + __pyx_v_paths = __Pyx_PyObject_to_MemoryviewSlice_d_d_dc_int(values[0], PyBUF_WRITABLE); if (unlikely(!__pyx_v_paths.memview)) __PYX_ERR(0, 42, __pyx_L3_error) + __pyx_v_values = __Pyx_PyObject_to_MemoryviewSlice_d_d_dc_float(values[1], PyBUF_WRITABLE); if (unlikely(!__pyx_v_values.memview)) __PYX_ERR(0, 42, __pyx_L3_error) + __pyx_v_t_xs = __Pyx_PyObject_to_MemoryviewSlice_dc_int(values[2], PyBUF_WRITABLE); if (unlikely(!__pyx_v_t_xs.memview)) __PYX_ERR(0, 42, __pyx_L3_error) + __pyx_v_t_ys = __Pyx_PyObject_to_MemoryviewSlice_dc_int(values[3], PyBUF_WRITABLE); if (unlikely(!__pyx_v_t_ys.memview)) __PYX_ERR(0, 42, __pyx_L3_error) + if (values[4]) { + __pyx_v_max_neg_val = __Pyx_PyFloat_AsFloat(values[4]); if (unlikely((__pyx_v_max_neg_val == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 42, __pyx_L3_error) + } else { + __pyx_v_max_neg_val = __pyx_mstate_global->__pyx_k__6; + } + } + goto __pyx_L6_skip; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("maximum_path_c", 0, 4, 5, __pyx_nargs); __PYX_ERR(0, 40, __pyx_L3_error) + __pyx_L6_skip:; + goto __pyx_L4_argument_unpacking_done; + __pyx_L3_error:; + for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { + Py_XDECREF(values[__pyx_temp]); + } + __PYX_XCLEAR_MEMVIEW(&__pyx_v_paths, 1); + __PYX_XCLEAR_MEMVIEW(&__pyx_v_values, 1); + __PYX_XCLEAR_MEMVIEW(&__pyx_v_t_xs, 1); + __PYX_XCLEAR_MEMVIEW(&__pyx_v_t_ys, 1); + __Pyx_AddTraceback("matcha.utils.monotonic_align.core.maximum_path_c", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_6matcha_5utils_15monotonic_align_4core_maximum_path_c(__pyx_self, __pyx_v_paths, __pyx_v_values, __pyx_v_t_xs, __pyx_v_t_ys, __pyx_v_max_neg_val); + + /* function exit code */ + for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) { + Py_XDECREF(values[__pyx_temp]); + } + __PYX_XCLEAR_MEMVIEW(&__pyx_v_paths, 1); + __PYX_XCLEAR_MEMVIEW(&__pyx_v_values, 1); + __PYX_XCLEAR_MEMVIEW(&__pyx_v_t_xs, 1); + __PYX_XCLEAR_MEMVIEW(&__pyx_v_t_ys, 1); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_6matcha_5utils_15monotonic_align_4core_maximum_path_c(CYTHON_UNUSED PyObject *__pyx_self, __Pyx_memviewslice __pyx_v_paths, __Pyx_memviewslice __pyx_v_values, __Pyx_memviewslice __pyx_v_t_xs, __Pyx_memviewslice __pyx_v_t_ys, float __pyx_v_max_neg_val) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + struct __pyx_opt_args_6matcha_5utils_15monotonic_align_4core_maximum_path_c __pyx_t_1; + PyObject *__pyx_t_2 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("maximum_path_c", 0); + __Pyx_XDECREF(__pyx_r); + if (unlikely(!__pyx_v_paths.memview)) { __Pyx_RaiseUnboundLocalError("paths"); __PYX_ERR(0, 40, __pyx_L1_error) } + if (unlikely(!__pyx_v_values.memview)) { __Pyx_RaiseUnboundLocalError("values"); __PYX_ERR(0, 40, __pyx_L1_error) } + if (unlikely(!__pyx_v_t_xs.memview)) { __Pyx_RaiseUnboundLocalError("t_xs"); __PYX_ERR(0, 40, __pyx_L1_error) } + if (unlikely(!__pyx_v_t_ys.memview)) { __Pyx_RaiseUnboundLocalError("t_ys"); __PYX_ERR(0, 40, __pyx_L1_error) } + __pyx_t_1.__pyx_n = 1; + __pyx_t_1.max_neg_val = __pyx_v_max_neg_val; + __pyx_f_6matcha_5utils_15monotonic_align_4core_maximum_path_c(__pyx_v_paths, __pyx_v_values, __pyx_v_t_xs, __pyx_v_t_ys, 1, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 40, __pyx_L1_error) + __pyx_t_2 = __Pyx_void_to_None(NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 40, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + goto __pyx_L0; + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("matcha.utils.monotonic_align.core.maximum_path_c", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} +/* #### Code section: module_exttypes ### */ +static struct __pyx_vtabstruct_array __pyx_vtable_array; + +static PyObject *__pyx_tp_new_array(PyTypeObject *t, PyObject *a, PyObject *k) { + struct __pyx_array_obj *p; + PyObject *o; + o = __Pyx_AllocateExtensionType(t, 0); + if (unlikely(!o)) return 0; + p = ((struct __pyx_array_obj *)o); + p->__pyx_vtab = __pyx_vtabptr_array; + p->mode = ((PyObject*)Py_None); Py_INCREF(Py_None); + p->_format = ((PyObject*)Py_None); Py_INCREF(Py_None); + if (unlikely(__pyx_array___cinit__(o, a, k) < 0)) goto bad; + return o; + bad: + Py_DECREF(o); o = 0; + return NULL; +} + +static void __pyx_tp_dealloc_array(PyObject *o) { + struct __pyx_array_obj *p = (struct __pyx_array_obj *)o; + #if CYTHON_USE_TP_FINALIZE + if (unlikely(__Pyx_PyObject_GetSlot(o, tp_finalize, destructor)) && (!PyType_IS_GC(Py_TYPE(o)) || !__Pyx_PyObject_GC_IsFinalized(o))) { + if (__Pyx_PyObject_GetSlot(o, tp_dealloc, destructor) == __pyx_tp_dealloc_array) { + if (PyObject_CallFinalizerFromDealloc(o)) return; + } + } + #endif + { + PyObject *etype, *eval, *etb; + PyErr_Fetch(&etype, &eval, &etb); + __Pyx_SET_REFCNT(o, Py_REFCNT(o) + 1); + __pyx_array___dealloc__(o); + __Pyx_SET_REFCNT(o, Py_REFCNT(o) - 1); + PyErr_Restore(etype, eval, etb); + } + Py_CLEAR(p->mode); + Py_CLEAR(p->_format); + PyTypeObject *tp = Py_TYPE(o); + #if CYTHON_USE_TYPE_SLOTS + (*tp->tp_free)(o); + #else + { + freefunc tp_free = (freefunc)PyType_GetSlot(tp, Py_tp_free); + if (tp_free) tp_free(o); + } + #endif + #if CYTHON_USE_TYPE_SPECS + Py_DECREF(tp); + #endif +} + +static PyObject *__pyx_sq_item_array(PyObject *o, Py_ssize_t i) { + PyObject *r; + PyObject *x = PyLong_FromSsize_t(i); if(!x) return 0; + #if CYTHON_USE_TYPE_SLOTS || (!CYTHON_USE_TYPE_SPECS && __PYX_LIMITED_VERSION_HEX < 0x030A0000) + r = Py_TYPE(o)->tp_as_mapping->mp_subscript(o, x); + #else + r = ((binaryfunc)PyType_GetSlot(Py_TYPE(o), Py_mp_subscript))(o, x); + #endif + Py_DECREF(x); + return r; +} + +static int __pyx_mp_ass_subscript_array(PyObject *o, PyObject *i, PyObject *v) { + if (v) { + return __pyx_array___setitem__(o, i, v); + } + else { + __Pyx_TypeName o_type_name; + o_type_name = __Pyx_PyType_GetFullyQualifiedName(Py_TYPE(o)); + PyErr_Format(PyExc_NotImplementedError, + "Subscript deletion not supported by " __Pyx_FMT_TYPENAME, o_type_name); + __Pyx_DECREF_TypeName(o_type_name); + return -1; + } +} + +static PyObject *__pyx_tp_getattro_array(PyObject *o, PyObject *n) { + PyObject *v = PyObject_GenericGetAttr(o, n); + if (!v && PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + v = __pyx_array___getattr__(o, n); + } + return v; +} + +static PyObject *__pyx_getprop___pyx_array_memview(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_15View_dot_MemoryView_5array_7memview_1__get__(o); +} + +static PyMethodDef __pyx_methods_array[] = { + {"__getattr__", (PyCFunction)__pyx_array___getattr__, METH_O|METH_COEXIST, 0}, + {"__reduce_cython__", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw___pyx_array_1__reduce_cython__, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}, + {"__setstate_cython__", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw___pyx_array_3__setstate_cython__, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}, + {0, 0, 0, 0} +}; + +static struct PyGetSetDef __pyx_getsets_array[] = { + {"memview", __pyx_getprop___pyx_array_memview, 0, 0, 0}, + {0, 0, 0, 0, 0} +}; +#if CYTHON_USE_TYPE_SPECS +#if !CYTHON_COMPILING_IN_LIMITED_API + +static PyBufferProcs __pyx_tp_as_buffer_array = { + __pyx_array_getbuffer, /*bf_getbuffer*/ + 0, /*bf_releasebuffer*/ +}; +#endif +static PyType_Slot __pyx_type___pyx_array_slots[] = { + {Py_tp_dealloc, (void *)__pyx_tp_dealloc_array}, + {Py_sq_length, (void *)__pyx_array___len__}, + {Py_sq_item, (void *)__pyx_sq_item_array}, + {Py_mp_length, (void *)__pyx_array___len__}, + {Py_mp_subscript, (void *)__pyx_array___getitem__}, + {Py_mp_ass_subscript, (void *)__pyx_mp_ass_subscript_array}, + {Py_tp_getattro, (void *)__pyx_tp_getattro_array}, + #if defined(Py_bf_getbuffer) + {Py_bf_getbuffer, (void *)__pyx_array_getbuffer}, + #endif + {Py_tp_methods, (void *)__pyx_methods_array}, + {Py_tp_getset, (void *)__pyx_getsets_array}, + {Py_tp_new, (void *)__pyx_tp_new_array}, + {0, 0}, +}; +static PyType_Spec __pyx_type___pyx_array_spec = { + "matcha.utils.monotonic_align.core.array", + sizeof(struct __pyx_array_obj), + 0, + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_SEQUENCE, + __pyx_type___pyx_array_slots, +}; +#else + +static PySequenceMethods __pyx_tp_as_sequence_array = { + __pyx_array___len__, /*sq_length*/ + 0, /*sq_concat*/ + 0, /*sq_repeat*/ + __pyx_sq_item_array, /*sq_item*/ + 0, /*sq_slice*/ + 0, /*sq_ass_item*/ + 0, /*sq_ass_slice*/ + 0, /*sq_contains*/ + 0, /*sq_inplace_concat*/ + 0, /*sq_inplace_repeat*/ +}; + +static PyMappingMethods __pyx_tp_as_mapping_array = { + __pyx_array___len__, /*mp_length*/ + __pyx_array___getitem__, /*mp_subscript*/ + __pyx_mp_ass_subscript_array, /*mp_ass_subscript*/ +}; + +static PyBufferProcs __pyx_tp_as_buffer_array = { + __pyx_array_getbuffer, /*bf_getbuffer*/ + 0, /*bf_releasebuffer*/ +}; + +static PyTypeObject __pyx_type___pyx_array = { + PyVarObject_HEAD_INIT(0, 0) + "matcha.utils.monotonic_align.core.""array", /*tp_name*/ + sizeof(struct __pyx_array_obj), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + __pyx_tp_dealloc_array, /*tp_dealloc*/ + 0, /*tp_vectorcall_offset*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_as_async*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + &__pyx_tp_as_sequence_array, /*tp_as_sequence*/ + &__pyx_tp_as_mapping_array, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + __pyx_tp_getattro_array, /*tp_getattro*/ + 0, /*tp_setattro*/ + &__pyx_tp_as_buffer_array, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_SEQUENCE, /*tp_flags*/ + 0, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + __pyx_methods_array, /*tp_methods*/ + 0, /*tp_members*/ + __pyx_getsets_array, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + #if !CYTHON_USE_TYPE_SPECS + 0, /*tp_dictoffset*/ + #endif + 0, /*tp_init*/ + 0, /*tp_alloc*/ + __pyx_tp_new_array, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ + 0, /*tp_bases*/ + 0, /*tp_mro*/ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0, /*tp_weaklist*/ + 0, /*tp_del*/ + 0, /*tp_version_tag*/ + #if CYTHON_USE_TP_FINALIZE + 0, /*tp_finalize*/ + #else + NULL, /*tp_finalize*/ + #endif + #if !CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800 + 0, /*tp_vectorcall*/ + #endif + #if __PYX_NEED_TP_PRINT_SLOT == 1 + 0, /*tp_print*/ + #endif + #if PY_VERSION_HEX >= 0x030C0000 + 0, /*tp_watched*/ + #endif + #if PY_VERSION_HEX >= 0x030d00A4 + 0, /*tp_versions_used*/ + #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000 + 0, /*tp_pypy_flags*/ + #endif +}; +#endif + +static PyObject *__pyx_tp_new_Enum(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) { + struct __pyx_MemviewEnum_obj *p; + PyObject *o; + o = __Pyx_AllocateExtensionType(t, 0); + if (unlikely(!o)) return 0; + p = ((struct __pyx_MemviewEnum_obj *)o); + p->name = Py_None; Py_INCREF(Py_None); + return o; +} + +static void __pyx_tp_dealloc_Enum(PyObject *o) { + struct __pyx_MemviewEnum_obj *p = (struct __pyx_MemviewEnum_obj *)o; + #if CYTHON_USE_TP_FINALIZE + if (unlikely(__Pyx_PyObject_GetSlot(o, tp_finalize, destructor)) && !__Pyx_PyObject_GC_IsFinalized(o)) { + if (__Pyx_PyObject_GetSlot(o, tp_dealloc, destructor) == __pyx_tp_dealloc_Enum) { + if (PyObject_CallFinalizerFromDealloc(o)) return; + } + } + #endif + PyObject_GC_UnTrack(o); + Py_CLEAR(p->name); + PyTypeObject *tp = Py_TYPE(o); + #if CYTHON_USE_TYPE_SLOTS + (*tp->tp_free)(o); + #else + { + freefunc tp_free = (freefunc)PyType_GetSlot(tp, Py_tp_free); + if (tp_free) tp_free(o); + } + #endif + #if CYTHON_USE_TYPE_SPECS + Py_DECREF(tp); + #endif +} + +static int __pyx_tp_traverse_Enum(PyObject *o, visitproc v, void *a) { + int e; + struct __pyx_MemviewEnum_obj *p = (struct __pyx_MemviewEnum_obj *)o; + { + e = __Pyx_call_type_traverse(o, 1, v, a); + if (e) return e; + } + if (p->name) { + e = (*v)(p->name, a); if (e) return e; + } + return 0; +} + +static int __pyx_tp_clear_Enum(PyObject *o) { + PyObject* tmp; + struct __pyx_MemviewEnum_obj *p = (struct __pyx_MemviewEnum_obj *)o; + tmp = ((PyObject*)p->name); + p->name = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + return 0; +} + +static PyMethodDef __pyx_methods_Enum[] = { + {"__reduce_cython__", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw___pyx_MemviewEnum_1__reduce_cython__, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}, + {"__setstate_cython__", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw___pyx_MemviewEnum_3__setstate_cython__, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}, + {0, 0, 0, 0} +}; +#if CYTHON_USE_TYPE_SPECS +static PyType_Slot __pyx_type___pyx_MemviewEnum_slots[] = { + {Py_tp_dealloc, (void *)__pyx_tp_dealloc_Enum}, + {Py_tp_repr, (void *)__pyx_MemviewEnum___repr__}, + {Py_tp_traverse, (void *)__pyx_tp_traverse_Enum}, + {Py_tp_clear, (void *)__pyx_tp_clear_Enum}, + {Py_tp_methods, (void *)__pyx_methods_Enum}, + {Py_tp_init, (void *)__pyx_MemviewEnum___init__}, + {Py_tp_new, (void *)__pyx_tp_new_Enum}, + {0, 0}, +}; +static PyType_Spec __pyx_type___pyx_MemviewEnum_spec = { + "matcha.utils.monotonic_align.core.Enum", + sizeof(struct __pyx_MemviewEnum_obj), + 0, + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, + __pyx_type___pyx_MemviewEnum_slots, +}; +#else + +static PyTypeObject __pyx_type___pyx_MemviewEnum = { + PyVarObject_HEAD_INIT(0, 0) + "matcha.utils.monotonic_align.core.""Enum", /*tp_name*/ + sizeof(struct __pyx_MemviewEnum_obj), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + __pyx_tp_dealloc_Enum, /*tp_dealloc*/ + 0, /*tp_vectorcall_offset*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_as_async*/ + __pyx_MemviewEnum___repr__, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + 0, /*tp_doc*/ + __pyx_tp_traverse_Enum, /*tp_traverse*/ + __pyx_tp_clear_Enum, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + __pyx_methods_Enum, /*tp_methods*/ + 0, /*tp_members*/ + 0, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + #if !CYTHON_USE_TYPE_SPECS + 0, /*tp_dictoffset*/ + #endif + __pyx_MemviewEnum___init__, /*tp_init*/ + 0, /*tp_alloc*/ + __pyx_tp_new_Enum, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ + 0, /*tp_bases*/ + 0, /*tp_mro*/ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0, /*tp_weaklist*/ + 0, /*tp_del*/ + 0, /*tp_version_tag*/ + #if CYTHON_USE_TP_FINALIZE + 0, /*tp_finalize*/ + #else + NULL, /*tp_finalize*/ + #endif + #if !CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800 + 0, /*tp_vectorcall*/ + #endif + #if __PYX_NEED_TP_PRINT_SLOT == 1 + 0, /*tp_print*/ + #endif + #if PY_VERSION_HEX >= 0x030C0000 + 0, /*tp_watched*/ + #endif + #if PY_VERSION_HEX >= 0x030d00A4 + 0, /*tp_versions_used*/ + #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000 + 0, /*tp_pypy_flags*/ + #endif +}; +#endif +static struct __pyx_vtabstruct_memoryview __pyx_vtable_memoryview; + +static PyObject *__pyx_tp_new_memoryview(PyTypeObject *t, PyObject *a, PyObject *k) { + struct __pyx_memoryview_obj *p; + PyObject *o; + o = __Pyx_AllocateExtensionType(t, 0); + if (unlikely(!o)) return 0; + p = ((struct __pyx_memoryview_obj *)o); + p->__pyx_vtab = __pyx_vtabptr_memoryview; + p->obj = Py_None; Py_INCREF(Py_None); + p->_size = Py_None; Py_INCREF(Py_None); + p->view.obj = NULL; + if (unlikely(__pyx_memoryview___cinit__(o, a, k) < 0)) goto bad; + return o; + bad: + Py_DECREF(o); o = 0; + return NULL; +} + +static void __pyx_tp_dealloc_memoryview(PyObject *o) { + struct __pyx_memoryview_obj *p = (struct __pyx_memoryview_obj *)o; + #if CYTHON_USE_TP_FINALIZE + if (unlikely(__Pyx_PyObject_GetSlot(o, tp_finalize, destructor)) && !__Pyx_PyObject_GC_IsFinalized(o)) { + if (__Pyx_PyObject_GetSlot(o, tp_dealloc, destructor) == __pyx_tp_dealloc_memoryview) { + if (PyObject_CallFinalizerFromDealloc(o)) return; + } + } + #endif + PyObject_GC_UnTrack(o); + { + PyObject *etype, *eval, *etb; + PyErr_Fetch(&etype, &eval, &etb); + __Pyx_SET_REFCNT(o, Py_REFCNT(o) + 1); + __pyx_memoryview___dealloc__(o); + __Pyx_SET_REFCNT(o, Py_REFCNT(o) - 1); + PyErr_Restore(etype, eval, etb); + } + Py_CLEAR(p->obj); + Py_CLEAR(p->_size); + PyTypeObject *tp = Py_TYPE(o); + #if CYTHON_USE_TYPE_SLOTS + (*tp->tp_free)(o); + #else + { + freefunc tp_free = (freefunc)PyType_GetSlot(tp, Py_tp_free); + if (tp_free) tp_free(o); + } + #endif + #if CYTHON_USE_TYPE_SPECS + Py_DECREF(tp); + #endif +} + +static int __pyx_tp_traverse_memoryview(PyObject *o, visitproc v, void *a) { + int e; + struct __pyx_memoryview_obj *p = (struct __pyx_memoryview_obj *)o; + { + e = __Pyx_call_type_traverse(o, 1, v, a); + if (e) return e; + } + if (p->obj) { + e = (*v)(p->obj, a); if (e) return e; + } + if (p->_size) { + e = (*v)(p->_size, a); if (e) return e; + } + if (p->view.obj) { + e = (*v)(p->view.obj, a); if (e) return e; + } + return 0; +} + +static int __pyx_tp_clear_memoryview(PyObject *o) { + PyObject* tmp; + struct __pyx_memoryview_obj *p = (struct __pyx_memoryview_obj *)o; + tmp = ((PyObject*)p->obj); + p->obj = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->_size); + p->_size = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + Py_CLEAR(p->view.obj); + return 0; +} + +static PyObject *__pyx_sq_item_memoryview(PyObject *o, Py_ssize_t i) { + PyObject *r; + PyObject *x = PyLong_FromSsize_t(i); if(!x) return 0; + #if CYTHON_USE_TYPE_SLOTS || (!CYTHON_USE_TYPE_SPECS && __PYX_LIMITED_VERSION_HEX < 0x030A0000) + r = Py_TYPE(o)->tp_as_mapping->mp_subscript(o, x); + #else + r = ((binaryfunc)PyType_GetSlot(Py_TYPE(o), Py_mp_subscript))(o, x); + #endif + Py_DECREF(x); + return r; +} + +static int __pyx_mp_ass_subscript_memoryview(PyObject *o, PyObject *i, PyObject *v) { + if (v) { + return __pyx_memoryview___setitem__(o, i, v); + } + else { + __Pyx_TypeName o_type_name; + o_type_name = __Pyx_PyType_GetFullyQualifiedName(Py_TYPE(o)); + PyErr_Format(PyExc_NotImplementedError, + "Subscript deletion not supported by " __Pyx_FMT_TYPENAME, o_type_name); + __Pyx_DECREF_TypeName(o_type_name); + return -1; + } +} + +static PyObject *__pyx_getprop___pyx_memoryview_T(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_15View_dot_MemoryView_10memoryview_1T_1__get__(o); +} + +static PyObject *__pyx_getprop___pyx_memoryview_base(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_15View_dot_MemoryView_10memoryview_4base_1__get__(o); +} + +static PyObject *__pyx_getprop___pyx_memoryview_shape(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_15View_dot_MemoryView_10memoryview_5shape_1__get__(o); +} + +static PyObject *__pyx_getprop___pyx_memoryview_strides(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_15View_dot_MemoryView_10memoryview_7strides_1__get__(o); +} + +static PyObject *__pyx_getprop___pyx_memoryview_suboffsets(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_15View_dot_MemoryView_10memoryview_10suboffsets_1__get__(o); +} + +static PyObject *__pyx_getprop___pyx_memoryview_ndim(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_15View_dot_MemoryView_10memoryview_4ndim_1__get__(o); +} + +static PyObject *__pyx_getprop___pyx_memoryview_itemsize(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_15View_dot_MemoryView_10memoryview_8itemsize_1__get__(o); +} + +static PyObject *__pyx_getprop___pyx_memoryview_nbytes(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_15View_dot_MemoryView_10memoryview_6nbytes_1__get__(o); +} + +static PyObject *__pyx_getprop___pyx_memoryview_size(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_15View_dot_MemoryView_10memoryview_4size_1__get__(o); +} + +static PyMethodDef __pyx_methods_memoryview[] = { + {"is_c_contig", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_memoryview_is_c_contig, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}, + {"is_f_contig", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_memoryview_is_f_contig, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}, + {"copy", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_memoryview_copy, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}, + {"copy_fortran", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_memoryview_copy_fortran, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}, + {"__reduce_cython__", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw___pyx_memoryview_1__reduce_cython__, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}, + {"__setstate_cython__", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw___pyx_memoryview_3__setstate_cython__, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}, + {0, 0, 0, 0} +}; + +static struct PyGetSetDef __pyx_getsets_memoryview[] = { + {"T", __pyx_getprop___pyx_memoryview_T, 0, 0, 0}, + {"base", __pyx_getprop___pyx_memoryview_base, 0, 0, 0}, + {"shape", __pyx_getprop___pyx_memoryview_shape, 0, 0, 0}, + {"strides", __pyx_getprop___pyx_memoryview_strides, 0, 0, 0}, + {"suboffsets", __pyx_getprop___pyx_memoryview_suboffsets, 0, 0, 0}, + {"ndim", __pyx_getprop___pyx_memoryview_ndim, 0, 0, 0}, + {"itemsize", __pyx_getprop___pyx_memoryview_itemsize, 0, 0, 0}, + {"nbytes", __pyx_getprop___pyx_memoryview_nbytes, 0, 0, 0}, + {"size", __pyx_getprop___pyx_memoryview_size, 0, 0, 0}, + {0, 0, 0, 0, 0} +}; +#if CYTHON_USE_TYPE_SPECS +#if !CYTHON_COMPILING_IN_LIMITED_API + +static PyBufferProcs __pyx_tp_as_buffer_memoryview = { + __pyx_memoryview_getbuffer, /*bf_getbuffer*/ + 0, /*bf_releasebuffer*/ +}; +#endif +static PyType_Slot __pyx_type___pyx_memoryview_slots[] = { + {Py_tp_dealloc, (void *)__pyx_tp_dealloc_memoryview}, + {Py_tp_repr, (void *)__pyx_memoryview___repr__}, + {Py_sq_length, (void *)__pyx_memoryview___len__}, + {Py_sq_item, (void *)__pyx_sq_item_memoryview}, + {Py_mp_length, (void *)__pyx_memoryview___len__}, + {Py_mp_subscript, (void *)__pyx_memoryview___getitem__}, + {Py_mp_ass_subscript, (void *)__pyx_mp_ass_subscript_memoryview}, + {Py_tp_str, (void *)__pyx_memoryview___str__}, + #if defined(Py_bf_getbuffer) + {Py_bf_getbuffer, (void *)__pyx_memoryview_getbuffer}, + #endif + {Py_tp_traverse, (void *)__pyx_tp_traverse_memoryview}, + {Py_tp_clear, (void *)__pyx_tp_clear_memoryview}, + {Py_tp_methods, (void *)__pyx_methods_memoryview}, + {Py_tp_getset, (void *)__pyx_getsets_memoryview}, + {Py_tp_new, (void *)__pyx_tp_new_memoryview}, + {0, 0}, +}; +static PyType_Spec __pyx_type___pyx_memoryview_spec = { + "matcha.utils.monotonic_align.core.memoryview", + sizeof(struct __pyx_memoryview_obj), + 0, + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, + __pyx_type___pyx_memoryview_slots, +}; +#else + +static PySequenceMethods __pyx_tp_as_sequence_memoryview = { + __pyx_memoryview___len__, /*sq_length*/ + 0, /*sq_concat*/ + 0, /*sq_repeat*/ + __pyx_sq_item_memoryview, /*sq_item*/ + 0, /*sq_slice*/ + 0, /*sq_ass_item*/ + 0, /*sq_ass_slice*/ + 0, /*sq_contains*/ + 0, /*sq_inplace_concat*/ + 0, /*sq_inplace_repeat*/ +}; + +static PyMappingMethods __pyx_tp_as_mapping_memoryview = { + __pyx_memoryview___len__, /*mp_length*/ + __pyx_memoryview___getitem__, /*mp_subscript*/ + __pyx_mp_ass_subscript_memoryview, /*mp_ass_subscript*/ +}; + +static PyBufferProcs __pyx_tp_as_buffer_memoryview = { + __pyx_memoryview_getbuffer, /*bf_getbuffer*/ + 0, /*bf_releasebuffer*/ +}; + +static PyTypeObject __pyx_type___pyx_memoryview = { + PyVarObject_HEAD_INIT(0, 0) + "matcha.utils.monotonic_align.core.""memoryview", /*tp_name*/ + sizeof(struct __pyx_memoryview_obj), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + __pyx_tp_dealloc_memoryview, /*tp_dealloc*/ + 0, /*tp_vectorcall_offset*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_as_async*/ + __pyx_memoryview___repr__, /*tp_repr*/ + 0, /*tp_as_number*/ + &__pyx_tp_as_sequence_memoryview, /*tp_as_sequence*/ + &__pyx_tp_as_mapping_memoryview, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + __pyx_memoryview___str__, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + &__pyx_tp_as_buffer_memoryview, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + 0, /*tp_doc*/ + __pyx_tp_traverse_memoryview, /*tp_traverse*/ + __pyx_tp_clear_memoryview, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + __pyx_methods_memoryview, /*tp_methods*/ + 0, /*tp_members*/ + __pyx_getsets_memoryview, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + #if !CYTHON_USE_TYPE_SPECS + 0, /*tp_dictoffset*/ + #endif + 0, /*tp_init*/ + 0, /*tp_alloc*/ + __pyx_tp_new_memoryview, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ + 0, /*tp_bases*/ + 0, /*tp_mro*/ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0, /*tp_weaklist*/ + 0, /*tp_del*/ + 0, /*tp_version_tag*/ + #if CYTHON_USE_TP_FINALIZE + 0, /*tp_finalize*/ + #else + NULL, /*tp_finalize*/ + #endif + #if !CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800 + 0, /*tp_vectorcall*/ + #endif + #if __PYX_NEED_TP_PRINT_SLOT == 1 + 0, /*tp_print*/ + #endif + #if PY_VERSION_HEX >= 0x030C0000 + 0, /*tp_watched*/ + #endif + #if PY_VERSION_HEX >= 0x030d00A4 + 0, /*tp_versions_used*/ + #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000 + 0, /*tp_pypy_flags*/ + #endif +}; +#endif +static struct __pyx_vtabstruct__memoryviewslice __pyx_vtable__memoryviewslice; + +static PyObject *__pyx_tp_new__memoryviewslice(PyTypeObject *t, PyObject *a, PyObject *k) { + struct __pyx_memoryviewslice_obj *p; + PyObject *o = __pyx_tp_new_memoryview(t, a, k); + if (unlikely(!o)) return 0; + p = ((struct __pyx_memoryviewslice_obj *)o); + p->__pyx_base.__pyx_vtab = (struct __pyx_vtabstruct_memoryview*)__pyx_vtabptr__memoryviewslice; + p->from_object = Py_None; Py_INCREF(Py_None); + p->from_slice.memview = NULL; + return o; +} + +static void __pyx_tp_dealloc__memoryviewslice(PyObject *o) { + struct __pyx_memoryviewslice_obj *p = (struct __pyx_memoryviewslice_obj *)o; + #if CYTHON_USE_TP_FINALIZE + if (unlikely(__Pyx_PyObject_GetSlot(o, tp_finalize, destructor)) && !__Pyx_PyObject_GC_IsFinalized(o)) { + if (__Pyx_PyObject_GetSlot(o, tp_dealloc, destructor) == __pyx_tp_dealloc__memoryviewslice) { + if (PyObject_CallFinalizerFromDealloc(o)) return; + } + } + #endif + PyObject_GC_UnTrack(o); + { + PyObject *etype, *eval, *etb; + PyErr_Fetch(&etype, &eval, &etb); + __Pyx_SET_REFCNT(o, Py_REFCNT(o) + 1); + __pyx_memoryviewslice___dealloc__(o); + __Pyx_SET_REFCNT(o, Py_REFCNT(o) - 1); + PyErr_Restore(etype, eval, etb); + } + Py_CLEAR(p->from_object); + PyObject_GC_Track(o); + __pyx_tp_dealloc_memoryview(o); +} + +static int __pyx_tp_traverse__memoryviewslice(PyObject *o, visitproc v, void *a) { + int e; + struct __pyx_memoryviewslice_obj *p = (struct __pyx_memoryviewslice_obj *)o; + e = __pyx_tp_traverse_memoryview(o, v, a); if (e) return e; + if (p->from_object) { + e = (*v)(p->from_object, a); if (e) return e; + } + return 0; +} + +static int __pyx_tp_clear__memoryviewslice(PyObject *o) { + PyObject* tmp; + struct __pyx_memoryviewslice_obj *p = (struct __pyx_memoryviewslice_obj *)o; + __pyx_tp_clear_memoryview(o); + tmp = ((PyObject*)p->from_object); + p->from_object = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + __PYX_XCLEAR_MEMVIEW(&p->from_slice, 1); + return 0; +} + +static PyMethodDef __pyx_methods__memoryviewslice[] = { + {"__reduce_cython__", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw___pyx_memoryviewslice_1__reduce_cython__, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}, + {"__setstate_cython__", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw___pyx_memoryviewslice_3__setstate_cython__, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0}, + {0, 0, 0, 0} +}; +#if CYTHON_USE_TYPE_SPECS +static PyType_Slot __pyx_type___pyx_memoryviewslice_slots[] = { + {Py_tp_dealloc, (void *)__pyx_tp_dealloc__memoryviewslice}, + {Py_tp_doc, (void *)PyDoc_STR("Internal class for passing memoryview slices to Python")}, + {Py_tp_traverse, (void *)__pyx_tp_traverse__memoryviewslice}, + {Py_tp_clear, (void *)__pyx_tp_clear__memoryviewslice}, + {Py_tp_methods, (void *)__pyx_methods__memoryviewslice}, + {Py_tp_new, (void *)__pyx_tp_new__memoryviewslice}, + {0, 0}, +}; +static PyType_Spec __pyx_type___pyx_memoryviewslice_spec = { + "matcha.utils.monotonic_align.core._memoryviewslice", + sizeof(struct __pyx_memoryviewslice_obj), + 0, + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC|Py_TPFLAGS_SEQUENCE, + __pyx_type___pyx_memoryviewslice_slots, +}; +#else + +static PyTypeObject __pyx_type___pyx_memoryviewslice = { + PyVarObject_HEAD_INIT(0, 0) + "matcha.utils.monotonic_align.core.""_memoryviewslice", /*tp_name*/ + sizeof(struct __pyx_memoryviewslice_obj), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + __pyx_tp_dealloc__memoryviewslice, /*tp_dealloc*/ + 0, /*tp_vectorcall_offset*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_as_async*/ + #if CYTHON_COMPILING_IN_PYPY || 0 + __pyx_memoryview___repr__, /*tp_repr*/ + #else + 0, /*tp_repr*/ + #endif + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + #if CYTHON_COMPILING_IN_PYPY || 0 + __pyx_memoryview___str__, /*tp_str*/ + #else + 0, /*tp_str*/ + #endif + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC|Py_TPFLAGS_SEQUENCE, /*tp_flags*/ + PyDoc_STR("Internal class for passing memoryview slices to Python"), /*tp_doc*/ + __pyx_tp_traverse__memoryviewslice, /*tp_traverse*/ + __pyx_tp_clear__memoryviewslice, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + __pyx_methods__memoryviewslice, /*tp_methods*/ + 0, /*tp_members*/ + 0, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + #if !CYTHON_USE_TYPE_SPECS + 0, /*tp_dictoffset*/ + #endif + 0, /*tp_init*/ + 0, /*tp_alloc*/ + __pyx_tp_new__memoryviewslice, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ + 0, /*tp_bases*/ + 0, /*tp_mro*/ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0, /*tp_weaklist*/ + 0, /*tp_del*/ + 0, /*tp_version_tag*/ + #if CYTHON_USE_TP_FINALIZE + 0, /*tp_finalize*/ + #else + NULL, /*tp_finalize*/ + #endif + #if !CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800 + 0, /*tp_vectorcall*/ + #endif + #if __PYX_NEED_TP_PRINT_SLOT == 1 + 0, /*tp_print*/ + #endif + #if PY_VERSION_HEX >= 0x030C0000 + 0, /*tp_watched*/ + #endif + #if PY_VERSION_HEX >= 0x030d00A4 + 0, /*tp_versions_used*/ + #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000 + 0, /*tp_pypy_flags*/ + #endif +}; +#endif + +static PyMethodDef __pyx_methods[] = { + {0, 0, 0, 0} +}; +/* #### Code section: initfunc_declarations ### */ +static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(__pyx_mstatetype *__pyx_mstate); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(__pyx_mstatetype *__pyx_mstate); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_InitConstants(__pyx_mstatetype *__pyx_mstate); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_global_init_code(__pyx_mstatetype *__pyx_mstate); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_variable_export_code(__pyx_mstatetype *__pyx_mstate); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_function_export_code(__pyx_mstatetype *__pyx_mstate); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_type_init_code(__pyx_mstatetype *__pyx_mstate); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_type_import_code(__pyx_mstatetype *__pyx_mstate); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_variable_import_code(__pyx_mstatetype *__pyx_mstate); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_function_import_code(__pyx_mstatetype *__pyx_mstate); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_CreateCodeObjects(__pyx_mstatetype *__pyx_mstate); /*proto*/ +/* #### Code section: init_module ### */ + +static int __Pyx_modinit_global_init_code(__pyx_mstatetype *__pyx_mstate) { + __Pyx_RefNannyDeclarations + CYTHON_UNUSED_VAR(__pyx_mstate); + __Pyx_RefNannySetupContext("__Pyx_modinit_global_init_code", 0); + /*--- Global init code ---*/ + __pyx_collections_abc_Sequence = Py_None; Py_INCREF(Py_None); + generic = Py_None; Py_INCREF(Py_None); + strided = Py_None; Py_INCREF(Py_None); + indirect = Py_None; Py_INCREF(Py_None); + contiguous = Py_None; Py_INCREF(Py_None); + indirect_contiguous = Py_None; Py_INCREF(Py_None); + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_variable_export_code(__pyx_mstatetype *__pyx_mstate) { + __Pyx_RefNannyDeclarations + CYTHON_UNUSED_VAR(__pyx_mstate); + __Pyx_RefNannySetupContext("__Pyx_modinit_variable_export_code", 0); + /*--- Variable export code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_function_export_code(__pyx_mstatetype *__pyx_mstate) { + __Pyx_RefNannyDeclarations + CYTHON_UNUSED_VAR(__pyx_mstate); + __Pyx_RefNannySetupContext("__Pyx_modinit_function_export_code", 0); + /*--- Function export code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_type_init_code(__pyx_mstatetype *__pyx_mstate) { + __Pyx_RefNannyDeclarations + CYTHON_UNUSED_VAR(__pyx_mstate); + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__Pyx_modinit_type_init_code", 0); + /*--- Type init code ---*/ + __pyx_vtabptr_array = &__pyx_vtable_array; + __pyx_vtable_array.get_memview = (PyObject *(*)(struct __pyx_array_obj *))__pyx_array_get_memview; + #if CYTHON_USE_TYPE_SPECS + __pyx_mstate->__pyx_array_type = (PyTypeObject *) __Pyx_PyType_FromModuleAndSpec(__pyx_m, &__pyx_type___pyx_array_spec, NULL); if (unlikely(!__pyx_mstate->__pyx_array_type)) __PYX_ERR(1, 118, __pyx_L1_error) + #if !CYTHON_COMPILING_IN_LIMITED_API + __pyx_mstate->__pyx_array_type->tp_as_buffer = &__pyx_tp_as_buffer_array; + if (!__pyx_mstate->__pyx_array_type->tp_as_buffer->bf_releasebuffer && __pyx_mstate->__pyx_array_type->tp_base->tp_as_buffer && __pyx_mstate->__pyx_array_type->tp_base->tp_as_buffer->bf_releasebuffer) { + __pyx_mstate->__pyx_array_type->tp_as_buffer->bf_releasebuffer = __pyx_mstate->__pyx_array_type->tp_base->tp_as_buffer->bf_releasebuffer; + } + #elif defined(Py_bf_getbuffer) && defined(Py_bf_releasebuffer) + /* PY_VERSION_HEX >= 0x03090000 || Py_LIMITED_API >= 0x030B0000 */ + #elif defined(_MSC_VER) + #pragma message ("The buffer protocol is not supported in the Limited C-API < 3.11.") + #else + #warning "The buffer protocol is not supported in the Limited C-API < 3.11." + #endif + if (__Pyx_fix_up_extension_type_from_spec(&__pyx_type___pyx_array_spec, __pyx_mstate->__pyx_array_type) < (0)) __PYX_ERR(1, 118, __pyx_L1_error) + #else + __pyx_mstate->__pyx_array_type = &__pyx_type___pyx_array; + #endif + #if !CYTHON_COMPILING_IN_LIMITED_API + #endif + #if !CYTHON_USE_TYPE_SPECS + if (__Pyx_PyType_Ready(__pyx_mstate->__pyx_array_type) < (0)) __PYX_ERR(1, 118, __pyx_L1_error) + #endif + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000 + PyUnstable_Object_EnableDeferredRefcount((PyObject*)__pyx_mstate->__pyx_array_type); + #endif + if (__Pyx_SetVtable(__pyx_mstate->__pyx_array_type, __pyx_vtabptr_array) < (0)) __PYX_ERR(1, 118, __pyx_L1_error) + if (__Pyx_MergeVtables(__pyx_mstate->__pyx_array_type) < (0)) __PYX_ERR(1, 118, __pyx_L1_error) + if (__Pyx_setup_reduce((PyObject *) __pyx_mstate->__pyx_array_type) < (0)) __PYX_ERR(1, 118, __pyx_L1_error) + #if CYTHON_USE_TYPE_SPECS + __pyx_mstate->__pyx_MemviewEnum_type = (PyTypeObject *) __Pyx_PyType_FromModuleAndSpec(__pyx_m, &__pyx_type___pyx_MemviewEnum_spec, NULL); if (unlikely(!__pyx_mstate->__pyx_MemviewEnum_type)) __PYX_ERR(1, 307, __pyx_L1_error) + if (__Pyx_fix_up_extension_type_from_spec(&__pyx_type___pyx_MemviewEnum_spec, __pyx_mstate->__pyx_MemviewEnum_type) < (0)) __PYX_ERR(1, 307, __pyx_L1_error) + #else + __pyx_mstate->__pyx_MemviewEnum_type = &__pyx_type___pyx_MemviewEnum; + #endif + #if !CYTHON_COMPILING_IN_LIMITED_API + #endif + #if !CYTHON_USE_TYPE_SPECS + if (__Pyx_PyType_Ready(__pyx_mstate->__pyx_MemviewEnum_type) < (0)) __PYX_ERR(1, 307, __pyx_L1_error) + #endif + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000 + PyUnstable_Object_EnableDeferredRefcount((PyObject*)__pyx_mstate->__pyx_MemviewEnum_type); + #endif + #if !CYTHON_COMPILING_IN_LIMITED_API + if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_mstate->__pyx_MemviewEnum_type->tp_dictoffset && __pyx_mstate->__pyx_MemviewEnum_type->tp_getattro == PyObject_GenericGetAttr)) { + __pyx_mstate->__pyx_MemviewEnum_type->tp_getattro = PyObject_GenericGetAttr; + } + #endif + if (__Pyx_setup_reduce((PyObject *) __pyx_mstate->__pyx_MemviewEnum_type) < (0)) __PYX_ERR(1, 307, __pyx_L1_error) + __pyx_vtabptr_memoryview = &__pyx_vtable_memoryview; + __pyx_vtable_memoryview.get_item_pointer = (char *(*)(struct __pyx_memoryview_obj *, PyObject *))__pyx_memoryview_get_item_pointer; + __pyx_vtable_memoryview.is_slice = (PyObject *(*)(struct __pyx_memoryview_obj *, PyObject *))__pyx_memoryview_is_slice; + __pyx_vtable_memoryview.setitem_slice_assignment = (PyObject *(*)(struct __pyx_memoryview_obj *, PyObject *, PyObject *))__pyx_memoryview_setitem_slice_assignment; + __pyx_vtable_memoryview.setitem_slice_assign_scalar = (PyObject *(*)(struct __pyx_memoryview_obj *, struct __pyx_memoryview_obj *, PyObject *))__pyx_memoryview_setitem_slice_assign_scalar; + __pyx_vtable_memoryview.setitem_indexed = (PyObject *(*)(struct __pyx_memoryview_obj *, PyObject *, PyObject *))__pyx_memoryview_setitem_indexed; + __pyx_vtable_memoryview.convert_item_to_object = (PyObject *(*)(struct __pyx_memoryview_obj *, char *))__pyx_memoryview_convert_item_to_object; + __pyx_vtable_memoryview.assign_item_from_object = (PyObject *(*)(struct __pyx_memoryview_obj *, char *, PyObject *))__pyx_memoryview_assign_item_from_object; + __pyx_vtable_memoryview._get_base = (PyObject *(*)(struct __pyx_memoryview_obj *))__pyx_memoryview__get_base; + #if CYTHON_USE_TYPE_SPECS + __pyx_mstate->__pyx_memoryview_type = (PyTypeObject *) __Pyx_PyType_FromModuleAndSpec(__pyx_m, &__pyx_type___pyx_memoryview_spec, NULL); if (unlikely(!__pyx_mstate->__pyx_memoryview_type)) __PYX_ERR(1, 342, __pyx_L1_error) + #if !CYTHON_COMPILING_IN_LIMITED_API + __pyx_mstate->__pyx_memoryview_type->tp_as_buffer = &__pyx_tp_as_buffer_memoryview; + if (!__pyx_mstate->__pyx_memoryview_type->tp_as_buffer->bf_releasebuffer && __pyx_mstate->__pyx_memoryview_type->tp_base->tp_as_buffer && __pyx_mstate->__pyx_memoryview_type->tp_base->tp_as_buffer->bf_releasebuffer) { + __pyx_mstate->__pyx_memoryview_type->tp_as_buffer->bf_releasebuffer = __pyx_mstate->__pyx_memoryview_type->tp_base->tp_as_buffer->bf_releasebuffer; + } + #elif defined(Py_bf_getbuffer) && defined(Py_bf_releasebuffer) + /* PY_VERSION_HEX >= 0x03090000 || Py_LIMITED_API >= 0x030B0000 */ + #elif defined(_MSC_VER) + #pragma message ("The buffer protocol is not supported in the Limited C-API < 3.11.") + #else + #warning "The buffer protocol is not supported in the Limited C-API < 3.11." + #endif + if (__Pyx_fix_up_extension_type_from_spec(&__pyx_type___pyx_memoryview_spec, __pyx_mstate->__pyx_memoryview_type) < (0)) __PYX_ERR(1, 342, __pyx_L1_error) + #else + __pyx_mstate->__pyx_memoryview_type = &__pyx_type___pyx_memoryview; + #endif + #if !CYTHON_COMPILING_IN_LIMITED_API + #endif + #if !CYTHON_USE_TYPE_SPECS + if (__Pyx_PyType_Ready(__pyx_mstate->__pyx_memoryview_type) < (0)) __PYX_ERR(1, 342, __pyx_L1_error) + #endif + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000 + PyUnstable_Object_EnableDeferredRefcount((PyObject*)__pyx_mstate->__pyx_memoryview_type); + #endif + #if !CYTHON_COMPILING_IN_LIMITED_API + if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_mstate->__pyx_memoryview_type->tp_dictoffset && __pyx_mstate->__pyx_memoryview_type->tp_getattro == PyObject_GenericGetAttr)) { + __pyx_mstate->__pyx_memoryview_type->tp_getattro = PyObject_GenericGetAttr; + } + #endif + if (__Pyx_SetVtable(__pyx_mstate->__pyx_memoryview_type, __pyx_vtabptr_memoryview) < (0)) __PYX_ERR(1, 342, __pyx_L1_error) + if (__Pyx_MergeVtables(__pyx_mstate->__pyx_memoryview_type) < (0)) __PYX_ERR(1, 342, __pyx_L1_error) + if (__Pyx_setup_reduce((PyObject *) __pyx_mstate->__pyx_memoryview_type) < (0)) __PYX_ERR(1, 342, __pyx_L1_error) + __pyx_vtabptr__memoryviewslice = &__pyx_vtable__memoryviewslice; + __pyx_vtable__memoryviewslice.__pyx_base = *__pyx_vtabptr_memoryview; + __pyx_vtable__memoryviewslice.__pyx_base.convert_item_to_object = (PyObject *(*)(struct __pyx_memoryview_obj *, char *))__pyx_memoryviewslice_convert_item_to_object; + __pyx_vtable__memoryviewslice.__pyx_base.assign_item_from_object = (PyObject *(*)(struct __pyx_memoryview_obj *, char *, PyObject *))__pyx_memoryviewslice_assign_item_from_object; + __pyx_vtable__memoryviewslice.__pyx_base._get_base = (PyObject *(*)(struct __pyx_memoryview_obj *))__pyx_memoryviewslice__get_base; + #if CYTHON_USE_TYPE_SPECS + __pyx_t_1 = PyTuple_Pack(1, (PyObject *)__pyx_mstate_global->__pyx_memoryview_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 856, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_mstate->__pyx_memoryviewslice_type = (PyTypeObject *) __Pyx_PyType_FromModuleAndSpec(__pyx_m, &__pyx_type___pyx_memoryviewslice_spec, __pyx_t_1); + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + if (unlikely(!__pyx_mstate->__pyx_memoryviewslice_type)) __PYX_ERR(1, 856, __pyx_L1_error) + if (__Pyx_fix_up_extension_type_from_spec(&__pyx_type___pyx_memoryviewslice_spec, __pyx_mstate->__pyx_memoryviewslice_type) < (0)) __PYX_ERR(1, 856, __pyx_L1_error) + #else + __pyx_mstate->__pyx_memoryviewslice_type = &__pyx_type___pyx_memoryviewslice; + #endif + #if !CYTHON_COMPILING_IN_LIMITED_API + __pyx_mstate_global->__pyx_memoryviewslice_type->tp_base = __pyx_mstate_global->__pyx_memoryview_type; + #endif + #if !CYTHON_USE_TYPE_SPECS + if (__Pyx_PyType_Ready(__pyx_mstate->__pyx_memoryviewslice_type) < (0)) __PYX_ERR(1, 856, __pyx_L1_error) + #endif + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000 + PyUnstable_Object_EnableDeferredRefcount((PyObject*)__pyx_mstate->__pyx_memoryviewslice_type); + #endif + #if !CYTHON_COMPILING_IN_LIMITED_API + if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_mstate->__pyx_memoryviewslice_type->tp_dictoffset && __pyx_mstate->__pyx_memoryviewslice_type->tp_getattro == PyObject_GenericGetAttr)) { + __pyx_mstate->__pyx_memoryviewslice_type->tp_getattro = PyObject_GenericGetAttr; + } + #endif + if (__Pyx_SetVtable(__pyx_mstate->__pyx_memoryviewslice_type, __pyx_vtabptr__memoryviewslice) < (0)) __PYX_ERR(1, 856, __pyx_L1_error) + if (__Pyx_MergeVtables(__pyx_mstate->__pyx_memoryviewslice_type) < (0)) __PYX_ERR(1, 856, __pyx_L1_error) + if (__Pyx_setup_reduce((PyObject *) __pyx_mstate->__pyx_memoryviewslice_type) < (0)) __PYX_ERR(1, 856, __pyx_L1_error) + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_RefNannyFinishContext(); + return -1; +} + +static int __Pyx_modinit_type_import_code(__pyx_mstatetype *__pyx_mstate) { + __Pyx_RefNannyDeclarations + CYTHON_UNUSED_VAR(__pyx_mstate); + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__Pyx_modinit_type_import_code", 0); + /*--- Type import code ---*/ + __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(3, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_mstate->__pyx_ptype_7cpython_4type_type = __Pyx_ImportType_3_2_5(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "type", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyTypeObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyTypeObject), + #elif CYTHON_COMPILING_IN_LIMITED_API + 0, 0, + #else + sizeof(PyHeapTypeObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyHeapTypeObject), + #endif + __Pyx_ImportType_CheckSize_Warn_3_2_5); if (!__pyx_mstate->__pyx_ptype_7cpython_4type_type) __PYX_ERR(3, 9, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyImport_ImportModule("numpy"); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 229, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_mstate->__pyx_ptype_5numpy_dtype = __Pyx_ImportType_3_2_5(__pyx_t_1, "numpy", "dtype", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyArray_Descr), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyArray_Descr), + #elif CYTHON_COMPILING_IN_LIMITED_API + sizeof(PyArray_Descr), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyArray_Descr), + #else + sizeof(PyArray_Descr), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyArray_Descr), + #endif + __Pyx_ImportType_CheckSize_Ignore_3_2_5); if (!__pyx_mstate->__pyx_ptype_5numpy_dtype) __PYX_ERR(2, 229, __pyx_L1_error) + __pyx_mstate->__pyx_ptype_5numpy_flatiter = __Pyx_ImportType_3_2_5(__pyx_t_1, "numpy", "flatiter", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyArrayIterObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyArrayIterObject), + #elif CYTHON_COMPILING_IN_LIMITED_API + sizeof(PyArrayIterObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyArrayIterObject), + #else + sizeof(PyArrayIterObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyArrayIterObject), + #endif + __Pyx_ImportType_CheckSize_Ignore_3_2_5); if (!__pyx_mstate->__pyx_ptype_5numpy_flatiter) __PYX_ERR(2, 274, __pyx_L1_error) + __pyx_mstate->__pyx_ptype_5numpy_broadcast = __Pyx_ImportType_3_2_5(__pyx_t_1, "numpy", "broadcast", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyArrayMultiIterObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyArrayMultiIterObject), + #elif CYTHON_COMPILING_IN_LIMITED_API + sizeof(PyArrayMultiIterObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyArrayMultiIterObject), + #else + sizeof(PyArrayMultiIterObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyArrayMultiIterObject), + #endif + __Pyx_ImportType_CheckSize_Ignore_3_2_5); if (!__pyx_mstate->__pyx_ptype_5numpy_broadcast) __PYX_ERR(2, 278, __pyx_L1_error) + __pyx_mstate->__pyx_ptype_5numpy_ndarray = __Pyx_ImportType_3_2_5(__pyx_t_1, "numpy", "ndarray", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyArrayObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyArrayObject), + #elif CYTHON_COMPILING_IN_LIMITED_API + sizeof(PyArrayObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyArrayObject), + #else + sizeof(PyArrayObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyArrayObject), + #endif + __Pyx_ImportType_CheckSize_Ignore_3_2_5); if (!__pyx_mstate->__pyx_ptype_5numpy_ndarray) __PYX_ERR(2, 317, __pyx_L1_error) + __pyx_mstate->__pyx_ptype_5numpy_generic = __Pyx_ImportType_3_2_5(__pyx_t_1, "numpy", "generic", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #elif CYTHON_COMPILING_IN_LIMITED_API + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #else + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #endif + __Pyx_ImportType_CheckSize_Warn_3_2_5); if (!__pyx_mstate->__pyx_ptype_5numpy_generic) __PYX_ERR(2, 826, __pyx_L1_error) + __pyx_mstate->__pyx_ptype_5numpy_number = __Pyx_ImportType_3_2_5(__pyx_t_1, "numpy", "number", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #elif CYTHON_COMPILING_IN_LIMITED_API + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #else + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #endif + __Pyx_ImportType_CheckSize_Warn_3_2_5); if (!__pyx_mstate->__pyx_ptype_5numpy_number) __PYX_ERR(2, 828, __pyx_L1_error) + __pyx_mstate->__pyx_ptype_5numpy_integer = __Pyx_ImportType_3_2_5(__pyx_t_1, "numpy", "integer", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #elif CYTHON_COMPILING_IN_LIMITED_API + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #else + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #endif + __Pyx_ImportType_CheckSize_Warn_3_2_5); if (!__pyx_mstate->__pyx_ptype_5numpy_integer) __PYX_ERR(2, 830, __pyx_L1_error) + __pyx_mstate->__pyx_ptype_5numpy_signedinteger = __Pyx_ImportType_3_2_5(__pyx_t_1, "numpy", "signedinteger", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #elif CYTHON_COMPILING_IN_LIMITED_API + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #else + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #endif + __Pyx_ImportType_CheckSize_Warn_3_2_5); if (!__pyx_mstate->__pyx_ptype_5numpy_signedinteger) __PYX_ERR(2, 832, __pyx_L1_error) + __pyx_mstate->__pyx_ptype_5numpy_unsignedinteger = __Pyx_ImportType_3_2_5(__pyx_t_1, "numpy", "unsignedinteger", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #elif CYTHON_COMPILING_IN_LIMITED_API + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #else + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #endif + __Pyx_ImportType_CheckSize_Warn_3_2_5); if (!__pyx_mstate->__pyx_ptype_5numpy_unsignedinteger) __PYX_ERR(2, 834, __pyx_L1_error) + __pyx_mstate->__pyx_ptype_5numpy_inexact = __Pyx_ImportType_3_2_5(__pyx_t_1, "numpy", "inexact", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #elif CYTHON_COMPILING_IN_LIMITED_API + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #else + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #endif + __Pyx_ImportType_CheckSize_Warn_3_2_5); if (!__pyx_mstate->__pyx_ptype_5numpy_inexact) __PYX_ERR(2, 836, __pyx_L1_error) + __pyx_mstate->__pyx_ptype_5numpy_floating = __Pyx_ImportType_3_2_5(__pyx_t_1, "numpy", "floating", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #elif CYTHON_COMPILING_IN_LIMITED_API + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #else + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #endif + __Pyx_ImportType_CheckSize_Warn_3_2_5); if (!__pyx_mstate->__pyx_ptype_5numpy_floating) __PYX_ERR(2, 838, __pyx_L1_error) + __pyx_mstate->__pyx_ptype_5numpy_complexfloating = __Pyx_ImportType_3_2_5(__pyx_t_1, "numpy", "complexfloating", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #elif CYTHON_COMPILING_IN_LIMITED_API + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #else + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #endif + __Pyx_ImportType_CheckSize_Warn_3_2_5); if (!__pyx_mstate->__pyx_ptype_5numpy_complexfloating) __PYX_ERR(2, 840, __pyx_L1_error) + __pyx_mstate->__pyx_ptype_5numpy_flexible = __Pyx_ImportType_3_2_5(__pyx_t_1, "numpy", "flexible", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #elif CYTHON_COMPILING_IN_LIMITED_API + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #else + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #endif + __Pyx_ImportType_CheckSize_Warn_3_2_5); if (!__pyx_mstate->__pyx_ptype_5numpy_flexible) __PYX_ERR(2, 842, __pyx_L1_error) + __pyx_mstate->__pyx_ptype_5numpy_character = __Pyx_ImportType_3_2_5(__pyx_t_1, "numpy", "character", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #elif CYTHON_COMPILING_IN_LIMITED_API + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #else + sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyObject), + #endif + __Pyx_ImportType_CheckSize_Warn_3_2_5); if (!__pyx_mstate->__pyx_ptype_5numpy_character) __PYX_ERR(2, 844, __pyx_L1_error) + __pyx_mstate->__pyx_ptype_5numpy_ufunc = __Pyx_ImportType_3_2_5(__pyx_t_1, "numpy", "ufunc", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyUFuncObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyUFuncObject), + #elif CYTHON_COMPILING_IN_LIMITED_API + sizeof(PyUFuncObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyUFuncObject), + #else + sizeof(PyUFuncObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_5(PyUFuncObject), + #endif + __Pyx_ImportType_CheckSize_Ignore_3_2_5); if (!__pyx_mstate->__pyx_ptype_5numpy_ufunc) __PYX_ERR(2, 908, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_RefNannyFinishContext(); + return -1; +} + +static int __Pyx_modinit_variable_import_code(__pyx_mstatetype *__pyx_mstate) { + __Pyx_RefNannyDeclarations + CYTHON_UNUSED_VAR(__pyx_mstate); + __Pyx_RefNannySetupContext("__Pyx_modinit_variable_import_code", 0); + /*--- Variable import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_function_import_code(__pyx_mstatetype *__pyx_mstate) { + __Pyx_RefNannyDeclarations + CYTHON_UNUSED_VAR(__pyx_mstate); + __Pyx_RefNannySetupContext("__Pyx_modinit_function_import_code", 0); + /*--- Function import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +#if CYTHON_PEP489_MULTI_PHASE_INIT +static PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def); /*proto*/ +static int __pyx_pymod_exec_core(PyObject* module); /*proto*/ +static PyModuleDef_Slot __pyx_moduledef_slots[] = { + {Py_mod_create, (void*)__pyx_pymod_create}, + {Py_mod_exec, (void*)__pyx_pymod_exec_core}, + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + {Py_mod_gil, __Pyx_FREETHREADING_COMPATIBLE}, + #endif + #if PY_VERSION_HEX >= 0x030C0000 && CYTHON_USE_MODULE_STATE + {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED}, + #endif + {0, NULL} +}; +#endif + +#ifdef __cplusplus +namespace { + struct PyModuleDef __pyx_moduledef = + #else + static struct PyModuleDef __pyx_moduledef = + #endif + { + PyModuleDef_HEAD_INIT, + "core", + 0, /* m_doc */ + #if CYTHON_USE_MODULE_STATE + sizeof(__pyx_mstatetype), /* m_size */ + #else + (CYTHON_PEP489_MULTI_PHASE_INIT) ? 0 : -1, /* m_size */ + #endif + __pyx_methods /* m_methods */, + #if CYTHON_PEP489_MULTI_PHASE_INIT + __pyx_moduledef_slots, /* m_slots */ + #else + NULL, /* m_reload */ + #endif + #if CYTHON_USE_MODULE_STATE + __pyx_m_traverse, /* m_traverse */ + __pyx_m_clear, /* m_clear */ + NULL /* m_free */ + #else + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL /* m_free */ + #endif + }; + #ifdef __cplusplus +} /* anonymous namespace */ +#endif + +/* PyModInitFuncType */ +#ifndef CYTHON_NO_PYINIT_EXPORT + #define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC +#else + #ifdef __cplusplus + #define __Pyx_PyMODINIT_FUNC extern "C" PyObject * + #else + #define __Pyx_PyMODINIT_FUNC PyObject * + #endif +#endif + +__Pyx_PyMODINIT_FUNC PyInit_core(void) CYTHON_SMALL_CODE; /*proto*/ +__Pyx_PyMODINIT_FUNC PyInit_core(void) +#if CYTHON_PEP489_MULTI_PHASE_INIT +{ + return PyModuleDef_Init(&__pyx_moduledef); +} +/* ModuleCreationPEP489 */ +#if CYTHON_COMPILING_IN_LIMITED_API && (__PYX_LIMITED_VERSION_HEX < 0x03090000\ + || ((defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS)) && __PYX_LIMITED_VERSION_HEX < 0x030A0000)) +static PY_INT64_T __Pyx_GetCurrentInterpreterId(void) { + { + PyObject *module = PyImport_ImportModule("_interpreters"); // 3.13+ I think + if (!module) { + PyErr_Clear(); // just try the 3.8-3.12 version + module = PyImport_ImportModule("_xxsubinterpreters"); + if (!module) goto bad; + } + PyObject *current = PyObject_CallMethod(module, "get_current", NULL); + Py_DECREF(module); + if (!current) goto bad; + if (PyTuple_Check(current)) { + PyObject *new_current = PySequence_GetItem(current, 0); + Py_DECREF(current); + current = new_current; + if (!new_current) goto bad; + } + long long as_c_int = PyLong_AsLongLong(current); + Py_DECREF(current); + return as_c_int; + } + bad: + PySys_WriteStderr("__Pyx_GetCurrentInterpreterId failed. Try setting the C define CYTHON_PEP489_MULTI_PHASE_INIT=0\n"); + return -1; +} +#endif +#if !CYTHON_USE_MODULE_STATE +static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) { + static PY_INT64_T main_interpreter_id = -1; +#if CYTHON_COMPILING_IN_GRAAL && defined(GRAALPY_VERSION_NUM) && GRAALPY_VERSION_NUM > 0x19000000 + PY_INT64_T current_id = GraalPyInterpreterState_GetIDFromThreadState(PyThreadState_Get()); +#elif CYTHON_COMPILING_IN_GRAAL + PY_INT64_T current_id = PyInterpreterState_GetIDFromThreadState(PyThreadState_Get()); +#elif CYTHON_COMPILING_IN_LIMITED_API && (__PYX_LIMITED_VERSION_HEX < 0x03090000\ + || ((defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS)) && __PYX_LIMITED_VERSION_HEX < 0x030A0000)) + PY_INT64_T current_id = __Pyx_GetCurrentInterpreterId(); +#elif CYTHON_COMPILING_IN_LIMITED_API + PY_INT64_T current_id = PyInterpreterState_GetID(PyInterpreterState_Get()); +#else + PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp); +#endif + if (unlikely(current_id == -1)) { + return -1; + } + if (main_interpreter_id == -1) { + main_interpreter_id = current_id; + return 0; + } else if (unlikely(main_interpreter_id != current_id)) { + PyErr_SetString( + PyExc_ImportError, + "Interpreter change detected - this module can only be loaded into one interpreter per process."); + return -1; + } + return 0; +} +#endif +static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name, int allow_none) +{ + PyObject *value = PyObject_GetAttrString(spec, from_name); + int result = 0; + if (likely(value)) { + if (allow_none || value != Py_None) { + result = PyDict_SetItemString(moddict, to_name, value); + } + Py_DECREF(value); + } else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + } else { + result = -1; + } + return result; +} +static CYTHON_SMALL_CODE PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def) { + PyObject *module = NULL, *moddict, *modname; + CYTHON_UNUSED_VAR(def); + #if !CYTHON_USE_MODULE_STATE + if (__Pyx_check_single_interpreter()) + return NULL; + #endif + if (__pyx_m) + return __Pyx_NewRef(__pyx_m); + modname = PyObject_GetAttrString(spec, "name"); + if (unlikely(!modname)) goto bad; + module = PyModule_NewObject(modname); + Py_DECREF(modname); + if (unlikely(!module)) goto bad; + moddict = PyModule_GetDict(module); + if (unlikely(!moddict)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "parent", "__package__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "submodule_search_locations", "__path__", 0) < 0)) goto bad; + return module; +bad: + Py_XDECREF(module); + return NULL; +} + + +static CYTHON_SMALL_CODE int __pyx_pymod_exec_core(PyObject *__pyx_pyinit_module) +#endif +{ + int stringtab_initialized = 0; + #if CYTHON_USE_MODULE_STATE + int pystate_addmodule_run = 0; + #endif + __pyx_mstatetype *__pyx_mstate = NULL; + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + size_t __pyx_t_6; + static PyThread_type_lock __pyx_t_7[8]; + int __pyx_t_8; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannyDeclarations + #if CYTHON_PEP489_MULTI_PHASE_INIT + if (__pyx_m) { + if (__pyx_m == __pyx_pyinit_module) return 0; + PyErr_SetString(PyExc_RuntimeError, "Module 'core' has already been imported. Re-initialisation is not supported."); + return -1; + } + #else + if (__pyx_m) return __Pyx_NewRef(__pyx_m); + #endif + /*--- Module creation code ---*/ + #if CYTHON_PEP489_MULTI_PHASE_INIT + __pyx_t_1 = __pyx_pyinit_module; + Py_INCREF(__pyx_t_1); + #else + __pyx_t_1 = PyModule_Create(&__pyx_moduledef); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #if CYTHON_USE_MODULE_STATE + { + int add_module_result = __Pyx_State_AddModule(__pyx_t_1, &__pyx_moduledef); + __pyx_t_1 = 0; /* transfer ownership from __pyx_t_1 to "core" pseudovariable */ + if (unlikely((add_module_result < 0))) __PYX_ERR(0, 1, __pyx_L1_error) + pystate_addmodule_run = 1; + } + #else + __pyx_m = __pyx_t_1; + #endif + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + PyUnstable_Module_SetGIL(__pyx_m, Py_MOD_GIL_USED); + #endif + __pyx_mstate = __pyx_mstate_global; + CYTHON_UNUSED_VAR(__pyx_t_1); + __pyx_mstate->__pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_mstate->__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_mstate->__pyx_d); + __pyx_mstate->__pyx_b = __Pyx_PyImport_AddModuleRef(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_mstate->__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_mstate->__pyx_cython_runtime = __Pyx_PyImport_AddModuleRef("cython_runtime"); if (unlikely(!__pyx_mstate->__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error) + if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_mstate->__pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error) + /* ImportRefnannyAPI */ + #if CYTHON_REFNANNY + __Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); + if (!__Pyx_RefNanny) { + PyErr_Clear(); + __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); + if (!__Pyx_RefNanny) + Py_FatalError("failed to import 'refnanny' module"); + } + #endif + +__Pyx_RefNannySetupContext("PyInit_core", 0); + __Pyx_init_runtime_version(); + if (__Pyx_check_binary_version(__PYX_LIMITED_VERSION_HEX, __Pyx_get_runtime_version(), CYTHON_COMPILING_IN_LIMITED_API) < (0)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_mstate->__pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_mstate->__pyx_empty_tuple)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_mstate->__pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_mstate->__pyx_empty_bytes)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_mstate->__pyx_empty_unicode = PyUnicode_FromStringAndSize("", 0); if (unlikely(!__pyx_mstate->__pyx_empty_unicode)) __PYX_ERR(0, 1, __pyx_L1_error) + /*--- Library function declarations ---*/ + /*--- Initialize various global constants etc. ---*/ + if (__Pyx_InitConstants(__pyx_mstate) < (0)) __PYX_ERR(0, 1, __pyx_L1_error) + stringtab_initialized = 1; + if (__Pyx_InitGlobals() < (0)) __PYX_ERR(0, 1, __pyx_L1_error) + if (__pyx_module_is_main_matcha__utils__monotonic_align__core) { + if (PyObject_SetAttr(__pyx_m, __pyx_mstate_global->__pyx_n_u_name_2, __pyx_mstate_global->__pyx_n_u_main) < (0)) __PYX_ERR(0, 1, __pyx_L1_error) + } + { + PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) __PYX_ERR(0, 1, __pyx_L1_error) + if (!PyDict_GetItemString(modules, "matcha.utils.monotonic_align.core")) { + if (unlikely((PyDict_SetItemString(modules, "matcha.utils.monotonic_align.core", __pyx_m) < 0))) __PYX_ERR(0, 1, __pyx_L1_error) + } + } + /*--- Builtin init code ---*/ + if (__Pyx_InitCachedBuiltins(__pyx_mstate) < (0)) __PYX_ERR(0, 1, __pyx_L1_error) + /*--- Constants init code ---*/ + if (__Pyx_InitCachedConstants(__pyx_mstate) < (0)) __PYX_ERR(0, 1, __pyx_L1_error) + if (__Pyx_CreateCodeObjects(__pyx_mstate) < (0)) __PYX_ERR(0, 1, __pyx_L1_error) + /*--- Global type/function init code ---*/ + (void)__Pyx_modinit_global_init_code(__pyx_mstate); + (void)__Pyx_modinit_variable_export_code(__pyx_mstate); + (void)__Pyx_modinit_function_export_code(__pyx_mstate); + if (unlikely((__Pyx_modinit_type_init_code(__pyx_mstate) < 0))) __PYX_ERR(0, 1, __pyx_L1_error) + if (unlikely((__Pyx_modinit_type_import_code(__pyx_mstate) < 0))) __PYX_ERR(0, 1, __pyx_L1_error) + (void)__Pyx_modinit_variable_import_code(__pyx_mstate); + (void)__Pyx_modinit_function_import_code(__pyx_mstate); + /*--- Execution code ---*/ + + /* "View.MemoryView":108 + * + * cdef object __pyx_collections_abc_Sequence "__pyx_collections_abc_Sequence" + * try: # <<<<<<<<<<<<<< + * __pyx_collections_abc_Sequence = __import__("collections.abc").abc.Sequence + * except: +*/ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_1); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + /*try:*/ { + + /* "View.MemoryView":109 + * cdef object __pyx_collections_abc_Sequence "__pyx_collections_abc_Sequence" + * try: + * __pyx_collections_abc_Sequence = __import__("collections.abc").abc.Sequence # <<<<<<<<<<<<<< + * except: + * +*/ + __pyx_t_5 = NULL; + __pyx_t_6 = 1; + { + PyObject *__pyx_callargs[2] = {__pyx_t_5, __pyx_mstate_global->__pyx_kp_u_collections_abc}; + __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_builtin___import__, __pyx_callargs+__pyx_t_6, (2-__pyx_t_6) | (__pyx_t_6*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 109, __pyx_L2_error) + __Pyx_GOTREF(__pyx_t_4); + } + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_abc); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 109, __pyx_L2_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_mstate_global->__pyx_n_u_Sequence); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 109, __pyx_L2_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XGOTREF(__pyx_collections_abc_Sequence); + __Pyx_DECREF_SET(__pyx_collections_abc_Sequence, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_4); + __pyx_t_4 = 0; + + /* "View.MemoryView":108 + * + * cdef object __pyx_collections_abc_Sequence "__pyx_collections_abc_Sequence" + * try: # <<<<<<<<<<<<<< + * __pyx_collections_abc_Sequence = __import__("collections.abc").abc.Sequence + * except: +*/ + } + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + goto __pyx_L7_try_end; + __pyx_L2_error:; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + + /* "View.MemoryView":110 + * try: + * __pyx_collections_abc_Sequence = __import__("collections.abc").abc.Sequence + * except: # <<<<<<<<<<<<<< + * + * __pyx_collections_abc_Sequence = None +*/ + /*except:*/ { + __Pyx_ErrRestore(0,0,0); + + /* "View.MemoryView":112 + * except: + * + * __pyx_collections_abc_Sequence = None # <<<<<<<<<<<<<< + * + * +*/ + __Pyx_INCREF(Py_None); + __Pyx_XGOTREF(__pyx_collections_abc_Sequence); + __Pyx_DECREF_SET(__pyx_collections_abc_Sequence, Py_None); + __Pyx_GIVEREF(Py_None); + goto __pyx_L3_exception_handled; + } + __pyx_L3_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_1); + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); + __pyx_L7_try_end:; + } + + /* "View.MemoryView":247 + * + * + * try: # <<<<<<<<<<<<<< + * count = __pyx_collections_abc_Sequence.count + * index = __pyx_collections_abc_Sequence.index +*/ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_3, &__pyx_t_2, &__pyx_t_1); + __Pyx_XGOTREF(__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_1); + /*try:*/ { + + /* "View.MemoryView":248 + * + * try: + * count = __pyx_collections_abc_Sequence.count # <<<<<<<<<<<<<< + * index = __pyx_collections_abc_Sequence.index + * except: +*/ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_collections_abc_Sequence, __pyx_mstate_global->__pyx_n_u_count); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 248, __pyx_L10_error) + __Pyx_GOTREF(__pyx_t_4); + if (__Pyx_SetItemOnTypeDict(__pyx_mstate_global->__pyx_array_type, __pyx_mstate_global->__pyx_n_u_count, __pyx_t_4) < (0)) __PYX_ERR(1, 248, __pyx_L10_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "View.MemoryView":249 + * try: + * count = __pyx_collections_abc_Sequence.count + * index = __pyx_collections_abc_Sequence.index # <<<<<<<<<<<<<< + * except: + * pass +*/ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_collections_abc_Sequence, __pyx_mstate_global->__pyx_n_u_index); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 249, __pyx_L10_error) + __Pyx_GOTREF(__pyx_t_4); + if (__Pyx_SetItemOnTypeDict(__pyx_mstate_global->__pyx_array_type, __pyx_mstate_global->__pyx_n_u_index, __pyx_t_4) < (0)) __PYX_ERR(1, 249, __pyx_L10_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "View.MemoryView":247 + * + * + * try: # <<<<<<<<<<<<<< + * count = __pyx_collections_abc_Sequence.count + * index = __pyx_collections_abc_Sequence.index +*/ + } + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + goto __pyx_L15_try_end; + __pyx_L10_error:; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + + /* "View.MemoryView":250 + * count = __pyx_collections_abc_Sequence.count + * index = __pyx_collections_abc_Sequence.index + * except: # <<<<<<<<<<<<<< + * pass + * +*/ + /*except:*/ { + __Pyx_ErrRestore(0,0,0); + goto __pyx_L11_exception_handled; + } + __pyx_L11_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_1); + __Pyx_ExceptionReset(__pyx_t_3, __pyx_t_2, __pyx_t_1); + __pyx_L15_try_end:; + } + + /* "View.MemoryView":315 + * return self.name + * + * cdef generic = Enum("") # <<<<<<<<<<<<<< + * cdef strided = Enum("") # default + * cdef indirect = Enum("") +*/ + __pyx_t_5 = NULL; + __pyx_t_6 = 1; + { + PyObject *__pyx_callargs[2] = {__pyx_t_5, __pyx_mstate_global->__pyx_kp_u_strided_and_direct_or_indirect}; + __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_mstate_global->__pyx_MemviewEnum_type, __pyx_callargs+__pyx_t_6, (2-__pyx_t_6) | (__pyx_t_6*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 315, __pyx_L1_error) + __Pyx_GOTREF((PyObject *)__pyx_t_4); + } + __Pyx_XGOTREF(generic); + __Pyx_DECREF_SET(generic, ((PyObject *)__pyx_t_4)); + __Pyx_GIVEREF((PyObject *)__pyx_t_4); + __pyx_t_4 = 0; + + /* "View.MemoryView":316 + * + * cdef generic = Enum("") + * cdef strided = Enum("") # default # <<<<<<<<<<<<<< + * cdef indirect = Enum("") + * +*/ + __pyx_t_5 = NULL; + __pyx_t_6 = 1; + { + PyObject *__pyx_callargs[2] = {__pyx_t_5, __pyx_mstate_global->__pyx_kp_u_strided_and_direct}; + __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_mstate_global->__pyx_MemviewEnum_type, __pyx_callargs+__pyx_t_6, (2-__pyx_t_6) | (__pyx_t_6*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 316, __pyx_L1_error) + __Pyx_GOTREF((PyObject *)__pyx_t_4); + } + __Pyx_XGOTREF(strided); + __Pyx_DECREF_SET(strided, ((PyObject *)__pyx_t_4)); + __Pyx_GIVEREF((PyObject *)__pyx_t_4); + __pyx_t_4 = 0; + + /* "View.MemoryView":317 + * cdef generic = Enum("") + * cdef strided = Enum("") # default + * cdef indirect = Enum("") # <<<<<<<<<<<<<< + * + * +*/ + __pyx_t_5 = NULL; + __pyx_t_6 = 1; + { + PyObject *__pyx_callargs[2] = {__pyx_t_5, __pyx_mstate_global->__pyx_kp_u_strided_and_indirect}; + __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_mstate_global->__pyx_MemviewEnum_type, __pyx_callargs+__pyx_t_6, (2-__pyx_t_6) | (__pyx_t_6*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 317, __pyx_L1_error) + __Pyx_GOTREF((PyObject *)__pyx_t_4); + } + __Pyx_XGOTREF(indirect); + __Pyx_DECREF_SET(indirect, ((PyObject *)__pyx_t_4)); + __Pyx_GIVEREF((PyObject *)__pyx_t_4); + __pyx_t_4 = 0; + + /* "View.MemoryView":320 + * + * + * cdef contiguous = Enum("") # <<<<<<<<<<<<<< + * cdef indirect_contiguous = Enum("") + * +*/ + __pyx_t_5 = NULL; + __pyx_t_6 = 1; + { + PyObject *__pyx_callargs[2] = {__pyx_t_5, __pyx_mstate_global->__pyx_kp_u_contiguous_and_direct}; + __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_mstate_global->__pyx_MemviewEnum_type, __pyx_callargs+__pyx_t_6, (2-__pyx_t_6) | (__pyx_t_6*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 320, __pyx_L1_error) + __Pyx_GOTREF((PyObject *)__pyx_t_4); + } + __Pyx_XGOTREF(contiguous); + __Pyx_DECREF_SET(contiguous, ((PyObject *)__pyx_t_4)); + __Pyx_GIVEREF((PyObject *)__pyx_t_4); + __pyx_t_4 = 0; + + /* "View.MemoryView":321 + * + * cdef contiguous = Enum("") + * cdef indirect_contiguous = Enum("") # <<<<<<<<<<<<<< + * + * +*/ + __pyx_t_5 = NULL; + __pyx_t_6 = 1; + { + PyObject *__pyx_callargs[2] = {__pyx_t_5, __pyx_mstate_global->__pyx_kp_u_contiguous_and_indirect}; + __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_mstate_global->__pyx_MemviewEnum_type, __pyx_callargs+__pyx_t_6, (2-__pyx_t_6) | (__pyx_t_6*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 321, __pyx_L1_error) + __Pyx_GOTREF((PyObject *)__pyx_t_4); + } + __Pyx_XGOTREF(indirect_contiguous); + __Pyx_DECREF_SET(indirect_contiguous, ((PyObject *)__pyx_t_4)); + __Pyx_GIVEREF((PyObject *)__pyx_t_4); + __pyx_t_4 = 0; + + /* "View.MemoryView":329 + * + * + * cdef int __pyx_memoryview_thread_locks_used = 0 # <<<<<<<<<<<<<< + * cdef PyThread_type_lock[8] __pyx_memoryview_thread_locks = [ + * PyThread_allocate_lock(), +*/ + __pyx_memoryview_thread_locks_used = 0; + + /* "View.MemoryView":330 + * + * cdef int __pyx_memoryview_thread_locks_used = 0 + * cdef PyThread_type_lock[8] __pyx_memoryview_thread_locks = [ # <<<<<<<<<<<<<< + * PyThread_allocate_lock(), + * PyThread_allocate_lock(), +*/ + __pyx_t_7[0] = PyThread_allocate_lock(); + __pyx_t_7[1] = PyThread_allocate_lock(); + __pyx_t_7[2] = PyThread_allocate_lock(); + __pyx_t_7[3] = PyThread_allocate_lock(); + __pyx_t_7[4] = PyThread_allocate_lock(); + __pyx_t_7[5] = PyThread_allocate_lock(); + __pyx_t_7[6] = PyThread_allocate_lock(); + __pyx_t_7[7] = PyThread_allocate_lock(); + memcpy(&(__pyx_memoryview_thread_locks[0]), __pyx_t_7, sizeof(__pyx_memoryview_thread_locks[0]) * (8)); + + /* "View.MemoryView":888 + * + * + * try: # <<<<<<<<<<<<<< + * count = __pyx_collections_abc_Sequence.count + * index = __pyx_collections_abc_Sequence.index +*/ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_1); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + /*try:*/ { + + /* "View.MemoryView":889 + * + * try: + * count = __pyx_collections_abc_Sequence.count # <<<<<<<<<<<<<< + * index = __pyx_collections_abc_Sequence.index + * except: +*/ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_collections_abc_Sequence, __pyx_mstate_global->__pyx_n_u_count); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 889, __pyx_L18_error) + __Pyx_GOTREF(__pyx_t_4); + if (__Pyx_SetItemOnTypeDict(__pyx_mstate_global->__pyx_memoryviewslice_type, __pyx_mstate_global->__pyx_n_u_count, __pyx_t_4) < (0)) __PYX_ERR(1, 889, __pyx_L18_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "View.MemoryView":890 + * try: + * count = __pyx_collections_abc_Sequence.count + * index = __pyx_collections_abc_Sequence.index # <<<<<<<<<<<<<< + * except: + * pass +*/ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_collections_abc_Sequence, __pyx_mstate_global->__pyx_n_u_index); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 890, __pyx_L18_error) + __Pyx_GOTREF(__pyx_t_4); + if (__Pyx_SetItemOnTypeDict(__pyx_mstate_global->__pyx_memoryviewslice_type, __pyx_mstate_global->__pyx_n_u_index, __pyx_t_4) < (0)) __PYX_ERR(1, 890, __pyx_L18_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "View.MemoryView":888 + * + * + * try: # <<<<<<<<<<<<<< + * count = __pyx_collections_abc_Sequence.count + * index = __pyx_collections_abc_Sequence.index +*/ + } + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + goto __pyx_L23_try_end; + __pyx_L18_error:; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + + /* "View.MemoryView":891 + * count = __pyx_collections_abc_Sequence.count + * index = __pyx_collections_abc_Sequence.index + * except: # <<<<<<<<<<<<<< + * pass + * +*/ + /*except:*/ { + __Pyx_ErrRestore(0,0,0); + goto __pyx_L19_exception_handled; + } + __pyx_L19_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_1); + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); + __pyx_L23_try_end:; + } + + /* "View.MemoryView":894 + * pass + * + * try: # <<<<<<<<<<<<<< + * if __pyx_collections_abc_Sequence: + * +*/ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_3, &__pyx_t_2, &__pyx_t_1); + __Pyx_XGOTREF(__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_1); + /*try:*/ { + + /* "View.MemoryView":895 + * + * try: + * if __pyx_collections_abc_Sequence: # <<<<<<<<<<<<<< + * + * +*/ + __pyx_t_8 = __Pyx_PyObject_IsTrue(__pyx_collections_abc_Sequence); if (unlikely((__pyx_t_8 < 0))) __PYX_ERR(1, 895, __pyx_L26_error) + if (__pyx_t_8) { + + /* "View.MemoryView":899 + * + * + * __pyx_collections_abc_Sequence.register(_memoryviewslice) # <<<<<<<<<<<<<< + * __pyx_collections_abc_Sequence.register(array) + * except: +*/ + __pyx_t_5 = __pyx_collections_abc_Sequence; + __Pyx_INCREF(__pyx_t_5); + __pyx_t_6 = 0; + { + PyObject *__pyx_callargs[2] = {__pyx_t_5, ((PyObject *)__pyx_mstate_global->__pyx_memoryviewslice_type)}; + __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_register, __pyx_callargs+__pyx_t_6, (2-__pyx_t_6) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 899, __pyx_L26_error) + __Pyx_GOTREF(__pyx_t_4); + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "View.MemoryView":900 + * + * __pyx_collections_abc_Sequence.register(_memoryviewslice) + * __pyx_collections_abc_Sequence.register(array) # <<<<<<<<<<<<<< + * except: + * pass # ignore failure, it's a minor issue +*/ + __pyx_t_5 = __pyx_collections_abc_Sequence; + __Pyx_INCREF(__pyx_t_5); + __pyx_t_6 = 0; + { + PyObject *__pyx_callargs[2] = {__pyx_t_5, ((PyObject *)__pyx_mstate_global->__pyx_array_type)}; + __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_register, __pyx_callargs+__pyx_t_6, (2-__pyx_t_6) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 900, __pyx_L26_error) + __Pyx_GOTREF(__pyx_t_4); + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "View.MemoryView":895 + * + * try: + * if __pyx_collections_abc_Sequence: # <<<<<<<<<<<<<< + * + * +*/ + } + + /* "View.MemoryView":894 + * pass + * + * try: # <<<<<<<<<<<<<< + * if __pyx_collections_abc_Sequence: + * +*/ + } + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + goto __pyx_L31_try_end; + __pyx_L26_error:; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + + /* "View.MemoryView":901 + * __pyx_collections_abc_Sequence.register(_memoryviewslice) + * __pyx_collections_abc_Sequence.register(array) + * except: # <<<<<<<<<<<<<< + * pass # ignore failure, it's a minor issue + * +*/ + /*except:*/ { + __Pyx_ErrRestore(0,0,0); + goto __pyx_L27_exception_handled; + } + __pyx_L27_exception_handled:; + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_1); + __Pyx_ExceptionReset(__pyx_t_3, __pyx_t_2, __pyx_t_1); + __pyx_L31_try_end:; + } + + /* "(tree fragment)":4 + * int __Pyx_CheckUnpickleChecksum(long, long, long, long, const char*) except -1 + * int __Pyx_UpdateUnpickledDict(object, object, Py_ssize_t) except -1 + * def __pyx_unpickle_Enum(__pyx_type, long __pyx_checksum, tuple __pyx_state): # <<<<<<<<<<<<<< + * cdef object __pyx_result + * __Pyx_CheckUnpickleChecksum(__pyx_checksum, 0x82a3537, 0x6ae9995, 0xb068931, b'name') +*/ + __pyx_t_4 = PyCFunction_NewEx(&__pyx_mdef_15View_dot_MemoryView_1__pyx_unpickle_Enum, NULL, __pyx_mstate_global->__pyx_n_u_View_MemoryView); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_pyx_unpickle_Enum, __pyx_t_4) < (0)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "matcha/utils/monotonic_align/core.pyx":1 + * import numpy as np # <<<<<<<<<<<<<< + * + * cimport cython +*/ + __pyx_t_1 = __Pyx_Import(__pyx_mstate_global->__pyx_n_u_numpy, 0, 0, NULL, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_t_4 = __pyx_t_1; + __Pyx_GOTREF(__pyx_t_4); + if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_np, __pyx_t_4) < (0)) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "matcha/utils/monotonic_align/core.pyx":42 + * @cython.boundscheck(False) + * @cython.wraparound(False) + * cpdef void maximum_path_c(int[:,:,::1] paths, float[:,:,::1] values, int[::1] t_xs, int[::1] t_ys, float max_neg_val=-1e9) nogil: # <<<<<<<<<<<<<< + * cdef int b = values.shape[0] + * +*/ + __pyx_mstate_global->__pyx_k__6 = (-1e9); + + /* "matcha/utils/monotonic_align/core.pyx":40 + * + * + * @cython.boundscheck(False) # <<<<<<<<<<<<<< + * @cython.wraparound(False) + * cpdef void maximum_path_c(int[:,:,::1] paths, float[:,:,::1] values, int[::1] t_xs, int[::1] t_ys, float max_neg_val=-1e9) nogil: +*/ + __pyx_t_4 = PyFloat_FromDouble((-1e9)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 42, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = PyTuple_Pack(1, __pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 40, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = __Pyx_CyFunction_New(&__pyx_mdef_6matcha_5utils_15monotonic_align_4core_1maximum_path_c, 0, __pyx_mstate_global->__pyx_n_u_maximum_path_c, NULL, __pyx_mstate_global->__pyx_n_u_matcha_utils_monotonic_align_cor, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[0])); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 40, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000 + PyUnstable_Object_EnableDeferredRefcount(__pyx_t_4); + #endif + __Pyx_CyFunction_SetDefaultsTuple(__pyx_t_4, __pyx_t_5); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_maximum_path_c, __pyx_t_4) < (0)) __PYX_ERR(0, 40, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "matcha/utils/monotonic_align/core.pyx":1 + * import numpy as np # <<<<<<<<<<<<<< + * + * cimport cython +*/ + __pyx_t_4 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_test, __pyx_t_4) < (0)) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /*--- Wrapped vars code ---*/ + + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + if (__pyx_m) { + if (__pyx_mstate->__pyx_d && stringtab_initialized) { + __Pyx_AddTraceback("init matcha.utils.monotonic_align.core", __pyx_clineno, __pyx_lineno, __pyx_filename); + } + #if !CYTHON_USE_MODULE_STATE + Py_CLEAR(__pyx_m); + #else + Py_DECREF(__pyx_m); + if (pystate_addmodule_run) { + PyObject *tp, *value, *tb; + PyErr_Fetch(&tp, &value, &tb); + PyState_RemoveModule(&__pyx_moduledef); + PyErr_Restore(tp, value, tb); + } + #endif + } else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_ImportError, "init matcha.utils.monotonic_align.core"); + } + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + #if CYTHON_PEP489_MULTI_PHASE_INIT + return (__pyx_m != NULL) ? 0 : -1; + #else + return __pyx_m; + #endif +} +/* #### Code section: pystring_table ### */ +/* #### Code section: cached_builtins ### */ + +static int __Pyx_InitCachedBuiltins(__pyx_mstatetype *__pyx_mstate) { + CYTHON_UNUSED_VAR(__pyx_mstate); + __pyx_builtin___import__ = __Pyx_GetBuiltinName(__pyx_mstate->__pyx_n_u_import); if (!__pyx_builtin___import__) __PYX_ERR(1, 109, __pyx_L1_error) + __pyx_builtin_enumerate = __Pyx_GetBuiltinName(__pyx_mstate->__pyx_n_u_enumerate); if (!__pyx_builtin_enumerate) __PYX_ERR(1, 165, __pyx_L1_error) + __pyx_builtin_Ellipsis = __Pyx_GetBuiltinName(__pyx_mstate->__pyx_n_u_Ellipsis); if (!__pyx_builtin_Ellipsis) __PYX_ERR(1, 418, __pyx_L1_error) + __pyx_builtin_id = __Pyx_GetBuiltinName(__pyx_mstate->__pyx_n_u_id); if (!__pyx_builtin_id) __PYX_ERR(1, 628, __pyx_L1_error) + + /* Cached unbound methods */ + __pyx_mstate->__pyx_umethod_PyDict_Type_items.type = (PyObject*)&PyDict_Type; + __pyx_mstate->__pyx_umethod_PyDict_Type_items.method_name = &__pyx_mstate->__pyx_n_u_items; + __pyx_mstate->__pyx_umethod_PyDict_Type_pop.type = (PyObject*)&PyDict_Type; + __pyx_mstate->__pyx_umethod_PyDict_Type_pop.method_name = &__pyx_mstate->__pyx_n_u_pop; + __pyx_mstate->__pyx_umethod_PyDict_Type_values.type = (PyObject*)&PyDict_Type; + __pyx_mstate->__pyx_umethod_PyDict_Type_values.method_name = &__pyx_mstate->__pyx_n_u_values; + return 0; + __pyx_L1_error:; + return -1; +} +/* #### Code section: cached_constants ### */ + +static int __Pyx_InitCachedConstants(__pyx_mstatetype *__pyx_mstate) { + __Pyx_RefNannyDeclarations + CYTHON_UNUSED_VAR(__pyx_mstate); + __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); + + /* "View.MemoryView":592 + * def suboffsets(self): + * if self.view.suboffsets == NULL: + * return (-1,) * self.view.ndim # <<<<<<<<<<<<<< + * + * return tuple([suboffset for suboffset in self.view.suboffsets[:self.view.ndim]]) +*/ + __pyx_mstate_global->__pyx_tuple[0] = PyTuple_New(1); if (unlikely(!__pyx_mstate_global->__pyx_tuple[0])) __PYX_ERR(1, 592, __pyx_L1_error) + __Pyx_GOTREF(__pyx_mstate_global->__pyx_tuple[0]); + __Pyx_INCREF(__pyx_mstate_global->__pyx_int_neg_1); + __Pyx_GIVEREF(__pyx_mstate_global->__pyx_int_neg_1); + if (__Pyx_PyTuple_SET_ITEM(__pyx_mstate_global->__pyx_tuple[0], 0, __pyx_mstate_global->__pyx_int_neg_1) != (0)) __PYX_ERR(1, 592, __pyx_L1_error); + __Pyx_GIVEREF(__pyx_mstate_global->__pyx_tuple[0]); + + /* "View.MemoryView":689 + * tup = index if isinstance(index, tuple) else (index,) + * + * result = [slice(None)] * ndim # <<<<<<<<<<<<<< + * have_slices = False + * seen_ellipsis = False +*/ + __pyx_mstate_global->__pyx_slice[0] = PySlice_New(Py_None, Py_None, Py_None); if (unlikely(!__pyx_mstate_global->__pyx_slice[0])) __PYX_ERR(1, 689, __pyx_L1_error) + __Pyx_GOTREF(__pyx_mstate_global->__pyx_slice[0]); + __Pyx_GIVEREF(__pyx_mstate_global->__pyx_slice[0]); + #if CYTHON_IMMORTAL_CONSTANTS + { + PyObject **table = __pyx_mstate->__pyx_tuple; + for (Py_ssize_t i=0; i<1; ++i) { + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + #if PY_VERSION_HEX < 0x030E0000 + if (_Py_IsOwnedByCurrentThread(table[i]) && Py_REFCNT(table[i]) == 1) + #else + if (PyUnstable_Object_IsUniquelyReferenced(table[i])) + #endif + { + Py_SET_REFCNT(table[i], _Py_IMMORTAL_REFCNT_LOCAL); + } + #else + Py_SET_REFCNT(table[i], _Py_IMMORTAL_INITIAL_REFCNT); + #endif + } + } + #endif + #if CYTHON_IMMORTAL_CONSTANTS + { + PyObject **table = __pyx_mstate->__pyx_slice; + for (Py_ssize_t i=0; i<1; ++i) { + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + #if PY_VERSION_HEX < 0x030E0000 + if (_Py_IsOwnedByCurrentThread(table[i]) && Py_REFCNT(table[i]) == 1) + #else + if (PyUnstable_Object_IsUniquelyReferenced(table[i])) + #endif + { + Py_SET_REFCNT(table[i], _Py_IMMORTAL_REFCNT_LOCAL); + } + #else + Py_SET_REFCNT(table[i], _Py_IMMORTAL_INITIAL_REFCNT); + #endif + } + } + #endif + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_RefNannyFinishContext(); + return -1; +} +/* #### Code section: init_constants ### */ + +static int __Pyx_InitConstants(__pyx_mstatetype *__pyx_mstate) { + CYTHON_UNUSED_VAR(__pyx_mstate); + { + const struct { const unsigned int length: 8; } index[] = {{2},{35},{54},{37},{60},{24},{52},{26},{34},{33},{45},{22},{15},{179},{37},{32},{1},{1},{1},{1},{1},{8},{5},{6},{15},{23},{25},{7},{6},{2},{6},{35},{9},{30},{37},{50},{39},{34},{8},{20},{32},{22},{30},{37},{5},{8},{20},{8},{15},{3},{15},{18},{4},{1},{9},{17},{18},{5},{8},{15},{6},{9},{5},{5},{6},{7},{8},{12},{2},{10},{5},{13},{5},{8},{8},{33},{11},{14},{7},{4},{10},{4},{8},{4},{7},{2},{5},{3},{4},{5},{3},{14},{11},{10},{19},{14},{12},{10},{17},{13},{8},{12},{10},{12},{19},{5},{4},{5},{4},{4},{6},{4},{4},{8},{6},{6},{6},{1},{59},{1}}; + #if (CYTHON_COMPRESS_STRINGS) == 2 /* compression: bz2 (1137 bytes) */ +const char* const cstring = "BZh91AY&SY\203\003\3133\000\000l\177\373\365\200\266\000b\347\344W\277#\373\000\277\377\377\360@@@@@@@@@@@\000@\000P\004+\331\316\341\221\240\024\273CI\242i\251\205=\030\221\3523D\321\240\320\000\364\200\321\243\324m@i\342\236\240\321\032\247\24654j\2152i\243@\0004\320\000\000\000\003@5=\004\232\n\032\032\007\250\323\020h\000\000\000\000\006\200\034h\311\221\204b\001\204\320`\023A\240d\311\243&C\010\014%4BdFSi\251\204\324\3654\232y!\352\017H\007\250\320\000\001\246\200\256B*~k\025YS\034\245\373O\366\317\336\016\217|\331>\026\254\211\243p\363\272\275\nc\254\006\362\320\204p\264;:\021>\266>\0374(cQ(0\244z\177\031z\351\337\340\263\300\372(\220\261 \327\325 \332\235=\035`K\370\265\231]\202\202\271D\317\332\263\275\357\023\324\273\010O\020\022\025\317sJy-\261\335+\207\005\330\257eu@\241b=-\206\241\270\210 a\204\264Q\032\212@\244\233\242\241\3275r\372\254E\020\035\330\241\005\330o7D\n\214k5u\246\370\344\235\354lNs\265x\355\3526\235\t\235,5\356U\331\235\032\256\030\310\000\263g\250\001l\244 kX]3\255\351\007|EE 6S_V\006T\336h\312\224\2444j\206\225\2213\206\004\241\010]\022\002b\247\004\207\251\010\202\034Xlf\241\320$j\026\266\274\214\342n\253\332b\261\335~\320\304\367\373\026B\213M\277\346\371\006\235{\n\200\341\331\022\ta\270\351\323L\302\225U8\346t\346+\331\325\304\346X\226\204\026\374.\017\013\370w\233\314\374\341\000Y\270\256{\272xab,\326\235\340\372fj'*\253)x^9O\037i\221/\305rK\372\221\2031\250BM\224\024/\220&?*:P\330\2129]\312{I\262\226j\n\227\303\246Bd\310\357\275\342P\005\232{_t\0056\320\326\244\335Xa\273X\215\250W16\322\"\211\235\303I\022$\330i\000\263\324\260\372 \220\035'T\225\020aaQ\300\241\035\257\240ft*\360J\207\300M\014\260\325~S\230(_\007c\241)u\274\366\351c\311\372(\351\220p\004\333B\0333C\001\213\354\312S*5}g\2167\271\240Pq\236n\315\263\003\240D\235\351\265x\247His\035\334\226\330\303\t\000\350\245\201Ue<\226\223Q@\307\266T\336F(#\270s\0201(.\321!\321\324\256\263l\330\233\200\2027\033\245*'\003\025\222\246\273g\\\237\t\366C\030H\242t$5\254\345\314F\027:\3316\230\261cs\017\257\026\310tE\265\255U\010HSJ\004h,\303Z\036Nc\261M\367\030\314\013\205C\200\201\266\274\321\204\302L]|\317d\300\346\231\300\251-W1o\017(U\255p(\213\036\232i\256?9\243\260e\253V:8\276\327_\363\363X\252?\305\334\221N\024$ \300\362\314\300"; + PyObject *data = __Pyx_DecompressString(cstring, 1137, 2); + if (unlikely(!data)) __PYX_ERR(0, 1, __pyx_L1_error) + const char* const bytes = __Pyx_PyBytes_AsString(data); + #if !CYTHON_ASSUME_SAFE_MACROS + if (likely(bytes)); else { Py_DECREF(data); __PYX_ERR(0, 1, __pyx_L1_error) } + #endif + #elif (CYTHON_COMPRESS_STRINGS) != 0 /* compression: zlib (1004 bytes) */ +const char* const cstring = "x\332}T\277o\034E\024&(\n%\002A?\024\350\202\024\257\203\344\002!c\224\330FrA\342\020\221v47\363vo\360\356\314z~\334\335RQR\272L\3512eJ\377\031\224)\371\023\370\023\370\336\354\336\371\022#\212\333{;\373~|\357{\337\274\357\305\323\\\327\024\304\322\322J\030OQ8\237\004\255{\037I\304\024\254\241x\254\234\360\256\035\204\016\244\022\t%\346cPZ\250$l\024\332\273d\233\354s\024\326\211\216:\037\206\nQ\234J\305h\033'\222\027\0106{%\317\350\301%'\247)\361*\330\244\346-M\016#\250:\370\356\377b\2553\264\026+\233\026\"\r=\211\331t\236\202r\261\264q\0332\272!\302\006\322I\030\333\221\213\326\273x\262\261\304\327\206;\342\004\243\323i\327\247A\304\205B\352\224{\200\253}\020zH\013\357*\025\202\032\316\356\246+\3611\367\275\017\211\314\231[\252\326\032\321yC\217\230[8\223\0213=\023H5C>\306:{$\032Dm\234\307\212\240S\255\201\347\360\347\322\303+\356\301\327\342\231\007[\205\375\343\002\204!\033j\355\234\002x\004K<9\024)#r\342\374\364|\357\340\273\003\241\234\001\223\277\241|\004\272\271n1\034L\034\t\347\331\266\t\305\230\301X\211\263Z\014>\013G\200\211\311\365\360\333\rH\013r\"RbC\314\n\335*\241o\211p\353\232\331D\235]\022G\377\244\332H\325\363\234J!\237\235AI\267\321\220\322\232\220\375ai\363WW\306\217 HjI\001\323M\324\361\273\2373\354\352h\366\315\217\312\030\351\230\000nG\200\203\307k\355\333\226\013\202\372J\315\365\341\216 \331i\204s\364\341\361F\007G\306F\256K\245z\243\305C\036DS$\300\030\321\022\246\226\310\245\242\357\355\230\301\372\030b\030e\264\277\2238\374A<\276#\220N%\275P\3739\3316\356w\036\330\275\263Zb\314\215\333\327>P\325\017k\3471\301Z\3456\t)\003\231\254IJara\303y\267\207\211.\255j\361U[g\223\224.w\375P\311\222\240C\234-\305D\255l;\216\315v\254\277]\267\014(\213;\036\023\271G\207\343}7\357qv\367\214E\273\245\356\275\357\333\323\274\235\243j[\257\313\322(\340\214J\252\372\217\257\243\3329\307\264s\252'/\217\317\316N\333\326\366\321F)\317\2075~'\020\265|\206Y\374B\365K\272\314\3444\361\235\250n\257\007\306\277\311*G\211\25188m}\005\006\372\344\363\253\317\256\276zw\377\313\253\027W\204\263\223\353\007\327\352:\2759xs\371\366\376\333\223\233{7_\334\274x\376/\t\017\325f"; + PyObject *data = __Pyx_DecompressString(cstring, 1004, 1); + if (unlikely(!data)) __PYX_ERR(0, 1, __pyx_L1_error) + const char* const bytes = __Pyx_PyBytes_AsString(data); + #if !CYTHON_ASSUME_SAFE_MACROS + if (likely(bytes)); else { Py_DECREF(data); __PYX_ERR(0, 1, __pyx_L1_error) } + #endif + #else /* compression: none (1884 bytes) */ +const char* const bytes = ": Buffer view does not expose stridesCan only create a buffer that is contiguous in memory.Cannot assign to read-only memoryviewCannot create writable memory view from read-only memoryviewCannot index with type 'Cannot transpose memoryview with indirect dimensionsDimension %d is not directEmpty shape tuple for cython.arrayIndirect dimensions not supportedInvalid mode, expected 'c' or 'fortran', got Invalid shape in axis ')?add_note and at 0xcollections.abcdisableenablegc (got got differing extents in dimension isenableditemsize <= 0 for cython.arraymatcha/utils/monotonic_align/core.pyxno default __reduce__ due to non-trivial __cinit__numpy._core.multiarray failed to importnumpy._core.umath failed to import object>unable to allocate array data.unable to allocate shape and strides.ASCIIEllipsis__Pyx_PyDict_NextRefSequenceView.MemoryViewabcallocate_bufferasyncio.coroutinesbasec__class____class_getitem__cline_in_tracebackcount__dict__dtype_is_objectencodeenumerateerrorflagsformatfortran__func____getstate__id__import__index_is_coroutineitemsitemsize__main__matcha.utils.monotonic_align.coremax_neg_valmaximum_path_cmemviewmode__module__name__name__ndim__new__npnumpyobjpackpathspop__pyx_checksum__pyx_state__pyx_type__pyx_unpickle_Enum__pyx_vtable____qualname____reduce____reduce_cython____reduce_ex__register__set_name__setdefault__setstate____setstate_cython__shapesizestartstepstopstructt_xst_ys__test__unpackupdatevaluesx\200\001\340uv\320vw\330\002\017\210v\220V\2301\230A\360\006\000\007\022\220\021\220!\330\004\025\220Q\220e\2301\230D\240\006\240a\240t\2504\250q\260\004\260D\270\001\270\024""\270QO"; + PyObject *data = NULL; + CYTHON_UNUSED_VAR(__Pyx_DecompressString); + #endif + PyObject **stringtab = __pyx_mstate->__pyx_string_tab; + Py_ssize_t pos = 0; + for (int i = 0; i < 118; i++) { + Py_ssize_t bytes_length = index[i].length; + PyObject *string = PyUnicode_DecodeUTF8(bytes + pos, bytes_length, NULL); + if (likely(string) && i >= 44) PyUnicode_InternInPlace(&string); + if (unlikely(!string)) { + Py_XDECREF(data); + __PYX_ERR(0, 1, __pyx_L1_error) + } + stringtab[i] = string; + pos += bytes_length; + } + for (int i = 118; i < 120; i++) { + Py_ssize_t bytes_length = index[i].length; + PyObject *string = PyBytes_FromStringAndSize(bytes + pos, bytes_length); + stringtab[i] = string; + pos += bytes_length; + if (unlikely(!string)) { + Py_XDECREF(data); + __PYX_ERR(0, 1, __pyx_L1_error) + } + } + Py_XDECREF(data); + for (Py_ssize_t i = 0; i < 120; i++) { + if (unlikely(PyObject_Hash(stringtab[i]) == -1)) { + __PYX_ERR(0, 1, __pyx_L1_error) + } + } + #if CYTHON_IMMORTAL_CONSTANTS + { + PyObject **table = stringtab + 118; + for (Py_ssize_t i=0; i<2; ++i) { + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + #if PY_VERSION_HEX < 0x030E0000 + if (_Py_IsOwnedByCurrentThread(table[i]) && Py_REFCNT(table[i]) == 1) + #else + if (PyUnstable_Object_IsUniquelyReferenced(table[i])) + #endif + { + Py_SET_REFCNT(table[i], _Py_IMMORTAL_REFCNT_LOCAL); + } + #else + Py_SET_REFCNT(table[i], _Py_IMMORTAL_INITIAL_REFCNT); + #endif + } + } + #endif + } + { + PyObject **numbertab = __pyx_mstate->__pyx_number_tab + 0; + int8_t const cint_constants_1[] = {0,-1,1}; + int32_t const cint_constants_4[] = {136983863L}; + for (int i = 0; i < 4; i++) { + numbertab[i] = PyLong_FromLong((i < 3 ? cint_constants_1[i - 0] : cint_constants_4[i - 3])); + if (unlikely(!numbertab[i])) __PYX_ERR(0, 1, __pyx_L1_error) + } + } + #if CYTHON_IMMORTAL_CONSTANTS + { + PyObject **table = __pyx_mstate->__pyx_number_tab; + for (Py_ssize_t i=0; i<4; ++i) { + #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + #if PY_VERSION_HEX < 0x030E0000 + if (_Py_IsOwnedByCurrentThread(table[i]) && Py_REFCNT(table[i]) == 1) + #else + if (PyUnstable_Object_IsUniquelyReferenced(table[i])) + #endif + { + Py_SET_REFCNT(table[i], _Py_IMMORTAL_REFCNT_LOCAL); + } + #else + Py_SET_REFCNT(table[i], _Py_IMMORTAL_INITIAL_REFCNT); + #endif + } + } + #endif + return 0; + __pyx_L1_error:; + return -1; +} +/* #### Code section: init_codeobjects ### */ +typedef struct { + unsigned int argcount : 3; + unsigned int num_posonly_args : 1; + unsigned int num_kwonly_args : 1; + unsigned int nlocals : 3; + unsigned int flags : 10; + unsigned int first_line : 6; +} __Pyx_PyCode_New_function_description; +/* NewCodeObj.proto */ +static PyObject* __Pyx_PyCode_New( + const __Pyx_PyCode_New_function_description descr, + PyObject * const *varnames, + PyObject *filename, + PyObject *funcname, + PyObject *line_table, + PyObject *tuple_dedup_map +); + + +static int __Pyx_CreateCodeObjects(__pyx_mstatetype *__pyx_mstate) { + PyObject* tuple_dedup_map = PyDict_New(); + if (unlikely(!tuple_dedup_map)) return -1; + { + const __Pyx_PyCode_New_function_description descr = {5, 0, 0, 5, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 40}; + PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_paths, __pyx_mstate->__pyx_n_u_values, __pyx_mstate->__pyx_n_u_t_xs, __pyx_mstate->__pyx_n_u_t_ys, __pyx_mstate->__pyx_n_u_max_neg_val}; + __pyx_mstate_global->__pyx_codeobj_tab[0] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_matcha_utils_monotonic_align_cor_2, __pyx_mstate->__pyx_n_u_maximum_path_c, __pyx_mstate->__pyx_kp_b_iso88591_uvvw_vV1A_Qe1D_at4q_D_Q, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[0])) goto bad; + } + Py_DECREF(tuple_dedup_map); + return 0; + bad: + Py_DECREF(tuple_dedup_map); + return -1; +} +/* #### Code section: init_globals ### */ + +static int __Pyx_InitGlobals(void) { + /* PythonCompatibility.init */ + if (likely(__Pyx_init_co_variables() == 0)); else + + if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1, __pyx_L1_error) + + /* AssertionsEnabled.init */ + if (likely(__Pyx_init_assertions_enabled() == 0)); else + + if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1, __pyx_L1_error) + + /* NumpyImportArray.init */ + /* + * Cython has automatically inserted a call to _import_array since + * you didn't include one when you cimported numpy. To disable this + * add the line + * numpy._import_array + */ + #ifdef NPY_FEATURE_VERSION + #ifndef NO_IMPORT_ARRAY + if (unlikely(_import_array() == -1)) { + PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import " + "(auto-generated because you didn't call 'numpy.import_array()' after cimporting numpy; " + "use 'numpy._import_array' to disable if you are certain you don't need it)."); + } + #endif + #endif + + if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1, __pyx_L1_error) + + /* CommonTypesMetaclass.init */ + if (likely(__pyx_CommonTypesMetaclass_init(__pyx_m) == 0)); else + + if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1, __pyx_L1_error) + + /* CachedMethodType.init */ + #if CYTHON_COMPILING_IN_LIMITED_API + { + PyObject *typesModule=NULL; + typesModule = PyImport_ImportModule("types"); + if (typesModule) { + __pyx_mstate_global->__Pyx_CachedMethodType = PyObject_GetAttrString(typesModule, "MethodType"); + Py_DECREF(typesModule); + } + } // error handling follows + #endif + + if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1, __pyx_L1_error) + + /* CythonFunctionShared.init */ + if (likely(__pyx_CyFunction_init(__pyx_m) == 0)); else + + if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1, __pyx_L1_error) + + return 0; + __pyx_L1_error:; + return -1; +} +/* #### Code section: cleanup_globals ### */ +/* #### Code section: cleanup_module ### */ +/* #### Code section: main_method ### */ +/* #### Code section: utility_code_pragmas ### */ +#ifdef _MSC_VER +#pragma warning( push ) +/* Warning 4127: conditional expression is constant + * Cython uses constant conditional expressions to allow in inline functions to be optimized at + * compile-time, so this warning is not useful + */ +#pragma warning( disable : 4127 ) +#endif + + + +/* #### Code section: utility_code_def ### */ + +/* --- Runtime support code --- */ +/* Refnanny */ +#if CYTHON_REFNANNY +static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { + PyObject *m = NULL, *p = NULL; + void *r = NULL; + m = PyImport_ImportModule(modname); + if (!m) goto end; + p = PyObject_GetAttrString(m, "RefNannyAPI"); + if (!p) goto end; + r = PyLong_AsVoidPtr(p); +end: + Py_XDECREF(p); + Py_XDECREF(m); + return (__Pyx_RefNannyAPIStruct *)r; +} +#endif + +/* TupleAndListFromArray (used by fastcall) */ +#if !CYTHON_COMPILING_IN_CPYTHON && CYTHON_METH_FASTCALL +static CYTHON_INLINE PyObject * +__Pyx_PyTuple_FromArray(PyObject *const *src, Py_ssize_t n) +{ + PyObject *res; + Py_ssize_t i; + if (n <= 0) { + return __Pyx_NewRef(__pyx_mstate_global->__pyx_empty_tuple); + } + res = PyTuple_New(n); + if (unlikely(res == NULL)) return NULL; + for (i = 0; i < n; i++) { + Py_INCREF(src[i]); + if (unlikely(__Pyx_PyTuple_SET_ITEM(res, i, src[i]) < (0))) { + Py_DECREF(res); + return NULL; + } + } + return res; +} +#elif CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE void __Pyx_copy_object_array(PyObject *const *CYTHON_RESTRICT src, PyObject** CYTHON_RESTRICT dest, Py_ssize_t length) { + PyObject *v; + Py_ssize_t i; + for (i = 0; i < length; i++) { + v = dest[i] = src[i]; + Py_INCREF(v); + } +} +static CYTHON_INLINE PyObject * +__Pyx_PyTuple_FromArray(PyObject *const *src, Py_ssize_t n) +{ + PyObject *res; + if (n <= 0) { + return __Pyx_NewRef(__pyx_mstate_global->__pyx_empty_tuple); + } + res = PyTuple_New(n); + if (unlikely(res == NULL)) return NULL; + __Pyx_copy_object_array(src, ((PyTupleObject*)res)->ob_item, n); + return res; +} +static CYTHON_INLINE PyObject * +__Pyx_PyList_FromArray(PyObject *const *src, Py_ssize_t n) +{ + PyObject *res; + if (n <= 0) { + return PyList_New(0); + } + res = PyList_New(n); + if (unlikely(res == NULL)) return NULL; + __Pyx_copy_object_array(src, ((PyListObject*)res)->ob_item, n); + return res; +} +#endif + +/* BytesEquals (used by UnicodeEquals) */ +static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int equals) { +#if CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_LIMITED_API || CYTHON_COMPILING_IN_GRAAL ||\ + !(CYTHON_ASSUME_SAFE_SIZE && CYTHON_ASSUME_SAFE_MACROS) + return PyObject_RichCompareBool(s1, s2, equals); +#else + if (s1 == s2) { + return (equals == Py_EQ); + } else if (PyBytes_CheckExact(s1) & PyBytes_CheckExact(s2)) { + const char *ps1, *ps2; + Py_ssize_t length = PyBytes_GET_SIZE(s1); + if (length != PyBytes_GET_SIZE(s2)) + return (equals == Py_NE); + ps1 = PyBytes_AS_STRING(s1); + ps2 = PyBytes_AS_STRING(s2); + if (ps1[0] != ps2[0]) { + return (equals == Py_NE); + } else if (length == 1) { + return (equals == Py_EQ); + } else { + int result; +#if CYTHON_USE_UNICODE_INTERNALS && (PY_VERSION_HEX < 0x030B0000) + Py_hash_t hash1, hash2; + hash1 = ((PyBytesObject*)s1)->ob_shash; + hash2 = ((PyBytesObject*)s2)->ob_shash; + if (hash1 != hash2 && hash1 != -1 && hash2 != -1) { + return (equals == Py_NE); + } +#endif + result = memcmp(ps1, ps2, (size_t)length); + return (equals == Py_EQ) ? (result == 0) : (result != 0); + } + } else if ((s1 == Py_None) & PyBytes_CheckExact(s2)) { + return (equals == Py_NE); + } else if ((s2 == Py_None) & PyBytes_CheckExact(s1)) { + return (equals == Py_NE); + } else { + int result; + PyObject* py_result = PyObject_RichCompare(s1, s2, equals); + if (!py_result) + return -1; + result = __Pyx_PyObject_IsTrue(py_result); + Py_DECREF(py_result); + return result; + } +#endif +} + +/* UnicodeEquals (used by fastcall) */ +static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int equals) { +#if CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_LIMITED_API || CYTHON_COMPILING_IN_GRAAL + return PyObject_RichCompareBool(s1, s2, equals); +#else + int s1_is_unicode, s2_is_unicode; + if (s1 == s2) { + goto return_eq; + } + s1_is_unicode = PyUnicode_CheckExact(s1); + s2_is_unicode = PyUnicode_CheckExact(s2); + if (s1_is_unicode & s2_is_unicode) { + Py_ssize_t length, length2; + int kind; + void *data1, *data2; + #if !CYTHON_COMPILING_IN_LIMITED_API + if (unlikely(__Pyx_PyUnicode_READY(s1) < 0) || unlikely(__Pyx_PyUnicode_READY(s2) < 0)) + return -1; + #endif + length = __Pyx_PyUnicode_GET_LENGTH(s1); + #if !CYTHON_ASSUME_SAFE_SIZE + if (unlikely(length < 0)) return -1; + #endif + length2 = __Pyx_PyUnicode_GET_LENGTH(s2); + #if !CYTHON_ASSUME_SAFE_SIZE + if (unlikely(length2 < 0)) return -1; + #endif + if (length != length2) { + goto return_ne; + } +#if CYTHON_USE_UNICODE_INTERNALS + { + Py_hash_t hash1, hash2; + hash1 = ((PyASCIIObject*)s1)->hash; + hash2 = ((PyASCIIObject*)s2)->hash; + if (hash1 != hash2 && hash1 != -1 && hash2 != -1) { + goto return_ne; + } + } +#endif + kind = __Pyx_PyUnicode_KIND(s1); + if (kind != __Pyx_PyUnicode_KIND(s2)) { + goto return_ne; + } + data1 = __Pyx_PyUnicode_DATA(s1); + data2 = __Pyx_PyUnicode_DATA(s2); + if (__Pyx_PyUnicode_READ(kind, data1, 0) != __Pyx_PyUnicode_READ(kind, data2, 0)) { + goto return_ne; + } else if (length == 1) { + goto return_eq; + } else { + int result = memcmp(data1, data2, (size_t)(length * kind)); + return (equals == Py_EQ) ? (result == 0) : (result != 0); + } + } else if ((s1 == Py_None) & s2_is_unicode) { + goto return_ne; + } else if ((s2 == Py_None) & s1_is_unicode) { + goto return_ne; + } else { + int result; + PyObject* py_result = PyObject_RichCompare(s1, s2, equals); + if (!py_result) + return -1; + result = __Pyx_PyObject_IsTrue(py_result); + Py_DECREF(py_result); + return result; + } +return_eq: + return (equals == Py_EQ); +return_ne: + return (equals == Py_NE); +#endif +} + +/* fastcall */ +#if CYTHON_METH_FASTCALL +static CYTHON_INLINE PyObject * __Pyx_GetKwValue_FASTCALL(PyObject *kwnames, PyObject *const *kwvalues, PyObject *s) +{ + Py_ssize_t i, n = __Pyx_PyTuple_GET_SIZE(kwnames); + #if !CYTHON_ASSUME_SAFE_SIZE + if (unlikely(n == -1)) return NULL; + #endif + for (i = 0; i < n; i++) + { + PyObject *namei = __Pyx_PyTuple_GET_ITEM(kwnames, i); + #if !CYTHON_ASSUME_SAFE_MACROS + if (unlikely(!namei)) return NULL; + #endif + if (s == namei) return kwvalues[i]; + } + for (i = 0; i < n; i++) + { + PyObject *namei = __Pyx_PyTuple_GET_ITEM(kwnames, i); + #if !CYTHON_ASSUME_SAFE_MACROS + if (unlikely(!namei)) return NULL; + #endif + int eq = __Pyx_PyUnicode_Equals(s, namei, Py_EQ); + if (unlikely(eq != 0)) { + if (unlikely(eq < 0)) return NULL; + return kwvalues[i]; + } + } + return NULL; +} +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030d0000 || CYTHON_COMPILING_IN_LIMITED_API +CYTHON_UNUSED static PyObject *__Pyx_KwargsAsDict_FASTCALL(PyObject *kwnames, PyObject *const *kwvalues) { + Py_ssize_t i, nkwargs; + PyObject *dict; +#if !CYTHON_ASSUME_SAFE_SIZE + nkwargs = PyTuple_Size(kwnames); + if (unlikely(nkwargs < 0)) return NULL; +#else + nkwargs = PyTuple_GET_SIZE(kwnames); +#endif + dict = PyDict_New(); + if (unlikely(!dict)) + return NULL; + for (i=0; itp_call; + if (unlikely(!call)) + return PyObject_Call(func, arg, kw); + if (unlikely(Py_EnterRecursiveCall(" while calling a Python object"))) + return NULL; + result = (*call)(func, arg, kw); + Py_LeaveRecursiveCall(); + if (unlikely(!result) && unlikely(!PyErr_Occurred())) { + PyErr_SetString( + PyExc_SystemError, + "NULL result without error in PyObject_Call"); + } + return result; +} +#endif + +/* PyObjectCallMethO (used by PyObjectFastCall) */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) { + PyObject *self, *result; + PyCFunction cfunc; + cfunc = __Pyx_CyOrPyCFunction_GET_FUNCTION(func); + self = __Pyx_CyOrPyCFunction_GET_SELF(func); + if (unlikely(Py_EnterRecursiveCall(" while calling a Python object"))) + return NULL; + result = cfunc(self, arg); + Py_LeaveRecursiveCall(); + if (unlikely(!result) && unlikely(!PyErr_Occurred())) { + PyErr_SetString( + PyExc_SystemError, + "NULL result without error in PyObject_Call"); + } + return result; +} +#endif + +/* PyObjectFastCall (used by PyObjectCallOneArg) */ +#if PY_VERSION_HEX < 0x03090000 || CYTHON_COMPILING_IN_LIMITED_API +static PyObject* __Pyx_PyObject_FastCall_fallback(PyObject *func, PyObject * const*args, size_t nargs, PyObject *kwargs) { + PyObject *argstuple; + PyObject *result = 0; + size_t i; + argstuple = PyTuple_New((Py_ssize_t)nargs); + if (unlikely(!argstuple)) return NULL; + for (i = 0; i < nargs; i++) { + Py_INCREF(args[i]); + if (__Pyx_PyTuple_SET_ITEM(argstuple, (Py_ssize_t)i, args[i]) != (0)) goto bad; + } + result = __Pyx_PyObject_Call(func, argstuple, kwargs); + bad: + Py_DECREF(argstuple); + return result; +} +#endif +#if CYTHON_VECTORCALL && !CYTHON_COMPILING_IN_LIMITED_API + #if PY_VERSION_HEX < 0x03090000 + #define __Pyx_PyVectorcall_Function(callable) _PyVectorcall_Function(callable) + #elif CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE vectorcallfunc __Pyx_PyVectorcall_Function(PyObject *callable) { + PyTypeObject *tp = Py_TYPE(callable); + #if defined(__Pyx_CyFunction_USED) + if (__Pyx_CyFunction_CheckExact(callable)) { + return __Pyx_CyFunction_func_vectorcall(callable); + } + #endif + if (!PyType_HasFeature(tp, Py_TPFLAGS_HAVE_VECTORCALL)) { + return NULL; + } + assert(PyCallable_Check(callable)); + Py_ssize_t offset = tp->tp_vectorcall_offset; + assert(offset > 0); + vectorcallfunc ptr; + memcpy(&ptr, (char *) callable + offset, sizeof(ptr)); + return ptr; +} + #else + #define __Pyx_PyVectorcall_Function(callable) PyVectorcall_Function(callable) + #endif +#endif +static CYTHON_INLINE PyObject* __Pyx_PyObject_FastCallDict(PyObject *func, PyObject *const *args, size_t _nargs, PyObject *kwargs) { + Py_ssize_t nargs = __Pyx_PyVectorcall_NARGS(_nargs); +#if CYTHON_COMPILING_IN_CPYTHON + if (nargs == 0 && kwargs == NULL) { + if (__Pyx_CyOrPyCFunction_Check(func) && likely( __Pyx_CyOrPyCFunction_GET_FLAGS(func) & METH_NOARGS)) + return __Pyx_PyObject_CallMethO(func, NULL); + } + else if (nargs == 1 && kwargs == NULL) { + if (__Pyx_CyOrPyCFunction_Check(func) && likely( __Pyx_CyOrPyCFunction_GET_FLAGS(func) & METH_O)) + return __Pyx_PyObject_CallMethO(func, args[0]); + } +#endif + if (kwargs == NULL) { + #if CYTHON_VECTORCALL + #if CYTHON_COMPILING_IN_LIMITED_API + return PyObject_Vectorcall(func, args, _nargs, NULL); + #else + vectorcallfunc f = __Pyx_PyVectorcall_Function(func); + if (f) { + return f(func, args, _nargs, NULL); + } + #endif + #endif + } + if (nargs == 0) { + return __Pyx_PyObject_Call(func, __pyx_mstate_global->__pyx_empty_tuple, kwargs); + } + #if PY_VERSION_HEX >= 0x03090000 && !CYTHON_COMPILING_IN_LIMITED_API + return PyObject_VectorcallDict(func, args, (size_t)nargs, kwargs); + #else + return __Pyx_PyObject_FastCall_fallback(func, args, (size_t)nargs, kwargs); + #endif +} + +/* PyObjectCallOneArg (used by CallUnboundCMethod0) */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { + PyObject *args[2] = {NULL, arg}; + return __Pyx_PyObject_FastCall(func, args+1, 1 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET); +} + +/* PyObjectGetAttrStr (used by UnpackUnboundCMethod) */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) { + PyTypeObject* tp = Py_TYPE(obj); + if (likely(tp->tp_getattro)) + return tp->tp_getattro(obj, attr_name); + return PyObject_GetAttr(obj, attr_name); +} +#endif + +/* UnpackUnboundCMethod (used by CallUnboundCMethod0) */ +#if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030C0000 +static PyObject *__Pyx_SelflessCall(PyObject *method, PyObject *args, PyObject *kwargs) { + PyObject *result; + PyObject *selfless_args = PyTuple_GetSlice(args, 1, PyTuple_Size(args)); + if (unlikely(!selfless_args)) return NULL; + result = PyObject_Call(method, selfless_args, kwargs); + Py_DECREF(selfless_args); + return result; +} +#elif CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x03090000 +static PyObject *__Pyx_SelflessCall(PyObject *method, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) { + return _PyObject_Vectorcall + (method, args ? args+1 : NULL, nargs ? nargs-1 : 0, kwnames); +} +#else +static PyObject *__Pyx_SelflessCall(PyObject *method, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { + return +#if PY_VERSION_HEX < 0x03090000 + _PyObject_Vectorcall +#else + PyObject_Vectorcall +#endif + (method, args ? args+1 : NULL, nargs ? (size_t) nargs-1 : 0, kwnames); +} +#endif +static PyMethodDef __Pyx_UnboundCMethod_Def = { + "CythonUnboundCMethod", + __PYX_REINTERPRET_FUNCION(PyCFunction, __Pyx_SelflessCall), +#if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030C0000 + METH_VARARGS | METH_KEYWORDS, +#else + METH_FASTCALL | METH_KEYWORDS, +#endif + NULL +}; +static int __Pyx_TryUnpackUnboundCMethod(__Pyx_CachedCFunction* target) { + PyObject *method, *result=NULL; + method = __Pyx_PyObject_GetAttrStr(target->type, *target->method_name); + if (unlikely(!method)) + return -1; + result = method; +#if CYTHON_COMPILING_IN_CPYTHON + if (likely(__Pyx_TypeCheck(method, &PyMethodDescr_Type))) + { + PyMethodDescrObject *descr = (PyMethodDescrObject*) method; + target->func = descr->d_method->ml_meth; + target->flag = descr->d_method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_STACKLESS); + } else +#endif +#if CYTHON_COMPILING_IN_PYPY +#else + if (PyCFunction_Check(method)) +#endif + { + PyObject *self; + int self_found; +#if CYTHON_COMPILING_IN_LIMITED_API || CYTHON_COMPILING_IN_PYPY + self = PyObject_GetAttrString(method, "__self__"); + if (!self) { + PyErr_Clear(); + } +#else + self = PyCFunction_GET_SELF(method); +#endif + self_found = (self && self != Py_None); +#if CYTHON_COMPILING_IN_LIMITED_API || CYTHON_COMPILING_IN_PYPY + Py_XDECREF(self); +#endif + if (self_found) { + PyObject *unbound_method = PyCFunction_New(&__Pyx_UnboundCMethod_Def, method); + if (unlikely(!unbound_method)) return -1; + Py_DECREF(method); + result = unbound_method; + } + } +#if !CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + if (unlikely(target->method)) { + Py_DECREF(result); + } else +#endif + target->method = result; + return 0; +} + +/* CallUnboundCMethod0 */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_CallUnboundCMethod0(__Pyx_CachedCFunction* cfunc, PyObject* self) { + int was_initialized = __Pyx_CachedCFunction_GetAndSetInitializing(cfunc); + if (likely(was_initialized == 2 && cfunc->func)) { + if (likely(cfunc->flag == METH_NOARGS)) + return __Pyx_CallCFunction(cfunc, self, NULL); + if (likely(cfunc->flag == METH_FASTCALL)) + return __Pyx_CallCFunctionFast(cfunc, self, NULL, 0); + if (cfunc->flag == (METH_FASTCALL | METH_KEYWORDS)) + return __Pyx_CallCFunctionFastWithKeywords(cfunc, self, NULL, 0, NULL); + if (likely(cfunc->flag == (METH_VARARGS | METH_KEYWORDS))) + return __Pyx_CallCFunctionWithKeywords(cfunc, self, __pyx_mstate_global->__pyx_empty_tuple, NULL); + if (cfunc->flag == METH_VARARGS) + return __Pyx_CallCFunction(cfunc, self, __pyx_mstate_global->__pyx_empty_tuple); + return __Pyx__CallUnboundCMethod0(cfunc, self); + } +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + else if (unlikely(was_initialized == 1)) { + __Pyx_CachedCFunction tmp_cfunc = { +#ifndef __cplusplus + 0 +#endif + }; + tmp_cfunc.type = cfunc->type; + tmp_cfunc.method_name = cfunc->method_name; + return __Pyx__CallUnboundCMethod0(&tmp_cfunc, self); + } +#endif + PyObject *result = __Pyx__CallUnboundCMethod0(cfunc, self); + __Pyx_CachedCFunction_SetFinishedInitializing(cfunc); + return result; +} +#endif +static PyObject* __Pyx__CallUnboundCMethod0(__Pyx_CachedCFunction* cfunc, PyObject* self) { + PyObject *result; + if (unlikely(!cfunc->method) && unlikely(__Pyx_TryUnpackUnboundCMethod(cfunc) < 0)) return NULL; + result = __Pyx_PyObject_CallOneArg(cfunc->method, self); + return result; +} + +/* py_dict_items (used by OwnedDictNext) */ +static CYTHON_INLINE PyObject* __Pyx_PyDict_Items(PyObject* d) { + return __Pyx_CallUnboundCMethod0(&__pyx_mstate_global->__pyx_umethod_PyDict_Type_items, d); +} + +/* py_dict_values (used by OwnedDictNext) */ +static CYTHON_INLINE PyObject* __Pyx_PyDict_Values(PyObject* d) { + return __Pyx_CallUnboundCMethod0(&__pyx_mstate_global->__pyx_umethod_PyDict_Type_values, d); +} + +/* OwnedDictNext (used by ParseKeywordsImpl) */ +#if CYTHON_AVOID_BORROWED_REFS +static int __Pyx_PyDict_NextRef(PyObject *p, PyObject **ppos, PyObject **pkey, PyObject **pvalue) { + PyObject *next = NULL; + if (!*ppos) { + if (pvalue) { + PyObject *dictview = pkey ? __Pyx_PyDict_Items(p) : __Pyx_PyDict_Values(p); + if (unlikely(!dictview)) goto bad; + *ppos = PyObject_GetIter(dictview); + Py_DECREF(dictview); + } else { + *ppos = PyObject_GetIter(p); + } + if (unlikely(!*ppos)) goto bad; + } + next = PyIter_Next(*ppos); + if (!next) { + if (PyErr_Occurred()) goto bad; + return 0; + } + if (pkey && pvalue) { + *pkey = __Pyx_PySequence_ITEM(next, 0); + if (unlikely(*pkey)) goto bad; + *pvalue = __Pyx_PySequence_ITEM(next, 1); + if (unlikely(*pvalue)) goto bad; + Py_DECREF(next); + } else if (pkey) { + *pkey = next; + } else { + assert(pvalue); + *pvalue = next; + } + return 1; + bad: + Py_XDECREF(next); +#if !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x030d0000 + PyErr_FormatUnraisable("Exception ignored in __Pyx_PyDict_NextRef"); +#else + PyErr_WriteUnraisable(__pyx_mstate_global->__pyx_n_u_Pyx_PyDict_NextRef); +#endif + if (pkey) *pkey = NULL; + if (pvalue) *pvalue = NULL; + return 0; +} +#else // !CYTHON_AVOID_BORROWED_REFS +static int __Pyx_PyDict_NextRef(PyObject *p, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue) { + int result = PyDict_Next(p, ppos, pkey, pvalue); + if (likely(result == 1)) { + if (pkey) Py_INCREF(*pkey); + if (pvalue) Py_INCREF(*pvalue); + } + return result; +} +#endif + +/* RaiseDoubleKeywords (used by ParseKeywordsImpl) */ +static void __Pyx_RaiseDoubleKeywordsError( + const char* func_name, + PyObject* kw_name) +{ + PyErr_Format(PyExc_TypeError, + "%s() got multiple values for keyword argument '%U'", func_name, kw_name); +} + +/* CallUnboundCMethod2 */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject *__Pyx_CallUnboundCMethod2(__Pyx_CachedCFunction *cfunc, PyObject *self, PyObject *arg1, PyObject *arg2) { + int was_initialized = __Pyx_CachedCFunction_GetAndSetInitializing(cfunc); + if (likely(was_initialized == 2 && cfunc->func)) { + PyObject *args[2] = {arg1, arg2}; + if (cfunc->flag == METH_FASTCALL) { + return __Pyx_CallCFunctionFast(cfunc, self, args, 2); + } + if (cfunc->flag == (METH_FASTCALL | METH_KEYWORDS)) + return __Pyx_CallCFunctionFastWithKeywords(cfunc, self, args, 2, NULL); + } +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + else if (unlikely(was_initialized == 1)) { + __Pyx_CachedCFunction tmp_cfunc = { +#ifndef __cplusplus + 0 +#endif + }; + tmp_cfunc.type = cfunc->type; + tmp_cfunc.method_name = cfunc->method_name; + return __Pyx__CallUnboundCMethod2(&tmp_cfunc, self, arg1, arg2); + } +#endif + PyObject *result = __Pyx__CallUnboundCMethod2(cfunc, self, arg1, arg2); + __Pyx_CachedCFunction_SetFinishedInitializing(cfunc); + return result; +} +#endif +static PyObject* __Pyx__CallUnboundCMethod2(__Pyx_CachedCFunction* cfunc, PyObject* self, PyObject* arg1, PyObject* arg2){ + if (unlikely(!cfunc->func && !cfunc->method) && unlikely(__Pyx_TryUnpackUnboundCMethod(cfunc) < 0)) return NULL; +#if CYTHON_COMPILING_IN_CPYTHON + if (cfunc->func && (cfunc->flag & METH_VARARGS)) { + PyObject *result = NULL; + PyObject *args = PyTuple_New(2); + if (unlikely(!args)) return NULL; + Py_INCREF(arg1); + PyTuple_SET_ITEM(args, 0, arg1); + Py_INCREF(arg2); + PyTuple_SET_ITEM(args, 1, arg2); + if (cfunc->flag & METH_KEYWORDS) + result = __Pyx_CallCFunctionWithKeywords(cfunc, self, args, NULL); + else + result = __Pyx_CallCFunction(cfunc, self, args); + Py_DECREF(args); + return result; + } +#endif + { + PyObject *args[4] = {NULL, self, arg1, arg2}; + return __Pyx_PyObject_FastCall(cfunc->method, args+1, 3 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET); + } +} + +/* ParseKeywordsImpl (used by ParseKeywords) */ +static int __Pyx_ValidateDuplicatePosArgs( + PyObject *kwds, + PyObject ** const argnames[], + PyObject ** const *first_kw_arg, + const char* function_name) +{ + PyObject ** const *name = argnames; + while (name != first_kw_arg) { + PyObject *key = **name; + int found = PyDict_Contains(kwds, key); + if (unlikely(found)) { + if (found == 1) __Pyx_RaiseDoubleKeywordsError(function_name, key); + goto bad; + } + name++; + } + return 0; +bad: + return -1; +} +#if CYTHON_USE_UNICODE_INTERNALS +static CYTHON_INLINE int __Pyx_UnicodeKeywordsEqual(PyObject *s1, PyObject *s2) { + int kind; + Py_ssize_t len = PyUnicode_GET_LENGTH(s1); + if (len != PyUnicode_GET_LENGTH(s2)) return 0; + kind = PyUnicode_KIND(s1); + if (kind != PyUnicode_KIND(s2)) return 0; + const void *data1 = PyUnicode_DATA(s1); + const void *data2 = PyUnicode_DATA(s2); + return (memcmp(data1, data2, (size_t) len * (size_t) kind) == 0); +} +#endif +static int __Pyx_MatchKeywordArg_str( + PyObject *key, + PyObject ** const argnames[], + PyObject ** const *first_kw_arg, + size_t *index_found, + const char *function_name) +{ + PyObject ** const *name; + #if CYTHON_USE_UNICODE_INTERNALS + Py_hash_t key_hash = ((PyASCIIObject*)key)->hash; + if (unlikely(key_hash == -1)) { + key_hash = PyObject_Hash(key); + if (unlikely(key_hash == -1)) + goto bad; + } + #endif + name = first_kw_arg; + while (*name) { + PyObject *name_str = **name; + #if CYTHON_USE_UNICODE_INTERNALS + if (key_hash == ((PyASCIIObject*)name_str)->hash && __Pyx_UnicodeKeywordsEqual(name_str, key)) { + *index_found = (size_t) (name - argnames); + return 1; + } + #else + #if CYTHON_ASSUME_SAFE_SIZE + if (PyUnicode_GET_LENGTH(name_str) == PyUnicode_GET_LENGTH(key)) + #endif + { + int cmp = PyUnicode_Compare(name_str, key); + if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; + if (cmp == 0) { + *index_found = (size_t) (name - argnames); + return 1; + } + } + #endif + name++; + } + name = argnames; + while (name != first_kw_arg) { + PyObject *name_str = **name; + #if CYTHON_USE_UNICODE_INTERNALS + if (unlikely(key_hash == ((PyASCIIObject*)name_str)->hash)) { + if (__Pyx_UnicodeKeywordsEqual(name_str, key)) + goto arg_passed_twice; + } + #else + #if CYTHON_ASSUME_SAFE_SIZE + if (PyUnicode_GET_LENGTH(name_str) == PyUnicode_GET_LENGTH(key)) + #endif + { + if (unlikely(name_str == key)) goto arg_passed_twice; + int cmp = PyUnicode_Compare(name_str, key); + if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; + if (cmp == 0) goto arg_passed_twice; + } + #endif + name++; + } + return 0; +arg_passed_twice: + __Pyx_RaiseDoubleKeywordsError(function_name, key); + goto bad; +bad: + return -1; +} +static int __Pyx_MatchKeywordArg_nostr( + PyObject *key, + PyObject ** const argnames[], + PyObject ** const *first_kw_arg, + size_t *index_found, + const char *function_name) +{ + PyObject ** const *name; + if (unlikely(!PyUnicode_Check(key))) goto invalid_keyword_type; + name = first_kw_arg; + while (*name) { + int cmp = PyObject_RichCompareBool(**name, key, Py_EQ); + if (cmp == 1) { + *index_found = (size_t) (name - argnames); + return 1; + } + if (unlikely(cmp == -1)) goto bad; + name++; + } + name = argnames; + while (name != first_kw_arg) { + int cmp = PyObject_RichCompareBool(**name, key, Py_EQ); + if (unlikely(cmp != 0)) { + if (cmp == 1) goto arg_passed_twice; + else goto bad; + } + name++; + } + return 0; +arg_passed_twice: + __Pyx_RaiseDoubleKeywordsError(function_name, key); + goto bad; +invalid_keyword_type: + PyErr_Format(PyExc_TypeError, + "%.200s() keywords must be strings", function_name); + goto bad; +bad: + return -1; +} +static CYTHON_INLINE int __Pyx_MatchKeywordArg( + PyObject *key, + PyObject ** const argnames[], + PyObject ** const *first_kw_arg, + size_t *index_found, + const char *function_name) +{ + return likely(PyUnicode_CheckExact(key)) ? + __Pyx_MatchKeywordArg_str(key, argnames, first_kw_arg, index_found, function_name) : + __Pyx_MatchKeywordArg_nostr(key, argnames, first_kw_arg, index_found, function_name); +} +static void __Pyx_RejectUnknownKeyword( + PyObject *kwds, + PyObject ** const argnames[], + PyObject ** const *first_kw_arg, + const char *function_name) +{ + #if CYTHON_AVOID_BORROWED_REFS + PyObject *pos = NULL; + #else + Py_ssize_t pos = 0; + #endif + PyObject *key = NULL; + __Pyx_BEGIN_CRITICAL_SECTION(kwds); + while ( + #if CYTHON_AVOID_BORROWED_REFS + __Pyx_PyDict_NextRef(kwds, &pos, &key, NULL) + #else + PyDict_Next(kwds, &pos, &key, NULL) + #endif + ) { + PyObject** const *name = first_kw_arg; + while (*name && (**name != key)) name++; + if (!*name) { + size_t index_found = 0; + int cmp = __Pyx_MatchKeywordArg(key, argnames, first_kw_arg, &index_found, function_name); + if (cmp != 1) { + if (cmp == 0) { + PyErr_Format(PyExc_TypeError, + "%s() got an unexpected keyword argument '%U'", + function_name, key); + } + #if CYTHON_AVOID_BORROWED_REFS + Py_DECREF(key); + #endif + break; + } + } + #if CYTHON_AVOID_BORROWED_REFS + Py_DECREF(key); + #endif + } + __Pyx_END_CRITICAL_SECTION(); + #if CYTHON_AVOID_BORROWED_REFS + Py_XDECREF(pos); + #endif + assert(PyErr_Occurred()); +} +static int __Pyx_ParseKeywordDict( + PyObject *kwds, + PyObject ** const argnames[], + PyObject *values[], + Py_ssize_t num_pos_args, + Py_ssize_t num_kwargs, + const char* function_name, + int ignore_unknown_kwargs) +{ + PyObject** const *name; + PyObject** const *first_kw_arg = argnames + num_pos_args; + Py_ssize_t extracted = 0; +#if !CYTHON_COMPILING_IN_PYPY || defined(PyArg_ValidateKeywordArguments) + if (unlikely(!PyArg_ValidateKeywordArguments(kwds))) return -1; +#endif + name = first_kw_arg; + while (*name && num_kwargs > extracted) { + PyObject * key = **name; + PyObject *value; + int found = 0; + #if __PYX_LIMITED_VERSION_HEX >= 0x030d0000 + found = PyDict_GetItemRef(kwds, key, &value); + #else + value = PyDict_GetItemWithError(kwds, key); + if (value) { + Py_INCREF(value); + found = 1; + } else { + if (unlikely(PyErr_Occurred())) goto bad; + } + #endif + if (found) { + if (unlikely(found < 0)) goto bad; + values[name-argnames] = value; + extracted++; + } + name++; + } + if (num_kwargs > extracted) { + if (ignore_unknown_kwargs) { + if (unlikely(__Pyx_ValidateDuplicatePosArgs(kwds, argnames, first_kw_arg, function_name) == -1)) + goto bad; + } else { + __Pyx_RejectUnknownKeyword(kwds, argnames, first_kw_arg, function_name); + goto bad; + } + } + return 0; +bad: + return -1; +} +static int __Pyx_ParseKeywordDictToDict( + PyObject *kwds, + PyObject ** const argnames[], + PyObject *kwds2, + PyObject *values[], + Py_ssize_t num_pos_args, + const char* function_name) +{ + PyObject** const *name; + PyObject** const *first_kw_arg = argnames + num_pos_args; + Py_ssize_t len; +#if !CYTHON_COMPILING_IN_PYPY || defined(PyArg_ValidateKeywordArguments) + if (unlikely(!PyArg_ValidateKeywordArguments(kwds))) return -1; +#endif + if (PyDict_Update(kwds2, kwds) < 0) goto bad; + name = first_kw_arg; + while (*name) { + PyObject *key = **name; + PyObject *value; +#if !CYTHON_COMPILING_IN_LIMITED_API && (PY_VERSION_HEX >= 0x030d00A2 || defined(PyDict_Pop)) + int found = PyDict_Pop(kwds2, key, &value); + if (found) { + if (unlikely(found < 0)) goto bad; + values[name-argnames] = value; + } +#elif __PYX_LIMITED_VERSION_HEX >= 0x030d0000 + int found = PyDict_GetItemRef(kwds2, key, &value); + if (found) { + if (unlikely(found < 0)) goto bad; + values[name-argnames] = value; + if (unlikely(PyDict_DelItem(kwds2, key) < 0)) goto bad; + } +#else + #if CYTHON_COMPILING_IN_CPYTHON + value = _PyDict_Pop(kwds2, key, kwds2); + #else + value = __Pyx_CallUnboundCMethod2(&__pyx_mstate_global->__pyx_umethod_PyDict_Type_pop, kwds2, key, kwds2); + #endif + if (value == kwds2) { + Py_DECREF(value); + } else { + if (unlikely(!value)) goto bad; + values[name-argnames] = value; + } +#endif + name++; + } + len = PyDict_Size(kwds2); + if (len > 0) { + return __Pyx_ValidateDuplicatePosArgs(kwds, argnames, first_kw_arg, function_name); + } else if (unlikely(len == -1)) { + goto bad; + } + return 0; +bad: + return -1; +} +static int __Pyx_ParseKeywordsTuple( + PyObject *kwds, + PyObject * const *kwvalues, + PyObject ** const argnames[], + PyObject *kwds2, + PyObject *values[], + Py_ssize_t num_pos_args, + Py_ssize_t num_kwargs, + const char* function_name, + int ignore_unknown_kwargs) +{ + PyObject *key = NULL; + PyObject** const * name; + PyObject** const *first_kw_arg = argnames + num_pos_args; + for (Py_ssize_t pos = 0; pos < num_kwargs; pos++) { +#if CYTHON_AVOID_BORROWED_REFS + key = __Pyx_PySequence_ITEM(kwds, pos); +#else + key = __Pyx_PyTuple_GET_ITEM(kwds, pos); +#endif +#if !CYTHON_ASSUME_SAFE_MACROS + if (unlikely(!key)) goto bad; +#endif + name = first_kw_arg; + while (*name && (**name != key)) name++; + if (*name) { + PyObject *value = kwvalues[pos]; + values[name-argnames] = __Pyx_NewRef(value); + } else { + size_t index_found = 0; + int cmp = __Pyx_MatchKeywordArg(key, argnames, first_kw_arg, &index_found, function_name); + if (cmp == 1) { + PyObject *value = kwvalues[pos]; + values[index_found] = __Pyx_NewRef(value); + } else { + if (unlikely(cmp == -1)) goto bad; + if (kwds2) { + PyObject *value = kwvalues[pos]; + if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; + } else if (!ignore_unknown_kwargs) { + goto invalid_keyword; + } + } + } + #if CYTHON_AVOID_BORROWED_REFS + Py_DECREF(key); + key = NULL; + #endif + } + return 0; +invalid_keyword: + PyErr_Format(PyExc_TypeError, + "%s() got an unexpected keyword argument '%U'", + function_name, key); + goto bad; +bad: + #if CYTHON_AVOID_BORROWED_REFS + Py_XDECREF(key); + #endif + return -1; +} + +/* ParseKeywords */ +static int __Pyx_ParseKeywords( + PyObject *kwds, + PyObject * const *kwvalues, + PyObject ** const argnames[], + PyObject *kwds2, + PyObject *values[], + Py_ssize_t num_pos_args, + Py_ssize_t num_kwargs, + const char* function_name, + int ignore_unknown_kwargs) +{ + if (CYTHON_METH_FASTCALL && likely(PyTuple_Check(kwds))) + return __Pyx_ParseKeywordsTuple(kwds, kwvalues, argnames, kwds2, values, num_pos_args, num_kwargs, function_name, ignore_unknown_kwargs); + else if (kwds2) + return __Pyx_ParseKeywordDictToDict(kwds, argnames, kwds2, values, num_pos_args, function_name); + else + return __Pyx_ParseKeywordDict(kwds, argnames, values, num_pos_args, num_kwargs, function_name, ignore_unknown_kwargs); +} + +/* RaiseArgTupleInvalid */ +static void __Pyx_RaiseArgtupleInvalid( + const char* func_name, + int exact, + Py_ssize_t num_min, + Py_ssize_t num_max, + Py_ssize_t num_found) +{ + Py_ssize_t num_expected; + const char *more_or_less; + if (num_found < num_min) { + num_expected = num_min; + more_or_less = "at least"; + } else { + num_expected = num_max; + more_or_less = "at most"; + } + if (exact) { + more_or_less = "exactly"; + } + PyErr_Format(PyExc_TypeError, + "%.200s() takes %.8s %" CYTHON_FORMAT_SSIZE_T "d positional argument%.1s (%" CYTHON_FORMAT_SSIZE_T "d given)", + func_name, more_or_less, num_expected, + (num_expected == 1) ? "" : "s", num_found); +} + +/* ArgTypeTestFunc (used by ArgTypeTest) */ +static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *name, int exact) +{ + __Pyx_TypeName type_name; + __Pyx_TypeName obj_type_name; + PyObject *extra_info = __pyx_mstate_global->__pyx_empty_unicode; + int from_annotation_subclass = 0; + if (unlikely(!type)) { + PyErr_SetString(PyExc_SystemError, "Missing type object"); + return 0; + } + else if (!exact) { + if (likely(__Pyx_TypeCheck(obj, type))) return 1; + } else if (exact == 2) { + if (__Pyx_TypeCheck(obj, type)) { + from_annotation_subclass = 1; + extra_info = __pyx_mstate_global->__pyx_kp_u_Note_that_Cython_is_deliberately; + } + } + type_name = __Pyx_PyType_GetFullyQualifiedName(type); + obj_type_name = __Pyx_PyType_GetFullyQualifiedName(Py_TYPE(obj)); + PyErr_Format(PyExc_TypeError, + "Argument '%.200s' has incorrect type (expected " __Pyx_FMT_TYPENAME + ", got " __Pyx_FMT_TYPENAME ")" +#if __PYX_LIMITED_VERSION_HEX < 0x030C0000 + "%s%U" +#endif + , name, type_name, obj_type_name +#if __PYX_LIMITED_VERSION_HEX < 0x030C0000 + , (from_annotation_subclass ? ". " : ""), extra_info +#endif + ); +#if __PYX_LIMITED_VERSION_HEX >= 0x030C0000 + if (exact == 2 && from_annotation_subclass) { + PyObject *res; + PyObject *vargs[2]; + vargs[0] = PyErr_GetRaisedException(); + vargs[1] = extra_info; + res = PyObject_VectorcallMethod(__pyx_mstate_global->__pyx_kp_u_add_note, vargs, 2, NULL); + Py_XDECREF(res); + PyErr_SetRaisedException(vargs[0]); + } +#endif + __Pyx_DECREF_TypeName(type_name); + __Pyx_DECREF_TypeName(obj_type_name); + return 0; +} + +/* PyErrExceptionMatches (used by PyObjectGetAttrStrNoError) */ +#if CYTHON_FAST_THREAD_STATE +static int __Pyx_PyErr_ExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { + Py_ssize_t i, n; + n = PyTuple_GET_SIZE(tuple); + for (i=0; i= 0x030C00A6 + PyObject *current_exception = tstate->current_exception; + if (unlikely(!current_exception)) return 0; + exc_type = (PyObject*) Py_TYPE(current_exception); + if (exc_type == err) return 1; +#else + exc_type = tstate->curexc_type; + if (exc_type == err) return 1; + if (unlikely(!exc_type)) return 0; +#endif + #if CYTHON_AVOID_BORROWED_REFS + Py_INCREF(exc_type); + #endif + if (unlikely(PyTuple_Check(err))) { + result = __Pyx_PyErr_ExceptionMatchesTuple(exc_type, err); + } else { + result = __Pyx_PyErr_GivenExceptionMatches(exc_type, err); + } + #if CYTHON_AVOID_BORROWED_REFS + Py_DECREF(exc_type); + #endif + return result; +} +#endif + +/* PyErrFetchRestore (used by PyObjectGetAttrStrNoError) */ +#if CYTHON_FAST_THREAD_STATE +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { +#if PY_VERSION_HEX >= 0x030C00A6 + PyObject *tmp_value; + assert(type == NULL || (value != NULL && type == (PyObject*) Py_TYPE(value))); + if (value) { + #if CYTHON_COMPILING_IN_CPYTHON + if (unlikely(((PyBaseExceptionObject*) value)->traceback != tb)) + #endif + PyException_SetTraceback(value, tb); + } + tmp_value = tstate->current_exception; + tstate->current_exception = value; + Py_XDECREF(tmp_value); + Py_XDECREF(type); + Py_XDECREF(tb); +#else + PyObject *tmp_type, *tmp_value, *tmp_tb; + tmp_type = tstate->curexc_type; + tmp_value = tstate->curexc_value; + tmp_tb = tstate->curexc_traceback; + tstate->curexc_type = type; + tstate->curexc_value = value; + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +#endif +} +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { +#if PY_VERSION_HEX >= 0x030C00A6 + PyObject* exc_value; + exc_value = tstate->current_exception; + tstate->current_exception = 0; + *value = exc_value; + *type = NULL; + *tb = NULL; + if (exc_value) { + *type = (PyObject*) Py_TYPE(exc_value); + Py_INCREF(*type); + #if CYTHON_COMPILING_IN_CPYTHON + *tb = ((PyBaseExceptionObject*) exc_value)->traceback; + Py_XINCREF(*tb); + #else + *tb = PyException_GetTraceback(exc_value); + #endif + } +#else + *type = tstate->curexc_type; + *value = tstate->curexc_value; + *tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; +#endif +} +#endif + +/* PyObjectGetAttrStrNoError (used by GetBuiltinName) */ +#if __PYX_LIMITED_VERSION_HEX < 0x030d0000 +static void __Pyx_PyObject_GetAttrStr_ClearAttributeError(void) { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + if (likely(__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError))) + __Pyx_PyErr_Clear(); +} +#endif +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name) { + PyObject *result; +#if __PYX_LIMITED_VERSION_HEX >= 0x030d0000 + (void) PyObject_GetOptionalAttr(obj, attr_name, &result); + return result; +#else +#if CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_TYPE_SLOTS + PyTypeObject* tp = Py_TYPE(obj); + if (likely(tp->tp_getattro == PyObject_GenericGetAttr)) { + return _PyObject_GenericGetAttrWithDict(obj, attr_name, NULL, 1); + } +#endif + result = __Pyx_PyObject_GetAttrStr(obj, attr_name); + if (unlikely(!result)) { + __Pyx_PyObject_GetAttrStr_ClearAttributeError(); + } + return result; +#endif +} + +/* GetBuiltinName */ +static PyObject *__Pyx_GetBuiltinName(PyObject *name) { + PyObject* result = __Pyx_PyObject_GetAttrStrNoError(__pyx_mstate_global->__pyx_b, name); + if (unlikely(!result) && !PyErr_Occurred()) { + PyErr_Format(PyExc_NameError, + "name '%U' is not defined", name); + } + return result; +} + +/* RaiseException */ +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { + PyObject* owned_instance = NULL; + if (tb == Py_None) { + tb = 0; + } else if (tb && !PyTraceBack_Check(tb)) { + PyErr_SetString(PyExc_TypeError, + "raise: arg 3 must be a traceback or None"); + goto bad; + } + if (value == Py_None) + value = 0; + if (PyExceptionInstance_Check(type)) { + if (value) { + PyErr_SetString(PyExc_TypeError, + "instance exception may not have a separate value"); + goto bad; + } + value = type; + type = (PyObject*) Py_TYPE(value); + } else if (PyExceptionClass_Check(type)) { + PyObject *instance_class = NULL; + if (value && PyExceptionInstance_Check(value)) { + instance_class = (PyObject*) Py_TYPE(value); + if (instance_class != type) { + int is_subclass = PyObject_IsSubclass(instance_class, type); + if (!is_subclass) { + instance_class = NULL; + } else if (unlikely(is_subclass == -1)) { + goto bad; + } else { + type = instance_class; + } + } + } + if (!instance_class) { + PyObject *args; + if (!value) + args = PyTuple_New(0); + else if (PyTuple_Check(value)) { + Py_INCREF(value); + args = value; + } else + args = PyTuple_Pack(1, value); + if (!args) + goto bad; + owned_instance = PyObject_Call(type, args, NULL); + Py_DECREF(args); + if (!owned_instance) + goto bad; + value = owned_instance; + if (!PyExceptionInstance_Check(value)) { + PyErr_Format(PyExc_TypeError, + "calling %R should have returned an instance of " + "BaseException, not %R", + type, Py_TYPE(value)); + goto bad; + } + } + } else { + PyErr_SetString(PyExc_TypeError, + "raise: exception class must be a subclass of BaseException"); + goto bad; + } + if (cause) { + PyObject *fixed_cause; + if (cause == Py_None) { + fixed_cause = NULL; + } else if (PyExceptionClass_Check(cause)) { + fixed_cause = PyObject_CallObject(cause, NULL); + if (fixed_cause == NULL) + goto bad; + } else if (PyExceptionInstance_Check(cause)) { + fixed_cause = cause; + Py_INCREF(fixed_cause); + } else { + PyErr_SetString(PyExc_TypeError, + "exception causes must derive from " + "BaseException"); + goto bad; + } + PyException_SetCause(value, fixed_cause); + } + PyErr_SetObject(type, value); + if (tb) { +#if PY_VERSION_HEX >= 0x030C00A6 + PyException_SetTraceback(value, tb); +#elif CYTHON_FAST_THREAD_STATE + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject* tmp_tb = tstate->curexc_traceback; + if (tb != tmp_tb) { + Py_INCREF(tb); + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_tb); + } +#else + PyObject *tmp_type, *tmp_value, *tmp_tb; + PyErr_Fetch(&tmp_type, &tmp_value, &tmp_tb); + Py_INCREF(tb); + PyErr_Restore(tmp_type, tmp_value, tb); + Py_XDECREF(tmp_tb); +#endif + } +bad: + Py_XDECREF(owned_instance); + return; +} + +/* PyObjectFastCallMethod */ +#if !CYTHON_VECTORCALL || PY_VERSION_HEX < 0x03090000 +static PyObject *__Pyx_PyObject_FastCallMethod(PyObject *name, PyObject *const *args, size_t nargsf) { + PyObject *result; + PyObject *attr = PyObject_GetAttr(args[0], name); + if (unlikely(!attr)) + return NULL; + result = __Pyx_PyObject_FastCall(attr, args+1, nargsf - 1); + Py_DECREF(attr); + return result; +} +#endif + +/* RaiseUnexpectedTypeError */ +static int +__Pyx_RaiseUnexpectedTypeError(const char *expected, PyObject *obj) +{ + __Pyx_TypeName obj_type_name = __Pyx_PyType_GetFullyQualifiedName(Py_TYPE(obj)); + PyErr_Format(PyExc_TypeError, "Expected %s, got " __Pyx_FMT_TYPENAME, + expected, obj_type_name); + __Pyx_DECREF_TypeName(obj_type_name); + return 0; +} + +/* CIntToDigits (used by CIntToPyUnicode) */ +static const char DIGIT_PAIRS_10[2*10*10+1] = { + "00010203040506070809" + "10111213141516171819" + "20212223242526272829" + "30313233343536373839" + "40414243444546474849" + "50515253545556575859" + "60616263646566676869" + "70717273747576777879" + "80818283848586878889" + "90919293949596979899" +}; +static const char DIGIT_PAIRS_8[2*8*8+1] = { + "0001020304050607" + "1011121314151617" + "2021222324252627" + "3031323334353637" + "4041424344454647" + "5051525354555657" + "6061626364656667" + "7071727374757677" +}; +static const char DIGITS_HEX[2*16+1] = { + "0123456789abcdef" + "0123456789ABCDEF" +}; + +/* BuildPyUnicode (used by COrdinalToPyUnicode) */ +static PyObject* __Pyx_PyUnicode_BuildFromAscii(Py_ssize_t ulength, const char* chars, int clength, + int prepend_sign, char padding_char) { + PyObject *uval; + Py_ssize_t uoffset = ulength - clength; +#if CYTHON_USE_UNICODE_INTERNALS + Py_ssize_t i; + void *udata; + uval = PyUnicode_New(ulength, 127); + if (unlikely(!uval)) return NULL; + udata = PyUnicode_DATA(uval); + if (uoffset > 0) { + i = 0; + if (prepend_sign) { + __Pyx_PyUnicode_WRITE(PyUnicode_1BYTE_KIND, udata, 0, '-'); + i++; + } + for (; i < uoffset; i++) { + __Pyx_PyUnicode_WRITE(PyUnicode_1BYTE_KIND, udata, i, padding_char); + } + } + for (i=0; i < clength; i++) { + __Pyx_PyUnicode_WRITE(PyUnicode_1BYTE_KIND, udata, uoffset+i, chars[i]); + } +#else + { + PyObject *sign = NULL, *padding = NULL; + uval = NULL; + if (uoffset > 0) { + prepend_sign = !!prepend_sign; + if (uoffset > prepend_sign) { + padding = PyUnicode_FromOrdinal(padding_char); + if (likely(padding) && uoffset > prepend_sign + 1) { + PyObject *tmp = PySequence_Repeat(padding, uoffset - prepend_sign); + Py_DECREF(padding); + padding = tmp; + } + if (unlikely(!padding)) goto done_or_error; + } + if (prepend_sign) { + sign = PyUnicode_FromOrdinal('-'); + if (unlikely(!sign)) goto done_or_error; + } + } + uval = PyUnicode_DecodeASCII(chars, clength, NULL); + if (likely(uval) && padding) { + PyObject *tmp = PyUnicode_Concat(padding, uval); + Py_DECREF(uval); + uval = tmp; + } + if (likely(uval) && sign) { + PyObject *tmp = PyUnicode_Concat(sign, uval); + Py_DECREF(uval); + uval = tmp; + } +done_or_error: + Py_XDECREF(padding); + Py_XDECREF(sign); + } +#endif + return uval; +} + +/* COrdinalToPyUnicode (used by CIntToPyUnicode) */ +static CYTHON_INLINE int __Pyx_CheckUnicodeValue(int value) { + return value <= 1114111; +} +static PyObject* __Pyx_PyUnicode_FromOrdinal_Padded(int value, Py_ssize_t ulength, char padding_char) { + Py_ssize_t padding_length = ulength - 1; + if (likely((padding_length <= 250) && (value < 0xD800 || value > 0xDFFF))) { + char chars[256]; + if (value <= 255) { + memset(chars, padding_char, (size_t) padding_length); + chars[ulength-1] = (char) value; + return PyUnicode_DecodeLatin1(chars, ulength, NULL); + } + char *cpos = chars + sizeof(chars); + if (value < 0x800) { + *--cpos = (char) (0x80 | (value & 0x3f)); + value >>= 6; + *--cpos = (char) (0xc0 | (value & 0x1f)); + } else if (value < 0x10000) { + *--cpos = (char) (0x80 | (value & 0x3f)); + value >>= 6; + *--cpos = (char) (0x80 | (value & 0x3f)); + value >>= 6; + *--cpos = (char) (0xe0 | (value & 0x0f)); + } else { + *--cpos = (char) (0x80 | (value & 0x3f)); + value >>= 6; + *--cpos = (char) (0x80 | (value & 0x3f)); + value >>= 6; + *--cpos = (char) (0x80 | (value & 0x3f)); + value >>= 6; + *--cpos = (char) (0xf0 | (value & 0x07)); + } + cpos -= padding_length; + memset(cpos, padding_char, (size_t) padding_length); + return PyUnicode_DecodeUTF8(cpos, chars + sizeof(chars) - cpos, NULL); + } + if (value <= 127 && CYTHON_USE_UNICODE_INTERNALS) { + const char chars[1] = {(char) value}; + return __Pyx_PyUnicode_BuildFromAscii(ulength, chars, 1, 0, padding_char); + } + { + PyObject *uchar, *padding_uchar, *padding, *result; + padding_uchar = PyUnicode_FromOrdinal(padding_char); + if (unlikely(!padding_uchar)) return NULL; + padding = PySequence_Repeat(padding_uchar, padding_length); + Py_DECREF(padding_uchar); + if (unlikely(!padding)) return NULL; + uchar = PyUnicode_FromOrdinal(value); + if (unlikely(!uchar)) { + Py_DECREF(padding); + return NULL; + } + result = PyUnicode_Concat(padding, uchar); + Py_DECREF(padding); + Py_DECREF(uchar); + return result; + } +} + +/* CIntToPyUnicode */ +static CYTHON_INLINE PyObject* __Pyx_uchar___Pyx_PyUnicode_From_int(int value, Py_ssize_t width, char padding_char) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const int neg_one = (int) -1, const_zero = (int) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (unlikely(!(is_unsigned || value == 0 || value > 0) || + !(sizeof(value) <= 2 || value & ~ (int) 0x01fffff || __Pyx_CheckUnicodeValue((int) value)))) { + PyErr_SetString(PyExc_OverflowError, "%c arg not in range(0x110000)"); + return NULL; + } + if (width <= 1) { + return PyUnicode_FromOrdinal((int) value); + } + return __Pyx_PyUnicode_FromOrdinal_Padded((int) value, width, padding_char); +} +static CYTHON_INLINE PyObject* __Pyx____Pyx_PyUnicode_From_int(int value, Py_ssize_t width, char padding_char, char format_char) { + char digits[sizeof(int)*3+2]; + char *dpos, *end = digits + sizeof(int)*3+2; + const char *hex_digits = DIGITS_HEX; + Py_ssize_t length, ulength; + int prepend_sign, last_one_off; + int remaining; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const int neg_one = (int) -1, const_zero = (int) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (format_char == 'X') { + hex_digits += 16; + format_char = 'x'; + } + remaining = value; + last_one_off = 0; + dpos = end; + do { + int digit_pos; + switch (format_char) { + case 'o': + digit_pos = abs((int)(remaining % (8*8))); + remaining = (int) (remaining / (8*8)); + dpos -= 2; + memcpy(dpos, DIGIT_PAIRS_8 + digit_pos * 2, 2); + last_one_off = (digit_pos < 8); + break; + case 'd': + digit_pos = abs((int)(remaining % (10*10))); + remaining = (int) (remaining / (10*10)); + dpos -= 2; + memcpy(dpos, DIGIT_PAIRS_10 + digit_pos * 2, 2); + last_one_off = (digit_pos < 10); + break; + case 'x': + *(--dpos) = hex_digits[abs((int)(remaining % 16))]; + remaining = (int) (remaining / 16); + break; + default: + assert(0); + break; + } + } while (unlikely(remaining != 0)); + assert(!last_one_off || *dpos == '0'); + dpos += last_one_off; + length = end - dpos; + ulength = length; + prepend_sign = 0; + if (!is_unsigned && value <= neg_one) { + if (padding_char == ' ' || width <= length + 1) { + *(--dpos) = '-'; + ++length; + } else { + prepend_sign = 1; + } + ++ulength; + } + if (width > ulength) { + ulength = width; + } + if (ulength == 1) { + return PyUnicode_FromOrdinal(*dpos); + } + return __Pyx_PyUnicode_BuildFromAscii(ulength, dpos, (int) length, prepend_sign, padding_char); +} + +/* CIntToPyUnicode */ +static CYTHON_INLINE PyObject* __Pyx_uchar___Pyx_PyUnicode_From_Py_ssize_t(Py_ssize_t value, Py_ssize_t width, char padding_char) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const Py_ssize_t neg_one = (Py_ssize_t) -1, const_zero = (Py_ssize_t) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (unlikely(!(is_unsigned || value == 0 || value > 0) || + !(sizeof(value) <= 2 || value & ~ (Py_ssize_t) 0x01fffff || __Pyx_CheckUnicodeValue((int) value)))) { + PyErr_SetString(PyExc_OverflowError, "%c arg not in range(0x110000)"); + return NULL; + } + if (width <= 1) { + return PyUnicode_FromOrdinal((int) value); + } + return __Pyx_PyUnicode_FromOrdinal_Padded((int) value, width, padding_char); +} +static CYTHON_INLINE PyObject* __Pyx____Pyx_PyUnicode_From_Py_ssize_t(Py_ssize_t value, Py_ssize_t width, char padding_char, char format_char) { + char digits[sizeof(Py_ssize_t)*3+2]; + char *dpos, *end = digits + sizeof(Py_ssize_t)*3+2; + const char *hex_digits = DIGITS_HEX; + Py_ssize_t length, ulength; + int prepend_sign, last_one_off; + Py_ssize_t remaining; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const Py_ssize_t neg_one = (Py_ssize_t) -1, const_zero = (Py_ssize_t) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (format_char == 'X') { + hex_digits += 16; + format_char = 'x'; + } + remaining = value; + last_one_off = 0; + dpos = end; + do { + int digit_pos; + switch (format_char) { + case 'o': + digit_pos = abs((int)(remaining % (8*8))); + remaining = (Py_ssize_t) (remaining / (8*8)); + dpos -= 2; + memcpy(dpos, DIGIT_PAIRS_8 + digit_pos * 2, 2); + last_one_off = (digit_pos < 8); + break; + case 'd': + digit_pos = abs((int)(remaining % (10*10))); + remaining = (Py_ssize_t) (remaining / (10*10)); + dpos -= 2; + memcpy(dpos, DIGIT_PAIRS_10 + digit_pos * 2, 2); + last_one_off = (digit_pos < 10); + break; + case 'x': + *(--dpos) = hex_digits[abs((int)(remaining % 16))]; + remaining = (Py_ssize_t) (remaining / 16); + break; + default: + assert(0); + break; + } + } while (unlikely(remaining != 0)); + assert(!last_one_off || *dpos == '0'); + dpos += last_one_off; + length = end - dpos; + ulength = length; + prepend_sign = 0; + if (!is_unsigned && value <= neg_one) { + if (padding_char == ' ' || width <= length + 1) { + *(--dpos) = '-'; + ++length; + } else { + prepend_sign = 1; + } + ++ulength; + } + if (width > ulength) { + ulength = width; + } + if (ulength == 1) { + return PyUnicode_FromOrdinal(*dpos); + } + return __Pyx_PyUnicode_BuildFromAscii(ulength, dpos, (int) length, prepend_sign, padding_char); +} + +/* JoinPyUnicode */ +static PyObject* __Pyx_PyUnicode_Join(PyObject** values, Py_ssize_t value_count, Py_ssize_t result_ulength, + Py_UCS4 max_char) { +#if CYTHON_USE_UNICODE_INTERNALS && CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + PyObject *result_uval; + int result_ukind, kind_shift; + Py_ssize_t i, char_pos; + void *result_udata; + if (max_char > 1114111) max_char = 1114111; + result_uval = PyUnicode_New(result_ulength, max_char); + if (unlikely(!result_uval)) return NULL; + result_ukind = (max_char <= 255) ? PyUnicode_1BYTE_KIND : (max_char <= 65535) ? PyUnicode_2BYTE_KIND : PyUnicode_4BYTE_KIND; + kind_shift = (result_ukind == PyUnicode_4BYTE_KIND) ? 2 : result_ukind - 1; + result_udata = PyUnicode_DATA(result_uval); + assert(kind_shift == 2 || kind_shift == 1 || kind_shift == 0); + if (unlikely((PY_SSIZE_T_MAX >> kind_shift) - result_ulength < 0)) + goto overflow; + char_pos = 0; + for (i=0; i < value_count; i++) { + int ukind; + Py_ssize_t ulength; + void *udata; + PyObject *uval = values[i]; + #if !CYTHON_COMPILING_IN_LIMITED_API + if (__Pyx_PyUnicode_READY(uval) == (-1)) + goto bad; + #endif + ulength = __Pyx_PyUnicode_GET_LENGTH(uval); + #if !CYTHON_ASSUME_SAFE_SIZE + if (unlikely(ulength < 0)) goto bad; + #endif + if (unlikely(!ulength)) + continue; + if (unlikely((PY_SSIZE_T_MAX >> kind_shift) - ulength < char_pos)) + goto overflow; + ukind = __Pyx_PyUnicode_KIND(uval); + udata = __Pyx_PyUnicode_DATA(uval); + if (ukind == result_ukind) { + memcpy((char *)result_udata + (char_pos << kind_shift), udata, (size_t) (ulength << kind_shift)); + } else { + #if PY_VERSION_HEX >= 0x030d0000 + if (unlikely(PyUnicode_CopyCharacters(result_uval, char_pos, uval, 0, ulength) < 0)) goto bad; + #elif CYTHON_COMPILING_IN_CPYTHON || defined(_PyUnicode_FastCopyCharacters) + _PyUnicode_FastCopyCharacters(result_uval, char_pos, uval, 0, ulength); + #else + Py_ssize_t j; + for (j=0; j < ulength; j++) { + Py_UCS4 uchar = __Pyx_PyUnicode_READ(ukind, udata, j); + __Pyx_PyUnicode_WRITE(result_ukind, result_udata, char_pos+j, uchar); + } + #endif + } + char_pos += ulength; + } + return result_uval; +overflow: + PyErr_SetString(PyExc_OverflowError, "join() result is too long for a Python string"); +bad: + Py_DECREF(result_uval); + return NULL; +#else + Py_ssize_t i; + PyObject *result = NULL; + PyObject *value_tuple = PyTuple_New(value_count); + if (unlikely(!value_tuple)) return NULL; + CYTHON_UNUSED_VAR(max_char); + CYTHON_UNUSED_VAR(result_ulength); + for (i=0; i__pyx_empty_unicode, value_tuple); +bad: + Py_DECREF(value_tuple); + return result; +#endif +} + +/* GetAttr */ +static CYTHON_INLINE PyObject *__Pyx_GetAttr(PyObject *o, PyObject *n) { +#if CYTHON_USE_TYPE_SLOTS + if (likely(PyUnicode_Check(n))) + return __Pyx_PyObject_GetAttrStr(o, n); +#endif + return PyObject_GetAttr(o, n); +} + +/* GetItemInt */ +static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) { + PyObject *r; + if (unlikely(!j)) return NULL; + r = PyObject_GetItem(o, j); + Py_DECREF(j); + return r; +} +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, + int wraparound, int boundscheck, int unsafe_shared) { + CYTHON_MAYBE_UNUSED_VAR(unsafe_shared); +#if CYTHON_ASSUME_SAFE_SIZE + Py_ssize_t wrapped_i = i; + if (wraparound & unlikely(i < 0)) { + wrapped_i += PyList_GET_SIZE(o); + } + if ((CYTHON_AVOID_BORROWED_REFS || CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS || !CYTHON_ASSUME_SAFE_MACROS)) { + return __Pyx_PyList_GetItemRefFast(o, wrapped_i, unsafe_shared); + } else + if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyList_GET_SIZE(o)))) { + return __Pyx_NewRef(PyList_GET_ITEM(o, wrapped_i)); + } + return __Pyx_GetItemInt_Generic(o, PyLong_FromSsize_t(i)); +#else + (void)wraparound; + (void)boundscheck; + return PySequence_GetItem(o, i); +#endif +} +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, + int wraparound, int boundscheck, int unsafe_shared) { + CYTHON_MAYBE_UNUSED_VAR(unsafe_shared); +#if CYTHON_ASSUME_SAFE_SIZE && CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + Py_ssize_t wrapped_i = i; + if (wraparound & unlikely(i < 0)) { + wrapped_i += PyTuple_GET_SIZE(o); + } + if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyTuple_GET_SIZE(o)))) { + return __Pyx_NewRef(PyTuple_GET_ITEM(o, wrapped_i)); + } + return __Pyx_GetItemInt_Generic(o, PyLong_FromSsize_t(i)); +#else + (void)wraparound; + (void)boundscheck; + return PySequence_GetItem(o, i); +#endif +} +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int is_list, + int wraparound, int boundscheck, int unsafe_shared) { + CYTHON_MAYBE_UNUSED_VAR(unsafe_shared); +#if CYTHON_ASSUME_SAFE_MACROS && CYTHON_ASSUME_SAFE_SIZE + if (is_list || PyList_CheckExact(o)) { + Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyList_GET_SIZE(o); + if ((CYTHON_AVOID_BORROWED_REFS || CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS)) { + return __Pyx_PyList_GetItemRefFast(o, n, unsafe_shared); + } else if ((!boundscheck) || (likely(__Pyx_is_valid_index(n, PyList_GET_SIZE(o))))) { + return __Pyx_NewRef(PyList_GET_ITEM(o, n)); + } + } else + #if !CYTHON_AVOID_BORROWED_REFS + if (PyTuple_CheckExact(o)) { + Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyTuple_GET_SIZE(o); + if ((!boundscheck) || likely(__Pyx_is_valid_index(n, PyTuple_GET_SIZE(o)))) { + return __Pyx_NewRef(PyTuple_GET_ITEM(o, n)); + } + } else + #endif +#endif +#if CYTHON_USE_TYPE_SLOTS && !CYTHON_COMPILING_IN_PYPY + { + PyMappingMethods *mm = Py_TYPE(o)->tp_as_mapping; + PySequenceMethods *sm = Py_TYPE(o)->tp_as_sequence; + if (!is_list && mm && mm->mp_subscript) { + PyObject *r, *key = PyLong_FromSsize_t(i); + if (unlikely(!key)) return NULL; + r = mm->mp_subscript(o, key); + Py_DECREF(key); + return r; + } + if (is_list || likely(sm && sm->sq_item)) { + if (wraparound && unlikely(i < 0) && likely(sm->sq_length)) { + Py_ssize_t l = sm->sq_length(o); + if (likely(l >= 0)) { + i += l; + } else { + if (!PyErr_ExceptionMatches(PyExc_OverflowError)) + return NULL; + PyErr_Clear(); + } + } + return sm->sq_item(o, i); + } + } +#else + if (is_list || !PyMapping_Check(o)) { + return PySequence_GetItem(o, i); + } +#endif + (void)wraparound; + (void)boundscheck; + return __Pyx_GetItemInt_Generic(o, PyLong_FromSsize_t(i)); +} + +/* ObjectGetItem */ +#if CYTHON_USE_TYPE_SLOTS +static PyObject *__Pyx_PyObject_GetIndex(PyObject *obj, PyObject *index) { + PyObject *runerr = NULL; + Py_ssize_t key_value; + key_value = __Pyx_PyIndex_AsSsize_t(index); + if (likely(key_value != -1 || !(runerr = PyErr_Occurred()))) { + return __Pyx_GetItemInt_Fast(obj, key_value, 0, 1, 1, 1); + } + if (PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError)) { + __Pyx_TypeName index_type_name = __Pyx_PyType_GetFullyQualifiedName(Py_TYPE(index)); + PyErr_Clear(); + PyErr_Format(PyExc_IndexError, + "cannot fit '" __Pyx_FMT_TYPENAME "' into an index-sized integer", index_type_name); + __Pyx_DECREF_TypeName(index_type_name); + } + return NULL; +} +static PyObject *__Pyx_PyObject_GetItem_Slow(PyObject *obj, PyObject *key) { + __Pyx_TypeName obj_type_name; + if (likely(PyType_Check(obj))) { + PyObject *meth = __Pyx_PyObject_GetAttrStrNoError(obj, __pyx_mstate_global->__pyx_n_u_class_getitem); + if (!meth) { + PyErr_Clear(); + } else { + PyObject *result = __Pyx_PyObject_CallOneArg(meth, key); + Py_DECREF(meth); + return result; + } + } + obj_type_name = __Pyx_PyType_GetFullyQualifiedName(Py_TYPE(obj)); + PyErr_Format(PyExc_TypeError, + "'" __Pyx_FMT_TYPENAME "' object is not subscriptable", obj_type_name); + __Pyx_DECREF_TypeName(obj_type_name); + return NULL; +} +static PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject *key) { + PyTypeObject *tp = Py_TYPE(obj); + PyMappingMethods *mm = tp->tp_as_mapping; + PySequenceMethods *sm = tp->tp_as_sequence; + if (likely(mm && mm->mp_subscript)) { + return mm->mp_subscript(obj, key); + } + if (likely(sm && sm->sq_item)) { + return __Pyx_PyObject_GetIndex(obj, key); + } + return __Pyx_PyObject_GetItem_Slow(obj, key); +} +#endif + +/* RejectKeywords */ +static void __Pyx_RejectKeywords(const char* function_name, PyObject *kwds) { + PyObject *key = NULL; + if (CYTHON_METH_FASTCALL && likely(PyTuple_Check(kwds))) { + key = __Pyx_PySequence_ITEM(kwds, 0); + } else { +#if CYTHON_AVOID_BORROWED_REFS + PyObject *pos = NULL; +#else + Py_ssize_t pos = 0; +#endif +#if !CYTHON_COMPILING_IN_PYPY || defined(PyArg_ValidateKeywordArguments) + if (unlikely(!PyArg_ValidateKeywordArguments(kwds))) return; +#endif + __Pyx_PyDict_NextRef(kwds, &pos, &key, NULL); +#if CYTHON_AVOID_BORROWED_REFS + Py_XDECREF(pos); +#endif + } + if (likely(key)) { + PyErr_Format(PyExc_TypeError, + "%s() got an unexpected keyword argument '%U'", + function_name, key); + Py_DECREF(key); + } +} + +/* DivInt[Py_ssize_t] */ +static CYTHON_INLINE Py_ssize_t __Pyx_div_Py_ssize_t(Py_ssize_t a, Py_ssize_t b, int b_is_constant) { + Py_ssize_t q = a / b; + Py_ssize_t r = a - q*b; + Py_ssize_t adapt_python = (b_is_constant ? + ((r != 0) & ((r < 0) ^ (b < 0))) : + ((r != 0) & ((r ^ b) < 0)) + ); + return q - adapt_python; +} + +/* GetAttr3 */ +#if __PYX_LIMITED_VERSION_HEX < 0x030d0000 +static PyObject *__Pyx_GetAttr3Default(PyObject *d) { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + if (unlikely(!__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError))) + return NULL; + __Pyx_PyErr_Clear(); + Py_INCREF(d); + return d; +} +#endif +static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *o, PyObject *n, PyObject *d) { + PyObject *r; +#if __PYX_LIMITED_VERSION_HEX >= 0x030d0000 + int res = PyObject_GetOptionalAttr(o, n, &r); + return (res != 0) ? r : __Pyx_NewRef(d); +#else + #if CYTHON_USE_TYPE_SLOTS + if (likely(PyUnicode_Check(n))) { + r = __Pyx_PyObject_GetAttrStrNoError(o, n); + if (unlikely(!r) && likely(!PyErr_Occurred())) { + r = __Pyx_NewRef(d); + } + return r; + } + #endif + r = PyObject_GetAttr(o, n); + return (likely(r)) ? r : __Pyx_GetAttr3Default(d); +#endif +} + +/* PyDictVersioning (used by GetModuleGlobalName) */ +#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) { + PyObject *dict = Py_TYPE(obj)->tp_dict; + return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0; +} +static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) { + PyObject **dictptr = NULL; + Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset; + if (offset) { +#if CYTHON_COMPILING_IN_CPYTHON + dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj); +#else + dictptr = _PyObject_GetDictPtr(obj); +#endif + } + return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0; +} +static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) { + PyObject *dict = Py_TYPE(obj)->tp_dict; + if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict))) + return 0; + return obj_dict_version == __Pyx_get_object_dict_version(obj); +} +#endif + +/* GetModuleGlobalName */ +#if CYTHON_USE_DICT_VERSIONS +static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value) +#else +static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name) +#endif +{ + PyObject *result; +#if CYTHON_COMPILING_IN_LIMITED_API + if (unlikely(!__pyx_m)) { + if (!PyErr_Occurred()) + PyErr_SetNone(PyExc_NameError); + return NULL; + } + result = PyObject_GetAttr(__pyx_m, name); + if (likely(result)) { + return result; + } + PyErr_Clear(); +#elif CYTHON_AVOID_BORROWED_REFS || CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS + if (unlikely(__Pyx_PyDict_GetItemRef(__pyx_mstate_global->__pyx_d, name, &result) == -1)) PyErr_Clear(); + __PYX_UPDATE_DICT_CACHE(__pyx_mstate_global->__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return result; + } +#else + result = _PyDict_GetItem_KnownHash(__pyx_mstate_global->__pyx_d, name, ((PyASCIIObject *) name)->hash); + __PYX_UPDATE_DICT_CACHE(__pyx_mstate_global->__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } + PyErr_Clear(); +#endif + return __Pyx_GetBuiltinName(name); +} + +/* RaiseTooManyValuesToUnpack */ +static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected) { + PyErr_Format(PyExc_ValueError, + "too many values to unpack (expected %" CYTHON_FORMAT_SSIZE_T "d)", expected); +} + +/* RaiseNeedMoreValuesToUnpack */ +static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) { + PyErr_Format(PyExc_ValueError, + "need more than %" CYTHON_FORMAT_SSIZE_T "d value%.1s to unpack", + index, (index == 1) ? "" : "s"); +} + +/* RaiseNoneIterError */ +static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); +} + +/* ExtTypeTest */ +static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) { + __Pyx_TypeName obj_type_name; + __Pyx_TypeName type_name; + if (unlikely(!type)) { + PyErr_SetString(PyExc_SystemError, "Missing type object"); + return 0; + } + if (likely(__Pyx_TypeCheck(obj, type))) + return 1; + obj_type_name = __Pyx_PyType_GetFullyQualifiedName(Py_TYPE(obj)); + type_name = __Pyx_PyType_GetFullyQualifiedName(type); + PyErr_Format(PyExc_TypeError, + "Cannot convert " __Pyx_FMT_TYPENAME " to " __Pyx_FMT_TYPENAME, + obj_type_name, type_name); + __Pyx_DECREF_TypeName(obj_type_name); + __Pyx_DECREF_TypeName(type_name); + return 0; +} + +/* GetTopmostException (used by SaveResetException) */ +#if CYTHON_USE_EXC_INFO_STACK && CYTHON_FAST_THREAD_STATE +static _PyErr_StackItem * +__Pyx_PyErr_GetTopmostException(PyThreadState *tstate) +{ + _PyErr_StackItem *exc_info = tstate->exc_info; + while ((exc_info->exc_value == NULL || exc_info->exc_value == Py_None) && + exc_info->previous_item != NULL) + { + exc_info = exc_info->previous_item; + } + return exc_info; +} +#endif + +/* SaveResetException */ +#if CYTHON_FAST_THREAD_STATE +static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { + #if CYTHON_USE_EXC_INFO_STACK && PY_VERSION_HEX >= 0x030B00a4 + _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate); + PyObject *exc_value = exc_info->exc_value; + if (exc_value == NULL || exc_value == Py_None) { + *value = NULL; + *type = NULL; + *tb = NULL; + } else { + *value = exc_value; + Py_INCREF(*value); + *type = (PyObject*) Py_TYPE(exc_value); + Py_INCREF(*type); + *tb = PyException_GetTraceback(exc_value); + } + #elif CYTHON_USE_EXC_INFO_STACK + _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate); + *type = exc_info->exc_type; + *value = exc_info->exc_value; + *tb = exc_info->exc_traceback; + Py_XINCREF(*type); + Py_XINCREF(*value); + Py_XINCREF(*tb); + #else + *type = tstate->exc_type; + *value = tstate->exc_value; + *tb = tstate->exc_traceback; + Py_XINCREF(*type); + Py_XINCREF(*value); + Py_XINCREF(*tb); + #endif +} +static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { + #if CYTHON_USE_EXC_INFO_STACK && PY_VERSION_HEX >= 0x030B00a4 + _PyErr_StackItem *exc_info = tstate->exc_info; + PyObject *tmp_value = exc_info->exc_value; + exc_info->exc_value = value; + Py_XDECREF(tmp_value); + Py_XDECREF(type); + Py_XDECREF(tb); + #else + PyObject *tmp_type, *tmp_value, *tmp_tb; + #if CYTHON_USE_EXC_INFO_STACK + _PyErr_StackItem *exc_info = tstate->exc_info; + tmp_type = exc_info->exc_type; + tmp_value = exc_info->exc_value; + tmp_tb = exc_info->exc_traceback; + exc_info->exc_type = type; + exc_info->exc_value = value; + exc_info->exc_traceback = tb; + #else + tmp_type = tstate->exc_type; + tmp_value = tstate->exc_value; + tmp_tb = tstate->exc_traceback; + tstate->exc_type = type; + tstate->exc_value = value; + tstate->exc_traceback = tb; + #endif + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); + #endif +} +#endif + +/* GetException */ +#if CYTHON_FAST_THREAD_STATE +static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) +#else +static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) +#endif +{ + PyObject *local_type = NULL, *local_value, *local_tb = NULL; +#if CYTHON_FAST_THREAD_STATE + PyObject *tmp_type, *tmp_value, *tmp_tb; + #if PY_VERSION_HEX >= 0x030C0000 + local_value = tstate->current_exception; + tstate->current_exception = 0; + #else + local_type = tstate->curexc_type; + local_value = tstate->curexc_value; + local_tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; + #endif +#elif __PYX_LIMITED_VERSION_HEX > 0x030C0000 + local_value = PyErr_GetRaisedException(); +#else + PyErr_Fetch(&local_type, &local_value, &local_tb); +#endif +#if __PYX_LIMITED_VERSION_HEX > 0x030C0000 + if (likely(local_value)) { + local_type = (PyObject*) Py_TYPE(local_value); + Py_INCREF(local_type); + local_tb = PyException_GetTraceback(local_value); + } +#else + PyErr_NormalizeException(&local_type, &local_value, &local_tb); +#if CYTHON_FAST_THREAD_STATE + if (unlikely(tstate->curexc_type)) +#else + if (unlikely(PyErr_Occurred())) +#endif + goto bad; + if (local_tb) { + if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0)) + goto bad; + } +#endif // __PYX_LIMITED_VERSION_HEX > 0x030C0000 + Py_XINCREF(local_tb); + Py_XINCREF(local_type); + Py_XINCREF(local_value); + *type = local_type; + *value = local_value; + *tb = local_tb; +#if CYTHON_FAST_THREAD_STATE + #if CYTHON_USE_EXC_INFO_STACK + { + _PyErr_StackItem *exc_info = tstate->exc_info; + #if PY_VERSION_HEX >= 0x030B00a4 + tmp_value = exc_info->exc_value; + exc_info->exc_value = local_value; + tmp_type = NULL; + tmp_tb = NULL; + Py_XDECREF(local_type); + Py_XDECREF(local_tb); + #else + tmp_type = exc_info->exc_type; + tmp_value = exc_info->exc_value; + tmp_tb = exc_info->exc_traceback; + exc_info->exc_type = local_type; + exc_info->exc_value = local_value; + exc_info->exc_traceback = local_tb; + #endif + } + #else + tmp_type = tstate->exc_type; + tmp_value = tstate->exc_value; + tmp_tb = tstate->exc_traceback; + tstate->exc_type = local_type; + tstate->exc_value = local_value; + tstate->exc_traceback = local_tb; + #endif + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +#elif __PYX_LIMITED_VERSION_HEX >= 0x030b0000 + PyErr_SetHandledException(local_value); + Py_XDECREF(local_value); + Py_XDECREF(local_type); + Py_XDECREF(local_tb); +#else + PyErr_SetExcInfo(local_type, local_value, local_tb); +#endif + return 0; +#if __PYX_LIMITED_VERSION_HEX <= 0x030C0000 +bad: + *type = 0; + *value = 0; + *tb = 0; + Py_XDECREF(local_type); + Py_XDECREF(local_value); + Py_XDECREF(local_tb); + return -1; +#endif +} + +/* SwapException */ +#if CYTHON_FAST_THREAD_STATE +static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + #if CYTHON_USE_EXC_INFO_STACK && PY_VERSION_HEX >= 0x030B00a4 + _PyErr_StackItem *exc_info = tstate->exc_info; + tmp_value = exc_info->exc_value; + exc_info->exc_value = *value; + if (tmp_value == NULL || tmp_value == Py_None) { + Py_XDECREF(tmp_value); + tmp_value = NULL; + tmp_type = NULL; + tmp_tb = NULL; + } else { + tmp_type = (PyObject*) Py_TYPE(tmp_value); + Py_INCREF(tmp_type); + #if CYTHON_COMPILING_IN_CPYTHON + tmp_tb = ((PyBaseExceptionObject*) tmp_value)->traceback; + Py_XINCREF(tmp_tb); + #else + tmp_tb = PyException_GetTraceback(tmp_value); + #endif + } + #elif CYTHON_USE_EXC_INFO_STACK + _PyErr_StackItem *exc_info = tstate->exc_info; + tmp_type = exc_info->exc_type; + tmp_value = exc_info->exc_value; + tmp_tb = exc_info->exc_traceback; + exc_info->exc_type = *type; + exc_info->exc_value = *value; + exc_info->exc_traceback = *tb; + #else + tmp_type = tstate->exc_type; + tmp_value = tstate->exc_value; + tmp_tb = tstate->exc_traceback; + tstate->exc_type = *type; + tstate->exc_value = *value; + tstate->exc_traceback = *tb; + #endif + *type = tmp_type; + *value = tmp_value; + *tb = tmp_tb; +} +#else +static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value, PyObject **tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + PyErr_GetExcInfo(&tmp_type, &tmp_value, &tmp_tb); + PyErr_SetExcInfo(*type, *value, *tb); + *type = tmp_type; + *value = tmp_value; + *tb = tmp_tb; +} +#endif + +/* HasAttr (used by ImportImpl) */ +#if __PYX_LIMITED_VERSION_HEX < 0x030d0000 +static CYTHON_INLINE int __Pyx_HasAttr(PyObject *o, PyObject *n) { + PyObject *r; + if (unlikely(!PyUnicode_Check(n))) { + PyErr_SetString(PyExc_TypeError, + "hasattr(): attribute name must be string"); + return -1; + } + r = __Pyx_PyObject_GetAttrStrNoError(o, n); + if (!r) { + return (unlikely(PyErr_Occurred())) ? -1 : 0; + } else { + Py_DECREF(r); + return 1; + } +} +#endif + +/* ImportImpl (used by Import) */ +static int __Pyx__Import_GetModule(PyObject *qualname, PyObject **module) { + PyObject *imported_module = PyImport_GetModule(qualname); + if (unlikely(!imported_module)) { + *module = NULL; + if (PyErr_Occurred()) { + return -1; + } + return 0; + } + *module = imported_module; + return 1; +} +static int __Pyx__Import_Lookup(PyObject *qualname, PyObject *const *imported_names, Py_ssize_t len_imported_names, PyObject **module) { + PyObject *imported_module; + PyObject *top_level_package_name; + Py_ssize_t i; + int status, module_found; + Py_ssize_t dot_index; + module_found = __Pyx__Import_GetModule(qualname, &imported_module); + if (unlikely(!module_found || module_found == -1)) { + *module = NULL; + return module_found; + } + if (imported_names) { + for (i = 0; i < len_imported_names; i++) { + PyObject *imported_name = imported_names[i]; +#if __PYX_LIMITED_VERSION_HEX < 0x030d0000 + int has_imported_attribute = PyObject_HasAttr(imported_module, imported_name); +#else + int has_imported_attribute = PyObject_HasAttrWithError(imported_module, imported_name); + if (unlikely(has_imported_attribute == -1)) goto error; +#endif + if (!has_imported_attribute) { + goto not_found; + } + } + *module = imported_module; + return 1; + } + dot_index = PyUnicode_FindChar(qualname, '.', 0, PY_SSIZE_T_MAX, 1); + if (dot_index == -1) { + *module = imported_module; + return 1; + } + if (unlikely(dot_index == -2)) goto error; + top_level_package_name = PyUnicode_Substring(qualname, 0, dot_index); + if (unlikely(!top_level_package_name)) goto error; + Py_DECREF(imported_module); + status = __Pyx__Import_GetModule(top_level_package_name, module); + Py_DECREF(top_level_package_name); + return status; +error: + Py_DECREF(imported_module); + *module = NULL; + return -1; +not_found: + Py_DECREF(imported_module); + *module = NULL; + return 0; +} +static PyObject *__Pyx__Import(PyObject *name, PyObject *const *imported_names, Py_ssize_t len_imported_names, PyObject *qualname, PyObject *moddict, int level) { + PyObject *module = 0; + PyObject *empty_dict = 0; + PyObject *from_list = 0; + int module_found; + if (!qualname) { + qualname = name; + } + module_found = __Pyx__Import_Lookup(qualname, imported_names, len_imported_names, &module); + if (likely(module_found == 1)) { + return module; + } else if (unlikely(module_found == -1)) { + return NULL; + } + empty_dict = PyDict_New(); + if (unlikely(!empty_dict)) + goto bad; + if (imported_names) { +#if CYTHON_COMPILING_IN_CPYTHON + from_list = __Pyx_PyList_FromArray(imported_names, len_imported_names); + if (unlikely(!from_list)) + goto bad; +#else + from_list = PyList_New(len_imported_names); + if (unlikely(!from_list)) goto bad; + for (Py_ssize_t i=0; i__pyx_d, level); +} + +/* FastTypeChecks */ +#if CYTHON_COMPILING_IN_CPYTHON +static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) { + while (a) { + a = __Pyx_PyType_GetSlot(a, tp_base, PyTypeObject*); + if (a == b) + return 1; + } + return b == &PyBaseObject_Type; +} +static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) { + PyObject *mro; + if (a == b) return 1; + mro = a->tp_mro; + if (likely(mro)) { + Py_ssize_t i, n; + n = PyTuple_GET_SIZE(mro); + for (i = 0; i < n; i++) { + if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) + return 1; + } + return 0; + } + return __Pyx_InBases(a, b); +} +static CYTHON_INLINE int __Pyx_IsAnySubtype2(PyTypeObject *cls, PyTypeObject *a, PyTypeObject *b) { + PyObject *mro; + if (cls == a || cls == b) return 1; + mro = cls->tp_mro; + if (likely(mro)) { + Py_ssize_t i, n; + n = PyTuple_GET_SIZE(mro); + for (i = 0; i < n; i++) { + PyObject *base = PyTuple_GET_ITEM(mro, i); + if (base == (PyObject *)a || base == (PyObject *)b) + return 1; + } + return 0; + } + return __Pyx_InBases(cls, a) || __Pyx_InBases(cls, b); +} +static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) { + if (exc_type1) { + return __Pyx_IsAnySubtype2((PyTypeObject*)err, (PyTypeObject*)exc_type1, (PyTypeObject*)exc_type2); + } else { + return __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2); + } +} +static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { + Py_ssize_t i, n; + assert(PyExceptionClass_Check(exc_type)); + n = PyTuple_GET_SIZE(tuple); + for (i=0; itp_as_sequence && type->tp_as_sequence->sq_repeat)) { + return type->tp_as_sequence->sq_repeat(seq, mul); + } else { + return __Pyx_PySequence_Multiply_Generic(seq, mul); + } +} +#endif + +/* PyObjectFormatAndDecref */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_FormatSimpleAndDecref(PyObject* s, PyObject* f) { + if (unlikely(!s)) return NULL; + if (likely(PyUnicode_CheckExact(s))) return s; + return __Pyx_PyObject_FormatAndDecref(s, f); +} +static CYTHON_INLINE PyObject* __Pyx_PyObject_FormatAndDecref(PyObject* s, PyObject* f) { + PyObject *result; + if (unlikely(!s)) return NULL; + result = PyObject_Format(s, f); + Py_DECREF(s); + return result; +} + +/* PyObjectFormat */ +#if CYTHON_USE_UNICODE_WRITER +static PyObject* __Pyx_PyObject_Format(PyObject* obj, PyObject* format_spec) { + int ret; + _PyUnicodeWriter writer; + if (likely(PyFloat_CheckExact(obj))) { + _PyUnicodeWriter_Init(&writer); + ret = _PyFloat_FormatAdvancedWriter( + &writer, + obj, + format_spec, 0, PyUnicode_GET_LENGTH(format_spec)); + } else if (likely(PyLong_CheckExact(obj))) { + _PyUnicodeWriter_Init(&writer); + ret = _PyLong_FormatAdvancedWriter( + &writer, + obj, + format_spec, 0, PyUnicode_GET_LENGTH(format_spec)); + } else { + return PyObject_Format(obj, format_spec); + } + if (unlikely(ret == -1)) { + _PyUnicodeWriter_Dealloc(&writer); + return NULL; + } + return _PyUnicodeWriter_Finish(&writer); +} +#endif + +/* SetItemInt */ +static int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) { + int r; + if (unlikely(!j)) return -1; + r = PyObject_SetItem(o, j, v); + Py_DECREF(j); + return r; +} +static CYTHON_INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v, int is_list, + int wraparound, int boundscheck, int unsafe_shared) { + CYTHON_MAYBE_UNUSED_VAR(unsafe_shared); +#if CYTHON_ASSUME_SAFE_MACROS && CYTHON_ASSUME_SAFE_SIZE && !CYTHON_AVOID_BORROWED_REFS + if (is_list || PyList_CheckExact(o)) { + Py_ssize_t n = (!wraparound) ? i : ((likely(i >= 0)) ? i : i + PyList_GET_SIZE(o)); + if ((CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS && !__Pyx_IS_UNIQUELY_REFERENCED(o, unsafe_shared))) { + Py_INCREF(v); + return PyList_SetItem(o, n, v); + } else if ((!boundscheck) || likely(__Pyx_is_valid_index(n, PyList_GET_SIZE(o)))) { + PyObject* old; + Py_INCREF(v); + old = PyList_GET_ITEM(o, n); + PyList_SET_ITEM(o, n, v); + Py_DECREF(old); + return 0; + } + } else +#endif +#if CYTHON_USE_TYPE_SLOTS && !CYTHON_COMPILING_IN_PYPY + { + PyMappingMethods *mm = Py_TYPE(o)->tp_as_mapping; + PySequenceMethods *sm = Py_TYPE(o)->tp_as_sequence; + if (!is_list && mm && mm->mp_ass_subscript) { + int r; + PyObject *key = PyLong_FromSsize_t(i); + if (unlikely(!key)) return -1; + r = mm->mp_ass_subscript(o, key, v); + Py_DECREF(key); + return r; + } + if (is_list || likely(sm && sm->sq_ass_item)) { + if (wraparound && unlikely(i < 0) && likely(sm->sq_length)) { + Py_ssize_t l = sm->sq_length(o); + if (likely(l >= 0)) { + i += l; + } else { + if (!PyErr_ExceptionMatches(PyExc_OverflowError)) + return -1; + PyErr_Clear(); + } + } + return sm->sq_ass_item(o, i, v); + } + } +#else + if (is_list || !PyMapping_Check(o)) { + return PySequence_SetItem(o, i, v); + } +#endif + (void)wraparound; + (void)boundscheck; + return __Pyx_SetItemInt_Generic(o, PyLong_FromSsize_t(i), v); +} + +/* RaiseUnboundLocalError */ +static void __Pyx_RaiseUnboundLocalError(const char *varname) { + PyErr_Format(PyExc_UnboundLocalError, "local variable '%s' referenced before assignment", varname); +} + +/* DivInt[long] */ +static CYTHON_INLINE long __Pyx_div_long(long a, long b, int b_is_constant) { + long q = a / b; + long r = a - q*b; + long adapt_python = (b_is_constant ? + ((r != 0) & ((r < 0) ^ (b < 0))) : + ((r != 0) & ((r ^ b) < 0)) + ); + return q - adapt_python; +} + +/* ReleaseUnknownGil */ +static __Pyx_UnknownThreadState __Pyx_SaveUnknownThread(void) { +#if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030d0000 + if (__Pyx_get_runtime_version() >= 0x030d0000) { + PyThreadState *ts = PyThreadState_Swap(NULL); + __Pyx_UnknownThreadState out = { ts, PyGILState_UNLOCKED }; + return out; + } else { + PyGILState_STATE gil_state = PyGILState_Ensure(); + PyThreadState *ts = PyEval_SaveThread(); + __Pyx_UnknownThreadState out = { ts, gil_state }; + return out; + } +#elif __PYX_LIMITED_VERSION_HEX >= 0x030d0000 + return PyThreadState_Swap(NULL); +#else + #if CYTHON_COMPILING_IN_PYPY || PY_VERSION_HEX < 0x030C0000 + if (PyGILState_Check()) + #else + if (_PyThreadState_UncheckedGet()) // UncheckedGet is a reliable check for the GIL from 3.12 upwards + #endif + { + return PyEval_SaveThread(); + } + return NULL; // Nothing to release - we don't have the GIL +#endif +} +static void __Pyx_RestoreUnknownThread(__Pyx_UnknownThreadState state) { +#if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030d0000 + if (!state.ts) return; + PyEval_RestoreThread(state.ts); + if (__Pyx_get_runtime_version() < 0x030d0000) { + PyGILState_Release(state.gil_state); + } +#else + if (state) { + PyEval_RestoreThread(state); + } +#endif +} +static CYTHON_INLINE int __Pyx_UnknownThreadStateDefinitelyHadGil(__Pyx_UnknownThreadState state) { + #if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030d0000 + return ((state.ts != NULL) && (__Pyx_get_runtime_version() >= 0x030d0000)); + #else + return state != NULL; + #endif +} +static CYTHON_INLINE int __Pyx_UnknownThreadStateMayHaveHadGil(__Pyx_UnknownThreadState state) { + #if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030d0000 + return state.ts != NULL; + #else + return state != NULL; + #endif +} + +/* ErrOccurredWithGIL */ +static CYTHON_INLINE int __Pyx_ErrOccurredWithGIL(void) { + int err; + PyGILState_STATE _save = PyGILState_Ensure(); + err = !!PyErr_Occurred(); + PyGILState_Release(_save); + return err; +} + +/* AllocateExtensionType */ +static PyObject *__Pyx_AllocateExtensionType(PyTypeObject *t, int is_final) { + if (is_final || likely(!__Pyx_PyType_HasFeature(t, Py_TPFLAGS_IS_ABSTRACT))) { + allocfunc alloc_func = __Pyx_PyType_GetSlot(t, tp_alloc, allocfunc); + return alloc_func(t, 0); + } else { + newfunc tp_new = __Pyx_PyType_TryGetSlot(&PyBaseObject_Type, tp_new, newfunc); + #if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030A0000 + if (!tp_new) { + PyObject *new_str = PyUnicode_FromString("__new__"); + if (likely(new_str)) { + PyObject *o = PyObject_CallMethodObjArgs((PyObject *)&PyBaseObject_Type, new_str, t, NULL); + Py_DECREF(new_str); + return o; + } else + return NULL; + } else + #endif + return tp_new(t, __pyx_mstate_global->__pyx_empty_tuple, 0); + } +} + +/* CallTypeTraverse */ +#if !CYTHON_USE_TYPE_SPECS || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX < 0x03090000) +#else +static int __Pyx_call_type_traverse(PyObject *o, int always_call, visitproc visit, void *arg) { + #if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x03090000 + if (__Pyx_get_runtime_version() < 0x03090000) return 0; + #endif + if (!always_call) { + PyTypeObject *base = __Pyx_PyObject_GetSlot(o, tp_base, PyTypeObject*); + unsigned long flags = PyType_GetFlags(base); + if (flags & Py_TPFLAGS_HEAPTYPE) { + return 0; + } + } + Py_VISIT((PyObject*)Py_TYPE(o)); + return 0; +} +#endif + +/* LimitedApiGetTypeDict (used by SetItemOnTypeDict) */ +#if CYTHON_COMPILING_IN_LIMITED_API +static Py_ssize_t __Pyx_GetTypeDictOffset(void) { + PyObject *tp_dictoffset_o; + Py_ssize_t tp_dictoffset; + tp_dictoffset_o = PyObject_GetAttrString((PyObject*)(&PyType_Type), "__dictoffset__"); + if (unlikely(!tp_dictoffset_o)) return -1; + tp_dictoffset = PyLong_AsSsize_t(tp_dictoffset_o); + Py_DECREF(tp_dictoffset_o); + if (unlikely(tp_dictoffset == 0)) { + PyErr_SetString( + PyExc_TypeError, + "'type' doesn't have a dictoffset"); + return -1; + } else if (unlikely(tp_dictoffset < 0)) { + PyErr_SetString( + PyExc_TypeError, + "'type' has an unexpected negative dictoffset. " + "Please report this as Cython bug"); + return -1; + } + return tp_dictoffset; +} +static PyObject *__Pyx_GetTypeDict(PyTypeObject *tp) { + static Py_ssize_t tp_dictoffset = 0; + if (unlikely(tp_dictoffset == 0)) { + tp_dictoffset = __Pyx_GetTypeDictOffset(); + if (unlikely(tp_dictoffset == -1 && PyErr_Occurred())) { + tp_dictoffset = 0; // try again next time? + return NULL; + } + } + return *(PyObject**)((char*)tp + tp_dictoffset); +} +#endif + +/* SetItemOnTypeDict (used by FixUpExtensionType) */ +static int __Pyx__SetItemOnTypeDict(PyTypeObject *tp, PyObject *k, PyObject *v) { + int result; + PyObject *tp_dict; +#if CYTHON_COMPILING_IN_LIMITED_API + tp_dict = __Pyx_GetTypeDict(tp); + if (unlikely(!tp_dict)) return -1; +#else + tp_dict = tp->tp_dict; +#endif + result = PyDict_SetItem(tp_dict, k, v); + if (likely(!result)) { + PyType_Modified(tp); + if (unlikely(PyObject_HasAttr(v, __pyx_mstate_global->__pyx_n_u_set_name))) { + PyObject *setNameResult = PyObject_CallMethodObjArgs(v, __pyx_mstate_global->__pyx_n_u_set_name, (PyObject *) tp, k, NULL); + if (!setNameResult) return -1; + Py_DECREF(setNameResult); + } + } + return result; +} + +/* FixUpExtensionType */ +static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject *type) { +#if __PYX_LIMITED_VERSION_HEX > 0x030900B1 + CYTHON_UNUSED_VAR(spec); + CYTHON_UNUSED_VAR(type); + CYTHON_UNUSED_VAR(__Pyx__SetItemOnTypeDict); +#else + const PyType_Slot *slot = spec->slots; + int changed = 0; +#if !CYTHON_COMPILING_IN_LIMITED_API + while (slot && slot->slot && slot->slot != Py_tp_members) + slot++; + if (slot && slot->slot == Py_tp_members) { +#if !CYTHON_COMPILING_IN_CPYTHON + const +#endif // !CYTHON_COMPILING_IN_CPYTHON) + PyMemberDef *memb = (PyMemberDef*) slot->pfunc; + while (memb && memb->name) { + if (memb->name[0] == '_' && memb->name[1] == '_') { + if (strcmp(memb->name, "__weaklistoffset__") == 0) { + assert(memb->type == T_PYSSIZET); + assert(memb->flags == READONLY); + type->tp_weaklistoffset = memb->offset; + changed = 1; + } + else if (strcmp(memb->name, "__dictoffset__") == 0) { + assert(memb->type == T_PYSSIZET); + assert(memb->flags == READONLY); + type->tp_dictoffset = memb->offset; + changed = 1; + } +#if CYTHON_METH_FASTCALL + else if (strcmp(memb->name, "__vectorcalloffset__") == 0) { + assert(memb->type == T_PYSSIZET); + assert(memb->flags == READONLY); + type->tp_vectorcall_offset = memb->offset; + changed = 1; + } +#endif // CYTHON_METH_FASTCALL +#if !CYTHON_COMPILING_IN_PYPY + else if (strcmp(memb->name, "__module__") == 0) { + PyObject *descr; + assert(memb->type == T_OBJECT); + assert(memb->flags == 0 || memb->flags == READONLY); + descr = PyDescr_NewMember(type, memb); + if (unlikely(!descr)) + return -1; + int set_item_result = PyDict_SetItem(type->tp_dict, PyDescr_NAME(descr), descr); + Py_DECREF(descr); + if (unlikely(set_item_result < 0)) { + return -1; + } + changed = 1; + } +#endif // !CYTHON_COMPILING_IN_PYPY + } + memb++; + } + } +#endif // !CYTHON_COMPILING_IN_LIMITED_API +#if !CYTHON_COMPILING_IN_PYPY + slot = spec->slots; + while (slot && slot->slot && slot->slot != Py_tp_getset) + slot++; + if (slot && slot->slot == Py_tp_getset) { + PyGetSetDef *getset = (PyGetSetDef*) slot->pfunc; + while (getset && getset->name) { + if (getset->name[0] == '_' && getset->name[1] == '_' && strcmp(getset->name, "__module__") == 0) { + PyObject *descr = PyDescr_NewGetSet(type, getset); + if (unlikely(!descr)) + return -1; + #if CYTHON_COMPILING_IN_LIMITED_API + PyObject *pyname = PyUnicode_FromString(getset->name); + if (unlikely(!pyname)) { + Py_DECREF(descr); + return -1; + } + int set_item_result = __Pyx_SetItemOnTypeDict(type, pyname, descr); + Py_DECREF(pyname); + #else + CYTHON_UNUSED_VAR(__Pyx__SetItemOnTypeDict); + int set_item_result = PyDict_SetItem(type->tp_dict, PyDescr_NAME(descr), descr); + #endif + Py_DECREF(descr); + if (unlikely(set_item_result < 0)) { + return -1; + } + changed = 1; + } + ++getset; + } + } +#else + CYTHON_UNUSED_VAR(__Pyx__SetItemOnTypeDict); +#endif // !CYTHON_COMPILING_IN_PYPY + if (changed) + PyType_Modified(type); +#endif // PY_VERSION_HEX > 0x030900B1 + return 0; +} + +/* PyObjectCallNoArg (used by PyObjectCallMethod0) */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func) { + PyObject *arg[2] = {NULL, NULL}; + return __Pyx_PyObject_FastCall(func, arg + 1, 0 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET); +} + +/* PyObjectGetMethod (used by PyObjectCallMethod0) */ +#if !(CYTHON_VECTORCALL && (__PYX_LIMITED_VERSION_HEX >= 0x030C0000 || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x03090000))) +static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) { + PyObject *attr; +#if CYTHON_UNPACK_METHODS && CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_PYTYPE_LOOKUP + __Pyx_TypeName type_name; + PyTypeObject *tp = Py_TYPE(obj); + PyObject *descr; + descrgetfunc f = NULL; + PyObject **dictptr, *dict; + int meth_found = 0; + assert (*method == NULL); + if (unlikely(tp->tp_getattro != PyObject_GenericGetAttr)) { + attr = __Pyx_PyObject_GetAttrStr(obj, name); + goto try_unpack; + } + if (unlikely(tp->tp_dict == NULL) && unlikely(PyType_Ready(tp) < 0)) { + return 0; + } + descr = _PyType_Lookup(tp, name); + if (likely(descr != NULL)) { + Py_INCREF(descr); +#if defined(Py_TPFLAGS_METHOD_DESCRIPTOR) && Py_TPFLAGS_METHOD_DESCRIPTOR + if (__Pyx_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)) +#else + #ifdef __Pyx_CyFunction_USED + if (likely(PyFunction_Check(descr) || __Pyx_IS_TYPE(descr, &PyMethodDescr_Type) || __Pyx_CyFunction_Check(descr))) + #else + if (likely(PyFunction_Check(descr) || __Pyx_IS_TYPE(descr, &PyMethodDescr_Type))) + #endif +#endif + { + meth_found = 1; + } else { + f = Py_TYPE(descr)->tp_descr_get; + if (f != NULL && PyDescr_IsData(descr)) { + attr = f(descr, obj, (PyObject *)Py_TYPE(obj)); + Py_DECREF(descr); + goto try_unpack; + } + } + } + dictptr = _PyObject_GetDictPtr(obj); + if (dictptr != NULL && (dict = *dictptr) != NULL) { + Py_INCREF(dict); + attr = __Pyx_PyDict_GetItemStr(dict, name); + if (attr != NULL) { + Py_INCREF(attr); + Py_DECREF(dict); + Py_XDECREF(descr); + goto try_unpack; + } + Py_DECREF(dict); + } + if (meth_found) { + *method = descr; + return 1; + } + if (f != NULL) { + attr = f(descr, obj, (PyObject *)Py_TYPE(obj)); + Py_DECREF(descr); + goto try_unpack; + } + if (likely(descr != NULL)) { + *method = descr; + return 0; + } + type_name = __Pyx_PyType_GetFullyQualifiedName(tp); + PyErr_Format(PyExc_AttributeError, + "'" __Pyx_FMT_TYPENAME "' object has no attribute '%U'", + type_name, name); + __Pyx_DECREF_TypeName(type_name); + return 0; +#else + attr = __Pyx_PyObject_GetAttrStr(obj, name); + goto try_unpack; +#endif +try_unpack: +#if CYTHON_UNPACK_METHODS + if (likely(attr) && PyMethod_Check(attr) && likely(PyMethod_GET_SELF(attr) == obj)) { + PyObject *function = PyMethod_GET_FUNCTION(attr); + Py_INCREF(function); + Py_DECREF(attr); + *method = function; + return 1; + } +#endif + *method = attr; + return 0; +} +#endif + +/* PyObjectCallMethod0 (used by PyType_Ready) */ +static PyObject* __Pyx_PyObject_CallMethod0(PyObject* obj, PyObject* method_name) { +#if CYTHON_VECTORCALL && (__PYX_LIMITED_VERSION_HEX >= 0x030C0000 || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x03090000)) + PyObject *args[1] = {obj}; + (void) __Pyx_PyObject_CallOneArg; + (void) __Pyx_PyObject_CallNoArg; + return PyObject_VectorcallMethod(method_name, args, 1 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); +#else + PyObject *method = NULL, *result = NULL; + int is_method = __Pyx_PyObject_GetMethod(obj, method_name, &method); + if (likely(is_method)) { + result = __Pyx_PyObject_CallOneArg(method, obj); + Py_DECREF(method); + return result; + } + if (unlikely(!method)) goto bad; + result = __Pyx_PyObject_CallNoArg(method); + Py_DECREF(method); +bad: + return result; +#endif +} + +/* ValidateBasesTuple (used by PyType_Ready) */ +#if CYTHON_COMPILING_IN_CPYTHON || CYTHON_COMPILING_IN_LIMITED_API || CYTHON_USE_TYPE_SPECS +static int __Pyx_validate_bases_tuple(const char *type_name, Py_ssize_t dictoffset, PyObject *bases) { + Py_ssize_t i, n; +#if CYTHON_ASSUME_SAFE_SIZE + n = PyTuple_GET_SIZE(bases); +#else + n = PyTuple_Size(bases); + if (unlikely(n < 0)) return -1; +#endif + for (i = 1; i < n; i++) + { + PyTypeObject *b; +#if CYTHON_AVOID_BORROWED_REFS + PyObject *b0 = PySequence_GetItem(bases, i); + if (!b0) return -1; +#elif CYTHON_ASSUME_SAFE_MACROS + PyObject *b0 = PyTuple_GET_ITEM(bases, i); +#else + PyObject *b0 = PyTuple_GetItem(bases, i); + if (!b0) return -1; +#endif + b = (PyTypeObject*) b0; + if (!__Pyx_PyType_HasFeature(b, Py_TPFLAGS_HEAPTYPE)) + { + __Pyx_TypeName b_name = __Pyx_PyType_GetFullyQualifiedName(b); + PyErr_Format(PyExc_TypeError, + "base class '" __Pyx_FMT_TYPENAME "' is not a heap type", b_name); + __Pyx_DECREF_TypeName(b_name); +#if CYTHON_AVOID_BORROWED_REFS + Py_DECREF(b0); +#endif + return -1; + } + if (dictoffset == 0) + { + Py_ssize_t b_dictoffset = 0; +#if CYTHON_USE_TYPE_SLOTS + b_dictoffset = b->tp_dictoffset; +#else + PyObject *py_b_dictoffset = PyObject_GetAttrString((PyObject*)b, "__dictoffset__"); + if (!py_b_dictoffset) goto dictoffset_return; + b_dictoffset = PyLong_AsSsize_t(py_b_dictoffset); + Py_DECREF(py_b_dictoffset); + if (b_dictoffset == -1 && PyErr_Occurred()) goto dictoffset_return; +#endif + if (b_dictoffset) { + { + __Pyx_TypeName b_name = __Pyx_PyType_GetFullyQualifiedName(b); + PyErr_Format(PyExc_TypeError, + "extension type '%.200s' has no __dict__ slot, " + "but base type '" __Pyx_FMT_TYPENAME "' has: " + "either add 'cdef dict __dict__' to the extension type " + "or add '__slots__ = [...]' to the base type", + type_name, b_name); + __Pyx_DECREF_TypeName(b_name); + } +#if !CYTHON_USE_TYPE_SLOTS + dictoffset_return: +#endif +#if CYTHON_AVOID_BORROWED_REFS + Py_DECREF(b0); +#endif + return -1; + } + } +#if CYTHON_AVOID_BORROWED_REFS + Py_DECREF(b0); +#endif + } + return 0; +} +#endif + +/* PyType_Ready */ +CYTHON_UNUSED static int __Pyx_PyType_HasMultipleInheritance(PyTypeObject *t) { + while (t) { + PyObject *bases = __Pyx_PyType_GetSlot(t, tp_bases, PyObject*); + if (bases) { + return 1; + } + t = __Pyx_PyType_GetSlot(t, tp_base, PyTypeObject*); + } + return 0; +} +static int __Pyx_PyType_Ready(PyTypeObject *t) { +#if CYTHON_USE_TYPE_SPECS || !CYTHON_COMPILING_IN_CPYTHON || defined(PYSTON_MAJOR_VERSION) + (void)__Pyx_PyObject_CallMethod0; +#if CYTHON_USE_TYPE_SPECS + (void)__Pyx_validate_bases_tuple; +#endif + return PyType_Ready(t); +#else + int r; + if (!__Pyx_PyType_HasMultipleInheritance(t)) { + return PyType_Ready(t); + } + PyObject *bases = __Pyx_PyType_GetSlot(t, tp_bases, PyObject*); + if (bases && unlikely(__Pyx_validate_bases_tuple(t->tp_name, t->tp_dictoffset, bases) == -1)) + return -1; +#if !defined(PYSTON_MAJOR_VERSION) + { + int gc_was_enabled; + #if PY_VERSION_HEX >= 0x030A00b1 + gc_was_enabled = PyGC_Disable(); + (void)__Pyx_PyObject_CallMethod0; + #else + PyObject *ret, *py_status; + PyObject *gc = NULL; + #if (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM+0 >= 0x07030400) &&\ + !CYTHON_COMPILING_IN_GRAAL + gc = PyImport_GetModule(__pyx_mstate_global->__pyx_kp_u_gc); + #endif + if (unlikely(!gc)) gc = PyImport_Import(__pyx_mstate_global->__pyx_kp_u_gc); + if (unlikely(!gc)) return -1; + py_status = __Pyx_PyObject_CallMethod0(gc, __pyx_mstate_global->__pyx_kp_u_isenabled); + if (unlikely(!py_status)) { + Py_DECREF(gc); + return -1; + } + gc_was_enabled = __Pyx_PyObject_IsTrue(py_status); + Py_DECREF(py_status); + if (gc_was_enabled > 0) { + ret = __Pyx_PyObject_CallMethod0(gc, __pyx_mstate_global->__pyx_kp_u_disable); + if (unlikely(!ret)) { + Py_DECREF(gc); + return -1; + } + Py_DECREF(ret); + } else if (unlikely(gc_was_enabled == -1)) { + Py_DECREF(gc); + return -1; + } + #endif + t->tp_flags |= Py_TPFLAGS_HEAPTYPE; +#if PY_VERSION_HEX >= 0x030A0000 + t->tp_flags |= Py_TPFLAGS_IMMUTABLETYPE; +#endif +#else + (void)__Pyx_PyObject_CallMethod0; +#endif + r = PyType_Ready(t); +#if !defined(PYSTON_MAJOR_VERSION) + t->tp_flags &= ~Py_TPFLAGS_HEAPTYPE; + #if PY_VERSION_HEX >= 0x030A00b1 + if (gc_was_enabled) + PyGC_Enable(); + #else + if (gc_was_enabled) { + PyObject *tp, *v, *tb; + PyErr_Fetch(&tp, &v, &tb); + ret = __Pyx_PyObject_CallMethod0(gc, __pyx_mstate_global->__pyx_kp_u_enable); + if (likely(ret || r == -1)) { + Py_XDECREF(ret); + PyErr_Restore(tp, v, tb); + } else { + Py_XDECREF(tp); + Py_XDECREF(v); + Py_XDECREF(tb); + r = -1; + } + } + Py_DECREF(gc); + #endif + } +#endif + return r; +#endif +} + +/* SetVTable */ +static int __Pyx_SetVtable(PyTypeObject *type, void *vtable) { + PyObject *ob = PyCapsule_New(vtable, 0, 0); + if (unlikely(!ob)) + goto bad; +#if CYTHON_COMPILING_IN_LIMITED_API + if (unlikely(PyObject_SetAttr((PyObject *) type, __pyx_mstate_global->__pyx_n_u_pyx_vtable, ob) < 0)) +#else + if (unlikely(PyDict_SetItem(type->tp_dict, __pyx_mstate_global->__pyx_n_u_pyx_vtable, ob) < 0)) +#endif + goto bad; + Py_DECREF(ob); + return 0; +bad: + Py_XDECREF(ob); + return -1; +} + +/* GetVTable (used by MergeVTables) */ +static void* __Pyx_GetVtable(PyTypeObject *type) { + void* ptr; +#if CYTHON_COMPILING_IN_LIMITED_API + PyObject *ob = PyObject_GetAttr((PyObject *)type, __pyx_mstate_global->__pyx_n_u_pyx_vtable); +#else + PyObject *ob = PyObject_GetItem(type->tp_dict, __pyx_mstate_global->__pyx_n_u_pyx_vtable); +#endif + if (!ob) + goto bad; + ptr = PyCapsule_GetPointer(ob, 0); + if (!ptr && !PyErr_Occurred()) + PyErr_SetString(PyExc_RuntimeError, "invalid vtable found for imported type"); + Py_DECREF(ob); + return ptr; +bad: + Py_XDECREF(ob); + return NULL; +} + +/* MergeVTables */ +static int __Pyx_MergeVtables(PyTypeObject *type) { + int i=0; + Py_ssize_t size; + void** base_vtables; + __Pyx_TypeName tp_base_name = NULL; + __Pyx_TypeName base_name = NULL; + void* unknown = (void*)-1; + PyObject* bases = __Pyx_PyType_GetSlot(type, tp_bases, PyObject*); + int base_depth = 0; + { + PyTypeObject* base = __Pyx_PyType_GetSlot(type, tp_base, PyTypeObject*); + while (base) { + base_depth += 1; + base = __Pyx_PyType_GetSlot(base, tp_base, PyTypeObject*); + } + } + base_vtables = (void**) PyMem_Malloc(sizeof(void*) * (size_t)(base_depth + 1)); + base_vtables[0] = unknown; +#if CYTHON_COMPILING_IN_LIMITED_API + size = PyTuple_Size(bases); + if (size < 0) goto other_failure; +#else + size = PyTuple_GET_SIZE(bases); +#endif + for (i = 1; i < size; i++) { + PyObject *basei; + void* base_vtable; +#if CYTHON_AVOID_BORROWED_REFS + basei = PySequence_GetItem(bases, i); + if (unlikely(!basei)) goto other_failure; +#elif !CYTHON_ASSUME_SAFE_MACROS + basei = PyTuple_GetItem(bases, i); + if (unlikely(!basei)) goto other_failure; +#else + basei = PyTuple_GET_ITEM(bases, i); +#endif + base_vtable = __Pyx_GetVtable((PyTypeObject*)basei); +#if CYTHON_AVOID_BORROWED_REFS + Py_DECREF(basei); +#endif + if (base_vtable != NULL) { + int j; + PyTypeObject* base = __Pyx_PyType_GetSlot(type, tp_base, PyTypeObject*); + for (j = 0; j < base_depth; j++) { + if (base_vtables[j] == unknown) { + base_vtables[j] = __Pyx_GetVtable(base); + base_vtables[j + 1] = unknown; + } + if (base_vtables[j] == base_vtable) { + break; + } else if (base_vtables[j] == NULL) { + goto bad; + } + base = __Pyx_PyType_GetSlot(base, tp_base, PyTypeObject*); + } + } + } + PyErr_Clear(); + PyMem_Free(base_vtables); + return 0; +bad: + { + PyTypeObject* basei = NULL; + PyTypeObject* tp_base = __Pyx_PyType_GetSlot(type, tp_base, PyTypeObject*); + tp_base_name = __Pyx_PyType_GetFullyQualifiedName(tp_base); +#if CYTHON_AVOID_BORROWED_REFS + basei = (PyTypeObject*)PySequence_GetItem(bases, i); + if (unlikely(!basei)) goto really_bad; +#elif !CYTHON_ASSUME_SAFE_MACROS + basei = (PyTypeObject*)PyTuple_GetItem(bases, i); + if (unlikely(!basei)) goto really_bad; +#else + basei = (PyTypeObject*)PyTuple_GET_ITEM(bases, i); +#endif + base_name = __Pyx_PyType_GetFullyQualifiedName(basei); +#if CYTHON_AVOID_BORROWED_REFS + Py_DECREF(basei); +#endif + } + PyErr_Format(PyExc_TypeError, + "multiple bases have vtable conflict: '" __Pyx_FMT_TYPENAME "' and '" __Pyx_FMT_TYPENAME "'", tp_base_name, base_name); +#if CYTHON_AVOID_BORROWED_REFS || !CYTHON_ASSUME_SAFE_MACROS +really_bad: // bad has failed! +#endif + __Pyx_DECREF_TypeName(tp_base_name); + __Pyx_DECREF_TypeName(base_name); +#if CYTHON_COMPILING_IN_LIMITED_API || CYTHON_AVOID_BORROWED_REFS || !CYTHON_ASSUME_SAFE_MACROS +other_failure: +#endif + PyMem_Free(base_vtables); + return -1; +} + +/* DelItemOnTypeDict (used by SetupReduce) */ +static int __Pyx__DelItemOnTypeDict(PyTypeObject *tp, PyObject *k) { + int result; + PyObject *tp_dict; +#if CYTHON_COMPILING_IN_LIMITED_API + tp_dict = __Pyx_GetTypeDict(tp); + if (unlikely(!tp_dict)) return -1; +#else + tp_dict = tp->tp_dict; +#endif + result = PyDict_DelItem(tp_dict, k); + if (likely(!result)) PyType_Modified(tp); + return result; +} + +/* SetupReduce */ +static int __Pyx_setup_reduce_is_named(PyObject* meth, PyObject* name) { + int ret; + PyObject *name_attr; + name_attr = __Pyx_PyObject_GetAttrStrNoError(meth, __pyx_mstate_global->__pyx_n_u_name_2); + if (likely(name_attr)) { + ret = PyObject_RichCompareBool(name_attr, name, Py_EQ); + } else { + ret = -1; + } + if (unlikely(ret < 0)) { + PyErr_Clear(); + ret = 0; + } + Py_XDECREF(name_attr); + return ret; +} +static int __Pyx_setup_reduce(PyObject* type_obj) { + int ret = 0; + PyObject *object_reduce = NULL; + PyObject *object_getstate = NULL; + PyObject *object_reduce_ex = NULL; + PyObject *reduce = NULL; + PyObject *reduce_ex = NULL; + PyObject *reduce_cython = NULL; + PyObject *setstate = NULL; + PyObject *setstate_cython = NULL; + PyObject *getstate = NULL; +#if CYTHON_USE_PYTYPE_LOOKUP + getstate = _PyType_Lookup((PyTypeObject*)type_obj, __pyx_mstate_global->__pyx_n_u_getstate); +#else + getstate = __Pyx_PyObject_GetAttrStrNoError(type_obj, __pyx_mstate_global->__pyx_n_u_getstate); + if (!getstate && PyErr_Occurred()) { + goto __PYX_BAD; + } +#endif + if (getstate) { +#if CYTHON_USE_PYTYPE_LOOKUP + object_getstate = _PyType_Lookup(&PyBaseObject_Type, __pyx_mstate_global->__pyx_n_u_getstate); +#else + object_getstate = __Pyx_PyObject_GetAttrStrNoError((PyObject*)&PyBaseObject_Type, __pyx_mstate_global->__pyx_n_u_getstate); + if (!object_getstate && PyErr_Occurred()) { + goto __PYX_BAD; + } +#endif + if (object_getstate != getstate) { + goto __PYX_GOOD; + } + } +#if CYTHON_USE_PYTYPE_LOOKUP + object_reduce_ex = _PyType_Lookup(&PyBaseObject_Type, __pyx_mstate_global->__pyx_n_u_reduce_ex); if (!object_reduce_ex) goto __PYX_BAD; +#else + object_reduce_ex = __Pyx_PyObject_GetAttrStr((PyObject*)&PyBaseObject_Type, __pyx_mstate_global->__pyx_n_u_reduce_ex); if (!object_reduce_ex) goto __PYX_BAD; +#endif + reduce_ex = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_mstate_global->__pyx_n_u_reduce_ex); if (unlikely(!reduce_ex)) goto __PYX_BAD; + if (reduce_ex == object_reduce_ex) { +#if CYTHON_USE_PYTYPE_LOOKUP + object_reduce = _PyType_Lookup(&PyBaseObject_Type, __pyx_mstate_global->__pyx_n_u_reduce); if (!object_reduce) goto __PYX_BAD; +#else + object_reduce = __Pyx_PyObject_GetAttrStr((PyObject*)&PyBaseObject_Type, __pyx_mstate_global->__pyx_n_u_reduce); if (!object_reduce) goto __PYX_BAD; +#endif + reduce = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_mstate_global->__pyx_n_u_reduce); if (unlikely(!reduce)) goto __PYX_BAD; + if (reduce == object_reduce || __Pyx_setup_reduce_is_named(reduce, __pyx_mstate_global->__pyx_n_u_reduce_cython)) { + reduce_cython = __Pyx_PyObject_GetAttrStrNoError(type_obj, __pyx_mstate_global->__pyx_n_u_reduce_cython); + if (likely(reduce_cython)) { + ret = __Pyx_SetItemOnTypeDict((PyTypeObject*)type_obj, __pyx_mstate_global->__pyx_n_u_reduce, reduce_cython); if (unlikely(ret < 0)) goto __PYX_BAD; + ret = __Pyx_DelItemOnTypeDict((PyTypeObject*)type_obj, __pyx_mstate_global->__pyx_n_u_reduce_cython); if (unlikely(ret < 0)) goto __PYX_BAD; + } else if (reduce == object_reduce || PyErr_Occurred()) { + goto __PYX_BAD; + } + setstate = __Pyx_PyObject_GetAttrStrNoError(type_obj, __pyx_mstate_global->__pyx_n_u_setstate); + if (!setstate) PyErr_Clear(); + if (!setstate || __Pyx_setup_reduce_is_named(setstate, __pyx_mstate_global->__pyx_n_u_setstate_cython)) { + setstate_cython = __Pyx_PyObject_GetAttrStrNoError(type_obj, __pyx_mstate_global->__pyx_n_u_setstate_cython); + if (likely(setstate_cython)) { + ret = __Pyx_SetItemOnTypeDict((PyTypeObject*)type_obj, __pyx_mstate_global->__pyx_n_u_setstate, setstate_cython); if (unlikely(ret < 0)) goto __PYX_BAD; + ret = __Pyx_DelItemOnTypeDict((PyTypeObject*)type_obj, __pyx_mstate_global->__pyx_n_u_setstate_cython); if (unlikely(ret < 0)) goto __PYX_BAD; + } else if (!setstate || PyErr_Occurred()) { + goto __PYX_BAD; + } + } + PyType_Modified((PyTypeObject*)type_obj); + } + } + goto __PYX_GOOD; +__PYX_BAD: + if (!PyErr_Occurred()) { + __Pyx_TypeName type_obj_name = + __Pyx_PyType_GetFullyQualifiedName((PyTypeObject*)type_obj); + PyErr_Format(PyExc_RuntimeError, + "Unable to initialize pickling for " __Pyx_FMT_TYPENAME, type_obj_name); + __Pyx_DECREF_TypeName(type_obj_name); + } + ret = -1; +__PYX_GOOD: +#if !CYTHON_USE_PYTYPE_LOOKUP + Py_XDECREF(object_reduce); + Py_XDECREF(object_reduce_ex); + Py_XDECREF(object_getstate); + Py_XDECREF(getstate); +#endif + Py_XDECREF(reduce); + Py_XDECREF(reduce_ex); + Py_XDECREF(reduce_cython); + Py_XDECREF(setstate); + Py_XDECREF(setstate_cython); + return ret; +} + +/* TypeImport */ +#ifndef __PYX_HAVE_RT_ImportType_3_2_5 +#define __PYX_HAVE_RT_ImportType_3_2_5 +static PyTypeObject *__Pyx_ImportType_3_2_5(PyObject *module, const char *module_name, const char *class_name, + size_t size, size_t alignment, enum __Pyx_ImportType_CheckSize_3_2_5 check_size) +{ + PyObject *result = 0; + Py_ssize_t basicsize; + Py_ssize_t itemsize; +#if defined(Py_LIMITED_API) || (defined(CYTHON_COMPILING_IN_LIMITED_API) && CYTHON_COMPILING_IN_LIMITED_API) + PyObject *py_basicsize; + PyObject *py_itemsize; +#endif + result = PyObject_GetAttrString(module, class_name); + if (!result) + goto bad; + if (!PyType_Check(result)) { + PyErr_Format(PyExc_TypeError, + "%.200s.%.200s is not a type object", + module_name, class_name); + goto bad; + } +#if !( defined(Py_LIMITED_API) || (defined(CYTHON_COMPILING_IN_LIMITED_API) && CYTHON_COMPILING_IN_LIMITED_API) ) + basicsize = ((PyTypeObject *)result)->tp_basicsize; + itemsize = ((PyTypeObject *)result)->tp_itemsize; +#else + if (size == 0) { + return (PyTypeObject *)result; + } + py_basicsize = PyObject_GetAttrString(result, "__basicsize__"); + if (!py_basicsize) + goto bad; + basicsize = PyLong_AsSsize_t(py_basicsize); + Py_DECREF(py_basicsize); + py_basicsize = 0; + if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred()) + goto bad; + py_itemsize = PyObject_GetAttrString(result, "__itemsize__"); + if (!py_itemsize) + goto bad; + itemsize = PyLong_AsSsize_t(py_itemsize); + Py_DECREF(py_itemsize); + py_itemsize = 0; + if (itemsize == (Py_ssize_t)-1 && PyErr_Occurred()) + goto bad; +#endif + if (itemsize) { + if (size % alignment) { + alignment = size % alignment; + } + if (itemsize < (Py_ssize_t)alignment) + itemsize = (Py_ssize_t)alignment; + } + if ((size_t)(basicsize + itemsize) < size) { + PyErr_Format(PyExc_ValueError, + "%.200s.%.200s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize+itemsize); + goto bad; + } + if (check_size == __Pyx_ImportType_CheckSize_Error_3_2_5 && + ((size_t)basicsize > size || (size_t)(basicsize + itemsize) < size)) { + PyErr_Format(PyExc_ValueError, + "%.200s.%.200s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd-%zd from PyObject", + module_name, class_name, size, basicsize, basicsize+itemsize); + goto bad; + } + else if (check_size == __Pyx_ImportType_CheckSize_Warn_3_2_5 && (size_t)basicsize > size) { + if (PyErr_WarnFormat(NULL, 0, + "%.200s.%.200s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize) < 0) { + goto bad; + } + } + return (PyTypeObject *)result; +bad: + Py_XDECREF(result); + return NULL; +} +#endif + +/* dict_setdefault (used by FetchCommonType) */ +static CYTHON_INLINE PyObject *__Pyx_PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *default_value) { + PyObject* value; +#if __PYX_LIMITED_VERSION_HEX >= 0x030F0000 || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x030d00A4) + PyDict_SetDefaultRef(d, key, default_value, &value); +#elif CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX >= 0x030C0000 + PyObject *args[] = {d, key, default_value}; + value = PyObject_VectorcallMethod(__pyx_mstate_global->__pyx_n_u_setdefault, args, 3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); +#elif CYTHON_COMPILING_IN_LIMITED_API + value = PyObject_CallMethodObjArgs(d, __pyx_mstate_global->__pyx_n_u_setdefault, key, default_value, NULL); +#else + value = PyDict_SetDefault(d, key, default_value); + if (unlikely(!value)) return NULL; + Py_INCREF(value); +#endif + return value; +} + +/* AddModuleRef (used by FetchSharedCythonModule) */ +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + static PyObject *__Pyx_PyImport_AddModuleObjectRef(PyObject *name) { + PyObject *module_dict = PyImport_GetModuleDict(); + PyObject *m; + if (PyMapping_GetOptionalItem(module_dict, name, &m) < 0) { + return NULL; + } + if (m != NULL && PyModule_Check(m)) { + return m; + } + Py_XDECREF(m); + m = PyModule_NewObject(name); + if (m == NULL) + return NULL; + if (PyDict_CheckExact(module_dict)) { + PyObject *new_m; + (void)PyDict_SetDefaultRef(module_dict, name, m, &new_m); + Py_DECREF(m); + return new_m; + } else { + if (PyObject_SetItem(module_dict, name, m) != 0) { + Py_DECREF(m); + return NULL; + } + return m; + } + } + static PyObject *__Pyx_PyImport_AddModuleRef(const char *name) { + PyObject *py_name = PyUnicode_FromString(name); + if (!py_name) return NULL; + PyObject *module = __Pyx_PyImport_AddModuleObjectRef(py_name); + Py_DECREF(py_name); + return module; + } +#elif __PYX_LIMITED_VERSION_HEX >= 0x030d0000 + #define __Pyx_PyImport_AddModuleRef(name) PyImport_AddModuleRef(name) +#else + static PyObject *__Pyx_PyImport_AddModuleRef(const char *name) { + PyObject *module = PyImport_AddModule(name); + Py_XINCREF(module); + return module; + } +#endif + +/* FetchSharedCythonModule (used by FetchCommonType) */ +static PyObject *__Pyx_FetchSharedCythonABIModule(void) { + return __Pyx_PyImport_AddModuleRef(__PYX_ABI_MODULE_NAME); +} + +/* FetchCommonType (used by CommonTypesMetaclass) */ +#if __PYX_LIMITED_VERSION_HEX < 0x030C0000 +static PyObject* __Pyx_PyType_FromMetaclass(PyTypeObject *metaclass, PyObject *module, PyType_Spec *spec, PyObject *bases) { + PyObject *result = __Pyx_PyType_FromModuleAndSpec(module, spec, bases); + if (result && metaclass) { + PyObject *old_tp = (PyObject*)Py_TYPE(result); + Py_INCREF((PyObject*)metaclass); +#if __PYX_LIMITED_VERSION_HEX >= 0x03090000 + Py_SET_TYPE(result, metaclass); +#else + result->ob_type = metaclass; +#endif + Py_DECREF(old_tp); + } + return result; +} +#else +#define __Pyx_PyType_FromMetaclass(me, mo, s, b) PyType_FromMetaclass(me, mo, s, b) +#endif +static int __Pyx_VerifyCachedType(PyObject *cached_type, + const char *name, + Py_ssize_t expected_basicsize) { + Py_ssize_t basicsize; + if (!PyType_Check(cached_type)) { + PyErr_Format(PyExc_TypeError, + "Shared Cython type %.200s is not a type object", name); + return -1; + } + if (expected_basicsize == 0) { + return 0; // size is inherited, nothing useful to check + } +#if CYTHON_COMPILING_IN_LIMITED_API + PyObject *py_basicsize; + py_basicsize = PyObject_GetAttrString(cached_type, "__basicsize__"); + if (unlikely(!py_basicsize)) return -1; + basicsize = PyLong_AsSsize_t(py_basicsize); + Py_DECREF(py_basicsize); + py_basicsize = NULL; + if (unlikely(basicsize == (Py_ssize_t)-1) && PyErr_Occurred()) return -1; +#else + basicsize = ((PyTypeObject*) cached_type)->tp_basicsize; +#endif + if (basicsize != expected_basicsize) { + PyErr_Format(PyExc_TypeError, + "Shared Cython type %.200s has the wrong size, try recompiling", + name); + return -1; + } + return 0; +} +static PyTypeObject *__Pyx_FetchCommonTypeFromSpec(PyTypeObject *metaclass, PyObject *module, PyType_Spec *spec, PyObject *bases) { + PyObject *abi_module = NULL, *cached_type = NULL, *abi_module_dict, *new_cached_type, *py_object_name; + int get_item_ref_result; + const char* object_name = strrchr(spec->name, '.'); + object_name = object_name ? object_name+1 : spec->name; + py_object_name = PyUnicode_FromString(object_name); + if (!py_object_name) return NULL; + abi_module = __Pyx_FetchSharedCythonABIModule(); + if (!abi_module) goto done; + abi_module_dict = PyModule_GetDict(abi_module); + if (!abi_module_dict) goto done; + get_item_ref_result = __Pyx_PyDict_GetItemRef(abi_module_dict, py_object_name, &cached_type); + if (get_item_ref_result == 1) { + if (__Pyx_VerifyCachedType( + cached_type, + object_name, + spec->basicsize) < 0) { + goto bad; + } + goto done; + } else if (unlikely(get_item_ref_result == -1)) { + goto bad; + } + cached_type = __Pyx_PyType_FromMetaclass( + metaclass, + CYTHON_USE_MODULE_STATE ? module : abi_module, + spec, bases); + if (unlikely(!cached_type)) goto bad; + if (unlikely(__Pyx_fix_up_extension_type_from_spec(spec, (PyTypeObject *) cached_type) < 0)) goto bad; + new_cached_type = __Pyx_PyDict_SetDefault(abi_module_dict, py_object_name, cached_type); + if (unlikely(new_cached_type != cached_type)) { + if (unlikely(!new_cached_type)) goto bad; + Py_DECREF(cached_type); + cached_type = new_cached_type; + if (__Pyx_VerifyCachedType( + cached_type, + object_name, + spec->basicsize) < 0) { + goto bad; + } + goto done; + } else { + Py_DECREF(new_cached_type); + } +done: + Py_XDECREF(abi_module); + Py_DECREF(py_object_name); + assert(cached_type == NULL || PyType_Check(cached_type)); + return (PyTypeObject *) cached_type; +bad: + Py_XDECREF(cached_type); + cached_type = NULL; + goto done; +} + +/* CommonTypesMetaclass (used by CythonFunctionShared) */ +static PyObject* __pyx_CommonTypesMetaclass_get_module(CYTHON_UNUSED PyObject *self, CYTHON_UNUSED void* context) { + return PyUnicode_FromString(__PYX_ABI_MODULE_NAME); +} +#if __PYX_LIMITED_VERSION_HEX < 0x030A0000 +static PyObject* __pyx_CommonTypesMetaclass_call(CYTHON_UNUSED PyObject *self, CYTHON_UNUSED PyObject *args, CYTHON_UNUSED PyObject *kwds) { + PyErr_SetString(PyExc_TypeError, "Cannot instantiate Cython internal types"); + return NULL; +} +static int __pyx_CommonTypesMetaclass_setattr(CYTHON_UNUSED PyObject *self, CYTHON_UNUSED PyObject *attr, CYTHON_UNUSED PyObject *value) { + PyErr_SetString(PyExc_TypeError, "Cython internal types are immutable"); + return -1; +} +#endif +static PyGetSetDef __pyx_CommonTypesMetaclass_getset[] = { + {"__module__", __pyx_CommonTypesMetaclass_get_module, NULL, NULL, NULL}, + {0, 0, 0, 0, 0} +}; +static PyType_Slot __pyx_CommonTypesMetaclass_slots[] = { + {Py_tp_getset, (void *)__pyx_CommonTypesMetaclass_getset}, + #if __PYX_LIMITED_VERSION_HEX < 0x030A0000 + {Py_tp_call, (void*)__pyx_CommonTypesMetaclass_call}, + {Py_tp_new, (void*)__pyx_CommonTypesMetaclass_call}, + {Py_tp_setattro, (void*)__pyx_CommonTypesMetaclass_setattr}, + #endif + {0, 0} +}; +static PyType_Spec __pyx_CommonTypesMetaclass_spec = { + __PYX_TYPE_MODULE_PREFIX "_common_types_metatype", + 0, + 0, + Py_TPFLAGS_IMMUTABLETYPE | + Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_DEFAULT, + __pyx_CommonTypesMetaclass_slots +}; +static int __pyx_CommonTypesMetaclass_init(PyObject *module) { + __pyx_mstatetype *mstate = __Pyx_PyModule_GetState(module); + PyObject *bases = PyTuple_Pack(1, &PyType_Type); + if (unlikely(!bases)) { + return -1; + } + mstate->__pyx_CommonTypesMetaclassType = __Pyx_FetchCommonTypeFromSpec(NULL, module, &__pyx_CommonTypesMetaclass_spec, bases); + Py_DECREF(bases); + if (unlikely(mstate->__pyx_CommonTypesMetaclassType == NULL)) { + return -1; + } + return 0; +} + +/* PyMethodNew (used by CythonFunctionShared) */ +#if CYTHON_COMPILING_IN_LIMITED_API +static PyObject *__Pyx_PyMethod_New(PyObject *func, PyObject *self, PyObject *typ) { + PyObject *result; + CYTHON_UNUSED_VAR(typ); + if (!self) + return __Pyx_NewRef(func); + #if __PYX_LIMITED_VERSION_HEX >= 0x030C0000 + { + PyObject *args[] = {func, self}; + result = PyObject_Vectorcall(__pyx_mstate_global->__Pyx_CachedMethodType, args, 2, NULL); + } + #else + result = PyObject_CallFunctionObjArgs(__pyx_mstate_global->__Pyx_CachedMethodType, func, self, NULL); + #endif + return result; +} +#else +static PyObject *__Pyx_PyMethod_New(PyObject *func, PyObject *self, PyObject *typ) { + CYTHON_UNUSED_VAR(typ); + if (!self) + return __Pyx_NewRef(func); + return PyMethod_New(func, self); +} +#endif + +/* PyVectorcallFastCallDict (used by CythonFunctionShared) */ +#if CYTHON_METH_FASTCALL && CYTHON_VECTORCALL +static PyObject *__Pyx_PyVectorcall_FastCallDict_kw(PyObject *func, __pyx_vectorcallfunc vc, PyObject *const *args, size_t nargs, PyObject *kw) +{ + PyObject *res = NULL; + PyObject *kwnames; + PyObject **newargs; + PyObject **kwvalues; + Py_ssize_t i; + #if CYTHON_AVOID_BORROWED_REFS + PyObject *pos; + #else + Py_ssize_t pos; + #endif + size_t j; + PyObject *key, *value; + unsigned long keys_are_strings; + #if !CYTHON_ASSUME_SAFE_SIZE + Py_ssize_t nkw = PyDict_Size(kw); + if (unlikely(nkw == -1)) return NULL; + #else + Py_ssize_t nkw = PyDict_GET_SIZE(kw); + #endif + newargs = (PyObject **)PyMem_Malloc((nargs + (size_t)nkw) * sizeof(args[0])); + if (unlikely(newargs == NULL)) { + PyErr_NoMemory(); + return NULL; + } + for (j = 0; j < nargs; j++) newargs[j] = args[j]; + kwnames = PyTuple_New(nkw); + if (unlikely(kwnames == NULL)) { + PyMem_Free(newargs); + return NULL; + } + kwvalues = newargs + nargs; + pos = 0; + i = 0; + keys_are_strings = Py_TPFLAGS_UNICODE_SUBCLASS; + while (__Pyx_PyDict_NextRef(kw, &pos, &key, &value)) { + keys_are_strings &= + #if CYTHON_COMPILING_IN_LIMITED_API + PyType_GetFlags(Py_TYPE(key)); + #else + Py_TYPE(key)->tp_flags; + #endif + #if !CYTHON_ASSUME_SAFE_MACROS + if (unlikely(PyTuple_SetItem(kwnames, i, key) < 0)) goto cleanup; + #else + PyTuple_SET_ITEM(kwnames, i, key); + #endif + kwvalues[i] = value; + i++; + } + if (unlikely(!keys_are_strings)) { + PyErr_SetString(PyExc_TypeError, "keywords must be strings"); + goto cleanup; + } + res = vc(func, newargs, nargs, kwnames); +cleanup: + #if CYTHON_AVOID_BORROWED_REFS + Py_DECREF(pos); + #endif + Py_DECREF(kwnames); + for (i = 0; i < nkw; i++) + Py_DECREF(kwvalues[i]); + PyMem_Free(newargs); + return res; +} +static CYTHON_INLINE PyObject *__Pyx_PyVectorcall_FastCallDict(PyObject *func, __pyx_vectorcallfunc vc, PyObject *const *args, size_t nargs, PyObject *kw) +{ + Py_ssize_t kw_size = + likely(kw == NULL) ? + 0 : +#if !CYTHON_ASSUME_SAFE_SIZE + PyDict_Size(kw); +#else + PyDict_GET_SIZE(kw); +#endif + if (kw_size == 0) { + return vc(func, args, nargs, NULL); + } +#if !CYTHON_ASSUME_SAFE_SIZE + else if (unlikely(kw_size == -1)) { + return NULL; + } +#endif + return __Pyx_PyVectorcall_FastCallDict_kw(func, vc, args, nargs, kw); +} +#endif + +/* CythonFunctionShared (used by CythonFunction) */ +#if CYTHON_COMPILING_IN_LIMITED_API +static CYTHON_INLINE int __Pyx__IsSameCyOrCFunctionNoMethod(PyObject *func, void (*cfunc)(void)) { + if (__Pyx_CyFunction_Check(func)) { + return PyCFunction_GetFunction(((__pyx_CyFunctionObject*)func)->func) == (PyCFunction) cfunc; + } else if (PyCFunction_Check(func)) { + return PyCFunction_GetFunction(func) == (PyCFunction) cfunc; + } + return 0; +} +static CYTHON_INLINE int __Pyx__IsSameCyOrCFunction(PyObject *func, void (*cfunc)(void)) { + if ((PyObject*)Py_TYPE(func) == __pyx_mstate_global->__Pyx_CachedMethodType) { + int result; + PyObject *newFunc = PyObject_GetAttr(func, __pyx_mstate_global->__pyx_n_u_func); + if (unlikely(!newFunc)) { + PyErr_Clear(); // It's only an optimization, so don't throw an error + return 0; + } + result = __Pyx__IsSameCyOrCFunctionNoMethod(newFunc, cfunc); + Py_DECREF(newFunc); + return result; + } + return __Pyx__IsSameCyOrCFunctionNoMethod(func, cfunc); +} +#else +static CYTHON_INLINE int __Pyx__IsSameCyOrCFunction(PyObject *func, void (*cfunc)(void)) { + if (PyMethod_Check(func)) { + func = PyMethod_GET_FUNCTION(func); + } + return __Pyx_CyOrPyCFunction_Check(func) && __Pyx_CyOrPyCFunction_GET_FUNCTION(func) == (PyCFunction) cfunc; +} +#endif +static CYTHON_INLINE void __Pyx__CyFunction_SetClassObj(__pyx_CyFunctionObject* f, PyObject* classobj) { +#if PY_VERSION_HEX < 0x030900B1 || CYTHON_COMPILING_IN_LIMITED_API + __Pyx_Py_XDECREF_SET( + __Pyx_CyFunction_GetClassObj(f), + ((classobj) ? __Pyx_NewRef(classobj) : NULL)); +#else + __Pyx_Py_XDECREF_SET( + ((PyCMethodObject *) (f))->mm_class, + (PyTypeObject*)((classobj) ? __Pyx_NewRef(classobj) : NULL)); +#endif +} +static PyObject * +__Pyx_CyFunction_get_doc_locked(__pyx_CyFunctionObject *op) +{ + if (unlikely(op->func_doc == NULL)) { +#if CYTHON_COMPILING_IN_LIMITED_API + op->func_doc = PyObject_GetAttrString(op->func, "__doc__"); + if (unlikely(!op->func_doc)) return NULL; +#else + if (((PyCFunctionObject*)op)->m_ml->ml_doc) { + op->func_doc = PyUnicode_FromString(((PyCFunctionObject*)op)->m_ml->ml_doc); + if (unlikely(op->func_doc == NULL)) + return NULL; + } else { + Py_INCREF(Py_None); + return Py_None; + } +#endif + } + Py_INCREF(op->func_doc); + return op->func_doc; +} +static PyObject * +__Pyx_CyFunction_get_doc(__pyx_CyFunctionObject *op, void *closure) { + PyObject *result; + CYTHON_UNUSED_VAR(closure); + __Pyx_BEGIN_CRITICAL_SECTION(op); + result = __Pyx_CyFunction_get_doc_locked(op); + __Pyx_END_CRITICAL_SECTION(); + return result; +} +static int +__Pyx_CyFunction_set_doc(__pyx_CyFunctionObject *op, PyObject *value, void *context) +{ + CYTHON_UNUSED_VAR(context); + if (value == NULL) { + value = Py_None; + } + Py_INCREF(value); + __Pyx_BEGIN_CRITICAL_SECTION(op); + __Pyx_Py_XDECREF_SET(op->func_doc, value); + __Pyx_END_CRITICAL_SECTION(); + return 0; +} +static PyObject * +__Pyx_CyFunction_get_name_locked(__pyx_CyFunctionObject *op) +{ + if (unlikely(op->func_name == NULL)) { +#if CYTHON_COMPILING_IN_LIMITED_API + op->func_name = PyObject_GetAttrString(op->func, "__name__"); +#else + op->func_name = PyUnicode_InternFromString(((PyCFunctionObject*)op)->m_ml->ml_name); +#endif + if (unlikely(op->func_name == NULL)) + return NULL; + } + Py_INCREF(op->func_name); + return op->func_name; +} +static PyObject * +__Pyx_CyFunction_get_name(__pyx_CyFunctionObject *op, void *context) +{ + PyObject *result = NULL; + CYTHON_UNUSED_VAR(context); + __Pyx_BEGIN_CRITICAL_SECTION(op); + result = __Pyx_CyFunction_get_name_locked(op); + __Pyx_END_CRITICAL_SECTION(); + return result; +} +static int +__Pyx_CyFunction_set_name(__pyx_CyFunctionObject *op, PyObject *value, void *context) +{ + CYTHON_UNUSED_VAR(context); + if (unlikely(value == NULL || !PyUnicode_Check(value))) { + PyErr_SetString(PyExc_TypeError, + "__name__ must be set to a string object"); + return -1; + } + Py_INCREF(value); + __Pyx_BEGIN_CRITICAL_SECTION(op); + __Pyx_Py_XDECREF_SET(op->func_name, value); + __Pyx_END_CRITICAL_SECTION(); + return 0; +} +static PyObject * +__Pyx_CyFunction_get_qualname(__pyx_CyFunctionObject *op, void *context) +{ + CYTHON_UNUSED_VAR(context); + PyObject *result; + __Pyx_BEGIN_CRITICAL_SECTION(op); + Py_INCREF(op->func_qualname); + result = op->func_qualname; + __Pyx_END_CRITICAL_SECTION(); + return result; +} +static int +__Pyx_CyFunction_set_qualname(__pyx_CyFunctionObject *op, PyObject *value, void *context) +{ + CYTHON_UNUSED_VAR(context); + if (unlikely(value == NULL || !PyUnicode_Check(value))) { + PyErr_SetString(PyExc_TypeError, + "__qualname__ must be set to a string object"); + return -1; + } + Py_INCREF(value); + __Pyx_BEGIN_CRITICAL_SECTION(op); + __Pyx_Py_XDECREF_SET(op->func_qualname, value); + __Pyx_END_CRITICAL_SECTION(); + return 0; +} +#if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030A0000 +static PyObject * +__Pyx_CyFunction_get_dict(__pyx_CyFunctionObject *op, void *context) +{ + CYTHON_UNUSED_VAR(context); + if (unlikely(op->func_dict == NULL)) { + op->func_dict = PyDict_New(); + if (unlikely(op->func_dict == NULL)) + return NULL; + } + Py_INCREF(op->func_dict); + return op->func_dict; +} +#endif +static PyObject * +__Pyx_CyFunction_get_globals(__pyx_CyFunctionObject *op, void *context) +{ + CYTHON_UNUSED_VAR(context); + Py_INCREF(op->func_globals); + return op->func_globals; +} +static PyObject * +__Pyx_CyFunction_get_closure(__pyx_CyFunctionObject *op, void *context) +{ + CYTHON_UNUSED_VAR(op); + CYTHON_UNUSED_VAR(context); + Py_INCREF(Py_None); + return Py_None; +} +static PyObject * +__Pyx_CyFunction_get_code(__pyx_CyFunctionObject *op, void *context) +{ + PyObject* result = (op->func_code) ? op->func_code : Py_None; + CYTHON_UNUSED_VAR(context); + Py_INCREF(result); + return result; +} +static int +__Pyx_CyFunction_init_defaults(__pyx_CyFunctionObject *op) { + int result = 0; + PyObject *res = op->defaults_getter((PyObject *) op); + if (unlikely(!res)) + return -1; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + op->defaults_tuple = PyTuple_GET_ITEM(res, 0); + Py_INCREF(op->defaults_tuple); + op->defaults_kwdict = PyTuple_GET_ITEM(res, 1); + Py_INCREF(op->defaults_kwdict); + #else + op->defaults_tuple = __Pyx_PySequence_ITEM(res, 0); + if (unlikely(!op->defaults_tuple)) result = -1; + else { + op->defaults_kwdict = __Pyx_PySequence_ITEM(res, 1); + if (unlikely(!op->defaults_kwdict)) result = -1; + } + #endif + Py_DECREF(res); + return result; +} +static int +__Pyx_CyFunction_set_defaults(__pyx_CyFunctionObject *op, PyObject* value, void *context) { + CYTHON_UNUSED_VAR(context); + if (!value) { + value = Py_None; + } else if (unlikely(value != Py_None && !PyTuple_Check(value))) { + PyErr_SetString(PyExc_TypeError, + "__defaults__ must be set to a tuple object"); + return -1; + } + PyErr_WarnEx(PyExc_RuntimeWarning, "changes to cyfunction.__defaults__ will not " + "currently affect the values used in function calls", 1); + Py_INCREF(value); + __Pyx_BEGIN_CRITICAL_SECTION(op); + __Pyx_Py_XDECREF_SET(op->defaults_tuple, value); + __Pyx_END_CRITICAL_SECTION(); + return 0; +} +static PyObject * +__Pyx_CyFunction_get_defaults_locked(__pyx_CyFunctionObject *op) { + PyObject* result = op->defaults_tuple; + if (unlikely(!result)) { + if (op->defaults_getter) { + if (unlikely(__Pyx_CyFunction_init_defaults(op) < 0)) return NULL; + result = op->defaults_tuple; + } else { + result = Py_None; + } + } + Py_INCREF(result); + return result; +} +static PyObject * +__Pyx_CyFunction_get_defaults(__pyx_CyFunctionObject *op, void *context) { + PyObject* result = NULL; + CYTHON_UNUSED_VAR(context); + __Pyx_BEGIN_CRITICAL_SECTION(op); + result = __Pyx_CyFunction_get_defaults_locked(op); + __Pyx_END_CRITICAL_SECTION(); + return result; +} +static int +__Pyx_CyFunction_set_kwdefaults(__pyx_CyFunctionObject *op, PyObject* value, void *context) { + CYTHON_UNUSED_VAR(context); + if (!value) { + value = Py_None; + } else if (unlikely(value != Py_None && !PyDict_Check(value))) { + PyErr_SetString(PyExc_TypeError, + "__kwdefaults__ must be set to a dict object"); + return -1; + } + PyErr_WarnEx(PyExc_RuntimeWarning, "changes to cyfunction.__kwdefaults__ will not " + "currently affect the values used in function calls", 1); + Py_INCREF(value); + __Pyx_BEGIN_CRITICAL_SECTION(op); + __Pyx_Py_XDECREF_SET(op->defaults_kwdict, value); + __Pyx_END_CRITICAL_SECTION(); + return 0; +} +static PyObject * +__Pyx_CyFunction_get_kwdefaults_locked(__pyx_CyFunctionObject *op) { + PyObject* result = op->defaults_kwdict; + if (unlikely(!result)) { + if (op->defaults_getter) { + if (unlikely(__Pyx_CyFunction_init_defaults(op) < 0)) return NULL; + result = op->defaults_kwdict; + } else { + result = Py_None; + } + } + Py_INCREF(result); + return result; +} +static PyObject * +__Pyx_CyFunction_get_kwdefaults(__pyx_CyFunctionObject *op, void *context) { + PyObject* result; + CYTHON_UNUSED_VAR(context); + __Pyx_BEGIN_CRITICAL_SECTION(op); + result = __Pyx_CyFunction_get_kwdefaults_locked(op); + __Pyx_END_CRITICAL_SECTION(); + return result; +} +static int +__Pyx_CyFunction_set_annotations(__pyx_CyFunctionObject *op, PyObject* value, void *context) { + CYTHON_UNUSED_VAR(context); + if (!value || value == Py_None) { + value = NULL; + } else if (unlikely(!PyDict_Check(value))) { + PyErr_SetString(PyExc_TypeError, + "__annotations__ must be set to a dict object"); + return -1; + } + Py_XINCREF(value); + __Pyx_BEGIN_CRITICAL_SECTION(op); + __Pyx_Py_XDECREF_SET(op->func_annotations, value); + __Pyx_END_CRITICAL_SECTION(); + return 0; +} +static PyObject * +__Pyx_CyFunction_get_annotations_locked(__pyx_CyFunctionObject *op) { + PyObject* result = op->func_annotations; + if (unlikely(!result)) { + result = PyDict_New(); + if (unlikely(!result)) return NULL; + op->func_annotations = result; + } + Py_INCREF(result); + return result; +} +static PyObject * +__Pyx_CyFunction_get_annotations(__pyx_CyFunctionObject *op, void *context) { + PyObject *result; + CYTHON_UNUSED_VAR(context); + __Pyx_BEGIN_CRITICAL_SECTION(op); + result = __Pyx_CyFunction_get_annotations_locked(op); + __Pyx_END_CRITICAL_SECTION(); + return result; +} +static PyObject * +__Pyx_CyFunction_get_is_coroutine_value(__pyx_CyFunctionObject *op) { + int is_coroutine = op->flags & __Pyx_CYFUNCTION_COROUTINE; + if (is_coroutine) { + PyObject *is_coroutine_value, *module, *fromlist, *marker = __pyx_mstate_global->__pyx_n_u_is_coroutine; + fromlist = PyList_New(1); + if (unlikely(!fromlist)) return NULL; + Py_INCREF(marker); +#if CYTHON_ASSUME_SAFE_MACROS + PyList_SET_ITEM(fromlist, 0, marker); +#else + if (unlikely(PyList_SetItem(fromlist, 0, marker) < 0)) { + Py_DECREF(fromlist); + return NULL; + } +#endif + module = PyImport_ImportModuleLevelObject(__pyx_mstate_global->__pyx_n_u_asyncio_coroutines, NULL, NULL, fromlist, 0); + Py_DECREF(fromlist); + if (unlikely(!module)) goto ignore; + is_coroutine_value = __Pyx_PyObject_GetAttrStr(module, marker); + Py_DECREF(module); + if (likely(is_coroutine_value)) { + return is_coroutine_value; + } +ignore: + PyErr_Clear(); + } + return __Pyx_PyBool_FromLong(is_coroutine); +} +static PyObject * +__Pyx_CyFunction_get_is_coroutine(__pyx_CyFunctionObject *op, void *context) { + PyObject *result; + CYTHON_UNUSED_VAR(context); + if (op->func_is_coroutine) { + return __Pyx_NewRef(op->func_is_coroutine); + } + result = __Pyx_CyFunction_get_is_coroutine_value(op); + if (unlikely(!result)) + return NULL; + __Pyx_BEGIN_CRITICAL_SECTION(op); + if (op->func_is_coroutine) { + Py_DECREF(result); + result = __Pyx_NewRef(op->func_is_coroutine); + } else { + op->func_is_coroutine = __Pyx_NewRef(result); + } + __Pyx_END_CRITICAL_SECTION(); + return result; +} +static void __Pyx_CyFunction_raise_argument_count_error(__pyx_CyFunctionObject *func, const char* message, Py_ssize_t size) { +#if CYTHON_COMPILING_IN_LIMITED_API + PyObject *py_name = __Pyx_CyFunction_get_name(func, NULL); + if (!py_name) return; + PyErr_Format(PyExc_TypeError, + "%.200S() %s (%" CYTHON_FORMAT_SSIZE_T "d given)", + py_name, message, size); + Py_DECREF(py_name); +#else + const char* name = ((PyCFunctionObject*)func)->m_ml->ml_name; + PyErr_Format(PyExc_TypeError, + "%.200s() %s (%" CYTHON_FORMAT_SSIZE_T "d given)", + name, message, size); +#endif +} +static void __Pyx_CyFunction_raise_type_error(__pyx_CyFunctionObject *func, const char* message) { +#if CYTHON_COMPILING_IN_LIMITED_API + PyObject *py_name = __Pyx_CyFunction_get_name(func, NULL); + if (!py_name) return; + PyErr_Format(PyExc_TypeError, + "%.200S() %s", + py_name, message); + Py_DECREF(py_name); +#else + const char* name = ((PyCFunctionObject*)func)->m_ml->ml_name; + PyErr_Format(PyExc_TypeError, + "%.200s() %s", + name, message); +#endif +} +#if CYTHON_COMPILING_IN_LIMITED_API +static PyObject * +__Pyx_CyFunction_get_module(__pyx_CyFunctionObject *op, void *context) { + CYTHON_UNUSED_VAR(context); + return PyObject_GetAttrString(op->func, "__module__"); +} +static int +__Pyx_CyFunction_set_module(__pyx_CyFunctionObject *op, PyObject* value, void *context) { + CYTHON_UNUSED_VAR(context); + return PyObject_SetAttrString(op->func, "__module__", value); +} +#endif +static PyGetSetDef __pyx_CyFunction_getsets[] = { + {"func_doc", (getter)__Pyx_CyFunction_get_doc, (setter)__Pyx_CyFunction_set_doc, 0, 0}, + {"__doc__", (getter)__Pyx_CyFunction_get_doc, (setter)__Pyx_CyFunction_set_doc, 0, 0}, + {"func_name", (getter)__Pyx_CyFunction_get_name, (setter)__Pyx_CyFunction_set_name, 0, 0}, + {"__name__", (getter)__Pyx_CyFunction_get_name, (setter)__Pyx_CyFunction_set_name, 0, 0}, + {"__qualname__", (getter)__Pyx_CyFunction_get_qualname, (setter)__Pyx_CyFunction_set_qualname, 0, 0}, +#if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030A0000 + {"func_dict", (getter)__Pyx_CyFunction_get_dict, (setter)PyObject_GenericSetDict, 0, 0}, + {"__dict__", (getter)__Pyx_CyFunction_get_dict, (setter)PyObject_GenericSetDict, 0, 0}, +#else + {"func_dict", (getter)PyObject_GenericGetDict, (setter)PyObject_GenericSetDict, 0, 0}, + {"__dict__", (getter)PyObject_GenericGetDict, (setter)PyObject_GenericSetDict, 0, 0}, +#endif + {"func_globals", (getter)__Pyx_CyFunction_get_globals, 0, 0, 0}, + {"__globals__", (getter)__Pyx_CyFunction_get_globals, 0, 0, 0}, + {"func_closure", (getter)__Pyx_CyFunction_get_closure, 0, 0, 0}, + {"__closure__", (getter)__Pyx_CyFunction_get_closure, 0, 0, 0}, + {"func_code", (getter)__Pyx_CyFunction_get_code, 0, 0, 0}, + {"__code__", (getter)__Pyx_CyFunction_get_code, 0, 0, 0}, + {"func_defaults", (getter)__Pyx_CyFunction_get_defaults, (setter)__Pyx_CyFunction_set_defaults, 0, 0}, + {"__defaults__", (getter)__Pyx_CyFunction_get_defaults, (setter)__Pyx_CyFunction_set_defaults, 0, 0}, + {"__kwdefaults__", (getter)__Pyx_CyFunction_get_kwdefaults, (setter)__Pyx_CyFunction_set_kwdefaults, 0, 0}, + {"__annotations__", (getter)__Pyx_CyFunction_get_annotations, (setter)__Pyx_CyFunction_set_annotations, 0, 0}, + {"_is_coroutine", (getter)__Pyx_CyFunction_get_is_coroutine, 0, 0, 0}, +#if CYTHON_COMPILING_IN_LIMITED_API + {"__module__", (getter)__Pyx_CyFunction_get_module, (setter)__Pyx_CyFunction_set_module, 0, 0}, +#endif + {0, 0, 0, 0, 0} +}; +static PyMemberDef __pyx_CyFunction_members[] = { +#if !CYTHON_COMPILING_IN_LIMITED_API + {"__module__", T_OBJECT, offsetof(PyCFunctionObject, m_module), 0, 0}, +#endif +#if PY_VERSION_HEX < 0x030C0000 || CYTHON_COMPILING_IN_LIMITED_API + {"__dictoffset__", T_PYSSIZET, offsetof(__pyx_CyFunctionObject, func_dict), READONLY, 0}, +#endif +#if CYTHON_METH_FASTCALL +#if CYTHON_COMPILING_IN_LIMITED_API + {"__vectorcalloffset__", T_PYSSIZET, offsetof(__pyx_CyFunctionObject, func_vectorcall), READONLY, 0}, +#else + {"__vectorcalloffset__", T_PYSSIZET, offsetof(PyCFunctionObject, vectorcall), READONLY, 0}, +#endif +#if CYTHON_COMPILING_IN_LIMITED_API + {"__weaklistoffset__", T_PYSSIZET, offsetof(__pyx_CyFunctionObject, func_weakreflist), READONLY, 0}, +#else + {"__weaklistoffset__", T_PYSSIZET, offsetof(PyCFunctionObject, m_weakreflist), READONLY, 0}, +#endif +#endif + {0, 0, 0, 0, 0} +}; +static PyObject * +__Pyx_CyFunction_reduce(__pyx_CyFunctionObject *m, PyObject *args) +{ + PyObject *result = NULL; + CYTHON_UNUSED_VAR(args); + __Pyx_BEGIN_CRITICAL_SECTION(m); + Py_INCREF(m->func_qualname); + result = m->func_qualname; + __Pyx_END_CRITICAL_SECTION(); + return result; +} +static PyMethodDef __pyx_CyFunction_methods[] = { + {"__reduce__", (PyCFunction)__Pyx_CyFunction_reduce, METH_VARARGS, 0}, + {0, 0, 0, 0} +}; +#if CYTHON_COMPILING_IN_LIMITED_API +#define __Pyx_CyFunction_weakreflist(cyfunc) ((cyfunc)->func_weakreflist) +#else +#define __Pyx_CyFunction_weakreflist(cyfunc) (((PyCFunctionObject*)cyfunc)->m_weakreflist) +#endif +static PyObject *__Pyx_CyFunction_Init(__pyx_CyFunctionObject *op, PyMethodDef *ml, int flags, PyObject* qualname, + PyObject *closure, PyObject *module, PyObject* globals, PyObject* code) { +#if !CYTHON_COMPILING_IN_LIMITED_API + PyCFunctionObject *cf = (PyCFunctionObject*) op; +#endif + if (unlikely(op == NULL)) + return NULL; +#if CYTHON_COMPILING_IN_LIMITED_API + op->func = PyCFunction_NewEx(ml, (PyObject*)op, module); + if (unlikely(!op->func)) return NULL; +#endif + op->flags = flags; + __Pyx_CyFunction_weakreflist(op) = NULL; +#if !CYTHON_COMPILING_IN_LIMITED_API + cf->m_ml = ml; + cf->m_self = (PyObject *) op; +#endif + Py_XINCREF(closure); + op->func_closure = closure; +#if !CYTHON_COMPILING_IN_LIMITED_API + Py_XINCREF(module); + cf->m_module = module; +#endif +#if PY_VERSION_HEX < 0x030C0000 || CYTHON_COMPILING_IN_LIMITED_API + op->func_dict = NULL; +#endif + op->func_name = NULL; + Py_INCREF(qualname); + op->func_qualname = qualname; + op->func_doc = NULL; +#if PY_VERSION_HEX < 0x030900B1 || CYTHON_COMPILING_IN_LIMITED_API + op->func_classobj = NULL; +#else + ((PyCMethodObject*)op)->mm_class = NULL; +#endif + op->func_globals = globals; + Py_INCREF(op->func_globals); + Py_XINCREF(code); + op->func_code = code; + op->defaults = NULL; + op->defaults_tuple = NULL; + op->defaults_kwdict = NULL; + op->defaults_getter = NULL; + op->func_annotations = NULL; + op->func_is_coroutine = NULL; +#if CYTHON_METH_FASTCALL + switch (ml->ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O | METH_KEYWORDS | METH_METHOD)) { + case METH_NOARGS: + __Pyx_CyFunction_func_vectorcall(op) = __Pyx_CyFunction_Vectorcall_NOARGS; + break; + case METH_O: + __Pyx_CyFunction_func_vectorcall(op) = __Pyx_CyFunction_Vectorcall_O; + break; + case METH_METHOD | METH_FASTCALL | METH_KEYWORDS: + __Pyx_CyFunction_func_vectorcall(op) = __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS_METHOD; + break; + case METH_FASTCALL | METH_KEYWORDS: + __Pyx_CyFunction_func_vectorcall(op) = __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS; + break; + case METH_VARARGS | METH_KEYWORDS: + __Pyx_CyFunction_func_vectorcall(op) = NULL; + break; + default: + PyErr_SetString(PyExc_SystemError, "Bad call flags for CyFunction"); + Py_DECREF(op); + return NULL; + } +#endif + return (PyObject *) op; +} +static int +__Pyx_CyFunction_clear(__pyx_CyFunctionObject *m) +{ + Py_CLEAR(m->func_closure); +#if CYTHON_COMPILING_IN_LIMITED_API + Py_CLEAR(m->func); +#else + Py_CLEAR(((PyCFunctionObject*)m)->m_module); +#endif +#if PY_VERSION_HEX < 0x030C0000 || CYTHON_COMPILING_IN_LIMITED_API + Py_CLEAR(m->func_dict); +#elif PY_VERSION_HEX < 0x030d0000 + _PyObject_ClearManagedDict((PyObject*)m); +#else + PyObject_ClearManagedDict((PyObject*)m); +#endif + Py_CLEAR(m->func_name); + Py_CLEAR(m->func_qualname); + Py_CLEAR(m->func_doc); + Py_CLEAR(m->func_globals); + Py_CLEAR(m->func_code); +#if PY_VERSION_HEX < 0x030900B1 || CYTHON_COMPILING_IN_LIMITED_API + Py_CLEAR(__Pyx_CyFunction_GetClassObj(m)); +#else + { + PyObject *cls = (PyObject*) ((PyCMethodObject *) (m))->mm_class; + ((PyCMethodObject *) (m))->mm_class = NULL; + Py_XDECREF(cls); + } +#endif + Py_CLEAR(m->defaults_tuple); + Py_CLEAR(m->defaults_kwdict); + Py_CLEAR(m->func_annotations); + Py_CLEAR(m->func_is_coroutine); + Py_CLEAR(m->defaults); + return 0; +} +static void __Pyx__CyFunction_dealloc(__pyx_CyFunctionObject *m) +{ + if (__Pyx_CyFunction_weakreflist(m) != NULL) + PyObject_ClearWeakRefs((PyObject *) m); + __Pyx_CyFunction_clear(m); + __Pyx_PyHeapTypeObject_GC_Del(m); +} +static void __Pyx_CyFunction_dealloc(__pyx_CyFunctionObject *m) +{ + PyObject_GC_UnTrack(m); + __Pyx__CyFunction_dealloc(m); +} +static int __Pyx_CyFunction_traverse(__pyx_CyFunctionObject *m, visitproc visit, void *arg) +{ + { + int e = __Pyx_call_type_traverse((PyObject*)m, 1, visit, arg); + if (e) return e; + } + Py_VISIT(m->func_closure); +#if CYTHON_COMPILING_IN_LIMITED_API + Py_VISIT(m->func); +#else + Py_VISIT(((PyCFunctionObject*)m)->m_module); +#endif +#if PY_VERSION_HEX < 0x030C0000 || CYTHON_COMPILING_IN_LIMITED_API + Py_VISIT(m->func_dict); +#else + { + int e = +#if PY_VERSION_HEX < 0x030d0000 + _PyObject_VisitManagedDict +#else + PyObject_VisitManagedDict +#endif + ((PyObject*)m, visit, arg); + if (e != 0) return e; + } +#endif + __Pyx_VISIT_CONST(m->func_name); + __Pyx_VISIT_CONST(m->func_qualname); + Py_VISIT(m->func_doc); + Py_VISIT(m->func_globals); + __Pyx_VISIT_CONST(m->func_code); + Py_VISIT(__Pyx_CyFunction_GetClassObj(m)); + Py_VISIT(m->defaults_tuple); + Py_VISIT(m->defaults_kwdict); + Py_VISIT(m->func_annotations); + Py_VISIT(m->func_is_coroutine); + Py_VISIT(m->defaults); + return 0; +} +static PyObject* +__Pyx_CyFunction_repr(__pyx_CyFunctionObject *op) +{ + PyObject *repr; + __Pyx_BEGIN_CRITICAL_SECTION(op); + repr = PyUnicode_FromFormat("", + op->func_qualname, (void *)op); + __Pyx_END_CRITICAL_SECTION(); + return repr; +} +static PyObject * __Pyx_CyFunction_CallMethod(PyObject *func, PyObject *self, PyObject *arg, PyObject *kw) { +#if CYTHON_COMPILING_IN_LIMITED_API + PyObject *f = ((__pyx_CyFunctionObject*)func)->func; + PyCFunction meth; + int flags; + meth = PyCFunction_GetFunction(f); + if (unlikely(!meth)) return NULL; + flags = PyCFunction_GetFlags(f); + if (unlikely(flags < 0)) return NULL; +#else + PyCFunctionObject* f = (PyCFunctionObject*)func; + PyCFunction meth = f->m_ml->ml_meth; + int flags = f->m_ml->ml_flags; +#endif + Py_ssize_t size; + switch (flags & (METH_VARARGS | METH_KEYWORDS | METH_NOARGS | METH_O)) { + case METH_VARARGS: + if (likely(kw == NULL || PyDict_Size(kw) == 0)) + return (*meth)(self, arg); + break; + case METH_VARARGS | METH_KEYWORDS: + return (*(PyCFunctionWithKeywords)(void(*)(void))meth)(self, arg, kw); + case METH_NOARGS: + if (likely(kw == NULL || PyDict_Size(kw) == 0)) { +#if CYTHON_ASSUME_SAFE_SIZE + size = PyTuple_GET_SIZE(arg); +#else + size = PyTuple_Size(arg); + if (unlikely(size < 0)) return NULL; +#endif + if (likely(size == 0)) + return (*meth)(self, NULL); + __Pyx_CyFunction_raise_argument_count_error( + (__pyx_CyFunctionObject*)func, + "takes no arguments", size); + return NULL; + } + break; + case METH_O: + if (likely(kw == NULL || PyDict_Size(kw) == 0)) { +#if CYTHON_ASSUME_SAFE_SIZE + size = PyTuple_GET_SIZE(arg); +#else + size = PyTuple_Size(arg); + if (unlikely(size < 0)) return NULL; +#endif + if (likely(size == 1)) { + PyObject *result, *arg0; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + arg0 = PyTuple_GET_ITEM(arg, 0); + #else + arg0 = __Pyx_PySequence_ITEM(arg, 0); if (unlikely(!arg0)) return NULL; + #endif + result = (*meth)(self, arg0); + #if !(CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS) + Py_DECREF(arg0); + #endif + return result; + } + __Pyx_CyFunction_raise_argument_count_error( + (__pyx_CyFunctionObject*)func, + "takes exactly one argument", size); + return NULL; + } + break; + default: + PyErr_SetString(PyExc_SystemError, "Bad call flags for CyFunction"); + return NULL; + } + __Pyx_CyFunction_raise_type_error( + (__pyx_CyFunctionObject*)func, "takes no keyword arguments"); + return NULL; +} +static CYTHON_INLINE PyObject *__Pyx_CyFunction_Call(PyObject *func, PyObject *arg, PyObject *kw) { + PyObject *self, *result; +#if CYTHON_COMPILING_IN_LIMITED_API + self = PyCFunction_GetSelf(((__pyx_CyFunctionObject*)func)->func); + if (unlikely(!self) && PyErr_Occurred()) return NULL; +#else + self = ((PyCFunctionObject*)func)->m_self; +#endif + result = __Pyx_CyFunction_CallMethod(func, self, arg, kw); + return result; +} +static PyObject *__Pyx_CyFunction_CallAsMethod(PyObject *func, PyObject *args, PyObject *kw) { + PyObject *result; + __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *) func; +#if CYTHON_METH_FASTCALL && CYTHON_VECTORCALL + __pyx_vectorcallfunc vc = __Pyx_CyFunction_func_vectorcall(cyfunc); + if (vc) { +#if CYTHON_ASSUME_SAFE_MACROS && CYTHON_ASSUME_SAFE_SIZE + return __Pyx_PyVectorcall_FastCallDict(func, vc, &PyTuple_GET_ITEM(args, 0), (size_t)PyTuple_GET_SIZE(args), kw); +#else + (void) &__Pyx_PyVectorcall_FastCallDict; + return PyVectorcall_Call(func, args, kw); +#endif + } +#endif + if ((cyfunc->flags & __Pyx_CYFUNCTION_CCLASS) && !(cyfunc->flags & __Pyx_CYFUNCTION_STATICMETHOD)) { + Py_ssize_t argc; + PyObject *new_args; + PyObject *self; +#if CYTHON_ASSUME_SAFE_SIZE + argc = PyTuple_GET_SIZE(args); +#else + argc = PyTuple_Size(args); + if (unlikely(argc < 0)) return NULL; +#endif + new_args = PyTuple_GetSlice(args, 1, argc); + if (unlikely(!new_args)) + return NULL; + self = PyTuple_GetItem(args, 0); + if (unlikely(!self)) { + Py_DECREF(new_args); + PyErr_Format(PyExc_TypeError, + "unbound method %.200S() needs an argument", + cyfunc->func_qualname); + return NULL; + } + result = __Pyx_CyFunction_CallMethod(func, self, new_args, kw); + Py_DECREF(new_args); + } else { + result = __Pyx_CyFunction_Call(func, args, kw); + } + return result; +} +#if CYTHON_METH_FASTCALL && CYTHON_VECTORCALL +static CYTHON_INLINE int __Pyx_CyFunction_Vectorcall_CheckArgs(__pyx_CyFunctionObject *cyfunc, Py_ssize_t nargs, PyObject *kwnames) +{ + int ret = 0; + if ((cyfunc->flags & __Pyx_CYFUNCTION_CCLASS) && !(cyfunc->flags & __Pyx_CYFUNCTION_STATICMETHOD)) { + if (unlikely(nargs < 1)) { + __Pyx_CyFunction_raise_type_error( + cyfunc, "needs an argument"); + return -1; + } + ret = 1; + } + if (unlikely(kwnames) && unlikely(__Pyx_PyTuple_GET_SIZE(kwnames))) { + __Pyx_CyFunction_raise_type_error( + cyfunc, "takes no keyword arguments"); + return -1; + } + return ret; +} +static PyObject * __Pyx_CyFunction_Vectorcall_NOARGS(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) +{ + __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *)func; + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + PyObject *self; +#if CYTHON_COMPILING_IN_LIMITED_API + PyCFunction meth = PyCFunction_GetFunction(cyfunc->func); + if (unlikely(!meth)) return NULL; +#else + PyCFunction meth = ((PyCFunctionObject*)cyfunc)->m_ml->ml_meth; +#endif + switch (__Pyx_CyFunction_Vectorcall_CheckArgs(cyfunc, nargs, kwnames)) { + case 1: + self = args[0]; + args += 1; + nargs -= 1; + break; + case 0: +#if CYTHON_COMPILING_IN_LIMITED_API + self = PyCFunction_GetSelf(((__pyx_CyFunctionObject*)cyfunc)->func); + if (unlikely(!self) && PyErr_Occurred()) return NULL; +#else + self = ((PyCFunctionObject*)cyfunc)->m_self; +#endif + break; + default: + return NULL; + } + if (unlikely(nargs != 0)) { + __Pyx_CyFunction_raise_argument_count_error( + cyfunc, "takes no arguments", nargs); + return NULL; + } + return meth(self, NULL); +} +static PyObject * __Pyx_CyFunction_Vectorcall_O(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) +{ + __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *)func; + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + PyObject *self; +#if CYTHON_COMPILING_IN_LIMITED_API + PyCFunction meth = PyCFunction_GetFunction(cyfunc->func); + if (unlikely(!meth)) return NULL; +#else + PyCFunction meth = ((PyCFunctionObject*)cyfunc)->m_ml->ml_meth; +#endif + switch (__Pyx_CyFunction_Vectorcall_CheckArgs(cyfunc, nargs, kwnames)) { + case 1: + self = args[0]; + args += 1; + nargs -= 1; + break; + case 0: +#if CYTHON_COMPILING_IN_LIMITED_API + self = PyCFunction_GetSelf(((__pyx_CyFunctionObject*)cyfunc)->func); + if (unlikely(!self) && PyErr_Occurred()) return NULL; +#else + self = ((PyCFunctionObject*)cyfunc)->m_self; +#endif + break; + default: + return NULL; + } + if (unlikely(nargs != 1)) { + __Pyx_CyFunction_raise_argument_count_error( + cyfunc, "takes exactly one argument", nargs); + return NULL; + } + return meth(self, args[0]); +} +static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) +{ + __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *)func; + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + PyObject *self; +#if CYTHON_COMPILING_IN_LIMITED_API + PyCFunction meth = PyCFunction_GetFunction(cyfunc->func); + if (unlikely(!meth)) return NULL; +#else + PyCFunction meth = ((PyCFunctionObject*)cyfunc)->m_ml->ml_meth; +#endif + switch (__Pyx_CyFunction_Vectorcall_CheckArgs(cyfunc, nargs, NULL)) { + case 1: + self = args[0]; + args += 1; + nargs -= 1; + break; + case 0: +#if CYTHON_COMPILING_IN_LIMITED_API + self = PyCFunction_GetSelf(((__pyx_CyFunctionObject*)cyfunc)->func); + if (unlikely(!self) && PyErr_Occurred()) return NULL; +#else + self = ((PyCFunctionObject*)cyfunc)->m_self; +#endif + break; + default: + return NULL; + } + return ((__Pyx_PyCFunctionFastWithKeywords)(void(*)(void))meth)(self, args, nargs, kwnames); +} +static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS_METHOD(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) +{ + __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *)func; + PyTypeObject *cls = (PyTypeObject *) __Pyx_CyFunction_GetClassObj(cyfunc); + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + PyObject *self; +#if CYTHON_COMPILING_IN_LIMITED_API + PyCFunction meth = PyCFunction_GetFunction(cyfunc->func); + if (unlikely(!meth)) return NULL; +#else + PyCFunction meth = ((PyCFunctionObject*)cyfunc)->m_ml->ml_meth; +#endif + switch (__Pyx_CyFunction_Vectorcall_CheckArgs(cyfunc, nargs, NULL)) { + case 1: + self = args[0]; + args += 1; + nargs -= 1; + break; + case 0: +#if CYTHON_COMPILING_IN_LIMITED_API + self = PyCFunction_GetSelf(((__pyx_CyFunctionObject*)cyfunc)->func); + if (unlikely(!self) && PyErr_Occurred()) return NULL; +#else + self = ((PyCFunctionObject*)cyfunc)->m_self; +#endif + break; + default: + return NULL; + } + #if PY_VERSION_HEX < 0x030e00A6 + size_t nargs_value = (size_t) nargs; + #else + Py_ssize_t nargs_value = nargs; + #endif + return ((__Pyx_PyCMethod)(void(*)(void))meth)(self, cls, args, nargs_value, kwnames); +} +#endif +static PyType_Slot __pyx_CyFunctionType_slots[] = { + {Py_tp_dealloc, (void *)__Pyx_CyFunction_dealloc}, + {Py_tp_repr, (void *)__Pyx_CyFunction_repr}, + {Py_tp_call, (void *)__Pyx_CyFunction_CallAsMethod}, + {Py_tp_traverse, (void *)__Pyx_CyFunction_traverse}, + {Py_tp_clear, (void *)__Pyx_CyFunction_clear}, + {Py_tp_methods, (void *)__pyx_CyFunction_methods}, + {Py_tp_members, (void *)__pyx_CyFunction_members}, + {Py_tp_getset, (void *)__pyx_CyFunction_getsets}, + {Py_tp_descr_get, (void *)__Pyx_PyMethod_New}, + {0, 0}, +}; +static PyType_Spec __pyx_CyFunctionType_spec = { + __PYX_TYPE_MODULE_PREFIX "cython_function_or_method", + sizeof(__pyx_CyFunctionObject), + 0, +#ifdef Py_TPFLAGS_METHOD_DESCRIPTOR + Py_TPFLAGS_METHOD_DESCRIPTOR | +#endif +#if CYTHON_METH_FASTCALL +#if defined(Py_TPFLAGS_HAVE_VECTORCALL) + Py_TPFLAGS_HAVE_VECTORCALL | +#elif defined(_Py_TPFLAGS_HAVE_VECTORCALL) + _Py_TPFLAGS_HAVE_VECTORCALL | +#endif +#endif // CYTHON_METH_FASTCALL +#if PY_VERSION_HEX >= 0x030C0000 && !CYTHON_COMPILING_IN_LIMITED_API + Py_TPFLAGS_MANAGED_DICT | +#endif + Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + __pyx_CyFunctionType_slots +}; +static int __pyx_CyFunction_init(PyObject *module) { + __pyx_mstatetype *mstate = __Pyx_PyModule_GetState(module); + mstate->__pyx_CyFunctionType = __Pyx_FetchCommonTypeFromSpec( + mstate->__pyx_CommonTypesMetaclassType, module, &__pyx_CyFunctionType_spec, NULL); + if (unlikely(mstate->__pyx_CyFunctionType == NULL)) { + return -1; + } + return 0; +} +static CYTHON_INLINE PyObject *__Pyx_CyFunction_InitDefaults(PyObject *func, PyTypeObject *defaults_type) { + __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func; + m->defaults = PyObject_CallObject((PyObject*)defaults_type, NULL); // _PyObject_New(defaults_type); + if (unlikely(!m->defaults)) + return NULL; + return m->defaults; +} +static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsTuple(PyObject *func, PyObject *tuple) { + __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func; + m->defaults_tuple = tuple; + Py_INCREF(tuple); +} +static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsKwDict(PyObject *func, PyObject *dict) { + __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func; + m->defaults_kwdict = dict; + Py_INCREF(dict); +} +static CYTHON_INLINE void __Pyx_CyFunction_SetAnnotationsDict(PyObject *func, PyObject *dict) { + __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func; + m->func_annotations = dict; + Py_INCREF(dict); +} + +/* CythonFunction */ +static PyObject *__Pyx_CyFunction_New(PyMethodDef *ml, int flags, PyObject* qualname, + PyObject *closure, PyObject *module, PyObject* globals, PyObject* code) { + PyObject *op = __Pyx_CyFunction_Init( + PyObject_GC_New(__pyx_CyFunctionObject, __pyx_mstate_global->__pyx_CyFunctionType), + ml, flags, qualname, closure, module, globals, code + ); + if (likely(op)) { + PyObject_GC_Track(op); + } + return op; +} + +/* CLineInTraceback (used by AddTraceback) */ +#if CYTHON_CLINE_IN_TRACEBACK && CYTHON_CLINE_IN_TRACEBACK_RUNTIME +#if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030A0000 +#define __Pyx_PyProbablyModule_GetDict(o) __Pyx_XNewRef(PyModule_GetDict(o)) +#elif !CYTHON_COMPILING_IN_CPYTHON || CYTHON_COMPILING_IN_CPYTHON_FREETHREADING +#define __Pyx_PyProbablyModule_GetDict(o) PyObject_GenericGetDict(o, NULL); +#else +PyObject* __Pyx_PyProbablyModule_GetDict(PyObject *o) { + PyObject **dict_ptr = _PyObject_GetDictPtr(o); + return dict_ptr ? __Pyx_XNewRef(*dict_ptr) : NULL; +} +#endif +static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line) { + PyObject *use_cline = NULL; + PyObject *ptype, *pvalue, *ptraceback; + PyObject *cython_runtime_dict; + CYTHON_MAYBE_UNUSED_VAR(tstate); + if (unlikely(!__pyx_mstate_global->__pyx_cython_runtime)) { + return c_line; + } + __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); + cython_runtime_dict = __Pyx_PyProbablyModule_GetDict(__pyx_mstate_global->__pyx_cython_runtime); + if (likely(cython_runtime_dict)) { + __PYX_PY_DICT_LOOKUP_IF_MODIFIED( + use_cline, cython_runtime_dict, + __Pyx_PyDict_SetDefault(cython_runtime_dict, __pyx_mstate_global->__pyx_n_u_cline_in_traceback, Py_False)) + } + if (use_cline == NULL || use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { + c_line = 0; + } + Py_XDECREF(use_cline); + Py_XDECREF(cython_runtime_dict); + __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); + return c_line; +} +#endif + +/* CodeObjectCache (used by AddTraceback) */ +static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) { + int start = 0, mid = 0, end = count - 1; + if (end >= 0 && code_line > entries[end].code_line) { + return count; + } + while (start < end) { + mid = start + (end - start) / 2; + if (code_line < entries[mid].code_line) { + end = mid; + } else if (code_line > entries[mid].code_line) { + start = mid + 1; + } else { + return mid; + } + } + if (code_line <= entries[mid].code_line) { + return mid; + } else { + return mid + 1; + } +} +static __Pyx_CachedCodeObjectType *__pyx__find_code_object(struct __Pyx_CodeObjectCache *code_cache, int code_line) { + __Pyx_CachedCodeObjectType* code_object; + int pos; + if (unlikely(!code_line) || unlikely(!code_cache->entries)) { + return NULL; + } + pos = __pyx_bisect_code_objects(code_cache->entries, code_cache->count, code_line); + if (unlikely(pos >= code_cache->count) || unlikely(code_cache->entries[pos].code_line != code_line)) { + return NULL; + } + code_object = code_cache->entries[pos].code_object; + Py_INCREF(code_object); + return code_object; +} +static __Pyx_CachedCodeObjectType *__pyx_find_code_object(int code_line) { +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING && !CYTHON_ATOMICS + (void)__pyx__find_code_object; + return NULL; // Most implementation should have atomics. But otherwise, don't make it thread-safe, just miss. +#else + struct __Pyx_CodeObjectCache *code_cache = &__pyx_mstate_global->__pyx_code_cache; +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + __pyx_nonatomic_int_type old_count = __pyx_atomic_incr_acq_rel(&code_cache->accessor_count); + if (old_count < 0) { + __pyx_atomic_decr_acq_rel(&code_cache->accessor_count); + return NULL; + } +#endif + __Pyx_CachedCodeObjectType *result = __pyx__find_code_object(code_cache, code_line); +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + __pyx_atomic_decr_acq_rel(&code_cache->accessor_count); +#endif + return result; +#endif +} +static void __pyx__insert_code_object(struct __Pyx_CodeObjectCache *code_cache, int code_line, __Pyx_CachedCodeObjectType* code_object) +{ + int pos, i; + __Pyx_CodeObjectCacheEntry* entries = code_cache->entries; + if (unlikely(!code_line)) { + return; + } + if (unlikely(!entries)) { + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry)); + if (likely(entries)) { + code_cache->entries = entries; + code_cache->max_count = 64; + code_cache->count = 1; + entries[0].code_line = code_line; + entries[0].code_object = code_object; + Py_INCREF(code_object); + } + return; + } + pos = __pyx_bisect_code_objects(code_cache->entries, code_cache->count, code_line); + if ((pos < code_cache->count) && unlikely(code_cache->entries[pos].code_line == code_line)) { + __Pyx_CachedCodeObjectType* tmp = entries[pos].code_object; + entries[pos].code_object = code_object; + Py_INCREF(code_object); + Py_DECREF(tmp); + return; + } + if (code_cache->count == code_cache->max_count) { + int new_max = code_cache->max_count + 64; + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc( + code_cache->entries, ((size_t)new_max) * sizeof(__Pyx_CodeObjectCacheEntry)); + if (unlikely(!entries)) { + return; + } + code_cache->entries = entries; + code_cache->max_count = new_max; + } + for (i=code_cache->count; i>pos; i--) { + entries[i] = entries[i-1]; + } + entries[pos].code_line = code_line; + entries[pos].code_object = code_object; + code_cache->count++; + Py_INCREF(code_object); +} +static void __pyx_insert_code_object(int code_line, __Pyx_CachedCodeObjectType* code_object) { +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING && !CYTHON_ATOMICS + (void)__pyx__insert_code_object; + return; // Most implementation should have atomics. But otherwise, don't make it thread-safe, just fail. +#else + struct __Pyx_CodeObjectCache *code_cache = &__pyx_mstate_global->__pyx_code_cache; +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + __pyx_nonatomic_int_type expected = 0; + if (!__pyx_atomic_int_cmp_exchange(&code_cache->accessor_count, &expected, INT_MIN)) { + return; + } +#endif + __pyx__insert_code_object(code_cache, code_line, code_object); +#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING + __pyx_atomic_sub(&code_cache->accessor_count, INT_MIN); +#endif +#endif +} + +/* AddTraceback */ +#include "compile.h" +#include "frameobject.h" +#include "traceback.h" +#if PY_VERSION_HEX >= 0x030b00a6 && !CYTHON_COMPILING_IN_LIMITED_API && !defined(PYPY_VERSION) + #ifndef Py_BUILD_CORE + #define Py_BUILD_CORE 1 + #endif + #include "internal/pycore_frame.h" +#endif +#if CYTHON_COMPILING_IN_LIMITED_API +static PyObject *__Pyx_PyCode_Replace_For_AddTraceback(PyObject *code, PyObject *scratch_dict, + PyObject *firstlineno, PyObject *name) { + PyObject *replace = NULL; + if (unlikely(PyDict_SetItemString(scratch_dict, "co_firstlineno", firstlineno))) return NULL; + if (unlikely(PyDict_SetItemString(scratch_dict, "co_name", name))) return NULL; + replace = PyObject_GetAttrString(code, "replace"); + if (likely(replace)) { + PyObject *result = PyObject_Call(replace, __pyx_mstate_global->__pyx_empty_tuple, scratch_dict); + Py_DECREF(replace); + return result; + } + PyErr_Clear(); + return NULL; +} +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename) { + PyObject *code_object = NULL, *py_py_line = NULL, *py_funcname = NULL, *dict = NULL; + PyObject *replace = NULL, *getframe = NULL, *frame = NULL; + PyObject *exc_type, *exc_value, *exc_traceback; + int success = 0; + if (c_line) { + c_line = __Pyx_CLineForTraceback(__Pyx_PyThreadState_Current, c_line); + } + PyErr_Fetch(&exc_type, &exc_value, &exc_traceback); + code_object = __pyx_find_code_object(c_line ? -c_line : py_line); + if (!code_object) { + code_object = Py_CompileString("_getframe()", filename, Py_eval_input); + if (unlikely(!code_object)) goto bad; + py_py_line = PyLong_FromLong(py_line); + if (unlikely(!py_py_line)) goto bad; + if (c_line) { + py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + } else { + py_funcname = PyUnicode_FromString(funcname); + } + if (unlikely(!py_funcname)) goto bad; + dict = PyDict_New(); + if (unlikely(!dict)) goto bad; + { + PyObject *old_code_object = code_object; + code_object = __Pyx_PyCode_Replace_For_AddTraceback(code_object, dict, py_py_line, py_funcname); + Py_DECREF(old_code_object); + } + if (unlikely(!code_object)) goto bad; + __pyx_insert_code_object(c_line ? -c_line : py_line, code_object); + } else { + dict = PyDict_New(); + } + getframe = PySys_GetObject("_getframe"); + if (unlikely(!getframe)) goto bad; + if (unlikely(PyDict_SetItemString(dict, "_getframe", getframe))) goto bad; + frame = PyEval_EvalCode(code_object, dict, dict); + if (unlikely(!frame) || frame == Py_None) goto bad; + success = 1; + bad: + PyErr_Restore(exc_type, exc_value, exc_traceback); + Py_XDECREF(code_object); + Py_XDECREF(py_py_line); + Py_XDECREF(py_funcname); + Py_XDECREF(dict); + Py_XDECREF(replace); + if (success) { + PyTraceBack_Here( + (struct _frame*)frame); + } + Py_XDECREF(frame); +} +#else +static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( + const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = NULL; + PyObject *py_funcname = NULL; + if (c_line) { + py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + if (!py_funcname) goto bad; + funcname = PyUnicode_AsUTF8(py_funcname); + if (!funcname) goto bad; + } + py_code = PyCode_NewEmpty(filename, funcname, py_line); + Py_XDECREF(py_funcname); + return py_code; +bad: + Py_XDECREF(py_funcname); + return NULL; +} +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = 0; + PyFrameObject *py_frame = 0; + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject *ptype, *pvalue, *ptraceback; + if (c_line) { + c_line = __Pyx_CLineForTraceback(tstate, c_line); + } + py_code = __pyx_find_code_object(c_line ? -c_line : py_line); + if (!py_code) { + __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); + py_code = __Pyx_CreateCodeObjectForTraceback( + funcname, c_line, py_line, filename); + if (!py_code) { + /* If the code object creation fails, then we should clear the + fetched exception references and propagate the new exception */ + Py_XDECREF(ptype); + Py_XDECREF(pvalue); + Py_XDECREF(ptraceback); + goto bad; + } + __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); + __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); + } + py_frame = PyFrame_New( + tstate, /*PyThreadState *tstate,*/ + py_code, /*PyCodeObject *code,*/ + __pyx_mstate_global->__pyx_d, /*PyObject *globals,*/ + 0 /*PyObject *locals*/ + ); + if (!py_frame) goto bad; + __Pyx_PyFrame_SetLineNumber(py_frame, py_line); + PyTraceBack_Here(py_frame); +bad: + Py_XDECREF(py_code); + Py_XDECREF(py_frame); +} +#endif + +/* MemviewRefcount */ +#include +#ifndef _Py_NO_RETURN +#define _Py_NO_RETURN +#endif +_Py_NO_RETURN +static void __pyx_fatalerror(const char *fmt, ...) { + va_list vargs; + char msg[200]; +#if PY_VERSION_HEX >= 0x030A0000 || defined(HAVE_STDARG_PROTOTYPES) + va_start(vargs, fmt); +#else + va_start(vargs); +#endif + vsnprintf(msg, 200, fmt, vargs); + va_end(vargs); + Py_FatalError(msg); +} +static CYTHON_INLINE int +__pyx_add_acquisition_count_locked(__pyx_atomic_int_type *acquisition_count, + PyThread_type_lock lock) +{ + int result; + PyThread_acquire_lock(lock, 1); + result = (*acquisition_count)++; + PyThread_release_lock(lock); + return result; +} +static CYTHON_INLINE int +__pyx_sub_acquisition_count_locked(__pyx_atomic_int_type *acquisition_count, + PyThread_type_lock lock) +{ + int result; + PyThread_acquire_lock(lock, 1); + result = (*acquisition_count)--; + PyThread_release_lock(lock); + return result; +} +static CYTHON_INLINE void +__Pyx_INC_MEMVIEW(__Pyx_memviewslice *memslice, int have_gil, int lineno) +{ + __pyx_nonatomic_int_type old_acquisition_count; + struct __pyx_memoryview_obj *memview = memslice->memview; + if (unlikely(!memview || (PyObject *) memview == Py_None)) { + return; + } + old_acquisition_count = __pyx_add_acquisition_count(memview); + if (unlikely(old_acquisition_count <= 0)) { + if (likely(old_acquisition_count == 0)) { + if (have_gil) { + Py_INCREF((PyObject *) memview); + } else { + PyGILState_STATE _gilstate = PyGILState_Ensure(); + Py_INCREF((PyObject *) memview); + PyGILState_Release(_gilstate); + } + } else { + __pyx_fatalerror("Acquisition count is %d (line %d)", + old_acquisition_count+1, lineno); + } + } +} +static CYTHON_INLINE void __Pyx_XCLEAR_MEMVIEW(__Pyx_memviewslice *memslice, + int have_gil, int lineno) { + __pyx_nonatomic_int_type old_acquisition_count; + struct __pyx_memoryview_obj *memview = memslice->memview; + if (unlikely(!memview || (PyObject *) memview == Py_None)) { + memslice->memview = NULL; + return; + } + old_acquisition_count = __pyx_sub_acquisition_count(memview); + memslice->data = NULL; + if (likely(old_acquisition_count > 1)) { + memslice->memview = NULL; + } else if (likely(old_acquisition_count == 1)) { + if (have_gil) { + Py_CLEAR(memslice->memview); + } else { + PyGILState_STATE _gilstate = PyGILState_Ensure(); + Py_CLEAR(memslice->memview); + PyGILState_Release(_gilstate); + } + } else { + __pyx_fatalerror("Acquisition count is %d (line %d)", + old_acquisition_count-1, lineno); + } +} + +/* MemviewSliceIsContig */ +static int +__pyx_memviewslice_is_contig(const __Pyx_memviewslice mvs, char order, int ndim) +{ + int i, index, step, start; + Py_ssize_t itemsize = mvs.memview->view.itemsize; + if (order == 'F') { + step = 1; + start = 0; + } else { + step = -1; + start = ndim - 1; + } + for (i = 0; i < ndim; i++) { + index = start + step * i; + if (mvs.suboffsets[index] >= 0 || mvs.strides[index] != itemsize) + return 0; + itemsize *= mvs.shape[index]; + } + return 1; +} + +/* OverlappingSlices */ +static void +__pyx_get_array_memory_extents(__Pyx_memviewslice *slice, + void **out_start, void **out_end, + int ndim, size_t itemsize) +{ + char *start, *end; + int i; + start = end = slice->data; + for (i = 0; i < ndim; i++) { + Py_ssize_t stride = slice->strides[i]; + Py_ssize_t extent = slice->shape[i]; + if (extent == 0) { + *out_start = *out_end = start; + return; + } else { + if (stride > 0) + end += stride * (extent - 1); + else + start += stride * (extent - 1); + } + } + *out_start = start; + *out_end = end + itemsize; +} +static int +__pyx_slices_overlap(__Pyx_memviewslice *slice1, + __Pyx_memviewslice *slice2, + int ndim, size_t itemsize) +{ + void *start1, *end1, *start2, *end2; + __pyx_get_array_memory_extents(slice1, &start1, &end1, ndim, itemsize); + __pyx_get_array_memory_extents(slice2, &start2, &end2, ndim, itemsize); + return (start1 < end2) && (start2 < end1); +} + +/* MemviewSliceInit */ +static int +__Pyx_init_memviewslice(struct __pyx_memoryview_obj *memview, + int ndim, + __Pyx_memviewslice *memviewslice, + int memview_is_new_reference) +{ + __Pyx_RefNannyDeclarations + int i, retval=-1; + Py_buffer *buf = &memview->view; + __Pyx_RefNannySetupContext("init_memviewslice", 0); + if (unlikely(memviewslice->memview || memviewslice->data)) { + PyErr_SetString(PyExc_ValueError, + "memviewslice is already initialized!"); + goto fail; + } + if (buf->strides) { + for (i = 0; i < ndim; i++) { + memviewslice->strides[i] = buf->strides[i]; + } + } else { + Py_ssize_t stride = buf->itemsize; + for (i = ndim - 1; i >= 0; i--) { + memviewslice->strides[i] = stride; + stride *= buf->shape[i]; + } + } + for (i = 0; i < ndim; i++) { + memviewslice->shape[i] = buf->shape[i]; + if (buf->suboffsets) { + memviewslice->suboffsets[i] = buf->suboffsets[i]; + } else { + memviewslice->suboffsets[i] = -1; + } + } + memviewslice->memview = memview; + memviewslice->data = (char *)buf->buf; + if (__pyx_add_acquisition_count(memview) == 0 && !memview_is_new_reference) { + Py_INCREF((PyObject*)memview); + } + retval = 0; + goto no_fail; +fail: + memviewslice->memview = 0; + memviewslice->data = 0; + retval = -1; +no_fail: + __Pyx_RefNannyFinishContext(); + return retval; +} + +/* SliceMemoryviewSlice */ +static void __pyx_memoryview_slice_memviewslice_err_dim(PyObject *error, const char* msg, int dim) { + PyGILState_STATE gilstate = PyGILState_Ensure(); + PyErr_Format(error, msg, dim); + PyGILState_Release(gilstate); +} +static CYTHON_INLINE int __pyx_memoryview_slice_memviewslice( + __Pyx_memviewslice *dst, + Py_ssize_t shape, Py_ssize_t stride, Py_ssize_t suboffset, + int dim, int new_ndim, int *suboffset_dim, + Py_ssize_t start, Py_ssize_t stop, Py_ssize_t step, + int have_start, int have_stop, int have_step, + int is_slice) { + if (!is_slice) { + if (start < 0) { + start += shape; + } + if (unlikely(!(0 <= start && start < shape))) { + __pyx_memoryview_slice_memviewslice_err_dim(PyExc_IndexError, "Index out of bounds (axis %d)", dim); + return -1; + } + } else { + int negative_step; + if (have_step) { + negative_step = step < 0; + if (unlikely(step == 0)) { + __pyx_memoryview_slice_memviewslice_err_dim(PyExc_ValueError, "Step may not be zero (axis %d)", dim); + return -1; + } + } else { + negative_step = 0; + step = 1; + } + if (have_start) { + if (start < 0) { + start += shape; + if (start < 0) { + start = 0; + } + } else if (start >= shape) { + start = negative_step ? (shape - 1) : shape; + } + } else { + start = negative_step ? (shape - 1) : 0; + } + if (have_stop) { + if (stop < 0) { + stop += shape; + if (stop < 0) { + stop = 0; + } + } else if (stop > shape) { + stop = shape; + } + } else { + stop = negative_step ? -1 : shape; + } + Py_ssize_t new_shape = (stop - start) / step; + if ((stop - start) - step * new_shape) { + ++new_shape; + } + if (new_shape < 0) { + new_shape = 0; + } + dst->strides[new_ndim] = stride * step; + dst->shape[new_ndim] = new_shape; + dst->suboffsets[new_ndim] = suboffset; + } + if (suboffset_dim[0] < 0) { + dst->data += start * stride; + } else { + dst->suboffsets[suboffset_dim[0]] += start * stride; + } + if (suboffset >= 0) { + if (!is_slice) { + if (likely(new_ndim == 0)) { + dst->data = ((char **)(dst->data))[0] + suboffset; + } else { + __pyx_memoryview_slice_memviewslice_err_dim( + PyExc_IndexError, + "All dimensions preceding dimension %d must be indexed and not sliced", + dim); + return -1; + } + } else { + suboffset_dim[0] = new_ndim; + } + } + return 0; +} + +/* IsLittleEndian (used by BufferFormatCheck) */ +static CYTHON_INLINE int __Pyx_Is_Little_Endian(void) +{ + union { + uint32_t u32; + uint8_t u8[4]; + } S; + S.u32 = 0x01020304; + return S.u8[0] == 4; +} + +/* BufferFormatCheck (used by MemviewSliceValidateAndInit) */ +static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx, + __Pyx_BufFmt_StackElem* stack, + const __Pyx_TypeInfo* type) { + stack[0].field = &ctx->root; + stack[0].parent_offset = 0; + ctx->root.type = type; + ctx->root.name = "buffer dtype"; + ctx->root.offset = 0; + ctx->head = stack; + ctx->head->field = &ctx->root; + ctx->fmt_offset = 0; + ctx->head->parent_offset = 0; + ctx->new_packmode = '@'; + ctx->enc_packmode = '@'; + ctx->new_count = 1; + ctx->enc_count = 0; + ctx->enc_type = 0; + ctx->is_complex = 0; + ctx->is_valid_array = 0; + ctx->struct_alignment = 0; + while (type->typegroup == 'S') { + ++ctx->head; + ctx->head->field = type->fields; + ctx->head->parent_offset = 0; + type = type->fields->type; + } +} +static int __Pyx_BufFmt_ParseNumber(const char** ts) { + int count; + const char* t = *ts; + if (*t < '0' || *t > '9') { + return -1; + } else { + count = *t++ - '0'; + while (*t >= '0' && *t <= '9') { + count *= 10; + count += *t++ - '0'; + } + } + *ts = t; + return count; +} +static int __Pyx_BufFmt_ExpectNumber(const char **ts) { + int number = __Pyx_BufFmt_ParseNumber(ts); + if (number == -1) + PyErr_Format(PyExc_ValueError,\ + "Does not understand character buffer dtype format string ('%c')", **ts); + return number; +} +static void __Pyx_BufFmt_RaiseUnexpectedChar(char ch) { + PyErr_Format(PyExc_ValueError, + "Unexpected format string character: '%c'", ch); +} +static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) { + switch (ch) { + case '?': return "'bool'"; + case 'c': return "'char'"; + case 'b': return "'signed char'"; + case 'B': return "'unsigned char'"; + case 'h': return "'short'"; + case 'H': return "'unsigned short'"; + case 'i': return "'int'"; + case 'I': return "'unsigned int'"; + case 'l': return "'long'"; + case 'L': return "'unsigned long'"; + case 'q': return "'long long'"; + case 'Q': return "'unsigned long long'"; + case 'f': return (is_complex ? "'complex float'" : "'float'"); + case 'd': return (is_complex ? "'complex double'" : "'double'"); + case 'g': return (is_complex ? "'complex long double'" : "'long double'"); + case 'T': return "a struct"; + case 'O': return "Python object"; + case 'P': return "a pointer"; + case 's': case 'p': return "a string"; + case 0: return "end"; + default: return "unparsable format string"; + } +} +static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) { + switch (ch) { + case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; + case 'h': case 'H': return 2; + case 'i': case 'I': case 'l': case 'L': return 4; + case 'q': case 'Q': return 8; + case 'f': return (is_complex ? 8 : 4); + case 'd': return (is_complex ? 16 : 8); + case 'g': { + PyErr_SetString(PyExc_ValueError, "Python does not define a standard format string size for long double ('g').."); + return 0; + } + case 'O': case 'P': return sizeof(void*); + default: + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } +} +static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) { + switch (ch) { + case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; + case 'h': case 'H': return sizeof(short); + case 'i': case 'I': return sizeof(int); + case 'l': case 'L': return sizeof(long); + case 'q': case 'Q': return sizeof(PY_LONG_LONG); + case 'f': return sizeof(float) * (is_complex ? 2 : 1); + case 'd': return sizeof(double) * (is_complex ? 2 : 1); + case 'g': return sizeof(long double) * (is_complex ? 2 : 1); + case 'O': case 'P': return sizeof(void*); + default: { + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } + } +} +typedef struct { char c; short x; } __Pyx_st_short; +typedef struct { char c; int x; } __Pyx_st_int; +typedef struct { char c; long x; } __Pyx_st_long; +typedef struct { char c; float x; } __Pyx_st_float; +typedef struct { char c; double x; } __Pyx_st_double; +typedef struct { char c; long double x; } __Pyx_st_longdouble; +typedef struct { char c; void *x; } __Pyx_st_void_p; +typedef struct { char c; PY_LONG_LONG x; } __Pyx_st_longlong; +static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, int is_complex) { + CYTHON_UNUSED_VAR(is_complex); + switch (ch) { + case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; + case 'h': case 'H': return sizeof(__Pyx_st_short) - sizeof(short); + case 'i': case 'I': return sizeof(__Pyx_st_int) - sizeof(int); + case 'l': case 'L': return sizeof(__Pyx_st_long) - sizeof(long); + case 'q': case 'Q': return sizeof(__Pyx_st_longlong) - sizeof(PY_LONG_LONG); + case 'f': return sizeof(__Pyx_st_float) - sizeof(float); + case 'd': return sizeof(__Pyx_st_double) - sizeof(double); + case 'g': return sizeof(__Pyx_st_longdouble) - sizeof(long double); + case 'P': case 'O': return sizeof(__Pyx_st_void_p) - sizeof(void*); + default: + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } +} +/* These are for computing the padding at the end of the struct to align + on the first member of the struct. This will probably the same as above, + but we don't have any guarantees. + */ +typedef struct { short x; char c; } __Pyx_pad_short; +typedef struct { int x; char c; } __Pyx_pad_int; +typedef struct { long x; char c; } __Pyx_pad_long; +typedef struct { float x; char c; } __Pyx_pad_float; +typedef struct { double x; char c; } __Pyx_pad_double; +typedef struct { long double x; char c; } __Pyx_pad_longdouble; +typedef struct { void *x; char c; } __Pyx_pad_void_p; +typedef struct { PY_LONG_LONG x; char c; } __Pyx_pad_longlong; +static size_t __Pyx_BufFmt_TypeCharToPadding(char ch, int is_complex) { + CYTHON_UNUSED_VAR(is_complex); + switch (ch) { + case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; + case 'h': case 'H': return sizeof(__Pyx_pad_short) - sizeof(short); + case 'i': case 'I': return sizeof(__Pyx_pad_int) - sizeof(int); + case 'l': case 'L': return sizeof(__Pyx_pad_long) - sizeof(long); + case 'q': case 'Q': return sizeof(__Pyx_pad_longlong) - sizeof(PY_LONG_LONG); + case 'f': return sizeof(__Pyx_pad_float) - sizeof(float); + case 'd': return sizeof(__Pyx_pad_double) - sizeof(double); + case 'g': return sizeof(__Pyx_pad_longdouble) - sizeof(long double); + case 'P': case 'O': return sizeof(__Pyx_pad_void_p) - sizeof(void*); + default: + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } +} +static char __Pyx_BufFmt_TypeCharToGroup(char ch, int is_complex) { + switch (ch) { + case 'c': + return 'H'; + case 'b': case 'h': case 'i': + case 'l': case 'q': case 's': case 'p': + return 'I'; + case '?': case 'B': case 'H': case 'I': case 'L': case 'Q': + return 'U'; + case 'f': case 'd': case 'g': + return (is_complex ? 'C' : 'R'); + case 'O': + return 'O'; + case 'P': + return 'P'; + default: { + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } + } +} +static void __Pyx_BufFmt_RaiseExpected(__Pyx_BufFmt_Context* ctx) { + if (ctx->head == NULL || ctx->head->field == &ctx->root) { + const char* expected; + const char* quote; + if (ctx->head == NULL) { + expected = "end"; + quote = ""; + } else { + expected = ctx->head->field->type->name; + quote = "'"; + } + PyErr_Format(PyExc_ValueError, + "Buffer dtype mismatch, expected %s%s%s but got %s", + quote, expected, quote, + __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex)); + } else { + const __Pyx_StructField* field = ctx->head->field; + const __Pyx_StructField* parent = (ctx->head - 1)->field; + PyErr_Format(PyExc_ValueError, + "Buffer dtype mismatch, expected '%s' but got %s in '%s.%s'", + field->type->name, __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex), + parent->type->name, field->name); + } +} +static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) { + char group; + size_t size, offset, arraysize = 1; + if (ctx->enc_type == 0) return 0; + if (ctx->head->field->type->arraysize[0]) { + int i, ndim = 0; + if (ctx->enc_type == 's' || ctx->enc_type == 'p') { + ctx->is_valid_array = ctx->head->field->type->ndim == 1; + ndim = 1; + if (ctx->enc_count != ctx->head->field->type->arraysize[0]) { + PyErr_Format(PyExc_ValueError, + "Expected a dimension of size %zu, got %zu", + ctx->head->field->type->arraysize[0], ctx->enc_count); + return -1; + } + } + if (!ctx->is_valid_array) { + PyErr_Format(PyExc_ValueError, "Expected %d dimensions, got %d", + ctx->head->field->type->ndim, ndim); + return -1; + } + for (i = 0; i < ctx->head->field->type->ndim; i++) { + arraysize *= ctx->head->field->type->arraysize[i]; + } + ctx->is_valid_array = 0; + ctx->enc_count = 1; + } + group = __Pyx_BufFmt_TypeCharToGroup(ctx->enc_type, ctx->is_complex); + do { + const __Pyx_StructField* field = ctx->head->field; + const __Pyx_TypeInfo* type = field->type; + if (ctx->enc_packmode == '@' || ctx->enc_packmode == '^') { + size = __Pyx_BufFmt_TypeCharToNativeSize(ctx->enc_type, ctx->is_complex); + } else { + size = __Pyx_BufFmt_TypeCharToStandardSize(ctx->enc_type, ctx->is_complex); + } + if (ctx->enc_packmode == '@') { + size_t align_at = __Pyx_BufFmt_TypeCharToAlignment(ctx->enc_type, ctx->is_complex); + size_t align_mod_offset; + if (align_at == 0) return -1; + align_mod_offset = ctx->fmt_offset % align_at; + if (align_mod_offset > 0) ctx->fmt_offset += align_at - align_mod_offset; + if (ctx->struct_alignment == 0) + ctx->struct_alignment = __Pyx_BufFmt_TypeCharToPadding(ctx->enc_type, + ctx->is_complex); + } + if (type->size != size || type->typegroup != group) { + if (type->typegroup == 'C' && type->fields != NULL) { + size_t parent_offset = ctx->head->parent_offset + field->offset; + ++ctx->head; + ctx->head->field = type->fields; + ctx->head->parent_offset = parent_offset; + continue; + } + if ((type->typegroup == 'H' || group == 'H') && type->size == size) { + } else { + __Pyx_BufFmt_RaiseExpected(ctx); + return -1; + } + } + offset = ctx->head->parent_offset + field->offset; + if (ctx->fmt_offset != offset) { + PyErr_Format(PyExc_ValueError, + "Buffer dtype mismatch; next field is at offset %" CYTHON_FORMAT_SSIZE_T "d but %" CYTHON_FORMAT_SSIZE_T "d expected", + (Py_ssize_t)ctx->fmt_offset, (Py_ssize_t)offset); + return -1; + } + ctx->fmt_offset += size; + if (arraysize) + ctx->fmt_offset += (arraysize - 1) * size; + --ctx->enc_count; + while (1) { + if (field == &ctx->root) { + ctx->head = NULL; + if (ctx->enc_count != 0) { + __Pyx_BufFmt_RaiseExpected(ctx); + return -1; + } + break; + } + ctx->head->field = ++field; + if (field->type == NULL) { + --ctx->head; + field = ctx->head->field; + continue; + } else if (field->type->typegroup == 'S') { + size_t parent_offset = ctx->head->parent_offset + field->offset; + if (field->type->fields->type == NULL) continue; + field = field->type->fields; + ++ctx->head; + ctx->head->field = field; + ctx->head->parent_offset = parent_offset; + break; + } else { + break; + } + } + } while (ctx->enc_count); + ctx->enc_type = 0; + ctx->is_complex = 0; + return 0; +} +static int +__pyx_buffmt_parse_array(__Pyx_BufFmt_Context* ctx, const char** tsp) +{ + const char *ts = *tsp; + int i = 0, number, ndim; + ++ts; + if (ctx->new_count != 1) { + PyErr_SetString(PyExc_ValueError, + "Cannot handle repeated arrays in format string"); + return -1; + } + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return -1; + ndim = ctx->head->field->type->ndim; + while (*ts && *ts != ')') { + switch (*ts) { + case ' ': case '\f': case '\r': case '\n': case '\t': case '\v': continue; + default: break; + } + number = __Pyx_BufFmt_ExpectNumber(&ts); + if (number == -1) return -1; + if (i < ndim && (size_t) number != ctx->head->field->type->arraysize[i]) { + PyErr_Format(PyExc_ValueError, + "Expected a dimension of size %zu, got %d", + ctx->head->field->type->arraysize[i], number); + return -1; + } + if (*ts != ',' && *ts != ')') { + PyErr_Format(PyExc_ValueError, + "Expected a comma in format string, got '%c'", *ts); + return -1; + } + if (*ts == ',') ts++; + i++; + } + if (i != ndim) { + PyErr_Format(PyExc_ValueError, "Expected %d dimension(s), got %d", + ctx->head->field->type->ndim, i); + return -1; + } + if (!*ts) { + PyErr_SetString(PyExc_ValueError, + "Unexpected end of format string, expected ')'"); + return -1; + } + ctx->is_valid_array = 1; + ctx->new_count = 1; + *tsp = ++ts; + return 0; +} +static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts) { + int got_Z = 0; + while (1) { + switch(*ts) { + case 0: + if (ctx->enc_type != 0 && ctx->head == NULL) { + __Pyx_BufFmt_RaiseExpected(ctx); + return NULL; + } + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + if (ctx->head != NULL) { + __Pyx_BufFmt_RaiseExpected(ctx); + return NULL; + } + return ts; + case ' ': + case '\r': + case '\n': + ++ts; + break; + case '<': + if (!__Pyx_Is_Little_Endian()) { + PyErr_SetString(PyExc_ValueError, "Little-endian buffer not supported on big-endian compiler"); + return NULL; + } + ctx->new_packmode = '='; + ++ts; + break; + case '>': + case '!': + if (__Pyx_Is_Little_Endian()) { + PyErr_SetString(PyExc_ValueError, "Big-endian buffer not supported on little-endian compiler"); + return NULL; + } + ctx->new_packmode = '='; + ++ts; + break; + case '=': + case '@': + case '^': + ctx->new_packmode = *ts++; + break; + case 'T': + { + const char* ts_after_sub; + size_t i, struct_count = ctx->new_count; + size_t struct_alignment = ctx->struct_alignment; + ctx->new_count = 1; + ++ts; + if (*ts != '{') { + PyErr_SetString(PyExc_ValueError, "Buffer acquisition: Expected '{' after 'T'"); + return NULL; + } + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + ctx->enc_type = 0; + ctx->enc_count = 0; + ctx->struct_alignment = 0; + ++ts; + ts_after_sub = ts; + for (i = 0; i != struct_count; ++i) { + ts_after_sub = __Pyx_BufFmt_CheckString(ctx, ts); + if (!ts_after_sub) return NULL; + } + ts = ts_after_sub; + if (struct_alignment) ctx->struct_alignment = struct_alignment; + } + break; + case '}': + { + size_t alignment = ctx->struct_alignment; + ++ts; + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + ctx->enc_type = 0; + if (alignment && ctx->fmt_offset % alignment) { + ctx->fmt_offset += alignment - (ctx->fmt_offset % alignment); + } + } + return ts; + case 'x': + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + ctx->fmt_offset += ctx->new_count; + ctx->new_count = 1; + ctx->enc_count = 0; + ctx->enc_type = 0; + ctx->enc_packmode = ctx->new_packmode; + ++ts; + break; + case 'Z': + got_Z = 1; + ++ts; + if (*ts != 'f' && *ts != 'd' && *ts != 'g') { + __Pyx_BufFmt_RaiseUnexpectedChar('Z'); + return NULL; + } + CYTHON_FALLTHROUGH; + case '?': case 'c': case 'b': case 'B': case 'h': case 'H': case 'i': case 'I': + case 'l': case 'L': case 'q': case 'Q': + case 'f': case 'd': case 'g': + case 'O': case 'p': + if ((ctx->enc_type == *ts) && (got_Z == ctx->is_complex) && + (ctx->enc_packmode == ctx->new_packmode) && (!ctx->is_valid_array)) { + ctx->enc_count += ctx->new_count; + ctx->new_count = 1; + got_Z = 0; + ++ts; + break; + } + CYTHON_FALLTHROUGH; + case 's': + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + ctx->enc_count = ctx->new_count; + ctx->enc_packmode = ctx->new_packmode; + ctx->enc_type = *ts; + ctx->is_complex = got_Z; + ++ts; + ctx->new_count = 1; + got_Z = 0; + break; + case ':': + ++ts; + while(*ts != ':') ++ts; + ++ts; + break; + case '(': + if (__pyx_buffmt_parse_array(ctx, &ts) < 0) return NULL; + break; + default: + { + int number = __Pyx_BufFmt_ExpectNumber(&ts); + if (number == -1) return NULL; + ctx->new_count = (size_t)number; + } + } + } +} + +/* TypeInfoCompare (used by MemviewSliceValidateAndInit) */ + static int + __pyx_typeinfo_cmp(const __Pyx_TypeInfo *a, const __Pyx_TypeInfo *b) + { + int i; + if (!a || !b) + return 0; + if (a == b) + return 1; + if (a->size != b->size || a->typegroup != b->typegroup || + a->is_unsigned != b->is_unsigned || a->ndim != b->ndim) { + if (a->typegroup == 'H' || b->typegroup == 'H') { + return a->size == b->size; + } else { + return 0; + } + } + if (a->ndim) { + for (i = 0; i < a->ndim; i++) + if (a->arraysize[i] != b->arraysize[i]) + return 0; + } + if (a->typegroup == 'S') { + if (a->flags != b->flags) + return 0; + if (a->fields || b->fields) { + if (!(a->fields && b->fields)) + return 0; + for (i = 0; a->fields[i].type && b->fields[i].type; i++) { + const __Pyx_StructField *field_a = a->fields + i; + const __Pyx_StructField *field_b = b->fields + i; + if (field_a->offset != field_b->offset || + !__pyx_typeinfo_cmp(field_a->type, field_b->type)) + return 0; + } + return !a->fields[i].type && !b->fields[i].type; + } + } + return 1; + } + +/* MemviewSliceValidateAndInit (used by ObjectToMemviewSlice) */ + static int + __pyx_check_strides(Py_buffer *buf, int dim, int ndim, int spec) + { + if (buf->shape[dim] <= 1) + return 1; + if (buf->strides) { + if (spec & __Pyx_MEMVIEW_CONTIG) { + if (spec & (__Pyx_MEMVIEW_PTR|__Pyx_MEMVIEW_FULL)) { + if (unlikely(buf->strides[dim] != sizeof(void *))) { + PyErr_Format(PyExc_ValueError, + "Buffer is not indirectly contiguous " + "in dimension %d.", dim); + goto fail; + } + } else if (unlikely(buf->strides[dim] != buf->itemsize)) { + PyErr_SetString(PyExc_ValueError, + "Buffer and memoryview are not contiguous " + "in the same dimension."); + goto fail; + } + } + if (spec & __Pyx_MEMVIEW_FOLLOW) { + Py_ssize_t stride = buf->strides[dim]; + if (stride < 0) + stride = -stride; + if (unlikely(stride < buf->itemsize)) { + PyErr_SetString(PyExc_ValueError, + "Buffer and memoryview are not contiguous " + "in the same dimension."); + goto fail; + } + } + } else { + if (unlikely(spec & __Pyx_MEMVIEW_CONTIG && dim != ndim - 1)) { + PyErr_Format(PyExc_ValueError, + "C-contiguous buffer is not contiguous in " + "dimension %d", dim); + goto fail; + } else if (unlikely(spec & (__Pyx_MEMVIEW_PTR))) { + PyErr_Format(PyExc_ValueError, + "C-contiguous buffer is not indirect in " + "dimension %d", dim); + goto fail; + } else if (unlikely(buf->suboffsets)) { + PyErr_SetString(PyExc_ValueError, + "Buffer exposes suboffsets but no strides"); + goto fail; + } + } + return 1; + fail: + return 0; + } + static int + __pyx_check_suboffsets(Py_buffer *buf, int dim, int ndim, int spec) + { + CYTHON_UNUSED_VAR(ndim); + if (spec & __Pyx_MEMVIEW_DIRECT) { + if (unlikely(buf->suboffsets && buf->suboffsets[dim] >= 0)) { + PyErr_Format(PyExc_ValueError, + "Buffer not compatible with direct access " + "in dimension %d.", dim); + goto fail; + } + } + if (spec & __Pyx_MEMVIEW_PTR) { + if (unlikely(!buf->suboffsets || (buf->suboffsets[dim] < 0))) { + PyErr_Format(PyExc_ValueError, + "Buffer is not indirectly accessible " + "in dimension %d.", dim); + goto fail; + } + } + return 1; + fail: + return 0; + } + static int + __pyx_verify_contig(Py_buffer *buf, int ndim, int c_or_f_flag) + { + int i; + if (c_or_f_flag & __Pyx_IS_F_CONTIG) { + Py_ssize_t stride = 1; + for (i = 0; i < ndim; i++) { + if (unlikely(stride * buf->itemsize != buf->strides[i] && buf->shape[i] > 1)) { + PyErr_SetString(PyExc_ValueError, + "Buffer not fortran contiguous."); + goto fail; + } + stride = stride * buf->shape[i]; + } + } else if (c_or_f_flag & __Pyx_IS_C_CONTIG) { + Py_ssize_t stride = 1; + for (i = ndim - 1; i >- 1; i--) { + if (unlikely(stride * buf->itemsize != buf->strides[i] && buf->shape[i] > 1)) { + PyErr_SetString(PyExc_ValueError, + "Buffer not C contiguous."); + goto fail; + } + stride = stride * buf->shape[i]; + } + } + return 1; + fail: + return 0; + } + static int __Pyx_ValidateAndInit_memviewslice( + int *axes_specs, + int c_or_f_flag, + int buf_flags, + int ndim, + const __Pyx_TypeInfo *dtype, + __Pyx_BufFmt_StackElem stack[], + __Pyx_memviewslice *memviewslice, + PyObject *original_obj) + { + struct __pyx_memoryview_obj *memview, *new_memview; + __Pyx_RefNannyDeclarations + Py_buffer *buf; + int i, spec = 0, retval = -1; + __Pyx_BufFmt_Context ctx; + int from_memoryview = __pyx_memoryview_check(original_obj); + __Pyx_RefNannySetupContext("ValidateAndInit_memviewslice", 0); + if (from_memoryview && __pyx_typeinfo_cmp(dtype, ((struct __pyx_memoryview_obj *) + original_obj)->typeinfo)) { + memview = (struct __pyx_memoryview_obj *) original_obj; + new_memview = NULL; + } else { + memview = (struct __pyx_memoryview_obj *) __pyx_memoryview_new( + original_obj, buf_flags, 0, dtype); + new_memview = memview; + if (unlikely(!memview)) + goto fail; + } + buf = &memview->view; + if (unlikely(buf->ndim != ndim)) { + PyErr_Format(PyExc_ValueError, + "Buffer has wrong number of dimensions (expected %d, got %d)", + ndim, buf->ndim); + goto fail; + } + if (new_memview) { + __Pyx_BufFmt_Init(&ctx, stack, dtype); + if (unlikely(!__Pyx_BufFmt_CheckString(&ctx, buf->format))) goto fail; + } + if (unlikely((unsigned) buf->itemsize != dtype->size)) { + PyErr_Format(PyExc_ValueError, + "Item size of buffer (%" CYTHON_FORMAT_SSIZE_T "u byte%s) " + "does not match size of '%s' (%" CYTHON_FORMAT_SSIZE_T "u byte%s)", + buf->itemsize, + (buf->itemsize > 1) ? "s" : "", + dtype->name, + dtype->size, + (dtype->size > 1) ? "s" : ""); + goto fail; + } + if (buf->len > 0) { + for (i = 0; i < ndim; i++) { + spec = axes_specs[i]; + if (unlikely(!__pyx_check_strides(buf, i, ndim, spec))) + goto fail; + if (unlikely(!__pyx_check_suboffsets(buf, i, ndim, spec))) + goto fail; + } + if (unlikely(buf->strides && !__pyx_verify_contig(buf, ndim, c_or_f_flag))) + goto fail; + } + if (unlikely(__Pyx_init_memviewslice(memview, ndim, memviewslice, + new_memview != NULL) == -1)) { + goto fail; + } + retval = 0; + goto no_fail; + fail: + Py_XDECREF((PyObject*)new_memview); + retval = -1; + no_fail: + __Pyx_RefNannyFinishContext(); + return retval; + } + +/* ObjectToMemviewSlice */ + static CYTHON_INLINE __Pyx_memviewslice __Pyx_PyObject_to_MemoryviewSlice_d_d_dc_int(PyObject *obj, int writable_flag) { + __Pyx_memviewslice result = __Pyx_MEMSLICE_INIT; + __Pyx_BufFmt_StackElem stack[1]; + int axes_specs[] = { (__Pyx_MEMVIEW_DIRECT | __Pyx_MEMVIEW_FOLLOW), (__Pyx_MEMVIEW_DIRECT | __Pyx_MEMVIEW_FOLLOW), (__Pyx_MEMVIEW_DIRECT | __Pyx_MEMVIEW_CONTIG) }; + int retcode; + if (obj == Py_None) { + result.memview = (struct __pyx_memoryview_obj *) Py_None; + return result; + } + retcode = __Pyx_ValidateAndInit_memviewslice(axes_specs, __Pyx_IS_C_CONTIG, + (PyBUF_C_CONTIGUOUS | PyBUF_FORMAT) | writable_flag, 3, + &__Pyx_TypeInfo_int, stack, + &result, obj); + if (unlikely(retcode == -1)) + goto __pyx_fail; + return result; + __pyx_fail: + result.memview = NULL; + result.data = NULL; + return result; + } + +/* ObjectToMemviewSlice */ + static CYTHON_INLINE __Pyx_memviewslice __Pyx_PyObject_to_MemoryviewSlice_d_d_dc_float(PyObject *obj, int writable_flag) { + __Pyx_memviewslice result = __Pyx_MEMSLICE_INIT; + __Pyx_BufFmt_StackElem stack[1]; + int axes_specs[] = { (__Pyx_MEMVIEW_DIRECT | __Pyx_MEMVIEW_FOLLOW), (__Pyx_MEMVIEW_DIRECT | __Pyx_MEMVIEW_FOLLOW), (__Pyx_MEMVIEW_DIRECT | __Pyx_MEMVIEW_CONTIG) }; + int retcode; + if (obj == Py_None) { + result.memview = (struct __pyx_memoryview_obj *) Py_None; + return result; + } + retcode = __Pyx_ValidateAndInit_memviewslice(axes_specs, __Pyx_IS_C_CONTIG, + (PyBUF_C_CONTIGUOUS | PyBUF_FORMAT) | writable_flag, 3, + &__Pyx_TypeInfo_float, stack, + &result, obj); + if (unlikely(retcode == -1)) + goto __pyx_fail; + return result; + __pyx_fail: + result.memview = NULL; + result.data = NULL; + return result; + } + +/* ObjectToMemviewSlice */ + static CYTHON_INLINE __Pyx_memviewslice __Pyx_PyObject_to_MemoryviewSlice_dc_int(PyObject *obj, int writable_flag) { + __Pyx_memviewslice result = __Pyx_MEMSLICE_INIT; + __Pyx_BufFmt_StackElem stack[1]; + int axes_specs[] = { (__Pyx_MEMVIEW_DIRECT | __Pyx_MEMVIEW_CONTIG) }; + int retcode; + if (obj == Py_None) { + result.memview = (struct __pyx_memoryview_obj *) Py_None; + return result; + } + retcode = __Pyx_ValidateAndInit_memviewslice(axes_specs, __Pyx_IS_C_CONTIG, + (PyBUF_C_CONTIGUOUS | PyBUF_FORMAT) | writable_flag, 1, + &__Pyx_TypeInfo_int, stack, + &result, obj); + if (unlikely(retcode == -1)) + goto __pyx_fail; + return result; + __pyx_fail: + result.memview = NULL; + result.data = NULL; + return result; + } + +/* CIntFromPyVerify */ + #define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) + #define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1) + #define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc)\ + {\ + func_type value = func_value;\ + if (sizeof(target_type) < sizeof(func_type)) {\ + if (unlikely(value != (func_type) (target_type) value)) {\ + func_type zero = 0;\ + if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))\ + return (target_type) -1;\ + if (is_unsigned && unlikely(value < zero))\ + goto raise_neg_overflow;\ + else\ + goto raise_overflow;\ + }\ + }\ + return (target_type) value;\ + } + +/* Declarations */ + #if CYTHON_CCOMPLEX && (1) && (!0 || __cplusplus) + #ifdef __cplusplus + static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { + return ::std::complex< float >(x, y); + } + #else + static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { + return x + y*(__pyx_t_float_complex)_Complex_I; + } + #endif + #else + static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { + __pyx_t_float_complex z; + z.real = x; + z.imag = y; + return z; + } + #endif + +/* Arithmetic */ + #if CYTHON_CCOMPLEX && (1) && (!0 || __cplusplus) + #else + static CYTHON_INLINE int __Pyx_c_eq_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { + return (a.real == b.real) && (a.imag == b.imag); + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sum_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + z.real = a.real + b.real; + z.imag = a.imag + b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_diff_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + z.real = a.real - b.real; + z.imag = a.imag - b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prod_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + z.real = a.real * b.real - a.imag * b.imag; + z.imag = a.real * b.imag + a.imag * b.real; + return z; + } + #if 1 + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { + if (b.imag == 0) { + return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.real); + } else if (fabsf(b.real) >= fabsf(b.imag)) { + if (b.real == 0 && b.imag == 0) { + return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.imag); + } else { + float r = b.imag / b.real; + float s = (float)(1.0) / (b.real + b.imag * r); + return __pyx_t_float_complex_from_parts( + (a.real + a.imag * r) * s, (a.imag - a.real * r) * s); + } + } else { + float r = b.real / b.imag; + float s = (float)(1.0) / (b.imag + b.real * r); + return __pyx_t_float_complex_from_parts( + (a.real * r + a.imag) * s, (a.imag * r - a.real) * s); + } + } + #else + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { + if (b.imag == 0) { + return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.real); + } else { + float denom = b.real * b.real + b.imag * b.imag; + return __pyx_t_float_complex_from_parts( + (a.real * b.real + a.imag * b.imag) / denom, + (a.imag * b.real - a.real * b.imag) / denom); + } + } + #endif + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_neg_float(__pyx_t_float_complex a) { + __pyx_t_float_complex z; + z.real = -a.real; + z.imag = -a.imag; + return z; + } + static CYTHON_INLINE int __Pyx_c_is_zero_float(__pyx_t_float_complex a) { + return (a.real == 0) && (a.imag == 0); + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conj_float(__pyx_t_float_complex a) { + __pyx_t_float_complex z; + z.real = a.real; + z.imag = -a.imag; + return z; + } + #if 1 + static CYTHON_INLINE float __Pyx_c_abs_float(__pyx_t_float_complex z) { + #if !defined(HAVE_HYPOT) || defined(_MSC_VER) + return sqrtf(z.real*z.real + z.imag*z.imag); + #else + return hypotf(z.real, z.imag); + #endif + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_pow_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + float r, lnr, theta, z_r, z_theta; + if (b.imag == 0 && b.real == (int)b.real) { + if (b.real < 0) { + float denom = a.real * a.real + a.imag * a.imag; + a.real = a.real / denom; + a.imag = -a.imag / denom; + b.real = -b.real; + } + switch ((int)b.real) { + case 0: + z.real = 1; + z.imag = 0; + return z; + case 1: + return a; + case 2: + return __Pyx_c_prod_float(a, a); + case 3: + z = __Pyx_c_prod_float(a, a); + return __Pyx_c_prod_float(z, a); + case 4: + z = __Pyx_c_prod_float(a, a); + return __Pyx_c_prod_float(z, z); + } + } + if (a.imag == 0) { + if (a.real == 0) { + return a; + } else if ((b.imag == 0) && (a.real >= 0)) { + z.real = powf(a.real, b.real); + z.imag = 0; + return z; + } else if (a.real > 0) { + r = a.real; + theta = 0; + } else { + r = -a.real; + theta = atan2f(0.0, -1.0); + } + } else { + r = __Pyx_c_abs_float(a); + theta = atan2f(a.imag, a.real); + } + lnr = logf(r); + z_r = expf(lnr * b.real - theta * b.imag); + z_theta = theta * b.real + lnr * b.imag; + z.real = z_r * cosf(z_theta); + z.imag = z_r * sinf(z_theta); + return z; + } + #endif + #endif + +/* Declarations */ + #if CYTHON_CCOMPLEX && (1) && (!0 || __cplusplus) + #ifdef __cplusplus + static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { + return ::std::complex< double >(x, y); + } + #else + static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { + return x + y*(__pyx_t_double_complex)_Complex_I; + } + #endif + #else + static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { + __pyx_t_double_complex z; + z.real = x; + z.imag = y; + return z; + } + #endif + +/* Arithmetic */ + #if CYTHON_CCOMPLEX && (1) && (!0 || __cplusplus) + #else + static CYTHON_INLINE int __Pyx_c_eq_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { + return (a.real == b.real) && (a.imag == b.imag); + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + z.real = a.real + b.real; + z.imag = a.imag + b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + z.real = a.real - b.real; + z.imag = a.imag - b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + z.real = a.real * b.real - a.imag * b.imag; + z.imag = a.real * b.imag + a.imag * b.real; + return z; + } + #if 1 + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { + if (b.imag == 0) { + return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.real); + } else if (fabs(b.real) >= fabs(b.imag)) { + if (b.real == 0 && b.imag == 0) { + return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.imag); + } else { + double r = b.imag / b.real; + double s = (double)(1.0) / (b.real + b.imag * r); + return __pyx_t_double_complex_from_parts( + (a.real + a.imag * r) * s, (a.imag - a.real * r) * s); + } + } else { + double r = b.real / b.imag; + double s = (double)(1.0) / (b.imag + b.real * r); + return __pyx_t_double_complex_from_parts( + (a.real * r + a.imag) * s, (a.imag * r - a.real) * s); + } + } + #else + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { + if (b.imag == 0) { + return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.real); + } else { + double denom = b.real * b.real + b.imag * b.imag; + return __pyx_t_double_complex_from_parts( + (a.real * b.real + a.imag * b.imag) / denom, + (a.imag * b.real - a.real * b.imag) / denom); + } + } + #endif + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg_double(__pyx_t_double_complex a) { + __pyx_t_double_complex z; + z.real = -a.real; + z.imag = -a.imag; + return z; + } + static CYTHON_INLINE int __Pyx_c_is_zero_double(__pyx_t_double_complex a) { + return (a.real == 0) && (a.imag == 0); + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj_double(__pyx_t_double_complex a) { + __pyx_t_double_complex z; + z.real = a.real; + z.imag = -a.imag; + return z; + } + #if 1 + static CYTHON_INLINE double __Pyx_c_abs_double(__pyx_t_double_complex z) { + #if !defined(HAVE_HYPOT) || defined(_MSC_VER) + return sqrt(z.real*z.real + z.imag*z.imag); + #else + return hypot(z.real, z.imag); + #endif + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_pow_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + double r, lnr, theta, z_r, z_theta; + if (b.imag == 0 && b.real == (int)b.real) { + if (b.real < 0) { + double denom = a.real * a.real + a.imag * a.imag; + a.real = a.real / denom; + a.imag = -a.imag / denom; + b.real = -b.real; + } + switch ((int)b.real) { + case 0: + z.real = 1; + z.imag = 0; + return z; + case 1: + return a; + case 2: + return __Pyx_c_prod_double(a, a); + case 3: + z = __Pyx_c_prod_double(a, a); + return __Pyx_c_prod_double(z, a); + case 4: + z = __Pyx_c_prod_double(a, a); + return __Pyx_c_prod_double(z, z); + } + } + if (a.imag == 0) { + if (a.real == 0) { + return a; + } else if ((b.imag == 0) && (a.real >= 0)) { + z.real = pow(a.real, b.real); + z.imag = 0; + return z; + } else if (a.real > 0) { + r = a.real; + theta = 0; + } else { + r = -a.real; + theta = atan2(0.0, -1.0); + } + } else { + r = __Pyx_c_abs_double(a); + theta = atan2(a.imag, a.real); + } + lnr = log(r); + z_r = exp(lnr * b.real - theta * b.imag); + z_theta = theta * b.real + lnr * b.imag; + z.real = z_r * cos(z_theta); + z.imag = z_r * sin(z_theta); + return z; + } + #endif + #endif + +/* Declarations */ + #if CYTHON_CCOMPLEX && (1) && (!0 || __cplusplus) + #ifdef __cplusplus + static CYTHON_INLINE __pyx_t_long_double_complex __pyx_t_long_double_complex_from_parts(long double x, long double y) { + return ::std::complex< long double >(x, y); + } + #else + static CYTHON_INLINE __pyx_t_long_double_complex __pyx_t_long_double_complex_from_parts(long double x, long double y) { + return x + y*(__pyx_t_long_double_complex)_Complex_I; + } + #endif + #else + static CYTHON_INLINE __pyx_t_long_double_complex __pyx_t_long_double_complex_from_parts(long double x, long double y) { + __pyx_t_long_double_complex z; + z.real = x; + z.imag = y; + return z; + } + #endif + +/* Arithmetic */ + #if CYTHON_CCOMPLEX && (1) && (!0 || __cplusplus) + #else + static CYTHON_INLINE int __Pyx_c_eq_long__double(__pyx_t_long_double_complex a, __pyx_t_long_double_complex b) { + return (a.real == b.real) && (a.imag == b.imag); + } + static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_sum_long__double(__pyx_t_long_double_complex a, __pyx_t_long_double_complex b) { + __pyx_t_long_double_complex z; + z.real = a.real + b.real; + z.imag = a.imag + b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_diff_long__double(__pyx_t_long_double_complex a, __pyx_t_long_double_complex b) { + __pyx_t_long_double_complex z; + z.real = a.real - b.real; + z.imag = a.imag - b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_prod_long__double(__pyx_t_long_double_complex a, __pyx_t_long_double_complex b) { + __pyx_t_long_double_complex z; + z.real = a.real * b.real - a.imag * b.imag; + z.imag = a.real * b.imag + a.imag * b.real; + return z; + } + #if 1 + static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_quot_long__double(__pyx_t_long_double_complex a, __pyx_t_long_double_complex b) { + if (b.imag == 0) { + return __pyx_t_long_double_complex_from_parts(a.real / b.real, a.imag / b.real); + } else if (fabsl(b.real) >= fabsl(b.imag)) { + if (b.real == 0 && b.imag == 0) { + return __pyx_t_long_double_complex_from_parts(a.real / b.real, a.imag / b.imag); + } else { + long double r = b.imag / b.real; + long double s = (long double)(1.0) / (b.real + b.imag * r); + return __pyx_t_long_double_complex_from_parts( + (a.real + a.imag * r) * s, (a.imag - a.real * r) * s); + } + } else { + long double r = b.real / b.imag; + long double s = (long double)(1.0) / (b.imag + b.real * r); + return __pyx_t_long_double_complex_from_parts( + (a.real * r + a.imag) * s, (a.imag * r - a.real) * s); + } + } + #else + static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_quot_long__double(__pyx_t_long_double_complex a, __pyx_t_long_double_complex b) { + if (b.imag == 0) { + return __pyx_t_long_double_complex_from_parts(a.real / b.real, a.imag / b.real); + } else { + long double denom = b.real * b.real + b.imag * b.imag; + return __pyx_t_long_double_complex_from_parts( + (a.real * b.real + a.imag * b.imag) / denom, + (a.imag * b.real - a.real * b.imag) / denom); + } + } + #endif + static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_neg_long__double(__pyx_t_long_double_complex a) { + __pyx_t_long_double_complex z; + z.real = -a.real; + z.imag = -a.imag; + return z; + } + static CYTHON_INLINE int __Pyx_c_is_zero_long__double(__pyx_t_long_double_complex a) { + return (a.real == 0) && (a.imag == 0); + } + static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_conj_long__double(__pyx_t_long_double_complex a) { + __pyx_t_long_double_complex z; + z.real = a.real; + z.imag = -a.imag; + return z; + } + #if 1 + static CYTHON_INLINE long double __Pyx_c_abs_long__double(__pyx_t_long_double_complex z) { + #if !defined(HAVE_HYPOT) || defined(_MSC_VER) + return sqrtl(z.real*z.real + z.imag*z.imag); + #else + return hypotl(z.real, z.imag); + #endif + } + static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_pow_long__double(__pyx_t_long_double_complex a, __pyx_t_long_double_complex b) { + __pyx_t_long_double_complex z; + long double r, lnr, theta, z_r, z_theta; + if (b.imag == 0 && b.real == (int)b.real) { + if (b.real < 0) { + long double denom = a.real * a.real + a.imag * a.imag; + a.real = a.real / denom; + a.imag = -a.imag / denom; + b.real = -b.real; + } + switch ((int)b.real) { + case 0: + z.real = 1; + z.imag = 0; + return z; + case 1: + return a; + case 2: + return __Pyx_c_prod_long__double(a, a); + case 3: + z = __Pyx_c_prod_long__double(a, a); + return __Pyx_c_prod_long__double(z, a); + case 4: + z = __Pyx_c_prod_long__double(a, a); + return __Pyx_c_prod_long__double(z, z); + } + } + if (a.imag == 0) { + if (a.real == 0) { + return a; + } else if ((b.imag == 0) && (a.real >= 0)) { + z.real = powl(a.real, b.real); + z.imag = 0; + return z; + } else if (a.real > 0) { + r = a.real; + theta = 0; + } else { + r = -a.real; + theta = atan2l(0.0, -1.0); + } + } else { + r = __Pyx_c_abs_long__double(a); + theta = atan2l(a.imag, a.real); + } + lnr = logl(r); + z_r = expl(lnr * b.real - theta * b.imag); + z_theta = theta * b.real + lnr * b.imag; + z.real = z_r * cosl(z_theta); + z.imag = z_r * sinl(z_theta); + return z; + } + #endif + #endif + +/* MemviewSliceCopy */ + static __Pyx_memviewslice + __pyx_memoryview_copy_new_contig(const __Pyx_memviewslice *from_mvs, + const char *mode, int ndim, + size_t sizeof_dtype, int contig_flag, + int dtype_is_object) + { + __Pyx_RefNannyDeclarations + int i; + __Pyx_memviewslice new_mvs = __Pyx_MEMSLICE_INIT; + struct __pyx_memoryview_obj *from_memview = from_mvs->memview; + Py_buffer *buf = &from_memview->view; + PyObject *shape_tuple = NULL; + struct __pyx_array_obj *array_obj = NULL; + struct __pyx_memoryview_obj *memview_obj = NULL; + __Pyx_RefNannySetupContext("__pyx_memoryview_copy_new_contig", 0); + for (i = 0; i < ndim; i++) { + if (unlikely(from_mvs->suboffsets[i] >= 0)) { + PyErr_Format(PyExc_ValueError, "Cannot copy memoryview slice with " + "indirect dimensions (axis %d)", i); + goto fail; + } + } + shape_tuple = PyTuple_New(ndim); + if (unlikely(!shape_tuple)) { + goto fail; + } + __Pyx_GOTREF(shape_tuple); + for(i = 0; i < ndim; i++) { + PyObject *temp_int = PyLong_FromSsize_t(from_mvs->shape[i]); + if(unlikely(!temp_int)) { + goto fail; + } else { + #if CYTHON_ASSUME_SAFE_MACROS + PyTuple_SET_ITEM(shape_tuple, i, temp_int); + #else + if (PyTuple_SetItem(shape_tuple, i, temp_int) < 0) { + goto fail; + } + #endif + } + } + array_obj = __pyx_array_new(shape_tuple, sizeof_dtype, buf->format, mode, NULL); + if (unlikely(!array_obj)) { + goto fail; + } + __Pyx_GOTREF(array_obj); + memview_obj = (struct __pyx_memoryview_obj *) __pyx_memoryview_new( + (PyObject *) array_obj, contig_flag, + dtype_is_object, + from_mvs->memview->typeinfo); + if (unlikely(!memview_obj)) + goto fail; + if (unlikely(__Pyx_init_memviewslice(memview_obj, ndim, &new_mvs, 1) < 0)) + goto fail; + if (unlikely(__pyx_memoryview_copy_contents(*from_mvs, new_mvs, ndim, ndim, + dtype_is_object) < 0)) + goto fail; + goto no_fail; + fail: + __Pyx_XDECREF((PyObject *) new_mvs.memview); + new_mvs.memview = NULL; + new_mvs.data = NULL; + no_fail: + __Pyx_XDECREF(shape_tuple); + __Pyx_XDECREF((PyObject *) array_obj); + __Pyx_RefNannyFinishContext(); + return new_mvs; + } + +/* PyObjectVectorCallKwBuilder (used by CIntToPy) */ + #if CYTHON_VECTORCALL + static int __Pyx_VectorcallBuilder_AddArg(PyObject *key, PyObject *value, PyObject *builder, PyObject **args, int n) { + (void)__Pyx_PyObject_FastCallDict; + Py_INCREF(key); + if (__Pyx_PyTuple_SET_ITEM(builder, n, key) != (0)) return -1; + args[n] = value; + return 0; + } + CYTHON_UNUSED static int __Pyx_VectorcallBuilder_AddArg_Check(PyObject *key, PyObject *value, PyObject *builder, PyObject **args, int n) { + (void)__Pyx_VectorcallBuilder_AddArgStr; + if (unlikely(!PyUnicode_Check(key))) { + PyErr_SetString(PyExc_TypeError, "keywords must be strings"); + return -1; + } + return __Pyx_VectorcallBuilder_AddArg(key, value, builder, args, n); + } + static int __Pyx_VectorcallBuilder_AddArgStr(const char *key, PyObject *value, PyObject *builder, PyObject **args, int n) { + PyObject *pyKey = PyUnicode_FromString(key); + if (!pyKey) return -1; + return __Pyx_VectorcallBuilder_AddArg(pyKey, value, builder, args, n); + } + #else // CYTHON_VECTORCALL + CYTHON_UNUSED static int __Pyx_VectorcallBuilder_AddArg_Check(PyObject *key, PyObject *value, PyObject *builder, CYTHON_UNUSED PyObject **args, CYTHON_UNUSED int n) { + if (unlikely(!PyUnicode_Check(key))) { + PyErr_SetString(PyExc_TypeError, "keywords must be strings"); + return -1; + } + return PyDict_SetItem(builder, key, value); + } + #endif + +/* CIntToPy */ + static CYTHON_INLINE PyObject* __Pyx_PyLong_From_int(int value) { + #ifdef __Pyx_HAS_GCC_DIAGNOSTIC + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wconversion" + #endif + const int neg_one = (int) -1, const_zero = (int) 0; + #ifdef __Pyx_HAS_GCC_DIAGNOSTIC + #pragma GCC diagnostic pop + #endif + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(int) < sizeof(long)) { + return PyLong_FromLong((long) value); + } else if (sizeof(int) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); + #if !CYTHON_COMPILING_IN_PYPY + } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); + #endif + } + } else { + if (sizeof(int) <= sizeof(long)) { + return PyLong_FromLong((long) value); + } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); + } + } + { + unsigned char *bytes = (unsigned char *)&value; + #if !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x030d00A4 + if (is_unsigned) { + return PyLong_FromUnsignedNativeBytes(bytes, sizeof(value), -1); + } else { + return PyLong_FromNativeBytes(bytes, sizeof(value), -1); + } + #elif !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX < 0x030d0000 + int one = 1; int little = (int)*(unsigned char *)&one; + return _PyLong_FromByteArray(bytes, sizeof(int), + little, !is_unsigned); + #else + int one = 1; int little = (int)*(unsigned char *)&one; + PyObject *from_bytes, *result = NULL, *kwds = NULL; + PyObject *py_bytes = NULL, *order_str = NULL; + from_bytes = PyObject_GetAttrString((PyObject*)&PyLong_Type, "from_bytes"); + if (!from_bytes) return NULL; + py_bytes = PyBytes_FromStringAndSize((char*)bytes, sizeof(int)); + if (!py_bytes) goto limited_bad; + order_str = PyUnicode_FromString(little ? "little" : "big"); + if (!order_str) goto limited_bad; + { + PyObject *args[3+(CYTHON_VECTORCALL ? 1 : 0)] = { NULL, py_bytes, order_str }; + if (!is_unsigned) { + kwds = __Pyx_MakeVectorcallBuilderKwds(1); + if (!kwds) goto limited_bad; + if (__Pyx_VectorcallBuilder_AddArgStr("signed", __Pyx_NewRef(Py_True), kwds, args+3, 0) < 0) goto limited_bad; + } + result = __Pyx_Object_Vectorcall_CallFromBuilder(from_bytes, args+1, 2 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET, kwds); + } + limited_bad: + Py_XDECREF(kwds); + Py_XDECREF(order_str); + Py_XDECREF(py_bytes); + Py_XDECREF(from_bytes); + return result; + #endif + } + } + +/* CIntFromPy */ + static CYTHON_INLINE int __Pyx_PyLong_As_int(PyObject *x) { + #ifdef __Pyx_HAS_GCC_DIAGNOSTIC + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wconversion" + #endif + const int neg_one = (int) -1, const_zero = (int) 0; + #ifdef __Pyx_HAS_GCC_DIAGNOSTIC + #pragma GCC diagnostic pop + #endif + const int is_unsigned = neg_one > const_zero; + if (unlikely(!PyLong_Check(x))) { + int val; + PyObject *tmp = __Pyx_PyNumber_Long(x); + if (!tmp) return (int) -1; + val = __Pyx_PyLong_As_int(tmp); + Py_DECREF(tmp); + return val; + } + if (is_unsigned) { + #if CYTHON_USE_PYLONG_INTERNALS + if (unlikely(__Pyx_PyLong_IsNeg(x))) { + goto raise_neg_overflow; + } else if (__Pyx_PyLong_IsCompact(x)) { + __PYX_VERIFY_RETURN_INT(int, __Pyx_compact_upylong, __Pyx_PyLong_CompactValueUnsigned(x)) + } else { + const digit* digits = __Pyx_PyLong_Digits(x); + assert(__Pyx_PyLong_DigitCount(x) > 1); + switch (__Pyx_PyLong_DigitCount(x)) { + case 2: + if ((8 * sizeof(int) > 1 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(int) >= 2 * PyLong_SHIFT)) { + return (int) (((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 3: + if ((8 * sizeof(int) > 2 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(int) >= 3 * PyLong_SHIFT)) { + return (int) (((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 4: + if ((8 * sizeof(int) > 3 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(int) >= 4 * PyLong_SHIFT)) { + return (int) (((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + } + } + #endif + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030C00A7 + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } + #else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (int) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } + #endif + if ((sizeof(int) <= sizeof(unsigned long))) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned long, PyLong_AsUnsignedLong(x)) + } else if ((sizeof(int) <= sizeof(unsigned PY_LONG_LONG))) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) + } + } else { + #if CYTHON_USE_PYLONG_INTERNALS + if (__Pyx_PyLong_IsCompact(x)) { + __PYX_VERIFY_RETURN_INT(int, __Pyx_compact_pylong, __Pyx_PyLong_CompactValue(x)) + } else { + const digit* digits = __Pyx_PyLong_Digits(x); + assert(__Pyx_PyLong_DigitCount(x) > 1); + switch (__Pyx_PyLong_SignedDigitCount(x)) { + case -2: + if ((8 * sizeof(int) - 1 > 1 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(int) - 1 > 2 * PyLong_SHIFT)) { + return (int) (((int)-1)*(((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 2: + if ((8 * sizeof(int) > 1 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(int) - 1 > 2 * PyLong_SHIFT)) { + return (int) ((((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -3: + if ((8 * sizeof(int) - 1 > 2 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(int) - 1 > 3 * PyLong_SHIFT)) { + return (int) (((int)-1)*(((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 3: + if ((8 * sizeof(int) > 2 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(int) - 1 > 3 * PyLong_SHIFT)) { + return (int) ((((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -4: + if ((8 * sizeof(int) - 1 > 3 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(int) - 1 > 4 * PyLong_SHIFT)) { + return (int) (((int)-1)*(((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 4: + if ((8 * sizeof(int) > 3 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(int) - 1 > 4 * PyLong_SHIFT)) { + return (int) ((((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + } + } + #endif + if ((sizeof(int) <= sizeof(long))) { + __PYX_VERIFY_RETURN_INT_EXC(int, long, PyLong_AsLong(x)) + } else if ((sizeof(int) <= sizeof(PY_LONG_LONG))) { + __PYX_VERIFY_RETURN_INT_EXC(int, PY_LONG_LONG, PyLong_AsLongLong(x)) + } + } + { + int val; + int ret = -1; + #if PY_VERSION_HEX >= 0x030d00A6 && !CYTHON_COMPILING_IN_LIMITED_API + Py_ssize_t bytes_copied = PyLong_AsNativeBytes( + x, &val, sizeof(val), Py_ASNATIVEBYTES_NATIVE_ENDIAN | (is_unsigned ? Py_ASNATIVEBYTES_UNSIGNED_BUFFER | Py_ASNATIVEBYTES_REJECT_NEGATIVE : 0)); + if (unlikely(bytes_copied == -1)) { + } else if (unlikely(bytes_copied > (Py_ssize_t) sizeof(val))) { + goto raise_overflow; + } else { + ret = 0; + } + #elif PY_VERSION_HEX < 0x030d0000 && !(CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_LIMITED_API) || defined(_PyLong_AsByteArray) + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + ret = _PyLong_AsByteArray((PyLongObject *)x, + bytes, sizeof(val), + is_little, !is_unsigned); + #else + PyObject *v; + PyObject *stepval = NULL, *mask = NULL, *shift = NULL; + int bits, remaining_bits, is_negative = 0; + int chunk_size = (sizeof(long) < 8) ? 30 : 62; + if (likely(PyLong_CheckExact(x))) { + v = __Pyx_NewRef(x); + } else { + v = PyNumber_Long(x); + if (unlikely(!v)) return (int) -1; + assert(PyLong_CheckExact(v)); + } + { + int result = PyObject_RichCompareBool(v, Py_False, Py_LT); + if (unlikely(result < 0)) { + Py_DECREF(v); + return (int) -1; + } + is_negative = result == 1; + } + if (is_unsigned && unlikely(is_negative)) { + Py_DECREF(v); + goto raise_neg_overflow; + } else if (is_negative) { + stepval = PyNumber_Invert(v); + Py_DECREF(v); + if (unlikely(!stepval)) + return (int) -1; + } else { + stepval = v; + } + v = NULL; + val = (int) 0; + mask = PyLong_FromLong((1L << chunk_size) - 1); if (unlikely(!mask)) goto done; + shift = PyLong_FromLong(chunk_size); if (unlikely(!shift)) goto done; + for (bits = 0; bits < (int) sizeof(int) * 8 - chunk_size; bits += chunk_size) { + PyObject *tmp, *digit; + long idigit; + digit = PyNumber_And(stepval, mask); + if (unlikely(!digit)) goto done; + idigit = PyLong_AsLong(digit); + Py_DECREF(digit); + if (unlikely(idigit < 0)) goto done; + val |= ((int) idigit) << bits; + tmp = PyNumber_Rshift(stepval, shift); + if (unlikely(!tmp)) goto done; + Py_DECREF(stepval); stepval = tmp; + } + Py_DECREF(shift); shift = NULL; + Py_DECREF(mask); mask = NULL; + { + long idigit = PyLong_AsLong(stepval); + if (unlikely(idigit < 0)) goto done; + remaining_bits = ((int) sizeof(int) * 8) - bits - (is_unsigned ? 0 : 1); + if (unlikely(idigit >= (1L << remaining_bits))) + goto raise_overflow; + val |= ((int) idigit) << bits; + } + if (!is_unsigned) { + if (unlikely(val & (((int) 1) << (sizeof(int) * 8 - 1)))) + goto raise_overflow; + if (is_negative) + val = ~val; + } + ret = 0; + done: + Py_XDECREF(shift); + Py_XDECREF(mask); + Py_XDECREF(stepval); + #endif + if (unlikely(ret)) + return (int) -1; + return val; + } + raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to int"); + return (int) -1; + raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to int"); + return (int) -1; + } + +/* CIntToPy */ + static CYTHON_INLINE PyObject* __Pyx_PyLong_From_long(long value) { + #ifdef __Pyx_HAS_GCC_DIAGNOSTIC + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wconversion" + #endif + const long neg_one = (long) -1, const_zero = (long) 0; + #ifdef __Pyx_HAS_GCC_DIAGNOSTIC + #pragma GCC diagnostic pop + #endif + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(long) < sizeof(long)) { + return PyLong_FromLong((long) value); + } else if (sizeof(long) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); + #if !CYTHON_COMPILING_IN_PYPY + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); + #endif + } + } else { + if (sizeof(long) <= sizeof(long)) { + return PyLong_FromLong((long) value); + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); + } + } + { + unsigned char *bytes = (unsigned char *)&value; + #if !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x030d00A4 + if (is_unsigned) { + return PyLong_FromUnsignedNativeBytes(bytes, sizeof(value), -1); + } else { + return PyLong_FromNativeBytes(bytes, sizeof(value), -1); + } + #elif !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX < 0x030d0000 + int one = 1; int little = (int)*(unsigned char *)&one; + return _PyLong_FromByteArray(bytes, sizeof(long), + little, !is_unsigned); + #else + int one = 1; int little = (int)*(unsigned char *)&one; + PyObject *from_bytes, *result = NULL, *kwds = NULL; + PyObject *py_bytes = NULL, *order_str = NULL; + from_bytes = PyObject_GetAttrString((PyObject*)&PyLong_Type, "from_bytes"); + if (!from_bytes) return NULL; + py_bytes = PyBytes_FromStringAndSize((char*)bytes, sizeof(long)); + if (!py_bytes) goto limited_bad; + order_str = PyUnicode_FromString(little ? "little" : "big"); + if (!order_str) goto limited_bad; + { + PyObject *args[3+(CYTHON_VECTORCALL ? 1 : 0)] = { NULL, py_bytes, order_str }; + if (!is_unsigned) { + kwds = __Pyx_MakeVectorcallBuilderKwds(1); + if (!kwds) goto limited_bad; + if (__Pyx_VectorcallBuilder_AddArgStr("signed", __Pyx_NewRef(Py_True), kwds, args+3, 0) < 0) goto limited_bad; + } + result = __Pyx_Object_Vectorcall_CallFromBuilder(from_bytes, args+1, 2 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET, kwds); + } + limited_bad: + Py_XDECREF(kwds); + Py_XDECREF(order_str); + Py_XDECREF(py_bytes); + Py_XDECREF(from_bytes); + return result; + #endif + } + } + +/* PyObjectCall2Args (used by PyObjectCallMethod1) */ + static CYTHON_INLINE PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2) { + PyObject *args[3] = {NULL, arg1, arg2}; + return __Pyx_PyObject_FastCall(function, args+1, 2 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET); + } + +/* PyObjectCallMethod1 (used by UpdateUnpickledDict) */ + #if !(CYTHON_VECTORCALL && (__PYX_LIMITED_VERSION_HEX >= 0x030C0000 || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x03090000))) + static PyObject* __Pyx__PyObject_CallMethod1(PyObject* method, PyObject* arg) { + PyObject *result = __Pyx_PyObject_CallOneArg(method, arg); + Py_DECREF(method); + return result; + } + #endif + static PyObject* __Pyx_PyObject_CallMethod1(PyObject* obj, PyObject* method_name, PyObject* arg) { + #if CYTHON_VECTORCALL && (__PYX_LIMITED_VERSION_HEX >= 0x030C0000 || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x03090000)) + PyObject *args[2] = {obj, arg}; + (void) __Pyx_PyObject_CallOneArg; + (void) __Pyx_PyObject_Call2Args; + return PyObject_VectorcallMethod(method_name, args, 2 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); + #else + PyObject *method = NULL, *result; + int is_method = __Pyx_PyObject_GetMethod(obj, method_name, &method); + if (likely(is_method)) { + result = __Pyx_PyObject_Call2Args(method, obj, arg); + Py_DECREF(method); + return result; + } + if (unlikely(!method)) return NULL; + return __Pyx__PyObject_CallMethod1(method, arg); + #endif + } + +/* UpdateUnpickledDict */ + static int __Pyx__UpdateUnpickledDict(PyObject *obj, PyObject *state, Py_ssize_t index) { + PyObject *state_dict = __Pyx_PySequence_ITEM(state, index); + if (unlikely(!state_dict)) { + return -1; + } + int non_empty = PyObject_IsTrue(state_dict); + if (non_empty == 0) { + Py_DECREF(state_dict); + return 0; + } else if (unlikely(non_empty == -1)) { + return -1; + } + PyObject *dict; + #if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030A0000 + dict = PyObject_GetAttrString(obj, "__dict__"); + #else + dict = PyObject_GenericGetDict(obj, NULL); + #endif + if (unlikely(!dict)) { + Py_DECREF(state_dict); + return -1; + } + int result; + if (likely(PyDict_CheckExact(dict))) { + result = PyDict_Update(dict, state_dict); + } else { + PyObject *obj_result = __Pyx_PyObject_CallMethod1(dict, __pyx_mstate_global->__pyx_n_u_update, state_dict); + if (likely(obj_result)) { + Py_DECREF(obj_result); + result = 0; + } else { + result = -1; + } + } + Py_DECREF(state_dict); + Py_DECREF(dict); + return result; + } + static int __Pyx_UpdateUnpickledDict(PyObject *obj, PyObject *state, Py_ssize_t index) { + Py_ssize_t state_size = __Pyx_PyTuple_GET_SIZE(state); + #if !CYTHON_ASSUME_SAFE_SIZE + if (unlikely(state_size == -1)) return -1; + #endif + if (state_size <= index) { + return 0; + } + return __Pyx__UpdateUnpickledDict(obj, state, index); + } + +/* CheckUnpickleChecksum */ + static void __Pyx_RaiseUnpickleChecksumError(long checksum, long checksum1, long checksum2, long checksum3, const char *members) { + PyObject *pickle_module = PyImport_ImportModule("pickle"); + if (unlikely(!pickle_module)) return; + PyObject *pickle_error = PyObject_GetAttrString(pickle_module, "PickleError"); + Py_DECREF(pickle_module); + if (unlikely(!pickle_error)) return; + if (checksum2 == checksum1) { + PyErr_Format(pickle_error, "Incompatible checksums (0x%x vs (0x%x) = (%s))", + checksum, checksum1, members); + } else if (checksum3 == checksum2) { + PyErr_Format(pickle_error, "Incompatible checksums (0x%x vs (0x%x, 0x%x) = (%s))", + checksum, checksum1, checksum2, members); + } else { + PyErr_Format(pickle_error, "Incompatible checksums (0x%x vs (0x%x, 0x%x, 0x%x) = (%s))", + checksum, checksum1, checksum2, checksum3, members); + } + Py_DECREF(pickle_error); + } + static int __Pyx_CheckUnpickleChecksum(long checksum, long checksum1, long checksum2, long checksum3, const char *members) { + int found = 0; + found |= checksum1 == checksum; + found |= checksum2 == checksum; + found |= checksum3 == checksum; + if (likely(found)) + return 0; + __Pyx_RaiseUnpickleChecksumError(checksum, checksum1, checksum2, checksum3, members); + return -1; + } + +/* CIntFromPy */ + static CYTHON_INLINE long __Pyx_PyLong_As_long(PyObject *x) { + #ifdef __Pyx_HAS_GCC_DIAGNOSTIC + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wconversion" + #endif + const long neg_one = (long) -1, const_zero = (long) 0; + #ifdef __Pyx_HAS_GCC_DIAGNOSTIC + #pragma GCC diagnostic pop + #endif + const int is_unsigned = neg_one > const_zero; + if (unlikely(!PyLong_Check(x))) { + long val; + PyObject *tmp = __Pyx_PyNumber_Long(x); + if (!tmp) return (long) -1; + val = __Pyx_PyLong_As_long(tmp); + Py_DECREF(tmp); + return val; + } + if (is_unsigned) { + #if CYTHON_USE_PYLONG_INTERNALS + if (unlikely(__Pyx_PyLong_IsNeg(x))) { + goto raise_neg_overflow; + } else if (__Pyx_PyLong_IsCompact(x)) { + __PYX_VERIFY_RETURN_INT(long, __Pyx_compact_upylong, __Pyx_PyLong_CompactValueUnsigned(x)) + } else { + const digit* digits = __Pyx_PyLong_Digits(x); + assert(__Pyx_PyLong_DigitCount(x) > 1); + switch (__Pyx_PyLong_DigitCount(x)) { + case 2: + if ((8 * sizeof(long) > 1 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(long) >= 2 * PyLong_SHIFT)) { + return (long) (((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 3: + if ((8 * sizeof(long) > 2 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(long) >= 3 * PyLong_SHIFT)) { + return (long) (((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 4: + if ((8 * sizeof(long) > 3 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(long) >= 4 * PyLong_SHIFT)) { + return (long) (((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + } + } + #endif + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030C00A7 + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } + #else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (long) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } + #endif + if ((sizeof(long) <= sizeof(unsigned long))) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned long, PyLong_AsUnsignedLong(x)) + } else if ((sizeof(long) <= sizeof(unsigned PY_LONG_LONG))) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) + } + } else { + #if CYTHON_USE_PYLONG_INTERNALS + if (__Pyx_PyLong_IsCompact(x)) { + __PYX_VERIFY_RETURN_INT(long, __Pyx_compact_pylong, __Pyx_PyLong_CompactValue(x)) + } else { + const digit* digits = __Pyx_PyLong_Digits(x); + assert(__Pyx_PyLong_DigitCount(x) > 1); + switch (__Pyx_PyLong_SignedDigitCount(x)) { + case -2: + if ((8 * sizeof(long) - 1 > 1 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(long) - 1 > 2 * PyLong_SHIFT)) { + return (long) (((long)-1)*(((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 2: + if ((8 * sizeof(long) > 1 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(long) - 1 > 2 * PyLong_SHIFT)) { + return (long) ((((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -3: + if ((8 * sizeof(long) - 1 > 2 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(long) - 1 > 3 * PyLong_SHIFT)) { + return (long) (((long)-1)*(((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 3: + if ((8 * sizeof(long) > 2 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(long) - 1 > 3 * PyLong_SHIFT)) { + return (long) ((((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -4: + if ((8 * sizeof(long) - 1 > 3 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(long) - 1 > 4 * PyLong_SHIFT)) { + return (long) (((long)-1)*(((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 4: + if ((8 * sizeof(long) > 3 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(long) - 1 > 4 * PyLong_SHIFT)) { + return (long) ((((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + } + } + #endif + if ((sizeof(long) <= sizeof(long))) { + __PYX_VERIFY_RETURN_INT_EXC(long, long, PyLong_AsLong(x)) + } else if ((sizeof(long) <= sizeof(PY_LONG_LONG))) { + __PYX_VERIFY_RETURN_INT_EXC(long, PY_LONG_LONG, PyLong_AsLongLong(x)) + } + } + { + long val; + int ret = -1; + #if PY_VERSION_HEX >= 0x030d00A6 && !CYTHON_COMPILING_IN_LIMITED_API + Py_ssize_t bytes_copied = PyLong_AsNativeBytes( + x, &val, sizeof(val), Py_ASNATIVEBYTES_NATIVE_ENDIAN | (is_unsigned ? Py_ASNATIVEBYTES_UNSIGNED_BUFFER | Py_ASNATIVEBYTES_REJECT_NEGATIVE : 0)); + if (unlikely(bytes_copied == -1)) { + } else if (unlikely(bytes_copied > (Py_ssize_t) sizeof(val))) { + goto raise_overflow; + } else { + ret = 0; + } + #elif PY_VERSION_HEX < 0x030d0000 && !(CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_LIMITED_API) || defined(_PyLong_AsByteArray) + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + ret = _PyLong_AsByteArray((PyLongObject *)x, + bytes, sizeof(val), + is_little, !is_unsigned); + #else + PyObject *v; + PyObject *stepval = NULL, *mask = NULL, *shift = NULL; + int bits, remaining_bits, is_negative = 0; + int chunk_size = (sizeof(long) < 8) ? 30 : 62; + if (likely(PyLong_CheckExact(x))) { + v = __Pyx_NewRef(x); + } else { + v = PyNumber_Long(x); + if (unlikely(!v)) return (long) -1; + assert(PyLong_CheckExact(v)); + } + { + int result = PyObject_RichCompareBool(v, Py_False, Py_LT); + if (unlikely(result < 0)) { + Py_DECREF(v); + return (long) -1; + } + is_negative = result == 1; + } + if (is_unsigned && unlikely(is_negative)) { + Py_DECREF(v); + goto raise_neg_overflow; + } else if (is_negative) { + stepval = PyNumber_Invert(v); + Py_DECREF(v); + if (unlikely(!stepval)) + return (long) -1; + } else { + stepval = v; + } + v = NULL; + val = (long) 0; + mask = PyLong_FromLong((1L << chunk_size) - 1); if (unlikely(!mask)) goto done; + shift = PyLong_FromLong(chunk_size); if (unlikely(!shift)) goto done; + for (bits = 0; bits < (int) sizeof(long) * 8 - chunk_size; bits += chunk_size) { + PyObject *tmp, *digit; + long idigit; + digit = PyNumber_And(stepval, mask); + if (unlikely(!digit)) goto done; + idigit = PyLong_AsLong(digit); + Py_DECREF(digit); + if (unlikely(idigit < 0)) goto done; + val |= ((long) idigit) << bits; + tmp = PyNumber_Rshift(stepval, shift); + if (unlikely(!tmp)) goto done; + Py_DECREF(stepval); stepval = tmp; + } + Py_DECREF(shift); shift = NULL; + Py_DECREF(mask); mask = NULL; + { + long idigit = PyLong_AsLong(stepval); + if (unlikely(idigit < 0)) goto done; + remaining_bits = ((int) sizeof(long) * 8) - bits - (is_unsigned ? 0 : 1); + if (unlikely(idigit >= (1L << remaining_bits))) + goto raise_overflow; + val |= ((long) idigit) << bits; + } + if (!is_unsigned) { + if (unlikely(val & (((long) 1) << (sizeof(long) * 8 - 1)))) + goto raise_overflow; + if (is_negative) + val = ~val; + } + ret = 0; + done: + Py_XDECREF(shift); + Py_XDECREF(mask); + Py_XDECREF(stepval); + #endif + if (unlikely(ret)) + return (long) -1; + return val; + } + raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to long"); + return (long) -1; + raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to long"); + return (long) -1; + } + +/* CIntFromPy */ + static CYTHON_INLINE char __Pyx_PyLong_As_char(PyObject *x) { + #ifdef __Pyx_HAS_GCC_DIAGNOSTIC + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wconversion" + #endif + const char neg_one = (char) -1, const_zero = (char) 0; + #ifdef __Pyx_HAS_GCC_DIAGNOSTIC + #pragma GCC diagnostic pop + #endif + const int is_unsigned = neg_one > const_zero; + if (unlikely(!PyLong_Check(x))) { + char val; + PyObject *tmp = __Pyx_PyNumber_Long(x); + if (!tmp) return (char) -1; + val = __Pyx_PyLong_As_char(tmp); + Py_DECREF(tmp); + return val; + } + if (is_unsigned) { + #if CYTHON_USE_PYLONG_INTERNALS + if (unlikely(__Pyx_PyLong_IsNeg(x))) { + goto raise_neg_overflow; + } else if (__Pyx_PyLong_IsCompact(x)) { + __PYX_VERIFY_RETURN_INT(char, __Pyx_compact_upylong, __Pyx_PyLong_CompactValueUnsigned(x)) + } else { + const digit* digits = __Pyx_PyLong_Digits(x); + assert(__Pyx_PyLong_DigitCount(x) > 1); + switch (__Pyx_PyLong_DigitCount(x)) { + case 2: + if ((8 * sizeof(char) > 1 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(char, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(char) >= 2 * PyLong_SHIFT)) { + return (char) (((((char)digits[1]) << PyLong_SHIFT) | (char)digits[0])); + } + } + break; + case 3: + if ((8 * sizeof(char) > 2 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(char, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(char) >= 3 * PyLong_SHIFT)) { + return (char) (((((((char)digits[2]) << PyLong_SHIFT) | (char)digits[1]) << PyLong_SHIFT) | (char)digits[0])); + } + } + break; + case 4: + if ((8 * sizeof(char) > 3 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(char, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(char) >= 4 * PyLong_SHIFT)) { + return (char) (((((((((char)digits[3]) << PyLong_SHIFT) | (char)digits[2]) << PyLong_SHIFT) | (char)digits[1]) << PyLong_SHIFT) | (char)digits[0])); + } + } + break; + } + } + #endif + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030C00A7 + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } + #else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (char) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } + #endif + if ((sizeof(char) <= sizeof(unsigned long))) { + __PYX_VERIFY_RETURN_INT_EXC(char, unsigned long, PyLong_AsUnsignedLong(x)) + } else if ((sizeof(char) <= sizeof(unsigned PY_LONG_LONG))) { + __PYX_VERIFY_RETURN_INT_EXC(char, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) + } + } else { + #if CYTHON_USE_PYLONG_INTERNALS + if (__Pyx_PyLong_IsCompact(x)) { + __PYX_VERIFY_RETURN_INT(char, __Pyx_compact_pylong, __Pyx_PyLong_CompactValue(x)) + } else { + const digit* digits = __Pyx_PyLong_Digits(x); + assert(__Pyx_PyLong_DigitCount(x) > 1); + switch (__Pyx_PyLong_SignedDigitCount(x)) { + case -2: + if ((8 * sizeof(char) - 1 > 1 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(char, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(char) - 1 > 2 * PyLong_SHIFT)) { + return (char) (((char)-1)*(((((char)digits[1]) << PyLong_SHIFT) | (char)digits[0]))); + } + } + break; + case 2: + if ((8 * sizeof(char) > 1 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(char, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(char) - 1 > 2 * PyLong_SHIFT)) { + return (char) ((((((char)digits[1]) << PyLong_SHIFT) | (char)digits[0]))); + } + } + break; + case -3: + if ((8 * sizeof(char) - 1 > 2 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(char, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(char) - 1 > 3 * PyLong_SHIFT)) { + return (char) (((char)-1)*(((((((char)digits[2]) << PyLong_SHIFT) | (char)digits[1]) << PyLong_SHIFT) | (char)digits[0]))); + } + } + break; + case 3: + if ((8 * sizeof(char) > 2 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(char, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(char) - 1 > 3 * PyLong_SHIFT)) { + return (char) ((((((((char)digits[2]) << PyLong_SHIFT) | (char)digits[1]) << PyLong_SHIFT) | (char)digits[0]))); + } + } + break; + case -4: + if ((8 * sizeof(char) - 1 > 3 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(char, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(char) - 1 > 4 * PyLong_SHIFT)) { + return (char) (((char)-1)*(((((((((char)digits[3]) << PyLong_SHIFT) | (char)digits[2]) << PyLong_SHIFT) | (char)digits[1]) << PyLong_SHIFT) | (char)digits[0]))); + } + } + break; + case 4: + if ((8 * sizeof(char) > 3 * PyLong_SHIFT)) { + if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) { + __PYX_VERIFY_RETURN_INT(char, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if ((8 * sizeof(char) - 1 > 4 * PyLong_SHIFT)) { + return (char) ((((((((((char)digits[3]) << PyLong_SHIFT) | (char)digits[2]) << PyLong_SHIFT) | (char)digits[1]) << PyLong_SHIFT) | (char)digits[0]))); + } + } + break; + } + } + #endif + if ((sizeof(char) <= sizeof(long))) { + __PYX_VERIFY_RETURN_INT_EXC(char, long, PyLong_AsLong(x)) + } else if ((sizeof(char) <= sizeof(PY_LONG_LONG))) { + __PYX_VERIFY_RETURN_INT_EXC(char, PY_LONG_LONG, PyLong_AsLongLong(x)) + } + } + { + char val; + int ret = -1; + #if PY_VERSION_HEX >= 0x030d00A6 && !CYTHON_COMPILING_IN_LIMITED_API + Py_ssize_t bytes_copied = PyLong_AsNativeBytes( + x, &val, sizeof(val), Py_ASNATIVEBYTES_NATIVE_ENDIAN | (is_unsigned ? Py_ASNATIVEBYTES_UNSIGNED_BUFFER | Py_ASNATIVEBYTES_REJECT_NEGATIVE : 0)); + if (unlikely(bytes_copied == -1)) { + } else if (unlikely(bytes_copied > (Py_ssize_t) sizeof(val))) { + goto raise_overflow; + } else { + ret = 0; + } + #elif PY_VERSION_HEX < 0x030d0000 && !(CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_LIMITED_API) || defined(_PyLong_AsByteArray) + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + ret = _PyLong_AsByteArray((PyLongObject *)x, + bytes, sizeof(val), + is_little, !is_unsigned); + #else + PyObject *v; + PyObject *stepval = NULL, *mask = NULL, *shift = NULL; + int bits, remaining_bits, is_negative = 0; + int chunk_size = (sizeof(long) < 8) ? 30 : 62; + if (likely(PyLong_CheckExact(x))) { + v = __Pyx_NewRef(x); + } else { + v = PyNumber_Long(x); + if (unlikely(!v)) return (char) -1; + assert(PyLong_CheckExact(v)); + } + { + int result = PyObject_RichCompareBool(v, Py_False, Py_LT); + if (unlikely(result < 0)) { + Py_DECREF(v); + return (char) -1; + } + is_negative = result == 1; + } + if (is_unsigned && unlikely(is_negative)) { + Py_DECREF(v); + goto raise_neg_overflow; + } else if (is_negative) { + stepval = PyNumber_Invert(v); + Py_DECREF(v); + if (unlikely(!stepval)) + return (char) -1; + } else { + stepval = v; + } + v = NULL; + val = (char) 0; + mask = PyLong_FromLong((1L << chunk_size) - 1); if (unlikely(!mask)) goto done; + shift = PyLong_FromLong(chunk_size); if (unlikely(!shift)) goto done; + for (bits = 0; bits < (int) sizeof(char) * 8 - chunk_size; bits += chunk_size) { + PyObject *tmp, *digit; + long idigit; + digit = PyNumber_And(stepval, mask); + if (unlikely(!digit)) goto done; + idigit = PyLong_AsLong(digit); + Py_DECREF(digit); + if (unlikely(idigit < 0)) goto done; + val |= ((char) idigit) << bits; + tmp = PyNumber_Rshift(stepval, shift); + if (unlikely(!tmp)) goto done; + Py_DECREF(stepval); stepval = tmp; + } + Py_DECREF(shift); shift = NULL; + Py_DECREF(mask); mask = NULL; + { + long idigit = PyLong_AsLong(stepval); + if (unlikely(idigit < 0)) goto done; + remaining_bits = ((int) sizeof(char) * 8) - bits - (is_unsigned ? 0 : 1); + if (unlikely(idigit >= (1L << remaining_bits))) + goto raise_overflow; + val |= ((char) idigit) << bits; + } + if (!is_unsigned) { + if (unlikely(val & (((char) 1) << (sizeof(char) * 8 - 1)))) + goto raise_overflow; + if (is_negative) + val = ~val; + } + ret = 0; + done: + Py_XDECREF(shift); + Py_XDECREF(mask); + Py_XDECREF(stepval); + #endif + if (unlikely(ret)) + return (char) -1; + return val; + } + raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to char"); + return (char) -1; + raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to char"); + return (char) -1; + } + +/* FormatTypeName */ + #if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030d0000 + static __Pyx_TypeName + __Pyx_PyType_GetFullyQualifiedName(PyTypeObject* tp) + { + PyObject *module = NULL, *name = NULL, *result = NULL; + #if __PYX_LIMITED_VERSION_HEX < 0x030b0000 + name = __Pyx_PyObject_GetAttrStr((PyObject *)tp, + __pyx_mstate_global->__pyx_n_u_qualname); + #else + name = PyType_GetQualName(tp); + #endif + if (unlikely(name == NULL) || unlikely(!PyUnicode_Check(name))) goto bad; + module = __Pyx_PyObject_GetAttrStr((PyObject *)tp, + __pyx_mstate_global->__pyx_n_u_module); + if (unlikely(module == NULL) || unlikely(!PyUnicode_Check(module))) goto bad; + if (PyUnicode_CompareWithASCIIString(module, "builtins") == 0) { + result = name; + name = NULL; + goto done; + } + result = PyUnicode_FromFormat("%U.%U", module, name); + if (unlikely(result == NULL)) goto bad; + done: + Py_XDECREF(name); + Py_XDECREF(module); + return result; + bad: + PyErr_Clear(); + if (name) { + result = name; + name = NULL; + } else { + result = __Pyx_NewRef(__pyx_mstate_global->__pyx_kp_u__7); + } + goto done; + } + #endif + +/* GetRuntimeVersion */ + #if __PYX_LIMITED_VERSION_HEX < 0x030b0000 + void __Pyx_init_runtime_version(void) { + if (__Pyx_cached_runtime_version == 0) { + const char* rt_version = Py_GetVersion(); + unsigned long version = 0; + unsigned long factor = 0x01000000UL; + unsigned int digit = 0; + int i = 0; + while (factor) { + while ('0' <= rt_version[i] && rt_version[i] <= '9') { + digit = digit * 10 + (unsigned int) (rt_version[i] - '0'); + ++i; + } + version += factor * digit; + if (rt_version[i] != '.') + break; + digit = 0; + factor >>= 8; + ++i; + } + __Pyx_cached_runtime_version = version; + } + } + #endif + static unsigned long __Pyx_get_runtime_version(void) { + #if __PYX_LIMITED_VERSION_HEX >= 0x030b0000 + return Py_Version & ~0xFFUL; + #else + return __Pyx_cached_runtime_version; + #endif + } + +/* CheckBinaryVersion */ + static int __Pyx_check_binary_version(unsigned long ct_version, unsigned long rt_version, int allow_newer) { + const unsigned long MAJOR_MINOR = 0xFFFF0000UL; + if ((rt_version & MAJOR_MINOR) == (ct_version & MAJOR_MINOR)) + return 0; + if (likely(allow_newer && (rt_version & MAJOR_MINOR) > (ct_version & MAJOR_MINOR))) + return 1; + { + char message[200]; + PyOS_snprintf(message, sizeof(message), + "compile time Python version %d.%d " + "of module '%.100s' " + "%s " + "runtime version %d.%d", + (int) (ct_version >> 24), (int) ((ct_version >> 16) & 0xFF), + __Pyx_MODULE_NAME, + (allow_newer) ? "was newer than" : "does not match", + (int) (rt_version >> 24), (int) ((rt_version >> 16) & 0xFF) + ); + return PyErr_WarnEx(NULL, message, 1); + } + } + +/* NewCodeObj */ + #if CYTHON_COMPILING_IN_LIMITED_API + static PyObject* __Pyx__PyCode_New(int a, int p, int k, int l, int s, int f, + PyObject *code, PyObject *c, PyObject* n, PyObject *v, + PyObject *fv, PyObject *cell, PyObject* fn, + PyObject *name, int fline, PyObject *lnos) { + PyObject *exception_table = NULL; + PyObject *types_module=NULL, *code_type=NULL, *result=NULL; + #if __PYX_LIMITED_VERSION_HEX < 0x030b0000 + PyObject *version_info; + PyObject *py_minor_version = NULL; + #endif + long minor_version = 0; + PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); + #if __PYX_LIMITED_VERSION_HEX >= 0x030b0000 + minor_version = 11; + #else + if (!(version_info = PySys_GetObject("version_info"))) goto end; + if (!(py_minor_version = PySequence_GetItem(version_info, 1))) goto end; + minor_version = PyLong_AsLong(py_minor_version); + Py_DECREF(py_minor_version); + if (minor_version == -1 && PyErr_Occurred()) goto end; + #endif + if (!(types_module = PyImport_ImportModule("types"))) goto end; + if (!(code_type = PyObject_GetAttrString(types_module, "CodeType"))) goto end; + if (minor_version <= 7) { + (void)p; + result = PyObject_CallFunction(code_type, "iiiiiOOOOOOiOOO", a, k, l, s, f, code, + c, n, v, fn, name, fline, lnos, fv, cell); + } else if (minor_version <= 10) { + result = PyObject_CallFunction(code_type, "iiiiiiOOOOOOiOOO", a,p, k, l, s, f, code, + c, n, v, fn, name, fline, lnos, fv, cell); + } else { + if (!(exception_table = PyBytes_FromStringAndSize(NULL, 0))) goto end; + result = PyObject_CallFunction(code_type, "iiiiiiOOOOOOOiOOOO", a,p, k, l, s, f, code, + c, n, v, fn, name, name, fline, lnos, exception_table, fv, cell); + } + end: + Py_XDECREF(code_type); + Py_XDECREF(exception_table); + Py_XDECREF(types_module); + if (type) { + PyErr_Restore(type, value, traceback); + } + return result; + } + #elif PY_VERSION_HEX >= 0x030B0000 + static PyCodeObject* __Pyx__PyCode_New(int a, int p, int k, int l, int s, int f, + PyObject *code, PyObject *c, PyObject* n, PyObject *v, + PyObject *fv, PyObject *cell, PyObject* fn, + PyObject *name, int fline, PyObject *lnos) { + PyCodeObject *result; + result = + #if PY_VERSION_HEX >= 0x030C0000 + PyUnstable_Code_NewWithPosOnlyArgs + #else + PyCode_NewWithPosOnlyArgs + #endif + (a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, name, fline, lnos, __pyx_mstate_global->__pyx_empty_bytes); + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030c00A1 + if (likely(result)) + result->_co_firsttraceable = 0; + #endif + return result; + } + #elif !CYTHON_COMPILING_IN_PYPY + #define __Pyx__PyCode_New(a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_NewWithPosOnlyArgs(a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) + #else + #define __Pyx__PyCode_New(a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) + #endif + static PyObject* __Pyx_PyCode_New( + const __Pyx_PyCode_New_function_description descr, + PyObject * const *varnames, + PyObject *filename, + PyObject *funcname, + PyObject *line_table, + PyObject *tuple_dedup_map + ) { + PyObject *code_obj = NULL, *varnames_tuple_dedup = NULL, *code_bytes = NULL; + Py_ssize_t var_count = (Py_ssize_t) descr.nlocals; + PyObject *varnames_tuple = PyTuple_New(var_count); + if (unlikely(!varnames_tuple)) return NULL; + for (Py_ssize_t i=0; i < var_count; i++) { + Py_INCREF(varnames[i]); + if (__Pyx_PyTuple_SET_ITEM(varnames_tuple, i, varnames[i]) != (0)) goto done; + } + #if CYTHON_COMPILING_IN_LIMITED_API + varnames_tuple_dedup = PyDict_GetItem(tuple_dedup_map, varnames_tuple); + if (!varnames_tuple_dedup) { + if (unlikely(PyDict_SetItem(tuple_dedup_map, varnames_tuple, varnames_tuple) < 0)) goto done; + varnames_tuple_dedup = varnames_tuple; + } + #else + varnames_tuple_dedup = PyDict_SetDefault(tuple_dedup_map, varnames_tuple, varnames_tuple); + if (unlikely(!varnames_tuple_dedup)) goto done; + #endif + #if CYTHON_AVOID_BORROWED_REFS + Py_INCREF(varnames_tuple_dedup); + #endif + if (__PYX_LIMITED_VERSION_HEX >= (0x030b0000) && line_table != NULL && !CYTHON_COMPILING_IN_GRAAL) { + Py_ssize_t line_table_length = __Pyx_PyBytes_GET_SIZE(line_table); + #if !CYTHON_ASSUME_SAFE_SIZE + if (unlikely(line_table_length == -1)) goto done; + #endif + Py_ssize_t code_len = (line_table_length * 2 + 4) & ~3LL; + code_bytes = PyBytes_FromStringAndSize(NULL, code_len); + if (unlikely(!code_bytes)) goto done; + char* c_code_bytes = PyBytes_AsString(code_bytes); + if (unlikely(!c_code_bytes)) goto done; + memset(c_code_bytes, 0, (size_t) code_len); + } + code_obj = (PyObject*) __Pyx__PyCode_New( + (int) descr.argcount, + (int) descr.num_posonly_args, + (int) descr.num_kwonly_args, + (int) descr.nlocals, + 0, + (int) descr.flags, + code_bytes ? code_bytes : __pyx_mstate_global->__pyx_empty_bytes, + __pyx_mstate_global->__pyx_empty_tuple, + __pyx_mstate_global->__pyx_empty_tuple, + varnames_tuple_dedup, + __pyx_mstate_global->__pyx_empty_tuple, + __pyx_mstate_global->__pyx_empty_tuple, + filename, + funcname, + (int) descr.first_line, + (__PYX_LIMITED_VERSION_HEX >= (0x030b0000) && line_table) ? line_table : __pyx_mstate_global->__pyx_empty_bytes + ); + done: + Py_XDECREF(code_bytes); + #if CYTHON_AVOID_BORROWED_REFS + Py_XDECREF(varnames_tuple_dedup); + #endif + Py_DECREF(varnames_tuple); + return code_obj; + } + +/* DecompressString */ + static PyObject *__Pyx_DecompressString(const char *s, Py_ssize_t length, int algo) { + PyObject *module = NULL, *decompress, *compressed_bytes, *decompressed; + const char* module_name = algo == 3 ? "compression.zstd" : algo == 2 ? "bz2" : "zlib"; + PyObject *methodname = PyUnicode_FromString("decompress"); + if (unlikely(!methodname)) return NULL; + #if __PYX_LIMITED_VERSION_HEX >= 0x030e0000 + if (algo == 3) { + PyObject *fromlist = Py_BuildValue("[O]", methodname); + if (unlikely(!fromlist)) goto bad; + module = PyImport_ImportModuleLevel("compression.zstd", NULL, NULL, fromlist, 0); + Py_DECREF(fromlist); + } else + #endif + module = PyImport_ImportModule(module_name); + if (unlikely(!module)) goto import_failed; + decompress = PyObject_GetAttr(module, methodname); + if (unlikely(!decompress)) goto import_failed; + { + #ifdef __cplusplus + char *memview_bytes = const_cast(s); + #else + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wcast-qual" + #elif !defined(__INTEL_COMPILER) && defined(__GNUC__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wcast-qual" + #endif + char *memview_bytes = (char*) s; + #if defined(__clang__) + #pragma clang diagnostic pop + #elif !defined(__INTEL_COMPILER) && defined(__GNUC__) + #pragma GCC diagnostic pop + #endif + #endif + #if CYTHON_COMPILING_IN_LIMITED_API && !defined(PyBUF_READ) + int memview_flags = 0x100; + #else + int memview_flags = PyBUF_READ; + #endif + compressed_bytes = PyMemoryView_FromMemory(memview_bytes, length, memview_flags); + } + if (unlikely(!compressed_bytes)) { + Py_DECREF(decompress); + goto bad; + } + decompressed = PyObject_CallFunctionObjArgs(decompress, compressed_bytes, NULL); + Py_DECREF(compressed_bytes); + Py_DECREF(decompress); + Py_DECREF(module); + Py_DECREF(methodname); + return decompressed; + import_failed: + PyErr_Format(PyExc_ImportError, + "Failed to import '%.20s.decompress' - cannot initialise module strings. " + "String compression was configured with the C macro 'CYTHON_COMPRESS_STRINGS=%d'.", + module_name, algo); + bad: + Py_XDECREF(module); + Py_DECREF(methodname); + return NULL; + } + +#include +static CYTHON_INLINE Py_ssize_t __Pyx_ssize_strlen(const char *s) { + size_t len = strlen(s); + if (unlikely(len > (size_t) PY_SSIZE_T_MAX)) { + PyErr_SetString(PyExc_OverflowError, "byte string is too long"); + return -1; + } + return (Py_ssize_t) len; +} +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) { + Py_ssize_t len = __Pyx_ssize_strlen(c_str); + if (unlikely(len < 0)) return NULL; + return __Pyx_PyUnicode_FromStringAndSize(c_str, len); +} +static CYTHON_INLINE PyObject* __Pyx_PyByteArray_FromString(const char* c_str) { + Py_ssize_t len = __Pyx_ssize_strlen(c_str); + if (unlikely(len < 0)) return NULL; + return PyByteArray_FromStringAndSize(c_str, len); +} +static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject* o) { + Py_ssize_t ignore; + return __Pyx_PyObject_AsStringAndSize(o, &ignore); +} +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 +static CYTHON_INLINE const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { + if (unlikely(__Pyx_PyUnicode_READY(o) == -1)) return NULL; +#if CYTHON_COMPILING_IN_LIMITED_API + { + const char* result; + Py_ssize_t unicode_length; + CYTHON_MAYBE_UNUSED_VAR(unicode_length); // only for __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + #if __PYX_LIMITED_VERSION_HEX < 0x030A0000 + if (unlikely(PyArg_Parse(o, "s#", &result, length) < 0)) return NULL; + #else + result = PyUnicode_AsUTF8AndSize(o, length); + #endif + #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + unicode_length = PyUnicode_GetLength(o); + if (unlikely(unicode_length < 0)) return NULL; + if (unlikely(unicode_length != *length)) { + PyUnicode_AsASCIIString(o); + return NULL; + } + #endif + return result; + } +#else +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + if (likely(PyUnicode_IS_ASCII(o))) { + *length = PyUnicode_GET_LENGTH(o); + return PyUnicode_AsUTF8(o); + } else { + PyUnicode_AsASCIIString(o); + return NULL; + } +#else + return PyUnicode_AsUTF8AndSize(o, length); +#endif +#endif +} +#endif +static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) { +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 + if (PyUnicode_Check(o)) { + return __Pyx_PyUnicode_AsStringAndSize(o, length); + } else +#endif + if (PyByteArray_Check(o)) { +#if (CYTHON_ASSUME_SAFE_SIZE && CYTHON_ASSUME_SAFE_MACROS) || (CYTHON_COMPILING_IN_PYPY && (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE))) + *length = PyByteArray_GET_SIZE(o); + return PyByteArray_AS_STRING(o); +#else + *length = PyByteArray_Size(o); + if (*length == -1) return NULL; + return PyByteArray_AsString(o); +#endif + } else + { + char* result; + int r = PyBytes_AsStringAndSize(o, &result, length); + if (unlikely(r < 0)) { + return NULL; + } else { + return result; + } + } +} +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { + int is_true = x == Py_True; + if (is_true | (x == Py_False) | (x == Py_None)) return is_true; + else return PyObject_IsTrue(x); +} +static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) { + int retval; + if (unlikely(!x)) return -1; + retval = __Pyx_PyObject_IsTrue(x); + Py_DECREF(x); + return retval; +} +static PyObject* __Pyx_PyNumber_LongWrongResultType(PyObject* result) { + __Pyx_TypeName result_type_name = __Pyx_PyType_GetFullyQualifiedName(Py_TYPE(result)); + if (PyLong_Check(result)) { + if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "__int__ returned non-int (type " __Pyx_FMT_TYPENAME "). " + "The ability to return an instance of a strict subclass of int is deprecated, " + "and may be removed in a future version of Python.", + result_type_name)) { + __Pyx_DECREF_TypeName(result_type_name); + Py_DECREF(result); + return NULL; + } + __Pyx_DECREF_TypeName(result_type_name); + return result; + } + PyErr_Format(PyExc_TypeError, + "__int__ returned non-int (type " __Pyx_FMT_TYPENAME ")", + result_type_name); + __Pyx_DECREF_TypeName(result_type_name); + Py_DECREF(result); + return NULL; +} +static CYTHON_INLINE PyObject* __Pyx_PyNumber_Long(PyObject* x) { +#if CYTHON_USE_TYPE_SLOTS + PyNumberMethods *m; +#endif + PyObject *res = NULL; + if (likely(PyLong_Check(x))) + return __Pyx_NewRef(x); +#if CYTHON_USE_TYPE_SLOTS + m = Py_TYPE(x)->tp_as_number; + if (likely(m && m->nb_int)) { + res = m->nb_int(x); + } +#else + if (!PyBytes_CheckExact(x) && !PyUnicode_CheckExact(x)) { + res = PyNumber_Long(x); + } +#endif + if (likely(res)) { + if (unlikely(!PyLong_CheckExact(res))) { + return __Pyx_PyNumber_LongWrongResultType(res); + } + } + else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, + "an integer is required"); + } + return res; +} +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { + Py_ssize_t ival; + PyObject *x; + if (likely(PyLong_CheckExact(b))) { + #if CYTHON_USE_PYLONG_INTERNALS + if (likely(__Pyx_PyLong_IsCompact(b))) { + return __Pyx_PyLong_CompactValue(b); + } else { + const digit* digits = __Pyx_PyLong_Digits(b); + const Py_ssize_t size = __Pyx_PyLong_SignedDigitCount(b); + switch (size) { + case 2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return (Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + } + } + #endif + return PyLong_AsSsize_t(b); + } + x = PyNumber_Index(b); + if (!x) return -1; + ival = PyLong_AsSsize_t(x); + Py_DECREF(x); + return ival; +} +static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject* o) { + if (sizeof(Py_hash_t) == sizeof(Py_ssize_t)) { + return (Py_hash_t) __Pyx_PyIndex_AsSsize_t(o); + } else { + Py_ssize_t ival; + PyObject *x; + x = PyNumber_Index(o); + if (!x) return -1; + ival = PyLong_AsLong(x); + Py_DECREF(x); + return ival; + } +} +static CYTHON_INLINE PyObject *__Pyx_Owned_Py_None(int b) { + CYTHON_UNUSED_VAR(b); + return __Pyx_NewRef(Py_None); +} +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { + return __Pyx_NewRef(b ? Py_True: Py_False); +} +static CYTHON_INLINE PyObject * __Pyx_PyLong_FromSize_t(size_t ival) { + return PyLong_FromSize_t(ival); +} + + + /* MultiPhaseInitModuleState */ + #if CYTHON_PEP489_MULTI_PHASE_INIT && CYTHON_USE_MODULE_STATE + #ifndef CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE + #if (CYTHON_COMPILING_IN_LIMITED_API || PY_VERSION_HEX >= 0x030C0000) + #define CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE 1 + #else + #define CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE 0 + #endif + #endif + #if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE && !CYTHON_ATOMICS + #error "Module state with PEP489 requires atomics. Currently that's one of\ + C11, C++11, gcc atomic intrinsics or MSVC atomic intrinsics" + #endif + #if !CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE + #define __Pyx_ModuleStateLookup_Lock() + #define __Pyx_ModuleStateLookup_Unlock() + #elif !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x030d0000 + static PyMutex __Pyx_ModuleStateLookup_mutex = {0}; + #define __Pyx_ModuleStateLookup_Lock() PyMutex_Lock(&__Pyx_ModuleStateLookup_mutex) + #define __Pyx_ModuleStateLookup_Unlock() PyMutex_Unlock(&__Pyx_ModuleStateLookup_mutex) + #elif defined(__cplusplus) && __cplusplus >= 201103L + #include + static std::mutex __Pyx_ModuleStateLookup_mutex; + #define __Pyx_ModuleStateLookup_Lock() __Pyx_ModuleStateLookup_mutex.lock() + #define __Pyx_ModuleStateLookup_Unlock() __Pyx_ModuleStateLookup_mutex.unlock() + #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ > 201112L) && !defined(__STDC_NO_THREADS__) + #include + static mtx_t __Pyx_ModuleStateLookup_mutex; + static once_flag __Pyx_ModuleStateLookup_mutex_once_flag = ONCE_FLAG_INIT; + static void __Pyx_ModuleStateLookup_initialize_mutex(void) { + mtx_init(&__Pyx_ModuleStateLookup_mutex, mtx_plain); + } + #define __Pyx_ModuleStateLookup_Lock()\ + call_once(&__Pyx_ModuleStateLookup_mutex_once_flag, __Pyx_ModuleStateLookup_initialize_mutex);\ + mtx_lock(&__Pyx_ModuleStateLookup_mutex) + #define __Pyx_ModuleStateLookup_Unlock() mtx_unlock(&__Pyx_ModuleStateLookup_mutex) + #elif defined(HAVE_PTHREAD_H) + #include + static pthread_mutex_t __Pyx_ModuleStateLookup_mutex = PTHREAD_MUTEX_INITIALIZER; + #define __Pyx_ModuleStateLookup_Lock() pthread_mutex_lock(&__Pyx_ModuleStateLookup_mutex) + #define __Pyx_ModuleStateLookup_Unlock() pthread_mutex_unlock(&__Pyx_ModuleStateLookup_mutex) + #elif defined(_WIN32) + #include // synchapi.h on its own doesn't work + static SRWLOCK __Pyx_ModuleStateLookup_mutex = SRWLOCK_INIT; + #define __Pyx_ModuleStateLookup_Lock() AcquireSRWLockExclusive(&__Pyx_ModuleStateLookup_mutex) + #define __Pyx_ModuleStateLookup_Unlock() ReleaseSRWLockExclusive(&__Pyx_ModuleStateLookup_mutex) + #else + #error "No suitable lock available for CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE.\ + Requires C standard >= C11, or C++ standard >= C++11,\ + or pthreads, or the Windows 32 API, or Python >= 3.13." + #endif + typedef struct { + int64_t id; + PyObject *module; + } __Pyx_InterpreterIdAndModule; + typedef struct { + char interpreter_id_as_index; + Py_ssize_t count; + Py_ssize_t allocated; + __Pyx_InterpreterIdAndModule table[1]; + } __Pyx_ModuleStateLookupData; + #define __PYX_MODULE_STATE_LOOKUP_SMALL_SIZE 32 + #if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE + static __pyx_atomic_int_type __Pyx_ModuleStateLookup_read_counter = 0; + #endif + #if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE + static __pyx_atomic_ptr_type __Pyx_ModuleStateLookup_data = 0; + #else + static __Pyx_ModuleStateLookupData* __Pyx_ModuleStateLookup_data = NULL; + #endif + static __Pyx_InterpreterIdAndModule* __Pyx_State_FindModuleStateLookupTableLowerBound( + __Pyx_InterpreterIdAndModule* table, + Py_ssize_t count, + int64_t interpreterId) { + __Pyx_InterpreterIdAndModule* begin = table; + __Pyx_InterpreterIdAndModule* end = begin + count; + if (begin->id == interpreterId) { + return begin; + } + while ((end - begin) > __PYX_MODULE_STATE_LOOKUP_SMALL_SIZE) { + __Pyx_InterpreterIdAndModule* halfway = begin + (end - begin)/2; + if (halfway->id == interpreterId) { + return halfway; + } + if (halfway->id < interpreterId) { + begin = halfway; + } else { + end = halfway; + } + } + for (; begin < end; ++begin) { + if (begin->id >= interpreterId) return begin; + } + return begin; + } + static PyObject *__Pyx_State_FindModule(CYTHON_UNUSED void* dummy) { + int64_t interpreter_id = PyInterpreterState_GetID(__Pyx_PyInterpreterState_Get()); + if (interpreter_id == -1) return NULL; + #if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE + __Pyx_ModuleStateLookupData* data = (__Pyx_ModuleStateLookupData*)__pyx_atomic_pointer_load_relaxed(&__Pyx_ModuleStateLookup_data); + { + __pyx_atomic_incr_acq_rel(&__Pyx_ModuleStateLookup_read_counter); + if (likely(data)) { + __Pyx_ModuleStateLookupData* new_data = (__Pyx_ModuleStateLookupData*)__pyx_atomic_pointer_load_acquire(&__Pyx_ModuleStateLookup_data); + if (likely(data == new_data)) { + goto read_finished; + } + } + __pyx_atomic_decr_acq_rel(&__Pyx_ModuleStateLookup_read_counter); + __Pyx_ModuleStateLookup_Lock(); + __pyx_atomic_incr_relaxed(&__Pyx_ModuleStateLookup_read_counter); + data = (__Pyx_ModuleStateLookupData*)__pyx_atomic_pointer_load_relaxed(&__Pyx_ModuleStateLookup_data); + __Pyx_ModuleStateLookup_Unlock(); + } + read_finished:; + #else + __Pyx_ModuleStateLookupData* data = __Pyx_ModuleStateLookup_data; + #endif + __Pyx_InterpreterIdAndModule* found = NULL; + if (unlikely(!data)) goto end; + if (data->interpreter_id_as_index) { + if (interpreter_id < data->count) { + found = data->table+interpreter_id; + } + } else { + found = __Pyx_State_FindModuleStateLookupTableLowerBound( + data->table, data->count, interpreter_id); + } + end: + { + PyObject *result=NULL; + if (found && found->id == interpreter_id) { + result = found->module; + } + #if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE + __pyx_atomic_decr_acq_rel(&__Pyx_ModuleStateLookup_read_counter); + #endif + return result; + } + } + #if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE + static void __Pyx_ModuleStateLookup_wait_until_no_readers(void) { + while (__pyx_atomic_load(&__Pyx_ModuleStateLookup_read_counter) != 0); + } + #else + #define __Pyx_ModuleStateLookup_wait_until_no_readers() + #endif + static int __Pyx_State_AddModuleInterpIdAsIndex(__Pyx_ModuleStateLookupData **old_data, PyObject* module, int64_t interpreter_id) { + Py_ssize_t to_allocate = (*old_data)->allocated; + while (to_allocate <= interpreter_id) { + if (to_allocate == 0) to_allocate = 1; + else to_allocate *= 2; + } + __Pyx_ModuleStateLookupData *new_data = *old_data; + if (to_allocate != (*old_data)->allocated) { + new_data = (__Pyx_ModuleStateLookupData *)realloc( + *old_data, + sizeof(__Pyx_ModuleStateLookupData)+(to_allocate-1)*sizeof(__Pyx_InterpreterIdAndModule)); + if (!new_data) { + PyErr_NoMemory(); + return -1; + } + for (Py_ssize_t i = new_data->allocated; i < to_allocate; ++i) { + new_data->table[i].id = i; + new_data->table[i].module = NULL; + } + new_data->allocated = to_allocate; + } + new_data->table[interpreter_id].module = module; + if (new_data->count < interpreter_id+1) { + new_data->count = interpreter_id+1; + } + *old_data = new_data; + return 0; + } + static void __Pyx_State_ConvertFromInterpIdAsIndex(__Pyx_ModuleStateLookupData *data) { + __Pyx_InterpreterIdAndModule *read = data->table; + __Pyx_InterpreterIdAndModule *write = data->table; + __Pyx_InterpreterIdAndModule *end = read + data->count; + for (; readmodule) { + write->id = read->id; + write->module = read->module; + ++write; + } + } + data->count = write - data->table; + for (; writeid = 0; + write->module = NULL; + } + data->interpreter_id_as_index = 0; + } + static int __Pyx_State_AddModule(PyObject* module, CYTHON_UNUSED void* dummy) { + int64_t interpreter_id = PyInterpreterState_GetID(__Pyx_PyInterpreterState_Get()); + if (interpreter_id == -1) return -1; + int result = 0; + __Pyx_ModuleStateLookup_Lock(); + #if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE + __Pyx_ModuleStateLookupData *old_data = (__Pyx_ModuleStateLookupData *) + __pyx_atomic_pointer_exchange(&__Pyx_ModuleStateLookup_data, 0); + #else + __Pyx_ModuleStateLookupData *old_data = __Pyx_ModuleStateLookup_data; + #endif + __Pyx_ModuleStateLookupData *new_data = old_data; + if (!new_data) { + new_data = (__Pyx_ModuleStateLookupData *)calloc(1, sizeof(__Pyx_ModuleStateLookupData)); + if (!new_data) { + result = -1; + PyErr_NoMemory(); + goto end; + } + new_data->allocated = 1; + new_data->interpreter_id_as_index = 1; + } + __Pyx_ModuleStateLookup_wait_until_no_readers(); + if (new_data->interpreter_id_as_index) { + if (interpreter_id < __PYX_MODULE_STATE_LOOKUP_SMALL_SIZE) { + result = __Pyx_State_AddModuleInterpIdAsIndex(&new_data, module, interpreter_id); + goto end; + } + __Pyx_State_ConvertFromInterpIdAsIndex(new_data); + } + { + Py_ssize_t insert_at = 0; + { + __Pyx_InterpreterIdAndModule* lower_bound = __Pyx_State_FindModuleStateLookupTableLowerBound( + new_data->table, new_data->count, interpreter_id); + assert(lower_bound); + insert_at = lower_bound - new_data->table; + if (unlikely(insert_at < new_data->count && lower_bound->id == interpreter_id)) { + lower_bound->module = module; + goto end; // already in table, nothing more to do + } + } + if (new_data->count+1 >= new_data->allocated) { + Py_ssize_t to_allocate = (new_data->count+1)*2; + new_data = + (__Pyx_ModuleStateLookupData*)realloc( + new_data, + sizeof(__Pyx_ModuleStateLookupData) + + (to_allocate-1)*sizeof(__Pyx_InterpreterIdAndModule)); + if (!new_data) { + result = -1; + new_data = old_data; + PyErr_NoMemory(); + goto end; + } + new_data->allocated = to_allocate; + } + ++new_data->count; + int64_t last_id = interpreter_id; + PyObject *last_module = module; + for (Py_ssize_t i=insert_at; icount; ++i) { + int64_t current_id = new_data->table[i].id; + new_data->table[i].id = last_id; + last_id = current_id; + PyObject *current_module = new_data->table[i].module; + new_data->table[i].module = last_module; + last_module = current_module; + } + } + end: + #if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE + __pyx_atomic_pointer_exchange(&__Pyx_ModuleStateLookup_data, new_data); + #else + __Pyx_ModuleStateLookup_data = new_data; + #endif + __Pyx_ModuleStateLookup_Unlock(); + return result; + } + static int __Pyx_State_RemoveModule(CYTHON_UNUSED void* dummy) { + int64_t interpreter_id = PyInterpreterState_GetID(__Pyx_PyInterpreterState_Get()); + if (interpreter_id == -1) return -1; + __Pyx_ModuleStateLookup_Lock(); + #if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE + __Pyx_ModuleStateLookupData *data = (__Pyx_ModuleStateLookupData *) + __pyx_atomic_pointer_exchange(&__Pyx_ModuleStateLookup_data, 0); + #else + __Pyx_ModuleStateLookupData *data = __Pyx_ModuleStateLookup_data; + #endif + if (data->interpreter_id_as_index) { + if (interpreter_id < data->count) { + data->table[interpreter_id].module = NULL; + } + goto done; + } + { + __Pyx_ModuleStateLookup_wait_until_no_readers(); + __Pyx_InterpreterIdAndModule* lower_bound = __Pyx_State_FindModuleStateLookupTableLowerBound( + data->table, data->count, interpreter_id); + if (!lower_bound) goto done; + if (lower_bound->id != interpreter_id) goto done; + __Pyx_InterpreterIdAndModule *end = data->table+data->count; + for (;lower_boundid = (lower_bound+1)->id; + lower_bound->module = (lower_bound+1)->module; + } + } + --data->count; + if (data->count == 0) { + free(data); + data = NULL; + } + done: + #if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE + __pyx_atomic_pointer_exchange(&__Pyx_ModuleStateLookup_data, data); + #else + __Pyx_ModuleStateLookup_data = data; + #endif + __Pyx_ModuleStateLookup_Unlock(); + return 0; + } + #endif + +/* #### Code section: utility_code_pragmas_end ### */ +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + + + +/* #### Code section: end ### */ +#endif /* Py_PYTHON_H */ diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/utils/monotonic_align/core.pyx b/matcha_inference_standalone/Matcha-TTS/matcha/utils/monotonic_align/core.pyx new file mode 100644 index 0000000000000000000000000000000000000000..091fcc3a50a51f3d3fee47a70825260757e6d885 --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/utils/monotonic_align/core.pyx @@ -0,0 +1,47 @@ +import numpy as np + +cimport cython +cimport numpy as np + +from cython.parallel import prange + + +@cython.boundscheck(False) +@cython.wraparound(False) +cdef void maximum_path_each(int[:,::1] path, float[:,::1] value, int t_x, int t_y, float max_neg_val) nogil: + cdef int x + cdef int y + cdef float v_prev + cdef float v_cur + cdef float tmp + cdef int index = t_x - 1 + + for y in range(t_y): + for x in range(max(0, t_x + y - t_y), min(t_x, y + 1)): + if x == y: + v_cur = max_neg_val + else: + v_cur = value[x, y-1] + if x == 0: + if y == 0: + v_prev = 0. + else: + v_prev = max_neg_val + else: + v_prev = value[x-1, y-1] + value[x, y] = max(v_cur, v_prev) + value[x, y] + + for y in range(t_y - 1, -1, -1): + path[index, y] = 1 + if index != 0 and (index == y or value[index, y-1] < value[index-1, y-1]): + index = index - 1 + + +@cython.boundscheck(False) +@cython.wraparound(False) +cpdef void maximum_path_c(int[:,:,::1] paths, float[:,:,::1] values, int[::1] t_xs, int[::1] t_ys, float max_neg_val=-1e9) nogil: + cdef int b = values.shape[0] + + cdef int i + for i in prange(b, nogil=True): + maximum_path_each(paths[i], values[i], t_xs[i], t_ys[i], max_neg_val) diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/utils/monotonic_align/setup.py b/matcha_inference_standalone/Matcha-TTS/matcha/utils/monotonic_align/setup.py new file mode 100644 index 0000000000000000000000000000000000000000..f22bc6a35a5a04c9e6d7b82040973722c9b770c9 --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/utils/monotonic_align/setup.py @@ -0,0 +1,7 @@ +# from distutils.core import setup +# from Cython.Build import cythonize +# import numpy + +# setup(name='monotonic_align', +# ext_modules=cythonize("core.pyx"), +# include_dirs=[numpy.get_include()]) diff --git a/matcha_inference_standalone/Matcha-TTS/matcha/utils/utils.py b/matcha_inference_standalone/Matcha-TTS/matcha/utils/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..c09e6692e0f609b17cb72d7ccb5db21a9e534c94 --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha/utils/utils.py @@ -0,0 +1,47 @@ +import os +import sys +from pathlib import Path +import numpy as np +import torch + +def intersperse(lst, item): + # Adds blank symbol + result = [item] * (len(lst) * 2 + 1) + result[1::2] = lst + return result + +def to_numpy(tensor): + if isinstance(tensor, np.ndarray): + return tensor + elif isinstance(tensor, torch.Tensor): + return tensor.detach().cpu().numpy() + elif isinstance(tensor, list): + return np.array(tensor) + else: + raise TypeError("Unsupported type for conversion to numpy array") + +def get_user_data_dir(appname="matcha_tts"): + MATCHA_HOME = os.environ.get("MATCHA_HOME") + if MATCHA_HOME is not None: + ans = Path(MATCHA_HOME).expanduser().resolve(strict=False) + elif sys.platform == "win32": + import winreg # pylint: disable=import-outside-toplevel + key = winreg.OpenKey( + winreg.HKEY_CURRENT_USER, + r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders", + ) + dir_, _ = winreg.QueryValueEx(key, "Local AppData") + ans = Path(dir_).resolve(strict=False) + elif sys.platform == "darwin": + ans = Path("~/Library/Application Support/").expanduser() + else: + ans = Path.home().joinpath(".local/share") + + final_path = ans.joinpath(appname) + final_path.mkdir(parents=True, exist_ok=True) + return final_path + +def assert_model_downloaded(checkpoint_path, url, use_wget=True): + if Path(checkpoint_path).exists(): + return + raise FileNotFoundError(f"Model not found at {checkpoint_path}! Standalone mode requires models to be pre-downloaded.") diff --git a/matcha_inference_standalone/Matcha-TTS/matcha_tts.egg-info/PKG-INFO b/matcha_inference_standalone/Matcha-TTS/matcha_tts.egg-info/PKG-INFO new file mode 100644 index 0000000000000000000000000000000000000000..b1c7fcaabd7cd3d494403633a12574cd9d710797 --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha_tts.egg-info/PKG-INFO @@ -0,0 +1,26 @@ +Metadata-Version: 2.4 +Name: matcha-tts +Version: 0.0.1 +Summary: Matcha-TTS Standalone Inference Package +Requires-Python: >=3.9.0 +Description-Content-Type: text/markdown +Requires-Dist: torch>=2.0.0 +Requires-Dist: lightning>=2.0.0 +Requires-Dist: numpy +Requires-Dist: scipy +Requires-Dist: librosa +Requires-Dist: soundfile +Requires-Dist: Cython +Requires-Dist: einops +Requires-Dist: inflect +Requires-Dist: Unidecode +Requires-Dist: conformer==0.3.2 +Requires-Dist: diffusers +Requires-Dist: phonemizer +Dynamic: description +Dynamic: description-content-type +Dynamic: requires-dist +Dynamic: requires-python +Dynamic: summary + +Matcha-TTS standalone package for inference diff --git a/matcha_inference_standalone/Matcha-TTS/matcha_tts.egg-info/SOURCES.txt b/matcha_inference_standalone/Matcha-TTS/matcha_tts.egg-info/SOURCES.txt new file mode 100644 index 0000000000000000000000000000000000000000..220ff39cd4b33cb84aa9412f342bec077defb0c6 --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha_tts.egg-info/SOURCES.txt @@ -0,0 +1,34 @@ +pyproject.toml +setup.py +matcha/__init__.py +matcha/hifigan/__init__.py +matcha/hifigan/config.py +matcha/hifigan/denoiser.py +matcha/hifigan/env.py +matcha/hifigan/meldataset.py +matcha/hifigan/models.py +matcha/hifigan/xutils.py +matcha/models/__init__.py +matcha/models/baselightningmodule.py +matcha/models/matcha_tts.py +matcha/models/components/__init__.py +matcha/models/components/decoder.py +matcha/models/components/flow_matching.py +matcha/models/components/text_encoder.py +matcha/models/components/transformer.py +matcha/text/__init__.py +matcha/text/cleaners.py +matcha/text/numbers.py +matcha/text/symbols.py +matcha/utils/__init__.py +matcha/utils/audio.py +matcha/utils/model.py +matcha/utils/utils.py +matcha/utils/monotonic_align/__init__.py +matcha/utils/monotonic_align/core.c +matcha/utils/monotonic_align/setup.py +matcha_tts.egg-info/PKG-INFO +matcha_tts.egg-info/SOURCES.txt +matcha_tts.egg-info/dependency_links.txt +matcha_tts.egg-info/requires.txt +matcha_tts.egg-info/top_level.txt \ No newline at end of file diff --git a/matcha_inference_standalone/Matcha-TTS/matcha_tts.egg-info/dependency_links.txt b/matcha_inference_standalone/Matcha-TTS/matcha_tts.egg-info/dependency_links.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha_tts.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/matcha_inference_standalone/Matcha-TTS/matcha_tts.egg-info/requires.txt b/matcha_inference_standalone/Matcha-TTS/matcha_tts.egg-info/requires.txt new file mode 100644 index 0000000000000000000000000000000000000000..3d8109f6162e5c77ecc937388d2bf38b7ff60ea6 --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha_tts.egg-info/requires.txt @@ -0,0 +1,13 @@ +torch>=2.0.0 +lightning>=2.0.0 +numpy +scipy +librosa +soundfile +Cython +einops +inflect +Unidecode +conformer==0.3.2 +diffusers +phonemizer diff --git a/matcha_inference_standalone/Matcha-TTS/matcha_tts.egg-info/top_level.txt b/matcha_inference_standalone/Matcha-TTS/matcha_tts.egg-info/top_level.txt new file mode 100644 index 0000000000000000000000000000000000000000..ac32aa8633c4ebede38a03041c895232292117ad --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/matcha_tts.egg-info/top_level.txt @@ -0,0 +1 @@ +matcha diff --git a/matcha_inference_standalone/Matcha-TTS/pyproject.toml b/matcha_inference_standalone/Matcha-TTS/pyproject.toml new file mode 100644 index 0000000000000000000000000000000000000000..1150674b4f9e94b54e68d884806b6d242268e21c --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/pyproject.toml @@ -0,0 +1,51 @@ +[build-system] +requires = ["setuptools", "wheel", "cython>=3.0.0", "numpy>=1.26.0", "packaging"] + +[tool.black] +line-length = 120 +target-version = ['py310'] +exclude = ''' + +( + /( + \.eggs # exclude a few common directories in the + | \.git # root of the project + | \.hg + | \.mypy_cache + | \.tox + | \.venv + | _build + | buck-out + | build + | dist + )/ + | foo.py # also separately exclude a file named foo.py in + # the root of the project +) +''' + +[tool.pytest.ini_options] +addopts = [ + "--color=yes", + "--durations=0", + "--strict-markers", + "--doctest-modules", +] +filterwarnings = [ + "ignore::DeprecationWarning", + "ignore::UserWarning", +] +log_cli = "True" +markers = [ + "slow: slow tests", +] +minversion = "6.0" +testpaths = "tests/" + +[tool.coverage.report] +exclude_lines = [ + "pragma: nocover", + "raise NotImplementedError", + "raise NotImplementedError()", + "if __name__ == .__main__.:", +] diff --git a/matcha_inference_standalone/Matcha-TTS/requirements.txt b/matcha_inference_standalone/Matcha-TTS/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..3d8109f6162e5c77ecc937388d2bf38b7ff60ea6 --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/requirements.txt @@ -0,0 +1,13 @@ +torch>=2.0.0 +lightning>=2.0.0 +numpy +scipy +librosa +soundfile +Cython +einops +inflect +Unidecode +conformer==0.3.2 +diffusers +phonemizer diff --git a/matcha_inference_standalone/Matcha-TTS/setup.py b/matcha_inference_standalone/Matcha-TTS/setup.py new file mode 100644 index 0000000000000000000000000000000000000000..7483d712253f872ef2301a4e4a52842574f5df0f --- /dev/null +++ b/matcha_inference_standalone/Matcha-TTS/setup.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python +import os +import numpy +from Cython.Build import cythonize +from setuptools import Extension, find_packages, setup + +exts = [ + Extension( + name="matcha.utils.monotonic_align.core", + sources=["matcha/utils/monotonic_align/core.pyx"], + ) +] + +def get_requires(): + requirements = os.path.join(os.path.dirname(__file__), "requirements.txt") + with open(requirements, encoding="utf-8") as reqfile: + return [str(r).strip() for r in reqfile] + +setup( + name="matcha-tts", + version="0.0.1", + description="Matcha-TTS Standalone Inference Package", + long_description="Matcha-TTS standalone package for inference", + long_description_content_type="text/markdown", + install_requires=get_requires(), + include_dirs=[numpy.get_include()], + include_package_data=True, + packages=find_packages(), + ext_modules=cythonize(exts, language_level=3), + python_requires=">=3.9.0", +) diff --git a/matcha_inference_standalone/README.md b/matcha_inference_standalone/README.md new file mode 100644 index 0000000000000000000000000000000000000000..c1dc4254d663cd01bc502e6a398fb8ef809fa2d4 --- /dev/null +++ b/matcha_inference_standalone/README.md @@ -0,0 +1,134 @@ +# Gói Chạy Model Matcha-TTS Di Động - Giọng Nữ Tiếng Việt (Tăng Tốc 4.0x Chuẩn Google) + +Thư mục này chứa đầy đủ mô hình và mã nguồn tối giản, chỉ giữ lại các tệp tin cần thiết nhất để chạy giọng nữ Tiếng Việt, hỗ trợ điều chỉnh tốc độ chuẩn Google (WSOLA) và chỉnh âm lượng. + +Có hai cách sử dụng: Chạy qua tập lệnh CLI (`run_tts.py`) hoặc chạy làm một API Server độc lập (`api_server.py`). + +## 📁 Cấu trúc thư mục tối giản +- `run_tts.py`: Tập lệnh CLI chính để chạy đọc truyện. +- `api_server.py`: API Server FastAPI hỗ trợ chạy ngầm và gọi qua HTTP POST. +- `model/`: + - `checkpoint_016.ckpt`: Checkpoint giọng nói (Epoch 16). + - `generator_v1`: Bộ giải mã âm thanh HiFi-GAN Vocoder. +- `Matcha-TTS/`: Thư viện lõi (chỉ chứa các file Python định nghĩa mô hình, không chứa file rác). + +--- + +## 🚀 Hướng dẫn cài đặt trên máy mới + +### Bước 1: Cài đặt công cụ hệ thống (FFmpeg) +Yêu cầu hệ thống cần có **FFmpeg** để điều chỉnh tốc độ và âm lượng. +- **Ubuntu / Debian**: + ```bash + sudo apt-get update && sudo apt-get install -y ffmpeg + ``` +- **macOS** (yêu cầu Homebrew): + ```bash + brew install ffmpeg + ``` + +### Bước 2: Thiết lập môi trường và biên dịch mô hình +Chạy lệnh sau tại thư mục chứa bộ code này: +```bash +# 1. Tạo và kích hoạt môi trường ảo Python (khuyên dùng Python 3.10 hoặc 3.12) +python -m venv .venv +source .venv/bin/activate + +# 2. Cài đặt các thư viện cần thiết và tự động biên dịch module core cho máy mới +cd Matcha-TTS +pip install -e . +cd .. +``` + +--- + +## 💻 Cách 1: Sử dụng CLI (`run_tts.py`) + +Kích hoạt môi trường ảo (`source .venv/bin/activate`) và chạy: + +### 1. Đọc truyện với tốc độ 4.0x (chuẩn Google) và âm lượng mặc định: +```bash +python run_tts.py --text "Thạch thôn nằm ở giữa núi rừng hoang dã." --speed 4.0 --output truyen_4x.wav +``` + +### 2. Tăng âm lượng to hơn (ví dụ: tăng gấp rưỡi hoặc gấp đôi): +* **Tăng 50% âm lượng (1.5 lần)**: + ```bash + python run_tts.py --text "Thạch thôn nằm ở giữa núi rừng hoang dã." --speed 4.0 --volume 1.5 --output truyen_to_hon.wav + ``` +* **Tăng gấp đôi âm lượng (2.0 lần)**: + ```bash + python run_tts.py --text "Thạch thôn nằm ở giữa núi rừng hoang dã." --speed 4.0 --volume 2.0 --output truyen_rat_to.wav + ``` + +--- + +## 🌐 Cách 2: Sử dụng API Server (`api_server.py`) + +Nếu bạn muốn chạy mô hình thành một dịch vụ ngầm (API) để các ứng dụng khác gọi qua mạng: + +### 1. Khởi chạy Server: +```bash +# Kích hoạt môi trường ảo +source .venv/bin/activate + +# Chạy server ở cổng mặc định 8016 (hoặc thay đổi bằng cách đặt biến môi trường PORT=8080) +python api_server.py +``` + +### 2. Gọi API để tổng hợp giọng nói: + +* **Gọi bằng `curl` (Lưu file Wav trực tiếp):** + ```bash + curl -X POST http://127.0.0.1:8016/synthesize \ + -H "Content-Type: application/json" \ + -d '{"text": "Kính chào quý thính giả đã đến với kênh truyện.", "speed": 4.0, "volume": 1.5}' \ + --output truyen_tu_api.wav + ``` + +* **Gọi bằng Python Code:** + ```python + import requests + + url = "http://127.0.0.1:8016/synthesize" + data = { + "text": "Kính chào quý thính giả đã đến với kênh truyện.", + "speed": 4.0, + "volume": 1.5 + } + + response = requests.post(url, json=data) + if response.status_code == 200: + with open("truyen_tu_api.wav", "wb") as f: + f.write(response.content) + print("Tải file thành công!") + else: + print("Lỗi:", response.json()) + ``` + +--- + +## 🧠 Thuật toán xử lý âm thanh & Ngắt nghỉ tối ưu (Audiobook Algorithm) + +Nhằm tối ưu hóa Matcha-TTS phục vụ việc đọc truyện tiểu thuyết dài hơi (ngọng ngắt, không đều giọng, giật pha), hệ thống đã cài đặt một thuật toán khâu nối waveform và xử lý văn bản chuyên biệt: + +### 1. Phân rã văn bản theo đoạn văn thực tế (Paragraph-based Chunking) +* **Nguyên lý:** Thay vì chia nhỏ văn bản theo từng câu độc lập (khiến mô hình mất đi tính liên kết ngữ cảnh và hạ giọng đột ngột), hệ thống chia văn bản dựa theo các **đoạn văn thực tế (xuống dòng `\n`)**. +* **Đặc điểm:** Một đoạn văn dài (nhiều câu) được sinh ra liên mạch trong một chu kỳ inference đơn lẻ của Matcha-TTS. Giúp mô hình tự kiểm soát ngữ điệu, cao độ luyến láy và nhịp ngắt nghỉ siêu ngắn giữa các câu con một cách tự nhiên nhất. +* **Hạn chế độ dài:** Chỉ khi đoạn văn vượt quá **85 từ**, thuật toán mới tự động chia tách nhỏ theo dấu chấm câu để tránh quá tải VRAM. + +### 2. Thuật toán Nối Smoothstep & Chèn khoảng nghỉ tĩnh (Fading & Silence Insertion) +Để ghép nối các đoạn văn độc lập mà không bị click/gập biên độ sóng âm hoặc tạo cảm giác dồn dập (hụt hơi), thuật toán `concatenate_with_pause_and_smooth_fades` thực hiện: +* **Fade-out đuôi đoạn trước (150ms):** Sử dụng hàm số mịn **Smoothstep** $s = 3t^2 - 2t^3$ (gia tốc biến đổi ở biên bằng 0) để vuốt âm lượng của 150ms cuối cùng về 0. Giúp giọng đọc giảm xuống một cách cực kỳ êm ái, nhẹ nhàng. +* **Khoảng nghỉ tĩnh (550ms):** Chèn một mảng dữ liệu âm thanh tĩnh (zeros) dài 550ms giữa hai đoạn văn. Đây là khoảng dừng vàng giúp người nghe có cảm giác thong thả, tự nhiên như MC thực sự ngắt nhịp để chuyển ý. +* **Fade-in đầu đoạn sau (150ms):** Vuốt âm lượng đầu đoạn văn sau từ 0 lên 1.0 trong 150ms bằng đường cong Smoothstep để triệt tiêu hiện tượng giật vọt biên độ (click nhiễu). + +### 3. Kiểm soát độ luyến láy / Lên xuống giọng (Noise Variance) +* **Tham số:** Tích hợp tham số điều khiển `temperature` (mặc định là `0.667`). +* **Đặc tính:** + * Tăng lên `0.8 - 0.9` sẽ làm tăng phương sai của nhiễu Gaussian đầu vào, thúc đẩy mô hình giải ODE tạo ra giọng đọc uốn lượn bay bổng, gia tốc cao độ mạnh mẽ hơn. + * Giảm xuống `0.5 - 0.55` sẽ làm giảm phương sai, ép giọng điệu bám sát quỹ đạo ổn định nhất, đặc biệt **hạn chế tối đa hiện tượng vọt biên hay giật giọng** ở vùng leo cao hoặc xuống thấp biên độ. + +### 4. Tăng tốc và Điều phối Âm lượng toàn cục +* Sau khi ghép nối các đoạn văn thành một sóng âm 1.0x hoàn chỉnh, hệ thống đẩy file qua bộ lọc **FFmpeg WSOLA (`atempo`)** để thay đổi tốc độ đọc mà không làm thay đổi tần số (méo giọng), kết hợp bộ lọc **`volume`** để chuẩn hóa cường độ âm thanh đầu ra. + diff --git a/matcha_inference_standalone/api_server.py b/matcha_inference_standalone/api_server.py new file mode 100644 index 0000000000000000000000000000000000000000..c989524ee34d6a322cfe91185738c6b344e8e616 --- /dev/null +++ b/matcha_inference_standalone/api_server.py @@ -0,0 +1,402 @@ +import os +import sys +import re +import tempfile +import subprocess +import hashlib +import shutil +import asyncio +from concurrent.futures import ThreadPoolExecutor + +import torch +import soundfile as sf +import numpy as np +import uvicorn +from fastapi import FastAPI, HTTPException, Body, BackgroundTasks +from fastapi.responses import FileResponse + +# ─── Cấu hình ──────────────────────────────────────────────────────────────── +current_dir = os.path.dirname(os.path.abspath(__file__)) +sys.path.insert(0, os.path.join(current_dir, "Matcha-TTS")) + +CHECKPOINT_PATH = os.path.join(current_dir, "model", "checkpoint_016_int8.pt") +VOCODER_PATH = os.path.join(current_dir, "model", "generator_v1") +CACHE_DIR = os.path.join(current_dir, "cache_1x") +SAMPLE_RATE = 22050 + +# Số worker = số core CPU muốn dùng song song (mặc định: dùng hết tất cả core) +NUM_WORKERS = int(os.environ.get("TTS_WORKERS", os.cpu_count() or 4)) + +os.makedirs(CACHE_DIR, exist_ok=True) + +# ─── Import model (lazy, chỉ import khi cần) ───────────────────────────────── +from matcha.hifigan.config import v1 +from matcha.hifigan.env import AttrDict +from matcha.hifigan.models import Generator as HiFiGAN +from matcha.models.matcha_tts import MatchaTTS +from matcha.text import text_to_sequence +from matcha.utils.utils import intersperse + +app = FastAPI(title="Matcha-TTS API – Per-Core Worker Pool") + +# ─── Trạng thái toàn cục ───────────────────────────────────────────────────── +_matcha_model = None +_vocoder_model = None +_executor = None # ThreadPoolExecutor +_device = None + +# ─── Khởi động server ──────────────────────────────────────────────────────── +@app.on_event("startup") +def startup(): + global _matcha_model, _vocoder_model, _executor, _device + + # Mỗi thread PyTorch chỉ dùng đúng 1 CPU core + torch.set_num_threads(1) + + _device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + mode = "GPU" if _device.type == "cuda" else f"CPU ({NUM_WORKERS} core song song)" + print(f"[+] Chế độ: {mode}") + + # Tải mô hình một lần, chia sẻ giữa các worker (weights only = read-only) + print(f"[!] Đang tải Matcha-TTS: {CHECKPOINT_PATH}") + # Đọc lớp PyTorch 2.6 an toàn + original_load = torch.load + def patched_load(*args, **kwargs): + kwargs['weights_only'] = False + return original_load(*args, **kwargs) + torch.load = patched_load + + ckpt_or_model = torch.load(CHECKPOINT_PATH, map_location=_device) + + # Hỗ trợ tự động nhận diện cả Model cũ (Float32) và Model nén (INT8) + if isinstance(ckpt_or_model, dict) and "state_dict" in ckpt_or_model: + _matcha_model = MatchaTTS(**ckpt_or_model["hyper_parameters"]) + _matcha_model.load_state_dict(ckpt_or_model["state_dict"]) + else: + _matcha_model = ckpt_or_model + + _matcha_model = _matcha_model.to(_device).eval() + + print("[!] Đang tải HiFi-GAN Vocoder...") + h = AttrDict(v1) + _vocoder_model = HiFiGAN(h).to(_device) + _vocoder_model.load_state_dict( + torch.load(VOCODER_PATH, map_location=_device)["generator"] + ) + _vocoder_model.eval() + _vocoder_model.remove_weight_norm() + + # Warm-up Matcha-TTS & Vocoder + print("[!] Đang chạy warm-up cho mô hình TTS...", flush=True) + try: + dummy_text = "Khởi động." + x = torch.tensor( + intersperse(text_to_sequence(dummy_text, ["basic_cleaners_vi_female"])[0], 0), + dtype=torch.long, device=_device, + )[None] + x_lengths = torch.tensor([x.shape[-1]], dtype=torch.long, device=_device) + with torch.inference_mode(): + out = _matcha_model.synthesise( + x, x_lengths, n_timesteps=2, + temperature=0.5, spks=None, length_scale=1.0 + ) + _ = _vocoder_model(out["mel"]).clamp(-1, 1).squeeze().cpu().numpy() + print("[✓] Warm-up mô hình TTS thành công!", flush=True) + except Exception as e: + print(f"[⚠️] Lỗi chạy warm-up mô hình TTS: {e}", flush=True) + + # Tạo thread pool: mỗi thread = 1 CPU core worker + _executor = ThreadPoolExecutor( + max_workers=NUM_WORKERS, + thread_name_prefix="tts-worker" + ) + print(f"[✓] Server sẵn sàng! {NUM_WORKERS} worker(s), mỗi worker = 1 CPU core") + +# ─── Utility ───────────────────────────────────────────────────────────────── +def cleanup_file(path: str): + try: + if os.path.exists(path): + os.remove(path) + except Exception: + pass + +def build_ffmpeg_filter(speed: float, volume: float) -> str: + filters = [] + if volume != 1.0: + filters.append(f"volume={volume}") + rem = speed + while rem > 2.0: + filters.append("atempo=2.0") + rem /= 2.0 + while rem < 0.5: + filters.append("atempo=0.5") + rem /= 0.5 + if abs(rem - 1.0) > 0.01: + filters.append(f"atempo={rem}") + return ",".join(filters) if filters else "anull" + +def split_text_into_chunks(text: str, max_words: int = 85) -> list[tuple[str, str]]: + """Tách văn bản thành các chunk dựa trên các đoạn văn (xuống dòng). + Giúp giọng đọc trong một đoạn văn (gồm nhiều câu) được liền mạch, trôi chảy và tự nhiên nhất. + Nếu một đoạn văn quá dài (> max_words), mới chia nhỏ theo dấu chấm câu. + """ + text = text.strip() + if not text: + return [] + + raw_paragraphs = [p.strip() for p in text.split('\n') if p.strip()] + sentence_boundary = re.compile(r'([.?!]+|\.\.\.)(?=\s|$)') + final_chunks = [] + + for paragraph in raw_paragraphs: + words = paragraph.split() + if len(words) <= max_words: + final_chunks.append((paragraph, '.')) + continue + + # Nếu đoạn văn quá dài, tách theo dấu câu kết thúc câu (. ? !) + pos = 0 + current_sentence = "" + for match in sentence_boundary.finditer(paragraph): + end_punc = match.group(1) + start_idx, end_idx = match.span() + chunk_content = paragraph[pos:start_idx].strip() + + if chunk_content: + if current_sentence: + current_sentence += " " + chunk_content + else: + current_sentence = chunk_content + + if current_sentence: + final_chunks.append((current_sentence + end_punc, '.')) + current_sentence = "" + pos = end_idx + + remaining = paragraph[pos:].strip() + if remaining: + if current_sentence: + current_sentence += " " + remaining + else: + current_sentence = remaining + if current_sentence: + final_chunks.append((current_sentence, '.')) + + return [(c.strip(), p) for c, p in final_chunks if c.strip()] + +def apply_fades(audio: np.ndarray, sample_rate: int = 22050, fade_duration: float = 0.05) -> np.ndarray: + """Áp dụng fade-in/out tuyến tính ở đầu và cuối audio để triệt tiêu tiếng click/gập biên độ.""" + audio = audio.copy() + fade_samples = int(fade_duration * sample_rate) + n_samples = len(audio) + actual_fade = min(fade_samples, n_samples // 2) + if actual_fade <= 0: + return audio + + # Fade in + fade_in = np.linspace(0.0, 1.0, actual_fade) + audio[:actual_fade] *= fade_in + + # Fade out + fade_out = np.linspace(1.0, 0.0, actual_fade) + audio[-actual_fade:] *= fade_out + + return audio + +def concatenate_with_pause_and_smooth_fades( + chunks: list[np.ndarray], + sample_rate: int = 22050, + fade_duration: float = 0.15, # 150ms fade + silence_duration: float = 0.20 # 200ms natural pause gap +) -> np.ndarray: + """ + Nối các chunk bằng cách vuốt Smoothstep nhanh về 0 (150ms), chèn khoảng nghỉ ngắn (200ms), + và vuốt Smoothstep lên từ 0 (150ms). Giúp giữ giọng bình bình ở cuối câu rồi nghỉ tự nhiên. + """ + if not chunks: + return np.zeros(0, dtype=np.float32) + + fade_samples = int(sample_rate * fade_duration) + silence_samples = int(sample_rate * silence_duration) + + processed_chunks = [] + for i, chunk in enumerate(chunks): + chunk = chunk.copy() + n_samples = len(chunk) + + # Fade in ở đầu chunk (từ câu thứ 2 trở đi) + if i > 0 and fade_samples > 0: + actual_fade = min(fade_samples, n_samples // 2) + if actual_fade > 0: + t = np.linspace(0.0, 1.0, actual_fade) + s = 3 * (t ** 2) - 2 * (t ** 3) + chunk[:actual_fade] *= s + + # Fade out ở cuối chunk (đến câu kế cuối) + if i < len(chunks) - 1 and fade_samples > 0: + actual_fade = min(fade_samples, n_samples // 2) + if actual_fade > 0: + t = np.linspace(0.0, 1.0, actual_fade) + s = 3 * (t ** 2) - 2 * (t ** 3) + chunk[-actual_fade:] *= (1.0 - s) + + processed_chunks.append(chunk) + + # Chèn khoảng nghỉ ở giữa + if i < len(chunks) - 1 and silence_samples > 0: + processed_chunks.append(np.zeros(silence_samples, dtype=np.float32)) + + return np.concatenate(processed_chunks) + +# ─── Công việc inference (chạy trong thread pool, 1 core / request) ────────── +def _do_inference(text: str, cache_path: str, n_timesteps: int, length_scale: float, temperature: float) -> np.ndarray: + """Chạy Matcha-TTS + HiFi-GAN cho 1 chunk, trả về waveform và ghi vào cache_path.""" + x = torch.tensor( + intersperse(text_to_sequence(text, ["basic_cleaners_vi_female"])[0], 0), + dtype=torch.long, device=_device, + )[None] + x_lengths = torch.tensor([x.shape[-1]], dtype=torch.long, device=_device) + + with torch.inference_mode(): + out = _matcha_model.synthesise( + x, x_lengths, n_timesteps=n_timesteps, + temperature=temperature, spks=None, length_scale=length_scale + ) + audio = _vocoder_model(out["mel"]).clamp(-1, 1).squeeze().cpu().numpy() + + # Chuẩn hóa âm lượng cho chunk + max_val = np.max(np.abs(audio)) + if max_val > 0: + audio = audio / max_val * 0.95 + + sf.write(cache_path, audio, SAMPLE_RATE) + return audio + +def _do_ffmpeg(input_path: str, speed: float, volume: float) -> str: + """Chạy FFmpeg để đổi tốc độ/âm lượng, trả về đường dẫn file tạm.""" + fd, out_path = tempfile.mkstemp(suffix=".wav") + os.close(fd) + f = build_ffmpeg_filter(speed, volume) + subprocess.run( + ["ffmpeg", "-y", "-i", input_path, "-filter:a", f, out_path], + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True + ) + return out_path + +# ─── Endpoint chính ─────────────────────────────────────────────────────────── +@app.post("/synthesize") +@app.post("/v1/audio/speech") +async def synthesize( + background_tasks: BackgroundTasks, + text: str = Body(None, embed=True), + input: str = Body(None, embed=True), + speed: float = Body(1.0, embed=True), + volume: float = Body(1.0, embed=True), + steps: int = Body(10, embed=True), # Mặc định: 10 steps + n_timesteps: int = Body(None, embed=True), + temperature: float = Body(0.50, embed=True), + length_scale: float = Body(None, embed=True), + bypass_cache: bool = Body(False, embed=True), +): + actual_text = text or input + if not actual_text or not actual_text.strip(): + raise HTTPException(400, "Văn bản không được để trống") + + actual_steps = n_timesteps if n_timesteps is not None else steps + loop = asyncio.get_event_loop() + + # Luôn sinh mô hình ở tốc độ 1.0x để tối ưu hoá tỷ lệ trúng cache của các chunk + # Sau đó sẽ dùng FFmpeg để điều chỉnh tốc độ đọc của tệp âm thanh hoàn chỉnh (bao gồm cả khoảng nghỉ) + if length_scale is not None: + model_length_scale = length_scale + ffmpeg_speed = speed / (1.0 / model_length_scale) if speed else 1.0 + else: + model_length_scale = 1.0 + ffmpeg_speed = speed if speed else 1.0 + + # Kiểm tra cache toàn cục cho câu đầy đủ ở tốc độ gốc 1.0x (ls = model_length_scale) + full_hash = hashlib.sha256( + f"{actual_text}_steps_{actual_steps}_ls_{model_length_scale:.4f}_temp_{temperature}".encode() + ).hexdigest() + full_cached_path = os.path.join(CACHE_DIR, f"full_{full_hash}.wav") + + if not bypass_cache and os.path.exists(full_cached_path): + print(f"[✓] Cache hit (full 1.0x hash: {full_hash[:8]}) – bỏ qua GPU/CPU") + cached_path = full_cached_path + else: + # Tách văn bản thành các chunk nhỏ tự nhiên + chunks = split_text_into_chunks(actual_text, max_words=85) + if not chunks: + raise HTTPException(400, "Văn bản không hợp lệ") + + print(f"[~] Bắt đầu xử lý {len(chunks)} chunk(s) với {actual_steps} steps (temp: {temperature}, ls: {model_length_scale:.4f})...") + + # Xử lý tuần tự từng chunk (caching riêng cho từng chunk ở tốc độ 1.0x) + chunk_audios = [] + for i, (chunk_text, punc) in enumerate(chunks): + chunk_hash = hashlib.sha256( + f"{chunk_text}_steps_{actual_steps}_ls_{model_length_scale:.4f}_temp_{temperature}".encode() + ).hexdigest() + chunk_cache_path = os.path.join(CACHE_DIR, f"chunk_{chunk_hash}.wav") + + if not bypass_cache and os.path.exists(chunk_cache_path): + print(f" [✓] Chunk {i+1}/{len(chunks)} cache hit (hash: {chunk_hash[:8]})") + audio, _ = await loop.run_in_executor(None, sf.read, chunk_cache_path) + chunk_audios.append(audio) + else: + print(f" [→] Chunk {i+1}/{len(chunks)} cache miss – đang sinh (hash: {chunk_hash[:8]})") + # Gọi inference chạy trên thread pool + audio = await loop.run_in_executor( + _executor, _do_inference, chunk_text, chunk_cache_path, actual_steps, model_length_scale, temperature + ) + chunk_audios.append(audio) + + # Ghép nối các chunk 1.0x với khoảng lặng mặc định là 300ms (0.3s) + # Khi dùng FFmpeg tăng tốc lên x1.5, khoảng nghỉ này tự động thu lại còn 200ms + full_audio = concatenate_with_pause_and_smooth_fades( + chunk_audios, + SAMPLE_RATE, + fade_duration=0.15, # 150ms vuốt nhanh Smoothstep + silence_duration=0.1 # Mặc định 100ms cho 1.0x + ) + + # Lưu cache file 1.0x + await loop.run_in_executor(None, sf.write, full_cached_path, full_audio, SAMPLE_RATE) + cached_path = full_cached_path + print(f"[✓] Đã lưu cache full 1.0x thành công: {cached_path}") + + # Áp dụng thay đổi tốc độ/âm lượng bằng FFmpeg toàn cục trên file đã ghép (nếu cần) + try: + if abs(ffmpeg_speed - 1.0) > 0.01 or abs(volume - 1.0) > 0.01: + out_path = await loop.run_in_executor( + _executor, _do_ffmpeg, cached_path, ffmpeg_speed, volume + ) + background_tasks.add_task(cleanup_file, out_path) + return FileResponse(out_path, media_type="audio/wav") + else: + return FileResponse(cached_path, media_type="audio/wav") + except Exception as e: + raise HTTPException(500, f"Lỗi FFmpeg: {e}") + +# ─── Endpoint phụ ───────────────────────────────────────────────────────────── +@app.post("/clear_cache") +async def clear_cache(): + shutil.rmtree(CACHE_DIR, ignore_errors=True) + os.makedirs(CACHE_DIR, exist_ok=True) + return {"status": "ok", "message": "Đã xóa toàn bộ cache"} + +@app.get("/status") +async def status(): + busy = _executor._work_queue.qsize() if _executor else 0 + return { + "workers": NUM_WORKERS, + "device": str(_device), + "threads_per_worker": 1, + "queue_pending": busy, + } + +if __name__ == "__main__": + port = int(os.environ.get("PORT", 8016)) + print(f"[*] Khởi động server tại http://0.0.0.0:{port}") + print(f"[*] Để tuỳ chỉnh số core: TTS_WORKERS=2 python api_server.py") + uvicorn.run(app, host="0.0.0.0", port=port) diff --git a/matcha_inference_standalone/test_api.py b/matcha_inference_standalone/test_api.py new file mode 100644 index 0000000000000000000000000000000000000000..d5c39b8f02a69f68e06103853d62045903dfa913 --- /dev/null +++ b/matcha_inference_standalone/test_api.py @@ -0,0 +1,40 @@ +import os +import requests +import time + +url = "http://127.0.0.1:8016/synthesize" +text_file = "novel_chapter.txt" + +if not os.path.exists(text_file): + print(f"Error: {text_file} not found!") + exit(1) + +with open(text_file, "r", encoding="utf-8") as f: + text = f.read() + +payload = { + "text": text, + "speed": 1.0, + "volume": 1.0, + "steps": 10, + "temperature": 0.50, + "bypass_cache": True # Force GPU processing to verify it runs without errors +} + +print(f"[~] Sending request to API server: {url}") +print(f"[~] Text length: {len(text)} characters, {len(text.split())} words") + +start_time = time.time() +response = requests.post(url, json=payload) +elapsed = time.time() - start_time + +if response.status_code == 200: + output_file = "api_test_output.wav" + with open(output_file, "wb") as f: + f.write(response.content) + print(f"[✓] Success! Response code: 200") + print(f"[✓] Time taken: {elapsed:.2f} seconds") + print(f"[✓] Output saved to: {output_file}") +else: + print(f"[x] Failed! Response code: {response.status_code}") + print(response.json()) diff --git a/matcha_inference_standalone/tienhiepai_tts_engine.spec b/matcha_inference_standalone/tienhiepai_tts_engine.spec new file mode 100644 index 0000000000000000000000000000000000000000..7a0f1fc671f0e20c7d760dab3fda99f86b5f8c34 --- /dev/null +++ b/matcha_inference_standalone/tienhiepai_tts_engine.spec @@ -0,0 +1,38 @@ +# -*- mode: python ; coding: utf-8 -*- + + +a = Analysis( + ['api_server.py'], + pathex=[], + binaries=[], + datas=[], + hiddenimports=[], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, + optimize=0, +) +pyz = PYZ(a.pure) + +exe = EXE( + pyz, + a.scripts, + a.binaries, + a.datas, + [], + name='tienhiepai_tts_engine', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + upx_exclude=[], + runtime_tmpdir=None, + console=True, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, +) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..f08dbb97608cdf5c038f363b6b75bf8773ba4471 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,18 @@ +Flask>=2.0.0 +PyJWT>=2.4.0 +bcrypt>=4.0.0 +requests>=2.28.0 +PyYAML>=6.0 +pytz>=2022.1 +gunicorn>=20.1.0 +psycopg2-binary>=2.9.0 +python-dotenv>=0.21.0 +flask-cors>=3.0.10 +google-auth>=2.15.0 +jieba>=0.42.1 +hanziconv>=0.3.2 +colorama>=0.4.6 +gevent>=23.9.1 +Flask-Compress>=1.14 +Flask-Compress +huggingface_hub>=0.20.0 diff --git a/start_hf.sh b/start_hf.sh new file mode 100755 index 0000000000000000000000000000000000000000..9b3beff8dd7edfe3462f1142fdc36b3ba482e8cb --- /dev/null +++ b/start_hf.sh @@ -0,0 +1,81 @@ +#!/bin/bash +set -e +echo "=== Tienhiep Backend Startup ===" + +APP_DIR="/home/user/app" +cd "$APP_DIR" + +# Download DB files from HF Dataset at RUNTIME (token available as env var) +echo "Checking database files..." +python3 - <<'PYEOF' +import os, sys +from huggingface_hub import hf_hub_download + +token = os.environ.get("HF_TOKEN", "") +if not token: + print("WARNING: HF_TOKEN not set - skipping DB download") + sys.exit(0) + +app_dir = "/home/user/app" +files_to_download = [ + "users_data.db", + "dictionaries/Aligned_HanViet.txt", + "dictionaries/HanViet_CharDict.txt", + "dictionaries/Names.txt", + "dictionaries/Vietphrase.txt", + "dictionaries/chu_nom_all.csv", + "dictionaries/han_all_readings.csv", + "dictionaries/han_characters_only.csv", + "dictionaries/han_readings_lookup.csv", + "dictionaries/user_dict_jieba.txt", + "dictionaries/user_dict_underthesea.txt", +] + +for fname in files_to_download: + target = os.path.join(app_dir, fname) + if fname == "users_data.db" and os.path.exists(target): + try: + os.remove(target) + except Exception: + pass + if os.path.exists(target) and os.path.getsize(target) > 1024: + print(f" OK (exists): {fname}") + continue + print(f" Downloading {fname}...", flush=True) + try: + os.makedirs(os.path.dirname(target), exist_ok=True) + hf_hub_download( + repo_id="Cong123779/tienhiep-data", + filename=fname, + repo_type="dataset", + token=token, + local_dir=app_dir, + local_dir_use_symlinks=False, + ) + size = os.path.getsize(target) // 1024 + if size > 1024: + print(f" Done: {fname} ({size // 1024}MB)", flush=True) + else: + print(f" Done: {fname} ({size}KB)", flush=True) + except Exception as e: + print(f" WARN: {fname}: {e}", flush=True) + +print("Database and dictionary check complete!", flush=True) +PYEOF + +PORT=${PORT:-7860} + +# Mặc định tắt Email Worker trên HuggingFace Space để tránh lỗi mạng IMAP và quá tải CPU +export DISABLE_FLASK_EMAIL_WORKER="true" +echo "Email Worker is disabled on HuggingFace Space." + +echo "Starting Gunicorn on port $PORT..." +exec gunicorn \ + --bind 0.0.0.0:$PORT \ + --workers 1 \ + --threads 4 \ + --timeout 120 \ + --preload \ + --access-logfile - \ + --error-logfile - \ + viewer_server:app diff --git a/viewer_server.py b/viewer_server.py new file mode 100644 index 0000000000000000000000000000000000000000..478a0fe6b2ac22aceea624749b925daf481f520f --- /dev/null +++ b/viewer_server.py @@ -0,0 +1,136 @@ +""" +viewer_server.py — Application Entrypoint + +This file was refactored from a 2800-line monolith into a clean entrypoint. +All business logic has been moved to the `backend/` package: + + backend/ + ├── __init__.py ← App Factory (create_app) + ├── config.py ← All config & environment variables + ├── api/ ← Flask Blueprints (routes/controllers) + │ ├── auth.py + │ ├── books.py + │ ├── payment.py + │ ├── translate.py + │ ├── epub.py + │ └── developer.py + ├── services/ ← Business logic layer + │ ├── auth_service.py + │ ├── book_service.py + │ ├── payment_service.py + │ ├── email_service.py + │ ├── epub_service.py + │ └── translation.py + ├── database/ + │ └── db_manager.py ← DB connections, circuit breaker, caches + ├── core/ + │ ├── security.py ← JWT, bcrypt helpers + │ ├── decorators.py ← @jwt_required, @require_api_key_auth + │ └── rate_limit.py ← IP rate limiters + └── workers/ + └── email_worker.py ← Background IMAP/Gmail email polling + +To run the server: + python viewer_server.py +Or with gunicorn: + gunicorn -w 4 -b 0.0.0.0:5051 "viewer_server:app" +""" + +import logging +import sys +import traceback +from flask import jsonify + +from backend.core.logger import setup_logger +logger = setup_logger("server") + +from backend import create_app + +app = create_app() + +@app.errorhandler(Exception) +def handle_exception(e): + """Global unhandled exception handler to output clean JSON in production.""" + # Log the complete stack trace + error_msg = f"Unhandled exception encountered: {str(e)}" + stack_trace = traceback.format_exc() + logger.error(error_msg) + logger.error(stack_trace) + + # Trigger asynchronous alert email to Admin + try: + from backend.services.alert_service import send_alert_to_admin + subject = f"Lỗi nghiêm trọng (500 Internal Error): {str(e)[:50]}" + body = f"Đã xảy ra lỗi chưa xử lý trên server:
Lỗi: {str(e)}

Stack Trace:
{stack_trace.replace(chr(10), '
')}" + send_alert_to_admin("critical_error", subject, body) + except Exception as alert_err: + logger.error(f"Failed to trigger alert email for exception: {alert_err}") + + # Return JSON response instead of HTML traceback page + return jsonify({ + "error": "Internal Server Error. Please contact administrator.", + "success": False + }), 500 + +@app.route("/api/temp-db-fix", methods=["GET"]) +def temp_db_fix(): + from flask import request + secret = request.args.get("secret") + if secret != "super_secret_db_fix_2026": + return "Unauthorized", 403 + + import os + import psycopg2 + url = os.environ.get("DATABASE_URL") + if not url: + return "DATABASE_URL environment variable is missing", 500 + + logs = [] + try: + conn = psycopg2.connect(url) + cursor = conn.cursor() + + # 1. Clean up user 75 + tables_to_clean = [ + "refresh_tokens", "bookshelf", "reading_history", "password_reset_tokens", + "api_keys", "api_usage", "translation_history", "vocabulary", + "user_settings", "usage_tracking", "personal_notifications", "login_history" + ] + for tbl in tables_to_clean: + try: + cursor.execute(f"DELETE FROM {tbl} WHERE user_id = 75") + logs.append(f"✔ Cleaned {tbl} for user_id = 75") + except Exception as e: + logs.append(f"ℹ Could not clean {tbl} for user_id = 75: {e}") + + try: + cursor.execute("DELETE FROM users WHERE id = 75") + logs.append("✔ Deleted user 75 from users table") + except Exception as e: + logs.append(f"❌ Failed to delete user 75: {e}") + + # 2. Link VIP user congkx123789 to Gmail + cursor.execute("SELECT id, username, email, vip_status FROM users WHERE username = %s OR id = 100", ("congkx123789",)) + vip_user = cursor.fetchone() + if vip_user: + vip_id = vip_user[0] + cursor.execute(""" + UPDATE users + SET email = %s, + google_id = NULL, + email_verified = 1 + WHERE id = %s + """, ("havucong25@gmail.com", vip_id)) + logs.append(f"✔ Linked VIP user {vip_user[1]} (ID {vip_id}) to havucong25@gmail.com") + else: + logs.append("❌ VIP user congkx123789 not found in database") + + conn.commit() + conn.close() + return jsonify({"success": True, "logs": logs}) + except Exception as e: + return jsonify({"success": False, "error": str(e), "logs": logs}) + +if __name__ == "__main__": + logger.info("🚀 Server đang khởi động tại: http://localhost:5051") + app.run(host="0.0.0.0", port=5051, debug=False, threaded=True)