507 lines
15 KiB
Go
507 lines
15 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
)
|
|
|
|
func ratingTestSegment(label string, start, duration, confidence float64) aiSegmentMeta {
|
|
return aiSegmentMeta{
|
|
Label: label,
|
|
StartSeconds: start,
|
|
EndSeconds: start + duration,
|
|
DurationSeconds: duration,
|
|
Score: confidence,
|
|
}
|
|
}
|
|
|
|
func TestComputeHighlightRatingSpansAllStars(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
segments []aiSegmentMeta
|
|
want int
|
|
}{
|
|
{
|
|
name: "one weak standing detection",
|
|
segments: []aiSegmentMeta{
|
|
ratingTestSegment("position:standing", 10, 6, 0.45),
|
|
},
|
|
want: 1,
|
|
},
|
|
{
|
|
name: "one brief strong position",
|
|
segments: []aiSegmentMeta{
|
|
ratingTestSegment("position:doggy", 10, 8, 0.72),
|
|
},
|
|
want: 2,
|
|
},
|
|
{
|
|
name: "two solid position segments",
|
|
segments: []aiSegmentMeta{
|
|
ratingTestSegment("position:doggy", 20, 18, 0.78),
|
|
ratingTestSegment("position:cowgirl", 120, 18, 0.78),
|
|
},
|
|
want: 3,
|
|
},
|
|
{
|
|
name: "several long high quality positions",
|
|
segments: []aiSegmentMeta{
|
|
ratingTestSegment("position:cowgirl", 20, 25, 0.82),
|
|
ratingTestSegment("position:reverse_cowgirl", 120, 25, 0.82),
|
|
ratingTestSegment("position:doggy", 220, 25, 0.82),
|
|
ratingTestSegment("position:toy_play", 320, 25, 0.82),
|
|
},
|
|
want: 4,
|
|
},
|
|
{
|
|
name: "exceptional sustained and varied positions",
|
|
segments: []aiSegmentMeta{
|
|
ratingTestSegment("position:cowgirl", 10, 40, 0.90),
|
|
ratingTestSegment("position:reverse_cowgirl", 100, 40, 0.90),
|
|
ratingTestSegment("position:doggy", 190, 40, 0.90),
|
|
ratingTestSegment("position:toy_play", 280, 40, 0.90),
|
|
ratingTestSegment("position:fingering", 370, 40, 0.90),
|
|
ratingTestSegment("position:missionary", 460, 40, 0.90),
|
|
},
|
|
want: 5,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := computeHighlightRating(tt.segments, 600)
|
|
if got.Stars != tt.want {
|
|
t.Fatalf("stars = %d, want %d (score %.1f)", got.Stars, tt.want, got.Score)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestExplicitPositionRanking(t *testing.T) {
|
|
labels := []string{
|
|
"cowgirl",
|
|
"reverse_cowgirl",
|
|
"doggy",
|
|
"toy_play",
|
|
"fingering",
|
|
"missionary",
|
|
"prone_bone",
|
|
"spooning",
|
|
"standing",
|
|
"69",
|
|
"blowjob",
|
|
}
|
|
|
|
previousWeight := 2.0
|
|
for index, label := range labels {
|
|
ranked := positionExplicitRatingRank(label)
|
|
wantRank := index + 1
|
|
|
|
if ranked.Rank != wantRank {
|
|
t.Fatalf("%s rank = %d, want %d", label, ranked.Rank, wantRank)
|
|
}
|
|
if ranked.Weight <= 0 || ranked.Weight >= previousWeight {
|
|
t.Fatalf(
|
|
"%s weight = %.2f, want a positive value below %.2f",
|
|
label,
|
|
ranked.Weight,
|
|
previousWeight,
|
|
)
|
|
}
|
|
|
|
previousWeight = ranked.Weight
|
|
}
|
|
|
|
for _, alias := range []string{"doggystyle", "standing_doggy"} {
|
|
if ranked := positionExplicitRatingRank(alias); ranked.Rank != 3 {
|
|
t.Fatalf("%s rank = %d, want alias rank 3", alias, ranked.Rank)
|
|
}
|
|
}
|
|
for _, grouped := range []string{"facesitting", "handjob", "cunnilingus", "boobjob"} {
|
|
if ranked := positionExplicitRatingRank(grouped); ranked.Rank != positionExplicitRatingRank("69").Rank &&
|
|
ranked.Rank != positionExplicitRatingRank("blowjob").Rank {
|
|
t.Fatalf("%s has unexpected grouped rank %d", grouped, ranked.Rank)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestExplicitClothingRanking(t *testing.T) {
|
|
labels := []string{
|
|
"lingerie",
|
|
"stockings",
|
|
"skirt",
|
|
"hotpants",
|
|
"bikini",
|
|
"bra",
|
|
"panties",
|
|
"croptop",
|
|
"heels",
|
|
"dress",
|
|
}
|
|
|
|
previousWeight := 2.0
|
|
for index, label := range labels {
|
|
ranked := clothingExplicitRatingRank(label)
|
|
wantRank := index + 1
|
|
|
|
if ranked.Rank != wantRank {
|
|
t.Fatalf("%s rank = %d, want %d", label, ranked.Rank, wantRank)
|
|
}
|
|
if ranked.Weight <= 0 || ranked.Weight >= previousWeight {
|
|
t.Fatalf(
|
|
"%s weight = %.2f, want a positive value below %.2f",
|
|
label,
|
|
ranked.Weight,
|
|
previousWeight,
|
|
)
|
|
}
|
|
|
|
previousWeight = ranked.Weight
|
|
}
|
|
}
|
|
|
|
func TestComputeHighlightRatingReportsBestExplicitRanks(t *testing.T) {
|
|
got := computeHighlightRating([]aiSegmentMeta{
|
|
ratingTestSegment("combo:position:standing+clothing:dress", 10, 20, 0.90),
|
|
ratingTestSegment("combo:position:cowgirl+clothing:panties", 80, 20, 0.90),
|
|
ratingTestSegment("combo:position:doggy+clothing:lingerie", 150, 20, 0.90),
|
|
}, 300)
|
|
|
|
if got.BestPosition != "cowgirl" || got.BestPositionRank != 1 {
|
|
t.Fatalf(
|
|
"best position = %q rank %d, want cowgirl rank 1",
|
|
got.BestPosition,
|
|
got.BestPositionRank,
|
|
)
|
|
}
|
|
if got.BestClothing != "lingerie" || got.BestClothingRank != 1 {
|
|
t.Fatalf(
|
|
"best clothing = %q rank %d, want lingerie rank 1",
|
|
got.BestClothing,
|
|
got.BestClothingRank,
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestComputeHighlightRatingFollowsExplicitRank(t *testing.T) {
|
|
positionScore := func(label string) float64 {
|
|
return computeHighlightRating([]aiSegmentMeta{
|
|
ratingTestSegment("position:"+label, 10, 30, 0.85),
|
|
}, 300).Score
|
|
}
|
|
clothingScore := func(label string) float64 {
|
|
return computeHighlightRating([]aiSegmentMeta{
|
|
ratingTestSegment("clothing:"+label, 10, 90, 0.90),
|
|
}, 300).Score
|
|
}
|
|
|
|
if !(positionScore("cowgirl") > positionScore("doggy") &&
|
|
positionScore("doggy") > positionScore("toy_play") &&
|
|
positionScore("toy_play") > positionScore("missionary") &&
|
|
positionScore("missionary") > positionScore("standing") &&
|
|
positionScore("standing") > positionScore("blowjob")) {
|
|
t.Fatal("position score does not follow the explicit ranking")
|
|
}
|
|
|
|
if !(clothingScore("lingerie") > clothingScore("stockings") &&
|
|
clothingScore("stockings") > clothingScore("hotpants") &&
|
|
clothingScore("hotpants") > clothingScore("bikini") &&
|
|
clothingScore("bikini") > clothingScore("panties") &&
|
|
clothingScore("panties") > clothingScore("dress")) {
|
|
t.Fatal("clothing score does not follow the explicit ranking")
|
|
}
|
|
}
|
|
|
|
func TestComputeHighlightRatingRewardsPositionDuration(t *testing.T) {
|
|
short := computeHighlightRating([]aiSegmentMeta{
|
|
ratingTestSegment("position:doggy", 10, 8, 0.80),
|
|
}, 600)
|
|
medium := computeHighlightRating([]aiSegmentMeta{
|
|
ratingTestSegment("position:doggy", 10, 35, 0.80),
|
|
}, 600)
|
|
long := computeHighlightRating([]aiSegmentMeta{
|
|
ratingTestSegment("position:doggy", 10, 120, 0.80),
|
|
}, 600)
|
|
|
|
if !(short.Score < medium.Score && medium.Score < long.Score) {
|
|
t.Fatalf(
|
|
"position duration should increase score: short=%.1f medium=%.1f long=%.1f",
|
|
short.Score,
|
|
medium.Score,
|
|
long.Score,
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestComputeHighlightRatingActionPrefersSustainedActivity(t *testing.T) {
|
|
briefPeak := computeHighlightRating([]aiSegmentMeta{
|
|
ratingTestSegment("position:doggy", 10, 8, 0.95),
|
|
}, 600)
|
|
sustained := computeHighlightRating([]aiSegmentMeta{
|
|
ratingTestSegment("position:doggy", 10, 45, 0.55),
|
|
}, 600)
|
|
|
|
if sustained.ActionScore <= briefPeak.ActionScore {
|
|
t.Fatalf(
|
|
"sustained action should outrank a brief peak: sustained=%.1f brief=%.1f",
|
|
sustained.ActionScore,
|
|
briefPeak.ActionScore,
|
|
)
|
|
}
|
|
if sustained.Score <= briefPeak.Score {
|
|
t.Fatalf(
|
|
"rating should follow sustained action: sustained=%.1f brief=%.1f",
|
|
sustained.Score,
|
|
briefPeak.Score,
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestComputeHighlightRatingDoesNotDoubleCountOverlaps(t *testing.T) {
|
|
got := computeHighlightRating([]aiSegmentMeta{
|
|
ratingTestSegment("position:cowgirl", 0, 30, 0.90),
|
|
ratingTestSegment("position:doggy", 10, 30, 0.90),
|
|
}, 100)
|
|
|
|
if got.FlaggedSeconds != 40 {
|
|
t.Fatalf("flagged seconds = %.1f, want 40.0", got.FlaggedSeconds)
|
|
}
|
|
if got.CoverageRatio != 0.4 {
|
|
t.Fatalf("coverage ratio = %.4f, want 0.4000", got.CoverageRatio)
|
|
}
|
|
}
|
|
|
|
func TestComputeHighlightRatingReportsIndependentComponents(t *testing.T) {
|
|
got := computeHighlightRating([]aiSegmentMeta{
|
|
ratingTestSegment("combo:position:cowgirl+body:pussy+clothing:lingerie", 10, 40, 0.90),
|
|
ratingTestSegment("combo:position:doggy+object:dildo+clothing:stockings", 100, 40, 0.90),
|
|
}, 300)
|
|
|
|
components := map[string]float64{
|
|
"position": got.PositionScore,
|
|
"clothing": got.ClothingScore,
|
|
"duration": got.DurationScore,
|
|
"strength": got.StrengthScore,
|
|
"coverage": got.CoverageScore,
|
|
"context": got.ContextScore,
|
|
"variety": got.VarietyScore,
|
|
"action": got.ActionScore,
|
|
}
|
|
for name, value := range components {
|
|
if value <= 0 || value > 100 {
|
|
t.Fatalf("%s component = %.1f, want value in (0, 100]", name, value)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestComputeHighlightRatingStrengthFollowsConfidence(t *testing.T) {
|
|
weak := computeHighlightRating([]aiSegmentMeta{
|
|
ratingTestSegment("position:doggy", 10, 45, 0.45),
|
|
}, 300)
|
|
strong := computeHighlightRating([]aiSegmentMeta{
|
|
ratingTestSegment("position:doggy", 10, 45, 0.90),
|
|
}, 300)
|
|
|
|
if strong.StrengthScore <= weak.StrengthScore {
|
|
t.Fatalf(
|
|
"strength should follow confidence: strong=%.1f weak=%.1f",
|
|
strong.StrengthScore,
|
|
weak.StrengthScore,
|
|
)
|
|
}
|
|
if strong.Score <= weak.Score {
|
|
t.Fatalf(
|
|
"rating should reward stronger evidence: strong=%.1f weak=%.1f",
|
|
strong.Score,
|
|
weak.Score,
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestComputeHighlightRatingRatesContextWithoutPosition(t *testing.T) {
|
|
clothingOnly := computeHighlightRating([]aiSegmentMeta{
|
|
ratingTestSegment("clothing:lingerie", 10, 60, 0.90),
|
|
ratingTestSegment("clothing:lingerie", 120, 60, 0.90),
|
|
ratingTestSegment("clothing:lingerie", 230, 60, 0.90),
|
|
}, 600)
|
|
richContext := computeHighlightRating([]aiSegmentMeta{
|
|
ratingTestSegment("combo:body:breasts+clothing:lingerie", 10, 45, 0.90),
|
|
ratingTestSegment("combo:object:vibrator+clothing:lingerie", 120, 60, 0.90),
|
|
ratingTestSegment("combo:body:penis+object:dildo", 240, 45, 0.90),
|
|
}, 600)
|
|
|
|
if clothingOnly.Stars != 3 {
|
|
t.Fatalf(
|
|
"clothing-only stars = %d, want 3 (score %.1f)",
|
|
clothingOnly.Stars,
|
|
clothingOnly.Score,
|
|
)
|
|
}
|
|
if richContext.Stars != 3 {
|
|
t.Fatalf(
|
|
"rich context stars = %d, want 3 (score %.1f)",
|
|
richContext.Stars,
|
|
richContext.Score,
|
|
)
|
|
}
|
|
if richContext.Stars > 3 {
|
|
t.Fatalf("context rating must stay below 4 stars: %#v", richContext)
|
|
}
|
|
}
|
|
|
|
func TestComputeHighlightRatingPositionsOutrankContext(t *testing.T) {
|
|
context := computeHighlightRating([]aiSegmentMeta{
|
|
ratingTestSegment("combo:body:breasts+clothing:lingerie+object:vibrator", 10, 240, 0.95),
|
|
}, 600)
|
|
positions := computeHighlightRating([]aiSegmentMeta{
|
|
ratingTestSegment("position:doggy", 10, 40, 0.90),
|
|
ratingTestSegment("position:cowgirl", 100, 40, 0.90),
|
|
ratingTestSegment("position:missionary", 190, 40, 0.90),
|
|
ratingTestSegment("position:blowjob", 280, 40, 0.90),
|
|
}, 600)
|
|
|
|
if positions.Score <= context.Score || positions.Stars <= context.Stars {
|
|
t.Fatalf(
|
|
"positions should outrank context: positions=%.1f/%d context=%.1f/%d",
|
|
positions.Score,
|
|
positions.Stars,
|
|
context.Score,
|
|
context.Stars,
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestComputeHighlightRatingExplicitSignalsBoostPositions(t *testing.T) {
|
|
positionSegments := []aiSegmentMeta{
|
|
ratingTestSegment("position:doggy", 20, 18, 0.78),
|
|
ratingTestSegment("position:cowgirl", 120, 18, 0.78),
|
|
}
|
|
|
|
base := computeHighlightRating(positionSegments, 600)
|
|
withObject := computeHighlightRating(append(
|
|
append([]aiSegmentMeta{}, positionSegments...),
|
|
ratingTestSegment("object:dildo", 220, 60, 0.90),
|
|
), 600)
|
|
withClothing := computeHighlightRating(append(
|
|
append([]aiSegmentMeta{}, positionSegments...),
|
|
ratingTestSegment("clothing:lingerie", 220, 60, 0.90),
|
|
), 600)
|
|
withBody := computeHighlightRating(append(
|
|
append([]aiSegmentMeta{}, positionSegments...),
|
|
ratingTestSegment("body:pussy", 220, 60, 0.90),
|
|
), 600)
|
|
|
|
if !(base.Score < withObject.Score &&
|
|
withObject.Score < withClothing.Score &&
|
|
withClothing.Score < withBody.Score) {
|
|
t.Fatalf(
|
|
"explicit signal priority is wrong: base=%.1f object=%.1f clothing=%.1f body=%.1f",
|
|
base.Score,
|
|
withObject.Score,
|
|
withClothing.Score,
|
|
withBody.Score,
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestComputeHighlightRatingExplicitContextCanElevateStrongPositions(t *testing.T) {
|
|
positions := []aiSegmentMeta{
|
|
ratingTestSegment("position:cowgirl", 20, 25, 0.82),
|
|
ratingTestSegment("position:reverse_cowgirl", 120, 25, 0.82),
|
|
ratingTestSegment("position:doggy", 220, 25, 0.82),
|
|
ratingTestSegment("position:toy_play", 320, 25, 0.82),
|
|
}
|
|
positionOnly := computeHighlightRating(positions, 600)
|
|
withExplicitContext := computeHighlightRating(append(
|
|
append([]aiSegmentMeta{}, positions...),
|
|
ratingTestSegment("body:pussy", 400, 90, 0.92),
|
|
ratingTestSegment("clothing:lingerie", 500, 90, 0.92),
|
|
), 600)
|
|
|
|
if positionOnly.Stars != 4 {
|
|
t.Fatalf("position-only stars = %d, want 4 (score %.1f)", positionOnly.Stars, positionOnly.Score)
|
|
}
|
|
if withExplicitContext.Stars != 5 {
|
|
t.Fatalf(
|
|
"positions with explicit context stars = %d, want 5 (score %.1f)",
|
|
withExplicitContext.Stars,
|
|
withExplicitContext.Score,
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestComputeHighlightRatingLongMixedContextRegression(t *testing.T) {
|
|
segments := []aiSegmentMeta{
|
|
ratingTestSegment("object:dildo", 24.5, 5, 0.792783260345459),
|
|
ratingTestSegment("object:dildo", 43.5, 8, 0.923585057258606),
|
|
ratingTestSegment("clothing:lingerie", 94.5, 21, 0.9069388088058022),
|
|
ratingTestSegment("clothing:lingerie", 120.5, 33, 0.887133002281189),
|
|
ratingTestSegment("object:vibrator", 215.5, 6, 0.40453797578811646),
|
|
ratingTestSegment("combo:body:breasts+clothing:lingerie", 298.5, 8, 0.6898824721574783),
|
|
ratingTestSegment("object:vibrator", 330.5, 5, 0.6836381554603577),
|
|
ratingTestSegment("clothing:lingerie", 348.5, 59, 0.9197490215301514),
|
|
ratingTestSegment("combo:object:vibrator+object:collar+clothing:lingerie", 416.5, 36, 0.8156423893044976),
|
|
ratingTestSegment("clothing:lingerie", 465.5, 36, 0.8007044196128845),
|
|
}
|
|
|
|
got := computeHighlightRating(segments, 504)
|
|
if got.Stars != 3 {
|
|
t.Fatalf("stars = %d, want 3 (score %.1f)", got.Stars, got.Score)
|
|
}
|
|
|
|
encoded, err := json.Marshal(got)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Logf("rating=%s", encoded)
|
|
}
|
|
|
|
func TestPrepareAIRatingSegmentsKeepsDifferentPositionsSeparate(t *testing.T) {
|
|
segments := prepareAIRatingSegments([]aiSegmentMeta{
|
|
ratingTestSegment("position:doggy", 10, 12, 0.85),
|
|
ratingTestSegment("position:cowgirl", 23, 12, 0.85),
|
|
})
|
|
|
|
if len(segments) != 2 {
|
|
t.Fatalf("segments = %d, want 2: %#v", len(segments), segments)
|
|
}
|
|
if segments[0].Position == segments[1].Position {
|
|
t.Fatalf("different positions were collapsed: %#v", segments)
|
|
}
|
|
}
|
|
|
|
func TestPrepareAIRatingSegmentsMergesSamePositionAcrossShortGap(t *testing.T) {
|
|
segments := prepareAIRatingSegments([]aiSegmentMeta{
|
|
ratingTestSegment("position:doggy", 10, 12, 0.85),
|
|
ratingTestSegment("position:doggy", 23, 12, 0.85),
|
|
})
|
|
|
|
if len(segments) != 1 {
|
|
t.Fatalf("segments = %d, want 1: %#v", len(segments), segments)
|
|
}
|
|
if segments[0].Position != "doggy" {
|
|
t.Fatalf("position = %q, want doggy", segments[0].Position)
|
|
}
|
|
if segments[0].DurationSeconds != 24 {
|
|
t.Fatalf(
|
|
"duration = %.1f, want 24 seconds of actual position evidence",
|
|
segments[0].DurationSeconds,
|
|
)
|
|
}
|
|
if segments[0].RatingIntensity <= 0 {
|
|
t.Fatalf("rating intensity = %.3f, want a positive heatcurve value", segments[0].RatingIntensity)
|
|
}
|
|
|
|
wantIntensity := ratingClamp01(
|
|
ratingSegmentSeverity(segments[0].Label) *
|
|
ratingConfidenceWeight(segments[0].Score),
|
|
)
|
|
if diff := segments[0].RatingIntensity - wantIntensity; diff < -0.0001 || diff > 0.0001 {
|
|
t.Fatalf(
|
|
"rating intensity = %.4f, want %.4f",
|
|
segments[0].RatingIntensity,
|
|
wantIntensity,
|
|
)
|
|
}
|
|
}
|