Скачиваний:
0
Добавлен:
11.01.2026
Размер:
47.39 Кб
Скачать
#include <vcl.h>
#include <windows.h>

#pragma comment(lib, "user32.lib")

// ПРАВИЛЬНАЯ ФУНКЦИЯ ДЛЯ #pragma startup
void SetRussianLocale()
{
    SetConsoleOutputCP(1251);
    SetConsoleCP(1251);
}
#pragma startup SetRussianLocale

#include <stdio.h>
#include <string.h>
#include <cctype>
#pragma hdrstop

#include "ControlListTech.h"
#include "class.h"
#include "TanksGame.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TFormControlListTech *FormControlListTech;
//---------------------------------------------------------------------------
__fastcall TFormControlListTech::TFormControlListTech(TComponent* Owner)
    : TForm(Owner), deviceCount(0), supplyCount(0), repairCount(0)
{
	// Настройка поля поиска
	SearchEdit->Visible = false;
	SearchEdit->TextHint = "Введите текст для поиска...";

	ListView1->OnDblClick = ListView1DblClick;
    ListView1->OnMouseDown = ListView1MouseDown;

	PageControl1->OnChange = PageControl1Change;

	BtnAdd->OnClick = BtnAddClickClick;

	ButtonAddSupplier->OnClick = ButtonAddSupplierClick;
    if (CheckListBox2) {
        CheckListBox2->OnClick = CheckListBox2Click;
	}


    if (CheckListBox1) {
        CheckListBox1->Items->Clear();
        CheckListBox1->Items->Add("Сканеры");
        CheckListBox1->Items->Add("Принтеры");
        CheckListBox1->Items->Add("Компьютеры");
        CheckListBox1->Items->Add("Факсы");
        CheckListBox1->Items->Add("Мониторы");

        // По умолчанию все отмечены
        for (int i = 0; i < CheckListBox1->Items->Count; i++) {
            CheckListBox1->Checked[i] = true;
        }
    }

    if (CheckListBox1) {
    CheckListBox1->OnClick = CheckListBox1ClickReport;
	}

    UpdateMainListView(); // Обновляем таблицу (будет пустая)
    ShowMessage("Программа запущена. Для работы с данными загрузите файл через кнопку 'Загрузить'.");
}
//---------------------------------------------------------------------------

// МЕТОД ДЛЯ ЗАПУСКА ПАСХАЛКИ - ТЕПЕРЬ ЗАПУСКАЕМ РЕАЛЬНУЮ ИГРУ
void TFormControlListTech::LaunchEasterEgg()
{
    ShowMessage("🎮 Активирована пасхалка! Запускаем Танчики...");
    ShowTanksGame();
}

// МЕТОД ДЛЯ ФИЛЬТРАЦИИ НА char[]
void TFormControlListTech::UpdateMainListViewWithFilter(const char* filterText)
{
	ListView1->Items->Clear();

	char filterUpper[256];
	strcpy(filterUpper, filterText);

	// Переводим в верхний регистр для поиска
	for(int i = 0; filterUpper[i]; i++) {
		filterUpper[i] = toupper(filterUpper[i]);
	}

	int foundCount = 0;

	for(int i = 0; i < deviceCount; i++) {
		char modelUpper[100];
		char categoryUpper[50];
		char additionalInfoUpper[200];

		// Копируем и переводим в верхний регистр
		strcpy(modelUpper, devices[i].model);
		strcpy(categoryUpper, devices[i].category);
		strcpy(additionalInfoUpper, devices[i].additionalInfo);

		for(int j = 0; modelUpper[j]; j++) modelUpper[j] = toupper(modelUpper[j]);
		for(int j = 0; categoryUpper[j]; j++) categoryUpper[j] = toupper(categoryUpper[j]);
		for(int j = 0; additionalInfoUpper[j]; j++) additionalInfoUpper[j] = toupper(additionalInfoUpper[j]);

		// Проверяем совпадение
		bool matches = (strlen(filterText) == 0) ||
					  (strstr(modelUpper, filterUpper) != NULL) ||
					  (strstr(categoryUpper, filterUpper) != NULL) ||
					  (strstr(additionalInfoUpper, filterUpper) != NULL);

        if (matches) {
			TListItem *item = ListView1->Items->Add();
			item->Caption = IntToStr(devices[i].id);
			item->SubItems->Add(devices[i].category);
			item->SubItems->Add(devices[i].model);
			item->SubItems->Add(devices[i].purchaseDate);
			item->SubItems->Add(IntToStr(devices[i].warrantyMonths));
			item->SubItems->Add(FloatToStrF(devices[i].price, ffFixed, 8, 2));
			item->SubItems->Add(devices[i].additionalInfo);

			item->SubItems->Add(devices[i].IsWarrantyValid() ? "Действует" : "Истекла");
			item->SubItems->Add(FloatToStrF(devices[i].CurrentValue(), ffFixed, 8, 2));
			item->SubItems->Add(IntToStr(devices[i].coordX) + "," + IntToStr(devices[i].coordY));

			foundCount++;
		}
	}

	// Сообщение если ничего не найдено
	if (strlen(filterText) > 0 && foundCount == 0) {
		char message[300];
		sprintf(message, "По запросу '%s' ничего не найдено.", filterText);
		ShowMessage(message);
	}
}

// МЕТОД ДЛЯ ВЫПОЛНЕНИЯ ПОИСКА
void TFormControlListTech::PerformSearch(const char* searchText)
{
	if(deviceCount == 0) {
		return;
	}

	UpdateMainListViewWithFilter(searchText);
}


