github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/pkg/control/controldisplay/group_counter_graph.go (about) 1 package controldisplay 2 3 import ( 4 "fmt" 5 "math" 6 "strings" 7 ) 8 9 const counterGraphSegments = 10 10 11 type CounterGraphRenderer struct { 12 failedControls int 13 totalControls int 14 15 maxTotalControls int 16 segmentSize float64 17 18 failedColorFunc colorFunc 19 } 20 21 type CounterGraphRendererOptions struct { 22 FailedColorFunc colorFunc 23 } 24 25 func NewCounterGraphRenderer(failedControls, totalControls, maxTotalControls int, options CounterGraphRendererOptions) *CounterGraphRenderer { 26 renderer := &CounterGraphRenderer{ 27 failedControls: failedControls, 28 totalControls: totalControls, 29 maxTotalControls: maxTotalControls, 30 // there are 10 segments - determine the value of each segment 31 segmentSize: float64(maxTotalControls) / float64(counterGraphSegments), 32 33 failedColorFunc: options.FailedColorFunc, 34 } 35 return renderer 36 } 37 38 func (r CounterGraphRenderer) Render() string { 39 // the graph has the format " [======= ]" 40 41 // if no controls have been run, return empty graph 42 if r.maxTotalControls == 0 { 43 return r.buildGraphString(0, 0, counterGraphSegments) 44 } 45 // if each segment is 10 controls, count 1-10 => 1 segment, 11-20 => 2 segments 46 var failSegments int 47 48 if r.failedControls == 0 { 49 failSegments = 0 50 } else { 51 // if there is a remainder round up 52 failSegments = int(math.Ceil(float64(r.failedControls) / r.segmentSize)) 53 54 } 55 totalSegments := int(math.Ceil(float64(r.totalControls) / r.segmentSize)) 56 57 passSegments := totalSegments - failSegments 58 // allow for pass being rounded down to zero 59 // if there are any successful runs, but there is no room for a successful bar, 60 // increment totalSegments to allow room 61 if passSegments == 0 && r.failedControls < r.totalControls && totalSegments < counterGraphSegments { 62 passSegments++ 63 totalSegments++ 64 } 65 spaces := counterGraphSegments - totalSegments 66 return r.buildGraphString(failSegments, passSegments, spaces) 67 } 68 69 func (r CounterGraphRenderer) buildGraphString(failSegments int, passSegments int, spaces int) string { 70 str := fmt.Sprintf("%s%s%s%s%s", 71 ControlColors.CountGraphBracket("["), 72 r.failedColorFunc(strings.Repeat("=", failSegments)), 73 ControlColors.CountGraphPass(strings.Repeat("=", passSegments)), 74 strings.Repeat(" ", spaces), 75 ControlColors.CountGraphBracket("]")) 76 return str 77 }