A scratch kotlin app which simulates a Lift system using Kotlin
-
The primary classes are
LiftCarandLiftController. The LiftController manages all the LiftCars and the Floors. -
Every
Floorhas an up FloorButton and a down FloorButton. -
Every
LiftCarhas an array ofLiftButtons. -
LiftButtonandFloorButtonare the places from where aLiftRequestoriginates. -
RequestHandlerdecides how to handle the requests originating from the liftbuttons and floorbuttons and which lift to assign that request to.
Initialises LiftCars and RequestHandler and takes care of the tick of the system.
A LiftCar looks like this
interface ILiftCar {
fun takeRequest(request: LiftRequest)
fun tick()
fun getCurrentFloor() : Float
}- Takes care of processing the request using takeRequest() which gets called by a higher order container, which in our case is
LiftControllerwhenever aLiftRequestis raised. - Initialises the array of floor buttons to be used in that LiftCar.
- Handles the tick of the system
There can be many types of RequestHandler, for now we have SimpleRequestHandler which assigns every request to the first LiftCar.
RequestHandler assigns the request to a lift by calling liftCar.takeRequest().
A Button has a RequestHandler object and the floor number for/on which this button is meant to be.
A LiftRequest represents the request object and contains:
- Reference to the source
LiftButton- can be removed and instead a observer/listener pattern can be used - The floor number of the request
- The RequestState
enum class RequestState {INITIATED, COMPLETED}Button uses a factory method pattern to create a LiftRequest.
abstract class Button(
val floor: Int,
private var requestHandler: RequestHandler,
var buttonState : ButtonState = ButtonState.OFF) {
abstract fun createRequest() : LiftRequest
open fun press() {
if (buttonState == ButtonState.ON) {
// Do nothing
return
}
buttonState = ButtonState.ON
val request = createRequest()
this.requestHandler.onNewRequest(request)
}
}
// LiftButton creates a `ExitRequest`
class LiftButton: Button {
constructor(floor: Int, requestHandler: RequestHandler) :super(floor, requestHandler)
override fun createRequest(): LiftRequest {
return ExitRequest(floor, this)
}
}
// FloorButton creates a EnterRequest
class FloorButton(floor: Int, private val direction: Direction, requestHandler: RequestHandler) : Button(floor, requestHandler) {
override fun createRequest(): LiftRequest {
return EnterRequest(floor, direction, this)
}
}LiftCar maintains 2 floor numbers tl and tu which are the lower and upper targets(floors) for that LiftCar which change on the basis of current Requests that the LiftCar is processing.
takeRequest() [link]
- Add the request to the requestMap
// TODO
//2. (Only EnterRequest)Decide the direction if the lift is STOPPED and the direction is not known. (only EnterRequest)
// 1. If the lift is at the same floor of this new request; the request direction
// 2.
//3. Modify the tl and tu
tick() [link]
-
If the direction is
UPdoposition += 1 -
If the direction is
DOWNdoposition -= 1 -
If needsToBeStopped(); stop the lift and mark the requests ending here as completed. Stop when:
- If the lift is at a bound (tl or tu)
- If any of the ExitRequest is for the current floor
- If any of the EnterRequest is for the current floor and is for the same direction in which the lift is flowing
-
If STOPPED
- Wait for some time and then try to getDirection using any pending requests
- If the direction is found, start moving as keep trying to getDirection