Skip to content

Commit 2bb478a

Browse files
committed
distance calculation bug + enhancements
1 parent b4c68e6 commit 2bb478a

5 files changed

Lines changed: 93 additions & 52 deletions

File tree

elevator_system/elevator.go

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,55 +7,55 @@ import (
77

88
type Elevator struct {
99
ID int
10-
Capacity int
1110
CurrentFloor int
12-
CurrentDirection Directions
13-
CurrentLoad int
11+
CurrentDirection Direction
1412
ElevatorPanel *ElevatorPanel
1513
Destinations []int
16-
sync.Mutex
14+
sync.Mutex // helps for locks over go routines
1715
}
1816

1917
func NewElevator(id int) *Elevator {
20-
return &Elevator{ID: id, Capacity: 10, CurrentFloor: 1, CurrentDirection: Still, CurrentLoad: 0, ElevatorPanel: NewElevatorPanel(id)}
18+
return &Elevator{
19+
ID: id,
20+
CurrentFloor: 1,
21+
CurrentDirection: Still,
22+
ElevatorPanel: NewElevatorPanel(id),
23+
}
2124
}
2225

2326
func (e *Elevator) AddDestination(destinationFloor int) {
2427
e.Lock()
28+
defer e.Unlock()
2529
e.ElevatorPanel.AddDestinationFloor(destinationFloor)
2630
e.Destinations = append(e.Destinations, destinationFloor)
2731
fmt.Printf("Elevator %d received destination floor %d\n", e.ID, destinationFloor)
28-
e.Unlock()
2932
}
3033

3134
func (e *Elevator) RemoveDestination(destinationFloor int) {
3235
e.Lock()
36+
defer e.Unlock()
3337
for i, floor := range e.Destinations {
3438
if floor == destinationFloor {
3539
e.Destinations = append(e.Destinations[:i], e.Destinations[i+1:]...)
3640
e.ElevatorPanel.RemoveDestinationFloor(destinationFloor)
3741
break
3842
}
3943
}
40-
e.Unlock()
44+
fmt.Printf("Elevator %d removed destination floor %d\n", e.ID, destinationFloor)
4145
}
4246

4347
func (e *Elevator) UpdateCurrentFloor(newFloor int) {
4448
e.Lock()
49+
defer e.Unlock()
50+
fmt.Printf("Elevator %d moving from floor %d to floor %d\n", e.ID, e.CurrentFloor, newFloor)
4551
e.CurrentFloor = newFloor
46-
e.Unlock()
47-
}
48-
49-
func (e *Elevator) UpdateCurrentLoad(newLoad int) {
50-
e.Lock()
51-
e.CurrentLoad = newLoad
52-
e.Unlock()
5352
}
5453

55-
func (e *Elevator) UpdateCurrentDirection(newDirection Directions) {
54+
func (e *Elevator) UpdateCurrentDirection(newDirection Direction) {
5655
e.Lock()
56+
defer e.Unlock()
57+
fmt.Printf("Elevator %d changing direction from %s to %s\n", e.ID, e.CurrentDirection, newDirection)
5758
e.CurrentDirection = newDirection
58-
e.Unlock()
5959
}
6060

6161
func (e *Elevator) FarthestDestination() int {
@@ -81,3 +81,16 @@ func (e *Elevator) NearestDestination() int {
8181

8282
return minFloor
8383
}
84+
85+
func (e *Elevator) PrintState() {
86+
e.Lock()
87+
defer e.Unlock()
88+
89+
fmt.Printf(
90+
"Elevator %d | Current Floor: %d | Direction: %s | Destinations: %v\n",
91+
e.ID,
92+
e.CurrentFloor,
93+
e.CurrentDirection,
94+
e.Destinations,
95+
)
96+
}

elevator_system/elevatorManager.go

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,20 @@ func NewElevatorManager(building *Building) *ElevatorManager {
1515

1616
func (em *ElevatorManager) OperateAllElevators() {
1717
for _, elevator := range em.Building.Elevators {
18-
go em.OperateElevator(elevator)
18+
elevator.PrintState()
19+
go em.OperateElevator(elevator) // go thread for each elevator
1920
}
2021
}
2122

2223
func (em *ElevatorManager) OperateElevator(elevator *Elevator) {
23-
for {
24-
elevator.Lock()
24+
for { // infinte loop to keep elevator operating(real world scenario -> event can come any time)
25+
2526
if len(elevator.Destinations) == 0 {
2627
elevator.CurrentDirection = Still
27-
elevator.Unlock()
2828
continue
2929
}
3030

3131
sort.Ints(elevator.Destinations)
32-
fmt.Printf("Elevator %d is starting from %d and going to %s\n", elevator.ID, elevator.CurrentFloor, elevator.CurrentDirection)
3332

3433
if elevator.CurrentDirection == Up {
3534
em.MoveElevatorUp(elevator)
@@ -38,16 +37,17 @@ func (em *ElevatorManager) OperateElevator(elevator *Elevator) {
3837
} else {
3938
em.DecideDirection(elevator)
4039
}
41-
elevator.Unlock()
40+
4241
}
4342
}
4443

44+
// move to nearest request
4545
func (em *ElevatorManager) DecideDirection(elevator *Elevator) {
46-
currentFloor := elevator.CurrentFloor
4746
if len(elevator.Destinations) == 0 {
4847
return
4948
}
5049

50+
currentFloor := elevator.CurrentFloor
5151
nearestDestination := elevator.Destinations[0]
5252
if nearestDestination > currentFloor {
5353
elevator.UpdateCurrentDirection(Up)
@@ -62,10 +62,11 @@ func (em *ElevatorManager) MoveElevatorUp(elevator *Elevator) {
6262
for i := 0; i < len(elevator.Destinations); i++ {
6363
destination := elevator.Destinations[i]
6464
if destination >= elevator.CurrentFloor {
65-
fmt.Printf("Elevator %d moving up to floor %d\n", elevator.ID, destination)
6665
elevator.UpdateCurrentFloor(destination)
6766
elevator.RemoveDestination(destination)
68-
i--
67+
i-- // because we have removed an element from the slice
68+
} else {
69+
// skip destinations below current floor
6970
}
7071
}
7172

@@ -80,9 +81,10 @@ func (em *ElevatorManager) MoveElevatorDown(elevator *Elevator) {
8081
for i := len(elevator.Destinations) - 1; i >= 0; i-- {
8182
destination := elevator.Destinations[i]
8283
if destination <= elevator.CurrentFloor {
83-
fmt.Printf("Elevator %d moving down to floor %d\n", elevator.ID, destination)
8484
elevator.UpdateCurrentFloor(destination)
8585
elevator.RemoveDestination(destination)
86+
} else {
87+
// skip destinations above current floor
8688
}
8789
}
8890

@@ -93,7 +95,8 @@ func (em *ElevatorManager) MoveElevatorDown(elevator *Elevator) {
9395
}
9496
}
9597

96-
func (em *ElevatorManager) AssignElevator(floor int, direction Directions) (bestElevator *Elevator) {
98+
// manager will assign the best elevator for the hall call request
99+
func (em *ElevatorManager) AssignElevator(floor int, direction Direction) (bestElevator *Elevator) {
97100
bestElevator = em.FindClosestElevator(floor, direction)
98101
if bestElevator != nil {
99102
bestElevator.AddDestination(floor)
@@ -102,41 +105,66 @@ func (em *ElevatorManager) AssignElevator(floor int, direction Directions) (best
102105
return bestElevator
103106
}
104107

105-
func (em *ElevatorManager) FindClosestElevator(floor int, direction Directions) *Elevator {
108+
// mamnager will find best elevator for the hall call request
109+
func (em *ElevatorManager) FindClosestElevator(floor int, direction Direction) *Elevator {
106110
var closestElevator *Elevator
107111
minDistance := int(1e9)
108112

109113
for _, elevator := range em.Building.Elevators {
110114
elevator.Lock()
111115
distance := em.calculateDistance(elevator, floor, direction)
116+
elevator.Unlock()
112117

113118
if distance < minDistance {
114119
minDistance = distance
115120
closestElevator = elevator
116121
}
117-
118-
elevator.Unlock()
119122
}
123+
120124
return closestElevator
121125
}
122126

123-
func (em *ElevatorManager) calculateDistance(elevator *Elevator, floor int, direction Directions) int {
127+
func (em *ElevatorManager) calculateDistance(elevator *Elevator, floor int, direction Direction) int {
124128
currentFloor := elevator.CurrentFloor
125129
currentDirection := elevator.CurrentDirection
126130

127-
if currentDirection == Still || (currentDirection == direction && ((direction == Up && floor > currentFloor) || (direction == Down && floor < currentFloor))) {
131+
fmt.Println("Calculating distance for Elevator", elevator.ID, "at floor", currentFloor, "going", currentDirection, "to floor", floor, "going", direction)
132+
133+
// Case 1: Elevator is idle
134+
if currentDirection == Still || len(elevator.Destinations) == 0 {
128135
return abs(floor - currentFloor)
129136
}
130137

138+
// Case 2: Elevator moving in same direction
139+
if currentDirection == direction {
140+
if (direction == Up && floor >= currentFloor) || (direction == Down && floor <= currentFloor) {
141+
// Request is ahead in same direction → pick up immediately
142+
return abs(floor - currentFloor)
143+
} else {
144+
// Request is behind → calculate distance after finishing current sweep
145+
if direction == Up {
146+
farthest := elevator.FarthestDestination()
147+
return abs(farthest - currentFloor) + abs(farthest - floor)
148+
} else { // Down
149+
nearest := elevator.NearestDestination()
150+
return abs(currentFloor - nearest) + abs(floor - nearest)
151+
}
152+
}
153+
}
154+
155+
// Case 3: Elevator moving in opposite direction
131156
if (currentDirection == Up && direction == Down) || (currentDirection == Down && direction == Up) {
132157
if currentDirection == Up {
133-
return abs(elevator.FarthestDestination()-currentFloor) + abs(elevator.FarthestDestination()-floor)
134-
} else {
135-
return abs(elevator.NearestDestination()-currentFloor) + abs(elevator.NearestDestination()-floor)
158+
farthest := elevator.FarthestDestination()
159+
return abs(farthest - currentFloor) + abs(farthest - floor)
160+
} else { // Down
161+
nearest := elevator.NearestDestination()
162+
return abs(currentFloor - nearest) + abs(floor - nearest)
136163
}
137164
}
138165

139-
return 100
166+
// Fallback: very far / unlikely elevator
167+
return 1000
140168
}
141169

142170
func abs(x int) int {

elevator_system/go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ module lld_go_elevator_system
22

33
go 1.22.5
44

5-
// elevatorPanel -> inside, ouside
6-
// elevator care
5+
// elevatorPanel -> inside, outside
6+
// elevator core
77
// floor
88
// building
99
// elevator system

elevator_system/hall_panel.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,29 @@ package main
22

33
import "fmt"
44

5-
type Directions string
5+
type Direction string
66

77
const (
8-
Up Directions = "Up"
9-
Down Directions = "Down"
10-
Still Directions = "Still"
8+
Up Direction = "Up"
9+
Down Direction = "Down"
10+
Still Direction = "Still"
1111
)
1212

1313
type HallPanel struct {
1414
PanelID int
15-
DirectionInstruction Directions
15+
DirectionInstruction Direction
1616
SourceFloor int
1717
}
1818

1919
func NewHallPanel(panelID int, sourceFloor int) *HallPanel {
2020
return &HallPanel{PanelID: panelID, SourceFloor: sourceFloor, DirectionInstruction: Still}
2121
}
2222

23-
func (h *HallPanel) SetDirectionInstructions(directionInstruction Directions) {
23+
func (h *HallPanel) SetDirectionInstructions(directionInstruction Direction) {
2424
h.DirectionInstruction = directionInstruction
2525
}
2626

27-
func (h *HallPanel) RequestElevator(manager *ElevatorManager, direction Directions) (elevator *Elevator) {
27+
func (h *HallPanel) RequestElevator(manager *ElevatorManager, direction Direction) (elevator *Elevator) {
2828
fmt.Printf("Panel %d requesting elevator with direction %s from floor %d\n", h.PanelID, direction, h.SourceFloor)
2929
return manager.AssignElevator(h.SourceFloor, direction)
3030
}

elevator_system/main.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ func main() {
1111
wg.Add(1)
1212
go func() {
1313
defer wg.Done()
14-
elevator := building.Floors[1].HallPanels[1].RequestElevator(manager, Up)
15-
elevator.AddDestination(6)
14+
elevator := building.Floors[1].HallPanels[1].RequestElevator(manager, Up) // request elevator from floor 1 to go Up -> hall call
15+
elevator.AddDestination(6) // destination floor 6
1616
}()
1717

1818
wg.Add(1)
1919
go func() {
2020
defer wg.Done()
21-
elevator := building.Floors[8].HallPanels[2].RequestElevator(manager, Down)
22-
elevator.AddDestination(7)
21+
secondElevator := building.Floors[8].HallPanels[2].RequestElevator(manager, Down)
22+
secondElevator.AddDestination(7)
2323
}()
2424

2525
wg.Add(1)
@@ -29,9 +29,9 @@ func main() {
2929
thirdElevator.AddDestination(12)
3030
}()
3131

32-
wg.Wait()
32+
wg.Wait() // wait unitl all requests are done
3333

34-
go manager.OperateAllElevators()
34+
go manager.OperateAllElevators() // start operating/simulating all elevators
3535

36-
select {}
36+
select {} // it is needed for blocking main for exiting as we have spawned goroutines
3737
}

0 commit comments

Comments
 (0)