currency.GetCurrency   F
last analyzed

Complexity

Conditions 15

Size

Total Lines 84
Code Lines 57

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 15
eloc 57
nop 1
dl 0
loc 84
rs 2.9998
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like currency.GetCurrency often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
package currency
2
3
import (
4
	"encoding/json"
5
	"fmt"
6
	"io/ioutil"
7
	"net/http"
8
	"strconv"
9
	"strings"
10
11
	"github.com/FlameInTheDark/dtbot/bot"
12
)
13
14
// Data currency structure
15
type Data struct {
16
	Date         string              `json:"Date"`
17
	PreviousDate string              `json:"PreviousDate"`
18
	PreviousURL  string              `json:"PreviousURL"`
19
	Timestamp    string              `json:"Timestamp"`
20
	Currencies   map[string]Currency `json:"Valute"`
21
}
22
23
// CurrencyCheck returns true if currency is real
24
func (d *Data) CurrencyCheck(currency string) bool {
25
	if currency == "RUB" {
26
		return true
27
	}
28
29
	if d.Currencies[currency].Value > 0 {
30
		return true
31
	}
32
33
	return false
34
}
35
36
// Currency structure
37
type Currency struct {
38
	ID       string
39
	NumCode  string
40
	CharCode string
41
	Nominal  int
42
	Name     string
43
	Value    float32
44
	Previous float32
45
}
46
47
// GetCurrency returns string of parsed currency data
48
func GetCurrency(ctx *bot.Context) (response string) {
49
	var (
50
		newData Data
51
		args    = ctx.Conf.Currency.Default
52
	)
53
54
	if len(ctx.Args) > 0 {
55
		args = ctx.Args
56
	}
57
58
	resp, err := http.Get("https://www.cbr-xml-daily.ru/daily_json.js")
59
	if err != nil {
60
		response = fmt.Sprintf("API error: %v", err)
61
		return
62
	}
63
64
	bbytes, berr := ioutil.ReadAll(resp.Body)
65
	if berr != nil {
66
		response = fmt.Sprintf("%v: %v", ctx.Loc("curr_resp_read_err"), berr)
67
		return
68
	}
69
70
	jerr := json.Unmarshal(bbytes, &newData)
71
	if jerr != nil {
72
		response = fmt.Sprintf("%v: %v", ctx.Loc("curr_resp_parse_err"), jerr)
73
		return
74
	}
75
76
	newData.Currencies["RUB"] = Currency{"R00000", "000", "RUB", 1, "Российский Рубль", 1, 1}
77
78
	response = ""
79
80
	// List of currencies
81
	if args[0] == "list" {
82
		ctx.MetricsCommand("currency", "list")
83
		response = fmt.Sprintf("%v: ", ctx.Loc("available_currencies"))
84
		for key := range newData.Currencies {
85
			response = fmt.Sprintf("%v %v", response, key)
86
		}
87
		return
88
	}
89
90
	// TODO: i should complete currency converter
91
	// Converting currencies
92
	if len(args) > 3 && args[0] == "conv" {
93
		ctx.MetricsCommand("currency", "conv")
94
		count, err := strconv.ParseFloat(args[3], 64)
95
		if err != nil {
96
			response = fmt.Sprintf("%v: %v", ctx.Loc("error"), ctx.Loc("nan"))
97
			return
98
		}
99
		if c1, ok1 := newData.Currencies[strings.ToUpper(args[1])]; ok1 {
100
			if c2, ok2 := newData.Currencies[strings.ToUpper(args[2])]; ok2 {
101
				cur1 := c1.Value / float32(c1.Nominal)
102
				cur2 := c2.Value / float32(c2.Nominal)
103
				//cur1Delta := 1 / cur1
104
				cur2Delta := 1 / cur2
105
				res := cur2Delta * (cur1 * float32(count))
106
				response = fmt.Sprintf("`%v %v = %0.2f %v`\n", args[3], args[1], res, args[2])
107
			}
108
		}
109
		return
110
	}
111
	ctx.MetricsCommand("currency", "main")
112
	var arrow string
113
	// Current currency
114
	for _, arg := range args {
115
		if newData.Currencies[arg].Value > 0 {
116
			if newData.Currencies[arg].Value > newData.Currencies[arg].Previous {
117
				arrow = "▲"
118
			} else {
119
				arrow = "▼"
120
			}
121
			response = fmt.Sprintf("%v%v\n`%v %v = %v RUB %v  %0.2v`\n",
122
				response,
123
				newData.Currencies[arg].Name,
124
				newData.Currencies[arg].Nominal,
125
				newData.Currencies[arg].CharCode,
126
				newData.Currencies[arg].Value,
127
				arrow,
128
				newData.Currencies[arg].Value-newData.Currencies[arg].Previous)
129
		}
130
	}
131
	return
132
}
133