From 61ab6ce6bd7eb1a825d8df9507c94a303ad7bbdc Mon Sep 17 00:00:00 2001 From: WithoutPants <53250216+WithoutPants@users.noreply.github.com> Date: Mon, 30 Jun 2025 07:52:53 +1000 Subject: [PATCH] Fix funscript parsing issues (#5978) * Accept floating point numbers for at field in funscript * Ignore type of script version field * Write rounded ints for csv --- .../generator_interactive_heatmap_speed.go | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/internal/manager/generator_interactive_heatmap_speed.go b/internal/manager/generator_interactive_heatmap_speed.go index ac6ca53bd..d10ce5b19 100644 --- a/internal/manager/generator_interactive_heatmap_speed.go +++ b/internal/manager/generator_interactive_heatmap_speed.go @@ -28,7 +28,8 @@ type InteractiveHeatmapSpeedGenerator struct { type Script struct { // Version of Launchscript - Version string `json:"version"` + // #5600 - ignore version, don't validate type + Version json.RawMessage `json:"version"` // Inverted causes up and down movement to be flipped. Inverted bool `json:"inverted,omitempty"` // Range is the percentage of a full stroke to use. @@ -40,7 +41,7 @@ type Script struct { // Action is a move at a specific time. type Action struct { // At time in milliseconds the action should fire. - At int64 `json:"at"` + At float64 `json:"at"` // Pos is the place in percent to move to. Pos int `json:"pos"` @@ -109,8 +110,8 @@ func (g *InteractiveHeatmapSpeedGenerator) LoadFunscriptData(path string, sceneD // trim actions with negative timestamps to avoid index range errors when generating heatmap // #3181 - also trim actions that occur after the scene duration loggedBadTimestamp := false - sceneDurationMilli := int64(sceneDuration * 1000) - isValid := func(x int64) bool { + sceneDurationMilli := sceneDuration * 1000 + isValid := func(x float64) bool { return x >= 0 && x < sceneDurationMilli } @@ -132,7 +133,7 @@ func (g *InteractiveHeatmapSpeedGenerator) LoadFunscriptData(path string, sceneD func (funscript *Script) UpdateIntensityAndSpeed() { - var t1, t2 int64 + var t1, t2 float64 var p1, p2 int var intensity float64 for i := range funscript.Actions { @@ -241,13 +242,13 @@ func (gt GradientTable) GetYRange(t float64) [2]float64 { func (funscript Script) getGradientTable(numSegments int, sceneDurationMilli int64) GradientTable { const windowSize = 15 - const backfillThreshold = 500 + const backfillThreshold = float64(500) segments := make([]struct { count int intensity int yRange [2]float64 - at int64 + at float64 }, numSegments) gradient := make(GradientTable, numSegments) posList := []int{} @@ -297,7 +298,7 @@ func (funscript Script) getGradientTable(numSegments int, sceneDurationMilli int // Fill in gaps in segments for i := 0; i < numSegments; i++ { - segmentTS := (maxts / int64(numSegments)) * int64(i) + segmentTS := float64((maxts / int64(numSegments)) * int64(i)) // Empty segment - fill it with the previous up to backfillThreshold ms if segments[i].count == 0 { @@ -406,7 +407,8 @@ func ConvertFunscriptToCSV(funscriptPath string) ([]byte, error) { pos = convertRange(pos, 0, funscript.Range, 0, 100) } - buffer.WriteString(fmt.Sprintf("%d,%d\r\n", action.At, pos)) + // I don't know whether the csv format requires int or float, so for now we'll use int + buffer.WriteString(fmt.Sprintf("%d,%d\r\n", int(math.Round(action.At)), pos)) } return buffer.Bytes(), nil }