Скачиваний:
0
Добавлен:
11.01.2026
Размер:
910.74 Кб
Скачать

Интерфейс приложения

Рисунок 2. Главная форма

Рисунок 3. Форма отчёта

Заключение

В результате выполнения курсовой работы было разработано приложение для учёта оргтехники в среде C++ Builder. Было реализовано: чтение и сохранение данных в файлы, добавление новых записей об оборудовании, редактирование и удаление строк, сортировку, поиск элементов, а также визуализацию расположения техники на плане помещения.

Также была реализована функциональность для расчёта амортизации оборудования и проверки гарантийных сроков. Реализованы эффективные алгоритмы обработки данных, включая быструю сортировку и линейный поиск.

Список использованных источников

1. А. В. Шевченко “Программирование и основы алгоритмизации: учеб. метод. пособие. Изд-во СПбГЭТУ «ЛЭТИ», 2011” // URL: https://vec.etu.ru/moodle/pluginfile.php/601203/mod_resource/content/0/Учебное%20пособие.%20Программирование%20и%20основы%20алгоритмизации.pdf (Дaта обращения: 09.09.2025)

2. Руководство по языку программирования Си. // URL: https://metanit.com/c/tutorial/ (Дата обращения: 25.09.2025)

3. Герберт Шилдт “С++ базовый курс” // URL: https://www.bsuir.by/m/12_100229_1_98220.pdf/ (Дата обращения: 30.10.2025)

4. Microsoft - “Справочник по языку C” // URL: https://learn.microsoft.com/ru-ru/cpp/c-language/c-language-reference?view=msvc-170 (дата обращения: 10.11.2025)

5. “C Programming Language Tutorial” // URL: https://www.geeksforgeeks.org/c-programming-language/?ysclid=mb7432j49u687387975 (дата обращения: 20.05.2025)

6. “Язык программирования С++” // URL: http://cppstudio.com/cat/274/ (дата обращения: 28.11.2025)

Приложение

ControlListTech.cpp

#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();

}

ControlListTech.h

#ifndef ControlListTechH

#define ControlListTechH

//---------------------------------------------------------------------------

#include <System.Classes.hpp>

#include <Vcl.Controls.hpp>

#include <Vcl.StdCtrls.hpp>

#include <Vcl.Forms.hpp>

#include <System.ImageList.hpp>

#include <Vcl.ImgList.hpp>

#include <Vcl.ComCtrls.hpp>

#include <Vcl.CheckLst.hpp>

#include <Vcl.ExtCtrls.hpp>

//---------------------------------------------------------------------------

#include <class.h>

class TFormControlListTech : public TForm

{

__published:

TImageList *ImageList1;

TButton *Button1;

TButton *Button2;

TPageControl *PageControl1;

TTabSheet *TablePage;

TTabSheet *PlanPage;

TListView *ListView1;

TButton *Button3;

TButton *BtnSort;

TButton *BtnSearch;

TTabSheet *Deliveries;

TTabSheet *TabSheet2;

TTabSheet *TabSheet3;

TPanel *Panel1;

TListView *Post;

TListView *ListView2;

TLabel *Label1;

TLabel *Label2;

TPanel *Panel2;

TLabel *Label3;

TCheckListBox *CheckListBox1;

TButton *BtnGenerateReport;

TCheckListBox *CheckListBox2;

TButton *ButtonAddSupplier;

TPanel *Panel3;

TPaintBox *sample_pb;

TEdit *SearchEdit;

TButton *BtnAdd;

void __fastcall BtnAddClickClick(TObject *Sender);

void __fastcall BtnEditClickClick(TObject *Sender);

void __fastcall BtnDeleteClickClick(TObject *Sender);

void __fastcall BtnSearchClickClick(TObject *Sender);

void __fastcall PaintPlanTech(TObject *Sender);

void __fastcall BtnSave(TObject *Sender);

void __fastcall BtnLoad(TObject *Sender);

void __fastcall BtnSearchClick(TObject *Sender);

void __fastcall SearchEditChange(TObject *Sender);

void __fastcall BtnSortClick(TObject *Sender);

private:

OrgTechnic devices[50]; // Основное оборудование

Supply supplies[50]; // Поставки

Repair repairs[50]; // Ремонты

int deviceCount;

int supplyCount;

int repairCount;

// Для работы с поставщиками

char suppliers[50][100]; // Массив поставщиков

int supplierCount; // Количество поставщиков

bool supplierFilter[50]; // Флаги выбранных поставщиков для фильтрации

void ManageDevices();

void AddDevice();

void EditDevice();

void DeleteDevice();

void SearchSort();

void DisplayDeviceOnPlan(OrgTechnic &device); // Отрисовка на плане

void UpdateMainListView(); // Обновление основной таблицы

void UpdateSuppliesListView(); // Обновление поставок

void AddSupplier();

void __fastcall ButtonAddSupplierClick(TObject *Sender);

void __fastcall ButtonResetFiltersClick(TObject *Sender);

void __fastcall ButtonAddSupplyClick(TObject *Sender);

void __fastcall CheckListBox1Click(TObject *Sender);

void UpdateSupplierCheckboxes();

void FilterBySuppliers();

void UpdateSuppliesListViewWithFilter();

void UpdateRepairsListView(); // Обновление ремонтов

void AddSampleData(); // Заполнение тестовыми данными

void SaveToFileWithDialog();

void LoadFromFileWithDialog();

void SaveToFile();

void LoadFromFile();

void LaunchEasterEgg(); // Запуск пасхалки

void PerformSearch(const char* searchText);

void UpdateMainListViewWithFilter(const char* filterText);

void HideSearchInput();

void __fastcall ListView1DblClick(TObject *Sender);

void __fastcall ListView1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y);

