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  }