dcuinfo.go 9.11 KB
Newer Older
liming6's avatar
liming6 committed
1
2
3
package tui

import (
liming6's avatar
liming6 committed
4
	"fmt"
5
	"get-container/utils"
6
	"regexp"
liming6's avatar
liming6 committed
7
8
	"strconv"
	"strings"
liming6's avatar
liming6 committed
9

liming6's avatar
liming6 committed
10
	"github.com/charmbracelet/bubbles/progress"
liming6's avatar
liming6 committed
11
	tea "github.com/charmbracelet/bubbletea"
liming6's avatar
liming6 committed
12
	"github.com/charmbracelet/lipgloss"
liming6's avatar
liming6 committed
13
14
	"github.com/lucasb-eyer/go-colorful"
	"github.com/muesli/gamut"
15
	"github.com/muesli/termenv"
liming6's avatar
liming6 committed
16
17
18
)

type ModelDCUInfo struct {
19
20
21
22
23
24
25
26
27
28
	width, height          int            // 屏幕尺寸
	pro                    progress.Model // 进度条
	proLowLeight           progress.Model // 低亮度进度条
	proWidth               int            // 进度条宽度
	modMsg                 *ModelMsg      // 缓存的模型信息
	actionMsg              *ActionMsg     // 缓存的动作信息
	darkModule             bool           // 是否为黑暗模式
	top, middle, bottom    string         // 缓存的边框
	topL, middleL, bottomL string         // 缓存的低亮度边框
	subLin                 int            // 边框更新标志
liming6's avatar
liming6 committed
29
30
}

liming6's avatar
liming6 committed
31
32
33
34
35
36
const (
	TopLine    = `╞═══════════════════════════════╪══════════════════════╪══════════════════════╪`
	MiddleLine = `├───────────────────────────────┼──────────────────────┼──────────────────────┼`
	BottomLine = `╞═══════════════════════════════╧══════════════════════╧══════════════════════╪`

	OtherWidth       = 8
liming6's avatar
liming6 committed
37
38
	StaticWidth      = 79 // 固定表格的宽度
	ProgressMinWidth = 15 // 进度条最小宽度
liming6's avatar
liming6 committed
39
40
)

41
42
43
44
var (
	ReDCUName = regexp.MustCompile(`(?i)^[A-Z0-9-_]*`)
)

45
func NewModelDCUInfo(w, h int) *ModelDCUInfo {
46
	return &ModelDCUInfo{width: w, height: h, darkModule: false}
liming6's avatar
liming6 committed
47
48
}

liming6's avatar
liming6 committed
49
func (m *ModelDCUInfo) Init() tea.Cmd {
50
	if m.width < StaticWidth+ProgressMinWidth+OtherWidth {
liming6's avatar
liming6 committed
51
52
53
		return tea.Quit
	}
	m.proWidth = ProgressMinWidth
54
55
	if m.width > StaticWidth+ProgressMinWidth+OtherWidth {
		m.proWidth = m.width - OtherWidth - StaticWidth
liming6's avatar
liming6 committed
56
	}
liming6's avatar
liming6 committed
57
58
59
60
	m.pro = progress.New(progress.WithColorProfile(termenv.TrueColor), progress.WithGradient("#0000ffff", "#ff0000ff"), progress.WithWidth(m.proWidth-5), progress.WithoutPercentage())
	c1, _ := colorful.MakeColor(gamut.Darker(lipgloss.Color("#0000ffff"), 0.8))
	c2, _ := colorful.MakeColor(gamut.Darker(lipgloss.Color("#ff0000ff"), 0.8))
	m.proLowLeight = progress.New(progress.WithColorProfile(termenv.TrueColor), progress.WithGradient(c1.Hex(), c2.Hex()), progress.WithWidth(m.proWidth-5), progress.WithoutPercentage())
liming6's avatar
liming6 committed
61
62
63
	return nil
}

liming6's avatar
liming6 committed
64
65
66
func (m *ModelDCUInfo) Update(inputMsg tea.Msg) (tea.Model, tea.Cmd) {
	switch msg := inputMsg.(type) {
	case *ModelMsg:
67
68
69
70
71
		m.modMsg = msg
		return m, nil
	case tea.WindowSizeMsg:
		m.height = msg.Height
		m.width = msg.Width
liming6's avatar
liming6 committed
72
		return m, nil
liming6's avatar
liming6 committed
73
74
	case *ActionMsg:
		m.actionMsg = msg
liming6's avatar
liming6 committed
75
		if msg.Action != nil && msg.VM == VMMain {
76
77
78
79
			m.darkModule = true
		} else {
			m.darkModule = false
		}
liming6's avatar
liming6 committed
80
		return m, nil
liming6's avatar
liming6 committed
81
	}
liming6's avatar
liming6 committed
82
83
84
85
	return m, nil
}

func (m *ModelDCUInfo) View() string {
86
87
88
	if m.modMsg == nil {
		return ""
	}
liming6's avatar
liming6 committed
89
	lineWidth := 0
90
91
	qmap, qlock := m.modMsg.DCUInfo.GetQuitInfo()
	smap, slock := m.modMsg.DCUInfo.GetSlowInfo()
liming6's avatar
liming6 committed
92
	strBuilder := strings.Builder{}
liming6's avatar
liming6 committed
93
94
	strCache := strings.Builder{}
	var targetDCU int = -1
95
96
	if m.actionMsg != nil {
		targetDCU = m.actionMsg.TargetDCUIndex
liming6's avatar
liming6 committed
97
	}
98
99
100
101
	var borderStr string = myBorder.Left
	if m.darkModule {
		borderStr = LowLeightStyle.Render(borderStr)
	}
102
	infos := make([]string, 0)
liming6's avatar
liming6 committed
103
104

	for i := range 32 {
105
106
107
108
109
		qinfo, haveq := qmap[i]
		sinfo, haves := smap[i]
		if !(haveq || haves) {
			continue
		}
110
111
		isLowStyle := (targetDCU != qinfo.Id && targetDCU != -1) || m.darkModule
		strBuilder.WriteString(borderStr)
liming6's avatar
liming6 committed
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

		strCache.WriteByte(' ')
		strCache.WriteString(FormatStr(strconv.Itoa(qinfo.Id), 4, lipgloss.Left))
		strCache.WriteByte(' ')
		strCache.WriteString(FormatStr(ReDCUName.FindString(qinfo.Name), 8, lipgloss.Left))
		strCache.WriteByte(' ')
		strCache.WriteString(FormatStr(qinfo.PerformanceLevel, 15, lipgloss.Right))
		strCache.WriteByte(' ')

		if isLowStyle {
			str := strCache.String()
			strBuilder.WriteString(LowLeightStyle.Render(str))
		} else {
			strBuilder.WriteString(strCache.String())
		}
		strCache.Reset()
128
		strBuilder.WriteString(borderStr)
liming6's avatar
liming6 committed
129
130
131
132
133
134
135
136
137

		strCache.WriteByte(' ')
		strCache.WriteString(FormatStr(qinfo.BusId, 13, lipgloss.Left))
		strCache.WriteByte(' ')
		strCache.WriteString(FormatStr("Off", 6, lipgloss.Right))
		strCache.WriteByte(' ')
		if isLowStyle {
			str := strCache.String()
			strBuilder.WriteString(LowLeightStyle.Render(str))
liming6's avatar
liming6 committed
138
		} else {
liming6's avatar
liming6 committed
139
			strBuilder.WriteString(strCache.String())
liming6's avatar
liming6 committed
140
		}
liming6's avatar
liming6 committed
141
142
143
144
		strCache.Reset()

		strCache.WriteByte(' ')
		strCache.WriteString(FormatStr("Off", 16, lipgloss.Left))
145
		strBuilder.WriteString(borderStr)
liming6's avatar
liming6 committed
146
		strCache.WriteByte(' ')
147
		if sinfo.Ecc.Load() {
liming6's avatar
liming6 committed
148
149
150
151
152
153
154
155
			strCache.WriteString(FormatStr("On", 3, lipgloss.Right))
		} else {
			strCache.WriteString(FormatStr("Off", 3, lipgloss.Right))
		}
		strCache.WriteByte(' ')
		if isLowStyle {
			str := strCache.String()
			strBuilder.WriteString(LowLeightStyle.Render(str))
liming6's avatar
liming6 committed
156
		} else {
liming6's avatar
liming6 committed
157
			strBuilder.WriteString(strCache.String())
liming6's avatar
liming6 committed
158
		}
liming6's avatar
liming6 committed
159
		strCache.Reset()
160
		strBuilder.WriteString(borderStr)
liming6's avatar
liming6 committed
161
162
163
164
165
166
167
168
169
170

		if isLowStyle {
			strBuilder.WriteString(LowLeightStyle.Render(" DCU: "))
			strBuilder.WriteString(m.proLowLeight.ViewAs(float64(qinfo.DCUUTil / 100)))
			strBuilder.WriteString(LowLeightStyle.Render(fmt.Sprintf(" %3d%% ", int(qinfo.DCUUTil))))
		} else {
			strBuilder.WriteString(" DCU: ")
			strBuilder.WriteString(m.pro.ViewAs(float64(qinfo.DCUUTil / 100)))
			strBuilder.WriteString(fmt.Sprintf(" %3d%% ", int(qinfo.DCUUTil)))
		}
171
		strBuilder.WriteString(borderStr)
liming6's avatar
liming6 committed
172
		strBuilder.WriteByte('\n')
173
		strBuilder.WriteString(borderStr)
liming6's avatar
liming6 committed
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189

		strCache.WriteByte(' ')
		strCache.WriteString(FormatStr(qinfo.Fan, 4, lipgloss.Left))
		strCache.WriteByte(' ')
		strCache.WriteString(FormatStr(fmt.Sprintf("%.1fC", qinfo.Temp), 6, lipgloss.Left))
		strCache.WriteByte(' ')
		strCache.WriteString(FormatStr(fmt.Sprintf("%.1fW / %.1fW", qinfo.PwrAvg, qinfo.PwrCap), 17, lipgloss.Right))
		strCache.WriteByte(' ')

		if isLowStyle {
			str := strCache.String()
			strBuilder.WriteString(LowLeightStyle.Render(str))
		} else {
			strBuilder.WriteString(strCache.String())
		}
		strCache.Reset()
190
		strBuilder.WriteString(borderStr)
liming6's avatar
liming6 committed
191
192
193
194
195
196
197
198
199
200
201
202
203

		if isLowStyle {
			strCache.WriteByte(' ')
			strCache.WriteString(FormatStr(fmt.Sprintf("%dMiB / %dMiB", qinfo.MemUsed/uint64(utils.MiB), qinfo.MemTotal/uint64(utils.MiB)), 20, lipgloss.Right))
			strCache.WriteByte(' ')
			strBuilder.WriteString(LowLeightStyle.Render(strCache.String()))
			strCache.Reset()
		} else {
			strBuilder.WriteByte(' ')
			strBuilder.WriteString(FormatStr(fmt.Sprintf("%dMiB / %dMiB", qinfo.MemUsed/uint64(utils.MiB), qinfo.MemTotal/uint64(utils.MiB)), 20, lipgloss.Right))
			strBuilder.WriteByte(' ')
		}

204
		strBuilder.WriteString(borderStr)
liming6's avatar
liming6 committed
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221

		if isLowStyle {
			strCache.WriteByte(' ')
			strCache.WriteString(FormatStr(fmt.Sprintf("%.1f%%", qinfo.DCUUTil), 6, lipgloss.Left))
			strCache.WriteByte(' ')
			strCache.WriteString(FormatStr(sinfo.PwrMode.Load().(string), 13, lipgloss.Right))
			strCache.WriteByte(' ')
			strBuilder.WriteString(LowLeightStyle.Render(strCache.String()))
			strCache.Reset()
		} else {
			strBuilder.WriteByte(' ')
			strBuilder.WriteString(FormatStr(fmt.Sprintf("%.1f%%", qinfo.DCUUTil), 6, lipgloss.Left))
			strBuilder.WriteByte(' ')
			strBuilder.WriteString(FormatStr(sinfo.PwrMode.Load().(string), 13, lipgloss.Right))
			strBuilder.WriteByte(' ')
		}

222
		strBuilder.WriteString(borderStr)
liming6's avatar
liming6 committed
223
224
225
226
227
228
229
230
231
232
233
234
235
236

		if isLowStyle {
			strCache.WriteString(" Mem: ")
			strCache.WriteString(m.proLowLeight.ViewAs(float64(qinfo.MemUsed) / float64(qinfo.MemTotal)))
			strCache.WriteString(LowLeightStyle.Render(fmt.Sprintf(" %3d%% ", int(100*float64(qinfo.MemUsed)/float64(qinfo.MemTotal)))))
			strBuilder.WriteString(LowLeightStyle.Render(strCache.String()))
			strCache.Reset()
		} else {
			strBuilder.WriteString(" Mem: ")
			strBuilder.WriteString(m.pro.ViewAs(float64(qinfo.MemUsed) / float64(qinfo.MemTotal)))
			strBuilder.WriteByte(' ')
			strBuilder.WriteString(fmt.Sprintf("%3d%%", int(100*float64(qinfo.MemUsed)/float64(qinfo.MemTotal))))
			strBuilder.WriteByte(' ')
		}
237
238
		strBuilder.WriteString(borderStr)
		strBuilder.WriteByte('\n')
239
		infos = append(infos, strBuilder.String())
liming6's avatar
liming6 committed
240
241
		strBuilder.Reset()
	}
242
243
	slock.Unlock()
	qlock.Unlock()
liming6's avatar
liming6 committed
244
245
246
	if len(infos) > 0 {
		lineWidth = lipgloss.Width(infos[0])
	}
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
	subLen := max(lineWidth-StaticWidth-1, 0)
	if subLen != m.subLin {
		top := TopLine + strings.Repeat("═", subLen) + "╕"
		middle := MiddleLine + strings.Repeat("─", subLen) + "┤"
		bottom := BottomLine + strings.Repeat("═", subLen) + "╡"
		m.topL = LowLeightStyle.Render(top) + "\n"
		m.middleL = LowLeightStyle.Render(middle) + "\n"
		m.bottomL = LowLeightStyle.Render(bottom) + "\n"
		m.top = top + "\n"
		m.middle = middle + "\n"
		m.bottom = bottom + "\n"
	}
	if m.darkModule {
		return m.topL + strings.Join(infos, m.middleL) + m.bottomL
	} else {
		return m.top + strings.Join(infos, m.middle) + m.bottom
liming6's avatar
liming6 committed
263
	}
liming6's avatar
liming6 committed
264
}