Əsas məzmuna keçin

Lift Sistem Dizaynı

Problem Təsviri​

Binada çoxlu liftləri effektiv şəkildə idarə edə bilən, müxtəlif mərtəbələrdəki istifadəçilərin sorğularını işləyən və lift hərəkətini optimallaşdıran lift sistemi dizayn edin.

Tələblər​

  1. Funksional Tələblər:

    • Binada çoxlu liftlər dəstəyi
    • Xarici sorğuların (mərtəbələrdən) və daxili sorğuların (lift içindən) işlənməsi
    • Liftlərin yuxarı və aşağı hərəkəti
    • Qapıların açılması və bağlanması
    • Cari mərtəbə və istiqamətin göstərilməsi
    • Təcili dayanma dəstəyi
  2. Qeyri-Funksional Tələblər:

    • Təhlükəsizlik (qapıların maneə olduqda bağlanmasının qarşısının alınması)
    • Effektivlik (gözləmə müddətinin və enerji sərfiyyatının minimuma endirilməsi)
    • Etibarlılıq
    • Concurrent sorğular üçün thread safety

Əsas Komponentlər​

  1. Lift Kabinası: Mərtəbələr arasında hərəkət edən fiziki lift
  2. Lift Kontrolleri: Liftin hərəkətini və əməliyyatlarını idarə edir
  3. Planlaşdırıcı: Sorğuları optimallaşdırma alqoritminə əsasən liftlərə təyin edir
  4. Düymə Paneli: Hər lift daxilində və hər mərtəbədə
  5. Ekran: Cari mərtəbə və istiqaməti göstərir

Dizayn Yanaşması​

Lift vəziyyətlərini modelləşdirmək üçün State Pattern istifadə edəcəyik:

  1. Idle: Lift sakit vəziyyətdə, qapılar bağlı
  2. Moving Up: Lift yuxarı hərəkət edir
  3. Moving Down: Lift aşağı hərəkət edir
  4. Doors Opening: Lift qapıları açılır
  5. Doors Open: Lift qapıları tam açıq
  6. Doors Closing: Lift qapıları bağlanır

İcra​

Koda bax
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

// Elevator state interface
interface ElevatorState {
void handleRequest(Elevator elevator, int floor);
void move(Elevator elevator);
void stop(Elevator elevator);
void openDoors(Elevator elevator);
void closeDoors(Elevator elevator);
}

// Idle state
class IdleState implements ElevatorState {
@Override
public void handleRequest(Elevator elevator, int floor) {
if (floor > elevator.getCurrentFloor()) {
elevator.setDirection(Direction.UP);
elevator.setState(new MovingUpState());
} else if (floor < elevator.getCurrentFloor()) {
elevator.setDirection(Direction.DOWN);
elevator.setState(new MovingDownState());
} else {
elevator.openDoors();
}
}

@Override
public void move(Elevator elevator) {
// Cannot move in idle state
}

@Override
public void stop(Elevator elevator) {
// Already stopped
}

@Override
public void openDoors(Elevator elevator) {
elevator.setState(new DoorsOpeningState());
}

@Override
public void closeDoors(Elevator elevator) {
// Doors already closed
}
}

// Moving Up state
class MovingUpState implements ElevatorState {
@Override
public void handleRequest(Elevator elevator, int floor) {
if (floor >= elevator.getCurrentFloor()) {
elevator.addRequest(floor);
}
}

@Override
public void move(Elevator elevator) {
elevator.moveUp();
if (elevator.shouldStopAtCurrentFloor()) {
elevator.stop();
}
}

@Override
public void stop(Elevator elevator) {
elevator.setState(new IdleState());
elevator.openDoors();
}

@Override
public void openDoors(Elevator elevator) {
// Cannot open doors while moving
}

@Override
public void closeDoors(Elevator elevator) {
// Doors already closed
}
}

