utils.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package feed
  2. import (
  3. "errors"
  4. "fmt"
  5. "net/url"
  6. "slices"
  7. "strings"
  8. )
  9. var (
  10. ErrNoContent = errors.New("failed to retrieve any content")
  11. ErrPartialContent = errors.New("failed to retrieve some of the content")
  12. )
  13. func percentChange(current, previous float64) float64 {
  14. return (current/previous - 1) * 100
  15. }
  16. func extractDomainFromUrl(u string) string {
  17. if u == "" {
  18. return ""
  19. }
  20. parsed, err := url.Parse(u)
  21. if err != nil {
  22. return ""
  23. }
  24. return strings.TrimPrefix(strings.ToLower(parsed.Host), "www.")
  25. }
  26. func SvgPolylineCoordsFromYValues(width float64, height float64, values []float64) string {
  27. if len(values) < 2 {
  28. return ""
  29. }
  30. verticalPadding := height * 0.02
  31. height -= verticalPadding * 2
  32. coordinates := make([]string, len(values))
  33. distanceBetweenPoints := width / float64(len(values)-1)
  34. min := slices.Min(values)
  35. max := slices.Max(values)
  36. for i := range values {
  37. coordinates[i] = fmt.Sprintf(
  38. "%.2f,%.2f",
  39. float64(i)*distanceBetweenPoints,
  40. ((max-values[i])/(max-min))*height+verticalPadding,
  41. )
  42. }
  43. return strings.Join(coordinates, " ")
  44. }
  45. func maybeCopySliceWithoutZeroValues[T int | float64](values []T) []T {
  46. if len(values) == 0 {
  47. return values
  48. }
  49. for i := range values {
  50. if values[i] != 0 {
  51. continue
  52. }
  53. c := make([]T, 0, len(values)-1)
  54. for i := range values {
  55. if values[i] != 0 {
  56. c = append(c, values[i])
  57. }
  58. }
  59. return c
  60. }
  61. return values
  62. }
  63. func currencyCodeToSymbol(code string) string {
  64. currencySymbols := map[string]string{
  65. "btc": "₿",
  66. "eth": "Ξ",
  67. "ltc": "Ł",
  68. "bch": "₡",
  69. "bnb": "Ƀ",
  70. "eos": "", // no symbol
  71. "xrp": "", // no symbol
  72. "xlm": "", // no symbol
  73. "link": "", // no symbol
  74. "dot": "", // no symbol
  75. "yfi": "", // no symbol
  76. "usd": "$",
  77. "aed": "د.إ",
  78. "ars": "$",
  79. "aud": "AU$",
  80. "bdt": "৳",
  81. "bhd": ".د.ب",
  82. "bmd": "$",
  83. "brl": "R$",
  84. "cad": "CA$",
  85. "chf": "CHF",
  86. "clp": "$",
  87. "cny": "¥",
  88. "czk": "Kč",
  89. "dkk": "kr",
  90. "eur": "€",
  91. "gbp": "£",
  92. "gel": "ლ",
  93. "hkd": "HK$",
  94. "huf": "Ft",
  95. "idr": "Rp",
  96. "ils": "₪",
  97. "inr": "₹",
  98. "jpy": "¥",
  99. "krw": "₩",
  100. "kwd": "د.ك",
  101. "lkr": "Rs",
  102. "mmk": "K",
  103. "mxn": "$",
  104. "myr": "RM",
  105. "ngn": "₦",
  106. "nok": "kr",
  107. "nzd": "NZ$",
  108. "php": "₱",
  109. "pkr": "Rs",
  110. "pln": "zł",
  111. "rub": "₽",
  112. "sar": "ر.س",
  113. "sek": "kr",
  114. "sgd": "SGD",
  115. "thb": "฿",
  116. "try": "₺",
  117. "twd": "NT$",
  118. "uah": "₴",
  119. "vef": "Bs",
  120. "vnd": "₫",
  121. "zar": "R",
  122. "xdr": "", // no symbol
  123. "xag": "", // no symbol
  124. "xau": "", // no symbol
  125. "bits": "", // no symbol
  126. "sats": "", // no symbol
  127. }
  128. symbol, ok := currencySymbols[code]
  129. if !ok {
  130. symbol = strings.ToUpper(code) + " "
  131. }
  132. return symbol
  133. }