49 lines
1.3 KiB
Go
49 lines
1.3 KiB
Go
package models
|
|
|
|
// Code generated by xo. DO NOT EDIT.
|
|
|
|
import (
|
|
"context"
|
|
)
|
|
|
|
// LeaderboardEntry represents a row from 'leaderboard_entry'.
|
|
type LeaderboardEntry struct {
|
|
Name string `json:"name"` // name
|
|
Points int `json:"points"` // points
|
|
LastValid Time `json:"last_valid"` // last_valid
|
|
}
|
|
|
|
// Leaderboard runs a custom query, returning results as LeaderboardEntry.
|
|
func Leaderboard(ctx context.Context, db DB) ([]*LeaderboardEntry, error) {
|
|
// query
|
|
const sqlstr = `SELECT u.name, ` +
|
|
`COALESCE(SUM(qa.points_awarded), 0) AS points, ` +
|
|
`COALESCE(MAX(qa.submitted_at), u.created_at) as last_valid_submission ` +
|
|
`FROM users u ` +
|
|
`LEFT JOIN question_attempt qa ON u.id = qa.user_id AND qa.correct ` +
|
|
`GROUP BY u.id ` +
|
|
`ORDER BY COALESCE(SUM(qa.points_awarded), 0) DESC, ` +
|
|
`MAX(qa.submitted_at) ASC`
|
|
// run
|
|
logf(sqlstr)
|
|
rows, err := db.QueryContext(ctx, sqlstr)
|
|
if err != nil {
|
|
return nil, logerror(err)
|
|
}
|
|
defer rows.Close()
|
|
// load results
|
|
var res []*LeaderboardEntry
|
|
for rows.Next() {
|
|
var le LeaderboardEntry
|
|
// scan
|
|
if err := rows.Scan(&le.Name, &le.Points, &le.LastValid); err != nil {
|
|
return nil, logerror(err)
|
|
}
|
|
res = append(res, &le)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, logerror(err)
|
|
}
|
|
return res, nil
|
|
}
|