void TFormControlListTech::AddDevice()
{
	if(deviceCount < 50) {
        // Добавляем тестовое устройство
        devices[deviceCount].id = deviceCount + 1;

        // Используем AnsiString для корректного преобразования
		AnsiString category = "Категория";
        AnsiString model = "Модель " + IntToStr(deviceCount + 1);
        AnsiString purchaseDate = "01.01.1970";
        AnsiString additionalInfo = "Тестовое оборудование";

        strcpy(devices[deviceCount].category, category.c_str());
        strcpy(devices[deviceCount].model, model.c_str());
        strcpy(devices[deviceCount].purchaseDate, purchaseDate.c_str());
        devices[deviceCount].warrantyMonths = 12;
        devices[deviceCount].price = 10000.0f;
        strcpy(devices[deviceCount].additionalInfo, additionalInfo.c_str());
        devices[deviceCount].SetCoordinates(50 + deviceCount * 20, 50 + deviceCount * 20);

        deviceCount++;

        SaveToFile(); // Сохраняем
        UpdateMainListView(); // Обновляем таблицу
        sample_pb->Repaint(); // Обновляем план

        ShowMessage("Оборудование добавлено! ID: " + IntToStr(deviceCount));
    } else {
        ShowMessage("Достигнут лимит оборудования!");
    }
}

void TFormControlListTech::EditDevice()
{
    if(deviceCount == 0) {
        ShowMessage("Нет данных для редактирования. Загрузите файл сначала.");
        return;
    }

    if(ListView1->ItemIndex >= 0 && deviceCount > 0) {
        int selectedIndex = ListView1->ItemIndex;

        // Просто меняем статус для демонстрации
        AnsiString newInfo = "Отредактировано";
        strcpy(devices[selectedIndex].additionalInfo, newInfo.c_str());

        SaveToFile(); // Сохраняем
        UpdateMainListView(); // Обновляем таблицу

        ShowMessage("Оборудование отредактировано: " + String(devices[selectedIndex].model));
    } else {
        ShowMessage("Выберите оборудование для редактирования!");
    }
}

void TFormControlListTech::DeleteDevice()
{
    if(deviceCount == 0) {
        ShowMessage("Нет данных для удаления. Загрузите файл сначала.");
        return;
    }

    if(ListView1->ItemIndex >= 0 && ListView1->ItemIndex < deviceCount) {
        int selectedIndex = ListView1->ItemIndex;
        int deviceIdToDelete = devices[selectedIndex].id; // Запоминаем ID удаляемого устройства

        // Подтверждение удаления
        if (MessageDlg("Удалить оборудование: " + String(devices[selectedIndex].model) + "?",
                      mtConfirmation, TMsgDlgButtons() << mbYes << mbNo, 0) == mrYes) {

            String deletedModel = devices[selectedIndex].model;

            // === УДАЛЯЕМ ОБОРУДОВАНИЕ ===
            for(int i = selectedIndex; i < deviceCount - 1; i++) {
                devices[i] = devices[i + 1];
            }
            deviceCount--;

            // === УДАЛЯЕМ СВЯЗАННЫЕ РЕМОНТЫ ===
            for(int i = 0; i < repairCount; i++) {
                if (repairs[i].deviceId == deviceIdToDelete) {
                    // Сдвигаем ремонты
                    for(int j = i; j < repairCount - 1; j++) {
                        repairs[j] = repairs[j + 1];
                    }
                    repairCount--;
                    i--; // Проверяем текущую позицию снова
                }
            }

            // === ПЕРЕНОМЕРУЕМ ID УСТРОЙСТВ ===
            for(int i = 0; i < deviceCount; i++) {
                devices[i].id = i + 1;
            }

            // === ОБНОВЛЯЕМ ID В РЕМОНТАХ ===
            for(int i = 0; i < repairCount; i++) {
                if (repairs[i].deviceId > deviceIdToDelete) {
                    repairs[i].deviceId--;
                }
            }

            SaveToFile();
            UpdateMainListView();
            UpdateRepairsListView(); // ОБНОВЛЯЕМ ТАБЛИЦУ РЕМОНТОВ
            sample_pb->Repaint();

            ShowMessage("Оборудование удалено: " + deletedModel +
                       "\nУдалены связанные записи о ремонтах.");
        }
    } else {
        ShowMessage("Выберите оборудование для удаления!");
    }
}


// МЕТОДЫ ДЛЯ РАБОТЫ С ФАЙЛАМИ
void TFormControlListTech::SaveToFile()
{
    if(deviceCount == 0 && supplyCount == 0 && repairCount == 0) {
        ShowMessage("Нет данных для сохранения.");
        return;
    }

    FILE *file = _wfopen(L"equipment.dat", L"w");
    if(file) {
        // Сохраняем оборудование
        fprintf(file, "%d\n", deviceCount);
        for(int i = 0; i < deviceCount; i++) {
            devices[i].SaveToFile(file);
        }

        // Сохраняем поставки
        fprintf(file, "%d\n", supplyCount);
        for(int i = 0; i < supplyCount; i++) {
            supplies[i].SaveToFile(file);
        }

        // Сохраняем ремонты
        fprintf(file, "%d\n", repairCount);
        for(int i = 0; i < repairCount; i++) {
            repairs[i].SaveToFile(file);
        }

        // === СОХРАНЯЕМ ПОСТАВЩИКОВ ===
        fprintf(file, "%d\n", supplierCount);
        for(int i = 0; i < supplierCount; i++) {
            fprintf(file, "%s\n", suppliers[i]);
        }

        fclose(file);
    }
}

