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


# modules/Import_Excel.py
import tkinter as tk
from tkinter import filedialog, messagebox, ttk

import numpy as np
import pandas as pd


class ImportFilesWindow(tk.Toplevel):
    def __init__(self, parent):
        super().__init__(parent)
        self.title("Импорт файлов из Excel")
        self.geometry("450x200")

        # Основная рамка окна
        main_frame = ttk.Frame(self)
        main_frame.pack(padx=10, pady=10, fill="both", expand=True)

        # Настройка весов колонок
        main_frame.columnconfigure(0, weight=1)
        main_frame.columnconfigure(1, weight=1)
        main_frame.columnconfigure(2, weight=1)

        # Элементы управления
        # ------------------------------

        # 1. Выбор файла
        tk.Label(main_frame, text="Выберите файл Excel:").grid(
            row=0, column=0, sticky="w"
        )
        self.file_path_entry = tk.Entry(main_frame, width=30)
        self.file_path_entry.grid(row=0, column=1, sticky="we", pady=5)
        browse_button = ttk.Button(
            main_frame, text="Обзор...", command=self.browse_file
        )
        browse_button.grid(row=0, column=2, sticky="e", pady=5)

        # 2. Выбор листа
        tk.Label(main_frame, text="Выберите лист (группу):").grid(
            row=1, column=0, sticky="w"
        )
        self.sheet_combobox = ttk.Combobox(main_frame, state="readonly", width=20)
        self.sheet_combobox.grid(row=1, column=1, sticky="we", pady=5)
        self.sheet_combobox.bind("<<ComboboxSelected>>", self.on_sheet_change)

        # 3. Проверка транзитивности
        tk.Label(main_frame, text="Проверить на транзитивность:").grid(
            row=2, column=0, sticky="w"
        )
        self.transitivity_percentage_label = tk.Label(
            main_frame, text="", relief="groove", width=10
        )
        self.transitivity_percentage_label.grid(row=2, column=1, sticky="w", pady=5)
        check_button = ttk.Button(
            main_frame, text="Проверить", command=self.check_transitivity
        )
        check_button.grid(row=2, column=2, sticky="e", pady=5)

        # 4. Кнопки принятия и отмены
        button_frame = ttk.Frame(main_frame)
        button_frame.grid(row=3, column=0, columnspan=3, sticky="we", pady=5)
        button_frame.columnconfigure(0, weight=1)
        button_frame.columnconfigure(1, weight=1)

        accept_button = ttk.Button(
            button_frame, text="Принять файл", command=self.accept_file
        )
        accept_button.grid(row=0, column=0, sticky="ew", padx=5)

        cancel_button = ttk.Button(
            button_frame, text="Отменить", command=self.cancel_file
        )
        cancel_button.grid(row=0, column=1, sticky="ew", padx=5)

    def browse_file(self):
        """Открывает диалог выбора файла."""
        file_path = filedialog.askopenfilename(
            filetypes=[("Excel files", ".xls .xlsx")]
        )
        if file_path:
            self.file_path_entry.delete(0, tk.END)
            self.file_path_entry.insert(0, file_path)
            self.load_sheets_from_file(file_path)

    def load_sheets_from_file(self, file_path):
        """Загружает листы из указанного файла."""
        try:
            xls = pd.ExcelFile(file_path)
            sheets = xls.sheet_names
            self.sheet_combobox["values"] = sheets
            if sheets:
                # Выбираем первый лист по умолчанию
                self.sheet_combobox.current(0)
        except Exception as e:
            print(f"Ошибка при загрузке листов: {e}")

    def on_sheet_change(self, event):
        """Очищает результат проверки при смене выбранного листа."""
        self.transitivity_percentage_label.config(text="")

    def check_transitivity(self):
        """Проверяет транзитивность матрицы."""
        file_path = self.file_path_entry.get()
        selected_sheet = self.sheet_combobox.get()

        if not file_path or not selected_sheet:
            messagebox.showwarning("Внимание", "Пожалуйста, укажите файл и лист!")
            return

        try:
            df = pd.read_excel(
                file_path,
                sheet_name=selected_sheet,
                decimal=",",
                header=None,
                skiprows=1,
            )
            df = df.select_dtypes(include=[np.number]).dropna(how="all").values

            # Проверяем транзитивность верхней треугольной матрицы
            transitivity_percentage = is_transitive_matrix_upper_triangular(df)
            self.transitivity_percentage_label.config(
                text=f"{transitivity_percentage:.1f}%"
            )
        except Exception as e:
            print(f"Ошибка при проверке транзитивности: {e}")
            self.transitivity_percentage_label.config(text="Ошибка при расчёте")

    def accept_file(self):
        """Подтверждает выбор файла."""
        file_path = self.file_path_entry.get()
        selected_sheet = self.sheet_combobox.get()

        if file_path and selected_sheet:
            # Здесь можно добавить дополнительную обработку принятого файла
            print(f"Принят файл: {file_path}, выбран лист: {selected_sheet}")
        else:
            messagebox.showwarning("Внимание", "Пожалуйста, укажите файл и лист!")

    def cancel_file(self):
        """Отменяет выбор файла."""
        self.file_path_entry.delete(0, tk.END)
        self.sheet_combobox.set("")
        self.transitivity_percentage_label.config(text="")


# Вспомогательная функция для проверки транзитивности матрицы
def is_transitive_matrix_upper_triangular(matrix):
    n = len(matrix)
    count = 0
    total_elements = 0

    # Просматриваем верхний треугольник матрицы
    for i in range(n):
        for j in range(i + 1, n):
            if matrix[i][j] >= 1:  # Первое условие выполнено
                for k in range(j + 1, n):
                    if matrix[j][k] >= 1:  # Второе условие выполнено
                        total_elements += 1
                        if matrix[i][k] >= 1:  # Третье условие выполнено
                            count += 1

    if total_elements == 0:
        return 100.0  # Нет данных для проверки, принимаем за транзитивную
    else:
        return (count / total_elements) * 100