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


program ParkingApp;

{$mode objfpc}{$H+}
{$codepage UTF-8}

uses
  heaptrc, // Поиск утечек памяти в куче
  {$ifdef unix}cwstring,{$endif}
  SysUtils,
  ConsoleUtils,
  Parking; // Наш модуль логики

{ Безопасный ввод чисел через паттерн TryStrToInt }
function ReadInteger(const APrompt: string): Integer;
var
  S: string;
begin
  repeat
    Write(APrompt);
    ReadLn(S);
    if not TryStrToInt(S, Result) then
      WriteLn(Format('Ошибка: "%s" — не число. Попробуйте ещё раз.', [S]));
  until TryStrToInt(S, Result);
end;

var
  ParkingLot: TParkingLot;
  InitialCapacity: Integer;
  MenuChoice: Integer;
  License: string;
  SpotNum: Integer;

begin
  InitialCapacity := ReadInteger('Вместимость парковки: ');
  ParkingLot := TParkingLot.Create(InitialCapacity);
  
  // Глобальный try..finally защищает ОЗУ от утечек при аварийном выходе
  try
    WriteLn(Format('=== Парковка (%d места) ===', [ParkingLot.Capacity]));
    WriteLn('1. Припарковать машину (автоматически)');
    WriteLn('2. Припарковать на конкретное место');
    WriteLn('3. Выехать');
    WriteLn('4. Найти машину');
    WriteLn('5. Переставить машину');
    WriteLn('6. Показать статус парковки');
    WriteLn('0. Выход');

    repeat
      MenuChoice := ReadInteger('> ');
      
      // Внутренний try..except ловит кастомные ошибки парковки и гасит их
      try
        case MenuChoice of
          1: 
            begin
              Write('Номер машины: ');
              ReadLn(License);
              SpotNum := ParkingLot.Park(License);
              WriteLn(Format('Машина припаркована на место %d.', [SpotNum]));
            end;
          2:
            begin
              Write('Номер машины: ');
              ReadLn(License);
              SpotNum := ReadInteger('Номер места: ');
              ParkingLot.ParkAtSpot(SpotNum, License);
              WriteLn(Format('Машина припаркована на место %d.', [SpotNum]));
            end;
          3:
            begin
              Write('Номер машины: ');
              ReadLn(License);
              SpotNum := ParkingLot.FindCar(License); // Узнаем место до удаления
              ParkingLot.Leave(License);
              WriteLn(Format('Место %d освобождено.', [SpotNum]));
            end;
          4:
            begin
              Write('Номер машины: ');
              ReadLn(License);
              SpotNum := ParkingLot.FindCar(License);
              WriteLn(Format('Машина %s найдена на месте %d.', [License, SpotNum]));
            end;
          5:
            begin
              Write('Номер машины: ');
              ReadLn(License);
              SpotNum := ReadInteger('Новое место: ');
              ParkingLot.MoveCar(License, SpotNum);
              WriteLn(Format('Машина %s успешно перемещена на место %d.', [License, SpotNum]));
            end;
          6:
            begin
              ParkingLot.PrintStatus;
            end;
          0: WriteLn('До свидания!');
        end;
        
      except
        on E: EParkingError do
          WriteLn('Ошибка: ', E.Message, '.');
      end;

    until MenuChoice = 0;

  finally
    ParkingLot.Free; // Гарантированное уничтожение объекта и чистка памяти
  end;
end.