Skip to content
Snippets Groups Projects
Commit 35aa6fb9 authored by ddnguyen's avatar ddnguyen
Browse files

scheduler update

parent 148dc495
Branches
No related tags found
No related merge requests found
Pipeline #18776 passed
# Simulateur d'ascenseur # Project 1 - Elevator system
## Description du projet This project is developed by students at the Aix-Marseille university during a coursework project for Génie Logiciel (GL) module. the project aims is to simulate the real time system environment of an elevator controller using java.
Projet du simulateur d'ascenseur. ## Table of contents
* [General info](#general-info)
* [Technologies](#technologies)
* [Launching](#launching)
## General info
This project was contributed by :
- NGUYEN Dang Dinh (M1-INFO-3rd group)
- NGUYEN Duc Duong (M1-INFO-3rd group)
## Technologies
Project is created with:
* java version: 17.0.4.1
* Gradle version: 7.5.1
## Launching
To run this project (with UI) using cmd:
```
$ cd ../elevator-template
$ gradlew run
```
To run this project's tests:
```
$ cd ../elevator-template
$ gradlew test
```
## References
[Documentation](https://jean-luc-massat.pedaweb.univ-amu.fr/ens/gl/elevator.html) [Documentation](https://jean-luc-massat.pedaweb.univ-amu.fr/ens/gl/elevator.html)
...@@ -6,8 +6,9 @@ import elevator.Scheduler.Direction; ...@@ -6,8 +6,9 @@ import elevator.Scheduler.Direction;
import elevator.Scheduler.FloorRequest; import elevator.Scheduler.FloorRequest;
import elevatorSimulator.ElevatorSimulator; import elevatorSimulator.ElevatorSimulator;
import elevatorSimulator.IElevator; import elevatorSimulator.IElevator;
import elevatorSimulator.State;
public class ControlCommand implements IControlCommand, Runnable{ public class CommandController implements IControlCommand, Runnable{
private Scheduler scheduler; private Scheduler scheduler;
private IElevator elevator; private IElevator elevator;
private StopConditionListener stopConditionListener; private StopConditionListener stopConditionListener;
...@@ -15,13 +16,13 @@ public class ControlCommand implements IControlCommand, Runnable{ ...@@ -15,13 +16,13 @@ public class ControlCommand implements IControlCommand, Runnable{
private final int nbOfFloor; private final int nbOfFloor;
private Direction currentDirection = null; private Direction currentDirection = null;
private int currentFloor = 0; private volatile int currentFloor = 0;
private int nextFloor = 0; private volatile int nextFloor = 0;
private int currentPosition = 0; private volatile int positionMeasurer = 0;
private volatile boolean isRunning = true; private volatile boolean isRunning = true;
public ControlCommand(Scheduler scheduler, IElevator elevator, int nbOfFloor) { public CommandController(Scheduler scheduler, IElevator elevator, int nbOfFloor) {
this.scheduler = scheduler; this.scheduler = scheduler;
this.elevator = elevator; this.elevator = elevator;
this.nbOfFloor = nbOfFloor; this.nbOfFloor = nbOfFloor;
...@@ -33,11 +34,17 @@ public class ControlCommand implements IControlCommand, Runnable{ ...@@ -33,11 +34,17 @@ public class ControlCommand implements IControlCommand, Runnable{
@Override @Override
public void registerFloorRequest(int floor, Direction direction) { public void registerFloorRequest(int floor, Direction direction) {
if(elevator.getState() == State.ERROR || floor < 0 || floor > nbOfFloor)
return;
scheduler.registerFloorRequest(new FloorRequest(floor,direction)); scheduler.registerFloorRequest(new FloorRequest(floor,direction));
} }
@Override @Override
public void registerCabinRequest(int floor) { public void registerCabinRequest(int floor) {
if(elevator.getState() == State.ERROR || floor < 0 || floor > nbOfFloor)
return;
if(getCurrentFloor() != floor)
scheduler.registerCabinRequest(new CabinRequest(floor)); scheduler.registerCabinRequest(new CabinRequest(floor));
} }
...@@ -48,22 +55,25 @@ public class ControlCommand implements IControlCommand, Runnable{ ...@@ -48,22 +55,25 @@ public class ControlCommand implements IControlCommand, Runnable{
@Override @Override
public void checkAndProcess() { public void checkAndProcess() {
System.out.printf("level = %3.2f, direction = %s, floor = %d\n", getCurrentPosition(), getCurrentDirection(), getCurrentFloor());
while(isRunning) { while(isRunning) {
if (stopConditionListener.conditionReached()) { if (stopConditionListener.conditionReached()) {
stop(); // Optionally stop the loop here stop();
} }
// l'ascenseur change son sens lorsqu'il atteint le niveau 0 // l'ascenseur change son sens lorsqu'il atteint le niveau 0
if(getCurrentPosition() == 0) if(getCurrentPosition() == 0) {
setCurrentDirection(Direction.UP); setCurrentDirection(Direction.UP);
}
// l'ascenseur change son sens lorsqu'il atteint le dernier niveau // l'ascenseur change son sens lorsqu'il atteint le dernier niveau
if(getCurrentPosition() == nbOfFloor) else if(getCurrentFloor() == nbOfFloor) {
setCurrentDirection(Direction.DOWN); setCurrentDirection(Direction.DOWN);
}
// l'ascenseur change son sens à niveau intermédiaire, s'il n'y a pas de requête dans le sens de sa progression courante // l'ascenseur change son sens à niveau intermédiaire, s'il n'y a pas de requête dans le sens de sa progression courante
if(!getScheduler().checkPendingFloorRequest(getCurrentFloor(),getCurrentDirection()) else if(!getScheduler().checkPendingFloorRequest(getCurrentFloor(),getCurrentDirection())
&& !getScheduler().checkPendingCabinRequest(getCurrentFloor(), getCurrentDirection())) { && !getScheduler().checkPendingCabinRequest(getCurrentFloor(), getCurrentDirection())
&& elevator.getState() != State.ERROR && elevator.getState() != State.RESET) {
if(getCurrentDirection() == Direction.UP) { if(getCurrentDirection() == Direction.UP) {
setCurrentDirection(Direction.DOWN); setCurrentDirection(Direction.DOWN);
} else { } else {
...@@ -71,47 +81,76 @@ public class ControlCommand implements IControlCommand, Runnable{ ...@@ -71,47 +81,76 @@ public class ControlCommand implements IControlCommand, Runnable{
} }
} }
System.out.printf("level = %3.2f, direction = %s\n", (getCurrentFloor() + getCurrentPosition()/15.0), getCurrentDirection()); int nextFloor = scheduler.calculateNextFloor(getCurrentFloor(), getCurrentDirection());
if(getCurrentPosition() > 0 && getCurrentPosition()%15 == 0) {
setCurrentFloor(getCurrentFloor() + 1);
setCurrentPosition(0);
}
int nextFloor = scheduler.calculateNextFloor(currentFloor, currentDirection);
//System.out.println("next floor: " + getNextFloor());
setNextFloor(nextFloor); setNextFloor(nextFloor);
switch(elevator.getState()) { switch(elevator.getState()) {
case UP: case UP:
if(getCurrentFloor() + getCurrentPosition()/15.0 + 1 == getNextFloor()) { if(getCurrentPosition() + 1 == getNextFloor()) {
elevator.stopNext(); elevator.stopNext();
} }
((ElevatorSimulator) elevator).oneStep(); ((ElevatorSimulator) elevator).oneStep();
setCurrentPosition(getCurrentPosition() + 1); setPositionMeasurer(getPositionMeasurer() + 1);
System.out.println("moving..."); System.out.println("moving up...");
if(getPositionMeasurer() > 0 && getPositionMeasurer()%15 == 0) {
setCurrentFloor(getCurrentFloor() + 1);
setPositionMeasurer(0);
}
break; break;
case DOWN: case DOWN:
if(getCurrentPosition() - 1 == getNextFloor()) {
elevator.stopNext();
}
((ElevatorSimulator) elevator).oneStep();
setPositionMeasurer(getPositionMeasurer() - 1);
System.out.println("moving down...");
if(getPositionMeasurer() < 0 && getPositionMeasurer()%15 == 0) {
setCurrentFloor(getCurrentFloor() - 1);
setPositionMeasurer(0);
}
break; break;
case ERROR: case ERROR:
System.out.println(elevator.getState());
for(int i = 0; i <= nbOfFloor; i++) {
cancelRequest(i,Direction.UP);
cancelRequest(i,Direction.DOWN);
}
break; break;
case OPEN: case OPEN:
cancelRequest(getCurrentFloor(), getCurrentDirection());
System.out.println("opening..."); System.out.println("opening...");
((ElevatorSimulator) elevator).oneStep(); ((ElevatorSimulator) elevator).oneStep();
cancelRequest(currentFloor, currentDirection);
break; break;
case RESET: case RESET:
setCurrentDirection(Direction.DOWN);
((ElevatorSimulator) elevator).oneStep();
setPositionMeasurer(getPositionMeasurer() - 1);
System.out.println("resetting...");
if(getPositionMeasurer() < 0 && getPositionMeasurer()%15 == 0) {
setCurrentFloor(getCurrentFloor() - 1);
setPositionMeasurer(0);
}
break; break;
case STOP: case STOP:
if(nextFloor > currentFloor) { if(nextFloor > currentFloor) {
setNextFloor(nextFloor);
elevator.up(); elevator.up();
} }
else if(nextFloor < currentFloor) {
elevator.down();
}
break; break;
default: default:
return; return;
} }
System.out.printf("level = %3.2f, direction = %s, floor = %d\n", getCurrentPosition(), getCurrentDirection(), getCurrentFloor());
try { try {
Thread.sleep(100); Thread.sleep(100);
} catch (InterruptedException e) { } catch (InterruptedException e) {
...@@ -135,12 +174,12 @@ public class ControlCommand implements IControlCommand, Runnable{ ...@@ -135,12 +174,12 @@ public class ControlCommand implements IControlCommand, Runnable{
return this.scheduler; return this.scheduler;
} }
public int getCurrentPosition() { public int getPositionMeasurer() {
return currentPosition; return positionMeasurer;
} }
public void setCurrentPosition(int currentPosition) { public void setPositionMeasurer(int currentPosition) {
this.currentPosition = currentPosition; this.positionMeasurer = currentPosition;
} }
public int getCurrentFloor() { public int getCurrentFloor() {
...@@ -160,10 +199,15 @@ public class ControlCommand implements IControlCommand, Runnable{ ...@@ -160,10 +199,15 @@ public class ControlCommand implements IControlCommand, Runnable{
} }
public Direction getCurrentDirection() { public Direction getCurrentDirection() {
return currentDirection; return this.currentDirection;
} }
public void setCurrentDirection(Direction currentDirection) { public void setCurrentDirection(Direction currentDirection) {
this.currentDirection = currentDirection; this.currentDirection = currentDirection;
} }
public double getCurrentPosition() {
return getCurrentFloor() + getPositionMeasurer()/15.0;
}
} }
package elevator; package elevator;
import elevator.Scheduler.Direction;
import elevatorSimulator.ElevatorSimulator;
import elevatorSimulator.IElevator;
public class MainElevator { public class MainElevator {
static public void main(String args[]) { public static void main(String args[]) {
System.out.println("Rien à faire."); IElevator e = new ElevatorSimulator(5, true);
Scheduler s = new Scheduler();
IControlCommand c = new CommandController(s,e,5);
StopConditionListener stopConditionListener = () -> {
return ((CommandController) c).getCurrentDirection() == Direction.DOWN && ((CommandController) c).getCurrentPosition() == 0;
};
((CommandController) c).setStopConditionListener(stopConditionListener);
Thread controlThread = new Thread((Runnable) c);
controlThread.start();
c.registerCabinRequest(5);
while(true) {
if( ((CommandController) c).getCurrentFloor()== 3) {
e.halt();
System.out.println("halting...");
System.out.println(e.getState());
break;
}
}
try {
Thread.sleep(1000);
e.reset();
controlThread.join();
} catch (InterruptedException e1) {
e1.printStackTrace();
} }
System.out.println(((ElevatorSimulator) e).getEvents());
}
} }
...@@ -3,15 +3,13 @@ package elevator; ...@@ -3,15 +3,13 @@ package elevator;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import elevatorSimulator.State;
public class Scheduler { public class Scheduler {
private List<FloorRequest> floorRequests; private List<FloorRequest> floorRequests;
private List<CabinRequest> cabinRequests; private List<CabinRequest> cabinRequests;
public Scheduler() { public Scheduler() {
floorRequests = new ArrayList<>(); floorRequests = new ArrayList<FloorRequest>();
cabinRequests = new ArrayList<>(); cabinRequests = new ArrayList<CabinRequest>();
} }
public List<CabinRequest> getCabinRequests(){ public List<CabinRequest> getCabinRequests(){
...@@ -23,46 +21,116 @@ public class Scheduler { ...@@ -23,46 +21,116 @@ public class Scheduler {
} }
public void registerFloorRequest(FloorRequest floorRequest) { public void registerFloorRequest(FloorRequest floorRequest) {
// Il ne peut y avoir qu'un appel pour monter ou pour descendre par niveau.
boolean requestExists = false;
for (FloorRequest existingRequest : floorRequests) {
if (existingRequest.equals(floorRequest) || existingRequest.getFloor() == floorRequest.getFloor()) {
requestExists = true;
break;
}
}
// Add the request to the list if it doesn't already exist
if (!requestExists)
floorRequests.add(floorRequest); floorRequests.add(floorRequest);
} }
public void registerCabinRequest(CabinRequest cabinRequest) { public void registerCabinRequest(CabinRequest cabinRequest) {
boolean requestExists = false;
for (CabinRequest existingRequest : cabinRequests) {
if (existingRequest.equals(cabinRequest)) {
requestExists = true;
break;
}
}
// Add the request to the list if it doesn't already exist
if (!requestExists)
cabinRequests.add(cabinRequest); cabinRequests.add(cabinRequest);
} }
public void cancelFloorRequest(int floor, State direction) { public void cancelRequest(int floor, Direction direction) {
cabinRequests.removeIf(cr -> cr.floor == floor);
floorRequests.removeIf(fr -> fr.floor == floor && fr.direction == direction); floorRequests.removeIf(fr -> fr.floor == floor && fr.direction == direction);
} }
public int calculateNextFloor(int currentFloor, State direction) { public int calculateNextFloor(int currentFloor, Direction direction) {
// En l'absence de requête, l'ascenseur continue à stationner jusqu'à l'arrivée d'une requête pour un autre niveau.
if(floorRequests.isEmpty() && cabinRequests.isEmpty())
return currentFloor;
int nextFloor = currentFloor;
// Sort floor requests based on direction and proximity to current floor // Sort floor requests based on direction and proximity to current floor
floorRequests.sort((fr1, fr2) -> { floorRequests.sort((fr1, fr2) -> {
if (direction == State.UP) { if (direction == Direction.UP) {
return Integer.compare(fr1.floor, fr2.floor); return Integer.compare(fr1.floor, fr2.floor);
} else { } else {
return Integer.compare(fr2.floor, fr1.floor); return Integer.compare(fr2.floor, fr1.floor);
} }
}); });
// Find the next floor to stop at // Sort cabin requests based on direction and proximity to current floor
cabinRequests.sort((cr1, cr2) -> {
if (direction == Direction.UP) {
return Integer.compare(cr1.floor, cr2.floor);
} else {
return Integer.compare(cr2.floor, cr1.floor);
}
});
// Check if there are pending floor requests in the current direction
for (FloorRequest request : floorRequests) { for (FloorRequest request : floorRequests) {
if (direction == State.UP && request.floor > currentFloor) { if (direction == Direction.UP && request.floor > currentFloor && request.direction == Direction.UP) {
return request.floor; nextFloor = request.floor;
} else if (direction == State.DOWN && request.floor < currentFloor) { break;
return request.floor; } else if (direction == Direction.DOWN && request.floor < currentFloor && request.direction == Direction.DOWN) {
nextFloor = request.floor;
break;
}
}
//System.out.println("pending floor request = " + nextFloor);
// Check if there are pending cabin requests in the current direction
for (CabinRequest cabinRequest : cabinRequests) {
if ((direction == Direction.UP && cabinRequest.floor > currentFloor) ||
(direction == Direction.DOWN && cabinRequest.floor < currentFloor)) {
nextFloor = cabinRequest.floor;
break;
} }
} }
//System.out.println("pending cabin request = " + nextFloor);
// If no pending requests in the current direction, continue in the same direction return nextFloor;
return currentFloor + (direction == State.UP ? 1 : -1);
} }
public boolean checkPendingFloorRequest(int currentFloor, Direction direction) {
for (FloorRequest request : floorRequests) {
if (direction == Direction.UP && (request.floor > currentFloor || request.direction == Direction.UP)) {
return true;
} else if (direction == Direction.DOWN && (request.floor < currentFloor || request.direction == Direction.DOWN)) {
return true;
}
}
return false;
}
public boolean checkPendingCabinRequest(int currentFloor, Direction direction) {
for (CabinRequest cabinRequest : cabinRequests) {
if ((direction == Direction.UP && cabinRequest.floor > currentFloor) ||
(direction == Direction.DOWN && cabinRequest.floor < currentFloor)) {
return true;
}
}
return false;
}
// Helper class to represent floor requests with direction // Helper class to represent floor requests with direction
public static class FloorRequest { public static class FloorRequest {
private final int floor; private final int floor;
private final State direction; private final Direction direction;
public FloorRequest(int floor, State direction) { public FloorRequest(int floor, Direction direction) {
this.floor = floor; this.floor = floor;
this.direction = direction; this.direction = direction;
} }
...@@ -71,9 +139,22 @@ public class Scheduler { ...@@ -71,9 +139,22 @@ public class Scheduler {
return floor; return floor;
} }
public State getDirection() { public Direction getDirection() {
return direction; return direction;
} }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FloorRequest that = (FloorRequest) o;
// Compare floor and direction for equality
if (floor != that.floor) return false;
return direction == that.direction;
}
} }
// Helper class to represent cabin requests // Helper class to represent cabin requests
...@@ -87,6 +168,19 @@ public class Scheduler { ...@@ -87,6 +168,19 @@ public class Scheduler {
public int getFloor() { public int getFloor() {
return floor; return floor;
} }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CabinRequest that = (CabinRequest) o;
// Compare floor for equality
return floor == that.floor;
}
} }
public enum Direction{UP, DOWN}
} }
...@@ -7,7 +7,6 @@ import static elevatorSimulator.State.RESET; ...@@ -7,7 +7,6 @@ import static elevatorSimulator.State.RESET;
import static elevatorSimulator.State.UP; import static elevatorSimulator.State.UP;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
...@@ -18,7 +17,6 @@ public class TestAutomaticElevator { ...@@ -18,7 +17,6 @@ public class TestAutomaticElevator {
@Test @Test
@Order(0) @Order(0)
@Disabled
@DisplayName("Elevator simulator - automatique mode") @DisplayName("Elevator simulator - automatique mode")
public void testAutomaticElevator() throws Exception { public void testAutomaticElevator() throws Exception {
System.out.printf("\nElevator simulator - auto mode\n"); System.out.printf("\nElevator simulator - auto mode\n");
...@@ -43,7 +41,6 @@ public class TestAutomaticElevator { ...@@ -43,7 +41,6 @@ public class TestAutomaticElevator {
@Test @Test
@Order(10) @Order(10)
@Disabled
@DisplayName("Elevator simulator - step by step mode") @DisplayName("Elevator simulator - step by step mode")
public void testElevatorByStep() throws Exception { public void testElevatorByStep() throws Exception {
System.out.printf("\nElevator simulator - step by step mode\n"); System.out.printf("\nElevator simulator - step by step mode\n");
...@@ -73,7 +70,6 @@ public class TestAutomaticElevator { ...@@ -73,7 +70,6 @@ public class TestAutomaticElevator {
@Test @Test
@Order(20) @Order(20)
@Disabled
@DisplayName("Elevator simulator - position by step") @DisplayName("Elevator simulator - position by step")
public void testElevatorPositionByStep() throws Exception { public void testElevatorPositionByStep() throws Exception {
System.out.printf("\nElevator simulator - position by step\n"); System.out.printf("\nElevator simulator - position by step\n");
...@@ -111,29 +107,25 @@ public class TestAutomaticElevator { ...@@ -111,29 +107,25 @@ public class TestAutomaticElevator {
@Test @Test
@Order(30) @Order(30)
@Disabled
@DisplayName("Elevator simulator - door and command") @DisplayName("Elevator simulator - door and command")
public void testElevatorDoorsAndCommand() throws Exception { public void testElevatorDoorsAndCommand() throws Exception {
//3 étages en mode automatique
var e = new ElevatorSimulator(3, true); var e = new ElevatorSimulator(3, true);
int count = 0; int count = 0;
double currentFloor = 0; double currentFloor = 0;
// ouvrir les portes et activer la montée
System.out.printf("level = %3.2f\n", (double)count/15); System.out.printf("level = %3.2f\n", (double)count/15);
// e.openDoor(); e.openDoor();
// assertEquals(OPEN, e.getState()); assertEquals(OPEN,e.getState());
// e.halt();
// System.out.println(e.getState()); while(e.getState() == OPEN) {
// e.reset(); e.oneStep();
// System.out.println(e.getState()); }
// System.out.println(e.getEvents()); // activer la montée
e.up(); e.up();
//l'évolution de l'ascenseur //l'évolution de l'ascenseur
while (e.getState() == UP) { while (e.getState() == UP) {
//demande à s'arrêter au 2e étage //demander à s'arrêter au 2e
if(currentFloor + 1 == 1) if(currentFloor + 1 == 2)
e.stopNext(); e.stopNext();
for(int i = 0; i < 15; i++) { for(int i = 0; i < 15; i++) {
...@@ -147,16 +139,15 @@ public class TestAutomaticElevator { ...@@ -147,16 +139,15 @@ public class TestAutomaticElevator {
} }
} }
// l'ascenseur est au 2ème // l'ascenseur est au 2ème
assertEquals(1.0, e.getLevel()); assertEquals(2.0, e.getLevel());
// l'ascenseur a a entraîné l'ouverture des portes // l'ascenseur a a entraîné l'ouverture des portes
assertEquals(OPEN, e.getState()); assertEquals(OPEN, e.getState());
// les étapes // les étapes
assertEquals("-S0-U0-U1-O2", e.getEvents()); assertEquals("-S0-O0-S0-U0-U1-O2", e.getEvents());
} }
@Test @Test
@Order(40) @Order(40)
@Disabled
@DisplayName("Elevator simulator - reset") @DisplayName("Elevator simulator - reset")
public void testElevatorReset() throws Exception { public void testElevatorReset() throws Exception {
//3 étages en mode automatique //3 étages en mode automatique
......
package elevator; package elevator;
import static elevatorSimulator.State.OPEN; import static elevatorSimulator.State.OPEN;
import static elevatorSimulator.State.STOP;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
...@@ -12,6 +12,7 @@ import org.junit.jupiter.api.Test; ...@@ -12,6 +12,7 @@ import org.junit.jupiter.api.Test;
import elevator.Scheduler.Direction; import elevator.Scheduler.Direction;
import elevatorSimulator.ElevatorSimulator; import elevatorSimulator.ElevatorSimulator;
import elevatorSimulator.IElevator; import elevatorSimulator.IElevator;
import elevatorSimulator.State;
public class TestCC { public class TestCC {
@Test @Test
...@@ -20,20 +21,22 @@ public class TestCC { ...@@ -20,20 +21,22 @@ public class TestCC {
public void testCCRegisterFloorRequest() throws Exception { public void testCCRegisterFloorRequest() throws Exception {
IElevator e = new ElevatorSimulator(3, true); IElevator e = new ElevatorSimulator(3, true);
Scheduler s = new Scheduler(); Scheduler s = new Scheduler();
IControlCommand c = new ControlCommand(s,e,3); IControlCommand c = new CommandController(s,e,3);
// Un client au rez-de-chaussée s'appuie deux fois sur le bouton monter // un client au rez-de-chaussée s'appuie deux fois sur le bouton monter
c.registerFloorRequest(0, Direction.UP); c.registerFloorRequest(0, Direction.UP);
c.registerFloorRequest(0, Direction.UP); c.registerFloorRequest(0, Direction.UP);
assertThat(((ControlCommand) c).getScheduler().getFloorRequests()).hasSize(1); assertThat(((CommandController) c).getScheduler().getFloorRequests()).hasSize(1);
c.registerFloorRequest(1, Direction.UP); c.registerFloorRequest(1, Direction.UP);
c.registerFloorRequest(2, Direction.DOWN); c.registerFloorRequest(2, Direction.DOWN);
c.registerFloorRequest(3, Direction.DOWN); c.registerFloorRequest(3, Direction.DOWN);
assertThat(((ControlCommand) c).getScheduler().getFloorRequests()).hasSize(4); assertThat(((CommandController) c).getScheduler().getFloorRequests()).hasSize(4);
assertThat(((ControlCommand) c).getScheduler().getFloorRequests().get(2).getFloor()).isEqualTo(2); assertThat(((CommandController) c).getScheduler().getFloorRequests().get(2).getFloor()).isEqualTo(2);
assertThat(((ControlCommand) c).getScheduler().getFloorRequests().get(2).getDirection()).isEqualTo(Direction.DOWN); assertThat(((CommandController) c).getScheduler().getFloorRequests().get(2).getDirection()).isEqualTo(Direction.DOWN);
c.registerFloorRequest(4, Direction.DOWN);
assertThat(((CommandController) c).getScheduler().getFloorRequests()).hasSize(4);
} }
@Test @Test
...@@ -42,43 +45,44 @@ public class TestCC { ...@@ -42,43 +45,44 @@ public class TestCC {
public void testCCRegisterCabinRequest() throws Exception { public void testCCRegisterCabinRequest() throws Exception {
IElevator e = new ElevatorSimulator(3, true); IElevator e = new ElevatorSimulator(3, true);
Scheduler s = new Scheduler(); Scheduler s = new Scheduler();
IControlCommand c = new ControlCommand(s,e,3); IControlCommand c = new CommandController(s,e,3);
c.registerCabinRequest(0);
c.registerCabinRequest(0);
assertThat(((ControlCommand) c).getScheduler().getCabinRequests()).hasSize(1);
c.registerCabinRequest(1); c.registerCabinRequest(1);
c.registerCabinRequest(1);
assertThat(((CommandController) c).getScheduler().getCabinRequests()).hasSize(1);
c.registerCabinRequest(2); c.registerCabinRequest(2);
c.registerCabinRequest(3); c.registerCabinRequest(3);
assertThat(((ControlCommand) c).getScheduler().getCabinRequests()).hasSize(4); assertThat(((CommandController) c).getScheduler().getCabinRequests()).hasSize(3);
assertThat(((ControlCommand) c).getScheduler().getCabinRequests().get(2).getFloor()).isEqualTo(2); assertThat(((CommandController) c).getScheduler().getCabinRequests().get(1).getFloor()).isEqualTo(2);
assertThat(((ControlCommand) c).getScheduler().getCabinRequests().get(3).getFloor()).isEqualTo(3); assertThat(((CommandController) c).getScheduler().getCabinRequests().get(2).getFloor()).isEqualTo(3);
c.registerCabinRequest(5);
assertThat(((CommandController) c).getScheduler().getCabinRequests()).hasSize(3);
} }
@Test @Test
@Order(20) @Order(20)
@Disabled
@DisplayName("Control command - cancel requests") @DisplayName("Control command - cancel requests")
public void testCCCancelRequest() throws Exception { public void testCCCancelRequest() throws Exception {
IElevator e = new ElevatorSimulator(3, true); IElevator e = new ElevatorSimulator(3, true);
Scheduler s = new Scheduler(); Scheduler s = new Scheduler();
IControlCommand c = new ControlCommand(s,e,3); IControlCommand c = new CommandController(s,e,3);
c.registerCabinRequest(0); c.registerCabinRequest(0);
assertThat(((ControlCommand) c).getScheduler().getCabinRequests()).hasSize(1); assertThat(((CommandController) c).getScheduler().getCabinRequests()).hasSize(0);
c.cancelRequest(0, null); c.cancelRequest(0, null);
assertThat(((ControlCommand) c).getScheduler().getCabinRequests()).hasSize(0); assertThat(((CommandController) c).getScheduler().getCabinRequests()).hasSize(0);
c.registerFloorRequest(1, Direction.UP); c.registerFloorRequest(1, Direction.UP);
c.registerFloorRequest(1, Direction.DOWN); c.registerFloorRequest(1, Direction.DOWN);
c.registerCabinRequest(1); c.registerCabinRequest(1);
c.cancelRequest(1, Direction.UP); c.cancelRequest(1, Direction.UP);
c.registerFloorRequest(2, Direction.UP); c.registerFloorRequest(2, Direction.UP);
assertThat(((ControlCommand) c).getScheduler().getCabinRequests()).hasSize(0); assertThat(((CommandController) c).getScheduler().getCabinRequests()).hasSize(0);
assertThat(((ControlCommand) c).getScheduler().getFloorRequests()).hasSize(2); assertThat(((CommandController) c).getScheduler().getFloorRequests()).hasSize(1);
assertThat(((ControlCommand) c).getScheduler().getFloorRequests().get(1).getFloor()).isEqualTo(2); assertThat(((CommandController) c).getScheduler().getFloorRequests().get(0).getFloor()).isEqualTo(2);
} }
@Test @Test
...@@ -87,33 +91,247 @@ public class TestCC { ...@@ -87,33 +91,247 @@ public class TestCC {
public void testCCCheckAndProcess001() throws Exception { public void testCCCheckAndProcess001() throws Exception {
IElevator e = new ElevatorSimulator(5, true); IElevator e = new ElevatorSimulator(5, true);
Scheduler s = new Scheduler(); Scheduler s = new Scheduler();
IControlCommand c = new ControlCommand(s,e,3); IControlCommand c = new CommandController(s,e,5);
StopConditionListener stopConditionListener = () -> { StopConditionListener stopConditionListener = () -> {
// Implement your stop condition logic return ((CommandController) c).getCurrentFloor() == 5;
// For example, stop after a certain amount of time or based on some external condition
return ((ControlCommand) c).getCurrentFloor() + ((ControlCommand) c).getCurrentPosition()/15.0 == 5; // Stop after 5 seconds
}; };
((ControlCommand) c).setStopConditionListener(stopConditionListener); ((CommandController) c).setStopConditionListener(stopConditionListener);
// Create a separate thread to run checkAndProcess concurrently
Thread controlThread = new Thread((Runnable) c); Thread controlThread = new Thread((Runnable) c);
controlThread.start(); controlThread.start();
// Now, you can add new requests dynamically while checkAndProcess is running
c.registerFloorRequest(5, Direction.UP); c.registerFloorRequest(5, Direction.UP);
c.registerCabinRequest(3); c.registerCabinRequest(3);
try { try {
controlThread.join(); // Wait for the controlThread to finish controlThread.join();
} catch (InterruptedException e1) { } catch (InterruptedException e1) {
e1.printStackTrace(); e1.printStackTrace();
} }
assertEquals(OPEN, e.getState()); assertEquals(OPEN, e.getState());
// les étapes // les étapes
assertEquals("-S0-U0-U1-U2-O3-S3-U3-U4-O5", ((ElevatorSimulator) e).getEvents()); assertEquals("-S0-U0-U1-U2-O3-S3-U3-U4-O5", ((ElevatorSimulator) e).getEvents());
} }
@Test
@Order(40)
@DisplayName("Control command - checkAndProcess - case 2")
public void testCCCheckAndProcess002() throws Exception {
IElevator e = new ElevatorSimulator(5, true);
Scheduler s = new Scheduler();
IControlCommand c = new CommandController(s,e,5);
StopConditionListener stopConditionListener = () -> {
return ((CommandController) c).getCurrentFloor() == 3 && e.getState() == OPEN;
};
((CommandController) c).setStopConditionListener(stopConditionListener);
Thread controlThread = new Thread((Runnable) c);
controlThread.start();
c.registerFloorRequest(5, Direction.UP);
while(true) {
if( ((CommandController) c).getCurrentFloor()== 5
&& e.getState()==STOP) {
c.registerCabinRequest(3);
break;
}
}
try {
controlThread.join();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
assertEquals("-S0-U0-U1-U2-U3-U4-O5-S5-D5-D4-O3", ((ElevatorSimulator) e).getEvents());
}
@Test
@Order(50)
@DisplayName("Control command - checkAndProcess - case 3")
public void testCCCheckAndProcess003() throws Exception {
IElevator e = new ElevatorSimulator(3, true);
Scheduler s = new Scheduler();
IControlCommand c = new CommandController(s,e,3);
StopConditionListener stopConditionListener = () -> {
return ((CommandController) c).getCurrentFloor() == 3 && e.getState() == STOP;
};
((CommandController) c).setStopConditionListener(stopConditionListener);
Thread controlThread = new Thread((Runnable) c);
controlThread.start();
c.registerFloorRequest(3, Direction.UP);
while(true) {
if( ((CommandController) c).getCurrentFloor()== 3) {
c.registerCabinRequest(3);
assertThat(((CommandController) c).getScheduler().getCabinRequests()).hasSize(0);
break;
}
}
try {
controlThread.join();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
assertEquals("-S0-U0-U1-U2-O3-S3", ((ElevatorSimulator) e).getEvents());
}
@Test
@Order(60)
@DisplayName("Control command - checkAndProcess - case 4")
public void testCCCheckAndProcess004() throws Exception {
IElevator e = new ElevatorSimulator(5, true);
Scheduler s = new Scheduler();
IControlCommand c = new CommandController(s,e,5);
StopConditionListener stopConditionListener = () -> {
return ((CommandController) c).getCurrentFloor() == 5;
};
((CommandController) c).setStopConditionListener(stopConditionListener);
Thread controlThread = new Thread((Runnable) c);
controlThread.start();
c.registerCabinRequest(4);
while(true) {
if( ((CommandController) c).getCurrentPosition()> 3
&& e.getState()==STOP) {
c.registerCabinRequest(5);
break;
}
}
try {
controlThread.join();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
assertEquals("-S0-U0-U1-U2-U3-O4-S4-U4-O5", ((ElevatorSimulator) e).getEvents());
}
@Test
@Order(70)
@DisplayName("Control command - checkAndProcess - case 5")
public void testCCCheckAndProcess005() throws Exception {
IElevator e = new ElevatorSimulator(5, true);
Scheduler s = new Scheduler();
IControlCommand c = new CommandController(s,e,5);
StopConditionListener stopConditionListener = () -> {
return ((CommandController) c).getCurrentFloor() == 2 && ((CommandController) c).getCurrentDirection() == Direction.DOWN;
};
((CommandController) c).setStopConditionListener(stopConditionListener);
Thread controlThread = new Thread((Runnable) c);
controlThread.start();
c.registerCabinRequest(5);
while(true) {
if( ((CommandController) c).getCurrentFloor()== 5
&& e.getState()==STOP) {
c.registerCabinRequest(3);
break;
}
}
while(true) {
if( ((CommandController) c).getCurrentPosition() <= 3) {
c.registerCabinRequest(2);
break;
}
}
try {
controlThread.join();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
assertEquals("-S0-U0-U1-U2-U3-U4-O5-S5-D5-D4-O3-S3-D3-O2", ((ElevatorSimulator) e).getEvents());
}
@Test
@Order(80)
@DisplayName("Control command - checkAndProcess - case 6")
public void testCCCheckAndProcess006() throws Exception {
IElevator e = new ElevatorSimulator(5, true);
Scheduler s = new Scheduler();
IControlCommand c = new CommandController(s,e,5);
StopConditionListener stopConditionListener = () -> {
return e.getState() == State.ERROR;
};
((CommandController) c).setStopConditionListener(stopConditionListener);
Thread controlThread = new Thread((Runnable) c);
controlThread.start();
c.registerCabinRequest(5);
while(true) {
if( ((CommandController) c).getCurrentFloor()== 3) {
e.halt();
break;
}
}
try {
controlThread.join();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
assertEquals("-S0-U0-U1-U2-U3-E3", ((ElevatorSimulator) e).getEvents());
}
@Test
@Order(80)
@DisplayName("Control command - checkAndProcess - case 7")
public void testCCCheckAndProcess007() throws Exception {
IElevator e = new ElevatorSimulator(5, true);
Scheduler s = new Scheduler();
IControlCommand c = new CommandController(s,e,5);
StopConditionListener stopConditionListener = () -> {
return ((CommandController) c).getCurrentDirection() == Direction.DOWN && ((CommandController) c).getCurrentPosition() == 0;
};
((CommandController) c).setStopConditionListener(stopConditionListener);
Thread controlThread = new Thread((Runnable) c);
controlThread.start();
c.registerCabinRequest(5);
while(true) {
if( ((CommandController) c).getCurrentFloor()== 3) {
e.halt();
break;
}
}
try {
Thread.sleep(1000);
e.reset();
controlThread.join();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
assertEquals("-S0-U0-U1-U2-U3-E3-R3-R2-R1-S0", ((ElevatorSimulator) e).getEvents());
}
} }
...@@ -3,13 +3,14 @@ package elevator; ...@@ -3,13 +3,14 @@ package elevator;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import elevator.Scheduler.CabinRequest; import elevator.Scheduler.CabinRequest;
import elevator.Scheduler.Direction;
import elevator.Scheduler.FloorRequest; import elevator.Scheduler.FloorRequest;
import elevatorSimulator.State;
public class TestScheduler { public class TestScheduler {
...@@ -30,6 +31,12 @@ public class TestScheduler { ...@@ -30,6 +31,12 @@ public class TestScheduler {
assertThat(s.getCabinRequests().get(0).getFloor()).isEqualTo(2); assertThat(s.getCabinRequests().get(0).getFloor()).isEqualTo(2);
assertThat(s.getCabinRequests().get(1).getFloor()).isEqualTo(3); assertThat(s.getCabinRequests().get(1).getFloor()).isEqualTo(3);
//il ne peut y avoir qu'une demande de déplacement par niveau
s.registerCabinRequest(new CabinRequest(3));
assertThat(s.getCabinRequests()).hasSize(2);
assertThat(s.getCabinRequests().get(0).getFloor()).isEqualTo(2);
assertThat(s.getCabinRequests().get(1).getFloor()).isEqualTo(3);
//scheduler registre un ordre monter/descendre vers le rez-de-chaussée //scheduler registre un ordre monter/descendre vers le rez-de-chaussée
s.registerCabinRequest(new CabinRequest(0)); s.registerCabinRequest(new CabinRequest(0));
assertThat(s.getCabinRequests().get(2).getFloor()).isEqualTo(0); assertThat(s.getCabinRequests().get(2).getFloor()).isEqualTo(0);
...@@ -43,61 +50,116 @@ public class TestScheduler { ...@@ -43,61 +50,116 @@ public class TestScheduler {
assertThat(s.getFloorRequests()).hasSize(0); assertThat(s.getFloorRequests()).hasSize(0);
//scheduler registre un ordre monter au rez-de-chaussée //scheduler registre un ordre pour monter au rez-de-chaussée
s.registerFloorRequest(new FloorRequest(0, State.UP)); s.registerFloorRequest(new FloorRequest(0, Direction.UP));
//scheduler registre un ordre monter au 1e étage //scheduler registre un ordre pour monter au 1e étage
s.registerFloorRequest(new FloorRequest(1, State.UP)); s.registerFloorRequest(new FloorRequest(1, Direction.UP));
//scheduler registre un ordre descendre au 1e étage //scheduler registre un ordre pour descendre au 1e étage
s.registerFloorRequest(new FloorRequest(1, State.DOWN)); s.registerFloorRequest(new FloorRequest(1, Direction.DOWN));
assertThat(s.getFloorRequests()).hasSize(3); assertThat(s.getFloorRequests()).hasSize(2);
assertThat(s.getFloorRequests().get(0).getFloor()).isEqualTo(0); assertThat(s.getFloorRequests().get(0).getFloor()).isEqualTo(0);
assertThat(s.getFloorRequests().get(0).getDirection()).isEqualTo(State.UP); assertThat(s.getFloorRequests().get(0).getDirection()).isEqualTo(Direction.UP);
// Il ne peut y avoir qu'un appel pour monter ou pour descendre par niveau.
assertThat(s.getFloorRequests().get(1).getFloor()).isEqualTo(1); assertThat(s.getFloorRequests().get(1).getFloor()).isEqualTo(1);
assertThat(s.getFloorRequests().get(1).getDirection()).isEqualTo(State.UP); assertThat(s.getFloorRequests().get(1).getDirection()).isEqualTo(Direction.UP);
assertThat(s.getFloorRequests().get(2).getFloor()).isEqualTo(1); s.cancelRequest(1, Direction.UP);
assertThat(s.getFloorRequests().get(2).getDirection()).isEqualTo(State.DOWN); assertThat(s.getFloorRequests()).hasSize(1);
assertThat(s.getFloorRequests().get(0).getFloor()).isEqualTo(0);
assertThat(s.getFloorRequests().get(0).getDirection()).isEqualTo(Direction.UP);
s.cancelFloorRequest(1, State.UP); //scheduler registre un ordre descendre au 1e étage
s.registerFloorRequest(new FloorRequest(1, Direction.DOWN));
assertThat(s.getFloorRequests()).hasSize(2); assertThat(s.getFloorRequests()).hasSize(2);
assertThat(s.getFloorRequests().get(1).getFloor()).isEqualTo(1); assertThat(s.getFloorRequests().get(1).getFloor()).isEqualTo(1);
assertThat(s.getFloorRequests().get(1).getDirection()).isEqualTo(State.DOWN); assertThat(s.getFloorRequests().get(1).getDirection()).isEqualTo(Direction.DOWN);
} }
@Test @Test
@Order(20) @Order(20)
@DisplayName("Scheduler - register and calculate Next Floor") @DisplayName("Scheduler - register and calculate Next Floor - Part 1")
public void testRegisterAndCalculateNextFloor() { public void testRegisterAndCalculateNextFloor01() {
Scheduler scheduler = new Scheduler(); Scheduler scheduler = new Scheduler();
// Register floor requests // register floor requests
scheduler.registerFloorRequest(new FloorRequest(3, State.UP)); scheduler.registerFloorRequest(new FloorRequest(3, Direction.UP));
scheduler.registerFloorRequest(new FloorRequest(1, State.DOWN)); scheduler.registerFloorRequest(new FloorRequest(1, Direction.DOWN));
scheduler.registerFloorRequest(new FloorRequest(2, State.UP)); scheduler.registerFloorRequest(new FloorRequest(2, Direction.UP));
// Calculate next floor when the elevator is at floor 2 going up // Calculate next floor when the elevator is at floor 2 going up
int nextFloor = scheduler.calculateNextFloor(2, State.UP); int nextFloor = scheduler.calculateNextFloor(2, Direction.UP);
assertEquals(3, nextFloor); assertEquals(3, nextFloor);
// Calculate next floor when the elevator is at floor 3 going down // Calculate next floor when the elevator is at floor 3 going down
nextFloor = scheduler.calculateNextFloor(3, State.DOWN); nextFloor = scheduler.calculateNextFloor(3, Direction.DOWN);
assertEquals(2, nextFloor); assertEquals(1, nextFloor);
// Register a cabin request
scheduler.registerCabinRequest(new CabinRequest(4));
// Calculate next floor when the elevator is at floor 1 going up // Calculate next floor when the elevator is at floor 1 going up
nextFloor = scheduler.calculateNextFloor(1, State.UP); nextFloor = scheduler.calculateNextFloor(1, Direction.UP);
assertEquals(2, nextFloor); assertEquals(2, nextFloor);
// Cancel a floor request // Cancel a floor request
scheduler.cancelFloorRequest(1, State.DOWN); scheduler.cancelRequest(1, Direction.DOWN);
// Calculate next floor when the elevator is at floor 1 going up (after canceling) // Calculate next floor when the elevator is at floor 1 going up (after canceling)
nextFloor = scheduler.calculateNextFloor(1, State.UP); nextFloor = scheduler.calculateNextFloor(1, Direction.UP);
assertEquals(2, nextFloor); assertEquals(2, nextFloor);
} }
@Test
@Order(30)
@DisplayName("Scheduler - register and calculate Next Floor - Part 2")
public void testRegisterAndCalculateNextFloor02() {
Scheduler scheduler = new Scheduler();
// L'ascenseur monte et il reste encore des requêtes à traiter dans les étages supérieurs
scheduler.registerFloorRequest(new FloorRequest(3, Direction.UP));
scheduler.registerFloorRequest(new FloorRequest(1, Direction.DOWN));
scheduler.registerFloorRequest(new FloorRequest(2, Direction.UP));
scheduler.registerFloorRequest(new FloorRequest(5, Direction.UP));
int nextFloor = scheduler.calculateNextFloor(2, Direction.UP);
assertEquals(3, nextFloor);
nextFloor = scheduler.calculateNextFloor(3, Direction.UP);
assertEquals(5, nextFloor);
// L'ascenseur monte et des requêtes vers les étages inférieurs arrivent
scheduler.registerCabinRequest(new CabinRequest(1));
nextFloor = scheduler.calculateNextFloor(3, Direction.UP);
assertEquals(5, nextFloor);
// L'ascenseur est au premier étage et monte vers le cinquième, lorsque arrive une requête à la montée au 3ème étage.
scheduler.cancelRequest(3, Direction.UP);
scheduler.cancelRequest(1, Direction.DOWN);
scheduler.cancelRequest(2, Direction.UP);
scheduler.registerFloorRequest(new FloorRequest(1, Direction.UP));
assertThat(scheduler.getFloorRequests()).hasSize(2);
assertThat(scheduler.getFloorRequests().get(0).getFloor()).isEqualTo(5);
assertThat(scheduler.getFloorRequests().get(0).getDirection()).isEqualTo(Direction.UP);
assertThat(scheduler.getFloorRequests().get(1).getFloor()).isEqualTo(1);
assertThat(scheduler.getFloorRequests().get(1).getDirection()).isEqualTo(Direction.UP);
nextFloor = scheduler.calculateNextFloor(1, Direction.UP);
assertEquals(5, nextFloor);
scheduler.registerCabinRequest(new CabinRequest(3));
nextFloor = scheduler.calculateNextFloor(1, Direction.UP);
assertEquals(3, nextFloor);
nextFloor = scheduler.calculateNextFloor(4, Direction.UP);
assertEquals(5, nextFloor);
// L'ascenseur est au troisième et à la montée et un utilisateur en cabine souhaite aller au rez-de-chaussée.
nextFloor = scheduler.calculateNextFloor(3, Direction.UP);
scheduler.registerCabinRequest(new CabinRequest(0));
assertEquals(5, nextFloor);
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment