2024-04-29 17:26:46 -04:00
/ *
Copyright ( C ) 2024 Pagefault Games
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU Affero General Public License for more details .
You should have received a copy of the GNU Affero General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
* /
2024-04-29 15:32:58 -04:00
2024-03-16 21:51:13 -04:00
package db
2024-03-17 13:18:51 -04:00
import (
2024-03-23 16:26:00 -04:00
"math"
2024-05-18 13:38:56 +02:00
"database/sql"
2024-03-23 16:26:00 -04:00
2024-04-29 15:22:27 -04:00
"github.com/pagefaultgames/rogueserver/defs"
2024-03-17 13:18:51 -04:00
)
2024-05-10 21:30:47 +02:00
func TryAddDailyRun ( seed string ) ( string , error ) {
var actualSeed string
err := handle . QueryRow ( "INSERT INTO dailyRuns (seed, date) VALUES (?, UTC_DATE()) ON DUPLICATE KEY UPDATE date = date RETURNING seed" , seed ) . Scan ( & actualSeed )
2024-03-16 21:51:13 -04:00
if err != nil {
2024-05-10 15:44:35 -04:00
return "" , err
2024-03-16 21:51:13 -04:00
}
2024-05-10 21:30:47 +02:00
return actualSeed , nil
}
func GetDailyRunSeed ( ) ( string , error ) {
var seed string
err := handle . QueryRow ( "SELECT seed FROM dailyRuns WHERE date = UTC_DATE()" ) . Scan ( & seed )
if err != nil {
2024-05-10 15:44:35 -04:00
return "" , err
2024-05-10 21:30:47 +02:00
}
return seed , nil
2024-03-16 21:51:13 -04:00
}
2024-03-17 13:18:51 -04:00
2024-03-17 20:48:49 -04:00
func AddOrUpdateAccountDailyRun ( uuid [ ] byte , score int , wave int ) error {
2024-03-22 21:42:27 -04:00
_ , err := handle . Exec ( "INSERT INTO accountDailyRuns (uuid, date, score, wave, timestamp) VALUES (?, UTC_DATE(), ?, ?, UTC_TIMESTAMP()) ON DUPLICATE KEY UPDATE score = GREATEST(score, ?), wave = GREATEST(wave, ?), timestamp = IF(score < ?, UTC_TIMESTAMP(), timestamp)" , uuid , score , wave , score , wave , score )
2024-03-17 20:48:49 -04:00
if err != nil {
return err
}
return nil
}
2024-05-18 13:38:56 +02:00
func FetchRankings ( category int , page int , uuid [ ] byte ) ( [ ] defs . DailyRanking , error ) {
2024-03-17 13:18:51 -04:00
var rankings [ ] defs . DailyRanking
2024-03-17 13:36:32 -04:00
offset := ( page - 1 ) * 10
2024-03-23 16:26:00 -04:00
var query string
switch category {
case 0 :
2024-04-30 14:34:40 -04:00
query = "SELECT RANK() OVER (ORDER BY adr.score DESC, adr.timestamp), a.username, adr.score, adr.wave FROM accountDailyRuns adr JOIN dailyRuns dr ON dr.date = adr.date JOIN accounts a ON adr.uuid = a.uuid WHERE dr.date = UTC_DATE() AND a.banned = 0 LIMIT 10 OFFSET ?"
2024-03-23 16:26:00 -04:00
case 1 :
2024-04-30 14:34:40 -04:00
query = "SELECT RANK() OVER (ORDER BY SUM(adr.score) DESC, adr.timestamp), a.username, SUM(adr.score), 0 FROM accountDailyRuns adr JOIN dailyRuns dr ON dr.date = adr.date JOIN accounts a ON adr.uuid = a.uuid WHERE dr.date >= DATE_SUB(DATE(UTC_TIMESTAMP()), INTERVAL DAYOFWEEK(UTC_TIMESTAMP()) - 1 DAY) AND a.banned = 0 GROUP BY a.username ORDER BY 1 LIMIT 10 OFFSET ?"
2024-05-18 13:38:56 +02:00
case 2 :
// We retrieve the friends of the user and the user itself
query = ` SELECT RANK ( ) OVER ( ORDER BY score DESC , timestamp ) AS rank , username , score , wave
FROM (
SELECT a . username , adr . score , adr . wave , adr . timestamp
FROM accountDailyRuns adr
JOIN dailyRuns dr ON dr . date = adr . date
JOIN accounts a ON adr . uuid = a . uuid
2024-05-18 22:59:00 +02:00
JOIN friends f ON a . uuid = f . friend
2024-05-18 13:38:56 +02:00
WHERE dr . date = UTC_DATE ( )
AND a . banned = 0
AND f . user = ?
UNION
SELECT a . username , adr . score , adr . wave , adr . timestamp
FROM accountDailyRuns adr
JOIN dailyRuns dr ON dr . date = adr . date
JOIN accounts a ON adr . uuid = a . uuid
WHERE dr . date = UTC_DATE ( )
AND a . banned = 0
2024-05-18 22:59:00 +02:00
AND a . uuid = ?
2024-05-18 13:38:56 +02:00
) AS combined LIMIT 10 OFFSET ? ; `
}
var results * sql . Rows
2024-05-18 22:59:00 +02:00
var err error
2024-05-18 13:38:56 +02:00
if category == 2 {
2024-05-18 22:59:00 +02:00
results , err = handle . Query ( query , uuid , uuid , offset )
2024-05-18 13:38:56 +02:00
} else {
results , err = handle . Query ( query , offset )
2024-03-23 16:26:00 -04:00
}
2024-03-17 13:18:51 -04:00
if err != nil {
return rankings , err
}
defer results . Close ( )
for results . Next ( ) {
2024-04-01 22:54:55 -04:00
var ranking defs . DailyRanking
2024-03-17 20:48:49 -04:00
err = results . Scan ( & ranking . Rank , & ranking . Username , & ranking . Score , & ranking . Wave )
2024-03-17 13:18:51 -04:00
if err != nil {
return rankings , err
}
rankings = append ( rankings , ranking )
}
return rankings , nil
}
2024-03-23 16:26:00 -04:00
2024-05-18 13:38:56 +02:00
func FetchRankingPageCount ( category int , uuid [ ] byte ) ( int , error ) {
2024-03-23 16:26:00 -04:00
var query string
switch category {
case 0 :
query = "SELECT COUNT(a.username) FROM accountDailyRuns adr JOIN dailyRuns dr ON dr.date = adr.date JOIN accounts a ON adr.uuid = a.uuid WHERE dr.date = UTC_DATE()"
case 1 :
2024-03-23 16:33:26 -04:00
query = "SELECT COUNT(DISTINCT a.username) FROM accountDailyRuns adr JOIN dailyRuns dr ON dr.date = adr.date JOIN accounts a ON adr.uuid = a.uuid WHERE dr.date >= DATE_SUB(DATE(UTC_TIMESTAMP()), INTERVAL DAYOFWEEK(UTC_TIMESTAMP()) - 1 DAY)"
2024-05-18 13:38:56 +02:00
case 2 :
query = ` SELECT COUNT ( a . username )
FROM accountDailyRuns adr
JOIN dailyRuns dr ON dr . date = adr . date
JOIN accounts a ON adr . uuid = a . uuid
2024-05-18 22:59:00 +02:00
JOIN friends f ON a . uuid = f . friend
2024-05-18 13:38:56 +02:00
WHERE dr . date = UTC_DATE ( )
2024-05-18 22:59:00 +02:00
AND f . user = ? `
2024-03-23 16:26:00 -04:00
}
2024-04-01 22:54:55 -04:00
var recordCount int
2024-05-18 22:59:00 +02:00
var err error
2024-05-18 13:38:56 +02:00
if category == 2 {
2024-05-18 22:59:00 +02:00
err = handle . QueryRow ( query , uuid ) . Scan ( & recordCount )
2024-05-18 13:38:56 +02:00
// We only fetch friends of the account, not the account itself so adding +1 here.
// this way, we don't have to do the big union query like in FetchRankings
recordCount += 1
} else {
err = handle . QueryRow ( query ) . Scan ( & recordCount )
2024-03-23 16:26:00 -04:00
}
2024-05-18 22:59:00 +02:00
if err != nil {
return 0 , err
}
2024-03-23 16:26:00 -04:00
return int ( math . Ceil ( float64 ( recordCount ) / 10 ) ) , nil
}