master
Michael Dvorkin 10 years ago
parent 7932776cf5
commit bc666ec165
  1. 2
      LICENSE
  2. 2
      README.md
  3. 4
      cmd/mop.go
  4. 4
      cnn_market.go
  5. 5
      column_editor.go
  6. 48
      layout.go
  7. 26
      line_editor.go
  8. 4
      markup.go
  9. 4
      profile.go
  10. 6
      screen.go
  11. 243
      sorter.go
  12. 2
      yahoo_quotes.go

@ -1,4 +1,4 @@
Copyright (c) 2013 Michael Dvorkin. All Rights Reserved. Copyright (c) 2013-2015 Michael Dvorkin. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the

@ -44,7 +44,7 @@ comments, suggestions, and contributions are welcome.
### License ### ### License ###
Copyright (c) 2013 Michael Dvorkin. All Rights Reserved. Copyright (c) 2013-2015 Michael Dvorkin. All Rights Reserved.
"mike" + "@dvorkin" + ".net" || "twitter.com/mid" "mike" + "@dvorkin" + ".net" || "twitter.com/mid"
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining

@ -1,4 +1,4 @@
// Copyright (c) 2013 by Michael Dvorkin. All Rights Reserved. // Copyright (c) 2013-2015 by Michael Dvorkin. All Rights Reserved.
// Use of this source code is governed by a MIT-style license that can // Use of this source code is governed by a MIT-style license that can
// be found in the LICENSE file. // be found in the LICENSE file.
@ -10,7 +10,7 @@ import (
`time` `time`
) )
const help = `Mop v0.2.0 -- Copyright (c) 2013-15 Michael Dvorkin. All Rights Reserved. const help = `Mop v0.2.0 -- Copyright (c) 2013-2015 by Michael Dvorkin. All Rights Reserved.
NO WARRANTIES OF ANY KIND WHATSOEVER. SEE THE LICENSE FILE FOR DETAILS. NO WARRANTIES OF ANY KIND WHATSOEVER. SEE THE LICENSE FILE FOR DETAILS.
<u>Command</u> <u>Description </u> <u>Command</u> <u>Description </u>