// Moving Down state
class MovingDownState implements ElevatorState {
@Override
public void handleRequest(Elevator elevator, int floor) {
if (floor <= elevator.getCurrentFloor()) {
elevator.addRequest(floor);
}
}

@Override
public void move(Elevator elevator) {
elevator.moveDown();
if (elevator.shouldStopAtCurrentFloor()) {
elevator.stop();
}
}

@Override
public void stop(Elevator elevator) {
elevator.setState(new IdleState());
elevator.openDoors();
}

@Override
public void openDoors(Elevator elevator) {
// Cannot open doors while moving
}

@Override
public void closeDoors(Elevator elevator) {
// Doors already closed
}
}

// Doors Opening state
class DoorsOpeningState implements ElevatorState {
@Override
public void handleRequest(Elevator elevator, int floor) {
elevator.addRequest(floor);
}

@Override
public void move(Elevator elevator) {
// Cannot move while doors are opening
}

@Override
public void stop(Elevator elevator) {
// Already stopped
}

@Override
public void openDoors(Elevator elevator) {
// Doors are already opening
}

@Override
public void closeDoors(Elevator elevator) {
// Cannot close doors while they are opening
}

// Transition to doors open state after doors finish opening
public void doorsOpened(Elevator elevator) {
elevator.setState(new DoorsOpenState());
}
}

// Doors Open state
class DoorsOpenState implements ElevatorState {
@Override
public void handleRequest(Elevator elevator, int floor) {
elevator.addRequest(floor);
}

@Override
public void move(Elevator elevator) {
// Cannot move while doors are open
}

@Override
public void stop(Elevator elevator) {
// Already stopped
}

@Override
public void openDoors(Elevator elevator) {
// Doors already open
}

@Override
public void closeDoors(Elevator elevator) {
elevator.setState(new DoorsClosingState());
}
}

// Doors Closing state
class DoorsClosingState implements ElevatorState {
@Override
public void handleRequest(Elevator elevator, int floor) {
if (floor == elevator.getCurrentFloor()) {
// Reopen doors if request is for current floor
elevator.openDoors();
} else {
elevator.addRequest(floor);
}
}

@Override
public void move(Elevator elevator) {
// Cannot move while doors are closing
}

@Override
public void stop(Elevator elevator) {
// Already stopped
}

@Override
public void openDoors(Elevator elevator) {
elevator.setState(new DoorsOpeningState());
}

@Override
public void closeDoors(Elevator elevator) {
// Doors already closing
}

// Transition to idle state after doors finish closing
public void doorsClosed(Elevator elevator) {
elevator.setState(new IdleState());
elevator.processNextRequest();
}
}

// Direction enum
enum Direction {
UP, DOWN, NONE
}

// Elevator class
class Elevator {
private final int id;
private int currentFloor;
private Direction direction;
private ElevatorState state;
private final Set<Integer> upRequests;
private final Set<Integer> downRequests;
private final int maxFloor;
private final Lock lock;
private boolean doorObstructed;

public Elevator(int id, int maxFloor) {
this.id = id;
this.currentFloor = 1;
this.direction = Direction.NONE;
this.state = new IdleState();
this.upRequests = new ConcurrentSkipListSet<>();
this.downRequests = new ConcurrentSkipListSet<>(Collections.reverseOrder());
this.maxFloor = maxFloor;
this.lock = new ReentrantLock();
this.doorObstructed = false;
}

public int getId() {
return id;
}

public int getCurrentFloor() {
return currentFloor;
}

public Direction getDirection() {
return direction;
}

public void setDirection(Direction direction) {
this.direction = direction;
}

public void setState(ElevatorState state) {
this.state = state;
}

public void addRequest(int floor) {
if (floor < 1 || floor > maxFloor) {
throw new IllegalArgumentException("Invalid floor: " + floor);
}

if (floor > currentFloor) {
upRequests.add(floor);
} else if (floor < currentFloor) {
downRequests.add(floor);
}
}

public void handleRequest(int floor) {
lock.lock();
try {
state.handleRequest(this, floor);
} finally {
lock.unlock();
}
}

public void moveUp() {
if (currentFloor < maxFloor) {
currentFloor++;
System.out.println("Elevator " + id + " moved up to floor " + currentFloor);
}
}

public void moveDown() {
if (currentFloor > 1) {
currentFloor--;
System.out.println("Elevator " + id + " moved down to floor " + currentFloor);
}
}

public void move() {
lock.lock();
try {
state.move(this);
} finally {
lock.unlock();
}
}

public void stop() {
lock.lock();
try {
state.stop(this);
System.out.println("Elevator " + id + " stopped at floor " + currentFloor);
} finally {
lock.unlock();
}
}

public void openDoors() {
lock.lock();
try {
state.openDoors(this);
System.out.println("Elevator " + id + " doors opening at floor " + currentFloor);

// Simulate doors opening
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}

if (state instanceof DoorsOpeningState) {
((DoorsOpeningState) state).doorsOpened(this);
System.out.println("Elevator " + id + " doors open at floor " + currentFloor);
}
} finally {
lock.unlock();
}
}