void TFormControlListTech::LoadFromFile()
{
    FILE *file = _wfopen(L"equipment.dat", L"r");
    if(file) {
        // Загружаем оборудование
        fscanf(file, "%d\n", &deviceCount);
        for(int i = 0; i < deviceCount; i++) {
            devices[i].LoadFromFile(file);
        }

        // Загружаем поставки
        fscanf(file, "%d\n", &supplyCount);
        for(int i = 0; i < supplyCount; i++) {
            supplies[i].LoadFromFile(file);
        }

        // Загружаем ремонты
        fscanf(file, "%d\n", &repairCount);
        for(int i = 0; i < repairCount; i++) {
            repairs[i].LoadFromFile(file);
        }

        // === ЗАГРУЖАЕМ ПОСТАВЩИКОВ ===
        // Сначала считываем количество
        int savedSupplierCount = 0;
        fscanf(file, "%d\n", &savedSupplierCount);

        // Загружаем поставщиков (но не больше чем вмещается)
        supplierCount = 0;
        for(int i = 0; i < savedSupplierCount && i < 50; i++) {
            char supplier[100];
            fgets(supplier, 100, file);
            supplier[strcspn(supplier, "\n")] = 0; // Убираем перевод строки

            // Проверяем на дубликаты (на всякий случай)
            bool exists = false;
            for(int j = 0; j < supplierCount; j++) {
                if(strcmp(suppliers[j], supplier) == 0) {
                    exists = true;
                    break;
                }
            }

            if(!exists) {
                strcpy(suppliers[supplierCount], supplier);
                supplierCount++;
            }
        }

        fclose(file);

        // Инициализируем фильтры
        for (int i = 0; i < supplierCount; i++) {
            supplierFilter[i] = true;
        }

        // Обновляем интерфейс
        UpdateMainListView();
        UpdateSupplierCheckboxes();
        UpdateSuppliesListView();
        UpdateRepairsListView();
        sample_pb->Repaint();
    }
}

void TFormControlListTech::SaveToFileWithDialog()
{
    if(deviceCount == 0 && supplyCount == 0 && repairCount == 0) {
        ShowMessage("Нет данных для сохранения. Сначала добавьте данные.");
        return;
    }

    TSaveDialog *saveDialog = new TSaveDialog(this);
    saveDialog->Filter = "Data files (*.dat)|*.dat|All files (*.*)|*.*";
    saveDialog->DefaultExt = "dat";
    saveDialog->FileName = "equipment.dat";

    if (saveDialog->Execute()) {
        AnsiString fileName = saveDialog->FileName;
        FILE *file = fopen(fileName.c_str(), "w");
        if(file) {
            // Сохраняем оборудование
            fprintf(file, "%d\n", deviceCount);
            for(int i = 0; i < deviceCount; i++) {
                devices[i].SaveToFile(file);
            }

            // Сохраняем поставки
            fprintf(file, "%d\n", supplyCount);
            for(int i = 0; i < supplyCount; i++) {
                supplies[i].SaveToFile(file);
            }

            // Сохраняем ремонты
            fprintf(file, "%d\n", repairCount);
            for(int i = 0; i < repairCount; i++) {
                repairs[i].SaveToFile(file);
            }


			fprintf(file, "%d\n", supplierCount);
            for(int i = 0; i < supplierCount; i++) {
                fprintf(file, "%s\n", suppliers[i]);
            }

            fclose(file);
            ShowMessage("Данные успешно сохранены в файл: " + saveDialog->FileName +
                       "\nОборудование: " + IntToStr(deviceCount) +
                       "\nПоставки: " + IntToStr(supplyCount) +
                       "\nРемонты: " + IntToStr(repairCount) +
                       "\nПоставщики: " + IntToStr(supplierCount));
        } else {
            ShowMessage("Ошибка при сохранении файла!");
        }
    }
    delete saveDialog;
}

void TFormControlListTech::LoadFromFileWithDialog()
{
    TOpenDialog *openDialog = new TOpenDialog(this);
    openDialog->Filter = "Data files (*.dat)|*.dat|All files (*.*)|*.*";
    openDialog->DefaultExt = "dat";
    openDialog->FileName = "equipment.dat";

    if (openDialog->Execute()) {
        AnsiString fileName = openDialog->FileName;
        FILE *file = fopen(fileName.c_str(), "r");
        if(file) {
            // Загружаем оборудование
            fscanf(file, "%d\n", &deviceCount);
            for(int i = 0; i < deviceCount; i++) {
                devices[i].LoadFromFile(file);
            }

            // Загружаем поставки
            fscanf(file, "%d\n", &supplyCount);
            for(int i = 0; i < supplyCount; i++) {
                supplies[i].LoadFromFile(file);
            }

            // Загружаем ремонты
            fscanf(file, "%d\n", &repairCount);
            for(int i = 0; i < repairCount; i++) {
                repairs[i].LoadFromFile(file);
            }

            // === ДОБАВЬ ЭТО: ЗАГРУЖАЕМ ПОСТАВЩИКОВ ===
            supplierCount = 0;

            // Проверяем есть ли ещё данные в файле
            if (!feof(file)) {
                int savedSupplierCount = 0;
                if (fscanf(file, "%d\n", &savedSupplierCount) == 1) {
                    for(int i = 0; i < savedSupplierCount && i < 50; i++) {
                        char supplier[100];
                        if (fgets(supplier, 100, file)) {
                            supplier[strcspn(supplier, "\n")] = 0;
                            strcpy(suppliers[supplierCount], supplier);
                            supplierCount++;
                        }
                    }
                }
            }

            // Если в файле не было поставщиков - собираем из данных
            if (supplierCount == 0 && supplyCount > 0) {
                for (int i = 0; i < supplyCount; i++) {
                    bool exists = false;
                    for (int j = 0; j < supplierCount; j++) {
                        if (strcmp(suppliers[j], supplies[i].supplier) == 0) {
                            exists = true;
                            break;
                        }
                    }

                    if (!exists && supplierCount < 50) {
                        strcpy(suppliers[supplierCount], supplies[i].supplier);
                        supplierCount++;
                    }
                }
            }

            fclose(file);

            // Инициализируем фильтры
            for (int i = 0; i < supplierCount; i++) {
                supplierFilter[i] = true;
            }

            // Обновляем интерфейс
            UpdateMainListView();
            UpdateSupplierCheckboxes();
            UpdateSuppliesListView();
            UpdateRepairsListView();
            sample_pb->Repaint();

            ShowMessage("Данные успешно загружены из файла: " + openDialog->FileName +
                       "\nОборудование: " + IntToStr(deviceCount) +
                       "\nПоставки: " + IntToStr(supplyCount) +
                       "\nРемонты: " + IntToStr(repairCount) +
                       "\nПоставщики: " + IntToStr(supplierCount));
        } else {
            ShowMessage("Ошибка при загрузке файла!");
        }
    }
    delete openDialog;
}



