ensure consistent ordering of data
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
96
main.go
96
main.go
@@ -36,10 +36,35 @@ type Record struct {
|
|||||||
Wsdc json.RawMessage `json:"Western Sydney Data Centre"`
|
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) {
|
func GenerateAvgVcpusCharts(f *excelize.File, data any, name string) {
|
||||||
var err error
|
var err error
|
||||||
rydeAvgCpu := make(map[string]interface{})
|
//rydeAvgCpu := make(map[string]interface{})
|
||||||
wsdcAvgCpu := make(map[string]interface{})
|
rydeAvgCpu := []KeyValue{}
|
||||||
|
//wsdcAvgCpu := make(map[string]interface{})
|
||||||
|
wsdcAvgCpu := []KeyValue{}
|
||||||
var avgCpuColumns []string
|
var avgCpuColumns []string
|
||||||
|
|
||||||
// Access AvgCpu using reflection
|
// Access AvgCpu using reflection
|
||||||
@@ -75,8 +100,11 @@ func GenerateAvgVcpusCharts(f *excelize.File, data any, name string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rydeAvgCpu[fieldName] = rydeData
|
rydeAvgCpu = addData(rydeAvgCpu, fieldName, rydeData)
|
||||||
wsdcAvgCpu[fieldName] = wsdcData
|
wsdcAvgCpu = addData(wsdcAvgCpu, fieldName, wsdcData)
|
||||||
|
|
||||||
|
//rydeAvgCpu[fieldName] = rydeData
|
||||||
|
//wsdcAvgCpu[fieldName] = wsdcData
|
||||||
avgCpuColumns = append(avgCpuColumns, fieldName)
|
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) {
|
func GenerateCharts(f *excelize.File, data any, name string, location string) {
|
||||||
var err error
|
var err error
|
||||||
parsedData := make(map[string]interface{})
|
//parsedData := make(map[string]interface{})
|
||||||
|
parsedData := []KeyValue{}
|
||||||
var dataColumns = []string{"RCC", "WSDC"}
|
var dataColumns = []string{"RCC", "WSDC"}
|
||||||
|
|
||||||
// Create interfaces to hold unmarshaled data
|
// 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
|
// store the data together
|
||||||
parsedData["RCC"] = rcc
|
parsedData = addData(parsedData, "RCC", rcc)
|
||||||
parsedData["WSDC"] = wsdc
|
parsedData = addData(parsedData, "WSDC", wsdc)
|
||||||
|
//parsedData["RCC"] = rcc
|
||||||
|
//parsedData["WSDC"] = wsdc
|
||||||
//prettyPrint(parsedData)
|
//prettyPrint(parsedData)
|
||||||
|
|
||||||
// Generate worksheet and graph
|
// Generate worksheet and graph
|
||||||
AvgChart(f, name, location, dataColumns, parsedData)
|
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 err error
|
||||||
var chartSeries []excelize.ChartSeries
|
var chartSeries []excelize.ChartSeries
|
||||||
var dataDates []string
|
var dataDates []string
|
||||||
var col int
|
var col int
|
||||||
var row int
|
var row int
|
||||||
|
|
||||||
|
fmt.Printf("Creating worksheet %s\n", worksheetName)
|
||||||
_, err = f.NewSheet(worksheetName)
|
_, err = f.NewSheet(worksheetName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@@ -144,12 +176,14 @@ func AvgChart(f *excelize.File, worksheetName string, location string, avgCpuCol
|
|||||||
f.SetCellValue(worksheetName, cell, avgCpuColumns[i])
|
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 _, v := range data {
|
||||||
for date := range v.(map[string]interface{}) {
|
if dateMap, ok := v.Value.(map[string]interface{}); ok {
|
||||||
dataDates = append(dataDates, date)
|
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
|
// 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])
|
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
|
// Find the column that matches, add one to account for the date column
|
||||||
col = slices.Index(avgCpuColumns, pool) + 1
|
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{}
|
// Type assertion to confirm that poolKv.Value is a map[string]interface{}
|
||||||
//fmt.Printf("val: %v\n", val)
|
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
|
// Find the correct row, add one to account for sheet heading
|
||||||
row = slices.Index(dataDates, date) + 1
|
row = slices.Index(dataDates, date) + 1
|
||||||
|
|
||||||
cell := string(rune('A'+col)) + strconv.Itoa(row+1)
|
cell := string(rune('A'+col)) + strconv.Itoa(row+1)
|
||||||
//fmt.Printf("Adding value %f (%s) to %s]\n", val, date, cell)
|
//fmt.Printf("Adding value %f (%s) to %s]\n", val, date, cell)
|
||||||
f.SetCellValue(worksheetName, cell, val)
|
f.SetCellValue(worksheetName, cell, val)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the chartseries for this resource pool
|
// Create the chartseries for this resource pool
|
||||||
thisChartSeries := excelize.ChartSeries{
|
thisChartSeries := excelize.ChartSeries{
|
||||||
Name: "'" + worksheetName + "'!$" + string(rune('A'+col)) + "$1", // Reference the cell containing the resource pool name, eg Tin in $B$1
|
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{
|
XAxis: excelize.ChartAxis{
|
||||||
MajorGridLines: true,
|
MajorGridLines: true,
|
||||||
MinorGridLines: true,
|
MinorGridLines: true,
|
||||||
|
Title: []excelize.RichTextRun{
|
||||||
|
{
|
||||||
|
Text: "Month Year",
|
||||||
|
},
|
||||||
|
},
|
||||||
Font: excelize.Font{
|
Font: excelize.Font{
|
||||||
Color: "000000",
|
Color: "000000",
|
||||||
},
|
},
|
||||||
@@ -227,6 +271,11 @@ func AvgChart(f *excelize.File, worksheetName string, location string, avgCpuCol
|
|||||||
YAxis: excelize.ChartAxis{
|
YAxis: excelize.ChartAxis{
|
||||||
MajorGridLines: true,
|
MajorGridLines: true,
|
||||||
MinorGridLines: true,
|
MinorGridLines: true,
|
||||||
|
Title: []excelize.RichTextRun{
|
||||||
|
{
|
||||||
|
Text: "Count/Size",
|
||||||
|
},
|
||||||
|
},
|
||||||
Font: excelize.Font{
|
Font: excelize.Font{
|
||||||
Color: "000000",
|
Color: "000000",
|
||||||
},
|
},
|
||||||
@@ -248,6 +297,9 @@ func main() {
|
|||||||
outputFile := flag.String("output", "book1.xlsx", "The filename to use when writing excel workbook")
|
outputFile := flag.String("output", "book1.xlsx", "The filename to use when writing excel workbook")
|
||||||
flag.Parse()
|
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
|
// Create the workbook
|
||||||
f := excelize.NewFile()
|
f := excelize.NewFile()
|
||||||
defer func() {
|
defer func() {
|
||||||
|
Reference in New Issue
Block a user