From f6c48982ecd064e13cece7e6501e7c289f4a45f9 Mon Sep 17 00:00:00 2001 From: Ani Channarasappa Date: Sun, 21 Feb 2021 00:59:00 -0500 Subject: [PATCH] fix: set precision to two for non-cryptocurrencies --- internal/quote/quote.go | 13 ++++ internal/ui/component/summary/summary.go | 6 +- internal/ui/component/summary/summary_test.go | 6 +- internal/ui/component/watchlist/watchlist.go | 38 ++++++------ .../ui/component/watchlist/watchlist_test.go | 62 +++++++++---------- internal/ui/util/format.go | 44 ++++++++++--- internal/ui/util/util_test.go | 36 ++++++++--- 7 files changed, 130 insertions(+), 75 deletions(-) diff --git a/internal/quote/quote.go b/internal/quote/quote.go index aec862d..b64e5b1 100644 --- a/internal/quote/quote.go +++ b/internal/quote/quote.go @@ -30,6 +30,7 @@ type ResponseQuote struct { PreMarketChange float64 `json:"preMarketChange"` PreMarketChangePercent float64 `json:"preMarketChangePercent"` PreMarketPrice float64 `json:"preMarketPrice"` + QuoteType string `json:"quoteType"` } type Quote struct { @@ -43,6 +44,7 @@ type Quote struct { ChangePercent float64 IsActive bool IsRegularTradingSession bool + IsVariablePrecision bool CurrencyConverted string } @@ -53,6 +55,10 @@ type Response struct { } `json:"quoteResponse"` } +func isVariablePrecision(responseQuote ResponseQuote) bool { + return responseQuote.QuoteType == "CRYPTOCURRENCY" +} + func transformResponseQuote(ctx c.Context, responseQuote ResponseQuote) Quote { currencyRate, _, currencyCode := currency.GetCurrencyRateFromContext(ctx, responseQuote.Currency) @@ -69,6 +75,7 @@ func transformResponseQuote(ctx c.Context, responseQuote ResponseQuote) Quote { ChangePercent: responseQuote.RegularMarketChangePercent, IsActive: true, IsRegularTradingSession: true, + IsVariablePrecision: isVariablePrecision(responseQuote), CurrencyConverted: currencyCode, } } @@ -85,6 +92,7 @@ func transformResponseQuote(ctx c.Context, responseQuote ResponseQuote) Quote { ChangePercent: responseQuote.RegularMarketChangePercent, IsActive: true, IsRegularTradingSession: false, + IsVariablePrecision: isVariablePrecision(responseQuote), CurrencyConverted: currencyCode, } } @@ -101,6 +109,7 @@ func transformResponseQuote(ctx c.Context, responseQuote ResponseQuote) Quote { ChangePercent: responseQuote.RegularMarketChangePercent, IsActive: false, IsRegularTradingSession: false, + IsVariablePrecision: isVariablePrecision(responseQuote), CurrencyConverted: currencyCode, } } @@ -117,6 +126,7 @@ func transformResponseQuote(ctx c.Context, responseQuote ResponseQuote) Quote { ChangePercent: responseQuote.PostMarketChangePercent + responseQuote.RegularMarketChangePercent, IsActive: true, IsRegularTradingSession: false, + IsVariablePrecision: isVariablePrecision(responseQuote), CurrencyConverted: currencyCode, } } @@ -133,6 +143,7 @@ func transformResponseQuote(ctx c.Context, responseQuote ResponseQuote) Quote { ChangePercent: responseQuote.PreMarketChangePercent, IsActive: true, IsRegularTradingSession: false, + IsVariablePrecision: isVariablePrecision(responseQuote), CurrencyConverted: currencyCode, } } @@ -149,6 +160,7 @@ func transformResponseQuote(ctx c.Context, responseQuote ResponseQuote) Quote { ChangePercent: responseQuote.PostMarketChangePercent + responseQuote.RegularMarketChangePercent, IsActive: false, IsRegularTradingSession: false, + IsVariablePrecision: isVariablePrecision(responseQuote), CurrencyConverted: currencyCode, } } @@ -164,6 +176,7 @@ func transformResponseQuote(ctx c.Context, responseQuote ResponseQuote) Quote { ChangePercent: responseQuote.RegularMarketChangePercent, IsActive: false, IsRegularTradingSession: false, + IsVariablePrecision: isVariablePrecision(responseQuote), CurrencyConverted: currencyCode, } diff --git a/internal/ui/component/summary/summary.go b/internal/ui/component/summary/summary.go index 92d8df1..c29bd3e 100644 --- a/internal/ui/component/summary/summary.go +++ b/internal/ui/component/summary/summary.go @@ -40,12 +40,12 @@ func (m Model) View() string { func quoteChangeText(change float64, changePercent float64) string { if change == 0.0 { - return StyleNeutralFaded(ConvertFloatToString(change) + " (" + ConvertFloatToString(changePercent) + "%)") + return StyleNeutralFaded(ConvertFloatToString(change, false) + " (" + ConvertFloatToString(changePercent, false) + "%)") } if change > 0.0 { - return StylePricePositive(changePercent)("↑ " + ConvertFloatToString(change) + " (" + ConvertFloatToString(changePercent) + "%)") + return StylePricePositive(changePercent)("↑ " + ConvertFloatToString(change, false) + " (" + ConvertFloatToString(changePercent, false) + "%)") } - return StylePriceNegative(changePercent)("↓ " + ConvertFloatToString(change) + " (" + ConvertFloatToString(changePercent) + "%)") + return StylePriceNegative(changePercent)("↓ " + ConvertFloatToString(change, false) + " (" + ConvertFloatToString(changePercent, false) + "%)") } diff --git a/internal/ui/component/summary/summary_test.go b/internal/ui/component/summary/summary_test.go index 26c5dcf..0749be0 100644 --- a/internal/ui/component/summary/summary_test.go +++ b/internal/ui/component/summary/summary_test.go @@ -29,7 +29,7 @@ var _ = Describe("Summary", func() { DayChangePercent: 10.0, } Expect(removeFormatting(m.View())).To(Equal(strings.Join([]string{ - "Day: ↑ 100.00 (10.000%) • Change: ↑ 9000.00 (1000.00%) • Value: 10000.00", + "Day: ↑ 100.00 (10.00%) • Change: ↑ 9000.00 (1000.00%) • Value: 10000.00", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━", }, "\n"))) }) @@ -47,7 +47,7 @@ var _ = Describe("Summary", func() { DayChangePercent: -10.0, } Expect(removeFormatting(m.View())).To(Equal(strings.Join([]string{ - "Day: ↓ -100.00 (-10.000%) • Change: ↓ -9000.00 (-1000.00%) • Value: 1000.00", + "Day: ↓ -100.00 (-10.00%) • Change: ↓ -9000.00 (-1000.00%) • Value: 1000.00", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━", }, "\n"))) }) @@ -57,7 +57,7 @@ var _ = Describe("Summary", func() { It("should render an empty summary", func() { m := NewModel() Expect(removeFormatting(m.View())).To(Equal(strings.Join([]string{ - "Day: 0.0000 (0.0000%) • Change: 0.0000 (0.0000%) • Value: ", + "Day: 0.00 (0.00%) • Change: 0.00 (0.00%) • Value: ", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━", }, "\n"))) }) diff --git a/internal/ui/component/watchlist/watchlist.go b/internal/ui/component/watchlist/watchlist.go index 3c78077..2eff258 100644 --- a/internal/ui/component/watchlist/watchlist.go +++ b/internal/ui/component/watchlist/watchlist.go @@ -51,7 +51,7 @@ func (m Model) View() string { strings.Join( []string{ item(quote, m.Positions[quote.Symbol], m.Width), - extraInfoHoldings(m.Context.Config.ShowHoldings, m.Positions[quote.Symbol], m.Width), + extraInfoHoldings(m.Context.Config.ShowHoldings, quote, m.Positions[quote.Symbol], m.Width), extraInfoFundamentals(m.ExtraInfoFundamentals, quote, m.Width), extraInfoExchange(m.ExtraInfoExchange, quote, m.Context.Config.Currency, m.Width), }, @@ -96,7 +96,7 @@ func item(q Quote, p Position, width int) string { }, Cell{ Width: 25, - Text: StyleNeutral(ConvertFloatToString(q.Price)), + Text: StyleNeutral(ConvertFloatToString(q.Price, q.IsVariablePrecision)), Align: RightAlign, }, ), @@ -107,12 +107,12 @@ func item(q Quote, p Position, width int) string { }, Cell{ Width: 25, - Text: valueChangeText(p.TotalChange, p.TotalChangePercent), + Text: valueChangeText(p.TotalChange, p.TotalChangePercent, q.IsVariablePrecision), Align: RightAlign, }, Cell{ Width: 25, - Text: quoteChangeText(q.Change, q.ChangePercent), + Text: quoteChangeText(q.Change, q.ChangePercent, q.IsVariablePrecision), Align: RightAlign, }, ), @@ -147,7 +147,7 @@ func extraInfoFundamentals(show bool, q Quote, width int) string { return "\n" + Line( width, Cell{ - Text: dayRangeText(q.PriceDayHigh, q.PriceDayLow), + Text: dayRangeText(q.PriceDayHigh, q.PriceDayLow, q.IsVariablePrecision), Align: RightAlign, }, Cell{ @@ -157,7 +157,7 @@ func extraInfoFundamentals(show bool, q Quote, width int) string { }, Cell{ Width: 10, - Text: StyleNeutral(ConvertFloatToString(q.PricePrevClose)), + Text: StyleNeutral(ConvertFloatToString(q.PricePrevClose, q.IsVariablePrecision)), Align: RightAlign, }, Cell{ @@ -167,13 +167,13 @@ func extraInfoFundamentals(show bool, q Quote, width int) string { }, Cell{ Width: 10, - Text: StyleNeutral(ConvertFloatToString(q.PriceOpen)), + Text: StyleNeutral(ConvertFloatToString(q.PriceOpen, q.IsVariablePrecision)), Align: RightAlign, }, ) } -func extraInfoHoldings(show bool, p Position, width int) string { +func extraInfoHoldings(show bool, q Quote, p Position, width int) string { if (p == Position{} || !show) { return "" } @@ -186,7 +186,7 @@ func extraInfoHoldings(show bool, p Position, width int) string { }, Cell{ Width: 7, - Text: StyleNeutral(ConvertFloatToString(p.Weight)) + "%", + Text: StyleNeutral(ConvertFloatToString(p.Weight, q.IsVariablePrecision)) + "%", Align: RightAlign, }, Cell{ @@ -196,7 +196,7 @@ func extraInfoHoldings(show bool, p Position, width int) string { }, Cell{ Width: 10, - Text: StyleNeutral(ConvertFloatToString(p.AverageCost)), + Text: StyleNeutral(ConvertFloatToString(p.AverageCost, q.IsVariablePrecision)), Align: RightAlign, }, Cell{ @@ -206,17 +206,17 @@ func extraInfoHoldings(show bool, p Position, width int) string { }, Cell{ Width: 10, - Text: StyleNeutral(ConvertFloatToString(p.Quantity)), + Text: StyleNeutral(ConvertFloatToString(p.Quantity, q.IsVariablePrecision)), Align: RightAlign, }, ) } -func dayRangeText(high float64, low float64) string { +func dayRangeText(high float64, low float64, isVariablePrecision bool) string { if high == 0.0 || low == 0.0 { return "" } - return StyleNeutralFaded("Day Range: ") + StyleNeutral(ConvertFloatToString(high)+" - "+ConvertFloatToString(low)) + return StyleNeutralFaded("Day Range: ") + StyleNeutral(ConvertFloatToString(high, isVariablePrecision)+" - "+ConvertFloatToString(low, isVariablePrecision)) } func exchangeDelayText(delay float64) string { @@ -243,22 +243,22 @@ func marketStateText(q Quote) string { return "" } -func valueChangeText(change float64, changePercent float64) string { +func valueChangeText(change float64, changePercent float64, isVariablePrecision bool) string { if change == 0.0 { return "" } - return quoteChangeText(change, changePercent) + return quoteChangeText(change, changePercent, isVariablePrecision) } -func quoteChangeText(change float64, changePercent float64) string { +func quoteChangeText(change float64, changePercent float64, isVariablePrecision bool) string { if change == 0.0 { - return StyleNeutralFaded(" " + ConvertFloatToString(change) + " (" + ConvertFloatToString(changePercent) + "%)") + return StyleNeutralFaded(" " + ConvertFloatToString(change, isVariablePrecision) + " (" + ConvertFloatToString(changePercent, false) + "%)") } if change > 0.0 { - return StylePricePositive(changePercent)("↑ " + ConvertFloatToString(change) + " (" + ConvertFloatToString(changePercent) + "%)") + return StylePricePositive(changePercent)("↑ " + ConvertFloatToString(change, isVariablePrecision) + " (" + ConvertFloatToString(changePercent, false) + "%)") } - return StylePriceNegative(changePercent)("↓ " + ConvertFloatToString(change) + " (" + ConvertFloatToString(changePercent) + "%)") + return StylePriceNegative(changePercent)("↓ " + ConvertFloatToString(change, isVariablePrecision) + " (" + ConvertFloatToString(changePercent, false) + "%)") } diff --git a/internal/ui/component/watchlist/watchlist_test.go b/internal/ui/component/watchlist/watchlist_test.go index 71eef98..05ad742 100644 --- a/internal/ui/component/watchlist/watchlist_test.go +++ b/internal/ui/component/watchlist/watchlist_test.go @@ -70,8 +70,8 @@ var _ = Describe("Watchlist", func() { 0.05, Position{}, strings.Join([]string{ - "AAPL ● 1.0500", - "Apple Inc. ↑ 0.0500 (0.0500%)", + "AAPL ● 1.05", + "Apple Inc. ↑ 0.05 (0.05%)", "", }, "\n"), ), @@ -82,8 +82,8 @@ var _ = Describe("Watchlist", func() { -0.05, Position{}, strings.Join([]string{ - "AAPL ● 0.9500", - "Apple Inc. ↓ -0.0500 (-0.0500%)", + "AAPL ● 0.95", + "Apple Inc. ↓ -0.05 (-0.05%)", "", }, "\n"), ), @@ -94,8 +94,8 @@ var _ = Describe("Watchlist", func() { 0.05, Position{}, strings.Join([]string{ - "AAPL ○ 1.0500", - "Apple Inc. ↑ 0.0500 (0.0500%)", + "AAPL ○ 1.05", + "Apple Inc. ↑ 0.05 (0.05%)", "", }, "\n"), ), @@ -117,8 +117,8 @@ var _ = Describe("Watchlist", func() { TotalChangePercent: 110.0, }, strings.Join([]string{ - "AAPL ● 105.00 1.0500", - "Apple Inc. ↑ 55.000 (110.00%) ↑ 0.0500 (0.0500%)", + "AAPL ● 105.00 1.05", + "Apple Inc. ↑ 55.00 (110.00%) ↑ 0.05 (0.05%)", "", }, "\n"), ), @@ -140,8 +140,8 @@ var _ = Describe("Watchlist", func() { TotalChangePercent: -30.0, }, strings.Join([]string{ - "AAPL ● 105.00 1.0500", - "Apple Inc. ↓ -45.000 (-30.000%) ↑ 0.0500 (0.0500%)", + "AAPL ● 105.00 1.05", + "Apple Inc. ↓ -45.00 (-30.00%) ↑ 0.05 (0.05%)", "", }, "\n"), ), @@ -163,8 +163,8 @@ var _ = Describe("Watchlist", func() { TotalChangePercent: 90.0, }, strings.Join([]string{ - "AAPL ● 95.000 0.9500", - "Apple Inc. ↑ 45.000 (90.000%) ↓ -0.0500 (-0.0500%)", + "AAPL ● 95.00 0.95", + "Apple Inc. ↑ 45.00 (90.00%) ↓ -0.05 (-0.05%)", "", }, "\n"), ), @@ -186,8 +186,8 @@ var _ = Describe("Watchlist", func() { TotalChangePercent: -36.67, }, strings.Join([]string{ - "AAPL ● 95.000 0.9500", - "Apple Inc. ↓ -55.000 (-36.670%) ↓ -0.0500 (-0.0500%)", + "AAPL ● 95.00 0.95", + "Apple Inc. ↓ -55.00 (-36.67%) ↓ -0.05 (-0.05%)", "", }, "\n"), ), @@ -207,8 +207,8 @@ var _ = Describe("Watchlist", func() { DayChangePercent: 0.0, }, strings.Join([]string{ - "AAPL 95.000 1.0000", - "Apple Inc. 0.0000 (0.0000%)", + "AAPL 95.00 1.00", + "Apple Inc. 0.00 (0.00%)", "", }, "\n"), ), @@ -274,13 +274,13 @@ var _ = Describe("Watchlist", func() { } expected := strings.Join([]string{ "BTC-USD ● 50000.00", - "Bitcoin ↑ 10000.00 (20.000%)", + "Bitcoin ↑ 10000.00 (20.00%)", "TW ○ 109.04", - "ThoughtWorks ↑ 3.5300 (5.6500%)", + "ThoughtWorks ↑ 3.53 (5.65%)", "GOOG ○ 2523.53", - "Google Inc. ↓ -32.020 (-1.3500%)", - "AAPL 1.0500", - "Apple Inc. 0.0000 (0.0000%)", + "Google Inc. ↓ -32.02 (-1.35%)", + "AAPL 1.05", + "Apple Inc. 0.00 (0.00%)", "", }, "\n") Expect(removeFormatting(m.View())).To(Equal(expected)) @@ -334,13 +334,13 @@ var _ = Describe("Watchlist", func() { } expected := strings.Join([]string{ "BTC-USD ● 50000.00", - "Bitcoin ↑ 10000.00 (20.000%)", + "Bitcoin ↑ 10000.00 (20.00%)", "────────────────────────────────────────────────────────────────────────────────", "TW ○ 109.04", - "ThoughtWorks ↑ 3.5300 (5.6500%)", + "ThoughtWorks ↑ 3.53 (5.65%)", "────────────────────────────────────────────────────────────────────────────────", "GOOG ○ 2523.53", - "Google Inc. ↓ -32.020 (-1.3500%)", + "Google Inc. ↓ -32.02 (-1.35%)", "", }, "\n") Expect(removeFormatting(m.View())).To(Equal(expected)) @@ -376,7 +376,7 @@ var _ = Describe("Watchlist", func() { } expected := strings.Join([]string{ "BTC-USD ● 50000.00", - "Bitcoin ↑ 10000.00 (20.000%)", + "Bitcoin ↑ 10000.00 (20.00%)", " USD Real-Time Cryptocurrency ", "", }, "\n") @@ -411,7 +411,7 @@ var _ = Describe("Watchlist", func() { } expected := strings.Join([]string{ "BTC-USD ● 50000.00", - "Bitcoin ↑ 10000.00 (20.000%)", + "Bitcoin ↑ 10000.00 (20.00%)", " USD Delayed 15min Cryptocurrency ", "", }, "\n") @@ -446,7 +446,7 @@ var _ = Describe("Watchlist", func() { m.Context.Config.Currency = "EUR" expected := strings.Join([]string{ "APPL ● 5000.00", - "Apple, Inc ↑ 1000.00 (20.000%)", + "Apple, Inc ↑ 1000.00 (20.00%)", " USD → EUR Real-Time NASDAQ ", "", }, "\n") @@ -488,7 +488,7 @@ var _ = Describe("Watchlist", func() { } expected := strings.Join([]string{ "BTC-USD ● 50000.00", - "Bitcoin ↑ 10000.00 (20.000%)", + "Bitcoin ↑ 10000.00 (20.00%)", "Day Range: 10000.00 - 10000.00 Prev Close: 10000.00 Open: 10000.00", "", }, "\n") @@ -524,7 +524,7 @@ var _ = Describe("Watchlist", func() { } expected := strings.Join([]string{ "BTC-USD ● 50000.00", - "Bitcoin ↑ 10000.00 (20.000%)", + "Bitcoin ↑ 10000.00 (20.00%)", " Prev Close: 10000.00 Open: 10000.00", "", }, "\n") @@ -570,8 +570,8 @@ var _ = Describe("Watchlist", func() { } expected := strings.Join([]string{ "PTON ● 105.00 100.00", - "Peloton ↑ 55.000 (110.00%) ↑ 10.000 (10.000%)", - " Weight: 0.0000% Avg. Cost: 0.0000 Quantity: 100.00", + "Peloton ↑ 55.00 (110.00%) ↑ 10.00 (10.00%)", + " Weight: 0.00% Avg. Cost: 0.00 Quantity: 100.00", "", }, "\n") Expect(removeFormatting(m.View())).To(Equal(expected)) diff --git a/internal/ui/util/format.go b/internal/ui/util/format.go index a726c41..418fc97 100644 --- a/internal/ui/util/format.go +++ b/internal/ui/util/format.go @@ -1,15 +1,41 @@ package util -import "strconv" - -func ConvertFloatToString(f float64) string { - var prec = 2 - if f < 10 && f > -10 { - prec = 4 - } else if f < 100 && f > -100 { - prec = 3 +import ( + "math" + "strconv" +) + +func getPrecision(f float64) int { + + v := math.Abs(f) + + if v == 0.0 { + return 2 + } + + if v >= 10000 { + return 0 + } + + if v < 10 { + return 4 } + if v < 100 { + return 3 + } + + return 2 +} + +func ConvertFloatToString(f float64, isVariablePrecision bool) string { + + if !isVariablePrecision { + return strconv.FormatFloat(f, 'f', 2, 64) + } + + prec := getPrecision(f) + return strconv.FormatFloat(f, 'f', prec, 64) } @@ -18,5 +44,5 @@ func ValueText(value float64) string { return "" } - return StyleNeutral(ConvertFloatToString(value)) + return StyleNeutral(ConvertFloatToString(value, false)) } diff --git a/internal/ui/util/util_test.go b/internal/ui/util/util_test.go index 85c2002..0cb47da 100644 --- a/internal/ui/util/util_test.go +++ b/internal/ui/util/util_test.go @@ -9,18 +9,34 @@ import ( var _ = Describe("Util", func() { Describe("ConvertFloatToString", func() { - It("should convert a float that smaller than 10 to a string with a precision of four", func() { - output := ConvertFloatToString(0.563412) - Expect(output).To(Equal("0.5634")) + It("should convert a float to a precision of two", func() { + output := ConvertFloatToString(0.563412, false) + Expect(output).To(Equal("0.56")) }) - It("should convert a float that between 10 and 100 to a string with a precision of three", func() { - output := ConvertFloatToString(12.5634) - Expect(output).To(Equal("12.563")) - }) - It("should convert a float that greater than 100 to a string with a precision of two", func() { - output := ConvertFloatToString(204.4325) - Expect(output).To(Equal("204.43")) + + When("there using variable precision", func() { + It("should convert a float that smaller than 10 to a string with a precision of four", func() { + output := ConvertFloatToString(0.563412, true) + Expect(output).To(Equal("0.5634")) + }) + It("should convert a float that between 10 and 100 to a string with a precision of three", func() { + output := ConvertFloatToString(12.5634, true) + Expect(output).To(Equal("12.563")) + }) + It("should convert a float that greater than 100 to a string with a precision of two", func() { + output := ConvertFloatToString(204.4325, true) + Expect(output).To(Equal("204.43")) + }) + It("should set a precision of two when the value is zero", func() { + output := ConvertFloatToString(0.0, true) + Expect(output).To(Equal("0.00")) + }) + It("should set a precision of zero when the value is over 10000", func() { + output := ConvertFloatToString(10000.0, true) + Expect(output).To(Equal("10000")) + }) }) + }) Describe("ValueText", func() { When("value is <= 0.0", func() {