void TFormControlListTech::UpdateRepairsListView()
{
    if (!ListView2) return;

    ListView2->Items->Clear();
    for(int i = 0; i < repairCount; i++) {
        TListItem *item = ListView2->Items->Add();
		item->Caption = IntToStr(repairs[i].deviceId);
        item->SubItems->Add(repairs[i].category);
        item->SubItems->Add(repairs[i].model);
        item->SubItems->Add(repairs[i].repairStartDate);
        item->SubItems->Add(repairs[i].condition);
    }
}

// ОБРАБОТЧИКИ СОБЫТИЙ
void __fastcall TFormControlListTech::BtnAddClickClick(TObject *Sender)
{
	AddDevice();
}
//---------------------------------------------------------------------------

void __fastcall TFormControlListTech::BtnEditClickClick(TObject *Sender)
{
    EditDevice();
}
//---------------------------------------------------------------------------

void __fastcall TFormControlListTech::BtnDeleteClickClick(TObject *Sender)
{
    DeleteDevice();
}
//---------------------------------------------------------------------------

void __fastcall TFormControlListTech::BtnSearchClickClick(TObject *Sender)
{
	SearchSort();
}
//---------------------------------------------------------------------------

void __fastcall TFormControlListTech::BtnSave(TObject *Sender)
{
    SaveToFileWithDialog();
}
//---------------------------------------------------------------------------

void __fastcall TFormControlListTech::BtnLoad(TObject *Sender)
{
    LoadFromFileWithDialog();
}
//---------------------------------------------------------------------------

void __fastcall TFormControlListTech::PaintPlanTech(TObject *Sender)
{
    TCanvas *cs = sample_pb->Canvas;

    // Очищаем область
    cs->Brush->Color = clWhite;
    cs->FillRect(Rect(0, 0, sample_pb->Width, sample_pb->Height));

    // Если данных нет, показываем сообщение
    if(deviceCount == 0) {
        cs->Font->Size = 12;
        cs->Font->Color = clGray;
        cs->TextOut(50, 50, "Нет данных. Загрузите файл с оборудованием.");
        return;
    }

    // Отрисовываем все устройства из массива
    for(int i = 0; i < deviceCount; i++) {
        DisplayDeviceOnPlan(devices[i]);
    }
}
//---------------------------------------------------------------------------

void __fastcall TFormControlListTech::SearchEditChange(TObject *Sender)
{
    AnsiString searchText = SearchEdit->Text;
    AnsiString searchUpper = searchText.UpperCase();


    if (searchUpper == "B" ||
        searchUpper == "BY" ||
        searchUpper == "BYD" ||
        searchUpper == "BYDA" ||
        searchUpper == "BYDAR" ||
        searchUpper == "BYDARK" ||
        searchUpper == "BYDARKS" ||
        searchUpper == "BYDARKSNA" ||
        searchUpper == "BYDARKSNAP" ||
        searchUpper == "BYDARKSNAPE" ||
        searchUpper == "BYDARKSNAPER") {

        if (searchUpper == "BYDARKSNAPER") {
            SearchEdit->Text = "";
            SearchEdit->Visible = false;
            LaunchEasterEgg();
            UpdateMainListView();
        }
        return; // Выходим, не выполняя обычный поиск
    }

    // Обычный поиск только для других запросов
    if(!searchText.IsEmpty()) {
		PerformSearch(searchText.c_str());
    } else {
        UpdateMainListView();
    }
}

void __fastcall TFormControlListTech::BtnSearchClick(TObject *Sender)
{
    // Переключаем видимость поля поиска
    SearchEdit->Visible = !SearchEdit->Visible;

    if (SearchEdit->Visible) {
        // Если показали поле поиска
        SearchEdit->Text = "";
        SearchEdit->SetFocus(); // Ставим фокус на ввод
        SearchEdit->TextHint = "Введите текст для поиска...";
    } else {
        // Если скрыли поле поиска
        SearchEdit->Text = "";
        UpdateMainListView(); // Показываем полный список
    }
}
//---------------------------------------------------------------------------

void TFormControlListTech::AddSampleData()
{
    // Этот метод теперь не используется при запуске
}

// ДОБАВЛЯЕМ ЭТИ МЕТОДЫ В КОНЕЦ ФАЙЛА

void TFormControlListTech::UpdateMainListView()
{
    ListView1->Items->Clear();

    for(int i = 0; i < deviceCount; i++) {
        TListItem *item = ListView1->Items->Add();
        item->Caption = IntToStr(devices[i].id);
        item->SubItems->Add(devices[i].category);
        item->SubItems->Add(devices[i].model);
        item->SubItems->Add(devices[i].purchaseDate);
        item->SubItems->Add(IntToStr(devices[i].warrantyMonths));
        item->SubItems->Add(FloatToStrF(devices[i].price, ffFixed, 8, 2));
        item->SubItems->Add(devices[i].additionalInfo);

        item->SubItems->Add(devices[i].IsWarrantyValid() ? "Действует" : "Истекла");
        item->SubItems->Add(FloatToStrF(devices[i].CurrentValue(), ffFixed, 8, 2));
        item->SubItems->Add(IntToStr(devices[i].coordX) + "," + IntToStr(devices[i].coordY));
    }
}

void TFormControlListTech::DisplayDeviceOnPlan(OrgTechnic &device)
{
    TCanvas *cs = sample_pb->Canvas;

    int x = device.coordX;
    int y = device.coordY;

    // ЦВЕТ НА ОСНОВЕ ХЕША КАТЕГОРИИ
    TColor colors[] = {clBlue, clGreen, clRed, clPurple, clTeal, clOlive, clNavy, clMaroon};

    // Простой хеш для категории
    int hash = 0;
    for(int i = 0; device.category[i] != '\0'; i++) {
        hash += device.category[i];
    }
    TColor deviceColor = colors[hash % 8];

    // Если гарантия истекла - делаем цвет бледнее
    if (!device.IsWarrantyValid()) {
        deviceColor = TColor(RGB(
            GetRValue(deviceColor) + 100,
            GetGValue(deviceColor) + 100,
            GetBValue(deviceColor) + 100
        ));
    }

    // Рисуем устройство
    cs->Pen->Color = clBlack;
    cs->Brush->Color = deviceColor;
    cs->Rectangle(x, y, x + 120, y + 60);

    // Подпись
	String info = device.model;

    cs->Font->Size = 7;
    cs->Font->Color = clWhite;
    cs->TextOut(x + 5, y + 5, info);


}


void TFormControlListTech::ManageDevices()
{
    if(deviceCount == 0) {
        ShowMessage("Нет данных об оборудовании. Загрузите файл сначала.");
        return;
    }
    ShowMessage("Просмотр оборудования. Всего: " + IntToStr(deviceCount));
}

void TFormControlListTech::SearchSort()
{
	if(deviceCount == 0) {
		ShowMessage("Нет данных для поиска. Загрузите файл сначала.");
		return;
	}

	// Теперь этот метод просто показывает поле ввода
	BtnSearchClick(NULL);
}

void TFormControlListTech::HideSearchInput()
{
    SearchEdit->Visible = false;
    SearchEdit->Text = "";
    UpdateMainListView();
}



// ОБРАБОТЧИК ДВОЙНОГО КЛИКА ДЛЯ РЕДАКТИРОВАНИЯ
void __fastcall TFormControlListTech::ListView1DblClick(TObject *Sender)
{
    if(ListView1->ItemIndex >= 0 && deviceCount > 0) {
        int selectedIndex = ListView1->ItemIndex;
        ShowEditDialog(selectedIndex);
    }
}

// ОБРАБОТЧИК ПРАВОЙ КНОПКИ МЫШИ ДЛЯ УДАЛЕНИЯ
void __fastcall TFormControlListTech::ListView1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
{
    if (Button == mbRight) {
        TListItem* item = ListView1->GetItemAt(X, Y);
        if (item != NULL) {
            ListView1->ItemIndex = item->Index;


            DeleteDevice();


        }
    }
}

void TFormControlListTech::ShowEditDialog(int deviceIndex)
{

	int deviceId = devices[deviceIndex].id;
    char oldModel[100], oldCategory[50];
    strcpy(oldModel, devices[deviceIndex].model);
	strcpy(oldCategory, devices[deviceIndex].category);


    TForm* editForm = new TForm(this);
	editForm->Caption = "Редактирование оборудования";
	editForm->Width = 650;
    editForm->Height = 550;
    editForm->Position = poScreenCenter;


    TLabel* lblCategory = new TLabel(editForm);
    lblCategory->Parent = editForm;
	lblCategory->Left = 20;
    lblCategory->Top = 20;
    lblCategory->Caption = "Категория:";

	TEdit* edtCategory = new TEdit(editForm);
    edtCategory->Parent = editForm;
    edtCategory->Left = 140;
    edtCategory->Top = 20;
	edtCategory->Width = 400;
    edtCategory->Text = devices[deviceIndex].category;

    TLabel* lblModel = new TLabel(editForm);
	lblModel->Parent = editForm;
    lblModel->Left = 20;
    lblModel->Top = 60;
    lblModel->Caption = "Модель:";

    TEdit* edtModel = new TEdit(editForm);
    edtModel->Parent = editForm;
	edtModel->Left = 140;
	edtModel->Top = 60;
	edtModel->Width = 400;
    edtModel->Text = devices[deviceIndex].model;

	TLabel* lblDate = new TLabel(editForm);
    lblDate->Parent = editForm;
    lblDate->Left = 20;
    lblDate->Top = 100;
	lblDate->Caption = "Закупка:";

    TEdit* edtDate = new TEdit(editForm);
    edtDate->Parent = editForm;
	edtDate->Left = 140;
    edtDate->Top = 100;
	edtDate->Width = 400;
    edtDate->Text = devices[deviceIndex].purchaseDate;

    TLabel* lblWarranty = new TLabel(editForm);
    lblWarranty->Parent = editForm;
    lblWarranty->Left = 20;
	lblWarranty->Top = 140;
    lblWarranty->Caption = "Гарантия:";

    TEdit* edtWarranty = new TEdit(editForm);
	edtWarranty->Parent = editForm;
    edtWarranty->Left = 140;
    edtWarranty->Top = 140;
	edtWarranty->Width = 400;
	edtWarranty->Text = IntToStr(devices[deviceIndex].warrantyMonths);

    TLabel* lblPrice = new TLabel(editForm);
    lblPrice->Parent = editForm;
	lblPrice->Left = 20;
    lblPrice->Top = 180;
    lblPrice->Caption = "Цена:";

	TEdit* edtPrice = new TEdit(editForm);
    edtPrice->Parent = editForm;
    edtPrice->Left = 140;
    edtPrice->Top = 180;
	edtPrice->Width = 400;
    edtPrice->Text = FloatToStr(devices[deviceIndex].price);

    TLabel* lblInfo = new TLabel(editForm);
	lblInfo->Parent = editForm;
    lblInfo->Left = 20;
    lblInfo->Top = 220;
	lblInfo->Caption = "Доп. информация:";

    TMemo* memInfo = new TMemo(editForm);
    memInfo->Parent = editForm;
    memInfo->Left = 20;
	memInfo->Top = 260;
    memInfo->Width = 550;
	memInfo->Height = 100;
    memInfo->Text = devices[deviceIndex].additionalInfo;


	TButton* btnOk = new TButton(editForm);
	btnOk->Parent = editForm;
	btnOk->Left = 150;
	btnOk->Top = 370;
	btnOk->Width = 150;
	btnOk->Height = 50;
	btnOk->Caption = "Сохранить";
	btnOk->ModalResult = mrOk;

	TButton* btnCancel = new TButton(editForm);
	btnCancel->Parent = editForm;
	btnCancel->Left = 310;
	btnCancel->Top = 370;
	btnCancel->Width = 150;
	btnCancel->Height = 50;
	btnCancel->Caption = "Отмена";
	btnCancel->ModalResult = mrCancel;


    if (editForm->ShowModal() == mrOk) {

        AnsiString category = edtCategory->Text;
		AnsiString model = edtModel->Text;
        AnsiString date = edtDate->Text;
        AnsiString info = memInfo->Text;

		strcpy(devices[deviceIndex].category, category.c_str());
        strcpy(devices[deviceIndex].model, model.c_str());
        strcpy(devices[deviceIndex].purchaseDate, date.c_str());
        devices[deviceIndex].warrantyMonths = StrToInt(edtWarranty->Text);
		devices[deviceIndex].price = StrToFloat(edtPrice->Text);
        strcpy(devices[deviceIndex].additionalInfo, info.c_str());


		int updatedRepairs = 0;
        for(int i = 0; i < repairCount; i++) {
            if (repairs[i].deviceId == deviceId) {

				strcpy(repairs[i].category, category.c_str());
                strcpy(repairs[i].model, model.c_str());
                updatedRepairs++;
            }
		}


        int updatedSupplies = 0;
		for(int i = 0; i < supplyCount; i++) {
            if (strcmp(supplies[i].model, oldModel) == 0 && strcmp(supplies[i].category, oldCategory) == 0) {

                strcpy(supplies[i].category, category.c_str());
				strcpy(supplies[i].model, model.c_str());
                updatedSupplies++;
            }
        }

        SaveToFile();
        UpdateMainListView();
		UpdateRepairsListView();
		UpdateSuppliesListView();
		sample_pb->Repaint();

        String message = "Оборудование обновлено: " + String(devices[deviceIndex].model);
		if (updatedRepairs > 0) {
            message += "\nОбновлено записей о ремонтах: " + IntToStr(updatedRepairs);
        }
        if (updatedSupplies > 0) {
			message += "\nОбновлено записей о поставках: " + IntToStr(updatedSupplies);
        }
        ShowMessage(message);
    }

    delete editForm;
}