void ShowEditDialog(int deviceIndex);

void CalculateTotalValue(); //стоимость

void UpdateReportTab();

void __fastcall PageControl1Change(TObject *Sender); // Обработчик смены вкладки

// ОБРАБОТЧИКИ СОРТИРОВКИ

void __fastcall BtnSortPriceAscClick(TObject *Sender);

void __fastcall BtnSortPriceDescClick(TObject *Sender);

void __fastcall BtnSortDateAscClick(TObject *Sender);

void __fastcall BtnSortDateDescClick(TObject *Sender);

//void __fastcall BtnSortClick(TObject *Sender); // Для меню

// МЕТОДЫ ДЛЯ БЫСТРОЙ СОРТИРОВКИ

void QuickSortByPrice(int left, int right, bool ascending = true);

void QuickSortByDate(int left, int right, bool ascending = true);

int PartitionByPrice(int left, int right, bool ascending);

int PartitionByDate(int left, int right, bool ascending);

void SwapDevices(int i, int j);

// МЕТОДЫ ДЛЯ ВЫЗОВА СОРТИРОВКИ

void SortByPrice(bool ascending);

void SortByDate(bool ascending);

void __fastcall CheckListBox2Click(TObject *Sender);

void __fastcall CheckListBox1ClickReport(TObject *Sender);

public:

__fastcall TFormControlListTech(TComponent* Owner);

};

//---------------------------------------------------------------------------

extern PACKAGE TFormControlListTech *FormControlListTech;

//---------------------------------------------------------------------------

#endif

class.cpp

#include "class.h"

#include <string.h>

#include <cmath>

#include <ctime>

bool OrgTechnic::IsWarrantyValid()

{

return MonthsInUse() <= warrantyMonths;

}

float OrgTechnic::CurrentValue()

{

int monthsUsed = MonthsInUse();

if(monthsUsed <= warrantyMonths) {

return price * (1.0f - (monthsUsed * 0.005f));

} else {

int monthsAfterWarranty = monthsUsed - warrantyMonths;

float depreciation = (warrantyMonths * 0.005f) + (monthsAfterWarranty * 0.02f);

float value = price * (1.0f - depreciation);

return (value > price * 0.1f) ? value : price * 0.1f;

}

}

int OrgTechnic::MonthsInUse()

{

int day, month, year;

sscanf(purchaseDate, "%d.%d.%d", &day, &month, &year);

time_t t = time(NULL);

struct tm *currentTime = localtime(&t);

int currentYear = currentTime->tm_year + 1900;

int currentMonth = currentTime->tm_mon + 1;

return (currentYear - year) * 12 + (currentMonth - month);

}

void OrgTechnic::SetCoordinates(int x, int y)

{

coordX = x;

coordY = y;

}

void OrgTechnic::SaveToFile(FILE *file)

{

fprintf(file, "%d|%s|%s|%s|%d|%f|%s|%d|%d\n",

id, category, model, purchaseDate, warrantyMonths,

price, additionalInfo, coordX, coordY);

}

void OrgTechnic::LoadFromFile(FILE *file)

{

fscanf(file, "%d|%[^|]|%[^|]|%[^|]|%d|%f|%[^|]|%d|%d\n",

&id, category, model, purchaseDate, &warrantyMonths,

&price, additionalInfo, &coordX, &coordY);

}

void Supply::SaveToFile(FILE *file)

{

fprintf(file, "%s|%s|%s|%s\n",

supplier, category, model, supplyDate);

}

void Supply::LoadFromFile(FILE *file)

{

char line[300];

if (fgets(line, sizeof(line), file)) {

char* token = strtok(line, "|\n");

if (token) strcpy(supplier, token);

token = strtok(NULL, "|\n");

if (token) strcpy(category, token);

token = strtok(NULL, "|\n");

if (token) strcpy(model, token);

token = strtok(NULL, "|\n");

if (token) strcpy(supplyDate, token);

}

}

void Repair::SaveToFile(FILE *file)

{

fprintf(file, "%d|%s|%s|%s|%s\n",

deviceId, category, model, repairStartDate, condition);

}

void Repair::LoadFromFile(FILE *file)

