ensure consistent ordering of data
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2024-10-04 15:39:33 +10:00
parent 64815f5fa3
commit 8f4765980a

96
main.go
View File

@@ -36,10 +36,35 @@ type Record struct {
Wsdc json.RawMessage `json:"Western Sydney Data Centre"`
}
type KeyValue struct {
Key string
Value interface{}
}
var sha1ver string // sha1 revision used to build the program
var buildTime string // when the executable was built
// Add a new key-value pair to the slice
func addData(data []KeyValue, key string, value interface{}) []KeyValue {
return append(data, KeyValue{Key: key, Value: value})
}
// Find a value by key
func findData(data []KeyValue, key string) (interface{}, bool) {
for _, kv := range data {
if kv.Key == key {
return kv.Value, true
}
}
return nil, false // Return false if key not found
}
func GenerateAvgVcpusCharts(f *excelize.File, data any, name string) {
var err error
rydeAvgCpu := make(map[string]interface{})
wsdcAvgCpu := make(map[string]interface{})
//rydeAvgCpu := make(map[string]interface{})
rydeAvgCpu := []KeyValue{}
//wsdcAvgCpu := make(map[string]interface{})
wsdcAvgCpu := []KeyValue{}
var avgCpuColumns []string
// Access AvgCpu using reflection
@@ -75,8 +100,11 @@ func GenerateAvgVcpusCharts(f *excelize.File, data any, name string) {
}
}
rydeAvgCpu[fieldName] = rydeData
wsdcAvgCpu[fieldName] = wsdcData
rydeAvgCpu = addData(rydeAvgCpu, fieldName, rydeData)
wsdcAvgCpu = addData(wsdcAvgCpu, fieldName, wsdcData)
//rydeAvgCpu[fieldName] = rydeData
//wsdcAvgCpu[fieldName] = wsdcData
avgCpuColumns = append(avgCpuColumns, fieldName)
}
@@ -88,7 +116,8 @@ func GenerateAvgVcpusCharts(f *excelize.File, data any, name string) {
func GenerateCharts(f *excelize.File, data any, name string, location string) {
var err error
parsedData := make(map[string]interface{})
//parsedData := make(map[string]interface{})
parsedData := []KeyValue{}
var dataColumns = []string{"RCC", "WSDC"}
// Create interfaces to hold unmarshaled data
@@ -117,21 +146,24 @@ func GenerateCharts(f *excelize.File, data any, name string, location string) {
}
// store the data together
parsedData["RCC"] = rcc
parsedData["WSDC"] = wsdc
parsedData = addData(parsedData, "RCC", rcc)
parsedData = addData(parsedData, "WSDC", wsdc)
//parsedData["RCC"] = rcc
//parsedData["WSDC"] = wsdc
//prettyPrint(parsedData)
// Generate worksheet and graph
AvgChart(f, name, location, dataColumns, parsedData)
}
func AvgChart(f *excelize.File, worksheetName string, location string, avgCpuColumns []string, data map[string]interface{}) {
func AvgChart(f *excelize.File, worksheetName string, location string, avgCpuColumns []string, data []KeyValue) {
var err error
var chartSeries []excelize.ChartSeries
var dataDates []string
var col int
var row int
fmt.Printf("Creating worksheet %s\n", worksheetName)
_, err = f.NewSheet(worksheetName)
if err != nil {
log.Fatal(err)
@@ -144,12 +176,14 @@ func AvgChart(f *excelize.File, worksheetName string, location string, avgCpuCol
f.SetCellValue(worksheetName, cell, avgCpuColumns[i])
}
// Get the values for the dates column
// Get the values for the dates column using the first object in data
for _, v := range data {
for date := range v.(map[string]interface{}) {
dataDates = append(dataDates, date)
if dateMap, ok := v.Value.(map[string]interface{}); ok {
for date := range dateMap {
dataDates = append(dataDates, date)
}
}
break
break // Assuming you only need the dates from the first entry
}
// Sort dates using the custom function
@@ -165,22 +199,27 @@ func AvgChart(f *excelize.File, worksheetName string, location string, avgCpuCol
f.SetCellValue(worksheetName, cell, dataDates[i])
}
for pool, v := range data { // iterate each resource pool type
// Iterate over each KeyValue in the data slice (resource pool types)
for _, poolKv := range data {
pool := poolKv.Key // The pool name
// Find the column that matches, add one to account for the date column
col = slices.Index(avgCpuColumns, pool) + 1
//fmt.Printf("Pool: %s, column: %d\n", pool, col)
fmt.Printf("Pool: %s, column: %d\n", pool, col)
for date, val := range v.(map[string]interface{}) { // use type assertion to loop over map[string]interface{}
//fmt.Printf("val: %v\n", val)
// Type assertion to confirm that poolKv.Value is a map[string]interface{}
if dateMap, ok := poolKv.Value.(map[string]interface{}); ok {
for date, val := range dateMap {
fmt.Printf("Date: %s, Value: %v\n", date, val)
// Find the correct row, add one to account for sheet heading
row = slices.Index(dataDates, date) + 1
// Find the correct row, add one to account for sheet heading
row = slices.Index(dataDates, date) + 1
cell := string(rune('A'+col)) + strconv.Itoa(row+1)
//fmt.Printf("Adding value %f (%s) to %s]\n", val, date, cell)
f.SetCellValue(worksheetName, cell, val)
cell := string(rune('A'+col)) + strconv.Itoa(row+1)
//fmt.Printf("Adding value %f (%s) to %s]\n", val, date, cell)
f.SetCellValue(worksheetName, cell, val)
}
}
// Create the chartseries for this resource pool
thisChartSeries := excelize.ChartSeries{
Name: "'" + worksheetName + "'!$" + string(rune('A'+col)) + "$1", // Reference the cell containing the resource pool name, eg Tin in $B$1
@@ -220,6 +259,11 @@ func AvgChart(f *excelize.File, worksheetName string, location string, avgCpuCol
XAxis: excelize.ChartAxis{
MajorGridLines: true,
MinorGridLines: true,
Title: []excelize.RichTextRun{
{
Text: "Month Year",
},
},
Font: excelize.Font{
Color: "000000",
},
@@ -227,6 +271,11 @@ func AvgChart(f *excelize.File, worksheetName string, location string, avgCpuCol
YAxis: excelize.ChartAxis{
MajorGridLines: true,
MinorGridLines: true,
Title: []excelize.RichTextRun{
{
Text: "Count/Size",
},
},
Font: excelize.Font{
Color: "000000",
},
@@ -248,6 +297,9 @@ func main() {
outputFile := flag.String("output", "book1.xlsx", "The filename to use when writing excel workbook")
flag.Parse()
fmt.Println("Excel chart generation utility, written by Nathan Coad (nathan.coad@dell.com)")
fmt.Printf("Built on %s from sha1 %s\n", buildTime, sha1ver)
// Create the workbook
f := excelize.NewFile()
defer func() {