How score = false works in beatoraja

未分类
4.2k 词

How score = false works in beatoraja

The code is based on lr2oraja endlessdream actually. There’re some additional notes about the design of freq mod in ed. Corresponding commit is fd76779133b425d8e18703e5f67ec94ff0e84b33

Preface

This is a note about how raja stores player’s scores. There’re some situations that raja doesn’t “want to” save a score, for example, if you’re using the expand judge feature and having easier judge timing, your score won’t be saved and be sent to IR service.

There’s a similar use cause in ED: Tachi IR specifically refused to receive any score with FREQ mod enabled. We’ll discuss the history of how ED implemented it, why there’re bugs, current situations later.

Score = false

Raja would set score to false if it doesn’t want to save next score. Example:

1
2
3
4
5
6
if (config.isCustomJudge() &&
(config.getKeyJudgeWindowRatePerfectGreat() > 100 || config.getKeyJudgeWindowRateGreat() > 100 || config.getKeyJudgeWindowRateGood() > 100
|| config.getScratchJudgeWindowRatePerfectGreat() > 100 || config.getScratchJudgeWindowRateGreat() > 100 || config.getScratchJudgeWindowRateGood() > 100)) {
assist = Math.max(assist, 2);
score = false;
}

And score flag is persisted on BMSResource by resource.setUpdateScore(score). Therefore, we can see the usage of bms.player.beatoraja.PlayerResource#isUpdateScore to find where this flag is being used. And we can find the only usage that is related to score storage is here:

1
2
3
4
5
6
7
8
9
10
if (isFreqTrainerEnabled()) {
resource.getScoreData().setClear(NoPlay.id);
}

if (resource.getPlayMode().mode == BMSPlayerMode.Mode.PLAY && !(isFreqTrainerEnabled() && isFreqNegative())) {
main.getPlayDataAccessor().writeScoreData(resource.getScoreData(), resource.getBMSModel(),
resource.getPlayerConfig().getLnmode(), resource.isUpdateScore());
} else {
Logger.getGlobal().info("プレイモードが" + resource.getPlayMode().mode.name() + "のため、スコア登録はされません");
}

writeScoreData

As the javadoc written, when flag updateScore is false, only playcount would be updated. Following the logic we can find the place that truly makes a difference is bms.player.beatoraja.ScoreData#update(bms.player.beatoraja.ScoreData, boolean). It compares the old score and the new one, and only updates the old score itself when there’s a difference and updateScore is true. However, there’re some exceptions:

1
2
3
4
5
6
if (clear < newscore.getClear()) {
setClear(newscore.getClear());
setOption(newscore.getOption());
setSeed(newscore.getSeed());
update = true;
}

This part isn’t required updateScore to be true. So by using the score = false doesn’t prevent raja stores a higher lamp score. This is the reason why expand judge feature is using the assist flag and score at the same time: to prevent storing a higher lamp.

A common assumption among developers that haven’t looked into the code might have is that the score flag is working as preventing stroing the score in database. But it’s actually not, it’s working by not updating part of the fields on old score (yeah, even not all fields from ScoreData but part of it). The database insert line is always called no matter what.

Endless Dream

Currently, a score with freq enabled would be saved in local if the freq rate is positive(i.e. the chart is speeding up) and cannot be sent to IR service.

  • If the freq mod is enabled and with a negative rate, the whole process is being skipped. However, this design introduced a bug (see #45) because you can disable the rate mod at the middle of play. And it’s fixed in #71 by persisting the value in BMSResource rather than accessing the fields from the FreqTrainerMenu directly.

  • If the freq mod is enabled with a positive rate, the score would be updated except the lamp value since it’s set to NO_PLAY forcefully.

  • For the IR service part, it’s achieved by preventing the IR send process happening, see the core/src/bms/player/beatoraja/result/MusicResult.java changes in #71.

However, as you can see we actually don’t have a simple flag that forbids sending scores to IR, I introduced one in #126. It has a small overlap with the changes introduced in #71. So maybe we should remove the changes in #71 in the near future.

The overlap

Arised in #142. Both !score and forceNoIRSend is preventing a score being sent to IR service. There’s a possibility that they’re both notified, for example, playing with freq enabled and a special random mod.

Here’s a small table illustrates the mod and consequences:

mod assist local score IR lamp
expand judge(easier timing) yes no no assist clear
expand judge(stricter timing) no yes yes play result
custom judge(easier timing) yes no no assist clear
expand judge(stricter timing) no yes yes play result
negative freq no skipped no no update
positive freq no yes no no update