public void closeDoors() {
lock.lock();
try {
if (doorObstructed) {
System.out.println("Elevator " + id + " doors obstructed, reopening");
doorObstructed = false;
openDoors();
return;
}

state.closeDoors(this);
System.out.println("Elevator " + id + " doors closing at floor " + currentFloor);

// Simulate doors closing
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}

if (state instanceof DoorsClosingState) {
((DoorsClosingState) state).doorsClosed(this);
System.out.println("Elevator " + id + " doors closed at floor " + currentFloor);
}
} finally {
lock.unlock();
}
}

public boolean shouldStopAtCurrentFloor() {
if (direction == Direction.UP && upRequests.contains(currentFloor)) {
upRequests.remove(currentFloor);
return true;
} else if (direction == Direction.DOWN && downRequests.contains(currentFloor)) {
downRequests.remove(currentFloor);
return true;
}
return false;
}

public void processNextRequest() {
if (!upRequests.isEmpty() && (direction == Direction.UP || downRequests.isEmpty())) {
direction = Direction.UP;
int nextFloor = upRequests.iterator().next();
handleRequest(nextFloor);
} else if (!downRequests.isEmpty()) {
direction = Direction.DOWN;
int nextFloor = downRequests.iterator().next();
handleRequest(nextFloor);
} else {
direction = Direction.NONE;
}
}

public void simulateDoorObstruction() {
doorObstructed = true;
}

public void emergencyStop() {
lock.lock();
try {
System.out.println("Elevator " + id + " EMERGENCY STOP at floor " + currentFloor);
state = new IdleState();
direction = Direction.NONE;
upRequests.clear();
downRequests.clear();
} finally {
lock.unlock();
}
}
}

