Add FPS density chart, add better way of serving static files
This commit is contained in:
parent
73b42dce4b
commit
ebed937b76
44
server.go
44
server.go
@ -1,7 +1,11 @@
|
||||
package flightlesssomething
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"html/template"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@ -80,10 +84,46 @@ func Start(c *Config) {
|
||||
r.SetHTMLTemplate(tmpl)
|
||||
|
||||
// Serve static files
|
||||
fileServer := http.FileServer(http.FS(staticFS))
|
||||
r.GET("/static/*filepath", func(c *gin.Context) {
|
||||
filepath := c.Param("filepath")
|
||||
file, err := staticFS.Open("static" + filepath)
|
||||
if err != nil {
|
||||
c.Status(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// Get file info
|
||||
fileInfo, err := file.Stat()
|
||||
if err != nil {
|
||||
c.Status(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Read file content into a byte slice
|
||||
content, err := fs.ReadFile(staticFS, "static"+filepath)
|
||||
if err != nil {
|
||||
c.Status(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Generate ETag based on file content
|
||||
hash := sha1.New()
|
||||
hash.Write(content)
|
||||
etag := hex.EncodeToString(hash.Sum(nil))
|
||||
|
||||
// Set ETag and Cache-Control headers
|
||||
c.Header("ETag", etag)
|
||||
c.Header("Cache-Control", "public, max-age=3600")
|
||||
fileServer.ServeHTTP(c.Writer, c.Request)
|
||||
|
||||
// Check if the ETag matches
|
||||
if match := c.GetHeader("If-None-Match"); match == etag {
|
||||
c.Status(http.StatusNotModified)
|
||||
return
|
||||
}
|
||||
|
||||
// Serve the file with ETag and Last-Modified headers
|
||||
http.ServeContent(c.Writer, c.Request, fileInfo.Name(), fileInfo.ModTime(), bytes.NewReader(content))
|
||||
})
|
||||
|
||||
r.GET("/", func(c *gin.Context) { c.Redirect(http.StatusTemporaryRedirect, "/benchmarks") })
|
||||
|
@ -461,6 +461,133 @@ Highcharts.chart('avgChart', {
|
||||
}]
|
||||
});
|
||||
|
||||
// Function to filter out the top and bottom 3% of FPS values
|
||||
function filterOutliers(data) {
|
||||
data.sort((a, b) => a - b);
|
||||
var start = Math.floor(data.length * 0.01); // Ignore bottom 1%
|
||||
var end = Math.ceil(data.length * 0.97); // Ignore top 1%
|
||||
return data.slice(start, end);
|
||||
}
|
||||
|
||||
// Function to count occurrences of each FPS value
|
||||
function countFPS(data) {
|
||||
var counts = {};
|
||||
data.forEach(function(fps) {
|
||||
var roundedFPS = Math.round(fps);
|
||||
counts[roundedFPS] = (counts[roundedFPS] || 0) + 1;
|
||||
});
|
||||
|
||||
var fpsArray = Object.keys(counts).map(function(key) {
|
||||
return [parseInt(key), counts[key]];
|
||||
}).sort(function(a, b) {
|
||||
return a[0] - b[0];
|
||||
});
|
||||
|
||||
// Combine closest FPS values until we have 100 or fewer points
|
||||
while (fpsArray.length > 100) {
|
||||
var minDiff = Infinity;
|
||||
var minIndex = -1;
|
||||
|
||||
// Find the pair with the smallest difference
|
||||
for (var i = 0; i < fpsArray.length - 1; i++) {
|
||||
var diff = fpsArray[i + 1][0] - fpsArray[i][0];
|
||||
if (diff < minDiff) {
|
||||
minDiff = diff;
|
||||
minIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Combine the closest pair
|
||||
fpsArray[minIndex][1] += fpsArray[minIndex + 1][1];
|
||||
fpsArray[minIndex][0] = (fpsArray[minIndex][0] + fpsArray[minIndex + 1][0]) / 2;
|
||||
fpsArray.splice(minIndex + 1, 1);
|
||||
}
|
||||
|
||||
return fpsArray;
|
||||
}
|
||||
|
||||
// Calculate counts for each dataset after filtering outliers
|
||||
var densityData = fpsDataArrays.map(function(dataArray) {
|
||||
var filteredData = filterOutliers(dataArray.data);
|
||||
return {
|
||||
name: dataArray.label,
|
||||
data: countFPS(filteredData)
|
||||
};
|
||||
});
|
||||
|
||||
// Create the chart
|
||||
Highcharts.chart('densityChart', {
|
||||
chart: {
|
||||
type: 'areaspline',
|
||||
backgroundColor: null
|
||||
},
|
||||
title: {
|
||||
text: 'FPS Density',
|
||||
style: {
|
||||
color: '#FFFFFF',
|
||||
fontSize: '16px'
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
title: {
|
||||
text: 'FPS',
|
||||
style: {
|
||||
color: '#FFFFFF'
|
||||
}
|
||||
},
|
||||
labels: {
|
||||
style: {
|
||||
color: '#FFFFFF'
|
||||
}
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
title: {
|
||||
text: 'Count',
|
||||
style: {
|
||||
color: '#FFFFFF'
|
||||
}
|
||||
},
|
||||
labels: {
|
||||
style: {
|
||||
color: '#FFFFFF'
|
||||
}
|
||||
},
|
||||
gridLineColor: 'rgba(255, 255, 255, 0.1)'
|
||||
},
|
||||
tooltip: {
|
||||
shared: true,
|
||||
backgroundColor: '#1E1E1E',
|
||||
borderColor: '#FFFFFF',
|
||||
style: {
|
||||
color: '#FFFFFF'
|
||||
},
|
||||
formatter: function() {
|
||||
var points = this.points;
|
||||
var tooltipText = '<b>' + points[0].series.name + '</b>: ' + points[0].y + ' points at ~' + Math.round(points[0].x) + ' FPS';
|
||||
return tooltipText;
|
||||
}
|
||||
},
|
||||
plotOptions: {
|
||||
areaspline: {
|
||||
fillOpacity: 0.5,
|
||||
marker: {
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
enabled: true,
|
||||
itemStyle: {
|
||||
color: '#FFFFFF'
|
||||
}
|
||||
},
|
||||
credits: {
|
||||
enabled: false
|
||||
},
|
||||
series: densityData
|
||||
});
|
||||
|
||||
function calculateSpikes(data, threshold) {
|
||||
if (data.length < 6) {
|
||||
throw new Error("Data length must be greater than or equal to 6.");
|
||||
|
@ -90,6 +90,8 @@
|
||||
|
||||
<div id="avgChart" style="height:250pt;"></div>
|
||||
|
||||
<div id="densityChart" style="height:250pt;"></div>
|
||||
|
||||
<div>
|
||||
<label for="spikeThreshold" style="color: #FFFFFF;">Ignore Spike Threshold (%):</label>
|
||||
<input type="range" id="spikeThreshold" name="spikeThreshold" min="5" max="150" value="50" oninput="updateSpikesChart(this.value)">
|
||||
|
Loading…
Reference in New Issue
Block a user