mirror of
https://github.com/Eyre-S/sekai-scores.git
synced 2024-11-24 20:17:40 +08:00
add a CLI program, which can read config, simple parse and echo a basic score
- CLI add config read, from $HOME/.config/sekai-scores/sekai-scores.properties. - now it can read a pjsekai user id, and the sekai-scores database config - add a command `add` - it now can parse 9 params from args, or let user input them in cli, to build a basic score - it can echo the score, which looks just like the result score screen in game - now the sekai-cli build script supports 'application' implementation, and supports UTF-8 and uses spotbugs-annotations.
This commit is contained in:
parent
079da346b0
commit
e6cbab2d3c
@ -1,16 +1,19 @@
|
|||||||
|
import java.nio.charset.Charset
|
||||||
|
import java.nio.charset.StandardCharsets
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id 'java'
|
id 'java'
|
||||||
|
id 'application'
|
||||||
}
|
}
|
||||||
|
|
||||||
group 'cc.sukazyo'
|
|
||||||
version projVersion
|
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
|
compileOnly "com.github.spotbugs:spotbugs-annotations:${lib_spotbugs_v}"
|
||||||
|
|
||||||
implementation rootProject
|
implementation rootProject
|
||||||
|
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-api:${lib_junit_v}"
|
testImplementation "org.junit.jupiter:junit-jupiter-api:${lib_junit_v}"
|
||||||
@ -18,6 +21,35 @@ dependencies {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final JavaVersion proj_java = JavaVersion.VERSION_17
|
||||||
|
final Charset proj_source_encoding = StandardCharsets.UTF_8
|
||||||
|
|
||||||
|
group 'cc.sukazyo'
|
||||||
|
version moduleVersion
|
||||||
|
|
||||||
|
application {
|
||||||
|
mainClass = "${group}.sekai_cli.ClientMain"
|
||||||
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
useJUnitPlatform()
|
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()
|
||||||
|
}
|
||||||
|
4
sekai-cli/gradle.properties
Normal file
4
sekai-cli/gradle.properties
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
## Project Configurations
|
||||||
|
|
||||||
|
# Proj Metadata
|
||||||
|
moduleVersion = 0.5
|
28
sekai-cli/src/main/java/cc/sukazyo/sekai_cli/ClientMain.java
Normal file
28
sekai-cli/src/main/java/cc/sukazyo/sekai_cli/ClientMain.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package cc.sukazyo.sekai_cli;
|
||||||
|
|
||||||
|
import cc.sukazyo.sekai_cli.client.AddScore;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class ClientMain {
|
||||||
|
|
||||||
|
public static final Config config = Config.loadUserConfig();
|
||||||
|
|
||||||
|
public static void main (String[] args) {
|
||||||
|
|
||||||
|
if (args.length > 0) {
|
||||||
|
if (args[0].equals("add")) {
|
||||||
|
AddScore.main(Arrays.copyOfRange(args, 1, args.length));
|
||||||
|
$done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("Unknown function call.\n please check your program param.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void $done () {
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
74
sekai-cli/src/main/java/cc/sukazyo/sekai_cli/Config.java
Normal file
74
sekai-cli/src/main/java/cc/sukazyo/sekai_cli/Config.java
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
package cc.sukazyo.sekai_cli;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import static cc.sukazyo.sekai_cli.Log._debug;
|
||||||
|
|
||||||
|
public class Config {
|
||||||
|
|
||||||
|
private static final String CONFIG_ROOT_NAME = "sekai-scores";
|
||||||
|
private static final String CONFIG_FILE = CONFIG_ROOT_NAME + ".properties";
|
||||||
|
|
||||||
|
public final long sekai_id;
|
||||||
|
@Nonnull public final String db_host;
|
||||||
|
@Nonnull public final String db_name;
|
||||||
|
@Nonnull public final String db_auth_user;
|
||||||
|
@Nonnull public final String db_auth_pwd;
|
||||||
|
@Nullable public final String db_prefix;
|
||||||
|
|
||||||
|
private Config (Properties props) {
|
||||||
|
// user config field
|
||||||
|
this.sekai_id = Long.parseLong(props.getProperty("user.sekai-id"));
|
||||||
|
_debug("config field user.sekai-id set: " + this.sekai_id);
|
||||||
|
this.db_host = getNonnull(props, "db.server");
|
||||||
|
_debug("config field db.server set: " + this.db_host);
|
||||||
|
this.db_name = getNonnull(props, "db.database");
|
||||||
|
_debug("config field db.database set: " + this.db_name);
|
||||||
|
this.db_auth_user = getNonnull(props, "db.auth.user");
|
||||||
|
_debug("config field db.auth.user set: " + this.db_auth_user);
|
||||||
|
this.db_auth_pwd = getNonnull(props, "db.auth.password");
|
||||||
|
_debug("config field db.auth.password set.");
|
||||||
|
this.db_prefix = props.getProperty("db.table-prefix");
|
||||||
|
_debug(this.db_prefix == null ? "config field db.prefix unset." : "config field db.table-prefix set: " + this.db_prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
private static String getNonnull (Properties props, String key) {
|
||||||
|
final String v = props.getProperty(key);
|
||||||
|
if (v == null) throw new NullPointerException("null at key " + key);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Config loadUserConfig() {
|
||||||
|
try {
|
||||||
|
|
||||||
|
final Properties props = new Properties();
|
||||||
|
final File propFile = Paths.get(getAppConfigPath(getSysUserConfigRoot()).toString(), CONFIG_FILE).toFile();
|
||||||
|
props.load(new FileInputStream(propFile));
|
||||||
|
_debug("loaded config file: " + propFile.getAbsolutePath());
|
||||||
|
|
||||||
|
return new Config(props);
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("error while load user config", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Path getAppConfigPath(Path configRoot) {
|
||||||
|
return Paths.get(configRoot.toString(), CONFIG_ROOT_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Path getSysUserConfigRoot () {
|
||||||
|
final Path userhome = Paths.get(System.getProperty("user.home"), ".config");
|
||||||
|
_debug("read config from user home : " + userhome.toAbsolutePath());
|
||||||
|
return userhome;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
16
sekai-cli/src/main/java/cc/sukazyo/sekai_cli/Log.java
Normal file
16
sekai-cli/src/main/java/cc/sukazyo/sekai_cli/Log.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package cc.sukazyo.sekai_cli;
|
||||||
|
|
||||||
|
public class Log {
|
||||||
|
|
||||||
|
private static final boolean IS_DEBUG = true;
|
||||||
|
|
||||||
|
public static void _debug (String m) {
|
||||||
|
if (!isDebug()) return;
|
||||||
|
m = "[DEBUG]" + m;
|
||||||
|
m = m.replaceAll("\\n", "'''''''");
|
||||||
|
System.out.println(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isDebug () { return IS_DEBUG; }
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
package cc.sukazyo.sekai_cli.client;
|
||||||
|
|
||||||
|
import cc.sukazyo.sekai_scores.ScoreBase;
|
||||||
|
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.util.InputMismatchException;
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
import static cc.sukazyo.sekai_cli.Log._debug;
|
||||||
|
|
||||||
|
public class AddScore {
|
||||||
|
|
||||||
|
public static void main (String[] args) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
final int[] scores = new int[9];
|
||||||
|
|
||||||
|
if (args.length == 0) {
|
||||||
|
System.out.println("Input your score,");
|
||||||
|
System.out.println(" score formatting: perfect ... miss late fast flick combo");
|
||||||
|
System.out.print("> ");
|
||||||
|
Scanner input = new Scanner(System.in);
|
||||||
|
for (int i = 0; i < 9; i++) {
|
||||||
|
scores[i] = input.nextInt();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < 9; i++) {
|
||||||
|
scores[i] = Integer.parseInt(args[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i : scores) {
|
||||||
|
if (i < 0 || i > 9999) throw new InputMismatchException(String.format("input %d out of range of [0, 9999]", i));
|
||||||
|
}
|
||||||
|
|
||||||
|
ScoreBase scoreBase = new ScoreBase(
|
||||||
|
scores[0], scores[1], scores[2], scores[3], scores[4],
|
||||||
|
scores[6], scores[5], scores[7], scores[8]
|
||||||
|
);
|
||||||
|
|
||||||
|
System.out.println(PrintScore.printTableScoreBase(scoreBase));
|
||||||
|
|
||||||
|
} catch (ArrayIndexOutOfBoundsException | NumberFormatException e) {
|
||||||
|
System.out.println("unsupported yet.");
|
||||||
|
final StringWriter sw = new StringWriter();
|
||||||
|
e.printStackTrace(new PrintWriter(sw));
|
||||||
|
_debug(sw.toString());
|
||||||
|
} catch (InputMismatchException e) {
|
||||||
|
System.out.println("unavailable input: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package cc.sukazyo.sekai_cli.client;
|
||||||
|
|
||||||
|
import cc.sukazyo.sekai_scores.ScoreBase;
|
||||||
|
|
||||||
|
public class PrintScore {
|
||||||
|
|
||||||
|
public static final String MESSAGE_AP = "ALL PERFECT!";
|
||||||
|
public static final String MESSAGE_FC = "FULL COMBO!";
|
||||||
|
|
||||||
|
public static String getMessageQuote(String message) {
|
||||||
|
return "\\ " + message + " /";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String printTableScoreBase (ScoreBase score) {
|
||||||
|
return String.format("""
|
||||||
|
COMBO %16s
|
||||||
|
╭────────────────────┬─────────────────┬───────────────╮
|
||||||
|
│ │ PERFECT %4d │ │
|
||||||
|
│ │ GREAT %4d │ LATE FAST │
|
||||||
|
│ %-4d │ GOOD %4d │ [%-4d %4d] │
|
||||||
|
│ │ BAD %4d │ FLICK %4d │
|
||||||
|
│ │ MISS %4d │ │
|
||||||
|
╰────────────────────┴─────────────────┴───────────────╯
|
||||||
|
""",
|
||||||
|
score.noteCount() == score.combo() ? getMessageQuote((score.noteCount()==score.perfect()?MESSAGE_AP : MESSAGE_FC)) : "",
|
||||||
|
score.perfect(),
|
||||||
|
score.great(),
|
||||||
|
score.combo(), score.good(), score.slow(), score.fast(),
|
||||||
|
score.bad(), score.flick(),
|
||||||
|
score.miss()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user