// Elevator Controller class
class ElevatorController {
private final List<Elevator> elevators;
private final int maxFloor;

public ElevatorController(int elevatorCount, int maxFloor) {
this.elevators = new ArrayList<>();
this.maxFloor = maxFloor;

for (int i = 1; i <= elevatorCount; i++) {
elevators.add(new Elevator(i, maxFloor));
}
}

public void requestElevator(int floor, Direction direction) {
if (floor < 1 || floor > maxFloor) {
throw new IllegalArgumentException("Invalid floor: " + floor);
}

// Find the best elevator to handle this request
Elevator bestElevator = findBestElevator(floor, direction);
bestElevator.handleRequest(floor);
}

public void requestFloor(int elevatorId, int floor) {
if (elevatorId < 1 || elevatorId > elevators.size()) {
throw new IllegalArgumentException("Invalid elevator ID: " + elevatorId);
}

if (floor < 1 || floor > maxFloor) {
throw new IllegalArgumentException("Invalid floor: " + floor);
}

Elevator elevator = elevators.get(elevatorId - 1);
elevator.handleRequest(floor);
}

private Elevator findBestElevator(int floor, Direction direction) {
// Simple algorithm: find the closest idle elevator or one moving in the same direction
Elevator bestElevator = null;
int minDistance = Integer.MAX_VALUE;

for (Elevator elevator : elevators) {
if (elevator.getDirection() == Direction.NONE) {
// Idle elevator
int distance = Math.abs(elevator.getCurrentFloor() - floor);
if (distance < minDistance) {
minDistance = distance;
bestElevator = elevator;
}
} else if (elevator.getDirection() == direction) {
// Elevator moving in the same direction
if ((direction == Direction.UP && elevator.getCurrentFloor() < floor) ||
(direction == Direction.DOWN && elevator.getCurrentFloor() > floor)) {
int distance = Math.abs(elevator.getCurrentFloor() - floor);
if (distance < minDistance) {
minDistance = distance;
bestElevator = elevator;
}
}
}
}

// If no suitable elevator found, just pick the first one
if (bestElevator == null) {
bestElevator = elevators.get(0);
}

return bestElevator;
}

public void step() {
// Simulate one time step for all elevators
for (Elevator elevator : elevators) {
if (elevator.getDirection() != Direction.NONE) {
elevator.move();
}
}
}
}

// Example usage
public class ElevatorSystemDemo {
public static void main(String[] args) {
// Create a controller with 3 elevators and 10 floors
ElevatorController controller = new ElevatorController(3, 10);

// Request elevators from different floors
controller.requestElevator(5, Direction.UP);
controller.requestElevator(3, Direction.DOWN);

// Simulate time steps
for (int i = 0; i < 10; i++) {
controller.step();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}

// Request a specific floor from inside an elevator
controller.requestFloor(1, 8);

// Simulate more time steps
for (int i = 0; i < 10; i++) {
controller.step();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}

Thread Safety Considerations​

  1. ReentrantLock: Liftlərdə thread-safe əməliyyatları təmin etmək üçün istifadə olunur
  2. ConcurrentSkipListSet: Mərtəbə sorğularının thread-safe idarə edilməsi üçün istifadə olunur
  3. State Pattern: Lift vəziyyət keçidlərinin atomik və tutarlı olmasını təmin edir
  4. Immutable Objects: Direction enum və state implementasiyaları dəyişməzdir

Optimallaşdırma Strategiyaları​

  1. Ən Yaxın Lift Alqoritmi: Sorğuları ən yaxın mövcud liftə təyin edir
  2. Eyni İstiqamət Prioriteti: Artıq tələb olunan istiqamətdə hərəkət edən liftlərə prioritet verir
  3. Skan Alqoritmi (Lift Alqoritmi): Bir istiqamətdə həmin istiqamətdə daha çox sorğu qalmayana qədər xidmət edir
  4. İrəliyə Baxış Strategiyası: Nümunələr əsasında gələcək sorğuları proqnozlaşdırır

Təhlükəsizlik Xüsusiyyətləri​

  1. Qapı Maneə Aşkarlaması: Maneə olduqda qapıların bağlanmasının qarşısını alır
  2. Təcili Dayanma: Lifti dərhal dayandırır və bütün sorğuları təmizləyir
  3. Mərtəbə Doğrulaması: Sorğu olunan mərtəbələrin etibarlı diapazonda olmasını təmin edir
  4. Vəziyyət Doğrulaması: Cari vəziyyətə əsasən yanlış əməliyyatların qarşısını alır

Əlavə Xüsusiyyətlər​

  1. Çəki Məhdudiyyəti Aşkarlaması: Liftin həddindən artıq yüklənməsinin qarşısını alır
  2. Prioritet Xidməti: Prioritet sorğularını dəstəkləyir (məsələn, təcili yardım personalı üçün)
  3. Ekspress Liftlər: Yalnız müəyyən mərtəbələrdə dayanan liftlər
  4. Texniki Xidmət Rejimi: Texniki xidmət üçün liftləri xidmətdən çıxarır