1
0
mirror of https://github.com/Eyre-S/sekai-scores.git synced 2025-02-12 18:59:55 +08:00

Compare commits

...

3 Commits

Author SHA1 Message Date
079da346b0
add "id" field to Song and Difficulty
- add "id" field to Song, means the song id in game and wiki.
- add "id" field to Difficulty, it is a String of EASY/EXPERT etc.
- changes the parseJSONString implementation
- add song 夜に駆ける, complete the group SekaiSpecial
2022-11-21 17:04:20 +08:00
3032af55e5
implement toString to serialize to JSON format, add "id" field for SongUnit 2022-11-21 16:26:17 +08:00
28ff69ceb8
add playtime field to UserScore 2022-11-21 15:06:08 +08:00
15 changed files with 279 additions and 72 deletions

View File

@ -19,6 +19,8 @@ dependencies {
testImplementation "org.junit.jupiter:junit-jupiter-api:${lib_junit_v}"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${lib_junit_v}"
testImplementation project(":sekai-scores-db")
}
final JavaVersion proj_java = JavaVersion.VERSION_17

View File

@ -1,7 +1,7 @@
## Project Configurations
# Proj Metadata
projVersion = 0.2
projVersion = 0.4
# Dependencies

View File

@ -1,10 +1,11 @@
import java.nio.charset.Charset
import java.nio.charset.StandardCharsets
plugins {
id 'java'
id 'java-library'
}
group 'cc.sukazyo'
version moduleVersion
repositories {
mavenCentral()
}
@ -18,6 +19,31 @@ dependencies {
}
final JavaVersion proj_java = JavaVersion.VERSION_17
final Charset proj_source_encoding = StandardCharsets.UTF_8
group 'cc.sukazyo'
version moduleVersion
test {
useJUnitPlatform()
}
}
java {
sourceCompatibility proj_java
targetCompatibility proj_java
withSourcesJar()
}
tasks.withType(JavaCompile) {
options.encoding = proj_source_encoding.name()
}
tasks.withType(Javadoc) {
options.encoding = proj_source_encoding.name()
options.docEncoding = proj_source_encoding.name()
options.charSet = proj_source_encoding.name()
}

View File

@ -1,4 +1,4 @@
## Project Configurations
# Proj Metadata
moduleVersion = 0.1
moduleVersion = 0.2

View File

@ -5,36 +5,41 @@ import cc.sukazyo.sekai_scores.DifficultiesSekai;
import cc.sukazyo.sekai_scores.Song;
import cc.sukazyo.sekai_scores.SongUnit;
import static cc.sukazyo.sekai_scores.DifficultiesSekai.*;
public class Nightcord25ji {
/** <a href="https://www.sekaipedia.org/wiki/Keitai_Renwa">...</a> */
public static final Song Keitai_Renwa = new Song(
"携帯恋話", SongUnit.NIGHTCORD_25JI,
61, "携帯恋話", SongUnit.NIGHTCORD_25JI,
new DifficultiesSekai(
new Difficulty( 8, 204),
new Difficulty(12, 361),
new Difficulty(18, 651),
new Difficulty(25, 981),
new Difficulty(29, 1131)
new Difficulty( EASY_NAME, 8, 204),
new Difficulty(NORMAL_NAME, 12, 361),
new Difficulty( HARD_NAME, 18, 651),
new Difficulty(EXPERT_NAME, 25, 981),
new Difficulty(MASTER_NAME, 29, 1131)
)
);
/** <a href="https://www.sekaipedia.org/wiki/Kuyamu_to_Kaite_Mirai">...</a> */
public static final Song Kuyamu_to_Kaite_Mirai = new Song(
"悔やむと書いてミライ", SongUnit.NIGHTCORD_25JI,
60, "悔やむと書いてミライ", SongUnit.NIGHTCORD_25JI,
new DifficultiesSekai(
new Difficulty( 8, 190),
new Difficulty(13, 440),
new Difficulty(17, 541),
new Difficulty(26, 815),
new Difficulty(30, 973)
new Difficulty( EASY_NAME, 8, 190),
new Difficulty(NORMAL_NAME,13, 440),
new Difficulty( HARD_NAME,17, 541),
new Difficulty(EXPERT_NAME,26, 815),
new Difficulty(MASTER_NAME,30, 973)
)
);
/** <a href="https://www.sekaipedia.org/wiki/ID_Smile">...</a> */
public static final Song ID_SMILE = new Song(
"アイディスマイル", SongUnit.NIGHTCORD_25JI,
116, "アイディスマイル", SongUnit.NIGHTCORD_25JI,
new DifficultiesSekai(
new Difficulty( 7, 263),
new Difficulty(12, 439),
new Difficulty(17, 703),
new Difficulty(25, 985),
new Difficulty(28, 1247)
new Difficulty( EASY_NAME, 7, 263),
new Difficulty(NORMAL_NAME,12, 439),
new Difficulty( HARD_NAME,17, 703),
new Difficulty(EXPERT_NAME,25, 985),
new Difficulty(MASTER_NAME,28, 1247)
)
);

View File

@ -5,26 +5,31 @@ import cc.sukazyo.sekai_scores.DifficultiesSekai;
import cc.sukazyo.sekai_scores.Song;
import cc.sukazyo.sekai_scores.SongUnit;
import static cc.sukazyo.sekai_scores.DifficultiesSekai.*;
public class Other {
/** <a href="https://www.sekaipedia.org/wiki/Don%27t_Fight_The_Music">...</a> */
public static final Song Dont_Fight_the_Music = new Song(
"Don't Fight The Music", SongUnit.OTHER,
164, "Don't Fight The Music", SongUnit.OTHER,
new DifficultiesSekai(
new Difficulty( 9, 520),
new Difficulty(15, 701),
new Difficulty(23, 1175),
new Difficulty(30, 1545),
new Difficulty(36, 1888)
new Difficulty( EASY_NAME, 9, 520),
new Difficulty(NORMAL_NAME,15, 701),
new Difficulty( HARD_NAME,23, 1175),
new Difficulty(EXPERT_NAME,30, 1545),
new Difficulty(MASTER_NAME,36, 1888)
)
);
/** <a href="https://www.sekaipedia.org/wiki/Tokugawa_Cup_Noodle_Kinshirei">...</a> */
public static final Song Tokugawa_Kappu_Nuudoru_Kinshirei = new Song(
"徳川カップヌードル禁止令", SongUnit.OTHER,
234, "徳川カップヌードル禁止令", SongUnit.OTHER,
new DifficultiesSekai(
new Difficulty( 8, 264),
new Difficulty(13, 498),
new Difficulty(19, 758),
new Difficulty(27, 1065),
new Difficulty(31, 1241)
new Difficulty( EASY_NAME, 8, 264),
new Difficulty(NORMAL_NAME,13, 498),
new Difficulty( HARD_NAME,19, 758),
new Difficulty(EXPERT_NAME,27, 1065),
new Difficulty(MASTER_NAME,31, 1241)
)
);

View File

@ -5,26 +5,41 @@ import cc.sukazyo.sekai_scores.DifficultiesSekai;
import cc.sukazyo.sekai_scores.Song;
import cc.sukazyo.sekai_scores.SongUnit;
import static cc.sukazyo.sekai_scores.DifficultiesSekai.*;
public class SekaiSpecial {
public static final Song Gunjou_Sanka = new Song(
"群青讃歌", SongUnit.SP,
/** <a href="https://www.sekaipedia.org/wiki/Yoru_ni_Kakeru">...</a> */
public static final Song Yoru_ni_Kakeru = new Song(
139, "夜に駆ける", SongUnit.SP,
new DifficultiesSekai(
new Difficulty( 7, 199),
new Difficulty(13, 344),
new Difficulty(17, 475),
new Difficulty(24, 711),
new Difficulty(27, 833)
new Difficulty( EASY_NAME, 6, 182),
new Difficulty(NORMAL_NAME,11, 357),
new Difficulty( HARD_NAME,18, 594),
new Difficulty(EXPERT_NAME,25, 932),
new Difficulty(MASTER_NAME,29, 1140)
)
);
public static final Song Journey = new Song(
"Journey", SongUnit.SP,
/** <a href="https://www.sekaipedia.org/wiki/Gunjou_Sanka">...</a> */
public static final Song Gunjou_Sanka = new Song(
141, "群青讃歌", SongUnit.SP,
new DifficultiesSekai(
new Difficulty( 6, 199),
new Difficulty(12, 512),
new Difficulty(18, 922),
new Difficulty(25, 1285),
new Difficulty(28, 1322)
new Difficulty( EASY_NAME, 7, 199),
new Difficulty(NORMAL_NAME,13, 344),
new Difficulty( HARD_NAME,17, 475),
new Difficulty(EXPERT_NAME,24, 711),
new Difficulty(MASTER_NAME,27, 833)
)
);
/** <a href="https://www.sekaipedia.org/wiki/Journey">...</a> */
public static final Song Journey = new Song(
235, "Journey", SongUnit.SP,
new DifficultiesSekai(
new Difficulty( EASY_NAME, 6, 199),
new Difficulty(NORMAL_NAME,12, 512),
new Difficulty( HARD_NAME,18, 922),
new Difficulty(EXPERT_NAME,25, 1285),
new Difficulty(MASTER_NAME,28, 1322)
)
);

View File

@ -1,10 +1,10 @@
package cc.sukazyo.sekai_scores;
import javax.annotation.Nonnull;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public interface Difficulties {
void forEach(@Nonnull BiConsumer<String, Difficulty> action);
void forEach(@Nonnull Consumer<Difficulty> action);
}

View File

@ -1,7 +1,7 @@
package cc.sukazyo.sekai_scores;
import javax.annotation.Nonnull;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public record DifficultiesSekai(
@Nonnull Difficulty easy,
@ -18,12 +18,21 @@ public record DifficultiesSekai(
public static final String MASTER_NAME = "MASTER";
@Override
public void forEach (@Nonnull BiConsumer<String, Difficulty> action) {
action.accept(EASY_NAME, easy);
action.accept(NORMAL_NAME, normal);
action.accept(HARD_NAME, hard);
action.accept(EXPERT_NAME, expert);
action.accept(MASTER_NAME, master);
public void forEach (@Nonnull Consumer<Difficulty> action) {
action.accept(easy);
action.accept(normal);
action.accept(hard);
action.accept(expert);
action.accept(master);
}
@Override
@Nonnull
public String toString() {
return String.format(
"[%s,%s,%s,%s,%s]",
easy,normal,hard,expert,master
);
}
}

View File

@ -1,8 +1,53 @@
package cc.sukazyo.sekai_scores;
import cc.sukazyo.sekai_scores.util.Converter;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
public record Difficulty(
@Nonnegative String id,
@Nonnegative int level,
@Nonnegative int noteCount
) {}
) {
/**
* @since 0.4
*/
@Nonnull public String id () { return id; }
/**
* The difficulty number of this difficulty map.
* <p>
* it is a number in range 1-36 in official prsk game.
* @since 0.2
*/
@Nonnegative public int level () { return level; }
/**
* an alias of {@link #level} field.
* @since 0.3
* @see #level()
*/
@Nonnegative public int difficulty () { return level(); }
/**
* The total note count in this difficulty map.
* @since 0.2
*/
@Nonnegative public int noteCount () { return noteCount; }
@Override
@Nonnull
public String toString() {
return String.format("{%s}", toStringSimple());
}
@Nonnull
public String toStringSimple () {
return String.format(
"\"id\":%s,\"difficulty\":%d,\"notes\":%d",
Converter.parseJSONString(id), level, noteCount
);
}
}

View File

@ -2,6 +2,7 @@ package cc.sukazyo.sekai_scores;
import javax.annotation.CheckForSigned;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
/**
* @see ScoreBase
@ -182,4 +183,17 @@ public class ScoreBaseData {
return combo;
}
@Override
@Nonnull
public String toString() {
return String.format(
"{\"perfect\":%d,\"great\":%d,\"good\":%d,\"bad\":%d,\"miss\":%d,\"judge\":{\"fast\":%s,\"slow\":%s,\"flick\":%s},\"combo\":%s}",
notePerfect, noteGreat, noteGood, noteBad, noteMiss,
judgeFast==NULL ? "null" : judgeFast,
judgeSlow==NULL ? "null" : judgeFast,
judgeFlick==NULL ? "null" : judgeFast,
combo==NULL ? "null" : combo
);
}
}

View File

@ -1,9 +1,26 @@
package cc.sukazyo.sekai_scores;
import cc.sukazyo.sekai_scores.util.Converter;
import javax.annotation.Nonnull;
public record Song(
int id,
@Nonnull String name,
@Nonnull SongUnit unit,
@Nonnull Difficulties difficulties
) {}
) {
@Override
@Nonnull
public String toString () {
return String.format(
"{\"id\":%d,\"name\":%s,\"unit\":%s,\"difficulties\":%s}",
id,
Converter.parseJSONString(name),
unit,
difficulties
);
}
}

View File

@ -1,23 +1,64 @@
package cc.sukazyo.sekai_scores;
import cc.sukazyo.sekai_scores.util.Converter;
import javax.annotation.Nonnull;
public enum SongUnit {
VSINGER("VIRTUAL SINGER"),
LEO_NEED("Leo/need"),
MORE_MORE_JUMP("MORE MORE JUMP!"),
VIVID_BAD_SQUAD("Vivid BAD SQUAD"),
WONDERLANDS_SHOWTIME("ワンダーランズ×ショウタイム"),
NIGHTCORD_25JI("25時、ナイトコードで。"),
OTHER("other"),
SP("セカイ")
VSINGER(0, "VIRTUAL SINGER"),
LEO_NEED(1, "Leo/need"),
MORE_MORE_JUMP(2, "MORE MORE JUMP!"),
VIVID_BAD_SQUAD(3, "Vivid BAD SQUAD"),
WONDERLANDS_SHOWTIME(4, "ワンダーランズ×ショウタイム"),
NIGHTCORD_25JI(5, "25時、ナイトコードで。"),
/**
* Just the "other" unit in game.
* @since 0.2
*/
OTHER(-1, "other"),
/**
* It collects that songs belongs to multiple units.
* <p>
* Like "Journey", "群青讃歌", it belongs to all of those units exists in game,
* and hard to assign those songs to those units exists. So this group was created,
* means the song belongs to "the whole セカイ".
* <p>
* This unit/group doesn't exist in the game.
* @since 0.2
*/
SP(-2, "セカイ")
;
/**
* An id of this group/unit.
* <p>
* The value start at 0 for {@link #VSINGER}
* and increment according to the order of the groups/units in the game.
* <p>
* for some special group/unit, it has a special id:
* <ul>
* <li>{@link #OTHER}: {@link -1}, as a special group that even exists in game</li>
* <li>{@link #SP}: {@link -2}, as a group that doesn't exist in game</li>
* </ul>
* @since 0.3
*/
public final int id;
@Nonnull public final String name;
SongUnit (@Nonnull String name) {
SongUnit (int id, @Nonnull String name) {
this.id = id;
this.name = name;
}
@Override
@Nonnull
public String toString() {
return String.format(
"{\"id\":%d,\"fullname\":%s}",
id,
Converter.parseJSONString(name)
);
}
}

View File

@ -1,9 +1,23 @@
package cc.sukazyo.sekai_scores;
import javax.annotation.Nonnull;
import java.time.ZonedDateTime;
public record UserScore (
@Nonnull Song song,
@Nonnull Difficulty difficulty,
@Nonnull ScoreBase score
) {}
@Nonnull ScoreBase score,
@Nonnull ZonedDateTime playtime
) {
@Override
@Nonnull
public String toString () {
return String.format(
"{\"song\":%s,\"difficulty\":%s,\"score\":%s,\"playtime\":%d}",
song, difficulty, score,
playtime.toInstant().toEpochMilli()
);
}
}

View File

@ -0,0 +1,14 @@
package cc.sukazyo.sekai_scores.util;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class Converter {
@Nonnull
public static String parseJSONString (@Nullable String input) {
if (input == null) return "null";
return "\"" + input.replaceAll("\\\\", "\\\\\\\\").replaceAll("\"", "\\\\\"") + "\"";
}
}