{

char line[300];

if (fgets(line, sizeof(line), file)) {

char* token = strtok(line, "|\n");

if (token) deviceId = atoi(token);

token = strtok(NULL, "|\n");

if (token) strcpy(category, token);

token = strtok(NULL, "|\n");

if (token) strcpy(model, token);

token = strtok(NULL, "|\n");

if (token) strcpy(repairStartDate, token);

token = strtok(NULL, "|\n");

if (token) strcpy(condition, token);

}

}

// Конструктор

ReportCalculator::ReportCalculator(OrgTechnic* devArray, int count, bool* filter, char** cats, int catCount)

{

devices = devArray;

deviceCount = count;

categoryFilter = filter;

categories = cats;

categoryCount = catCount;

}

// Проверка проходит ли устройство через фильтр категорий

bool ReportCalculator::DevicePassesFilter(int index)

{

// Если фильтр не установлен - пропускаем все устройства

if (categoryFilter == NULL || categories == NULL || categoryCount == 0) {

return true;

}

// Ищем категорию устройства в фильтре

for (int i = 0; i < categoryCount; i++) {

if (strcmp(devices[index].category, categories[i]) == 0) {

// Нашли категорию - проверяем выбран ли её чекбокс

return categoryFilter[i];

}

}

// Категория не найдена в фильтре - не показываем

return false;

}

// Общая первоначальная стоимость (с фильтром)

float ReportCalculator::CalculateTotalOriginalValue()

{

float total = 0.0f;

for(int i = 0; i < deviceCount; i++) {

if (DevicePassesFilter(i)) {

total += devices[i].price;

}

}

return total;

}

// Общая текущая стоимость (с фильтром)

float ReportCalculator::CalculateTotalCurrentValue()

{

float total = 0.0f;

for(int i = 0; i < deviceCount; i++) {

if (DevicePassesFilter(i)) {

total += devices[i].CurrentValue();

}

}

return total;

}

// Общая амортизация (с фильтром)

float ReportCalculator::CalculateTotalDepreciation()

{

return CalculateTotalOriginalValue() - CalculateTotalCurrentValue();

}

// Процент амортизации (с фильтром)

float ReportCalculator::CalculateDepreciationPercentage()

{

float original = CalculateTotalOriginalValue();

if(original == 0) return 0.0f;

return (CalculateTotalDepreciation() / original) * 100.0f;

}

// Количество устройств с гарантией (с фильтром)

int ReportCalculator::CountDevicesWithWarranty()

{

int count = 0;

for(int i = 0; i < deviceCount; i++) {

if (DevicePassesFilter(i) && devices[i].IsWarrantyValid()) {

count++;

}

}

return count;

}

// Количество устройств без гарантии (с фильтром)

int ReportCalculator::CountDevicesWithoutWarranty()

{

int count = 0;

for(int i = 0; i < deviceCount; i++) {

if (DevicePassesFilter(i) && !devices[i].IsWarrantyValid()) {

count++;

}

}

return count;

}

// Общее количество устройств (с фильтром)

int ReportCalculator::GetTotalDevicesCount()

{

int count = 0;

for(int i = 0; i < deviceCount; i++) {

if (DevicePassesFilter(i)) {

count++;

}

}

return count;

}

class.h

#ifndef ORGTECHCLASS_H

#define ORGTECHCLASS_H

class OrgTechnic

{

public:

int id;

char category[50];

char model[100];

char purchaseDate[20];

int warrantyMonths;

float price;

char additionalInfo[200];

int coordX;

int coordY;

// Методы

bool IsWarrantyValid();

float CurrentValue();

int MonthsInUse();

void SetCoordinates(int x, int y);

// Методы для работы с файлами

void SaveToFile(FILE *file);

void LoadFromFile(FILE *file);

};

class Supply

{

public:

char supplier[100];

char category[50];

char model[100];

char supplyDate[20];

void SaveToFile(FILE *file);

void LoadFromFile(FILE *file);

};

class Repair

{

public:

int deviceId;

char category[50];

char model[100];

char repairStartDate[20];

char condition[100];

void SaveToFile(FILE *file);

void LoadFromFile(FILE *file);

};

class ReportCalculator

{

private:

OrgTechnic* devices;

int deviceCount;

bool* categoryFilter; // Фильтр по категориям

char** categories; // Список категорий

int categoryCount; // Количество категорий

public:

// Конструктор

ReportCalculator(OrgTechnic* devArray, int count);

// Новый конструктор с фильтром

ReportCalculator(OrgTechnic* devArray, int count, bool* filter, char** cats, int catCount);

// Методы для расчетов

float CalculateTotalOriginalValue();

float CalculateTotalCurrentValue();

float CalculateTotalDepreciation();

float CalculateDepreciationPercentage();

int CountDevicesWithWarranty();

int CountDevicesWithoutWarranty();

int GetTotalDevicesCount();

// Метод для проверки проходит ли устройство через фильтр

bool DevicePassesFilter(int index);

};

#endif

Соседние файлы в папке Курсовая работа Армашев 3 семестр. Список оргтехники предприятия. С++