Adds godoc to api package
This commit is contained in:
parent
6d2e25b0d8
commit
ad96293edb
10
adaptor.go
10
adaptor.go
|
@ -9,6 +9,7 @@ type Adaptor struct {
|
|||
adaptorType string
|
||||
}
|
||||
|
||||
// AdaptorInterface defines behaviour expected for a Gobot Adaptor
|
||||
type AdaptorInterface interface {
|
||||
Finalize() bool
|
||||
Connect() bool
|
||||
|
@ -22,6 +23,7 @@ type AdaptorInterface interface {
|
|||
ToJSON() *JSONConnection
|
||||
}
|
||||
|
||||
// NewAdaptor returns a new Gobot Adaptor
|
||||
func NewAdaptor(name string, adaptorType string, v ...interface{}) *Adaptor {
|
||||
if name == "" {
|
||||
name = fmt.Sprintf("%X", Rand(int(^uint(0)>>1)))
|
||||
|
@ -43,34 +45,42 @@ func NewAdaptor(name string, adaptorType string, v ...interface{}) *Adaptor {
|
|||
return a
|
||||
}
|
||||
|
||||
// Port returns adaptor port
|
||||
func (a *Adaptor) Port() string {
|
||||
return a.port
|
||||
}
|
||||
|
||||
// SetPort sets adaptor port
|
||||
func (a *Adaptor) SetPort(s string) {
|
||||
a.port = s
|
||||
}
|
||||
|
||||
// Name returns adaptor name
|
||||
func (a *Adaptor) Name() string {
|
||||
return a.name
|
||||
}
|
||||
|
||||
// SetName sets adaptor name
|
||||
func (a *Adaptor) SetName(s string) {
|
||||
a.name = s
|
||||
}
|
||||
|
||||
// Type returns adaptor type
|
||||
func (a *Adaptor) Type() string {
|
||||
return a.adaptorType
|
||||
}
|
||||
|
||||
// Connected returns true if adaptor is connected
|
||||
func (a *Adaptor) Connected() bool {
|
||||
return a.connected
|
||||
}
|
||||
|
||||
// SetConnected sets adaptor as connected/disconnected
|
||||
func (a *Adaptor) SetConnected(b bool) {
|
||||
a.connected = b
|
||||
}
|
||||
|
||||
// ToJSON returns a json representation of adaptor
|
||||
func (a *Adaptor) ToJSON() *JSONConnection {
|
||||
return &JSONConnection{
|
||||
Name: a.Name(),
|
||||
|
|
48
api/api.go
48
api/api.go
|
@ -12,8 +12,6 @@ import (
|
|||
"github.com/hybridgroup/gobot/api/robeaux"
|
||||
)
|
||||
|
||||
// Optional restful API through Gobot has access
|
||||
// all the robots.
|
||||
type api struct {
|
||||
gobot *gobot.Gobot
|
||||
router *pat.PatternServeMux
|
||||
|
@ -25,6 +23,8 @@ type api struct {
|
|||
start func(*api)
|
||||
}
|
||||
|
||||
// newAPI returns a gobot api instance
|
||||
// and starts a http server using configuration options
|
||||
func NewAPI(g *gobot.Gobot) *api {
|
||||
return &api{
|
||||
gobot: g,
|
||||
|
@ -47,6 +47,7 @@ func NewAPI(g *gobot.Gobot) *api {
|
|||
}
|
||||
}
|
||||
|
||||
// ServeHTTP calls api handlers and then serves request using api router
|
||||
func (a *api) ServeHTTP(res http.ResponseWriter, req *http.Request) {
|
||||
for _, handler := range a.handlers {
|
||||
handler(res, req)
|
||||
|
@ -54,38 +55,43 @@ func (a *api) ServeHTTP(res http.ResponseWriter, req *http.Request) {
|
|||
a.router.ServeHTTP(res, req)
|
||||
}
|
||||
|
||||
// Post wraps api router Post call
|
||||
func (a *api) Post(path string, f func(http.ResponseWriter, *http.Request)) {
|
||||
a.router.Post(path, http.HandlerFunc(f))
|
||||
}
|
||||
|
||||
// Put wraps api router Put call
|
||||
func (a *api) Put(path string, f func(http.ResponseWriter, *http.Request)) {
|
||||
a.router.Put(path, http.HandlerFunc(f))
|
||||
}
|
||||
|
||||
// Delete wraps api router Delete call
|
||||
func (a *api) Delete(path string, f func(http.ResponseWriter, *http.Request)) {
|
||||
a.router.Del(path, http.HandlerFunc(f))
|
||||
}
|
||||
|
||||
// Options wraps api router Options call
|
||||
func (a *api) Options(path string, f func(http.ResponseWriter, *http.Request)) {
|
||||
a.router.Options(path, http.HandlerFunc(f))
|
||||
}
|
||||
|
||||
// Get wraps api router Get call
|
||||
func (a *api) Get(path string, f func(http.ResponseWriter, *http.Request)) {
|
||||
a.router.Get(path, http.HandlerFunc(f))
|
||||
}
|
||||
|
||||
// Head wraps api router Head call
|
||||
func (a *api) Head(path string, f func(http.ResponseWriter, *http.Request)) {
|
||||
a.router.Head(path, http.HandlerFunc(f))
|
||||
}
|
||||
|
||||
// AddHandler appends handler to api handlers
|
||||
func (a *api) AddHandler(f func(http.ResponseWriter, *http.Request)) {
|
||||
a.handlers = append(a.handlers, f)
|
||||
}
|
||||
|
||||
// start starts the api using the start function
|
||||
// sets on the API on initialization.
|
||||
// Start initializes the api by setting up c3pio routes and robeaux
|
||||
func (a *api) Start() {
|
||||
// api
|
||||
mcpCommandRoute := "/api/commands/:command"
|
||||
deviceCommandRoute := "/api/robots/:robot/devices/:device/commands/:command"
|
||||
robotCommandRoute := "/api/robots/:robot/commands/:command"
|
||||
|
@ -108,7 +114,6 @@ func (a *api) Start() {
|
|||
a.Get("/api/robots/:robot/connections/:connection", a.robotConnection)
|
||||
a.Get("/api/", a.mcp)
|
||||
|
||||
// robeaux
|
||||
a.Get("/", func(res http.ResponseWriter, req *http.Request) {
|
||||
http.Redirect(res, req, "/index.html", http.StatusMovedPermanently)
|
||||
})
|
||||
|
@ -125,6 +130,8 @@ func (a *api) Start() {
|
|||
a.start(a)
|
||||
}
|
||||
|
||||
// robeaux returns handler for robeaux routes.
|
||||
// Writes asset in response and sets correct header
|
||||
func (a *api) robeaux(res http.ResponseWriter, req *http.Request) {
|
||||
path := req.URL.Path
|
||||
buf, err := robeaux.Asset(path[1:])
|
||||
|
@ -141,14 +148,20 @@ func (a *api) robeaux(res http.ResponseWriter, req *http.Request) {
|
|||
res.Write(buf)
|
||||
}
|
||||
|
||||
// mcp returns MCP route handler.
|
||||
// Writes JSON with gobot representation
|
||||
func (a *api) mcp(res http.ResponseWriter, req *http.Request) {
|
||||
a.writeJSON(map[string]interface{}{"MCP": a.gobot.ToJSON()}, res)
|
||||
}
|
||||
|
||||
// mcpCommands returns commands route handler.
|
||||
// Writes JSON with global commands representation
|
||||
func (a *api) mcpCommands(res http.ResponseWriter, req *http.Request) {
|
||||
a.writeJSON(map[string]interface{}{"commands": a.gobot.ToJSON().Commands}, res)
|
||||
}
|
||||
|
||||
// robots returns route handler.
|
||||
// Writes JSON with robots representation
|
||||
func (a *api) robots(res http.ResponseWriter, req *http.Request) {
|
||||
jsonRobots := []*gobot.JSONRobot{}
|
||||
a.gobot.Robots().Each(func(r *gobot.Robot) {
|
||||
|
@ -157,14 +170,20 @@ func (a *api) robots(res http.ResponseWriter, req *http.Request) {
|
|||
a.writeJSON(map[string]interface{}{"robots": jsonRobots}, res)
|
||||
}
|
||||
|
||||
// robot returns route handler.
|
||||
// Writes JSON with robot representation
|
||||
func (a *api) robot(res http.ResponseWriter, req *http.Request) {
|
||||
a.writeJSON(map[string]interface{}{"robot": a.gobot.Robot(req.URL.Query().Get(":robot")).ToJSON()}, res)
|
||||
}
|
||||
|
||||
// robotCommands returns commands route handler
|
||||
// Writes JSON with robot commands representation
|
||||
func (a *api) robotCommands(res http.ResponseWriter, req *http.Request) {
|
||||
a.writeJSON(map[string]interface{}{"commands": a.gobot.Robot(req.URL.Query().Get(":robot")).ToJSON().Commands}, res)
|
||||
}
|
||||
|
||||
// robotDevices returns devices route handler.
|
||||
// Writes JSON with robot devices representation
|
||||
func (a *api) robotDevices(res http.ResponseWriter, req *http.Request) {
|
||||
jsonDevices := []*gobot.JSONDevice{}
|
||||
a.gobot.Robot(req.URL.Query().Get(":robot")).Devices().Each(func(d gobot.Device) {
|
||||
|
@ -173,6 +192,8 @@ func (a *api) robotDevices(res http.ResponseWriter, req *http.Request) {
|
|||
a.writeJSON(map[string]interface{}{"devices": jsonDevices}, res)
|
||||
}
|
||||
|
||||
// robotDevice returns device route handler.
|
||||
// Writes JSON with robot device representation
|
||||
func (a *api) robotDevice(res http.ResponseWriter, req *http.Request) {
|
||||
a.writeJSON(
|
||||
map[string]interface{}{"device": a.gobot.Robot(req.URL.Query().Get(":robot")).
|
||||
|
@ -180,6 +201,9 @@ func (a *api) robotDevice(res http.ResponseWriter, req *http.Request) {
|
|||
)
|
||||
}
|
||||
|
||||
// robotDeviceEvent returns device event route handler.
|
||||
// Creates an event stream connection
|
||||
// and queries event data to be written when received
|
||||
func (a *api) robotDeviceEvent(res http.ResponseWriter, req *http.Request) {
|
||||
f, _ := res.(http.Flusher)
|
||||
c, _ := res.(http.CloseNotifier)
|
||||
|
@ -210,6 +234,8 @@ func (a *api) robotDeviceEvent(res http.ResponseWriter, req *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
// robotDeviceCommands returns device commands route handler
|
||||
// writes JSON with robot device commands representation
|
||||
func (a *api) robotDeviceCommands(res http.ResponseWriter, req *http.Request) {
|
||||
a.writeJSON(
|
||||
map[string]interface{}{"commands": a.gobot.Robot(req.URL.Query().Get(":robot")).
|
||||
|
@ -217,6 +243,8 @@ func (a *api) robotDeviceCommands(res http.ResponseWriter, req *http.Request) {
|
|||
)
|
||||
}
|
||||
|
||||
// robotConnections returns connections route handler
|
||||
// writes JSON with robot connections representation
|
||||
func (a *api) robotConnections(res http.ResponseWriter, req *http.Request) {
|
||||
jsonConnections := []*gobot.JSONConnection{}
|
||||
a.gobot.Robot(req.URL.Query().Get(":robot")).Connections().Each(func(c gobot.Connection) {
|
||||
|
@ -225,6 +253,8 @@ func (a *api) robotConnections(res http.ResponseWriter, req *http.Request) {
|
|||
a.writeJSON(map[string]interface{}{"connections": jsonConnections}, res)
|
||||
}
|
||||
|
||||
// robotConnection returns connection route handler
|
||||
// writes JSON with robot connection representation
|
||||
func (a *api) robotConnection(res http.ResponseWriter, req *http.Request) {
|
||||
a.writeJSON(
|
||||
map[string]interface{}{"connection": a.gobot.Robot(req.URL.Query().Get(":robot")).
|
||||
|
@ -233,6 +263,7 @@ func (a *api) robotConnection(res http.ResponseWriter, req *http.Request) {
|
|||
)
|
||||
}
|
||||
|
||||
// executeMcpCommand calls a global command asociated to requested route
|
||||
func (a *api) executeMcpCommand(res http.ResponseWriter, req *http.Request) {
|
||||
a.executeCommand(a.gobot.Command(req.URL.Query().Get(":command")),
|
||||
res,
|
||||
|
@ -240,6 +271,7 @@ func (a *api) executeMcpCommand(res http.ResponseWriter, req *http.Request) {
|
|||
)
|
||||
}
|
||||
|
||||
// executeDeviceCommand calls a device command asociated to requested route
|
||||
func (a *api) executeDeviceCommand(res http.ResponseWriter, req *http.Request) {
|
||||
a.executeCommand(
|
||||
a.gobot.Robot(req.URL.Query().Get(":robot")).
|
||||
|
@ -250,6 +282,7 @@ func (a *api) executeDeviceCommand(res http.ResponseWriter, req *http.Request) {
|
|||
)
|
||||
}
|
||||
|
||||
// executeRobotCommand calls a robot command asociated to requested route
|
||||
func (a *api) executeRobotCommand(res http.ResponseWriter, req *http.Request) {
|
||||
a.executeCommand(
|
||||
a.gobot.Robot(req.URL.Query().Get(":robot")).
|
||||
|
@ -259,6 +292,7 @@ func (a *api) executeRobotCommand(res http.ResponseWriter, req *http.Request) {
|
|||
)
|
||||
}
|
||||
|
||||
// executeCommand writes JSON response with `f` returned value.
|
||||
func (a *api) executeCommand(f func(map[string]interface{}) interface{},
|
||||
res http.ResponseWriter,
|
||||
req *http.Request,
|
||||
|
@ -274,12 +308,14 @@ func (a *api) executeCommand(f func(map[string]interface{}) interface{},
|
|||
}
|
||||
}
|
||||
|
||||
// writeJSON writes `j` as JSON in response
|
||||
func (a *api) writeJSON(j interface{}, res http.ResponseWriter) {
|
||||
data, _ := json.Marshal(j)
|
||||
res.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
res.Write(data)
|
||||
}
|
||||
|
||||
// Debug add handler to api that prints each request
|
||||
func (a *api) Debug() {
|
||||
a.AddHandler(func(res http.ResponseWriter, req *http.Request) {
|
||||
log.Println(req)
|
||||
|
|
|
@ -6,9 +6,9 @@ import (
|
|||
"net/http"
|
||||
)
|
||||
|
||||
// BasicAuth returns basic auth handler.
|
||||
// Inspired by https://github.com/codegangsta/martini-contrib/blob/master/auth/
|
||||
func BasicAuth(username, password string) http.HandlerFunc {
|
||||
// basic auth inspired by
|
||||
// https://github.com/codegangsta/martini-contrib/blob/master/auth/
|
||||
return func(res http.ResponseWriter, req *http.Request) {
|
||||
if !secureCompare(req.Header.Get("Authorization"),
|
||||
"Basic "+base64.StdEncoding.EncodeToString([]byte(username+":"+password)),
|
||||
|
|
|
@ -14,6 +14,7 @@ type CORS struct {
|
|||
allowOriginPatterns []string
|
||||
}
|
||||
|
||||
// AllowRequestFrom returns handler to verify that requests come from allowedOrigins
|
||||
func AllowRequestsFrom(allowedOrigins ...string) http.HandlerFunc {
|
||||
c := &CORS{
|
||||
AllowOrigins: allowedOrigins,
|
||||
|
@ -35,6 +36,7 @@ func AllowRequestsFrom(allowedOrigins ...string) http.HandlerFunc {
|
|||
}
|
||||
}
|
||||
|
||||
// isOriginAllowed returns true if origin matches an allowed origin pattern.
|
||||
func (c *CORS) isOriginAllowed(origin string) (allowed bool) {
|
||||
for _, allowedOriginPattern := range c.allowOriginPatterns {
|
||||
allowed, _ = regexp.MatchString(allowedOriginPattern, origin)
|
||||
|
@ -45,6 +47,7 @@ func (c *CORS) isOriginAllowed(origin string) (allowed bool) {
|
|||
return
|
||||
}
|
||||
|
||||
// generatePatterns generates regex expresions for AllowOrigins
|
||||
func (c *CORS) generatePatterns() {
|
||||
if c.AllowOrigins != nil {
|
||||
for _, origin := range c.AllowOrigins {
|
||||
|
@ -56,10 +59,12 @@ func (c *CORS) generatePatterns() {
|
|||
}
|
||||
}
|
||||
|
||||
// AllowedHeaders returns allowed headers in a string
|
||||
func (c *CORS) AllowedHeaders() string {
|
||||
return strings.Join(c.AllowHeaders, ",")
|
||||
}
|
||||
|
||||
// AllowedMethods returns allowed http methods in a string
|
||||
func (c *CORS) AllowedMethods() string {
|
||||
return strings.Join(c.AllowMethods, ",")
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
Package api provides functionally to expose your gobot programs
|
||||
to other by using starting a web server and adding commands.
|
||||
|
||||
Example:
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hybridgroup/gobot"
|
||||
"github.com/hybridgroup/gobot/api"
|
||||
)
|
||||
|
||||
func main() {
|
||||
gbot := gobot.NewGobot()
|
||||
|
||||
// Starts the API server on default port 3000
|
||||
api.NewAPI(gbot).Start()
|
||||
|
||||
// Accessible via http://localhost:3000/api/commands/say_hello
|
||||
gbot.AddCommand("say_hello", func(params map[string]interface{}) interface{} {
|
||||
return "Master says hello!"
|
||||
})
|
||||
|
||||
hello := gbot.AddRobot(gobot.NewRobot("Eve"))
|
||||
|
||||
// Accessible via http://localhost:3000/robots/Eve/commands/say_hello
|
||||
hello.AddCommand("say_hello", func(params map[string]interface{}) interface{} {
|
||||
return fmt.Sprintf("%v says hello!", hello.Name)
|
||||
})
|
||||
|
||||
gbot.Start()
|
||||
}
|
||||
|
||||
It follows Common Protocol for Programming Physical Input and Output (CPPP-IO) spec:
|
||||
https://github.com/hybridgroup/cppp-io
|
||||
*/
|
||||
package api
|
|
@ -5,6 +5,7 @@ import (
|
|||
"log"
|
||||
)
|
||||
|
||||
// JSONConnection holds a JSON representation of a connection.
|
||||
type JSONConnection struct {
|
||||
Name string `json:"name"`
|
||||
Adaptor string `json:"adaptor"`
|
||||
|
@ -14,17 +15,19 @@ type Connection AdaptorInterface
|
|||
|
||||
type connections []Connection
|
||||
|
||||
// Len returns connections length
|
||||
func (c *connections) Len() int {
|
||||
return len(*c)
|
||||
}
|
||||
|
||||
// Each calls function for each connection
|
||||
func (c *connections) Each(f func(Connection)) {
|
||||
for _, connection := range *c {
|
||||
f(connection)
|
||||
}
|
||||
}
|
||||
|
||||
// Start() starts all the connections.
|
||||
// Start initializes all the connections.
|
||||
func (c *connections) Start() error {
|
||||
var err error
|
||||
log.Println("Starting connections...")
|
||||
|
@ -42,7 +45,7 @@ func (c *connections) Start() error {
|
|||
return err
|
||||
}
|
||||
|
||||
// Finalize() finalizes all the connections.
|
||||
// Finalize finishes all the connections.
|
||||
func (c *connections) Finalize() {
|
||||
for _, connection := range *c {
|
||||
connection.Finalize()
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"log"
|
||||
)
|
||||
|
||||
// JSONDevice is a JSON representation of a Gobot Device.
|
||||
type JSONDevice struct {
|
||||
Name string `json:"name"`
|
||||
Driver string `json:"driver"`
|
||||
|
@ -16,17 +17,19 @@ type Device DriverInterface
|
|||
|
||||
type devices []Device
|
||||
|
||||
// Len returns devices length
|
||||
func (d *devices) Len() int {
|
||||
return len(*d)
|
||||
}
|
||||
|
||||
// Each calls `f` function each device
|
||||
func (d *devices) Each(f func(Device)) {
|
||||
for _, device := range *d {
|
||||
f(device)
|
||||
}
|
||||
}
|
||||
|
||||
// Start() starts all the devices.
|
||||
// Start starts all the devices.
|
||||
func (d *devices) Start() error {
|
||||
var err error
|
||||
log.Println("Starting devices...")
|
||||
|
@ -44,7 +47,7 @@ func (d *devices) Start() error {
|
|||
return err
|
||||
}
|
||||
|
||||
// Halt() stop all the devices.
|
||||
// Halt stop all the devices.
|
||||
func (d *devices) Halt() {
|
||||
for _, device := range *d {
|
||||
device.Halt()
|
||||
|
|
18
driver.go
18
driver.go
|
@ -5,6 +5,7 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// DriverInterface defines Driver expected behaviour
|
||||
type DriverInterface interface {
|
||||
Start() bool
|
||||
Halt() bool
|
||||
|
@ -35,6 +36,8 @@ type Driver struct {
|
|||
driverType string
|
||||
}
|
||||
|
||||
// NewDriver returns a Driver with specified parameters
|
||||
// and sets driver pin, adaptor and interval
|
||||
func NewDriver(name string, driverType string, v ...interface{}) *Driver {
|
||||
if name == "" {
|
||||
name = fmt.Sprintf("%X", Rand(int(^uint(0)>>1)))
|
||||
|
@ -64,42 +67,52 @@ func NewDriver(name string, driverType string, v ...interface{}) *Driver {
|
|||
return d
|
||||
}
|
||||
|
||||
// Adaptor returns driver adaptor
|
||||
func (d *Driver) Adaptor() AdaptorInterface {
|
||||
return d.adaptor
|
||||
}
|
||||
|
||||
// SetInterval defines driver interval duration.
|
||||
func (d *Driver) SetInterval(t time.Duration) {
|
||||
d.interval = t
|
||||
}
|
||||
|
||||
// Interval current driver interval duration
|
||||
func (d *Driver) Interval() time.Duration {
|
||||
return d.interval
|
||||
}
|
||||
|
||||
// SetName sets driver name.
|
||||
func (d *Driver) SetName(s string) {
|
||||
d.name = s
|
||||
}
|
||||
|
||||
// Name returns driver name.
|
||||
func (d *Driver) Name() string {
|
||||
return d.name
|
||||
}
|
||||
|
||||
// Pin returns driver pin
|
||||
func (d *Driver) Pin() string {
|
||||
return d.pin
|
||||
}
|
||||
|
||||
// SetPin defines driver pin
|
||||
func (d *Driver) SetPin(pin string) {
|
||||
d.pin = pin
|
||||
}
|
||||
|
||||
// Type returns driver type
|
||||
func (d *Driver) Type() string {
|
||||
return d.driverType
|
||||
}
|
||||
|
||||
// Events returns driver events map
|
||||
func (d *Driver) Events() map[string]*Event {
|
||||
return d.events
|
||||
}
|
||||
|
||||
// Event returns an event by name if exists
|
||||
func (d *Driver) Event(name string) *Event {
|
||||
e, ok := d.events[name]
|
||||
if ok {
|
||||
|
@ -109,22 +122,27 @@ func (d *Driver) Event(name string) *Event {
|
|||
}
|
||||
}
|
||||
|
||||
// AddEvents adds a new event by name
|
||||
func (d *Driver) AddEvent(name string) {
|
||||
d.events[name] = NewEvent()
|
||||
}
|
||||
|
||||
// Command retrieves a command by name
|
||||
func (d *Driver) Command(name string) func(map[string]interface{}) interface{} {
|
||||
return d.commands[name]
|
||||
}
|
||||
|
||||
// Commands returns a map of driver commands
|
||||
func (d *Driver) Commands() map[string]func(map[string]interface{}) interface{} {
|
||||
return d.commands
|
||||
}
|
||||
|
||||
// AddCommand links specified command name to `f`
|
||||
func (d *Driver) AddCommand(name string, f func(map[string]interface{}) interface{}) {
|
||||
d.commands[name] = f
|
||||
}
|
||||
|
||||
// ToJSON returns JSON Driver represnentation including adaptor and commands
|
||||
func (d *Driver) ToJSON() *JSONDevice {
|
||||
jsonDevice := &JSONDevice{
|
||||
Name: d.Name(),
|
||||
|
|
5
event.go
5
event.go
|
@ -10,6 +10,8 @@ type Event struct {
|
|||
Callbacks []callback
|
||||
}
|
||||
|
||||
// NewEvent generates a new event by making a channel
|
||||
// and start reading from it
|
||||
func NewEvent() *Event {
|
||||
e := &Event{
|
||||
Chan: make(chan interface{}, 1),
|
||||
|
@ -23,6 +25,7 @@ func NewEvent() *Event {
|
|||
return e
|
||||
}
|
||||
|
||||
// Writes sends event data to channel
|
||||
func (e *Event) Write(data interface{}) {
|
||||
select {
|
||||
case e.Chan <- data:
|
||||
|
@ -30,6 +33,8 @@ func (e *Event) Write(data interface{}) {
|
|||
}
|
||||
}
|
||||
|
||||
// Read waits data from channel and execute callbacks
|
||||
// for each event when received
|
||||
func (e *Event) Read() {
|
||||
for s := range e.Chan {
|
||||
tmp := []callback{}
|
||||
|
|
13
utils.go
13
utils.go
|
@ -10,13 +10,10 @@ import (
|
|||
// Every triggers f every `t` time until the end of days.
|
||||
func Every(t time.Duration, f func()) {
|
||||
c := time.Tick(t)
|
||||
// start a go routine to not bloc the function
|
||||
|
||||
go func() {
|
||||
for {
|
||||
// wait for the ticker to tell us to run
|
||||
<-c
|
||||
// run the passed function in another go routine
|
||||
// so we don't slow down the loop.
|
||||
go f()
|
||||
}
|
||||
}()
|
||||
|
@ -27,27 +24,35 @@ func After(t time.Duration, f func()) {
|
|||
time.AfterFunc(t, f)
|
||||
}
|
||||
|
||||
// Publish emits an event by writting value
|
||||
func Publish(e *Event, val interface{}) {
|
||||
e.Write(val)
|
||||
}
|
||||
|
||||
// On adds `f` to callbacks that are executed on specified event
|
||||
func On(e *Event, f func(s interface{})) {
|
||||
e.Callbacks = append(e.Callbacks, callback{f, false})
|
||||
}
|
||||
|
||||
// Once adds `f` to callbacks that are executed on specified event
|
||||
// and sets flag to be called only once
|
||||
func Once(e *Event, f func(s interface{})) {
|
||||
e.Callbacks = append(e.Callbacks, callback{f, true})
|
||||
}
|
||||
|
||||
// Rand generates random int lower than max
|
||||
func Rand(max int) int {
|
||||
i, _ := rand.Int(rand.Reader, big.NewInt(int64(max)))
|
||||
return int(i.Int64())
|
||||
}
|
||||
|
||||
// FromScale creates a scale using min and max values
|
||||
// to be used in combination with ToScale
|
||||
func FromScale(input, min, max float64) float64 {
|
||||
return (input - math.Min(min, max)) / (math.Max(min, max) - math.Min(min, max))
|
||||
}
|
||||
|
||||
// ToScale is used with FromScale to return input converted to new scale
|
||||
func ToScale(input, min, max float64) float64 {
|
||||
i := input*(math.Max(min, max)-math.Min(min, max)) + math.Min(min, max)
|
||||
if i < math.Min(min, max) {
|
||||
|
|
Loading…
Reference in New Issue