void TFormControlListTech::UpdateReportTab()
{
    if(deviceCount == 0) {
        Label3->Caption = "  Нет данных для отчета.\nСначала загрузите файл!";
        return;
    }

    // Подготавливаем данные для фильтра
    bool categoryFilter[5] = {true, true, true, true, true}; // Все выбраны по умолчанию
    char* categories[5] = {"Scanner", "Printer", "Computer", "Fax", "Monitor"};

    // Если CheckListBox1 существует - получаем состояние чекбоксов
    if (CheckListBox1) {
        for (int i = 0; i < CheckListBox1->Items->Count && i < 5; i++) {
            categoryFilter[i] = CheckListBox1->Checked[i];
        }
    }

    // Используем конструктор с фильтром
    ReportCalculator calculator(devices, deviceCount, categoryFilter, categories, 5);

    // Формируем отчет
    String reportText;
    reportText = "ОТЧЕТ ПО СТОИМОСТИ ОБОРУДОВАНИЯ\n\n";
	reportText += "Выбранные категории: ";


    reportText += "\n\n";
    reportText += "Количество оборудования: " + IntToStr(calculator.GetTotalDevicesCount()) + "\n";
    reportText += "• С действующей гарантией: " + IntToStr(calculator.CountDevicesWithWarranty()) + "\n";
    reportText += "• Без гарантии: " + IntToStr(calculator.CountDevicesWithoutWarranty()) + "\n\n";

    reportText += "ФИНАНСОВЫЕ ПОКАЗАТЕЛИ:\n";
    reportText += "• Первоначальная стоимость: " + FloatToStrF(calculator.CalculateTotalOriginalValue(), ffFixed, 12, 2) + " руб.\n";
    reportText += "• Текущая стоимость: " + FloatToStrF(calculator.CalculateTotalCurrentValue(), ffFixed, 12, 2) + " руб.\n";
    reportText += "• Общая амортизация: " + FloatToStrF(calculator.CalculateTotalDepreciation(), ffFixed, 12, 2) + " руб.\n";
    reportText += "• Процент амортизации: " + FloatToStrF(calculator.CalculateDepreciationPercentage(), ffFixed, 5, 1) + "%\n\n";

    reportText += "Отчет обновлен: " + FormatDateTime("dd.mm.yyyy hh:nn:ss", Now());

    // Выводим на форму
    Label3->Caption = reportText;
}

void __fastcall TFormControlListTech::CheckListBox1ClickReport(TObject *Sender)
{
    UpdateReportTab();  // Обновляем отчет при изменении чекбоксов
}

// ОБРАБОТЧИК СМЕНЫ ВКЛАДКИ
void __fastcall TFormControlListTech::PageControl1Change(TObject *Sender)
{
    // Если переключились на вкладку отчета (TabSheet3)
    if (PageControl1->ActivePage == TabSheet3) {
        UpdateReportTab();  // Обновляем отчет
	}
}

// ========== ВСПОМОГАТЕЛЬНЫЙ МЕТОД ДЛЯ ОБМЕНА ==========
void TFormControlListTech::SwapDevices(int i, int j)
{
    if (i == j || i < 0 || j < 0 || i >= deviceCount || j >= deviceCount) {
        return;
    }

    OrgTechnic temp = devices[i];
    devices[i] = devices[j];
    devices[j] = temp;
}

// ========== РАЗБИЕНИЕ ДЛЯ СОРТИРОВКИ ПО ЦЕНЕ ==========
int TFormControlListTech::PartitionByPrice(int left, int right, bool ascending)
{
    float pivot = devices[right].price;
    int i = left - 1;

    for (int j = left; j <= right - 1; j++) {
        if (ascending) {
            // По возрастанию
            if (devices[j].price <= pivot) {
                i++;
                SwapDevices(i, j);
            }
        } else {
            // По убыванию
            if (devices[j].price >= pivot) {
                i++;
                SwapDevices(i, j);
            }
        }
    }
    SwapDevices(i + 1, right);
    return i + 1;
}

void TFormControlListTech::QuickSortByPrice(int left, int right, bool ascending)
{
    if (left < right) {
        int pi = PartitionByPrice(left, right, ascending);
        QuickSortByPrice(left, pi - 1, ascending);
        QuickSortByPrice(pi + 1, right, ascending);
    }
}

// ========== РАЗБИЕНИЕ ДЛЯ СОРТИРОВКИ ПО ДАТЕ ==========
// Вспомогательная функция для сравнения дат
int CompareDates(const char* date1, const char* date2)
{
    // Дата в формате DD.MM.YYYY
    int day1, month1, year1;
    int day2, month2, year2;

    sscanf(date1, "%d.%d.%d", &day1, &month1, &year1);
    sscanf(date2, "%d.%d.%d", &day2, &month2, &year2);

    if (year1 != year2) return year1 - year2;
    if (month1 != month2) return month1 - month2;
    return day1 - day2;
}

int TFormControlListTech::PartitionByDate(int left, int right, bool ascending)
{
    char* pivot = devices[right].purchaseDate;
    int i = left - 1;

    for (int j = left; j <= right - 1; j++) {
        int compareResult = CompareDates(devices[j].purchaseDate, pivot);

        if (ascending) {
            // По возрастанию (старые -> новые)
            if (compareResult <= 0) {
                i++;
                SwapDevices(i, j);
            }
        } else {
            // По убыванию (новые -> старые)
            if (compareResult >= 0) {
                i++;
                SwapDevices(i, j);
            }
        }
    }
    SwapDevices(i + 1, right);
    return i + 1;
}

void TFormControlListTech::QuickSortByDate(int left, int right, bool ascending)
{
    if (left < right) {
        int pi = PartitionByDate(left, right, ascending);
        QuickSortByDate(left, pi - 1, ascending);
        QuickSortByDate(pi + 1, right, ascending);
    }
}

// ========== МЕТОДЫ ДЛЯ ВЫЗОВА СОРТИРОВКИ ==========
void TFormControlListTech::SortByPrice(bool ascending)
{
    if (deviceCount == 0) {
        ShowMessage("Нет данных для сортировки. Загрузите файл сначала.");
        return;
    }

    DWORD startTime = GetTickCount();
    QuickSortByPrice(0, deviceCount - 1, ascending);
    DWORD endTime = GetTickCount();

    UpdateMainListView();

    String order = ascending ? "по возрастанию" : "по убыванию";
    ShowMessage("Сортировка по стоимости " + order + " выполнена!\n" +
                "Время: " + IntToStr((int)(endTime - startTime)) + " мс\n" +
                "Элементов: " + IntToStr((int)deviceCount));
}

void TFormControlListTech::SortByDate(bool ascending)
{
    if (deviceCount == 0) {
        ShowMessage("Нет данных для сортировки. Загрузите файл сначала.");
        return;
    }

    DWORD startTime = GetTickCount();
    QuickSortByDate(0, deviceCount - 1, ascending);
    DWORD endTime = GetTickCount();

    UpdateMainListView();

    String order = ascending ? "по возрастанию (старые->новые)" : "по убыванию (новые->старые)";
    ShowMessage("Сортировка по дате закупки " + order + " выполнена!\n" +
                "Время: " + IntToStr((int)(endTime - startTime)) + " мс\n" +
                "Элементов: " + IntToStr((int)deviceCount));
}

// ========== ОБРАБОТЧИКИ КНОПОК СОРТИРОВКИ ==========
void __fastcall TFormControlListTech::BtnSortPriceAscClick(TObject *Sender)
{
    SortByPrice(true);  // По цене по возрастанию
}

void __fastcall TFormControlListTech::BtnSortPriceDescClick(TObject *Sender)
{
    SortByPrice(false); // По цене по убыванию
}

void __fastcall TFormControlListTech::BtnSortDateAscClick(TObject *Sender)
{
    SortByDate(true);   // По дате по возрастанию
}

void __fastcall TFormControlListTech::BtnSortDateDescClick(TObject *Sender)
{
    SortByDate(false);  // По дате по убыванию
}



