Created
September 18, 2018 17:22
-
-
Save msoedov/e8c77a5132e4eaf6e10ab3b1fea671e3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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