github.com/wrgl/wrgl@v0.14.0/pkg/widgets/prof/stat_diff_table.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright © 2022 Wrangle Ltd
     3  
     4  package widgetsprof
     5  
     6  import (
     7  	"fmt"
     8  	"sort"
     9  
    10  	"github.com/rivo/tview"
    11  	diffprof "github.com/wrgl/wrgl/pkg/diff/prof"
    12  	"github.com/wrgl/wrgl/pkg/widgets"
    13  )
    14  
    15  type StatDiffTable struct {
    16  	*widgets.SelectableTable
    17  	pool        *widgets.CellsPool
    18  	tpd         *diffprof.TableProfileDiff
    19  	diffCells   [][]StatDiffCells
    20  	rowsPerStat []int
    21  	statNames   []string
    22  }
    23  
    24  func NewStatDiffTable(tpd *diffprof.TableProfileDiff) (*StatDiffTable, error) {
    25  	t := &StatDiffTable{
    26  		SelectableTable: widgets.NewSelectableTable(),
    27  		tpd:             tpd,
    28  	}
    29  	t.SelectableTable.SetGetCellsFunc(t.getCells).
    30  		SetMinSelection(1, 1).
    31  		Select(1, 1, 0)
    32  	totalRows, err := t.calculateRowsCount()
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  	t.VirtualTable.SetFixed(1, 1).
    37  		SetShape(totalRows+1, len(tpd.Columns)+1).
    38  		SetSeparator('│')
    39  	t.pool = widgets.NewCellsPool(t.VirtualTable)
    40  	return t, nil
    41  }
    42  
    43  func (t *StatDiffTable) calculateRowsCount() (int, error) {
    44  	rows := map[string]int{}
    45  	diffCells := map[string]map[int]StatDiffCells{}
    46  	for i, col := range t.tpd.Columns {
    47  		for _, stat := range col.Stats {
    48  			var sdc StatDiffCells
    49  			switch v := stat.(type) {
    50  			case *diffprof.Uint16Stat:
    51  				sdc = &uint16StatDiffCells{v}
    52  			case *diffprof.Uint32Stat:
    53  				sdc = &uint32StatDiffCells{v}
    54  			case *diffprof.Float64Stat:
    55  				sdc = &float64StatDiffCells{v}
    56  			case *diffprof.TopValuesStat:
    57  				sdc = &topValuesStatDiffCells{v}
    58  			case *diffprof.PercentilesStat:
    59  				sdc = &percentilesStatDiffCells{v}
    60  			default:
    61  				return 0, fmt.Errorf("unanticipated type %T", v)
    62  			}
    63  			if c, ok := rows[sdc.Name()]; !ok || c < sdc.NumRows() {
    64  				rows[sdc.Name()] = sdc.NumRows()
    65  				if !ok {
    66  					t.statNames = append(t.statNames, sdc.Name())
    67  				}
    68  			}
    69  			if _, ok := diffCells[sdc.Name()]; !ok {
    70  				diffCells[sdc.Name()] = map[int]StatDiffCells{}
    71  			}
    72  			diffCells[sdc.Name()][i] = sdc
    73  		}
    74  	}
    75  	totalRows := 0
    76  	sort.Slice(t.statNames, func(i, j int) bool {
    77  		if t.statNames[i] == "Top values" {
    78  			return false
    79  		}
    80  		if t.statNames[j] == "Top values" {
    81  			return true
    82  		}
    83  		if t.statNames[i] == "Percentiles" {
    84  			return false
    85  		}
    86  		if t.statNames[j] == "Percentiles" {
    87  			return true
    88  		}
    89  		if t.statNames[i] == "NA count" {
    90  			return true
    91  		}
    92  		if t.statNames[j] == "NA count" {
    93  			return false
    94  		}
    95  		return i < j
    96  	})
    97  	for _, name := range t.statNames {
    98  		n := len(t.diffCells)
    99  		t.diffCells = append(t.diffCells, make([]StatDiffCells, len(t.tpd.Columns)))
   100  		for i, sdc := range diffCells[name] {
   101  			t.diffCells[n][i] = sdc
   102  		}
   103  		totalRows += rows[name]
   104  		t.rowsPerStat = append(t.rowsPerStat, rows[name])
   105  	}
   106  	return totalRows, nil
   107  }
   108  
   109  func (t *StatDiffTable) getCells(row, column int) []*widgets.TableCell {
   110  	if row == 0 {
   111  		if column == 0 {
   112  			return nil
   113  		}
   114  		cells, ok := t.pool.Get(row, column, 1)
   115  		if !ok {
   116  			cells[0].SetText(t.tpd.Columns[column-1].Name).
   117  				SetStyle(columnStyle).
   118  				SetAlign(tview.AlignCenter)
   119  		}
   120  		return cells
   121  	}
   122  	sum := 0
   123  	// var sc StatDiffCells
   124  	var statRow int
   125  	var statInd int
   126  	for i, rowsCount := range t.rowsPerStat {
   127  		sum += rowsCount
   128  		if sum > row-1 {
   129  			// sc = t.diffCells[i][column-1]
   130  			statInd = i
   131  			statRow = row - 1 - sum + rowsCount
   132  			break
   133  		}
   134  	}
   135  	if column == 0 {
   136  		cells, ok := t.pool.Get(row, column, 1)
   137  		if !ok && statRow == 0 {
   138  			cells[0].SetText(t.statNames[statInd]).SetStyle(statNameStyle)
   139  		}
   140  		return cells
   141  	}
   142  	sc := t.diffCells[statInd][column-1]
   143  	if sc != nil {
   144  		cells, ok := t.pool.Get(row, column, sc.NumColumns())
   145  		if !ok && statRow < sc.NumRows() {
   146  			sc.DecorateCells(statRow, cells)
   147  		}
   148  		return cells
   149  	}
   150  	cells, _ := t.pool.Get(row, column, 1)
   151  	return cells
   152  }