Improve live and random live handling

- Add random live handlers, schemas and persistence for lot/play/continue/gameover/reward flow
- Update live status and schedule generation, including special rotation handling and CN timezone alignment
- Add config support for unlocking all daily special rotation songs and document the option
- Refresh live play, reward, precise score and session logic plus bundled main.db updates

Signed-off-by: Sean Du <do4suki@gmail.com>
This commit is contained in:
2026-06-06 20:59:45 +08:00
parent 4e642cc7c1
commit 0aacf8a4e9
28 changed files with 1085 additions and 228 deletions
+35
View File
@@ -10,6 +10,10 @@ import (
// https://github.com/YumeMichi/honoka-chan/blob/a749efad9fd0789668dedcb59948248da369d32c/handler/live.go#L554
// https://github.com/DarkEnergyProcessor/NPPS4/blob/29aaba6e7a3b4b80d414e58f4b511a9627cb0e24/npps4/system/live.py#L360
func (ss *Session) GetLiveInProgress() (bool, *usermodel.UserLiveInProgress) {
if ss.UserEng == nil {
return false, nil
}
progress := usermodel.UserLiveInProgress{}
has, err := ss.UserEng.Table(new(usermodel.UserLiveInProgress)).
Where("user_id = ?", ss.UserID).Get(&progress)
@@ -24,6 +28,10 @@ func (ss *Session) GetLiveInProgress() (bool, *usermodel.UserLiveInProgress) {
// https://github.com/YumeMichi/honoka-chan/blob/a749efad9fd0789668dedcb59948248da369d32c/handler/live.go#L45
// https://github.com/DarkEnergyProcessor/NPPS4/blob/29aaba6e7a3b4b80d414e58f4b511a9627cb0e24/npps4/system/live.py#L372
func (ss *Session) RegisterLiveInProgress(deckID int) {
if ss.UserEng == nil {
return
}
var err error
has, progress := ss.GetLiveInProgress()
if has {
@@ -45,12 +53,39 @@ func (ss *Session) RegisterLiveInProgress(deckID int) {
// https://github.com/YumeMichi/honoka-chan/blob/a749efad9fd0789668dedcb59948248da369d32c/handler/live.go#L554
// https://github.com/DarkEnergyProcessor/NPPS4/blob/29aaba6e7a3b4b80d414e58f4b511a9627cb0e24/npps4/system/live.py#L366
func (ss *Session) ClearLiveInProgress() {
if ss.UserEng == nil {
return
}
_, err := ss.UserEng.Table(new(usermodel.UserLiveInProgress)).Where("user_id = ?", ss.UserID).Delete()
if ss.CheckErr(err) {
return
}
}
func (ss *Session) GetActiveRandomLiveByDifficulty(liveDifficultyID int) (bool, *usermodel.UserLiveRandom, error) {
randomLive := usermodel.UserLiveRandom{}
has, err := ss.UserEng.Table(new(usermodel.UserLiveRandom)).
Where("user_id = ? AND live_difficulty_id = ? AND in_progress = ?", ss.UserID, liveDifficultyID, true).
Get(&randomLive)
if err != nil {
return false, nil, err
}
return has, &randomLive, nil
}
func (ss *Session) ResetRandomLiveInProgress() error {
if ss.UserEng == nil {
return nil
}
_, err := ss.UserEng.Table(new(usermodel.UserLiveRandom)).
Where("user_id = ? AND in_progress = ?", ss.UserID, true).
Cols("in_progress").
Update(&usermodel.UserLiveRandom{InProgress: false})
return err
}
func (ss *Session) GetLiveInfo(LiveDifficultyID int) (bool, *liveschema.LiveInfo) {
var info struct {
LiveDifficultyID int `xorm:"live_difficulty_id"`