Scene Marker duration filter and sort (#5472)

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
This commit is contained in:
dogwithakeyboard
2024-11-29 05:28:10 +00:00
committed by GitHub
parent e097f2b3f4
commit 6ad0951878
8 changed files with 155 additions and 2 deletions

View File

@@ -11,6 +11,8 @@ type SceneMarkerFilterType struct {
Performers *MultiCriterionInput `json:"performers"`
// Filter to only include scene markers from these scenes
Scenes *MultiCriterionInput `json:"scenes"`
// Filter by duration (in seconds)
Duration *FloatCriterionInput `json:"duration"`
// Filter by created at
CreatedAt *TimestampCriterionInput `json:"created_at"`
// Filter by updated at

View File

@@ -367,6 +367,7 @@ var sceneMarkerSortOptions = sortOptions{
"scenes_updated_at",
"seconds",
"updated_at",
"duration",
}
func (qb *SceneMarkerStore) setSceneMarkerSort(query *queryBuilder, findFilter *models.FindFilterType) error {
@@ -386,6 +387,9 @@ func (qb *SceneMarkerStore) setSceneMarkerSort(query *queryBuilder, findFilter *
case "title":
query.join(tagTable, "", "scene_markers.primary_tag_id = tags.id")
query.sortAndPagination += " ORDER BY COALESCE(NULLIF(scene_markers.title,''), tags.name) COLLATE NATURAL_CI " + direction
case "duration":
sort = "(scene_markers.end_seconds - scene_markers.seconds)"
query.sortAndPagination += getSort(sort, direction, sceneMarkerTable)
default:
query.sortAndPagination += getSort(sort, direction, sceneMarkerTable)
}

View File

@@ -41,6 +41,7 @@ func (qb *sceneMarkerFilterHandler) criterionHandler() criterionHandler {
qb.sceneTagsCriterionHandler(sceneMarkerFilter.SceneTags),
qb.performersCriterionHandler(sceneMarkerFilter.Performers),
qb.scenesCriterionHandler(sceneMarkerFilter.Scenes),
floatCriterionHandler(sceneMarkerFilter.Duration, "COALESCE(scene_markers.end_seconds - scene_markers.seconds, NULL)", nil),
&timestampCriterionHandler{sceneMarkerFilter.CreatedAt, "scene_markers.created_at", nil},
&timestampCriterionHandler{sceneMarkerFilter.UpdatedAt, "scene_markers.updated_at", nil},
&dateCriterionHandler{sceneMarkerFilter.SceneDate, "scenes.date", qb.joinScenes},

View File

@@ -391,6 +391,116 @@ func TestMarkerQuerySceneTags(t *testing.T) {
})
}
func markersToIDs(i []*models.SceneMarker) []int {
ret := make([]int, len(i))
for i, v := range i {
ret[i] = v.ID
}
return ret
}
func TestMarkerQueryDuration(t *testing.T) {
type test struct {
name string
markerFilter *models.SceneMarkerFilterType
include []int
exclude []int
}
cases := []test{
{
"is null",
&models.SceneMarkerFilterType{
Duration: &models.FloatCriterionInput{
Modifier: models.CriterionModifierIsNull,
},
},
[]int{markerIdxWithScene},
[]int{markerIdxWithDuration},
},
{
"not null",
&models.SceneMarkerFilterType{
Duration: &models.FloatCriterionInput{
Modifier: models.CriterionModifierNotNull,
},
},
[]int{markerIdxWithDuration},
[]int{markerIdxWithScene},
},
{
"equals",
&models.SceneMarkerFilterType{
Duration: &models.FloatCriterionInput{
Modifier: models.CriterionModifierEquals,
Value: markerIdxWithDuration,
},
},
[]int{markerIdxWithDuration},
[]int{markerIdx2WithDuration, markerIdxWithScene},
},
{
"not equals",
&models.SceneMarkerFilterType{
Duration: &models.FloatCriterionInput{
Modifier: models.CriterionModifierNotEquals,
Value: markerIdx2WithDuration,
},
},
[]int{markerIdxWithDuration},
[]int{markerIdx2WithDuration, markerIdxWithScene},
},
{
"greater than",
&models.SceneMarkerFilterType{
Duration: &models.FloatCriterionInput{
Modifier: models.CriterionModifierGreaterThan,
Value: markerIdxWithDuration,
},
},
[]int{markerIdx2WithDuration},
[]int{markerIdxWithDuration, markerIdxWithScene},
},
{
"less than",
&models.SceneMarkerFilterType{
Duration: &models.FloatCriterionInput{
Modifier: models.CriterionModifierLessThan,
Value: markerIdx2WithDuration,
},
},
[]int{markerIdxWithDuration},
[]int{markerIdx2WithDuration, markerIdxWithScene},
},
}
qb := db.SceneMarker
for _, tt := range cases {
runWithRollbackTxn(t, tt.name, func(t *testing.T, ctx context.Context) {
assert := assert.New(t)
got, _, err := qb.Query(ctx, tt.markerFilter, nil)
if err != nil {
t.Errorf("SceneMarkerStore.Query() error = %v", err)
return
}
ids := markersToIDs(got)
include := indexesToIDs(markerIDs, tt.include)
exclude := indexesToIDs(markerIDs, tt.exclude)
for _, i := range include {
assert.Contains(ids, i)
}
for _, e := range exclude {
assert.NotContains(ids, e)
}
})
}
}
func queryMarkers(ctx context.Context, t *testing.T, sqb models.SceneMarkerReader, markerFilter *models.SceneMarkerFilterType, findFilter *models.FindFilterType) []*models.SceneMarker {
t.Helper()
result, _, err := sqb.Query(ctx, markerFilter, findFilter)

View File

@@ -276,6 +276,8 @@ const (
markerIdxWithScene = iota
markerIdxWithTag
markerIdxWithSceneTag
markerIdxWithDuration
markerIdx2WithDuration
totalMarkers
)
@@ -1754,10 +1756,20 @@ func createStudios(ctx context.Context, n int, o int) error {
return nil
}
func getMarkerEndSeconds(index int) *float64 {
if index != markerIdxWithDuration && index != markerIdx2WithDuration {
return nil
}
ret := float64(index)
return &ret
}
func createMarker(ctx context.Context, mqb models.SceneMarkerReaderWriter, markerSpec markerSpec) error {
markerIdx := len(markerIDs)
marker := models.SceneMarker{
SceneID: sceneIDs[markerSpec.sceneIdx],
PrimaryTagID: tagIDs[markerSpec.primaryTagIdx],
EndSeconds: getMarkerEndSeconds(markerIdx),
}
err := mqb.Create(ctx, &marker)