Skip to content

Commit

Permalink
Add additional stats to the Stats page (stashapp#3812)
Browse files Browse the repository at this point in the history
* Add o_counter, play_duration, play_count, unique_play_count stats
  • Loading branch information
hontheinternet authored Jul 11, 2023
1 parent 4f0e0e1 commit ff22577
Show file tree
Hide file tree
Showing 9 changed files with 209 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,4 @@ node_modules
/stash
dist
.DS_Store
/.local
/.local*
22 changes: 13 additions & 9 deletions graphql/documents/queries/misc.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,20 @@ query AllTagsForFilter {

query Stats {
stats {
scene_count,
scenes_size,
scenes_duration,
image_count,
images_size,
gallery_count,
performer_count,
studio_count,
movie_count,
scene_count
scenes_size
scenes_duration
image_count
images_size
gallery_count
performer_count
studio_count
movie_count
tag_count
total_o_count
total_play_duration
total_play_count
scenes_played
}
}

Expand Down
4 changes: 4 additions & 0 deletions graphql/schema/types/stats.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@ type StatsResultType {
studio_count: Int!
movie_count: Int!
tag_count: Int!
total_o_count: Int!
total_play_duration: Float!
total_play_count: Int!
scenes_played: Int!
}
28 changes: 18 additions & 10 deletions internal/api/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,18 +157,26 @@ func (r *queryResolver) Stats(ctx context.Context) (*StatsResultType, error) {
studiosCount, _ := studiosQB.Count(ctx)
moviesCount, _ := moviesQB.Count(ctx)
tagsCount, _ := tagsQB.Count(ctx)
totalOCount, _ := scenesQB.OCount(ctx)
totalPlayDuration, _ := scenesQB.PlayDuration(ctx)
totalPlayCount, _ := scenesQB.PlayCount(ctx)
uniqueScenePlayCount, _ := scenesQB.UniqueScenePlayCount(ctx)

ret = StatsResultType{
SceneCount: scenesCount,
ScenesSize: scenesSize,
ScenesDuration: scenesDuration,
ImageCount: imageCount,
ImagesSize: imageSize,
GalleryCount: galleryCount,
PerformerCount: performersCount,
StudioCount: studiosCount,
MovieCount: moviesCount,
TagCount: tagsCount,
SceneCount: scenesCount,
ScenesSize: scenesSize,
ScenesDuration: scenesDuration,
ImageCount: imageCount,
ImagesSize: imageSize,
GalleryCount: galleryCount,
PerformerCount: performersCount,
StudioCount: studiosCount,
MovieCount: moviesCount,
TagCount: tagsCount,
TotalOCount: totalOCount,
TotalPlayDuration: totalPlayDuration,
TotalPlayCount: totalPlayCount,
ScenesPlayed: uniqueScenePlayCount,
}

return nil
Expand Down
84 changes: 84 additions & 0 deletions pkg/models/mocks/SceneReaderWriter.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions pkg/models/scene.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,16 @@ type SceneReader interface {

CountByPerformerID(ctx context.Context, performerID int) (int, error)
OCountByPerformerID(ctx context.Context, performerID int) (int, error)
OCount(ctx context.Context) (int, error)
// FindByStudioID(studioID int) ([]*Scene, error)
FindByMovieID(ctx context.Context, movieID int) ([]*Scene, error)
CountByMovieID(ctx context.Context, movieID int) (int, error)
Count(ctx context.Context) (int, error)
PlayCount(ctx context.Context) (int, error)
UniqueScenePlayCount(ctx context.Context) (int, error)
Size(ctx context.Context) (float64, error)
Duration(ctx context.Context) (float64, error)
PlayDuration(ctx context.Context) (float64, error)
// SizeCount() (string, error)
CountByStudioID(ctx context.Context, studioID int) (int, error)
CountByTagID(ctx context.Context, tagID int) (int, error)
Expand Down
43 changes: 43 additions & 0 deletions pkg/sqlite/scene.go
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,18 @@ func (qb *SceneStore) OCountByPerformerID(ctx context.Context, performerID int)
return ret, nil
}

func (qb *SceneStore) OCount(ctx context.Context) (int, error) {
table := qb.table()

q := dialect.Select(goqu.COALESCE(goqu.SUM("o_counter"), 0)).From(table)
var ret int
if err := querySimple(ctx, q, &ret); err != nil {
return 0, err
}

return ret, nil
}

func (qb *SceneStore) FindByMovieID(ctx context.Context, movieID int) ([]*models.Scene, error) {
sq := dialect.From(scenesMoviesJoinTable).Select(scenesMoviesJoinTable.Col(sceneIDColumn)).Where(
scenesMoviesJoinTable.Col(movieIDColumn).Eq(movieID),
Expand All @@ -730,6 +742,24 @@ func (qb *SceneStore) Count(ctx context.Context) (int, error) {
return count(ctx, q)
}

func (qb *SceneStore) PlayCount(ctx context.Context) (int, error) {
q := dialect.Select(goqu.COALESCE(goqu.SUM("play_count"), 0)).From(qb.table())

var ret int
if err := querySimple(ctx, q, &ret); err != nil {
return 0, err
}

return ret, nil
}

func (qb *SceneStore) UniqueScenePlayCount(ctx context.Context) (int, error) {
table := qb.table()
q := dialect.Select(goqu.COUNT("*")).From(table).Where(table.Col("play_count").Gt(0))

return count(ctx, q)
}

func (qb *SceneStore) Size(ctx context.Context) (float64, error) {
table := qb.table()
fileTable := fileTableMgr.table
Expand Down Expand Up @@ -771,6 +801,19 @@ func (qb *SceneStore) Duration(ctx context.Context) (float64, error) {
return ret, nil
}

func (qb *SceneStore) PlayDuration(ctx context.Context) (float64, error) {
table := qb.table()

q := dialect.Select(goqu.COALESCE(goqu.SUM("play_duration"), 0)).From(table)

var ret float64
if err := querySimple(ctx, q, &ret); err != nil {
return 0, err
}

return ret, nil
}

func (qb *SceneStore) CountByStudioID(ctx context.Context, studioID int) (int, error) {
table := qb.table()

Expand Down
37 changes: 37 additions & 0 deletions ui/v2.5/src/components/Stats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ export const Stats: React.FC = () => {
3
);

const totalPlayDuration = TextUtils.secondsAsTimeString(
data.stats.total_play_duration,
3
);

return (
<div className="mt-5">
<div className="col col-sm-8 m-sm-auto row stats">
Expand Down Expand Up @@ -114,6 +119,38 @@ export const Stats: React.FC = () => {
</p>
</div>
</div>
<div className="col col-sm-8 m-sm-auto row stats">
<div className="stats-element">
<p className="title">
<FormattedNumber value={data.stats.total_o_count} />
</p>
<p className="heading">
<FormattedMessage id="stats.total_o_count" />
</p>
</div>
<div className="stats-element">
<p className="title">
<FormattedNumber value={data.stats.total_play_count} />
</p>
<p className="heading">
<FormattedMessage id="stats.total_play_count" />
</p>
</div>
<div className="stats-element">
<p className="title">
<FormattedNumber value={data.stats.scenes_played} />
</p>
<p className="heading">
<FormattedMessage id="stats.scenes_played" />
</p>
</div>
<div className="stats-element">
<p className="title">{totalPlayDuration || "-"}</p>
<p className="heading">
<FormattedMessage id="stats.total_play_duration" />
</p>
</div>
</div>
</div>
);
};
Expand Down
6 changes: 5 additions & 1 deletion ui/v2.5/src/locales/en-GB.json
Original file line number Diff line number Diff line change
Expand Up @@ -1218,7 +1218,11 @@
"stats": {
"image_size": "Images size",
"scenes_duration": "Scenes duration",
"scenes_size": "Scenes size"
"scenes_size": "Scenes size",
"scenes_played": "Scenes Played",
"total_play_duration": "Total Play Duration",
"total_play_count": "Total Play Count",
"total_o_count": "Total O-Count"
},
"status": "Status: {statusText}",
"studio": "Studio",
Expand Down

0 comments on commit ff22577

Please sign in to comment.