Description:
Given a parking lot containing multiple levels and each level containing multiple rows and each row in turn containing multiple spots. The questions is to determine if there are enough spots to check if a vehicle can be parked.
Which object is responsible to determine if there is enough spots, I mean its the parking lot object which is supposed to receive the first query but ultimately it should be either level or row to implement the actual algorithm, right?
Its not about a single class but system as a whole.
Requirement:
The parking lot has multiple levels. Each level has multiple rows of spots.
The parking lot can park motorcycles, cars, and buses.
The parking lot has motorcycle spots, compact spots, and large spots.
A motorcycle can park in any spot.
A car can park in either a single compact spot or a single large spot.
A bus can park in five large spots that are consecutive and within the same row. It cannot park in small spots.
The question is that the given system should be able to given answer to the queries like:
Given a car the system should be able to tell if there is a spot for car or not, if yes the answer should be something like:
There is a spot on level x row y and spot z
The issues I face while solving such problems is where to start and how to find correct objects which should represent the domain correctly.
I did try to start somewhere and below is my code:
Enum Size {
SMALL,
COMPACT,
LARGE
}
private class Spot {
private boolean empty;
private int number;
private Size size;
Spot(Size size, int number) {
this.size = size;
}
full() {
this.empty = false;
}
empty() {
this.empty = true;
}
status() {
return this.empty;
}
boolean canPark(Vehicle vehicle) {
return false;
}
}
class LargeSpot extends Spot {
boolean canPark(Vehicle vehicle) {
return
vehicle.size() == Size.LARGE ||
vehicle.size() == Size.COMPACT ||
vehicle.size() == Size.SMALL;
}
}
class CompactSpot extends Spot {
boolean canPark(Vehicle vehicle) {
return
vehicle.size() == Size.COMPACT ||
vehicle.size() == Size.SMALL;
}
}
class SmallSpot extends Spot {
boolean canPark(Vehicle vehicle) {
return vehicle.size() == Size.SMALL;
}
}
private class Row {
private ArrayList<Spot> spots;
Row(List<Spot> spots) {
this.spots = spots;
}
void spot(Spot spot) {
this.spots.add(spot);
}
List<Spot> getSpots(Vehicle vehicle) {
List<Spot> emptySpots = new ArrayList<>();
if (vehicle.size() == Size.LARGE) {
// five consecutive large spots
int length = spots.size();
for (int i = 0; i < length; i++) {
int j = 0;
for (; j < 5; j++) {
if (!spot.canPark(vehicle)) break; // break out of inner loop
}
if (j == 5) { // found five spots
for (int k = i; k < i + j; k++) {
emptySpots.add(spot);
}
i += j;
}
}
} else {
for (Spot spot : spots) {
if (spot.canPark(vehicle)) {
emptySpots.add(spot);
}
}
}
return emptySpots;
}
}
private class Level {
private final int number;
private final ArrayList<Row> rows;
Level(number, rows) {
this.number = number;
this.rows = rows;
}
}
class ParkingLot {
private List<Level> levels;
ParkingLot(List<Level> levels) {
this.levels = levels;
}
public String status(Vehicle vehicle) {
List<Spot> emptySpots = new ArrayList<>();
for (Level level : levels) {
for (Row : level.rows()) {
if (row.canPark(vehicle)) {
emptySpots.addAll(row.getSpots(vehicle));
}
}
}
return emptySpots;
}
}
public class Main {
private final List<Level> floors = new ArrayList<>();
floors.add(
new Level(
0,
new Row[4]{new SmallSpotSpot(), new CarSpot(), new CarSpot()}));
floors.add(
new Level(
1,
new Row[4]{
new LargeSpot(), new LargeSpot(), new LargeSpot(), new LargeSpot()}));
private final Lot lot = new ParkingLot(floors);
private final Car car = new Car(Size.Compact);
System.out.println(lot.status(car));
}
The code definitely broken at many places but the readers can get the faint idea what I am trying to achieve. Also, it can be seen parking Large vehicle is one of the pain points in designing a good solution.