@ -1,4 +1,4 @@
// Copyright (c) 2013 by Michael Dvorkin. All Rights Reserved. // Copyright (c) 2013-2015 by Michael Dvorkin. All Rights Reserved.
// Use of this source code is governed by a MIT-style license that can // Use of this source code is governed by a MIT-style license that can
// be found in the LICENSE file. // be found in the LICENSE file.
@ -37,7 +37,7 @@ type Market struct {
// Returns new initialized Market struct. // Returns new initialized Market struct.
func NewMarket() *Market { func NewMarket() *Market {
market := &Market{}; market := &Market{}
market.IsClosed = false market.IsClosed = false
market.Dow = make(map[string]string) market.Dow = make(map[string]string)
market.Nasdaq = make(map[string]string) market.Nasdaq = make(map[string]string)

@ -1,4 +1,4 @@
// Copyright (c) 2013 by Michael Dvorkin. All Rights Reserved. // Copyright (c) 2013-2015 by Michael Dvorkin. All Rights Reserved.
// Use of this source code is governed by a MIT-style license that can // Use of this source code is governed by a MIT-style license that can
// be found in the LICENSE file. // be found in the LICENSE file.
@ -72,7 +72,7 @@ func (editor *ColumnEditor) selectLeftColumn() *ColumnEditor {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
func (editor *ColumnEditor) selectRightColumn() *ColumnEditor { func (editor *ColumnEditor) selectRightColumn() *ColumnEditor {
editor.profile.selectedColumn++ editor.profile.selectedColumn++
if editor.profile.selectedColumn > editor.layout.TotalColumns() - 1 { if editor.profile.selectedColumn > editor.layout.TotalColumns()-1 {
editor.profile.selectedColumn = 0 editor.profile.selectedColumn = 0
} }
return editor return editor
@ -98,4 +98,3 @@ func (editor *ColumnEditor) redrawHeader() {
editor.screen.DrawLine(0, 4, editor.layout.Header(editor.profile)) editor.screen.DrawLine(0, 4, editor.layout.Header(editor.profile))
termbox.Flush() termbox.Flush()
} }

@ -1,4 +1,4 @@
// Copyright (c) 2013 by Michael Dvorkin. All Rights Reserved. // Copyright (c) 2013-2015 by Michael Dvorkin. All Rights Reserved.
// Use of this source code is governed by a MIT-style license that can // Use of this source code is governed by a MIT-style license that can
// be found in the LICENSE file. // be found in the LICENSE file.
@ -20,7 +20,7 @@ type Column struct {
width int // Column width. width int // Column width.
name string // The name of the field in the Stock struct. name string // The name of the field in the Stock struct.
title string // Column title to display in the header. title string // Column title to display in the header.
formatter func(string)string // Optional function to format the contents of the column. formatter func(string) string // Optional function to format the contents of the column.
} }
// Layout is used to format and display all the collected data, i.e. market // Layout is used to format and display all the collected data, i.e. market
@ -37,21 +37,21 @@ type Layout struct {
func NewLayout() *Layout { func NewLayout() *Layout {
layout := &Layout{} layout := &Layout{}
layout.columns = []Column{ layout.columns = []Column{
{ -7, `Ticker`, `Ticker`, nil }, {-7, `Ticker`, `Ticker`, nil},
{ 10, `LastTrade`, `Last`, currency }, {10, `LastTrade`, `Last`, currency},
{ 10, `Change`, `Change`, currency }, {10, `Change`, `Change`, currency},
{ 10, `ChangePct`, `Change%`, last }, {10, `ChangePct`, `Change%`, last},
{ 10, `Open`, `Open`, currency }, {10, `Open`, `Open`, currency},
{ 10, `Low`, `Low`, currency }, {10, `Low`, `Low`, currency},
{ 10, `High`, `High`, currency }, {10, `High`, `High`, currency},
{ 10, `Low52`, `52w Low`, currency }, {10, `Low52`, `52w Low`, currency},
{ 10, `High52`, `52w High`, currency }, {10, `High52`, `52w High`, currency},
{ 11, `Volume`, `Volume`, nil }, {11, `Volume`, `Volume`, nil},
{ 11, `AvgVolume`, `AvgVolume`, nil }, {11, `AvgVolume`, `AvgVolume`, nil},
{ 9, `PeRatio`, `P/E`, blank }, {9, `PeRatio`, `P/E`, blank},
{ 9, `Dividend`, `Dividend`, zero }, {9, `Dividend`, `Dividend`, zero},
{ 9, `Yield`, `Yield`, percent }, {9, `Yield`, `Yield`, percent},
{ 11, `MarketCap`, `MktCap`, currency }, {11, `MarketCap`, `MktCap`, currency},
} }
layout.regex = regexp.MustCompile(`(\.\d+)[BMK]?$`) layout.regex = regexp.MustCompile(`(\.\d+)[BMK]?$`)
layout.marketTemplate = buildMarketTemplate() layout.marketTemplate = buildMarketTemplate()
@ -107,12 +107,12 @@ func (layout *Layout) Quotes(quotes *Quotes) string {
func (layout *Layout) Header(profile *Profile) string { func (layout *Layout) Header(profile *Profile) string {
str, selectedColumn := ``, profile.selectedColumn str, selectedColumn := ``, profile.selectedColumn
for i,col := range layout.columns { for i, col := range layout.columns {
arrow := arrowFor(i, profile) arrow := arrowFor(i, profile)
if i != selectedColumn { if i != selectedColumn {
str += fmt.Sprintf(`%*s`, col.width, arrow + col.title) str += fmt.Sprintf(`%*s`, col.width, arrow+col.title)
} else { } else {
str += fmt.Sprintf(`<r>%*s</r>`, col.width, arrow + col.title) str += fmt.Sprintf(`<r>%*s</r>`, col.width, arrow+col.title)
} }
} }
@ -139,7 +139,7 @@ func (layout *Layout) prettify(quotes *Quotes) []Stock {
// - If the column has the formatter method then call it. // - If the column has the formatter method then call it.
// - Set the column value padding it to the given width. // - Set the column value padding it to the given width.
// //
for _,column := range layout.columns { for _, column := range layout.columns {
// ex. value = stock.Change // ex. value = stock.Change
value := reflect.ValueOf(&stock).Elem().FieldByName(column.name).String() value := reflect.ValueOf(&stock).Elem().FieldByName(column.name).String()
if column.formatter != nil { if column.formatter != nil {
@ -173,7 +173,7 @@ func (layout *Layout) pad(str string, width int) string {
if len(match) > 0 { if len(match) > 0 {
switch len(match[1]) { switch len(match[1]) {
case 2: case 2:
str = strings.Replace(str, match[1], match[1] + `0`, 1) str = strings.Replace(str, match[1], match[1]+`0`, 1)
case 4, 5: case 4, 5:
str = strings.Replace(str, match[1], match[1][0:3], 1) str = strings.Replace(str, match[1], match[1][0:3], 1)
} }
@ -218,13 +218,13 @@ func group(stocks []Stock) []Stock {
grouped := make([]Stock, len(stocks)) grouped := make([]Stock, len(stocks))
current := 0 current := 0
for _,stock := range stocks { for _, stock := range stocks {
if stock.Advancing { if stock.Advancing {
grouped[current] = stock grouped[current] = stock
current++ current++
} }
} }
for _,stock := range stocks { for _, stock := range stocks {
if !stock.Advancing { if !stock.Advancing {
grouped[current] = stock grouped[current] = stock
current++ current++

@ -1,4 +1,4 @@
// Copyright (c) 2013 by Michael Dvorkin. All Rights Reserved. // Copyright (c) 2013-2015 by Michael Dvorkin. All Rights Reserved.
// Use of this source code is governed by a MIT-style license that can // Use of this source code is governed by a MIT-style license that can
// be found in the LICENSE file. // be found in the LICENSE file.
@ -42,7 +42,7 @@ func (editor *LineEditor) Prompt(command rune) *LineEditor {
editor.prompt = prompt editor.prompt = prompt
editor.command = command editor.command = command
editor.screen.DrawLine(0, 3, `<white>` + editor.prompt + `</>`) editor.screen.DrawLine(0, 3, `<white>`+editor.prompt+`</>`)
termbox.SetCursor(len(editor.prompt), 3) termbox.SetCursor(len(editor.prompt), 3)
termbox.Flush() termbox.Flush()
} }
@ -97,12 +97,12 @@ func (editor *LineEditor) deletePreviousCharacter() *LineEditor {
if editor.cursor > 0 { if editor.cursor > 0 {
if editor.cursor < len(editor.input) { if editor.cursor < len(editor.input) {
// Remove character in the middle of the input string. // Remove character in the middle of the input string.
editor.input = editor.input[0 : editor.cursor-1] + editor.input[editor.cursor : len(editor.input)] editor.input = editor.input[0:editor.cursor-1] + editor.input[editor.cursor:len(editor.input)]
} else { } else {
// Remove last input character. // Remove last input character.
editor.input = editor.input[ : len(editor.input)-1] editor.input = editor.input[:len(editor.input)-1]
} }
editor.screen.DrawLine(len(editor.prompt), 3, editor.input + ` `) // Erase last character. editor.screen.DrawLine(len(editor.prompt), 3, editor.input+` `) // Erase last character.
editor.moveLeft() editor.moveLeft()
} }
@ -113,7 +113,7 @@ func (editor *LineEditor) deletePreviousCharacter() *LineEditor {
func (editor *LineEditor) insertCharacter(ch rune) *LineEditor { func (editor *LineEditor) insertCharacter(ch rune) *LineEditor {
if editor.cursor < len(editor.input) { if editor.cursor < len(editor.input) {
// Insert the character in the middle of the input string. // Insert the character in the middle of the input string.
editor.input = editor.input[0 : editor.cursor] + string(ch) + editor.input[editor.cursor : len(editor.input)] editor.input = editor.input[0:editor.cursor] + string(ch) + editor.input[editor.cursor:len(editor.input)]
} else { } else {
// Append the character to the end of the input string. // Append the character to the end of the input string.
editor.input += string(ch) editor.input += string(ch)
@ -128,7 +128,7 @@ func (editor *LineEditor) insertCharacter(ch rune) *LineEditor {
func (editor *LineEditor) moveLeft() *LineEditor { func (editor *LineEditor) moveLeft() *LineEditor {
if editor.cursor > 0 { if editor.cursor > 0 {
editor.cursor-- editor.cursor--
termbox.SetCursor(len(editor.prompt) + editor.cursor, 3) termbox.SetCursor(len(editor.prompt)+editor.cursor, 3)
} }
return editor return editor
@ -138,7 +138,7 @@ func (editor *LineEditor) moveLeft() *LineEditor {
func (editor *LineEditor) moveRight() *LineEditor { func (editor *LineEditor) moveRight() *LineEditor {
if editor.cursor < len(editor.input) { if editor.cursor < len(editor.input) {
editor.cursor++ editor.cursor++
termbox.SetCursor(len(editor.prompt) + editor.cursor, 3) termbox.SetCursor(len(editor.prompt)+editor.cursor, 3)
} }
return editor return editor
@ -147,7 +147,7 @@ func (editor *LineEditor) moveRight() *LineEditor {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
func (editor *LineEditor) jumpToBeginning() *LineEditor { func (editor *LineEditor) jumpToBeginning() *LineEditor {
editor.cursor = 0 editor.cursor = 0
termbox.SetCursor(len(editor.prompt) + editor.cursor, 3) termbox.SetCursor(len(editor.prompt)+editor.cursor, 3)
return editor return editor
} }
@ -155,7 +155,7 @@ func (editor *LineEditor) jumpToBeginning() *LineEditor {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
func (editor *LineEditor) jumpToEnd() *LineEditor { func (editor *LineEditor) jumpToEnd() *LineEditor {
editor.cursor = len(editor.input) editor.cursor = len(editor.input)
termbox.SetCursor(len(editor.prompt) + editor.cursor, 3) termbox.SetCursor(len(editor.prompt)+editor.cursor, 3)
return editor return editor
} }
@ -166,7 +166,7 @@ func (editor *LineEditor) execute() *LineEditor {
case '+': case '+':
tickers := editor.tokenize() tickers := editor.tokenize()
if len(tickers) > 0 { if len(tickers) > 0 {
if added,_ := editor.quotes.AddTickers(tickers); added > 0 { if added, _ := editor.quotes.AddTickers(tickers); added > 0 {
editor.screen.Draw(editor.quotes) editor.screen.Draw(editor.quotes)
} }
} }
@ -174,13 +174,13 @@ func (editor *LineEditor) execute() *LineEditor {
tickers := editor.tokenize() tickers := editor.tokenize()
if len(tickers) > 0 { if len(tickers) > 0 {
before := len(editor.quotes.profile.Tickers) before := len(editor.quotes.profile.Tickers)
if removed,_ := editor.quotes.RemoveTickers(tickers); removed > 0 { if removed, _ := editor.quotes.RemoveTickers(tickers); removed > 0 {
editor.screen.Draw(editor.quotes) editor.screen.Draw(editor.quotes)
// Clear the lines at the bottom of the list, if any. // Clear the lines at the bottom of the list, if any.
after := before - removed after := before - removed
for i := before; i > after; i-- { for i := before; i > after; i-- {
editor.screen.ClearLine(0, i + 4) editor.screen.ClearLine(0, i+4)
} }
} }
} }

@ -1,4 +1,4 @@
// Copyright (c) 2013 by Michael Dvorkin. All Rights Reserved. // Copyright (c) 2013-2015 by Michael Dvorkin. All Rights Reserved.
// Use of this source code is governed by a MIT-style license that can // Use of this source code is governed by a MIT-style license that can
// be found in the LICENSE file. // be found in the LICENSE file.
@ -138,7 +138,7 @@ func (markup *Markup) supportedTags() *regexp.Regexp {
arr := []string{} arr := []string{}
for tag := range markup.tags { for tag := range markup.tags {
arr = append(arr, `</?` + tag + `>`) arr = append(arr, `</?`+tag+`>`)
} }
return regexp.MustCompile(strings.Join(arr, `|`)) return regexp.MustCompile(strings.Join(arr, `|`))

@ -1,4 +1,4 @@
// Copyright (c) 2013 by Michael Dvorkin. All Rights Reserved. // Copyright (c) 2013-2015 by Michael Dvorkin. All Rights Reserved.
// Use of this source code is governed by a MIT-style license that can // Use of this source code is governed by a MIT-style license that can
// be found in the LICENSE file. // be found in the LICENSE file.
@ -36,7 +36,7 @@ func NewProfile() *Profile {
profile.MarketRefresh = 12 // Market data gets fetched every 12s (5 times per minute). profile.MarketRefresh = 12 // Market data gets fetched every 12s (5 times per minute).
profile.QuotesRefresh = 5 // Stock quotes get updated every 5s (12 times per minute). profile.QuotesRefresh = 5 // Stock quotes get updated every 5s (12 times per minute).
profile.Grouped = false // Stock quotes are *not* grouped by advancing/declining. profile.Grouped = false // Stock quotes are *not* grouped by advancing/declining.
profile.Tickers = []string{ `AAPL`, `C`, `GOOG`, `IBM`, `KO`, `ORCL`, `V` } profile.Tickers = []string{`AAPL`, `C`, `GOOG`, `IBM`, `KO`, `ORCL`, `V`}
profile.SortColumn = 0 // Stock quotes are sorted by ticker name. profile.SortColumn = 0 // Stock quotes are sorted by ticker name.
profile.Ascending = true // A to Z. profile.Ascending = true // A to Z.
profile.Save() profile.Save()

@ -1,4 +1,4 @@
// Copyright (c) 2013 by Michael Dvorkin. All Rights Reserved. // Copyright (c) 2013-2015 by Michael Dvorkin. All Rights Reserved.
// Use of this source code is governed by a MIT-style license that can // Use of this source code is governed by a MIT-style license that can
// be found in the LICENSE file. // be found in the LICENSE file.
@ -87,7 +87,7 @@ func (screen *Screen) ClearLine(x int, y int) *Screen {
// market data, stock quotes, current time, and an arbitrary string. // market data, stock quotes, current time, and an arbitrary string.
func (screen *Screen) Draw(objects ...interface{}) *Screen { func (screen *Screen) Draw(objects ...interface{}) *Screen {
if screen.pausedAt != nil { if screen.pausedAt != nil {
defer screen.DrawLine(0, 0, `<right><r>` + screen.pausedAt.Format(`3:04:05pm PST`) + `</r></right>`) defer screen.DrawLine(0, 0, `<right><r>`+screen.pausedAt.Format(`3:04:05pm PST`)+`</r></right>`)
} }
for _, ptr := range objects { for _, ptr := range objects {
switch ptr.(type) { switch ptr.(type) {
@ -99,7 +99,7 @@ func (screen *Screen) Draw(objects ...interface{}) *Screen {
screen.draw(screen.layout.Quotes(object.Fetch())) screen.draw(screen.layout.Quotes(object.Fetch()))
case time.Time: case time.Time:
timestamp := ptr.(time.Time).Format(`3:04:05pm PST`) timestamp := ptr.(time.Time).Format(`3:04:05pm PST`)
screen.DrawLine(0, 0, `<right>` + timestamp + `</right>`) screen.DrawLine(0, 0, `<right>`+timestamp+`</right>`)
default: default:
screen.draw(ptr.(string)) screen.draw(ptr.(string))
} }

@ -1,4 +1,4 @@
// Copyright (c) 2013 by Michael Dvorkin. All Rights Reserved. // Copyright (c) 2013-2015 by Michael Dvorkin. All Rights Reserved.
// Use of this source code is governed by a MIT-style license that can // Use of this source code is governed by a MIT-style license that can
// be found in the LICENSE file. // be found in the LICENSE file.
@ -18,72 +18,129 @@ type Sorter struct {
} }
type sortable []Stock type sortable []Stock
func (list sortable) Len() int { return len(list) } func (list sortable) Len() int { return len(list) }
func (list sortable) Swap(i, j int) { list[i], list[j] = list[j], list[i] } func (list sortable) Swap(i, j int) { list[i], list[j] = list[j], list[i] }
type byTickerAsc struct { sortable } type byTickerAsc struct{ sortable }
type byLastTradeAsc struct { sortable } type byLastTradeAsc struct{ sortable }
type byChangeAsc struct { sortable } type byChangeAsc struct{ sortable }
type byChangePctAsc struct { sortable } type byChangePctAsc struct{ sortable }
type byOpenAsc struct { sortable } type byOpenAsc struct{ sortable }
type byLowAsc struct { sortable } type byLowAsc struct{ sortable }
type byHighAsc struct { sortable } type byHighAsc struct{ sortable }
type byLow52Asc struct { sortable } type byLow52Asc struct{ sortable }
type byHigh52Asc struct { sortable } type byHigh52Asc struct{ sortable }
type byVolumeAsc struct { sortable } type byVolumeAsc struct{ sortable }
type byAvgVolumeAsc struct { sortable } type byAvgVolumeAsc struct{ sortable }
type byPeRatioAsc struct { sortable } type byPeRatioAsc struct{ sortable }
type byDividendAsc struct { sortable } type byDividendAsc struct{ sortable }
type byYieldAsc struct { sortable } type byYieldAsc struct{ sortable }
type byMarketCapAsc struct { sortable } type byMarketCapAsc struct{ sortable }
type byTickerDesc struct { sortable } type byTickerDesc struct{ sortable }
type byLastTradeDesc struct { sortable } type byLastTradeDesc struct{ sortable }
type byChangeDesc struct { sortable } type byChangeDesc struct{ sortable }
type byChangePctDesc struct { sortable } type byChangePctDesc struct{ sortable }
type byOpenDesc struct { sortable } type byOpenDesc struct{ sortable }
type byLowDesc struct { sortable } type byLowDesc struct{ sortable }
type byHighDesc struct { sortable } type byHighDesc struct{ sortable }
type byLow52Desc struct { sortable } type byLow52Desc struct{ sortable }
type byHigh52Desc struct { sortable } type byHigh52Desc struct{ sortable }
type byVolumeDesc struct { sortable } type byVolumeDesc struct{ sortable }
type byAvgVolumeDesc struct { sortable } type byAvgVolumeDesc struct{ sortable }
type byPeRatioDesc struct { sortable } type byPeRatioDesc struct{ sortable }
type byDividendDesc struct { sortable } type byDividendDesc struct{ sortable }
type byYieldDesc struct { sortable } type byYieldDesc struct{ sortable }
type byMarketCapDesc struct { sortable } type byMarketCapDesc struct{ sortable }
func (list byTickerAsc) Less(i, j int) bool { return list.sortable[i].Ticker < list.sortable[j].Ticker } func (list byTickerAsc) Less(i, j int) bool {
func (list byLastTradeAsc) Less(i, j int) bool { return list.sortable[i].LastTrade < list.sortable[j].LastTrade } return list.sortable[i].Ticker < list.sortable[j].Ticker
func (list byChangeAsc) Less(i, j int) bool { return c(list.sortable[i].Change) < c(list.sortable[j].Change) } }
func (list byChangePctAsc) Less(i, j int) bool { return c(list.sortable[i].ChangePct) < c(list.sortable[j].ChangePct) } func (list byLastTradeAsc) Less(i, j int) bool {
func (list byOpenAsc) Less(i, j int) bool { return list.sortable[i].Open < list.sortable[j].Open } return list.sortable[i].LastTrade < list.sortable[j].LastTrade
}
func (list byChangeAsc) Less(i, j int) bool {
return c(list.sortable[i].Change) < c(list.sortable[j].Change)
}
func (list byChangePctAsc) Less(i, j int) bool {
return c(list.sortable[i].ChangePct) < c(list.sortable[j].ChangePct)
}
func (list byOpenAsc) Less(i, j int) bool {
return list.sortable[i].Open < list.sortable[j].Open
}
func (list byLowAsc) Less(i, j int) bool { return list.sortable[i].Low < list.sortable[j].Low } func (list byLowAsc) Less(i, j int) bool { return list.sortable[i].Low < list.sortable[j].Low }
func (list byHighAsc) Less(i, j int) bool { return list.sortable[i].High < list.sortable[j].High } func (list byHighAsc) Less(i, j int) bool {
func (list byLow52Asc) Less(i, j int) bool { return list.sortable[i].Low52 < list.sortable[j].Low52 } return list.sortable[i].High < list.sortable[j].High
func (list byHigh52Asc) Less(i, j int) bool { return list.sortable[i].High52 < list.sortable[j].High52 } }
func (list byVolumeAsc) Less(i, j int) bool { return list.sortable[i].Volume < list.sortable[j].Volume } func (list byLow52Asc) Less(i, j int) bool {
func (list byAvgVolumeAsc) Less(i, j int) bool { return list.sortable[i].AvgVolume < list.sortable[j].AvgVolume } return list.sortable[i].Low52 < list.sortable[j].Low52
func (list byPeRatioAsc) Less(i, j int) bool { return list.sortable[i].PeRatio < list.sortable[j].PeRatio } }
func (list byDividendAsc) Less(i, j int) bool { return list.sortable[i].Dividend < list.sortable[j].Dividend } func (list byHigh52Asc) Less(i, j int) bool {
func (list byYieldAsc) Less(i, j int) bool { return list.sortable[i].Yield < list.sortable[j].Yield } return list.sortable[i].High52 < list.sortable[j].High52
func (list byMarketCapAsc) Less(i, j int) bool { return m(list.sortable[i].MarketCap) < m(list.sortable[j].MarketCap) } }
func (list byVolumeAsc) Less(i, j int) bool {
func (list byTickerDesc) Less(i, j int) bool { return list.sortable[j].Ticker < list.sortable[i].Ticker } return list.sortable[i].Volume < list.sortable[j].Volume
func (list byLastTradeDesc) Less(i, j int) bool { return list.sortable[j].LastTrade < list.sortable[i].LastTrade } }
func (list byChangeDesc) Less(i, j int) bool { return c(list.sortable[j].ChangePct) < c(list.sortable[i].ChangePct) } func (list byAvgVolumeAsc) Less(i, j int) bool {
func (list byChangePctDesc) Less(i, j int) bool { return c(list.sortable[j].ChangePct) < c(list.sortable[i].ChangePct) } return list.sortable[i].AvgVolume < list.sortable[j].AvgVolume
func (list byOpenDesc) Less(i, j int) bool { return list.sortable[j].Open < list.sortable[i].Open } }
func (list byPeRatioAsc) Less(i, j int) bool {
return list.sortable[i].PeRatio < list.sortable[j].PeRatio
}
func (list byDividendAsc) Less(i, j int) bool {
return list.sortable[i].Dividend < list.sortable[j].Dividend
}
func (list byYieldAsc) Less(i, j int) bool {
return list.sortable[i].Yield < list.sortable[j].Yield
}
func (list byMarketCapAsc) Less(i, j int) bool {
return m(list.sortable[i].MarketCap) < m(list.sortable[j].MarketCap)
}
func (list byTickerDesc) Less(i, j int) bool {
return list.sortable[j].Ticker < list.sortable[i].Ticker
}
func (list byLastTradeDesc) Less(i, j int) bool {
return list.sortable[j].LastTrade < list.sortable[i].LastTrade
}
func (list byChangeDesc) Less(i, j int) bool {
return c(list.sortable[j].ChangePct) < c(list.sortable[i].ChangePct)
}
func (list byChangePctDesc) Less(i, j int) bool {
return c(list.sortable[j].ChangePct) < c(list.sortable[i].ChangePct)
}
func (list byOpenDesc) Less(i, j int) bool {
return list.sortable[j].Open < list.sortable[i].Open
}
func (list byLowDesc) Less(i, j int) bool { return list.sortable[j].Low < list.sortable[i].Low } func (list byLowDesc) Less(i, j int) bool { return list.sortable[j].Low < list.sortable[i].Low }
func (list byHighDesc) Less(i, j int) bool { return list.sortable[j].High < list.sortable[i].High } func (list byHighDesc) Less(i, j int) bool {
func (list byLow52Desc) Less(i, j int) bool { return list.sortable[j].Low52 < list.sortable[i].Low52 } return list.sortable[j].High < list.sortable[i].High
func (list byHigh52Desc) Less(i, j int) bool { return list.sortable[j].High52 < list.sortable[i].High52 } }
func (list byVolumeDesc) Less(i, j int) bool { return list.sortable[j].Volume < list.sortable[i].Volume } func (list byLow52Desc) Less(i, j int) bool {
func (list byAvgVolumeDesc) Less(i, j int) bool { return list.sortable[j].AvgVolume < list.sortable[i].AvgVolume } return list.sortable[j].Low52 < list.sortable[i].Low52
func (list byPeRatioDesc) Less(i, j int) bool { return list.sortable[j].PeRatio < list.sortable[i].PeRatio } }
func (list byDividendDesc) Less(i, j int) bool { return list.sortable[j].Dividend < list.sortable[i].Dividend } func (list byHigh52Desc) Less(i, j int) bool {
func (list byYieldDesc) Less(i, j int) bool { return list.sortable[j].Yield < list.sortable[i].Yield } return list.sortable[j].High52 < list.sortable[i].High52
func (list byMarketCapDesc) Less(i, j int) bool { return m(list.sortable[j].MarketCap) < m(list.sortable[i].MarketCap) } }
func (list byVolumeDesc) Less(i, j int) bool {
return list.sortable[j].Volume < list.sortable[i].Volume
}
func (list byAvgVolumeDesc) Less(i, j int) bool {
return list.sortable[j].AvgVolume < list.sortable[i].AvgVolume
}
func (list byPeRatioDesc) Less(i, j int) bool {
return list.sortable[j].PeRatio < list.sortable[i].PeRatio
}
func (list byDividendDesc) Less(i, j int) bool {
return list.sortable[j].Dividend < list.sortable[i].Dividend
}
func (list byYieldDesc) Less(i, j int) bool {
return list.sortable[j].Yield < list.sortable[i].Yield
}
func (list byMarketCapDesc) Less(i, j int) bool {
return m(list.sortable[j].MarketCap) < m(list.sortable[i].MarketCap)
}
// Returns new Sorter struct. // Returns new Sorter struct.
func NewSorter(profile *Profile) *Sorter { func NewSorter(profile *Profile) *Sorter {
@ -99,39 +156,39 @@ func (sorter *Sorter) SortByCurrentColumn(stocks []Stock) *Sorter {
if sorter.profile.Ascending { if sorter.profile.Ascending {
interfaces = []sort.Interface{ interfaces = []sort.Interface{
byTickerAsc { stocks }, byTickerAsc{stocks},
byLastTradeAsc { stocks }, byLastTradeAsc{stocks},
byChangeAsc { stocks }, byChangeAsc{stocks},
byChangePctAsc { stocks }, byChangePctAsc{stocks},
byOpenAsc { stocks }, byOpenAsc{stocks},
byLowAsc { stocks }, byLowAsc{stocks},
byHighAsc { stocks }, byHighAsc{stocks},
byLow52Asc { stocks }, byLow52Asc{stocks},
byHigh52Asc { stocks }, byHigh52Asc{stocks},
byVolumeAsc { stocks }, byVolumeAsc{stocks},
byAvgVolumeAsc { stocks }, byAvgVolumeAsc{stocks},
byPeRatioAsc { stocks }, byPeRatioAsc{stocks},
byDividendAsc { stocks }, byDividendAsc{stocks},
byYieldAsc { stocks }, byYieldAsc{stocks},
byMarketCapAsc { stocks }, byMarketCapAsc{stocks},
} }
} else { } else {
interfaces = []sort.Interface{ interfaces = []sort.Interface{
byTickerDesc { stocks }, byTickerDesc{stocks},
byLastTradeDesc { stocks }, byLastTradeDesc{stocks},
byChangeDesc { stocks }, byChangeDesc{stocks},
byChangePctDesc { stocks }, byChangePctDesc{stocks},
byOpenDesc { stocks }, byOpenDesc{stocks},
byLowDesc { stocks }, byLowDesc{stocks},
byHighDesc { stocks }, byHighDesc{stocks},
byLow52Desc { stocks }, byLow52Desc{stocks},
byHigh52Desc { stocks }, byHigh52Desc{stocks},
byVolumeDesc { stocks }, byVolumeDesc{stocks},
byAvgVolumeDesc { stocks }, byAvgVolumeDesc{stocks},
byPeRatioDesc { stocks }, byPeRatioDesc{stocks},
byDividendDesc { stocks }, byDividendDesc{stocks},
byYieldDesc { stocks }, byYieldDesc{stocks},
byMarketCapDesc { stocks }, byMarketCapDesc{stocks},
} }
} }
@ -153,7 +210,7 @@ func c(str string) float32 {
func m(str string) float32 { func m(str string) float32 {
multiplier := 1.0 multiplier := 1.0
switch str[len(str)-1:len(str)] { // Check the last character. switch str[len(str)-1 : len(str)] { // Check the last character.
case `B`: case `B`:
multiplier = 1000000000.0 multiplier = 1000000000.0
case `M`: case `M`:

@ -1,4 +1,4 @@
// Copyright (c) 2013 by Michael Dvorkin. All Rights Reserved. // Copyright (c) 2013-2015 by Michael Dvorkin. All Rights Reserved.
// Use of this source code is governed by a MIT-style license that can // Use of this source code is governed by a MIT-style license that can
// be found in the LICENSE file. // be found in the LICENSE file.

Loading…
Cancel
Save