You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: grid.go
    path of file: ./repos/sampler/component/runchart
    
    the code of the file until where you have to start completion: package runchart

import (
	ui "github.com/gizak/termui/v3"
	"github.com/sqshq/sampler/component/util"
	"image"
	"math"
	"time"
)

const defaultValueLength = 4

type chartGrid struct {
	timeRange    TimeRange
	timePerPoint time.Duration
	valueExtrema ValueExtrema
	linesCount   int
	maxTimeWidth int
	minTimeWidth int
}

func (c *RunChart) newChartGrid() chartGrid {

	linesCount := (c.Inner.Max.X - c.Inner.Min.X - c.grid.minTimeWidth) / xAxisGridWidth
	timeRange := c.getTimeRange(linesCount)

	return chartGrid{
		timeRange:    timeRange,
		timePerPoint: c.timescale / time.Duration(xAxisGridWidth),
		valueExtrema: getLocalExtrema(c.lines, timeRange),
		linesCount:   linesCount,
		maxTimeWidth: c.Inner.Max.X,
		minTimeWidth: defaultValueLength,
	}
}

func (c *RunChart) renderAxes(buffer *ui.Buffer) {

	// draw y axis labels
	if c.grid.valueExtrema.max != c.grid.valueExtrema.min {
		labelsCount := (c.Inner.Dy() - xAxisLabelsHeight - 1) / (yAxisLabelsIndent + yAxisLabelsHeight)
		valuePerY := (c.grid.valueExtrema.max - c.grid.valueExtrema.min) / float64(c.Inner.Dy()-xAxisLabelsHeight-3)
		for i := 0; i < int(labelsCount); i++ {
			val := c.grid.valueExtrema.max - (valuePerY * float64(i) * (yAxisLabelsIndent + yAxisLabelsHeight))
			fmt := util.FormatValue(val, c.scale)
			if len(fmt) > c.grid.minTimeWidth {
				c.grid.minTimeWidth = len(fmt)
			}
			buffer.SetString(
				fmt,
				ui.NewStyle(c.palette.BaseColor),
				image.Pt(c.Inner.Min.X, 1+c.Inner.Min.Y+i*(yAxisLabelsIndent+yAxisLabelsHeight)))
		}
	} else {
		fmt := util.FormatValue(c.grid.valueExtrema.max, c.scale)
		c.grid.minTimeWidth = len(fmt)
		buffer.SetString(
			fmt,
			ui.NewStyle(c.palette.BaseColor),
			image.Pt(c.Inner.Min.X, c.Inner.Min.Y+c.Inner.Dy()/2))
	}

	// draw origin cell
	buffer.SetCell(
		ui.NewCell(ui.BOTTOM_LEFT, ui.NewStyle(c.palette.BaseColor)),
		image.Pt(c.Inner.Min.X+c.grid.minTimeWidth, c.Inner.Max.Y-xAxisLabelsHeight-1))

	/
    
func (c *RunChart) renderAxes(buffer *ui.Buffer) {

	// draw y axis labels
	if c.grid.valueExtrema.max != c.grid.valueExtrema.min {
		labelsCount := (c.Inner.Dy() - xAxisLabelsHeight - 1) / (yAxisLabelsIndent + yAxisLabelsHeight)
		valuePerY := (c.grid.valueExtrema.max - c.grid.valueExtrema.min) / float64(c.Inner.Dy()-xAxisLabelsHeight-3)
		for i := 0; i < int(labelsCount); i++ {
			val := c.grid.valueExtrema.max - (valuePerY * float64(i) * (yAxisLabelsIndent + yAxisLabelsHeight))
			fmt := util.FormatValue(val, c.scale)
			if len(fmt) > c.grid.minTimeWidth {
				c.grid.minTimeWidth = len(fmt)
			}
			buffer.SetString(
				fmt,
				ui.NewStyle(c.palette.BaseColor),
				image.Pt(c.Inner.Min.X, 1+c.Inner.Min.Y+i*(yAxisLabelsIndent+yAxisLabelsHeight)))
		}
	} else {
		fmt := util.FormatValue(c.grid.valueExtrema.max, c.scale)
		c.grid.minTimeWidth = len(fmt)
		buffer.SetString(
			fmt,
			ui.NewStyle(c.palette.BaseColor),
			image.Pt(c.Inner.Min.X, c.Inner.Min.Y+c.Inner.Dy()/2))
	}

	// draw origin cell
	buffer.SetCell(
		ui.NewCell(ui.BOTTOM_LEFT, ui.NewStyle(c.palette.BaseColor)),
		image.Pt(c.Inner.Min.X+c.grid.minTimeWidth, c.Inner.Max.Y-xAxisLabelsHeight-1))

	// draw x axis line
	for i := c.grid.minTimeWidth + 1; i < c.Inner.Dx(); i++ {
		buffer.SetCell(
			ui.NewCell(ui.HORIZONTAL_DASH, ui.NewStyle(c.palette.BaseColor)),
			image.Pt(i+c.Inner.Min.X, c.Inner.Max.Y-xAxisLabelsHeight-1))
	}

	// draw grid lines
	for y := 0; y < c.Inner.Dy()-xAxisLabelsHeight-2; y = y + 2 {
		for x := 1; x <= c.grid.linesCount; x++ {
			buffer.SetCell(
				ui.NewCell(ui.VERTICAL_DASH, ui.NewStyle(c.palette.MediumColor)),
				image.Pt(c.grid.maxTimeWidth-x*xAxisGridWidth, y+c.Inner.Min.Y+1))
		}
	}

	// draw y axis line
	for i := 0; i < c.Inner.Dy()-xAxisLabelsHeight-1; i++ {
		buffer.SetCell(
			ui.NewCell(ui.VERTICAL_DASH, ui.NewStyle(c.palette.BaseColor)),
			image.Pt(c.Inner.Min.X+c.grid.minTimeWidth, i+c.Inner.Min.Y))
	}

	// draw x axis time labels
	for i := 1; i <= c.grid.linesCount; i++ {
		labelTime := c.grid.timeRange.max.Add(time.Duration(-i) * c.timescale)
		buffer.SetString(
			labelTime.Format("15:04:05"),
			ui.NewStyle(c.palette.BaseColor),
			image.Pt(c.grid.maxTimeWidth-xAxisLabelsWidth/2-i*(xAxisGridWidth), c.Inner.Max.Y-1))
	}
}