Add FPS density chart, add better way of serving static files

This commit is contained in:
Erikas 2024-07-14 17:51:34 +03:00
parent 73b42dce4b
commit ebed937b76
3 changed files with 171 additions and 2 deletions

View File

@ -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") })

View File

@ -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.");

View File

@ -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)">