forked from mop-tracker/mop
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprofile.go
134 lines (115 loc) · 4.08 KB
/
profile.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright (c) 2013-2016 by Michael Dvorkin. All Rights Reserved.
// Use of this source code is governed by a MIT-style license that can
// be found in the LICENSE file.
package mop
import (
`encoding/json`
`io/ioutil`
`os/user`
`sort`
)
// File name in user's home directory where we store the settings.
const moprc = `/.moprc`
// Profile manages Mop program settings as defined by user (ex. list of
// stock tickers). The settings are serialized using JSON and saved in
// the ~/.moprc file.
type Profile struct {
Tickers []string // List of stock tickers to display.
MarketRefresh int // Time interval to refresh market data.
QuotesRefresh int // Time interval to refresh stock quotes.
SortColumn int // Column number by which we sort stock quotes.
Ascending bool // True when sort order is ascending.
Grouped bool // True when stocks are grouped by advancing/declining.
selectedColumn int // Stores selected column number when the column editor is active.
}
// Creates the profile and attempts to load the settings from ~/.moprc file.
// If the file is not there it gets created with default values.
func NewProfile() *Profile {
profile := &Profile{}
data, err := ioutil.ReadFile(profile.defaultFileName())
if err != nil { // Set default values:
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.Grouped = false // Stock quotes are *not* grouped by advancing/declining.
profile.Tickers = []string{`AAPL`, `C`, `GOOG`, `IBM`, `KO`, `ORCL`, `V`}
profile.SortColumn = 0 // Stock quotes are sorted by ticker name.
profile.Ascending = true // A to Z.
profile.Save()
} else {
json.Unmarshal(data, profile)
}
profile.selectedColumn = -1
return profile
}
// Save serializes settings using JSON and saves them in ~/.moprc file.
func (profile *Profile) Save() error {
data, err := json.Marshal(profile)
if err != nil {
return err
}
return ioutil.WriteFile(profile.defaultFileName(), data, 0644)
}
// AddTickers updates the list of existing tikers to add the new ones making
// sure there are no duplicates.
func (profile *Profile) AddTickers(tickers []string) (added int, err error) {
added, err = 0, nil
existing := make(map[string]bool)
// Build a hash of existing tickers so we could look it up quickly.
for _, ticker := range profile.Tickers {
existing[ticker] = true
}
// Iterate over the list of new tickers excluding the ones that
// already exist.
for _, ticker := range tickers {
if _, found := existing[ticker]; !found {
profile.Tickers = append(profile.Tickers, ticker)
added++
}
}
if added > 0 {
sort.Strings(profile.Tickers)
err = profile.Save()
}
return
}
// RemoveTickers removes requested stock tickers from the list we track.
func (profile *Profile) RemoveTickers(tickers []string) (removed int, err error) {
removed, err = 0, nil
for _, ticker := range tickers {
for i, existing := range profile.Tickers {
if ticker == existing {
// Requested ticker is there: remove i-th slice item.
profile.Tickers = append(profile.Tickers[:i], profile.Tickers[i+1:]...)
removed++
}
}
}
if removed > 0 {
err = profile.Save()
}
return
}
// Reorder gets called by the column editor to either reverse sorting order
// for the current column, or to pick another sort column.
func (profile *Profile) Reorder() error {
if profile.selectedColumn == profile.SortColumn {
profile.Ascending = !profile.Ascending // Reverse sort order.
} else {
profile.SortColumn = profile.selectedColumn // Pick new sort column.
}
return profile.Save()
}
// Regroup flips the flag that controls whether the stock quotes are grouped
// by advancing/declining issues.
func (profile *Profile) Regroup() error {
profile.Grouped = !profile.Grouped
return profile.Save()
}
//-----------------------------------------------------------------------------
func (profile *Profile) defaultFileName() string {
usr, err := user.Current()
if err != nil {
panic(err)
}
return usr.HomeDir + moprc
}