Skip to content

Instantly share code, notes, and snippets.

@msoedov
Created September 18, 2018 17:22
Show Gist options
  • Save msoedov/e8c77a5132e4eaf6e10ab3b1fea671e3 to your computer and use it in GitHub Desktop.
Save msoedov/e8c77a5132e4eaf6e10ab3b1fea671e3 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"math"
"sync"
"time"
log "github.com/Sirupsen/logrus"
)
// ElManager documents here
type ElManager struct {
list []*Elevator
}
func (self *ElManager) init(els ...*Elevator) *ElManager {
self.list = els
return self
}
func NewElManager(els ...*Elevator) *ElManager {
return new(ElManager).init(els...)
}
func (self *ElManager) Request(target int) (*Elevator, bool) {
var minDistance float64 = math.MaxFloat64
var closestElevator *Elevator
for _, el := range self.list {
if !el.Idle() {
continue
}
distance := math.Abs(float64(target - el.CurrentFloor))
if distance < minDistance {
minDistance = distance
closestElevator = el
}
}
if closestElevator != nil {
log.WithFields(log.Fields{"found": closestElevator, "toFloor": target}).Info("Mng.Request")
ok := closestElevator.Request(target)
return closestElevator, ok
}
log.WithFields(log.Fields{"target": target}).Info("Could not route to")
return nil, false
}
// Elevator documents here
type Elevator struct {
CurrentFloor int
targetFloor int
maxFloor int
minFloor int
idle bool
lock sync.Mutex
}
func (self *Elevator) init(init, min, max int) *Elevator {
if min > max {
panic("Mix grt than max")
}
if init > max || min > init {
panic("Init floor is not in range")
}
self.CurrentFloor = init
self.maxFloor = max
self.minFloor = min
self.idle = true
return self
}
func (self *Elevator) validateRange(val int) bool {
if val > self.maxFloor || val < self.minFloor {
return false
}
return true
}
func (self *Elevator) move(to int) {
self.lock.Lock()
defer self.lock.Unlock()
self.idle = false
distance := math.Abs(float64(to - self.CurrentFloor))
time.Sleep(time.Duration(distance) * time.Second)
self.CurrentFloor = to
self.idle = true
return
}
func (self *Elevator) Idle() bool {
// self.lock.Lock()
// defer self.lock.Unlock()
return self.idle
}
func (self *Elevator) Request(floor int) bool {
if ok := self.validateRange(floor); !ok {
return ok
}
log.WithFields(log.Fields{"floor": floor}).Info("Requested")
go self.move(floor)
return true
}
func (self *Elevator) SendTo(target int) bool {
if ok := self.validateRange(target); !ok {
return ok
}
go self.move(target)
log.WithFields(log.Fields{"targetFloor": target}).Info("SendTo")
return true
}
func NewElevator(init, min, max int) *Elevator {
return new(Elevator).init(init, min, max)
}
func main() {
mngr := NewElManager(NewElevator(1, 0, 18), NewElevator(2, 0, 18), NewElevator(3, 0, 18), NewElevator(4, 0, 18))
el, _ := mngr.Request(10)
el.SendTo(3)
el, _ = mngr.Request(12)
el.SendTo(5)
el, _ = mngr.Request(14)
el.SendTo(-1)
el, _ = mngr.Request(6)
el, _ = mngr.Request(-1)
fmt.Printf("mngr %#v\n", mngr)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment