Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
liming6
dcu-process-montor
Commits
c915d1bd
Commit
c915d1bd
authored
Nov 24, 2025
by
liming6
Browse files
fix 处理条形图显示逻辑
parent
ed4a196f
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
274 additions
and
113 deletions
+274
-113
cmd/hytop/main.go
cmd/hytop/main.go
+1
-1
cmd/hytop/tui/sysload.go
cmd/hytop/tui/sysload.go
+10
-10
cmd/hytop/tui/timechart.go
cmd/hytop/tui/timechart.go
+118
-80
cmd/hytop/tui/tui_test.go
cmd/hytop/tui/tui_test.go
+0
-22
test-data/mw.log
test-data/mw.log
+22
-0
utils/char.go
utils/char.go
+87
-0
utils/utils_test.go
utils/utils_test.go
+36
-0
No files found.
cmd/hytop/main.go
View file @
c915d1bd
...
...
@@ -21,7 +21,7 @@ func main() {
log
.
Fatalf
(
"error init data backend: %v"
,
err
)
}
model
:=
tui
.
NewModelMain
(
w
,
h
)
if
_
,
err
:=
tea
.
NewProgram
(
&
model
,
tea
.
WithAltScreen
()
)
.
Run
();
err
!=
nil
{
if
_
,
err
:=
tea
.
NewProgram
(
&
model
)
.
Run
();
err
!=
nil
{
log
.
Fatalf
(
"error create program; %v"
,
err
)
}
backend
.
Shutdown
()
...
...
cmd/hytop/tui/sysload.go
View file @
c915d1bd
...
...
@@ -65,16 +65,16 @@ func NewModelSysLoad(width int) *ModelSysLoad {
}
return
0
})
result
.
colors
=
gamut
.
Blends
(
lipgloss
.
Color
(
"#ff0000"
),
lipgloss
.
Color
(
"#00ff00ff"
),
SysLoadHeight
)
subLine
:=
width
-
StaticWidth
-
1
result
.
SysMem
=
NewTimeChart
(
SysLoadWidth
,
SysLoadHeight
,
0
,
100
,
map
[
string
]
lipgloss
.
Color
{
"default"
:
lipgloss
.
Color
(
"#20ff2cff"
)})
result
.
SysCPU
=
NewTimeChart
(
SysLoadWidth
,
SysLoadHeight
,
0
,
100
,
map
[
string
]
lipgloss
.
Color
{
"default"
:
lipgloss
.
Color
(
"#ff3030ff"
)})
result
.
DCU
=
NewTimeChart
(
subLine
,
SysLoadHeight
,
0
,
100
,
map
[
string
]
lipgloss
.
Color
{
"default"
:
lipgloss
.
Color
(
"#27ffdbff"
)})
result
.
DCUMem
=
NewTimeChart
(
subLine
,
SysLoadHeight
,
0
,
100
,
map
[
string
]
lipgloss
.
Color
{
"default"
:
lipgloss
.
Color
(
"#20b1ffff"
)})
result
.
SysMem
=
NewTimeChart
(
SysLoadWidth
,
SysLoadHeight
,
0
,
100
,
result
.
colors
)
result
.
SysCPU
=
NewTimeChart
(
SysLoadWidth
,
SysLoadHeight
,
0
,
100
,
result
.
colors
)
result
.
DCU
=
NewTimeChart
(
subLine
,
SysLoadHeight
,
0
,
100
,
result
.
colors
)
result
.
DCUMem
=
NewTimeChart
(
subLine
,
SysLoadHeight
,
0
,
100
,
result
.
colors
)
result
.
topLine
=
myBorder
.
MiddleLeft
+
genXAxis
(
SysLoadWidth
)
+
myBorder
.
Middle
+
genXAxis
(
subLine
)
+
myBorder
.
MiddleRight
result
.
bottomLine
=
"╞"
+
strings
.
Repeat
(
myBorder
.
Bottom
,
SysLoadWidth
)
+
"╧"
+
strings
.
Repeat
(
myBorder
.
Bottom
,
subLine
)
+
"╡"
result
.
style
=
lipgloss
.
NewStyle
()
result
.
colors
=
gamut
.
Blends
(
lipgloss
.
Color
(
"#ff0000"
),
lipgloss
.
Color
(
"#00ff00ff"
),
SysLoadHeight
)
return
&
result
}
...
...
@@ -212,22 +212,22 @@ func (m *ModelSysLoad) updateInfo(t *ModelMsg) {
wg
.
Add
(
4
)
go
func
()
{
defer
wg
.
Done
()
m1
,
_
:=
m
.
SysMem
.
Update
(
MyTimeChartMsg
{
Points
:
map
[
string
]
[]
tchart
.
TimePoint
{
"default"
:
{{
Time
:
t
.
t
,
Value
:
s
.
MemUsedPercent
}}}
}
)
m1
,
_
:=
m
.
SysMem
.
Update
(
MyTimeChartMsg
{[]
tchart
.
TimePoint
{{
Time
:
t
.
t
,
Value
:
s
.
MemUsedPercent
}}})
m
.
SysMem
=
m1
.
(
*
MyTimeChart
)
}()
go
func
()
{
defer
wg
.
Done
()
m2
,
_
:=
m
.
SysCPU
.
Update
(
MyTimeChartMsg
{
Points
:
map
[
string
]
[]
tchart
.
TimePoint
{
"default"
:
{{
Time
:
t
.
t
,
Value
:
s
.
CPUPercent
}}}
}
)
m2
,
_
:=
m
.
SysCPU
.
Update
(
MyTimeChartMsg
{[]
tchart
.
TimePoint
{{
Time
:
t
.
t
,
Value
:
s
.
CPUPercent
}}})
m
.
SysCPU
=
m2
.
(
*
MyTimeChart
)
}()
go
func
()
{
defer
wg
.
Done
()
m3
,
_
:=
m
.
DCU
.
Update
(
MyTimeChartMsg
{
Points
:
map
[
string
]
[]
tchart
.
TimePoint
{
"default"
:
{{
Time
:
t
.
t
,
Value
:
float64
(
s
.
DCUUsageAvg
)}}}
}
)
m3
,
_
:=
m
.
DCU
.
Update
(
MyTimeChartMsg
{[]
tchart
.
TimePoint
{{
Time
:
t
.
t
,
Value
:
float64
(
s
.
DCUUsageAvg
)}}})
m
.
DCU
=
m3
.
(
*
MyTimeChart
)
}()
go
func
()
{
defer
wg
.
Done
()
m4
,
_
:=
m
.
DCUMem
.
Update
(
MyTimeChartMsg
{
Points
:
map
[
string
]
[]
tchart
.
TimePoint
{
"default"
:
{{
Time
:
t
.
t
,
Value
:
float64
(
s
.
DCUMemUsageAvg
)}}}
}
)
m4
,
_
:=
m
.
DCUMem
.
Update
(
MyTimeChartMsg
{[]
tchart
.
TimePoint
{{
Time
:
t
.
t
,
Value
:
float64
(
s
.
DCUMemUsageAvg
)}}})
m
.
DCUMem
=
m4
.
(
*
MyTimeChart
)
}()
// 存放数据
...
...
cmd/hytop/tui/timechart.go
View file @
c915d1bd
package
tui
import
(
"image/color"
"sort"
"strconv"
"strings"
...
...
@@ -8,11 +9,13 @@ import (
"time"
"get-container/cmd/hytop/tchart"
"get-container/utils"
"github.com/NimbleMarkets/ntcharts/canvas/runes"
tea
"github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
zone
"github.com/lrstanley/bubblezone"
"github.com/lucasb-eyer/go-colorful"
)
const
(
...
...
@@ -56,23 +59,22 @@ func genXAxis(l int) string {
// MyTimeChartMsg 时间流表消息,用于插入数据
type
MyTimeChartMsg
struct
{
Points
map
[
string
]
[]
tchart
.
TimePoint
Points
[]
tchart
.
TimePoint
}
// MyTimeChart 特化的时间流表,时间区域就是宽度的2倍,单位是秒
type
MyTimeChart
struct
{
chart
*
tchart
.
Model
// 原始图表
zM
*
zone
.
Manager
// 区域管理
dataSet
map
[
string
]
[]
tchart
.
TimePoint
// 数据点
points
[]
tchart
.
TimePoint
// 数据点
width
,
height
int
// 图表的高度和宽度
max
,
min
float64
// y轴的最值
dataStyle
map
[
string
]
lipgloss
.
Style
// 记录每个数据集的样式
lockDataSet
sync
.
RWMutex
// 保护dataSet的并发读写
lockChart
sync
.
RWMutex
// 保护chart的数据集的并发读写
lockPoints
sync
.
RWMutex
// 保护dataSet的并发读写
color
[]
color
.
Color
}
// New 新建图表,其中dataSet的Key为数据集名称,value为数据集的颜色
func
NewTimeChart
(
width
,
height
int
,
vmin
,
vmax
float64
,
dataSet
map
[
string
]
lipgloss
.
Color
)
*
MyTimeChart
{
func
NewTimeChart
(
width
,
height
int
,
vmin
,
vmax
float64
,
color
[]
color
.
Color
)
*
MyTimeChart
{
result
:=
MyTimeChart
{}
result
.
max
=
vmax
result
.
min
=
vmin
...
...
@@ -80,70 +82,30 @@ func NewTimeChart(width, height int, vmin, vmax float64, dataSet map[string]lipg
result
.
height
=
height
zoneManager
:=
zone
.
New
()
result
.
zM
=
zoneManager
result
.
dataSet
=
make
(
map
[
string
][]
tchart
.
TimePoint
)
result
.
dataStyle
=
make
(
map
[
string
]
lipgloss
.
Style
)
result
.
lockChart
=
sync
.
RWMutex
{}
result
.
lockDataSet
=
sync
.
RWMutex
{}
result
.
lockDataSet
.
Lock
()
for
k
,
v
:=
range
dataSet
{
result
.
dataSet
[
k
]
=
make
([]
tchart
.
TimePoint
,
(
result
.
width
*
2
)
+
1
)
result
.
dataStyle
[
k
]
=
lipgloss
.
NewStyle
()
.
Foreground
(
v
)
}
initPoints
:=
make
([]
tchart
.
TimePoint
,
(
result
.
width
*
2
)
+
1
)
result
.
lockPoints
=
sync
.
RWMutex
{}
result
.
lockPoints
.
Lock
()
result
.
points
=
make
([]
tchart
.
TimePoint
,
(
result
.
width
*
2
)
+
1
)
// 准备数据,数据间隔为1秒
now
:=
time
.
Now
()
for
i
:=
result
.
width
*
2
;
i
>=
0
;
i
--
{
initP
oints
[
i
]
=
tchart
.
TimePoint
{
Time
:
now
.
Add
(
time
.
Duration
(
-
i
)
*
time
.
Second
),
Value
:
vmin
}
result
.
p
oints
[
i
]
=
tchart
.
TimePoint
{
Time
:
now
.
Add
(
time
.
Duration
(
-
i
)
*
time
.
Second
),
Value
:
vmin
}
}
for
k
:=
range
dataSet
{
copy
(
result
.
dataSet
[
k
],
initPoints
)
}
result
.
lockDataSet
.
Unlock
()
result
.
lockPoints
.
Unlock
()
s
:=
tchart
.
New
(
width
,
height
+
1
,
tchart
.
WithLineStyle
(
runes
.
ThinLineStyle
),
tchart
.
WithZoneManager
(
zoneManager
),
tchart
.
WithYRange
(
vmin
,
vmax
),
tchart
.
WithXYSteps
(
0
,
0
),
tchart
.
WithTimeSeries
(
result
.
points
),
)
wg
:=
sync
.
WaitGroup
{}
wg
.
Add
(
len
(
dataSet
))
for
k
:=
range
dataSet
{
points
:=
result
.
dataSet
[
k
]
style
:=
result
.
dataStyle
[
k
]
go
func
(
ps
[]
tchart
.
TimePoint
,
st
lipgloss
.
Style
,
key
string
)
{
result
.
lockChart
.
Lock
()
s
.
SetDataSet
(
key
,
ps
)
s
.
SetDataSetStyle
(
key
,
st
)
result
.
lockChart
.
Unlock
()
wg
.
Done
()
}(
points
,
style
,
k
)
}
wg
.
Wait
()
result
.
chart
=
&
s
result
.
color
=
color
return
&
result
}
func
(
m
*
MyTimeChart
)
PutPoint
(
points
map
[
string
][]
tchart
.
TimePoint
)
{
// 更新chart
s
:=
tchart
.
New
(
m
.
width
,
m
.
height
+
1
,
tchart
.
WithLineStyle
(
runes
.
ThinLineStyle
),
tchart
.
WithZoneManager
(
m
.
zM
),
tchart
.
WithYRange
(
m
.
min
,
m
.
max
),
tchart
.
WithXYSteps
(
0
,
0
),
)
m
.
chart
=
&
s
wg
:=
sync
.
WaitGroup
{}
wg
.
Add
(
len
(
m
.
dataSet
))
keys
,
index
:=
make
([]
string
,
len
(
m
.
dataSet
)),
0
for
k
:=
range
m
.
dataSet
{
keys
[
index
]
=
k
index
++
}
for
_
,
k
:=
range
keys
{
newPoints
:=
points
[
k
]
oldPoints
:=
m
.
dataSet
[
k
]
go
func
(
ops
,
nps
[]
tchart
.
TimePoint
,
ds
map
[
string
][]
tchart
.
TimePoint
,
key
string
)
{
ops
=
append
(
ops
,
nps
...
)
func
(
m
*
MyTimeChart
)
PutPoint
(
points
[]
tchart
.
TimePoint
)
{
ops
:=
append
(
m
.
points
,
points
...
)
// 排序
sort
.
Slice
(
ops
,
func
(
i
,
j
int
)
bool
{
return
ops
[
i
]
.
Time
.
Before
(
ops
[
j
]
.
Time
)
})
...
...
@@ -155,18 +117,18 @@ func (m *MyTimeChart) PutPoint(points map[string][]tchart.TimePoint) {
break
}
}
nps
=
append
(
make
([]
tchart
.
TimePoint
,
0
),
ops
[
targetIndex
:
]
...
)
m
.
lockDataSet
.
Lock
()
ds
[
key
]
=
nps
m
.
lockDataSet
.
Unlock
()
m
.
lockChart
.
Lock
()
s
.
SetDataSet
(
key
,
nps
)
s
.
SetDataSetStyle
(
key
,
m
.
dataStyle
[
key
])
m
.
lockChart
.
Unlock
()
wg
.
Done
(
)
}(
oldPoints
,
newPoints
,
m
.
dataSet
,
k
)
}
wg
.
Wait
()
nps
:
=
append
(
make
([]
tchart
.
TimePoint
,
0
),
ops
[
targetIndex
:
]
...
)
m
.
points
=
nps
s
:=
tchart
.
New
(
m
.
width
,
m
.
height
+
1
,
tchart
.
WithLineStyle
(
runes
.
ThinLineStyle
),
tchart
.
WithZoneManager
(
m
.
zM
),
tchart
.
WithYRange
(
m
.
min
,
m
.
max
),
tchart
.
WithXYSteps
(
0
,
0
),
tchart
.
WithTimeSeries
(
m
.
points
),
)
// 插入数据
m
.
chart
=
nil
m
.
chart
=
&
s
m
.
chart
.
DrawXYAxisAndLabel
()
m
.
chart
.
DrawBrailleAll
()
}
...
...
@@ -187,9 +149,85 @@ func (m *MyTimeChart) Update(inputMsg tea.Msg) (tea.Model, tea.Cmd) {
}
func
(
m
*
MyTimeChart
)
View
()
string
{
rl
:=
m
.
lockChart
.
RLocker
()
rl
.
Lock
()
str
:=
m
.
zM
.
Scan
(
m
.
chart
.
View
())
rl
.
Unlock
()
return
str
[
m
.
width
+
1
:
]
sb
:=
strings
.
Builder
{}
sb
.
WriteString
(
str
[
m
.
width
+
1
:
])
str
=
sb
.
String
()
// return str
lines
:=
strings
.
Split
(
strings
.
Trim
(
str
,
"
\n
"
),
"
\n
"
)
runes
:=
make
([][]
rune
,
len
(
lines
))
for
k
,
v
:=
range
lines
{
runes
[
k
]
=
[]
rune
(
v
)
}
width
:=
lipgloss
.
Width
(
str
)
height
:=
lipgloss
.
Height
(
str
)
for
col
:=
range
width
{
firstLine
:=
-
1
var
charStat
utils
.
CharType
=
utils
.
CharEmpty
for
line
:=
range
height
{
c
:=
runes
[
line
][
col
]
charType
:=
utils
.
GetCharType
(
c
)
if
charType
!=
utils
.
CharEmpty
&&
firstLine
==
-
1
{
firstLine
=
line
}
if
firstLine
==
-
1
{
continue
}
if
firstLine
==
line
{
// 遇到了一列的第一个非空字符
if
t
,
have
:=
utils
.
MM
[
c
];
have
{
runes
[
line
][
col
]
=
t
}
charStat
=
utils
.
CharTypeOr
(
charStat
,
utils
.
GetCharType
(
runes
[
line
][
col
]))
}
else
{
// 第一个非空字符下面的字符
switch
charType
{
case
utils
.
CharEmpty
:
switch
charStat
{
case
utils
.
CharLeft
:
runes
[
line
][
col
]
=
utils
.
LeftFullMW
case
utils
.
CharRight
:
runes
[
line
][
col
]
=
utils
.
RightFullMW
case
utils
.
CharFull
:
runes
[
line
][
col
]
=
utils
.
FullMW
}
case
utils
.
CharLeft
:
switch
utils
.
CharTypeOr
(
charStat
,
utils
.
CharLeft
)
{
case
utils
.
CharLeft
:
runes
[
line
][
col
]
=
utils
.
LeftFullMW
case
utils
.
CharRight
:
runes
[
line
][
col
]
=
utils
.
RightFullMW
case
utils
.
CharFull
:
runes
[
line
][
col
]
=
utils
.
FullMW
}
charStat
=
utils
.
CharTypeOr
(
charStat
,
utils
.
CharLeft
)
case
utils
.
CharRight
:
switch
utils
.
CharTypeOr
(
charStat
,
utils
.
CharRight
)
{
case
utils
.
CharLeft
:
runes
[
line
][
col
]
=
utils
.
LeftFullMW
case
utils
.
CharRight
:
runes
[
line
][
col
]
=
utils
.
RightFullMW
case
utils
.
CharFull
:
runes
[
line
][
col
]
=
utils
.
FullMW
}
charStat
=
utils
.
CharTypeOr
(
charStat
,
utils
.
CharRight
)
case
utils
.
CharFull
:
charStat
=
utils
.
CharFull
}
}
}
}
resultLines
:=
make
([]
string
,
height
)
for
k
,
v
:=
range
runes
{
resultLines
[
k
]
=
string
(
v
)
}
if
len
(
m
.
color
)
==
height
{
for
k
,
v
:=
range
resultLines
{
c
,
_
:=
colorful
.
MakeColor
(
m
.
color
[
k
])
resultLines
[
k
]
=
lipgloss
.
NewStyle
()
.
Foreground
(
lipgloss
.
Color
(
c
.
Hex
()))
.
Render
(
v
)
}
}
return
strings
.
Join
(
resultLines
,
"
\n
"
)
}
cmd/hytop/tui/tui_test.go
View file @
c915d1bd
...
...
@@ -3,7 +3,6 @@ package tui
import
(
"fmt"
"get-container/cmd/hytop/backend"
"get-container/cmd/hytop/tchart"
"testing"
"time"
...
...
@@ -50,27 +49,6 @@ func TestModel(t *testing.T) {
t
.
Log
(
str
)
}
func
TestMyTimeChart
(
t
*
testing
.
T
)
{
chart
:=
NewTimeChart
(
100
,
5
,
0.0
,
100.0
,
map
[
string
]
lipgloss
.
Color
{
"default"
:
lipgloss
.
Color
(
"#ff2222ff"
),
"other"
:
lipgloss
.
Color
(
"#0037ffff"
)})
chart
.
Init
()
s
:=
chart
.
View
()
t
.
Logf
(
"
\n
%s"
,
s
)
time
.
Sleep
(
time
.
Second
)
now
:=
time
.
Now
()
points
:=
make
(
map
[
string
][]
tchart
.
TimePoint
)
points
[
"default"
]
=
[]
tchart
.
TimePoint
{{
Time
:
now
,
Value
:
94.0
}}
points
[
"other"
]
=
[]
tchart
.
TimePoint
{{
Time
:
now
,
Value
:
94.0
}}
chart
.
Update
(
MyTimeChartMsg
{
Points
:
points
})
time
.
Sleep
(
time
.
Second
)
now
=
time
.
Now
()
points
=
make
(
map
[
string
][]
tchart
.
TimePoint
)
points
[
"default"
]
=
[]
tchart
.
TimePoint
{{
Time
:
now
,
Value
:
0.0
}}
points
[
"other"
]
=
[]
tchart
.
TimePoint
{{
Time
:
now
,
Value
:
0.0
}}
chart
.
Update
(
MyTimeChartMsg
{
Points
:
points
})
t
.
Logf
(
"
\n
%s"
,
chart
.
View
())
t
.
Logf
(
"ok"
)
}
func
TestBinaryHeap
(
t
*
testing
.
T
)
{
err
:=
backend
.
Init
()
if
err
!=
nil
{
...
...
test-data/mw.log
0 → 100644
View file @
c915d1bd
⠀|⠁|⠂|⠃|⠄|⠅|⠆|⠇|⠈|⠉|⠊|⠋|⠌|⠍|⠎|⠏
⠐|⠑|⠒|⠓|⠔|⠕|⠖|⠗|⠘|⠙|⠚|⠛|⠜|⠝|⠞|⠟
⠠|⠡|⠢|⠣|⠤|⠥|⠦|⠧|⠨|⠩|⠪|⠫|⠬|⠭|⠮|⠯
⠰|⠱|⠲|⠳|⠴|⠵|⠶|⠷|⠸|⠹|⠺|⠻|⠼|⠽|⠾|⠿
⡀|⡁|⡂|⡃|⡄|⡅|⡆|⡇|⡈|⡉|⡊|⡋|⡌|⡍|⡎|⡏
⡐|⡑|⡒|⡓|⡔|⡕|⡖|⡗|⡘|⡙|⡚|⡛|⡜|⡝|⡞|⡟
⡠|⡡|⡢|⡣|⡤|⡥|⡦|⡧|⡨|⡩|⡪|⡫|⡬|⡭|⡮|⡯
⡰|⡱|⡲|⡳|⡴|⡵|⡶|⡷|⡸|⡹|⡺|⡻|⡼|⡽|⡾|⡿
⢀|⢁|⢂|⢃|⢄|⢅|⢆|⢇|⢈|⢉|⢊|⢋|⢌|⢍|⢎|⢏
⢐|⢑|⢒|⢓|⢔|⢕|⢖|⢗|⢘|⢙|⢚|⢛|⢜|⢝|⢞|⢟
⢠|⢡|⢢|⢣|⢤|⢥|⢦|⢧|⢨|⢩|⢪|⢫|⢬|⢭|⢮|⢯
⢰|⢱|⢲|⢳|⢴|⢵|⢶|⢷|⢸|⢹|⢺|⢻|⢼|⢽|⢾|⢿
⣀|⣁|⣂|⣃|⣄|⣅|⣆|⣇|⣈|⣉|⣊|⣋|⣌|⣍|⣎|⣏
⣐|⣑|⣒|⣓|⣔|⣕|⣖|⣗|⣘|⣙|⣚|⣛|⣜|⣝|⣞|⣟
⣠|⣡|⣢|⣣|⣤|⣥|⣦|⣧|⣨|⣩|⣪|⣫|⣬|⣭|⣮|⣯
⣰|⣱|⣲|⣳|⣴|⣵|⣶|⣷|⣸|⣹|⣺|⣻|⣼|⣽|⣾|⣿
⠁⠂⠄⡀
utils/char.go
0 → 100644
View file @
c915d1bd
package
utils
import
(
"slices"
"strings"
)
type
CharType
byte
const
(
MW
=
`
⠀⠀|⠁⡇|⠂⡆|⠃⡇|⠄⡄|⠅⡇|⠆⡆|⠇⡇|⠈⢸|⠉⣿|⠊⣾|⠋⣿|⠌⣼|⠍⣿|⠎⣾|⠏⣿
⠐⢰|⠑⣷|⠒⣶|⠓⣷|⠔⣴|⠕⣷|⠖⣶|⠗⣷|⠘⢸|⠙⣿|⠚⣾|⠛⣿|⠜⣼|⠝⣿|⠞⣾|⠟⣿
⠠⢠|⠡⣧|⠢⣦|⠣⣧|⠤⣤|⠥⣧|⠦⣦|⠧⣧|⠨⢸|⠩⣿|⠪⣾|⠫⣿|⠬⣼|⠭⣿|⠮⣾|⠯⣿
⠰⢰|⠱⣷|⠲⣶|⠳⣷|⠴⣴|⠵⣷|⠶⣶|⠷⣷|⠸⢸|⠹⣿|⠺⣾|⠻⣿|⠼⣼|⠽⣿|⠾⣾|⠿⣿
⡀⡀|⡁⡇|⡂⡆|⡃⡇|⡄⡄|⡅⡇|⡆⡆|⡇⡇|⡈⣸|⡉⣿|⡊⣾|⡋⣿|⡌⣾|⡍⣿|⡎⣾|⡏⣿
⡐⣰|⡑⣷|⡒⣶|⡓⣷|⡔⣴|⡕⣷|⡖⣶|⡗⣷|⡘⣸|⡙⣿|⡚⣾|⡛⣿|⡜⣼|⡝⣿|⡞⣾|⡟⣿
⡠⣠|⡡⣧|⡢⣦|⡣⣧|⡤⣤|⡥⣧|⡦⣦|⡧⣧|⡨⣸|⡩⣿|⡪⣾|⡫⣿|⡬⣼|⡭⣿|⡮⣾|⡯⣿
⡰⣰|⡱⣷|⡲⣶|⡳⣷|⡴⣴|⡵⣷|⡶⣶|⡷⣷|⡸⣸|⡹⣿|⡺⣾|⡻⣿|⡼⣼|⡽⣿|⡾⣾|⡿⣿
⢀⢀|⢁⣇|⢂⣆|⢃⣇|⢄⣄|⢅⣇|⢆⣆|⢇⣇|⢈⢸|⢉⣿|⢊⣾|⢋⣿|⢌⣼|⢍⣿|⢎⣾|⢏⣿
⢐⢰|⢑⣷|⢒⣶|⢓⣷|⢔⣴|⢕⣷|⢖⣶|⢗⣷|⢘⢸|⢙⣿|⢚⣾|⢛⣿|⢜⣼|⢝⣿|⢞⣾|⢟⣿
⢠⢠|⢡⣧|⢢⣦|⢣⣧|⢤⣤|⢥⣧|⢦⣦|⢧⣧|⢨⢸|⢩⣿|⢪⣾|⢫⣿|⢬⣼|⢭⣿|⢮⣾|⢯⣿
⢰⢰|⢱⣷|⢲⣶|⢳⣷|⢴⣴|⢵⣷|⢶⣶|⢷⣷|⢸⢸|⢹⣿|⢺⣾|⢻⣿|⢼⣼|⢽⣿|⢾⣾|⢿⣿
⣀⣀|⣁⣇|⣂⣆|⣃⣇|⣄⣄|⣅⣇|⣆⣆|⣇⣇|⣈⣸|⣉⣿|⣊⣾|⣋⣿|⣌⣼|⣍⣿|⣎⣾|⣏⣿
⣐⣰|⣑⣷|⣒⣶|⣓⣷|⣔⣴|⣕⣷|⣖⣶|⣗⣷|⣘⣸|⣙⣿|⣚⣾|⣛⣿|⣜⣼|⣝⣿|⣞⣾|⣟⣿
⣠⣠|⣡⣧|⣢⣦|⣣⣧|⣤⣤|⣥⣧|⣦⣦|⣧⣧|⣨⣸|⣩⣿|⣪⣾|⣫⣿|⣬⣼|⣭⣿|⣮⣾|⣯⣿
⣰⣰|⣱⣷|⣲⣶|⣳⣷|⣴⣴|⣵⣷|⣶⣶|⣷⣷|⣸⣸|⣹⣿|⣺⣾|⣻⣿|⣼⣼|⣽⣿|⣾⣾|⣿⣿
`
SpaceMW
=
rune
(
'⠀'
)
FullMW
=
rune
(
'⣿'
)
LeftFullMW
=
rune
(
'⡇'
)
RightFullMW
=
rune
(
'⢸'
)
OneThreeMW
=
rune
(
'⣸'
)
CharLeft
CharType
=
1
<<
2
CharRight
CharType
=
1
<<
1
CharEmpty
CharType
=
0
CharFull
CharType
=
CharLeft
+
CharRight
)
var
(
MM
=
Full
()
LeftOnlyMW
=
[]
rune
(
"⠁⠂⠄⡀⠃⡄⠆⠅⡁⡂⡆⠇⡃⡅⡇"
)
RightOnlyMW
=
[]
rune
(
"⠈⠐⠠⢀⠘⠰⠨⢈⢐⢠⢘⢨⠸⢰⢸"
)
)
/*
├─────────────120s├──────────────────────────60s├───────────30s├──────────────┼──────────────────────360s├─────────────────────────300s├─────────────────────────240s├─────────────────────────180s├─────────────────────────120s├──────────────────────────60s├───────────30s├──────────────┤
│ │ ⡏⠉⡇⣿⢸⢹ │
│ │ ⡇ ⢣⠃⠇⠈⡆ │
│ │ ⡇ ⠸ ⡇ │
│ │ ⡇ ⢣ │
│ MEM: 93.0GiB (6.2%)⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⠤⠤⠤⠤⠤⠤⠤⠤⠄│ AVG DCU UTL: 0.0%⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⡇ ⢸⣀⣀⣀⣀⣀⡀│
*/
func
Full
()
map
[
rune
]
rune
{
result
:=
make
(
map
[
rune
]
rune
)
str
:=
strings
.
ReplaceAll
(
strings
.
ReplaceAll
(
strings
.
Trim
(
MW
,
"
\n
"
),
"|"
,
""
),
"
\n
"
,
""
)
runes
:=
[]
rune
(
str
)
l
:=
len
(
runes
)
/
2
for
i
:=
range
l
{
k
:=
runes
[
2
*
i
]
v
:=
runes
[
2
*
i
+
1
]
if
k
!=
v
{
result
[
k
]
=
v
}
}
return
result
}
func
GetCharType
(
r
rune
)
CharType
{
if
r
==
' '
||
r
==
SpaceMW
{
return
CharEmpty
}
if
slices
.
Contains
(
LeftOnlyMW
,
r
)
{
return
CharLeft
}
if
slices
.
Contains
(
RightOnlyMW
,
r
)
{
return
CharRight
}
return
CharFull
}
func
CharTypeOr
(
a
,
b
CharType
)
CharType
{
return
CharType
(
a
|
b
)
}
utils/utils_test.go
View file @
c915d1bd
package
utils
import
(
"fmt"
"strings"
"sync/atomic"
"testing"
)
...
...
@@ -76,3 +78,37 @@ func TestPCIBusId(t *testing.T) {
i
:=
atomic
.
Int32
{}
t
.
Log
(
i
.
Load
())
}
func
TestTimesort
(
t
*
testing
.
T
)
{
fmt
.
Println
(
"--- 打印所有 256 个 8 点盲文(Unicode 字符)---"
)
fmt
.
Println
(
" (如果您的字体支持,将显示从 U+2800 到 U+28FF 的符号)"
)
fmt
.
Println
(
strings
.
Repeat
(
"-"
,
60
))
// 8点盲文的 Unicode 范围是 U+2800 到 U+28FF
const
startCodePoint
=
0x2800
const
endCodePoint
=
0x28FF
const
charsPerRow
=
16
// 每行打印 16 个字符,共 16 行
// 循环遍历并打印所有 256 个字符
for
i
:=
startCodePoint
;
i
<=
endCodePoint
;
i
++
{
// 打印 Unicode 符号本身
fmt
.
Printf
(
"%c"
,
rune
(
i
))
// 每 16 个字符换一行
if
(
i
-
startCodePoint
+
1
)
%
charsPerRow
==
0
{
fmt
.
Print
(
"
\n
"
)
}
else
{
fmt
.
Print
(
"|"
)
// 字符之间用空格分隔
}
}
fmt
.
Println
(
strings
.
Repeat
(
"-"
,
60
))
fmt
.
Println
(
"所有 256 个组合打印完成 (从 U+2800 到 U+28FF)。"
)
}
func
TestChartype
(
t
*
testing
.
T
)
{
r
:=
GetCharType
(
LeftFullMW
)
t
.
Log
(
r
)
t
.
Log
(
CharTypeOr
(
GetCharType
(
' '
),
GetCharType
(
' '
)))
t
.
Log
(
GetCharType
(
'⢠'
))
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment