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: scenarios.go
    path of file: ./repos/grafana/pkg/tsdb/grafana-testdata-datasource
    
    the code of the file until where you have to start completion: package testdatasource

import (
	"context"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"math"
	"math/rand"
	"strconv"
	"strings"
	"time"

	"github.com/grafana/grafana-plugin-sdk-go/backend"
	"github.com/grafana/grafana-plugin-sdk-go/backend/log"
	"github.com/grafana/grafana-plugin-sdk-go/backend/tracing"
	"github.com/grafana/grafana-plugin-sdk-go/data"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/trace"
)

const (
	randomWalkQuery                   queryType = "random_walk"
	randomWalkSlowQuery               queryType = "slow_query"
	randomWalkWithErrorQuery          queryType = "random_walk_with_error"
	randomWalkTableQuery              queryType = "random_walk_table"
	exponentialHeatmapBucketDataQuery queryType = "exponential_heatmap_bucket_data"
	linearHeatmapBucketDataQuery      queryType = "linear_heatmap_bucket_data"
	noDataPointsQuery                 queryType = "no_data_points"
	datapointsOutsideRangeQuery       que
    
func RandomWalk(query backend.DataQuery, model JSONModel, index int) *data.Frame {
	rand := rand.New(rand.NewSource(time.Now().UnixNano() + int64(index)))
	timeWalkerMs := query.TimeRange.From.UnixNano() / int64(time.Millisecond)
	to := query.TimeRange.To.UnixNano() / int64(time.Millisecond)
	startValue := model.StartValue
	spread := model.Spread
	noise := model.Noise
	drop := model.Drop / 100.0 // value is 0-100

	min := float64(0)
	hasMin := false
	if model.Min != nil {
		hasMin = true
		min = *model.Min
	}
	max := float64(0)
	hasMax := false
	if model.Max != nil {
		hasMax = true
		max = *model.Max
	}

	timeVec := make([]*time.Time, 0)
	floatVec := make([]*float64, 0)

	walker := startValue

	for i := int64(0); i < 10000 && timeWalkerMs < to; i++ {
		nextValue := walker + (rand.Float64() * noise)

		if hasMin && nextValue < min {
			nextValue = min
			walker = min
		}

		if hasMax && nextValue > max {
			nextValue = max
			walker = max
		}

		if drop > 0 && rand.Float64() < drop {
			// skip value
		} else {
			t := time.Unix(timeWalkerMs/int64(1e+3), (timeWalkerMs%int64(1e+3))*int64(1e+6))
			timeVec = append(timeVec, &t)
			floatVec = append(floatVec, &nextValue)
		}

		walker += (rand.Float64() - 0.5) * spread
		timeWalkerMs += query.Interval.Milliseconds()
	}

	frame := data.NewFrame("",
		data.NewField("time", nil, timeVec).
			SetConfig(&data.FieldConfig{
				Interval: float64(query.Interval.Milliseconds()),
			}),
		data.NewField(frameNameForQuery(query, model, index), parseLabels(model, index), floatVec),
	)

	frame.SetMeta(&data.FrameMeta{
		Custom: map[string]interface{}{
			"customStat": 10,
		},
	})

	return frame
}