diff --git a/_sample_configs/bargraph_config.yml b/_sample_configs/bargraph_config.yml new file mode 100644 index 00000000..577771ee --- /dev/null +++ b/_sample_configs/bargraph_config.yml @@ -0,0 +1,27 @@ +wtf: + colors: + border: + focusable: darkslateblue + focused: orange + normal: gray + grid: + columns: [40, 40] + rows: [13, 13, 4] + refreshInterval: 1 + mods: + bargraph: + colors: + from: + name: coral + displayName: grey + to: + name: white + price: green + enabled: true + position: + top: 2 + left: 0 + height: 2 + width: 2 + refreshInterval: 30 + updateInterval: 15 \ No newline at end of file diff --git a/bargraph/widget.go b/bargraph/widget.go new file mode 100644 index 00000000..0e798952 --- /dev/null +++ b/bargraph/widget.go @@ -0,0 +1,79 @@ +package bargraph + +/************** +This is a demo bargraph that just populates some random date/val data +*/ + +import ( + "math/rand" + "time" + + "github.com/olebedev/config" + "github.com/senorprogrammer/wtf/wtf" +) + +// Config is a pointer to the global config object +var Config *config.Config + +var started = false +var ok = true + +// Widget define wtf widget to register widget later +type Widget struct { + wtf.BarGraph + + // time interval for send http request + updateInterval int +} + +// NewWidget Make new instance of widget +func NewWidget() *Widget { + widget := Widget{ + BarGraph: wtf.NewBarGraph(" Sample Bar Graph", "bargraph", false), + } + + widget.View.SetWrap(true) + widget.View.SetWordWrap(true) + + return &widget +} + +/* -------------------- Exported Functions -------------------- */ + +// MakeGraph - Load the dead drop stats +func MakeGraph(widget *Widget) { + + //this could come from config + const lineCount = 20 + var stats [lineCount][2]int64 + + for i := lineCount - 1; i >= 0; i-- { + + stats[i][1] = time.Now().AddDate(0, 0, i*-1).Unix() * 1000 + stats[i][0] = int64(rand.Intn(120-5) + 5) + + } + + widget.BarGraph.BuildBars(20, "🌟", stats[:]) + +} + +// Refresh & update after interval time +func (widget *Widget) Refresh() { + + if widget.Disabled() { + return + } + + widget.UpdateRefreshedAt() + widget.View.Clear() + + display(widget) + +} + +/* -------------------- Unexported Functions -------------------- */ + +func display(widget *Widget) { + MakeGraph(widget) +} diff --git a/wtf.go b/wtf.go index 949d5ffc..2c801fa2 100644 --- a/wtf.go +++ b/wtf.go @@ -11,6 +11,7 @@ import ( "github.com/radovskyb/watcher" "github.com/rivo/tview" "github.com/senorprogrammer/wtf/bamboohr" + "github.com/senorprogrammer/wtf/bargraph" "github.com/senorprogrammer/wtf/clocks" "github.com/senorprogrammer/wtf/cmdrunner" "github.com/senorprogrammer/wtf/cryptoexchanges/bittrex" @@ -218,6 +219,7 @@ func makeWidgets(app *tview.Application, pages *tview.Pages) { // Always in alphabetical order bamboohr.Config = Config + bargraph.Config = Config bittrex.Config = Config clocks.Config = Config cmdrunner.Config = Config @@ -245,6 +247,7 @@ func makeWidgets(app *tview.Application, pages *tview.Pages) { if enabled, _ := Config.Bool("wtf.mods." + mod + ".enabled"); enabled { addWidget(app, pages, mod) } + } FocusTracker = wtf.FocusTracker{ diff --git a/wtf/bargraph.go b/wtf/bargraph.go new file mode 100644 index 00000000..7c7da2ac --- /dev/null +++ b/wtf/bargraph.go @@ -0,0 +1,161 @@ +package wtf + +import ( + "bytes" + "fmt" + "strings" + "time" + + "github.com/rivo/tview" +) + +//BarGraph lets make graphs +type BarGraph struct { + enabled bool + focusable bool + + Name string + RefreshedAt time.Time + RefreshInt int + View *tview.TextView + + Position + + Data [][2]int64 +} + +// NewBarGraph initialize your fancy new graph +func NewBarGraph(name string, configKey string, focusable bool) BarGraph { + widget := BarGraph{ + enabled: Config.UBool(fmt.Sprintf("wtf.mods.%s.enabled", configKey), false), + focusable: focusable, + + Name: Config.UString(fmt.Sprintf("wtf.mods.%s.title", configKey), name), + RefreshInt: Config.UInt(fmt.Sprintf("wtf.mods.%s.refreshInterval", configKey)), + } + + widget.Position = NewPosition( + Config.UInt(fmt.Sprintf("wtf.mods.%s.position.top", configKey)), + Config.UInt(fmt.Sprintf("wtf.mods.%s.position.left", configKey)), + Config.UInt(fmt.Sprintf("wtf.mods.%s.position.width", configKey)), + Config.UInt(fmt.Sprintf("wtf.mods.%s.position.height", configKey)), + ) + + widget.addView() + + return widget +} + +func (widget *BarGraph) BorderColor() string { + if widget.Focusable() { + return Config.UString("wtf.colors.border.focusable", "red") + } + + return Config.UString("wtf.colors.border.normal", "gray") +} + +func (widget *BarGraph) Disabled() bool { + return !widget.Enabled() +} + +func (widget *BarGraph) Enabled() bool { + return widget.enabled +} + +func (widget *BarGraph) Focusable() bool { + return widget.enabled && widget.focusable +} + +func (widget *BarGraph) RefreshInterval() int { + return widget.RefreshInt +} + +func (widget *BarGraph) TextView() *tview.TextView { + return widget.View +} + +/* -------------------- Unexported Functions -------------------- */ + +func (widget *BarGraph) UpdateRefreshedAt() { + widget.RefreshedAt = time.Now() +} + +func (widget *BarGraph) addView() { + view := tview.NewTextView() + + view.SetBackgroundColor(ColorFor(Config.UString("wtf.colors.background", "black"))) + view.SetBorder(true) + view.SetBorderColor(ColorFor(widget.BorderColor())) + view.SetDynamicColors(true) + view.SetTitle(widget.Name) + view.SetWrap(false) + + widget.View = view +} + +// BuildBars will build a string of * to represent your data of [time][value] +// time should be passed as a int64 +func (widget *BarGraph) BuildBars(maxStars int, starChar string, data [][2]int64) { + + var buffer bytes.Buffer + + //counter to inintialize min value + var count int + + //store the max value from the array + var maxValue int + + //store the min value from the array + var minValue int + + //just getting min and max values + for i := range data { + + var val = int(data[i][0]) + + //initialize the min value + if count == 0 { + minValue = val + } + count++ + + //update max value + if val > maxValue { + maxValue = val + } + + //update minValue + if val < minValue { + minValue = val + } + + } + + // each number = how many stars? + var starRatio = float64(maxStars) / float64((maxValue - minValue)) + + //build the stars + for i := range data { + var val = int(data[i][0]) + + //how many stars for this one? + var starCount = int(float64((val - minValue)) * starRatio) + + if starCount == 0 { + starCount = 1 + } + //build the actual string + var stars = strings.Repeat(starChar, starCount) + + //parse the time + var t = time.Unix(int64(data[i][1]/1000), 0) + + //write the line + buffer.WriteString(fmt.Sprintf("%s -\t [red]%s[white] - (%d)\n", t.Format("Jan 02, 2006"), stars, val)) + } + + widget.View.SetText(buffer.String()) + +} + +/* -------------------- Exported Functions -------------------- */