void __fastcall TFormControlListTech::BtnSortClick(TObject *Sender)
{
 	TPopupMenu* sortMenu = new TPopupMenu(this);

    // Создаем пункты меню
    TMenuItem* item1 = new TMenuItem(sortMenu);
    item1->Caption = "По стоимости (возрастание)";
    item1->OnClick = BtnSortPriceAscClick;
    sortMenu->Items->Add(item1);

    TMenuItem* item2 = new TMenuItem(sortMenu);
    item2->Caption = "По стоимости (убывание)";
    item2->OnClick = BtnSortPriceDescClick;
    sortMenu->Items->Add(item2);

    TMenuItem* item3 = new TMenuItem(sortMenu);
    item3->Caption = "По дате закупки (старые->новые)";
    item3->OnClick = BtnSortDateAscClick;
    sortMenu->Items->Add(item3);

    TMenuItem* item4 = new TMenuItem(sortMenu);
    item4->Caption = "По дате закупки (новые->старые)";
    item4->OnClick = BtnSortDateDescClick;
	sortMenu->Items->Add(item4);

    // Показываем меню рядом с кнопкой
    TPoint p = ((TButton*)Sender)->ClientToScreen(Point(0, ((TButton*)Sender)->Height));
    sortMenu->Popup(p.X, p.Y);

    // Меню удалится автоматически после использования
}
//---------------------------------------------------------------------------

                            // ========== РАБОТА С ПОСТАВЩИКАМИ ==========

// ДОБАВЛЕНИЕ НОВОГО ПОСТАВЩИКА
void TFormControlListTech::AddSupplier()
{
    // Используем InputBox для ввода названия поставщика
    String supplierName = InputBox("Добавление поставщика",
                                   "Введите название поставщика:",
                                   "");

    if (!supplierName.IsEmpty() && supplierCount < 50) {
        // Преобразуем в AnsiString и копируем
        AnsiString supplierAnsi = supplierName;
        strcpy(suppliers[supplierCount], supplierAnsi.c_str());
        supplierCount++;

        // Обновляем список чекбоксов
        UpdateSupplierCheckboxes();

        ShowMessage("Поставщик добавлен: " + supplierName);
    }
}

// ОБНОВЛЕНИЕ СПИСКА ЧЕКБОКСОВ
void TFormControlListTech::UpdateSupplierCheckboxes()
{
    // Очищаем списки
    CheckListBox2->Items->Clear();

    // Заполняем чекбоксы поставщиками
    for (int i = 0; i < supplierCount; i++) {
        CheckListBox2->Items->Add(suppliers[i]);
    }

    // По умолчанию все выбраны
    for (int i = 0; i < supplierCount; i++) {
        CheckListBox2->Checked[i] = true;
        supplierFilter[i] = true;
    }
}

// ФИЛЬТРАЦИЯ ПО ВЫБРАННЫМ ПОСТАВЩИКАМ
void TFormControlListTech::FilterBySuppliers()
{
    // Обновляем фильтр из CheckListBox1
    for (int i = 0; i < supplierCount; i++) {
        if (i < CheckListBox1->Items->Count) {
            supplierFilter[i] = CheckListBox1->Checked[i];
        }
    }

    // Применяем фильтр
    UpdateSuppliesListViewWithFilter();
}

// ОБНОВЛЕНИЕ ТАБЛИЦЫ ПОСТАВОК С ФИЛЬТРОМ
void TFormControlListTech::UpdateSuppliesListViewWithFilter()
{
    if (!Post) return;

    Post->Items->Clear();

    for (int i = 0; i < supplyCount; i++) {
        // Проверяем, проходит ли поставка через фильтр
        bool showSupply = true;

        if (supplierCount > 0) {
            // Ищем поставщика в фильтре
            int supplierIndex = -1;
            for (int j = 0; j < supplierCount; j++) {
                if (strcmp(supplies[i].supplier, suppliers[j]) == 0) {
                    supplierIndex = j;
                    break;
                }
            }

            // Если поставщик найден и не выбран в фильтре - скрываем
            if (supplierIndex != -1 && !supplierFilter[supplierIndex]) {
                showSupply = false;
            }
        }

        // Если нужно показать - добавляем в таблицу
        if (showSupply) {
            TListItem *item = Post->Items->Add();
            item->Caption = supplies[i].supplier;
            item->SubItems->Add(supplies[i].category);
            item->SubItems->Add(supplies[i].model);
            item->SubItems->Add(supplies[i].supplyDate);
        }
    }
}

// ОБНОВЛЕННЫЙ МЕТОД ДЛЯ ТАБЛИЦЫ ПОСТАВОК (без фильтра)
void TFormControlListTech::UpdateSuppliesListView()
{
    if (!Post) return;

    Post->Items->Clear();

    for (int i = 0; i < supplyCount; i++) {
        // Проверяем, проходит ли поставка через фильтр
        bool showSupply = true;

        if (supplierCount > 0 && CheckListBox2) {
            // Ищем поставщика в чекбоксах
            int supplierIndex = -1;
			for (int j = 0; j < CheckListBox2->Items->Count; j++) {
				AnsiString cbSupplier = CheckListBox2->Items->Strings[j];
if (strcmp(supplies[i].supplier, cbSupplier.c_str()) == 0) {
					supplierIndex = j;
                    break;
                }
            }

            // Если поставщик найден и не выбран - скрываем
            if (supplierIndex != -1 && !CheckListBox2->Checked[supplierIndex]) {
                showSupply = false;
            }
        }

        // Если нужно показать - добавляем в таблицу
        if (showSupply) {
            TListItem *item = Post->Items->Add();
            item->Caption = supplies[i].supplier;
            item->SubItems->Add(supplies[i].category);
            item->SubItems->Add(supplies[i].model);
            item->SubItems->Add(supplies[i].supplyDate);
        }
    }

}

// ОБРАБОТЧИК ИЗМЕНЕНИЯ ЧЕКБОКСОВ
void __fastcall TFormControlListTech::CheckListBox1Click(TObject *Sender)
{
    FilterBySuppliers(); // Применяем фильтр при клике
}

void __fastcall TFormControlListTech::ButtonAddSupplierClick(TObject *Sender)
{
    AddSupplier();
}



void __fastcall TFormControlListTech::CheckListBox2Click(TObject *Sender)
{
    // Обновляем фильтр
    UpdateSuppliesListView();
}
Соседние файлы в папке Курсовая работа Армашев 3 семестр. Список оргтехники предприятия. С++