• R/O
  • HTTP
  • SSH
  • HTTPS

DelesteRandomSelector: Commit

開発Git


Commit MetaInfo

Revisiondd42ddc75597f5a15dc7eddb4ee7db11601a8db7 (tree)
Time2022-03-10 13:20:01
Authorhizumiaoba <56146205+hizumiaoba@user...>
CommiterGitHub

Log Message

Merge pull request #50 from hizumiaoba/release/v4.0.0-Beta

Release/v4.0.0 beta

Change Summary

Incremental Difference

--- /dev/null
+++ b/Crash-Report/2022-03-09-18-22-28.txt
@@ -0,0 +1,53 @@
1+---- DelesteRandomSelector Crash Report ----
2+// I may be so bad to code?
3+
4+
5+Time: 22/03/09 18:22
6+Description: Unexpected Error
7+
8+
9+These are simplified stack trace. (shown up to 5 lines. Full Stack trace is below.)
10+java.lang.IllegalStateException: java.util.concurrent.CompletionException: java.lang.IllegalArgumentException: Level must not negative.
11+ at com.ranfa.main.DelesteRandomSelector.lambda$20(DelesteRandomSelector.java:412)
12+ at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:859)
13+ at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:837)
14+ at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:478)
15+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
16+
17+
18+A detailed walkthrough of the error, its code path and all known details is as follows:
19+---------------------------------------------------------------------------------------
20+
21+
22+Stacktrace:
23+ at com.ranfa.main.DelesteRandomSelector.lambda$20(DelesteRandomSelector.java:412)
24+ at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:859)
25+ at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:837)
26+ at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:478)
27+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
28+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
29+ at java.base/java.lang.Thread.run(Thread.java:829)
30+Caused by: java.util.concurrent.CompletionException: java.lang.IllegalArgumentException: Level must not negative.
31+ at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:314)
32+ at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:319)
33+ at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1739)
34+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
35+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
36+ at java.base/java.lang.Thread.run(Thread.java:829)
37+Caused by: java.lang.IllegalArgumentException: Level must not negative.
38+ at com.ranfa.lib.database.Scraping.getSpecificLevelSongs(Scraping.java:176)
39+ at com.ranfa.main.DelesteRandomSelector.lambda$19(DelesteRandomSelector.java:399)
40+ at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1736)
41+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
42+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
43+ at java.base/java.lang.Thread.run(Thread.java:829)
44+
45+
46+-- System Details --
47+Details:
48+ DelesteRandomSelector Version: v3.1.0
49+ Operating System: Windows 10 (amd64) version 10.0
50+ Java Version: 11, Eclipse Adoptium
51+ Java VM Version: OpenJDK 64-Bit Server VM, version 11.0.13+8
52+ Memory: 84176784 bytes / 268435456 bytes up to 4273995776 bytes
53+ JVM Flags: 1 total: [-Dfile.encoding=UTF-8]
--- /dev/null
+++ b/Crash-Report/2022-03-09-19-00-42.txt
@@ -0,0 +1,52 @@
1+---- DelesteRandomSelector Crash Report ----
2+// These Easter sentences were inspired by Minecraft Crash Report!
3+
4+
5+Time: 22/03/09 19:00
6+Description: Unexpected Error
7+
8+
9+These are simplified stack trace. (shown up to 5 lines. Full Stack trace is below.)
10+java.lang.IllegalStateException: java.util.concurrent.CompletionException: java.lang.NullPointerException
11+ at com.ranfa.main.DelesteRandomSelector.lambda$37(DelesteRandomSelector.java:629)
12+ at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:859)
13+ at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:837)
14+ at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:478)
15+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
16+
17+
18+A detailed walkthrough of the error, its code path and all known details is as follows:
19+---------------------------------------------------------------------------------------
20+
21+
22+Stacktrace:
23+ at com.ranfa.main.DelesteRandomSelector.lambda$37(DelesteRandomSelector.java:629)
24+ at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:859)
25+ at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:837)
26+ at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:478)
27+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
28+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
29+ at java.base/java.lang.Thread.run(Thread.java:829)
30+Caused by: java.util.concurrent.CompletionException: java.lang.NullPointerException
31+ at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:314)
32+ at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:319)
33+ at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1739)
34+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
35+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
36+ at java.base/java.lang.Thread.run(Thread.java:829)
37+Caused by: java.lang.NullPointerException
38+ at com.ranfa.main.DelesteRandomSelector.lambda$36(DelesteRandomSelector.java:600)
39+ at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1736)
40+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
41+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
42+ at java.base/java.lang.Thread.run(Thread.java:829)
43+
44+
45+-- System Details --
46+Details:
47+ DelesteRandomSelector Version: v3.1.0
48+ Operating System: Windows 10 (amd64) version 10.0
49+ Java Version: 11, Eclipse Adoptium
50+ Java VM Version: OpenJDK 64-Bit Server VM, version 11.0.13+8
51+ Memory: 53935864 bytes / 268435456 bytes up to 4273995776 bytes
52+ JVM Flags: 1 total: [-Dfile.encoding=UTF-8]
--- /dev/null
+++ b/Crash-Report/2022-03-09-19-03-41.txt
@@ -0,0 +1,53 @@
1+---- DelesteRandomSelector Crash Report ----
2+// I may be so bad to code?
3+
4+
5+Time: 22/03/09 19:03
6+Description: Unexpected Error
7+
8+
9+These are simplified stack trace. (shown up to 5 lines. Full Stack trace is below.)
10+java.lang.IllegalStateException: java.util.concurrent.CompletionException: java.lang.IllegalArgumentException: Level must not negative.
11+ at com.ranfa.main.DelesteRandomSelector.lambda$20(DelesteRandomSelector.java:412)
12+ at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:859)
13+ at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:837)
14+ at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:478)
15+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
16+
17+
18+A detailed walkthrough of the error, its code path and all known details is as follows:
19+---------------------------------------------------------------------------------------
20+
21+
22+Stacktrace:
23+ at com.ranfa.main.DelesteRandomSelector.lambda$20(DelesteRandomSelector.java:412)
24+ at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:859)
25+ at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:837)
26+ at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:478)
27+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
28+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
29+ at java.base/java.lang.Thread.run(Thread.java:829)
30+Caused by: java.util.concurrent.CompletionException: java.lang.IllegalArgumentException: Level must not negative.
31+ at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:314)
32+ at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:319)
33+ at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1739)
34+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
35+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
36+ at java.base/java.lang.Thread.run(Thread.java:829)
37+Caused by: java.lang.IllegalArgumentException: Level must not negative.
38+ at com.ranfa.lib.database.Scraping.getSpecificLevelSongs(Scraping.java:176)
39+ at com.ranfa.main.DelesteRandomSelector.lambda$19(DelesteRandomSelector.java:399)
40+ at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1736)
41+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
42+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
43+ at java.base/java.lang.Thread.run(Thread.java:829)
44+
45+
46+-- System Details --
47+Details:
48+ DelesteRandomSelector Version: v3.1.0
49+ Operating System: Windows 10 (amd64) version 10.0
50+ Java Version: 11, Eclipse Adoptium
51+ Java VM Version: OpenJDK 64-Bit Server VM, version 11.0.13+8
52+ Memory: 56076176 bytes / 268435456 bytes up to 4273995776 bytes
53+ JVM Flags: 1 total: [-Dfile.encoding=UTF-8]
--- /dev/null
+++ b/Crash-Report/2022-03-09-19-07-43.txt
@@ -0,0 +1,52 @@
1+---- DelesteRandomSelector Crash Report ----
2+// I may be so bad to code?
3+
4+
5+Time: 22/03/09 19:07
6+Description: Unexpected Error
7+
8+
9+These are simplified stack trace. (shown up to 5 lines. Full Stack trace is below.)
10+java.lang.IllegalStateException: java.util.concurrent.CompletionException: java.lang.NullPointerException
11+ at com.ranfa.main.DelesteRandomSelector.lambda$37(DelesteRandomSelector.java:629)
12+ at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:859)
13+ at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:837)
14+ at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:478)
15+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
16+
17+
18+A detailed walkthrough of the error, its code path and all known details is as follows:
19+---------------------------------------------------------------------------------------
20+
21+
22+Stacktrace:
23+ at com.ranfa.main.DelesteRandomSelector.lambda$37(DelesteRandomSelector.java:629)
24+ at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:859)
25+ at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:837)
26+ at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:478)
27+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
28+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
29+ at java.base/java.lang.Thread.run(Thread.java:829)
30+Caused by: java.util.concurrent.CompletionException: java.lang.NullPointerException
31+ at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:314)
32+ at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:319)
33+ at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1739)
34+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
35+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
36+ at java.base/java.lang.Thread.run(Thread.java:829)
37+Caused by: java.lang.NullPointerException
38+ at com.ranfa.main.DelesteRandomSelector.lambda$36(DelesteRandomSelector.java:600)
39+ at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1736)
40+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
41+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
42+ at java.base/java.lang.Thread.run(Thread.java:829)
43+
44+
45+-- System Details --
46+Details:
47+ DelesteRandomSelector Version: v3.1.0
48+ Operating System: Windows 10 (amd64) version 10.0
49+ Java Version: 11, Eclipse Adoptium
50+ Java VM Version: OpenJDK 64-Bit Server VM, version 11.0.13+8
51+ Memory: 53868088 bytes / 268435456 bytes up to 4273995776 bytes
52+ JVM Flags: 1 total: [-Dfile.encoding=UTF-8]
--- /dev/null
+++ b/Crash-Report/2022-03-09-21-10-51.txt
@@ -0,0 +1,52 @@
1+---- DelesteRandomSelector Crash Report ----
2+// I may be so bad to code?
3+
4+
5+Time: 22/03/09 21:10
6+Description: Unexpected Error
7+
8+
9+These are simplified stack trace. (shown up to 5 lines. Full Stack trace is below.)
10+java.lang.IllegalStateException: java.util.concurrent.CompletionException: java.lang.NullPointerException
11+ at com.ranfa.main.DelesteRandomSelector.lambda$37(DelesteRandomSelector.java:629)
12+ at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:859)
13+ at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:837)
14+ at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:478)
15+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
16+
17+
18+A detailed walkthrough of the error, its code path and all known details is as follows:
19+---------------------------------------------------------------------------------------
20+
21+
22+Stacktrace:
23+ at com.ranfa.main.DelesteRandomSelector.lambda$37(DelesteRandomSelector.java:629)
24+ at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:859)
25+ at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:837)
26+ at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:478)
27+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
28+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
29+ at java.base/java.lang.Thread.run(Thread.java:829)
30+Caused by: java.util.concurrent.CompletionException: java.lang.NullPointerException
31+ at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:314)
32+ at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:319)
33+ at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1739)
34+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
35+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
36+ at java.base/java.lang.Thread.run(Thread.java:829)
37+Caused by: java.lang.NullPointerException
38+ at com.ranfa.main.DelesteRandomSelector.lambda$36(DelesteRandomSelector.java:600)
39+ at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1736)
40+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
41+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
42+ at java.base/java.lang.Thread.run(Thread.java:829)
43+
44+
45+-- System Details --
46+Details:
47+ DelesteRandomSelector Version: v3.1.0
48+ Operating System: Windows 10 (amd64) version 10.0
49+ Java Version: 11, Eclipse Adoptium
50+ Java VM Version: OpenJDK 64-Bit Server VM, version 11.0.13+8
51+ Memory: 39191552 bytes / 268435456 bytes up to 4273995776 bytes
52+ JVM Flags: 1 total: [-Dfile.encoding=UTF-8]
--- /dev/null
+++ b/Crash-Report/2022-03-09-21-12-05.txt
@@ -0,0 +1,53 @@
1+---- DelesteRandomSelector Crash Report ----
2+// I may be so bad to code?
3+
4+
5+Time: 22/03/09 21:12
6+Description: Unexpected Error
7+
8+
9+These are simplified stack trace. (shown up to 5 lines. Full Stack trace is below.)
10+java.lang.IllegalStateException: java.util.concurrent.CompletionException: java.lang.IllegalArgumentException: Illegal boolean value.
11+ at com.ranfa.main.DelesteRandomSelector.lambda$20(DelesteRandomSelector.java:412)
12+ at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:859)
13+ at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:837)
14+ at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:478)
15+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
16+
17+
18+A detailed walkthrough of the error, its code path and all known details is as follows:
19+---------------------------------------------------------------------------------------
20+
21+
22+Stacktrace:
23+ at com.ranfa.main.DelesteRandomSelector.lambda$20(DelesteRandomSelector.java:412)
24+ at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:859)
25+ at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:837)
26+ at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:478)
27+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
28+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
29+ at java.base/java.lang.Thread.run(Thread.java:829)
30+Caused by: java.util.concurrent.CompletionException: java.lang.IllegalArgumentException: Illegal boolean value.
31+ at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:314)
32+ at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:319)
33+ at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1739)
34+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
35+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
36+ at java.base/java.lang.Thread.run(Thread.java:829)
37+Caused by: java.lang.IllegalArgumentException: Illegal boolean value.
38+ at com.ranfa.lib.database.Scraping.getSpecificLevelSongs(Scraping.java:182)
39+ at com.ranfa.main.DelesteRandomSelector.lambda$19(DelesteRandomSelector.java:399)
40+ at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1736)
41+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
42+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
43+ at java.base/java.lang.Thread.run(Thread.java:829)
44+
45+
46+-- System Details --
47+Details:
48+ DelesteRandomSelector Version: v3.1.0
49+ Operating System: Windows 10 (amd64) version 10.0
50+ Java Version: 11, Eclipse Adoptium
51+ Java VM Version: OpenJDK 64-Bit Server VM, version 11.0.13+8
52+ Memory: 63350808 bytes / 268435456 bytes up to 4273995776 bytes
53+ JVM Flags: 1 total: [-Dfile.encoding=UTF-8]
--- /dev/null
+++ b/Crash-Report/2022-03-10-12-33-54.txt
@@ -0,0 +1,52 @@
1+---- DelesteRandomSelector Crash Report ----
2+// Shimamura Uzuki, I'll do my best!
3+
4+
5+Time: 22/03/10 12:33
6+Description: Unexpected Error
7+
8+
9+These are simplified stack trace. (shown up to 5 lines. Full Stack trace is below.)
10+java.lang.IllegalStateException: java.util.concurrent.CompletionException: java.lang.NullPointerException
11+ at com.ranfa.main.DelesteRandomSelector.lambda$37(DelesteRandomSelector.java:629)
12+ at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:859)
13+ at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:837)
14+ at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:478)
15+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
16+
17+
18+A detailed walkthrough of the error, its code path and all known details is as follows:
19+---------------------------------------------------------------------------------------
20+
21+
22+Stacktrace:
23+ at com.ranfa.main.DelesteRandomSelector.lambda$37(DelesteRandomSelector.java:629)
24+ at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:859)
25+ at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:837)
26+ at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:478)
27+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
28+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
29+ at java.base/java.lang.Thread.run(Thread.java:829)
30+Caused by: java.util.concurrent.CompletionException: java.lang.NullPointerException
31+ at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:314)
32+ at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:319)
33+ at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1739)
34+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
35+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
36+ at java.base/java.lang.Thread.run(Thread.java:829)
37+Caused by: java.lang.NullPointerException
38+ at com.ranfa.main.DelesteRandomSelector.lambda$36(DelesteRandomSelector.java:600)
39+ at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1736)
40+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
41+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
42+ at java.base/java.lang.Thread.run(Thread.java:829)
43+
44+
45+-- System Details --
46+Details:
47+ DelesteRandomSelector Version: v3.1.0
48+ Operating System: Windows 10 (amd64) version 10.0
49+ Java Version: 11, Eclipse Adoptium
50+ Java VM Version: OpenJDK 64-Bit Server VM, version 11.0.13+8
51+ Memory: 58056088 bytes / 268435456 bytes up to 4273995776 bytes
52+ JVM Flags: 1 total: [-Dfile.encoding=UTF-8]
--- /dev/null
+++ b/Crash-Report/2022-03-10-12-44-31.txt
@@ -0,0 +1,52 @@
1+---- DelesteRandomSelector Crash Report ----
2+// I... leave all books... behind... 'cause I want to talk... with you...
3+
4+
5+Time: 22/03/10 12:44
6+Description: Unexpected Error
7+
8+
9+These are simplified stack trace. (shown up to 5 lines. Full Stack trace is below.)
10+java.lang.IllegalStateException: java.util.concurrent.CompletionException: java.lang.NullPointerException
11+ at com.ranfa.main.DelesteRandomSelector.lambda$37(DelesteRandomSelector.java:630)
12+ at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:859)
13+ at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:837)
14+ at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:478)
15+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
16+
17+
18+A detailed walkthrough of the error, its code path and all known details is as follows:
19+---------------------------------------------------------------------------------------
20+
21+
22+Stacktrace:
23+ at com.ranfa.main.DelesteRandomSelector.lambda$37(DelesteRandomSelector.java:630)
24+ at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:859)
25+ at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:837)
26+ at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:478)
27+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
28+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
29+ at java.base/java.lang.Thread.run(Thread.java:829)
30+Caused by: java.util.concurrent.CompletionException: java.lang.NullPointerException
31+ at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:314)
32+ at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:319)
33+ at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1739)
34+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
35+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
36+ at java.base/java.lang.Thread.run(Thread.java:829)
37+Caused by: java.lang.NullPointerException
38+ at com.ranfa.main.DelesteRandomSelector.lambda$36(DelesteRandomSelector.java:601)
39+ at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1736)
40+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
41+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
42+ at java.base/java.lang.Thread.run(Thread.java:829)
43+
44+
45+-- System Details --
46+Details:
47+ DelesteRandomSelector Version: v3.1.0-Stable
48+ Operating System: Windows 10 (amd64) version 10.0
49+ Java Version: 11, Eclipse Adoptium
50+ Java VM Version: OpenJDK 64-Bit Server VM, version 11.0.13+8
51+ Memory: 56034960 bytes / 268435456 bytes up to 4273995776 bytes
52+ JVM Flags: 1 total: [-Dfile.encoding=UTF-8]
--- /dev/null
+++ b/Crash-Report/2022-03-10-12-53-51.txt
@@ -0,0 +1,52 @@
1+---- DelesteRandomSelector Crash Report ----
2+// Shimamura Uzuki, I'll do my best!
3+
4+
5+Time: 22/03/10 12:53
6+Description: Unexpected Error
7+
8+
9+These are simplified stack trace. (shown up to 5 lines. Full Stack trace is below.)
10+java.lang.IllegalStateException: java.util.concurrent.CompletionException: java.lang.NullPointerException
11+ at com.ranfa.main.DelesteRandomSelector.lambda$37(DelesteRandomSelector.java:630)
12+ at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:859)
13+ at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:837)
14+ at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:478)
15+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
16+
17+
18+A detailed walkthrough of the error, its code path and all known details is as follows:
19+---------------------------------------------------------------------------------------
20+
21+
22+Stacktrace:
23+ at com.ranfa.main.DelesteRandomSelector.lambda$37(DelesteRandomSelector.java:630)
24+ at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:859)
25+ at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:837)
26+ at java.base/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:478)
27+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
28+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
29+ at java.base/java.lang.Thread.run(Thread.java:829)
30+Caused by: java.util.concurrent.CompletionException: java.lang.NullPointerException
31+ at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:314)
32+ at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:319)
33+ at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1739)
34+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
35+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
36+ at java.base/java.lang.Thread.run(Thread.java:829)
37+Caused by: java.lang.NullPointerException
38+ at com.ranfa.main.DelesteRandomSelector.lambda$36(DelesteRandomSelector.java:601)
39+ at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1736)
40+ at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
41+ at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
42+ at java.base/java.lang.Thread.run(Thread.java:829)
43+
44+
45+-- System Details --
46+Details:
47+ DelesteRandomSelector Version: v4.0.0-Beta
48+ Operating System: Windows 10 (amd64) version 10.0
49+ Java Version: 11, Eclipse Adoptium
50+ Java VM Version: OpenJDK 64-Bit Server VM, version 11.0.13+8
51+ Memory: 29829208 bytes / 268435456 bytes up to 4273995776 bytes
52+ JVM Flags: 3 total: [-agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:62536, -javaagent:D:\pleiades-latest\eclipse\configuration\org.eclipse.osgi\418\0\.cp\lib\javaagent-shaded.jar, -Dfile.encoding=UTF-8]
--- a/generated/settings.json
+++ b/generated/settings.json
@@ -1,8 +1,8 @@
11 {
22 "checkLibraryUpdates" : true,
33 "checkVersion" : true,
4- "windowHeight" : 360,
5- "songLimit" : 15,
4+ "windowHeight" : 540,
5+ "songLimit" : 5,
66 "saveScoreLog" : true,
7- "windowWidth" : 640
7+ "windowWidth" : 960
88 }
\ No newline at end of file
--- a/src/com/ranfa/languages/List_en_US.properties
+++ b/src/com/ranfa/languages/List_en_US.properties
@@ -28,4 +28,17 @@ MSGNarrowDownProcedure:How to select songs\r\n1.Select difficulty, attribute, an
2828 MSGCurrentAlbumType:\nCurrent MASTER+ ALBUM type(based on simulation):
2929 MSGManualUpdate:<html><body>Manual<br>Update</body></html>
3030 MSGManualUpdateNotCompleteYet:Manual Update has not been finished yet. Please wait a moment.
31-MSGConfigurations:Config
\ No newline at end of file
31+MSGConfigurations:Config
32+MSGAPIWaitAPIFetch:Getting informations from API. Please wait.
33+MSGInfoPlayedSongs:The songs you played
34+MSGInfoWait:Please wait...
35+MSGInfoSongName:Song Name
36+MSGInfoLyricsBy:Lyrics By
37+MSGInfoSongAttribute:Song Attribute
38+MSGInfoComposedBy:Composed By
39+MSGInfoSongDifficulty:Difficulty
40+MSGInfoArrangedBy:Arranged By
41+MSGInfoSongLevel:Song Level
42+MSGInfoMember:Member
43+MSGInfoSongNotes:Notes
44+MSGInfoOpenBrowser:More Information
\ No newline at end of file
--- a/src/com/ranfa/languages/List_ja_JP.properties
+++ b/src/com/ranfa/languages/List_ja_JP.properties
@@ -28,4 +28,17 @@ MSGNarrowDownProcedure:\u697d\u66f2\u9078\u629e\u306e\u624b\u9806\r\n\uff11\uff0
2828 MSGCurrentAlbumType:\n\u73fe\u5728\u306eMASTER+\u30a2\u30eb\u30d0\u30e0\u5468\u671f\uff08\u63a8\u5b9a\uff09\uff1a
2929 MSGManualUpdate:<html><body>\u624b\u52d5\u66f4\u65b0</body></html>
3030 MSGManualUpdateNotCompleteYet:\u624b\u52d5\u66f4\u65b0\u304c\u5b8c\u4e86\u3057\u3066\u3044\u307e\u305b\u3093\u3002\u3082\u3046\u3057\u3070\u3089\u304f\u304a\u5f85\u3061\u304f\u3060\u3055\u3044\u3002
31-MSGConfigurations:\u8a2d\u5b9a
\ No newline at end of file
31+MSGConfigurations:\u8a2d\u5b9a
32+MSGAPIWaitAPIFetch:\u697D\u66F2\u60C5\u5831\u0041\u0050\u0049\u3088\u308A\u53D6\u5F97\u4E2D\u3067\u3059\u3002\n\u3057\u3070\u3089\u304F\u304A\u5F85\u3061\u304F\u3060\u3055\u3044\u3002
33+MSGInfoPlayedSongs:\u4ECA\u56DE\u30D7\u30EC\u30A4\u3057\u305F\u697D\u66F2
34+MSGInfoWait:\u3057\u3070\u3089\u304F\u304A\u5F85\u3061\u304F\u3060\u3055\u3044\u2026
35+MSGInfoSongName:\u66F2\u540D
36+MSGInfoLyricsBy:\u4F5C\u8A5E\u8005
37+MSGInfoSongAttribute:\u66F2\u30BF\u30A4\u30D7
38+MSGInfoComposedBy:\u4F5C\u66F2\u8005
39+MSGInfoSongDifficulty:\u96E3\u6613\u5EA6
40+MSGInfoArrangedBy:\u7DE8\u66F2\u8005
41+MSGInfoSongLevel:\u30EC\u30D9\u30EB
42+MSGInfoMember:\u767B\u5834\u30E1\u30F3\u30D0\u30FC
43+MSGInfoSongNotes:\u30CE\u30FC\u30C8\u6570
44+MSGInfoOpenBrowser:\u66F4\u306B\u8A73\u3057\u3044\u60C5\u5831\u3092\u898B\u308B
\ No newline at end of file
--- a/src/com/ranfa/lib/CheckVersion.java
+++ b/src/com/ranfa/lib/CheckVersion.java
@@ -17,6 +17,8 @@ public class CheckVersion {
1717 private final static String RELEASE_STRING = "https://github.com/hizumiaoba/DelesteRandomSelector/releases";
1818
1919 public static void needToBeUpdated() {
20+ if(!getSuffix().equals(Suffix.STABLE))
21+ return;
2022 int latestMajor = 0;
2123 int latestMinor = 0;
2224 int latestPatch = 0;
@@ -48,7 +50,8 @@ public class CheckVersion {
4850 String value = "v"
4951 + getMajorVersion() + "."
5052 + getMinorVersion() + "."
51- + getPatchVersion();
53+ + getPatchVersion() + "-"
54+ + getSuffix().toString();
5255 return value;
5356 }
5457
@@ -66,5 +69,10 @@ public class CheckVersion {
6669 Version version = DelesteRandomSelector.class.getAnnotation(Version.class);
6770 return version.patch();
6871 }
72+
73+ public static Suffix getSuffix() {
74+ Version version = DelesteRandomSelector.class.getAnnotation(Version.class);
75+ return version.suffix();
76+ }
6977
7078 }
--- a/src/com/ranfa/lib/ManualUpdateThreadImpl.java
+++ b/src/com/ranfa/lib/ManualUpdateThreadImpl.java
@@ -9,13 +9,17 @@ import java.util.function.BiConsumer;
99 import org.slf4j.Logger;
1010 import org.slf4j.LoggerFactory;
1111
12+import com.ranfa.lib.concurrent.CountedThreadFactory;
13+import com.ranfa.lib.database.Scraping;
14+import com.ranfa.lib.database.Song;
15+
1216 public class ManualUpdateThreadImpl implements Runnable {
1317
1418 //Declare flag
1519 private static boolean flag = true;
1620
1721 //Declare Executor service
18- private Executor executor = Executors.newWorkStealingPool();
22+ private Executor executor = Executors.newCachedThreadPool(new CountedThreadFactory(() -> "DRS", "ManualUpdateThread"));
1923 private BiConsumer<ArrayList<Song>, ArrayList<Song>> updateConsumer = (list1, list2) -> {
2024 this.logger.info("Checking database updates...");
2125 if(list1.size() > list2.size()) {
--- a/src/com/ranfa/lib/Settings.java
+++ b/src/com/ranfa/lib/Settings.java
@@ -64,7 +64,7 @@ public class Settings {
6464 }
6565
6666 public static int getWindowWidth() {
67- int res = 640;
67+ int res = 960;
6868 ObjectMapper mapper = new ObjectMapper();
6969 try {
7070 JsonNode node = mapper.readTree(new File(FILEPATH));
@@ -76,7 +76,7 @@ public class Settings {
7676 }
7777
7878 public static int getWindowHeight() {
79- int res = 360;
79+ int res = 540;
8080 ObjectMapper mapper = new ObjectMapper();
8181 try {
8282 JsonNode node = mapper.readTree(new File(FILEPATH));
@@ -116,8 +116,8 @@ public class Settings {
116116 SettingJSONProperty property = new SettingJSONProperty();
117117 property.setCheckVersion(true);
118118 property.setCheckLibraryUpdates(true);
119- property.setWindowWidth(640);
120- property.setWindowHeight(360);
119+ property.setWindowWidth(960);
120+ property.setWindowHeight(540);
121121 property.setSongLimit(3);
122122 property.setSaveScoreLog(false);
123123 ObjectWriter writer = new ObjectMapper().writer(new DefaultPrettyPrinter());
--- /dev/null
+++ b/src/com/ranfa/lib/Suffix.java
@@ -0,0 +1,24 @@
1+package com.ranfa.lib;
2+
3+public enum Suffix {
4+
5+ /** Alpha channel*/
6+ ALPHA("Alpha"),
7+
8+ /** Beta channel*/
9+ BETA("Beta"),
10+
11+ /** Stable channel*/
12+ STABLE("Stable");
13+
14+ private String suf;
15+
16+ Suffix(String str) {
17+ this.suf = str;
18+ }
19+
20+ @Override
21+ public String toString() {
22+ return suf;
23+ }
24+}
--- a/src/com/ranfa/lib/Version.java
+++ b/src/com/ranfa/lib/Version.java
@@ -11,4 +11,5 @@ public @interface Version {
1111 int major();
1212 int minor();
1313 int patch();
14+ Suffix suffix();
1415 }
--- /dev/null
+++ b/src/com/ranfa/lib/calc/FanCalc.java
@@ -0,0 +1,97 @@
1+package com.ranfa.lib.calc;
2+
3+import java.math.BigDecimal;
4+import java.math.RoundingMode;
5+import java.util.concurrent.CompletableFuture;
6+import java.util.concurrent.ExecutorService;
7+import java.util.concurrent.Executors;
8+import java.util.concurrent.atomic.AtomicBoolean;
9+import java.util.concurrent.atomic.AtomicInteger;
10+
11+import org.slf4j.Logger;
12+import org.slf4j.LoggerFactory;
13+
14+import com.ranfa.lib.concurrent.CountedThreadFactory;
15+
16+/**
17+ * ファン計算用とのライブラリ
18+ * ファン数計算とスコア計算を実装
19+ * @author hizum
20+ *
21+ */
22+public class FanCalc {
23+
24+ private static final Logger logger = LoggerFactory.getLogger(FanCalc.class);
25+ private static final ExecutorService async = Executors.newSingleThreadExecutor(new CountedThreadFactory(() -> "DRS", "FanCalcThread", false));
26+
27+ /**
28+ * 計算式は
29+ * 端数切り上げ(スコア*0.001*ルーム補正値*センター、ゲスト効果補正値*プロデュース方針補正値)
30+ * ルーム、センター、ゲスト、プロデュース方針の補正値は百分率。計算時に自動で変換します
31+ * @param score ライブで獲得したスコアを入力します
32+ * @param room ルームアイテムによる補正値を百分率のまま(xxx%)入力します
33+ * @param center センター、ゲスト効果による補正値を百分率のまま入力します
34+ * @param produce プロデュース方針による補正値を百分率のまま入力します
35+ * @return 一人あたりの獲得ファン数。1回のライブで獲得出来るファン数はこの値の5倍です
36+ */
37+ public static int fan(int score, int room, int center, int produce, int premium) {
38+ BigDecimal toPercent = new BigDecimal(100);
39+ BigDecimal res = new BigDecimal(0);
40+ BigDecimal roomPercent = new BigDecimal(room).divide(toPercent);
41+ BigDecimal centerPercent = new BigDecimal(center).divide(toPercent);
42+ BigDecimal producePercent = new BigDecimal(produce).divide(toPercent);
43+ BigDecimal premiumPercent = new BigDecimal(premium).divide(toPercent);
44+ BigDecimal corrections = new BigDecimal(-1)
45+ .add(roomPercent)
46+ .add(centerPercent);
47+ res = res.add(new BigDecimal(score))
48+ .multiply(corrections)
49+ .divide(new BigDecimal("1000"));
50+ res = res.setScale(0,RoundingMode.UP);
51+ BigDecimal resCorrected = res.multiply(producePercent);
52+ resCorrected = resCorrected.setScale(0,RoundingMode.UP);
53+ BigDecimal resPremiumed = resCorrected.multiply(premiumPercent);
54+ resPremiumed = resPremiumed.setScale(0, RoundingMode.UP);
55+ return (resPremiumed.compareTo(BigDecimal.ZERO) == 0) || (resPremiumed == null) ? 0 : Integer.parseInt(resPremiumed.toString());
56+ }
57+
58+ /**
59+ * 目標スコアを計算。
60+ * 初期実装の思想は並列処理による再帰計算。
61+ * @param fan 目標ファン
62+ * @param multiplier LIVEの繰り返し回数
63+ * @param room ルームアイテム補正値(百分率)
64+ * @param center センター、ゲスト効果による補正値
65+ * @param produce プロデュース方針にとる補正値
66+ * @param premium プレミアムパスによる補正値
67+ * @return LIVE一回当たりの目標スコア
68+ */
69+ public static CompletableFuture<Integer> scoreAsync(int fan, int multiplier, int room, int center, int produce, int premium) {
70+ return CompletableFuture.supplyAsync(() -> score(fan, multiplier, room, center, produce, premium), async);
71+ }
72+
73+ /**
74+ * @param fan 目標ファン
75+ * @param multiplier LIVEの繰り返し回数
76+ * @param room ルームアイテム補正値(百分率)
77+ * @param center センター、ゲスト効果による補正値
78+ * @param produce プロデュース方針にとる補正値
79+ * @param premium プレミアムパスによる補正値
80+ * @return LIVE一回当たりの目標スコア
81+ */
82+ private static int score(int fan, int multiplier, int room, int center, int produce, int premium) {
83+ BigDecimal goalFan = new BigDecimal(fan).divide(new BigDecimal(multiplier), 0, RoundingMode.UP);
84+ final AtomicInteger result = new AtomicInteger(0);
85+ final AtomicBoolean flag = new AtomicBoolean(false);
86+ logger.info("Started to calculate score at dedicated thread.");
87+ while(!flag.get()) {
88+ int localFan = fan(result.incrementAndGet(), room, center, produce, premium) * 5;
89+ if(goalFan.compareTo(new BigDecimal(localFan)) <= 0) {
90+ flag.set(true);
91+ }
92+ }
93+ return Integer.parseInt(result.toString());
94+ }
95+
96+
97+}
--- /dev/null
+++ b/src/com/ranfa/lib/calc/PRPCalc.java
@@ -0,0 +1,66 @@
1+package com.ranfa.lib.calc;
2+
3+import java.io.IOException;
4+import java.math.BigDecimal;
5+import java.math.RoundingMode;
6+import java.nio.file.Files;
7+import java.nio.file.Paths;
8+import java.util.List;
9+
10+import org.slf4j.Logger;
11+import org.slf4j.LoggerFactory;
12+
13+import com.fasterxml.jackson.core.type.TypeReference;
14+import com.fasterxml.jackson.databind.ObjectMapper;
15+
16+public class PRPCalc {
17+
18+ private final Logger logger = LoggerFactory.getLogger(PRPCalc.class);
19+
20+ private static final String PRP_STORAGE_FILE_PATH = "generated/prp.json";
21+ private static final BigDecimal THAUSAND = BigDecimal.valueOf(1000);
22+
23+ private List<Integer> TotalPRPList;
24+ private int TotalPRP;
25+
26+ public PRPCalc() {
27+ if(Files.notExists(Paths.get(PRP_STORAGE_FILE_PATH)))
28+ generateEmptyPRPFile();
29+ TypeReference<List<Integer>> typeref = new TypeReference<List<Integer>>() {};
30+ try {
31+ TotalPRPList = new ObjectMapper().readValue(Paths.get(PRP_STORAGE_FILE_PATH).toFile(), typeref);
32+ } catch (IOException e) {
33+ logger.error("Couldn't read prp file from disk.", e);
34+ }
35+ TotalPRP = calcCurrentTotal();
36+ }
37+
38+ public boolean generateEmptyPRPFile() {
39+ if(Files.notExists(Paths.get("generated")))
40+ try {
41+ Files.createDirectory(Paths.get("generated"));
42+ Files.createFile(Paths.get(PRP_STORAGE_FILE_PATH));
43+ } catch (IOException e) {
44+ logger.error("cannot make prp file.", e);
45+ return false;
46+ }
47+ return true;
48+ }
49+
50+ public int calcCurrentTotal() {
51+ int res = 0;
52+ for(int val : TotalPRPList)
53+ res += val;
54+ return res;
55+ }
56+
57+ public int getTotalPRP() {
58+ return TotalPRP;
59+ }
60+
61+ public static int calcPRPFromScore(int score) {
62+ BigDecimal scoreDecimal = BigDecimal.valueOf(score);
63+ scoreDecimal.divide(THAUSAND, RoundingMode.DOWN);
64+ return scoreDecimal.intValueExact();
65+ }
66+}
--- /dev/null
+++ b/src/com/ranfa/lib/concurrent/CountedThreadFactory.java
@@ -0,0 +1,34 @@
1+package com.ranfa.lib.concurrent;
2+
3+import java.util.concurrent.ThreadFactory;
4+import java.util.concurrent.atomic.AtomicLong;
5+import java.util.function.Supplier;
6+
7+import lombok.NonNull;
8+
9+public class CountedThreadFactory implements ThreadFactory {
10+
11+ private final Supplier<String> identifier;
12+ private final AtomicLong count = new AtomicLong(1);
13+ private final boolean isDaemon;
14+
15+ public CountedThreadFactory() {
16+ this(() -> "Default", "Thread");
17+ }
18+
19+ public CountedThreadFactory(Supplier<String> identifier, String specifier) {
20+ this(identifier, specifier, true);
21+ }
22+
23+ public CountedThreadFactory(Supplier<String> identifier, String specifier, boolean isDaemon) {
24+ this.identifier = () -> identifier.get() + " " + specifier;
25+ this.isDaemon = isDaemon;
26+ }
27+
28+ @Override
29+ public Thread newThread(@NonNull Runnable r) {
30+ final Thread thread = new Thread(r, identifier.get() + "-Worker " + count.getAndIncrement());
31+ thread.setDaemon(isDaemon);
32+ return thread;
33+ }
34+}
--- a/src/com/ranfa/lib/Album.java
+++ b/src/com/ranfa/lib/database/Album.java
@@ -1,4 +1,4 @@
1-package com.ranfa.lib;
1+package com.ranfa.lib.database;
22
33 public class Album {
44
--- a/src/com/ranfa/lib/AlbumCycleDefinitionProperty.java
+++ b/src/com/ranfa/lib/database/AlbumCycleDefinitionProperty.java
@@ -1,4 +1,4 @@
1-package com.ranfa.lib;
1+package com.ranfa.lib.database;
22
33 public class AlbumCycleDefinitionProperty {
44
--- a/src/com/ranfa/lib/AlbumTypeEstimate.java
+++ b/src/com/ranfa/lib/database/AlbumTypeEstimate.java
@@ -1,9 +1,11 @@
1-package com.ranfa.lib;
1+package com.ranfa.lib.database;
22
33 import java.io.IOException;
44 import java.util.ArrayList;
55 import java.util.concurrent.CompletableFuture;
66 import java.util.concurrent.ExecutionException;
7+import java.util.concurrent.ExecutorService;
8+import java.util.concurrent.Executors;
79
810 import org.jsoup.Jsoup;
911 import org.jsoup.nodes.Document;
@@ -11,9 +13,12 @@ import org.jsoup.select.Elements;
1113 import org.slf4j.Logger;
1214 import org.slf4j.LoggerFactory;
1315
16+import com.ranfa.lib.concurrent.CountedThreadFactory;
17+
1418 public class AlbumTypeEstimate {
1519
1620 public final static String ALBUM_DATA_URI = "https://imascg-slstage-wiki.gamerch.com/%E6%A5%BD%E6%9B%B2%E8%A9%B3%E7%B4%B0%E4%B8%80%E8%A6%A7%EF%BC%88%E9%9B%A3%E6%98%93%E5%BA%A6%E5%88%A5%EF%BC%89";
21+ private static ExecutorService executor = Executors.newCachedThreadPool(new CountedThreadFactory(() -> "DRS", "AlbumEstimateThread"));
1722 private static Logger logger = LoggerFactory.getLogger(AlbumTypeEstimate.class);
1823
1924 //アルバム種類の定義
@@ -45,8 +50,8 @@ public class AlbumTypeEstimate {
4550 Elements elements = document.getElementsByTag("tbody");
4651 Elements newMasterPlus = elements.get(4).select("tr");
4752 Elements legacyMasterPlus = elements.get(5).select("tr");
48- CompletableFuture<ArrayList<Album>> fetchNew = CompletableFuture.supplyAsync(() -> fetch(newMasterPlus));
49- CompletableFuture<ArrayList<Album>> fetchLegacy = CompletableFuture.supplyAsync(() -> fetch(legacyMasterPlus));
53+ CompletableFuture<ArrayList<Album>> fetchNew = CompletableFuture.supplyAsync(() -> fetch(newMasterPlus), executor);
54+ CompletableFuture<ArrayList<Album>> fetchLegacy = CompletableFuture.supplyAsync(() -> fetch(legacyMasterPlus), executor);
5055 res.add(fetchNew.get());
5156 res.add(fetchLegacy.get());
5257 } catch (IOException | InterruptedException | ExecutionException e) {
--- a/src/com/ranfa/lib/EstimateAlbumTypeCycle.java
+++ b/src/com/ranfa/lib/database/EstimateAlbumTypeCycle.java
@@ -1,4 +1,4 @@
1-package com.ranfa.lib;
1+package com.ranfa.lib.database;
22
33 import java.io.IOException;
44 import java.nio.file.Files;
--- a/src/com/ranfa/lib/Scraping.java
+++ b/src/com/ranfa/lib/database/Scraping.java
@@ -1,4 +1,4 @@
1-package com.ranfa.lib;
1+package com.ranfa.lib.database;
22
33 import java.io.File;
44 import java.io.IOException;
@@ -22,7 +22,8 @@ import org.slf4j.LoggerFactory;
2222 import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
2323 import com.fasterxml.jackson.databind.ObjectMapper;
2424 import com.fasterxml.jackson.databind.ObjectWriter;
25-import com.ranfa.lib.AlbumTypeEstimate.MASTERPLUS_TYPE;
25+import com.ranfa.lib.concurrent.CountedThreadFactory;
26+import com.ranfa.lib.database.AlbumTypeEstimate.MASTERPLUS_TYPE;
2627 import com.ranfa.main.Messages;
2728
2829 public class Scraping {
@@ -58,7 +59,7 @@ public class Scraping {
5859
5960 public static ArrayList<Song> getWholeData() {
6061 long time = System.currentTimeMillis();
61- ExecutorService es = Executors.newWorkStealingPool();
62+ ExecutorService es = Executors.newCachedThreadPool(new CountedThreadFactory(() -> "DRS", "WebdataFetchThread"));
6263 CompletableFuture<ArrayList<ArrayList<Album>>> typeFetchFuture = CompletableFuture.supplyAsync(() -> AlbumTypeEstimate.getAlbumType(), es);
6364 // if(databaseExists())
6465 // return null;
--- a/src/com/ranfa/lib/Song.java
+++ b/src/com/ranfa/lib/database/Song.java
@@ -1,4 +1,4 @@
1-package com.ranfa.lib;
1+package com.ranfa.lib.database;
22
33 public class Song {
44
--- a/src/com/ranfa/lib/SongJSONProperty.java
+++ b/src/com/ranfa/lib/database/SongJSONProperty.java
@@ -1,4 +1,4 @@
1-package com.ranfa.lib;
1+package com.ranfa.lib.database;
22
33 import java.util.List;
44
--- /dev/null
+++ b/src/com/ranfa/lib/handler/CrashHandler.java
@@ -0,0 +1,193 @@
1+package com.ranfa.lib.handler;
2+
3+import java.lang.management.ManagementFactory;
4+import java.lang.management.MemoryMXBean;
5+import java.lang.management.MemoryUsage;
6+import java.lang.management.OperatingSystemMXBean;
7+import java.lang.management.RuntimeMXBean;
8+import java.text.SimpleDateFormat;
9+import java.util.Date;
10+import java.util.Random;
11+import java.util.concurrent.CompletionException;
12+
13+import org.slf4j.Logger;
14+import org.slf4j.LoggerFactory;
15+
16+import com.ranfa.lib.CheckVersion;
17+
18+public class CrashHandler {
19+
20+ // Logger
21+ private final Logger LOG = LoggerFactory.getLogger(CrashHandler.class);
22+
23+ // fields
24+ private Throwable e;
25+ private String description;
26+ private int estimateExitCode;
27+ private CrashReportList<String> crashReportLines = new CrashReportList<>();
28+ private Random random = new Random(System.currentTimeMillis());
29+
30+
31+ // constants
32+ private static final SimpleDateFormat FORMAT = new SimpleDateFormat("yy/MM/dd HH:mm");
33+ private static final String DEFAULT_DESCRIPTION = "Unexpected Error";
34+ private static final String[] EASTER_LINES = {
35+ "// It will need to do more test?",
36+ "// I may be so bad to code?",
37+ "// Shimamura Uzuki, I'll do my best!",
38+ "// This is also adventure!, isn't it?",
39+ "// I... leave all books... behind... 'cause I want to talk... with you...",
40+ "// This software was developed by @hizumiaoba",
41+ "// These Easter sentences were inspired by Minecraft Crash Report!"
42+ };
43+
44+ private static final int EXIT_WITH_NESTED_CAUSE = 2;
45+ private static final int EXIT_WITH_NULL_POINTER_EXCEPTION = 3;
46+ private static final int EXIT_WITH_ILLEGAL_STATE_EXCEPTION = 5;
47+ private static final int EXIT_WITH_COMPLETION_EXCEPTION = 7;
48+ private static final int EXIT_WITH_ILLEGAL_ARGUMENT_EXCEPTION = 9;
49+
50+ public CrashHandler() {
51+ this(DEFAULT_DESCRIPTION);
52+ }
53+
54+ public CrashHandler(String m) {
55+ this(m, null);
56+ }
57+
58+ public CrashHandler(Throwable e) {
59+ this(DEFAULT_DESCRIPTION, e);
60+ }
61+
62+ public CrashHandler(String description, Throwable e) {
63+ LOG.warn("Unexpected Exception has occured. : {}", e == null ? "null" : e.toString());
64+ LOG.warn("Provided Detail Message : {}", description);
65+ this.e = e;
66+ this.description = description;
67+ estimateExitCode = Integer.MIN_VALUE;
68+ crashReportLines.add("---- DelesteRandomSelector Crash Report ----");
69+ int randomInt = random.nextInt(EASTER_LINES.length);
70+ crashReportLines.add(EASTER_LINES[randomInt]);
71+ }
72+
73+ public void execute() {
74+ if(e == null)
75+ throw new NullPointerException("Cannot execute crash because throwable is null.");
76+ estimateExitCode = calcExitCode();
77+ LOG.error("Cannot keep up application! : {}", e.toString());
78+ LOG.error("Application will exit with exit code : {}", estimateExitCode);
79+ LOG.error(outputReport());
80+ crashReportLines.outCrashReport();
81+ System.exit(estimateExitCode);
82+ }
83+
84+ private String outputReport() {
85+ crashReportLines.emptyLine();
86+ crashReportLines.add("Time: " + FORMAT.format(new Date()));
87+ crashReportLines.add("Description: " + description);
88+ crashReportLines.emptyLine();
89+ LOG.debug("Gathering exception informations.");
90+ if(e != null) {
91+ crashReportLines.add("These are simplified stack trace. (shown up to 5 lines. Full Stack trace is below.)");
92+ crashReportLines.add(e.toString());
93+ StackTraceElement[] topElements = e.getStackTrace();
94+ for(int i = 0; i < 5; i++) {
95+ crashReportLines.add("\tat " + topElements[i].toString());
96+ }
97+ crashReportLines.emptyLine();
98+ crashReportLines.add("A detailed walkthrough of the error, its code path and all known details is as follows:");
99+ crashReportLines.add("---------------------------------------------------------------------------------------");
100+ crashReportLines.emptyLine();
101+ crashReportLines.add("Stacktrace:");
102+ addLinesRecursively(e, crashReportLines);
103+ }
104+ LOG.debug("Gathering system informations.");
105+ RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
106+ OperatingSystemMXBean operatingBean = ManagementFactory.getOperatingSystemMXBean();
107+ MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
108+ MemoryUsage memUsage = memoryBean.getHeapMemoryUsage();
109+ crashReportLines.emptyLine();
110+ crashReportLines.add("-- System Details --");
111+ crashReportLines.add("Details:");
112+ crashReportLines.add("\tDelesteRandomSelector Version: " + CheckVersion.getVersion());
113+ crashReportLines.add("\tOperating System: "
114+ + operatingBean.getName() + " ("
115+ + operatingBean.getArch() + ") version "
116+ + operatingBean.getVersion());
117+ crashReportLines.add("\tJava Version: " + runtimeBean.getSpecVersion() + ", " + runtimeBean.getVmVendor());
118+ crashReportLines.add("\tJava VM Version: " + runtimeBean.getVmName() + ", version " + runtimeBean.getVmVersion());
119+ crashReportLines.add("\tMemory: " + memUsage.getUsed() + " bytes / " + memUsage.getInit() + " bytes up to " + memUsage.getMax() + " bytes");
120+ crashReportLines.add("\tJVM Flags: " + runtimeBean.getInputArguments().size() + " total: " + runtimeBean.getInputArguments().toString());
121+ return crashReportLines.generateCrashReport();
122+ }
123+
124+ public String outSystemInfo() {
125+ // Override fields
126+ this.e = null;
127+ this.description = "Loading screen debug info\n"
128+ + "\n"
129+ + "This is just a prompt for computer specs to be printed. THIS IS NOT A ERROR";
130+ String res = outputReport();
131+ LOG.info(res);
132+ return res;
133+ }
134+
135+ public static CrashReportList<String> addLinesRecursively(Throwable e, CrashReportList<String> list) {
136+ if(e == null)
137+ return list;
138+ StackTraceElement[] elements = e.getStackTrace();
139+ for(StackTraceElement element : elements) {
140+ list.add("\tat " + element.toString());
141+ }
142+ if(e.getCause() != null) {
143+ list.add("Caused by: " + e.getCause().toString());
144+ addLinesRecursively(e.getCause(), list);
145+ }
146+ return list;
147+ }
148+
149+ public String getDescription() {
150+ return description;
151+ }
152+
153+ public Throwable getThrowable() {
154+ return e;
155+ }
156+
157+ public int getEstimateExitCode() {
158+ return estimateExitCode;
159+ }
160+
161+ private int calcExitCode() {
162+ int res = 1;
163+ if(e.getCause() != null)
164+ res *= EXIT_WITH_NESTED_CAUSE;
165+ if(e instanceof NullPointerException )
166+ res *= EXIT_WITH_NULL_POINTER_EXCEPTION;
167+ if(e instanceof IllegalStateException)
168+ res *= EXIT_WITH_ILLEGAL_STATE_EXCEPTION;
169+ if(e instanceof CompletionException )
170+ res *= EXIT_WITH_COMPLETION_EXCEPTION;
171+ if(e instanceof IllegalArgumentException)
172+ res *= EXIT_WITH_ILLEGAL_ARGUMENT_EXCEPTION;
173+ if(e.getCause() != null)
174+ return calcExitCode(e.getCause(), res);
175+ return res;
176+ }
177+
178+ private static int calcExitCode(Throwable e, int current) {
179+ if(e == null)
180+ return current;
181+ if(e.getCause() != null)
182+ current *= EXIT_WITH_NESTED_CAUSE;
183+ if(e instanceof NullPointerException )
184+ current *= EXIT_WITH_NULL_POINTER_EXCEPTION;
185+ if(e instanceof IllegalStateException)
186+ current *= EXIT_WITH_ILLEGAL_STATE_EXCEPTION;
187+ if(e instanceof CompletionException )
188+ current *= EXIT_WITH_COMPLETION_EXCEPTION;
189+ if(e instanceof IllegalArgumentException)
190+ current *= EXIT_WITH_ILLEGAL_ARGUMENT_EXCEPTION;
191+ return calcExitCode(e.getCause(), current);
192+ }
193+}
--- /dev/null
+++ b/src/com/ranfa/lib/handler/CrashReportList.java
@@ -0,0 +1,55 @@
1+package com.ranfa.lib.handler;
2+
3+import java.io.FileWriter;
4+import java.io.IOException;
5+import java.nio.file.Paths;
6+import java.text.SimpleDateFormat;
7+import java.util.ArrayList;
8+import java.util.Date;
9+import java.util.List;
10+
11+import org.slf4j.LoggerFactory;
12+
13+public class CrashReportList <E> extends ArrayList<E> {
14+
15+ private static final String EMPTY_LINE_PLACEHOLDER = "{empty}";
16+
17+ private final SimpleDateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
18+
19+ private List<E> store;
20+
21+ public CrashReportList() {
22+ super();
23+ store = new ArrayList<>();
24+ }
25+
26+ @Override
27+ public boolean add(E e) {
28+ return store.add(e);
29+ }
30+
31+ @SuppressWarnings("unchecked")
32+ public String generateCrashReport() {
33+ StringBuilder builder = new StringBuilder();
34+ for(E str : store) {
35+ if(str.equals(EMPTY_LINE_PLACEHOLDER))
36+ str = (E) "\n";
37+ builder.append(str).append("\n");
38+ }
39+ return builder.toString();
40+ }
41+ @SuppressWarnings("unchecked")
42+ public boolean emptyLine() {
43+ return store.add((E) EMPTY_LINE_PLACEHOLDER);
44+ }
45+
46+ public void outCrashReport() {
47+ try {
48+ FileWriter writer = new FileWriter(Paths.get("Crash-Report/" + FORMAT.format(new Date()) + ".txt").toFile());
49+ writer.write(generateCrashReport());
50+ writer.close();
51+ } catch (IOException e) {
52+ LoggerFactory.getLogger(CrashReportList.class).error("Cannot write crash report.", e);
53+ }
54+ }
55+}
--- /dev/null
+++ b/src/com/ranfa/lib/io/FileIO.java
@@ -0,0 +1,73 @@
1+package com.ranfa.lib.io;
2+
3+import java.io.FileInputStream;
4+import java.io.FileOutputStream;
5+import java.io.IOException;
6+import java.io.ObjectInputStream;
7+import java.io.ObjectOutputStream;
8+import java.text.SimpleDateFormat;
9+import java.util.Date;
10+import java.util.List;
11+import java.util.Map;
12+
13+import org.slf4j.Logger;
14+import org.slf4j.LoggerFactory;
15+
16+public class FileIO {
17+
18+ private static Logger logger = LoggerFactory.getLogger(FileIO.class);
19+
20+ // constants
21+ private static final String FILE_NAME_PATTERN = "YYYY-MM-dd-HH-mm-ss";
22+ private static final String FILE_EXTENSION = ".drs";
23+
24+ // fields
25+ /**
26+ * songname
27+ * level
28+ * difficulty
29+ * attribute
30+ * score
31+ */
32+ List<Map<String, String>> songList;
33+
34+
35+ public FileIO(List<Map<String, String>> songList) {
36+ this.songList = songList;
37+ }
38+
39+ public FileIO() {
40+ this.songList = null;
41+ }
42+
43+ public boolean write() {
44+ StringBuilder builder = new StringBuilder(new SimpleDateFormat(FILE_NAME_PATTERN).format(new Date()));
45+ builder.append(FILE_EXTENSION);
46+ try {
47+ ObjectOutputStream outStream = new ObjectOutputStream(new FileOutputStream(builder.toString()));
48+ OutputDataStructure structure = new OutputDataStructure(songList);
49+ outStream.writeObject(structure);
50+ outStream.flush();
51+ outStream.close();
52+ return true;
53+ } catch (IOException e) {
54+ logger.error("Exception while output objects", e);
55+ return false;
56+ }
57+ }
58+
59+ public static OutputDataStructure read(String fileName) {
60+ FileInputStream fileInputStream;
61+ try {
62+ fileInputStream = new FileInputStream(fileName);
63+ ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
64+ OutputDataStructure structure = (OutputDataStructure) objectInputStream.readObject();
65+ objectInputStream.close();
66+ return structure;
67+ } catch (IOException | ClassNotFoundException e) {
68+ logger.error("Exception while reading objects", e);
69+ return null;
70+ }
71+ }
72+
73+}
--- /dev/null
+++ b/src/com/ranfa/lib/io/OutputDataStructure.java
@@ -0,0 +1,46 @@
1+package com.ranfa.lib.io;
2+
3+import java.io.Serializable;
4+import java.util.List;
5+import java.util.Map;
6+import java.util.Objects;
7+
8+public class OutputDataStructure implements Serializable {
9+
10+ private static final long serialVersionUID = 1L;
11+
12+ // fields
13+ List<Map<String, String>> songList;
14+
15+ public OutputDataStructure(List<Map<String, String>> songList) {
16+ this.songList = songList;
17+ }
18+
19+ public static long getSerialversionuid() {
20+ return serialVersionUID;
21+ }
22+
23+ public List<Map<String, String>> getSongList() {
24+ return songList;
25+ }
26+
27+
28+ @Override
29+ public int hashCode() {
30+ return Objects.hash(songList);
31+ }
32+
33+ @Override
34+ public boolean equals(Object obj) {
35+ if (this == obj) {
36+ return true;
37+ }
38+ if (!(obj instanceof OutputDataStructure)) {
39+ return false;
40+ }
41+ OutputDataStructure other = (OutputDataStructure) obj;
42+ return Objects.equals(songList, other.songList);
43+ }
44+
45+
46+}
--- /dev/null
+++ b/src/com/ranfa/lib/songinfo/FetchFromAPI.java
@@ -0,0 +1,197 @@
1+package com.ranfa.lib.songinfo;
2+
3+import java.io.IOException;
4+import java.text.Normalizer;
5+import java.util.ArrayList;
6+import java.util.Arrays;
7+import java.util.Collections;
8+import java.util.HashMap;
9+import java.util.LinkedHashMap;
10+import java.util.List;
11+import java.util.Map;
12+import java.util.concurrent.CompletableFuture;
13+import java.util.concurrent.ExecutorService;
14+import java.util.concurrent.Executors;
15+import java.util.concurrent.TimeUnit;
16+import java.util.concurrent.atomic.AtomicInteger;
17+
18+import org.slf4j.Logger;
19+import org.slf4j.LoggerFactory;
20+
21+import com.fasterxml.jackson.core.type.TypeReference;
22+import com.fasterxml.jackson.databind.JsonNode;
23+import com.fasterxml.jackson.databind.ObjectMapper;
24+import com.ranfa.lib.concurrent.CountedThreadFactory;
25+import com.ranfa.main.DelesteRandomSelector;
26+
27+import HajimeAPI4J.api.HajimeAPI4J;
28+import HajimeAPI4J.api.HajimeAPI4J.List_Params;
29+import HajimeAPI4J.api.HajimeAPI4J.List_Type;
30+import HajimeAPI4J.api.HajimeAPI4J.Music_Params;
31+import HajimeAPI4J.api.HajimeAPI4J.Token;
32+import HajimeAPI4J.api.HajimeAPIBuilder;
33+import HajimeAPI4J.api.util.datatype.Member;
34+import HajimeAPI4J.exception.NoSuchURIException;
35+
36+public class FetchFromAPI {
37+
38+ private Logger logger = LoggerFactory.getLogger(FetchFromAPI.class);
39+
40+
41+ private ExecutorService localDispatcher = Executors.newCachedThreadPool(new CountedThreadFactory(() -> "DRS", "LocalDispatcher"));
42+ private List<JsonNode> nodes;
43+
44+ // constructor
45+
46+ public FetchFromAPI(String... songnames) {
47+ List<JsonNode> listFutures = new ArrayList<>();
48+ final AtomicInteger n = new AtomicInteger(0);
49+ for(String songname : Arrays.asList(songnames)) {
50+ DelesteRandomSelector.labelInfoProgressSongName.setText("<html><body>Processing : " + songname + "</body></html>");
51+ Map<String, Object> data = fetchList(songname);
52+ if(data.getOrDefault("error", "false").equals("true")) {
53+ JsonNode errorNode = new ObjectMapper().valueToTree(data);
54+ listFutures.add(errorNode);
55+ continue;
56+ }
57+ int taxId = Integer.parseInt(data.get("song_id").toString());
58+ HajimeAPI4J impl = HajimeAPIBuilder.createDefault(Token.MUSIC)
59+ .addParameter(Music_Params.ID , String.valueOf(taxId))
60+ .build();
61+ logger.info("fetch data : {}", taxId);
62+
63+ try {
64+ listFutures.add(impl.get());
65+ } catch (NoSuchURIException | IOException | InterruptedException e) {
66+ logger.error("Exception while processing json.", e);
67+ } finally {
68+ DelesteRandomSelector.progressTool.setValue(n.incrementAndGet());
69+ }
70+ }
71+ DelesteRandomSelector.labelInfoProgressSongName.setText("");
72+ nodes = listFutures;
73+ }
74+
75+ private Map<String, Object> fetchList(String songname) {
76+ HajimeAPI4J api = HajimeAPIBuilder.createDefault(Token.LIST)
77+ .addParameter(List_Params.TYPE, List_Type.MUSIC.toString())
78+ .addParameter(List_Params.SEARCH, songname)
79+ .build();
80+ List<Map<String, Object>> parse = Collections.emptyList();
81+ try {
82+ parse = new ObjectMapper().readValue( api.get().traverse(), new TypeReference<List<Map<String, Object>>>() {});
83+ TimeUnit.SECONDS.sleep(1);
84+ } catch (IOException | InterruptedException | NoSuchURIException e) {
85+ logger.error("Exception while processing json map");
86+ }
87+ if(parse == null) {
88+ parse = new ArrayList<>(1);
89+ Map<String, Object> tmp = new HashMap<>();
90+ tmp.put("error", "true");
91+ tmp.put("name", songname);
92+ parse.add(tmp);
93+ } else if(parse.isEmpty()) {
94+ parse = new ArrayList<>(1);
95+ Map<String, Object> tmp = new HashMap<>();
96+ tmp.put("error", "true");
97+ tmp.put("name", songname);
98+ parse.add(tmp);
99+ }
100+ for(Map<String, Object> tmp : parse ) {
101+ String normalizeApiName = Normalizer.normalize(tmp.get("name").toString(), Normalizer.Form.NFKD);
102+ String normalizeLocalName = Normalizer.normalize(songname, Normalizer.Form.NFKD);
103+ if(normalizeApiName.equalsIgnoreCase(normalizeLocalName))
104+ return tmp;
105+ }
106+ HashMap<String, Object> altRes = new HashMap<>();
107+ altRes.put("error", "true");
108+ altRes.put("name", songname);
109+ return altRes;
110+ }
111+
112+ public List<Map<String, String>> getInformation() {
113+ List<Map<String, String>> resultList = new ArrayList<>();
114+ int nodeSize = nodes.size();
115+ try {
116+ TimeUnit.SECONDS.sleep(1);
117+ for(JsonNode node : nodes) {
118+ if(node == null) {
119+ Map<String, String> tmp = new HashMap<>();
120+ String errorStr = "Failed to get.";
121+ tmp.put("songname", errorStr);
122+ tmp.put("link", errorStr);
123+ tmp.put("lyric", errorStr);
124+ tmp.put("composer", errorStr);
125+ tmp.put("arrange", errorStr);
126+ tmp.put("member", errorStr);
127+ resultList.add(tmp);
128+ continue;
129+ }
130+ if(node.get("error") != null) {
131+ Map<String, String> tmp = new HashMap<>();
132+ String errorStr = "Failed to get.";
133+ tmp.put("songname", node.get("name").asText());
134+ tmp.put("link", errorStr);
135+ tmp.put("lyric", errorStr);
136+ tmp.put("composer", errorStr);
137+ tmp.put("arrange", errorStr);
138+ tmp.put("member", errorStr);
139+ resultList.add(tmp);
140+ continue;
141+ }
142+ LinkedHashMap<String, String> result = new LinkedHashMap<>();
143+ result.put("songname", node.get("name").asText());
144+ result.put("link", node.get("link").asText());
145+ TypeReference<List<Map<String, Object>>> typeRef = new TypeReference<List<Map<String,Object>>>() {};
146+ ObjectMapper mapper = new ObjectMapper();
147+ List<Map<String, Object>> lyricList = mapper.readValue(node.get("lyrics").traverse(), typeRef),
148+ composerList = mapper.readValue(node.get("composer").traverse(), typeRef),
149+ arrangeList = mapper.readValue(node.get("arrange").traverse(), typeRef);
150+ List<CompletableFuture<Void>> nameArraySupplyFutures = List.of(
151+ CompletableFuture.supplyAsync(() -> getArrayedNames(lyricList), localDispatcher).thenAcceptAsync(str -> result.put("lyric", str), localDispatcher),
152+ CompletableFuture.supplyAsync(() -> getArrayedNames(composerList), localDispatcher).thenAcceptAsync(str -> result.put("composer", str), localDispatcher),
153+ CompletableFuture.supplyAsync(() -> getArrayedNames(arrangeList), localDispatcher).thenAcceptAsync(str -> result.put("arrange", str), localDispatcher)
154+ );
155+ StringBuilder memberBuilder = new StringBuilder();
156+ for(Member tmpMember : mapper.readValue(node.get("member").traverse(), new TypeReference<List<Member>>() {})) {
157+ if(tmpMember.getProduction().equals("cg"))
158+ memberBuilder.append(tmpMember.getName()).append(",");
159+ }
160+ memberBuilder.deleteCharAt(memberBuilder.length() - 1);
161+ result.put("member", memberBuilder.toString());
162+ CompletableFuture.allOf(nameArraySupplyFutures.toArray(new CompletableFuture[] {})).join();
163+ resultList.add(result);
164+ }
165+ } catch(IOException | InterruptedException e) {
166+ logger.warn("Exception while processing json", e);
167+ String errorStr = "No data";
168+ for(int i = 0; i < nodeSize; i++) {
169+ Map<String, String> tmp = new HashMap<>();
170+ JsonNode tmpNode = nodes.get(i);
171+ tmp.put("songname", tmpNode.get("name").asText());
172+ tmp.put("link", tmpNode.get("link").asText());
173+ tmp.put("lyric", errorStr);
174+ tmp.put("composer", errorStr);
175+ tmp.put("arrange", errorStr);
176+ tmp.put("member", errorStr);
177+ resultList.add(tmp);
178+ }
179+ }
180+ resultList.stream().forEach(map -> logger.debug("data fetch complete : {}", map));
181+ return resultList;
182+ }
183+
184+
185+ private String getArrayedNames(List<Map<String, Object>> data) {
186+ if(data == null) {
187+ return "No Data";
188+ }
189+ StringBuilder builder = new StringBuilder();
190+ for(Map<String, Object> tmp : data) {
191+ builder.append(tmp.get("name").toString()).append(",");
192+ }
193+ builder.deleteCharAt(builder.length() - 1);
194+ return builder.toString();
195+ }
196+
197+}
--- a/src/com/ranfa/main/DelesteRandomSelector.java
+++ b/src/com/ranfa/main/DelesteRandomSelector.java
@@ -1,17 +1,26 @@
11 package com.ranfa.main;
22
33 import java.awt.BorderLayout;
4+import java.awt.CardLayout;
5+import java.awt.Desktop;
46 import java.awt.EventQueue;
57 import java.awt.Font;
68 import java.io.IOException;
9+import java.net.URI;
10+import java.net.URISyntaxException;
711 import java.nio.file.Files;
812 import java.nio.file.Paths;
13+import java.text.Normalizer;
914 import java.util.ArrayList;
15+import java.util.HashMap;
16+import java.util.List;
17+import java.util.Map;
1018 import java.util.Random;
1119 import java.util.concurrent.CompletableFuture;
1220 import java.util.concurrent.ExecutorService;
1321 import java.util.concurrent.Executors;
1422 import java.util.function.BiConsumer;
23+import java.util.stream.Collectors;
1524
1625 import javax.swing.DefaultComboBoxModel;
1726 import javax.swing.JButton;
@@ -21,8 +30,10 @@ import javax.swing.JFrame;
2130 import javax.swing.JLabel;
2231 import javax.swing.JOptionPane;
2332 import javax.swing.JPanel;
33+import javax.swing.JProgressBar;
2434 import javax.swing.JScrollPane;
2535 import javax.swing.JSpinner;
36+import javax.swing.JTabbedPane;
2637 import javax.swing.JTextArea;
2738 import javax.swing.border.EmptyBorder;
2839
@@ -35,91 +46,203 @@ import com.jgoodies.forms.layout.FormSpecs;
3546 import com.jgoodies.forms.layout.RowSpec;
3647 import com.ranfa.lib.CheckVersion;
3748 import com.ranfa.lib.Easter;
38-import com.ranfa.lib.EstimateAlbumTypeCycle;
3949 import com.ranfa.lib.ManualUpdateThreadImpl;
40-import com.ranfa.lib.Scraping;
4150 import com.ranfa.lib.SettingJSONProperty;
4251 import com.ranfa.lib.Settings;
43-import com.ranfa.lib.Song;
52+import com.ranfa.lib.Suffix;
4453 import com.ranfa.lib.TwitterIntegration;
4554 import com.ranfa.lib.Version;
46-
47-@Version(major = 3, minor = 1, patch = 1)
55+import com.ranfa.lib.concurrent.CountedThreadFactory;
56+import com.ranfa.lib.database.EstimateAlbumTypeCycle;
57+import com.ranfa.lib.database.Scraping;
58+import com.ranfa.lib.database.Song;
59+import com.ranfa.lib.handler.CrashHandler;
60+import com.ranfa.lib.songinfo.FetchFromAPI;
61+
62+@Version(major = 4, minor = 0, patch = 0, suffix = Suffix.BETA)
4863 public class DelesteRandomSelector extends JFrame {
4964
50- private static ArrayList<Song> selectedSongsList = new ArrayList<>();
51-
52- private JPanel contentPane;
53- private JPanel panelNorth;
54- private JPanel panelWest;
55- private JLabel labelVersion;
56- private JLabel labelTitle;
57- private JLabel labelDifficulty;
58- private JLabel labelLevel;
59- private JSpinner spinnerLevel;
60- private JCheckBox checkMoreLv;
61- private JCheckBox checkLessLv;
62- private JPanel panelEast;
63- private JPanel panelCentre;
64- private JButton btnImport;
65- private JButton btnStart;
66- private JButton btnExit;
67- private JComboBox comboDifficultySelect;
68- private JLabel labelLvCaution;
69- private JComboBox comboAttribute;
70- private SettingJSONProperty property = new SettingJSONProperty();
71- private JButton btnTwitterIntegration;
72- private String[] integratorArray;
73- private boolean integratorBool = false;
74- private JTextArea textArea;
75- private JScrollPane scrollPane;
76- private CompletableFuture<Void> softwareUpdateFuture = null;
77- private CompletableFuture<Void> albumTypeEstimateFuture = null;
78- private String albumType = Messages.MSGAlbumTypeBeingCalculated.toString();
79- private Logger logger = LoggerFactory.getLogger(DelesteRandomSelector.class);
80- private ManualUpdateThreadImpl impl;
81- private Thread manualUpdateThread;
82- private JButton btnManualUpdate;
83- private Easter easter;
84- private JButton btnConfig;
85-
86- /**
87- * Launch the application.
88- */
89- public static void main(String[] args) {
90- EventQueue.invokeLater(() -> {
91- try {
92- DelesteRandomSelector frame = new DelesteRandomSelector();
93- frame.setVisible(true);
94- } catch (Exception e) {
95- e.printStackTrace();
65+ private static ArrayList<Song> selectedSongsList = new ArrayList<>();
66+
67+ private JPanel contentPane;
68+ private SettingJSONProperty property = new SettingJSONProperty();
69+ private String[] integratorArray;
70+ private boolean integratorBool = false;
71+ private CompletableFuture<Void> softwareUpdateFuture = null;
72+ private CompletableFuture<Void> albumTypeEstimateFuture = null;
73+ private String albumType = Messages.MSGAlbumTypeBeingCalculated.toString();
74+ private Logger logger = LoggerFactory.getLogger(DelesteRandomSelector.class);
75+ private ManualUpdateThreadImpl impl;
76+ private List<Song> toolIntegrateList;
77+ private FetchFromAPI fetchData;
78+ private List<Map<String, String>> listToolMapData;
79+ private CompletableFuture<List<Map<String, String>>> listToolMapDataFuture;
80+ private Easter easter;
81+ private JPanel panelMain;
82+ private JPanel panelNorthMain;
83+ private JLabel labelTitle;
84+ private JLabel labelVersion;
85+ private JPanel panelWestMain;
86+ private JLabel labelDifficulty;
87+ private JComboBox<String[]> comboDifficultySelect;
88+ private JComboBox<String[]> comboAttribute;
89+ private JLabel labelLevel;
90+ private JSpinner spinnerLevel;
91+ private JCheckBox checkLessLv;
92+ private JCheckBox checkMoreLv;
93+ private JLabel labelLvCaution;
94+ private JPanel panelEastMain;
95+ private JButton btnImport;
96+ private JButton btnConfig;
97+ private JButton btnStart;
98+ private JButton btnManualUpdate;
99+ private JButton btnTwitterIntegration;
100+ private JButton btnExit;
101+ private JPanel panelCenterMain;
102+ private JScrollPane scrollPane;
103+ private JTextArea textArea;
104+ private JTabbedPane tabbedPane;
105+ private JPanel panelInfo;
106+ private JPanel panelNorthTool;
107+ private JLabel labelSubToolTitle;
108+ private JLabel labelVersionTool;
109+ private JPanel panelCenterTool;
110+ private JLabel labelInfoPlaySongs;
111+ private JLabel labelSongNameToolTitle;
112+ private JLabel labelSongNameToolTip;
113+ private JLabel labelAttributeToolTitle;
114+ private JLabel labelAttributeToolTip;
115+ private JLabel labelDifficultyToolTitle;
116+ private JLabel labelDifficultyToolTip;
117+ private JLabel labelLevelToolTitle;
118+ private JLabel labelLevelToolTip;
119+ private JLabel labelNotesToolTitle;
120+ private JLabel labelNotesToolTip;
121+ private JButton btnPrevSongTool;
122+ private JButton btnNextSongTool;
123+ private JLabel labelSlashTool;
124+ private JLabel labelCurrentSongOrderTool;
125+ private JLabel labelSongLimitTool;
126+ private JLabel labelLyricToolTitle;
127+ private JLabel labelLyricToolTip;
128+ private JLabel labelComposerToolTitle;
129+ private JLabel labelArrangeToolTitle;
130+ private JLabel labelComposerToolTip;
131+ private JLabel labelArrangeToolTip;
132+ private JLabel labelMemberToolTitle;
133+ private JLabel labelMemberToolTip;
134+ private JButton btnMoreInfoTool;
135+
136+ BiConsumer<ArrayList<Song>, ArrayList<Song>> updateConsumer = (list1, list2) -> {
137+ this.logger.info("Checking database updates...");
138+ if(list1.size() > list2.size()) {
139+ long time = System.currentTimeMillis();
140+ this.logger.info("{} Update detected.", (list1.size() - list2.size()));
141+ Scraping.writeToJson(list1);
142+ this.logger.info("Update completed in {} ms", (System.currentTimeMillis() - time));
143+ this.logger.info("Updated database size: {}", list1.size());
144+ } else {
145+ this.logger.info("database is up-to-date.");
146+ }
147+ };
148+ Runnable setEnabled = () -> {
149+ try {
150+ Thread.sleep(3 * 1000L);
151+ } catch (InterruptedException e1) {
152+ this.logger.error("Thread has been interrupted during waiting cooldown.", e1);
153+ }
154+ this.btnImport.setEnabled(true);
155+ this.btnImport.setText(Messages.MSGNarrowingDownSongs.toString());
156+ };
157+ private JLabel labelToolProgress;
158+ public static JProgressBar progressTool;
159+ public static JLabel labelInfoProgressSongName;
160+ private JPanel panelScore;
161+ private JPanel panelScoreNorth;
162+ private JPanel panelScoreCenter;
163+ private JLabel labelScoreTitle;
164+ private JLabel labelScoreVersion;
165+
166+ /**
167+ * Launch the application.
168+ */
169+ public static void main(String[] args) {
170+ EventQueue.invokeLater(() -> {
171+ try {
172+ DelesteRandomSelector frame = new DelesteRandomSelector();
173+ frame.setVisible(true);
174+ } catch (Exception e) {
175+ e.printStackTrace();
176+ }
177+
178+ });
179+ }
180+
181+ /**
182+ * log file prefix:
183+ * this.getClass() + ":[LEVEL]: " +
184+ */
185+
186+ /**
187+ * Create the frame.
188+ */
189+ public DelesteRandomSelector() {
190+ ExecutorService es = Executors.newCachedThreadPool(new CountedThreadFactory(() -> "DRS", "AsyncEventInquerier", false));
191+ this.contentPane = new JPanel();
192+ // output system info phase
193+ CompletableFuture.runAsync(() -> {
194+ CrashHandler handle = new CrashHandler();
195+ handle.outSystemInfo();
196+ }, es).whenCompleteAsync((ret, ex) -> {
197+ if(ex != null) {
198+ logger.error("Exception was thrown during concurrent process", ex);
199+ CrashHandler handle = new CrashHandler(ex);
200+ if(ex instanceof NullPointerException) {
201+ handle.execute();
96202 }
97- });
98- }
99-
100- /**
101- * log file prefix:
102- * this.getClass() + ":[LEVEL]: " +
103- */
104-
105- /**
106- * Create the frame.
107- */
108- public DelesteRandomSelector() {
109- boolean isFirst = !Scraping.databaseExists();
203+ handle = new CrashHandler(new IllegalStateException(ex));
204+ handle.execute();
205+ }
206+ }, es);
207+ boolean isFirst = !Scraping.databaseExists();
208+ // database check phase
209+ CompletableFuture.runAsync(() -> {
110210 if(isFirst) {
111- JOptionPane.showMessageDialog(this, Messages.MSGDatabaseNotExist.toString());
112- if(!Scraping.writeToJson(Scraping.getWholeData())) {
113- JOptionPane.showMessageDialog(this, "Exception:NullPointerException\nCannot Keep up! Please re-download this Application!");
114- throw new NullPointerException("FATAL: cannot continue!");
211+ JOptionPane.showMessageDialog(this, Messages.MSGDatabaseNotExist.toString());
212+ if(!Scraping.writeToJson(Scraping.getWholeData())) {
213+ JOptionPane.showMessageDialog(this, "Exception:NullPointerException\nCannot Keep up! Please re-download this Application!");
214+ throw new NullPointerException("FATAL: cannot continue!");
215+ }
216+ }
217+ }, es).whenCompleteAsync((ret, ex) -> {
218+ if(ex != null) {
219+ logger.error("Exception was thrown during concurrent process", ex);
220+ CrashHandler handle = new CrashHandler(ex);
221+ if(ex instanceof NullPointerException) {
222+ handle.execute();
115223 }
224+ handle = new CrashHandler(new IllegalStateException(ex));
225+ handle.execute();
116226 }
117- ExecutorService es = Executors.newWorkStealingPool();
118- CompletableFuture<ArrayList<Song>> getFromJsonFuture = CompletableFuture.supplyAsync(() -> Scraping.getFromJson(), es);
119- CompletableFuture<ArrayList<Song>> getWholeDataFuture = CompletableFuture.supplyAsync(() -> Scraping.getWholeData(), es);
227+ }, es);
228+ CompletableFuture<ArrayList<Song>> getFromJsonFuture = CompletableFuture.supplyAsync(() -> Scraping.getFromJson(), es);
229+ CompletableFuture<ArrayList<Song>> getWholeDataFuture = CompletableFuture.supplyAsync(() -> Scraping.getWholeData(), es);
230+ // setting check phase
231+ CompletableFuture.runAsync(() -> {
120232 if(!Settings.fileExists() && !Settings.writeDownJSON()) {
121- JOptionPane.showMessageDialog(this, "Exception:NullPointerException\nCannot Keep up! Please re-download this Application!");
122- throw new NullPointerException("FATAL: cannot continue!");
233+ JOptionPane.showMessageDialog(this, "Exception:NullPointerException\nPlease see crash report for more detail.");
234+ CrashHandler handle = new CrashHandler("Failed to generate setting file.", new NullPointerException("FATAL: cannot continue!"));
235+ handle.execute();
236+ }
237+ }, es).whenCompleteAsync((ret, ex) -> {
238+ if(ex != null) {
239+ logger.error("Exception was thrown during concurrent process", ex);
240+ CrashHandler handle = new CrashHandler(ex);
241+ if(ex instanceof NullPointerException) {
242+ handle.execute();
243+ }
244+ handle = new CrashHandler(new IllegalStateException(ex));
245+ handle.execute();
123246 }
124247 this.logger.debug("Loading settings...");
125248 this.property.setCheckLibraryUpdates(Settings.needToCheckLibraryUpdates());
@@ -135,152 +258,141 @@ public class DelesteRandomSelector extends JFrame {
135258 this.logger.debug("Window Height: {}", this.property.getWindowHeight());
136259 this.logger.debug("Song Limit: {}", this.property.getSongLimit());
137260 this.logger.debug("SaveScoreLog: {}", this.property.isSaveScoreLog());
138- EstimateAlbumTypeCycle.Initialization();
139- if(Files.exists(Paths.get("generated/albumCycle.json"))) {
140- this.albumType = EstimateAlbumTypeCycle.getCurrentCycle();
141- }
261+ this.setBounds(100, 100, this.property.getWindowWidth(), this.property.getWindowHeight());
142262 if(this.property.isCheckVersion()) {
143- this.softwareUpdateFuture = CompletableFuture.runAsync(() -> CheckVersion.needToBeUpdated(), es);
263+ this.softwareUpdateFuture = CompletableFuture.runAsync(() -> CheckVersion.needToBeUpdated(), es);
144264 }
145- BiConsumer<ArrayList<Song>, ArrayList<Song>> updateConsumer = (list1, list2) -> {
146- this.logger.info("Checking database updates...");
147- if(list1.size() > list2.size()) {
148- long time = System.currentTimeMillis();
149- this.logger.info("{} Update detected.", (list1.size() - list2.size()));
150- Scraping.writeToJson(list1);
151- this.logger.info("Update completed in {} ms", (System.currentTimeMillis() - time));
152- this.logger.info("Updated database size: {}", list1.size());
153- } else {
154- this.logger.info("database is up-to-date.");
155- }
156- };
157- Runnable setEnabled = () -> {
158- try {
159- Thread.sleep(3 * 1000L);
160- } catch (InterruptedException e1) {
161- this.logger.error("Thread has been interrupted during waiting cooldown.", e1);
162- }
163- this.btnImport.setEnabled(true);
164- this.btnImport.setText(Messages.MSGNarrowingDownSongs.toString());
165- };
166- getWholeDataFuture.thenAcceptAsync(list -> this.logger.info("Scraping data size:" + list.size()), es);
167- getFromJsonFuture.thenAcceptAsync(list -> this.logger.info("Currently database size:" + list.size()), es);
168265 if(this.property.isCheckLibraryUpdates()) {
169- CompletableFuture<Void> updatedFuture = getWholeDataFuture.thenAcceptBothAsync(getFromJsonFuture, updateConsumer, es);
170- updatedFuture.thenRunAsync(setEnabled, es);
266+ CompletableFuture<Void> updatedFuture = getWholeDataFuture.thenAcceptBothAsync(getFromJsonFuture, updateConsumer, es);
267+ updatedFuture.thenRunAsync(setEnabled, es);
268+ }
269+ }, es);
270+ CompletableFuture.runAsync(() -> {
271+ EstimateAlbumTypeCycle.Initialization();
272+ if(Files.exists(Paths.get("generated/albumCycle.json"))) {
273+ this.albumType = EstimateAlbumTypeCycle.getCurrentCycle();
274+ }
275+ }, es).whenCompleteAsync((ret, ex) -> {
276+ if(ex != null) {
277+ logger.error("Exception was thrown during concurrent process", ex);
278+ CrashHandler handle = new CrashHandler(new IllegalStateException(ex));
279+ handle.execute();
171280 }
281+ }, es);
282+ getWholeDataFuture.thenAcceptAsync(list -> this.logger.info("Scraping data size:" + list.size()), es);
283+ getFromJsonFuture.thenAcceptAsync(list -> this.logger.info("Currently database size:" + list.size()), es);
284+ // easter phase
285+ CompletableFuture.runAsync(() -> {
172286 this.easter = new Easter();
173287 this.setTitle(this.easter.getTodaysBirth());
174- this.logger.debug("Version: {}", CheckVersion.getVersion());
175- this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
176- this.setBounds(100, 100, this.property.getWindowWidth(), this.property.getWindowHeight());
177- // this.setBounds(100, 100, 640, 360);
178- this.contentPane = new JPanel();
179- this.contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
180- this.setContentPane(this.contentPane);
181- this.contentPane.setLayout(new BorderLayout(0, 0));
182-
183- this.panelNorth = new JPanel();
184- this.contentPane.add(this.panelNorth, BorderLayout.NORTH);
185- this.panelNorth.setLayout(new FormLayout(new ColumnSpec[] {
186- ColumnSpec.decode("max(302dlu;default)"),
187- FormSpecs.RELATED_GAP_COLSPEC,
188- ColumnSpec.decode("40px"),},
189- new RowSpec[] {
190- RowSpec.decode("20px"),}));
191-
192- this.labelTitle = new JLabel(Messages.MSGTitle.toString());
193- this.labelTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 16));
194- this.panelNorth.add(this.labelTitle, "1, 1, center, top");
195-
196- this.labelVersion = new JLabel(CheckVersion.getVersion());
197- this.labelVersion.setFont(new Font("SansSerif", Font.BOLD, 12));
198- this.panelNorth.add(this.labelVersion, "3, 1, right, top");
199-
200- this.panelWest = new JPanel();
201- this.contentPane.add(this.panelWest, BorderLayout.WEST);
202- this.panelWest.setLayout(new FormLayout(new ColumnSpec[] {
203- FormSpecs.LABEL_COMPONENT_GAP_COLSPEC,
204- ColumnSpec.decode("112px:grow"),},
205- new RowSpec[] {
206- FormSpecs.LINE_GAP_ROWSPEC,
207- RowSpec.decode("19px"),
208- FormSpecs.RELATED_GAP_ROWSPEC,
209- RowSpec.decode("max(12dlu;default)"),
210- FormSpecs.RELATED_GAP_ROWSPEC,
211- RowSpec.decode("max(12dlu;default)"),
212- FormSpecs.RELATED_GAP_ROWSPEC,
213- RowSpec.decode("12dlu"),
214- FormSpecs.RELATED_GAP_ROWSPEC,
215- RowSpec.decode("max(12dlu;default)"),
216- FormSpecs.RELATED_GAP_ROWSPEC,
217- RowSpec.decode("max(12dlu;default)"),
218- FormSpecs.RELATED_GAP_ROWSPEC,
219- RowSpec.decode("max(12dlu;default)"),
220- FormSpecs.RELATED_GAP_ROWSPEC,
221- RowSpec.decode("max(52dlu;default)"),}));
222-
223- this.labelDifficulty = new JLabel(Messages.MSGSelectDifficulty.toString());
224- this.labelDifficulty.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
225- this.panelWest.add(this.labelDifficulty, "2, 2, center, default");
226-
227- this.comboDifficultySelect = new JComboBox();
228- this.comboDifficultySelect.setFont(new Font("Dialog", Font.BOLD, 12));
229- this.comboDifficultySelect.setModel(new DefaultComboBoxModel(new String[] {Messages.MSGNonSelected.toString(), "DEBUT", "REGULAR", "PRO", "MASTER", "MASTER+", "ⓁMASTER+", "LIGHT", "TRICK", "PIANO", "FORTE", "WITCH"}));
230- this.panelWest.add(this.comboDifficultySelect, "2, 4, fill, default");
231-
232- this.comboAttribute = new JComboBox();
233- this.comboAttribute.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
234- this.comboAttribute.setModel(new DefaultComboBoxModel(new String[] {Messages.MSGNonSelected.toString(), "全タイプ", "キュート", "クール", "パッション"}));
235- this.panelWest.add(this.comboAttribute, "2, 6, fill, default");
236-
237- this.labelLevel = new JLabel(Messages.MSGSongLevel.toString());
238- this.labelLevel.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
239- this.panelWest.add(this.labelLevel, "2, 8, center, default");
240-
241- this.spinnerLevel = new JSpinner();
242- this.panelWest.add(this.spinnerLevel, "2, 10");
243-
244- this.checkLessLv = new JCheckBox(Messages.MSGBelowSpecificLevel.toString());
245- this.checkLessLv.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
246- this.panelWest.add(this.checkLessLv, "2, 12");
247-
248- this.checkMoreLv = new JCheckBox(Messages.MSGOverSpecificLevel.toString());
249- this.checkMoreLv.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
250- this.panelWest.add(this.checkMoreLv, "2, 14");
251-
252- this.labelLvCaution = new JLabel(Messages.MSGLevelCheckboxInfo.toString());
253- this.labelLvCaution.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
254- this.panelWest.add(this.labelLvCaution, "2, 16, fill, fill");
255-
256- this.panelEast = new JPanel();
257- this.contentPane.add(this.panelEast, BorderLayout.EAST);
258- this.panelEast.setLayout(new FormLayout(new ColumnSpec[] {
259- ColumnSpec.decode("98px"),},
260- new RowSpec[] {
261- RowSpec.decode("26px"),
262- FormSpecs.RELATED_GAP_ROWSPEC,
263- RowSpec.decode("max(36dlu;default)"),
264- FormSpecs.RELATED_GAP_ROWSPEC,
265- FormSpecs.DEFAULT_ROWSPEC,
266- FormSpecs.RELATED_GAP_ROWSPEC,
267- RowSpec.decode("max(30dlu;default)"),
268- FormSpecs.RELATED_GAP_ROWSPEC,
269- RowSpec.decode("max(15dlu;default)"),
270- FormSpecs.RELATED_GAP_ROWSPEC,
271- RowSpec.decode("max(11dlu;default)"),
272- FormSpecs.RELATED_GAP_ROWSPEC,
273- FormSpecs.DEFAULT_ROWSPEC,
274- FormSpecs.RELATED_GAP_ROWSPEC,
275- FormSpecs.DEFAULT_ROWSPEC,
276- FormSpecs.RELATED_GAP_ROWSPEC,
277- FormSpecs.DEFAULT_ROWSPEC,}));
278-
279- this.btnImport = new JButton(Messages.MSGUpdatingDatabase.toString());
280- this.btnImport.setEnabled(false);
281- this.btnImport.addActionListener(e -> {
282- if(this.impl != null) {
283- if(!this.impl.getFlag()) {
288+ }, es);
289+ this.logger.debug("Version: {}", CheckVersion.getVersion());
290+ this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
291+ // this.setBounds(100, 100, 960, 643);
292+ this.contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
293+ this.setContentPane(this.contentPane);
294+ contentPane.setLayout(new CardLayout(0, 0));
295+
296+ panelMain = new JPanel();
297+ panelMain.setLayout(new BorderLayout(0, 0));
298+
299+ panelNorthMain = new JPanel();
300+ panelMain.add(panelNorthMain, BorderLayout.NORTH);
301+ panelNorthMain.setLayout(new FormLayout(new ColumnSpec[] {
302+ ColumnSpec.decode("829px"),
303+ FormSpecs.LABEL_COMPONENT_GAP_COLSPEC,
304+ ColumnSpec.decode("center:94px"),},
305+ new RowSpec[] {
306+ RowSpec.decode("20px"),}));
307+
308+ labelTitle = new JLabel(Messages.MSGTitle.toString());
309+ labelTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 16));
310+ panelNorthMain.add(labelTitle, "1, 1, center, top");
311+
312+ labelVersion = new JLabel(CheckVersion.getVersion());
313+ labelVersion.setFont(new Font("SansSerif", Font.BOLD, 12));
314+ panelNorthMain.add(labelVersion, "3, 1, center, center");
315+
316+ panelWestMain = new JPanel();
317+ panelMain.add(panelWestMain, BorderLayout.WEST);
318+ panelWestMain.setLayout(new FormLayout(new ColumnSpec[] {
319+ FormSpecs.LABEL_COMPONENT_GAP_COLSPEC,
320+ ColumnSpec.decode("120px"),},
321+ new RowSpec[] {
322+ FormSpecs.LINE_GAP_ROWSPEC,
323+ RowSpec.decode("25px"),
324+ FormSpecs.RELATED_GAP_ROWSPEC,
325+ FormSpecs.DEFAULT_ROWSPEC,
326+ FormSpecs.RELATED_GAP_ROWSPEC,
327+ FormSpecs.DEFAULT_ROWSPEC,
328+ FormSpecs.RELATED_GAP_ROWSPEC,
329+ FormSpecs.DEFAULT_ROWSPEC,
330+ FormSpecs.RELATED_GAP_ROWSPEC,
331+ FormSpecs.DEFAULT_ROWSPEC,
332+ FormSpecs.RELATED_GAP_ROWSPEC,
333+ FormSpecs.DEFAULT_ROWSPEC,
334+ FormSpecs.RELATED_GAP_ROWSPEC,
335+ FormSpecs.DEFAULT_ROWSPEC,
336+ FormSpecs.RELATED_GAP_ROWSPEC,
337+ RowSpec.decode("max(41dlu;default)"),}));
338+
339+ labelDifficulty = new JLabel(Messages.MSGSelectDifficulty.toString());
340+ labelDifficulty.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
341+ panelWestMain.add(labelDifficulty, "2, 2, center, center");
342+
343+ comboDifficultySelect = new JComboBox<>();
344+ comboDifficultySelect.setModel(new DefaultComboBoxModel(new String[] {Messages.MSGNonSelected.toString(), "DEBUT", "REGULAR", "PRO", "MASTER", "MASTER+", "ⓁMASTER+", "LIGHT", "TRICK", "PIANO", "FORTE", "WITCH"}));
345+ comboDifficultySelect.setFont(new Font("Dialog", Font.BOLD, 12));
346+ panelWestMain.add(comboDifficultySelect, "2, 4, fill, fill");
347+
348+ comboAttribute = new JComboBox<>();
349+ comboAttribute.setModel(new DefaultComboBoxModel(new String[] {Messages.MSGNonSelected.toString(), "全タイプ", "キュート", "クール", "パッション"}));
350+ comboAttribute.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
351+ panelWestMain.add(comboAttribute, "2, 6, fill, top");
352+
353+ labelLevel = new JLabel(Messages.MSGSongLevel.toString());
354+ labelLevel.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
355+ panelWestMain.add(labelLevel, "2, 8, center, center");
356+
357+ spinnerLevel = new JSpinner();
358+ panelWestMain.add(spinnerLevel, "2, 10, fill, center");
359+
360+ checkLessLv = new JCheckBox(Messages.MSGBelowSpecificLevel.toString());
361+ checkLessLv.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
362+ panelWestMain.add(checkLessLv, "2, 12, left, top");
363+
364+ checkMoreLv = new JCheckBox(Messages.MSGOverSpecificLevel.toString());
365+ checkMoreLv.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
366+ panelWestMain.add(checkMoreLv, "2, 14, left, top");
367+
368+ labelLvCaution = new JLabel(Messages.MSGLevelCheckboxInfo.toString());
369+ labelLvCaution.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
370+ panelWestMain.add(labelLvCaution, "2, 16, left, center");
371+
372+ panelEastMain = new JPanel();
373+ panelMain.add(panelEastMain, BorderLayout.EAST);
374+ panelEastMain.setLayout(new FormLayout(new ColumnSpec[] {
375+ FormSpecs.LABEL_COMPONENT_GAP_COLSPEC,
376+ ColumnSpec.decode("100px"),},
377+ new RowSpec[] {
378+ FormSpecs.LINE_GAP_ROWSPEC,
379+ RowSpec.decode("77px"),
380+ FormSpecs.RELATED_GAP_ROWSPEC,
381+ FormSpecs.DEFAULT_ROWSPEC,
382+ FormSpecs.RELATED_GAP_ROWSPEC,
383+ FormSpecs.DEFAULT_ROWSPEC,
384+ FormSpecs.RELATED_GAP_ROWSPEC,
385+ FormSpecs.DEFAULT_ROWSPEC,
386+ FormSpecs.RELATED_GAP_ROWSPEC,
387+ RowSpec.decode("max(36dlu;default)"),
388+ FormSpecs.RELATED_GAP_ROWSPEC,
389+ FormSpecs.DEFAULT_ROWSPEC,}));
390+
391+ btnImport = new JButton(Messages.MSGUpdatingDatabase.toString());
392+ btnImport.addActionListener(e -> {
393+ CompletableFuture.runAsync(() -> {
394+ if(impl != null) {
395+ if(!impl.getFlag()) {
284396 JOptionPane.showMessageDialog(null, Messages.MSGManualUpdateNotCompleteYet.toString());
285397 }
286398 }
@@ -295,44 +407,109 @@ public class DelesteRandomSelector extends JFrame {
295407 selectedSongsList.addAll((DelesteRandomSelector.this.comboDifficultySelect.getSelectedItem().equals(Scraping.MASTERPLUS) || DelesteRandomSelector.this.comboDifficultySelect.getSelectedItem().equals(Scraping.LEGACYMASTERPLUS)) ? specificTypeList : specificAttributeList);
296408 DelesteRandomSelector.this.logger.info("Songs are selected.We are Ready to go.");
297409 JOptionPane.showMessageDialog(null, Messages.MSGCompleteNarrowDown.toString());
298- });
299- this.btnImport.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
300- this.panelEast.add(this.btnImport, "1, 3, fill, fill");
301-
302- this.btnStart = new JButton(Messages.MSGCalcStart.toString());
303- this.btnStart.addActionListener(e -> {
410+ }, es).whenCompleteAsync((ret, ex) -> {
411+ if(ex != null) {
412+ logger.error("Exception was thrown during concurrent process", ex);
413+ CrashHandler handle = new CrashHandler(new IllegalStateException(ex));
414+ handle.execute();
415+ }
416+ }, es);
417+ });
418+ btnImport.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
419+ btnImport.setEnabled(false);
420+ panelEastMain.add(btnImport, "2, 2, fill, fill");
421+
422+ btnConfig = new JButton(Messages.MSGConfigurations.toString());
423+ btnConfig.addActionListener(e -> {
424+ CompletableFuture.runAsync(() -> {
425+ ProcessBuilder builder = new ProcessBuilder("java", "-jar", "Configurations.jar");
426+ try {
427+ builder.start();
428+ } catch (IOException e1) {
429+ logger.error("Exception was thrown during concurrent process", e1);
430+ CrashHandler handle = new CrashHandler(new IllegalStateException(e1));
431+ handle.execute();
432+ }
433+ }, es).whenCompleteAsync((ret, ex) -> {
434+ if(ex != null) {
435+ logger.error("Exception was thrown during concurrent process", ex);
436+ CrashHandler handle = new CrashHandler(new IllegalStateException(ex));
437+ handle.execute();
438+ }
439+ }, es);
440+ });
441+ panelEastMain.add(btnConfig, "2, 6, fill, fill");
442+
443+ btnStart = new JButton(Messages.MSGCalcStart.toString());
444+ btnStart.addActionListener(e -> {
445+ CompletableFuture.runAsync(() -> {
304446 Random random = new Random(System.currentTimeMillis());
305- String paneString = "";
447+ toolIntegrateList = new ArrayList<>();
448+ StringBuilder paneBuilder = new StringBuilder();
306449 DelesteRandomSelector.this.integratorArray = new String[DelesteRandomSelector.this.property.getSongLimit()];
307450 for(int i = 0; i < DelesteRandomSelector.this.property.getSongLimit(); i++) {
308451 int randomInt = random.nextInt(selectedSongsList.size());
309452 String typeString = DelesteRandomSelector.this.comboDifficultySelect.getSelectedItem().equals(Scraping.MASTERPLUS) || DelesteRandomSelector.this.comboDifficultySelect.getSelectedItem().equals(Scraping.LEGACYMASTERPLUS) ? EstimateAlbumTypeCycle.getCurrentCycle() : "";
310- paneString = paneString + (i + 1) + Messages.MSGNumberOfSongs.toString() + " " + selectedSongsList.get(randomInt).getAttribute() + " [" + selectedSongsList.get(randomInt).getDifficulty() + "]「" + selectedSongsList.get(randomInt).getName() + "」!(Lv:" + selectedSongsList.get(randomInt).getLevel() + " " + typeString + ")\n\n";
311- DelesteRandomSelector.this.integratorArray[i] = selectedSongsList.get(randomInt).getName() + "(Lv" + selectedSongsList.get(randomInt).getLevel() + ")\n";
453+ paneBuilder.append(i + 1)
454+ .append(Messages.MSGNumberOfSongs.toString())
455+ .append(" ")
456+ .append(selectedSongsList.get(randomInt).getAttribute())
457+ .append("[")
458+ .append(selectedSongsList.get(randomInt).getDifficulty())
459+ .append("]「")
460+ .append(selectedSongsList.get(randomInt).getName())
461+ .append("」!(Lv:")
462+ .append(selectedSongsList.get(randomInt).getLevel())
463+ .append(" ")
464+ .append(typeString)
465+ .append(")\n\n");
466+ this.integratorArray[i] = selectedSongsList.get(randomInt).getName() + "(Lv" + selectedSongsList.get(randomInt).getLevel() + ")\n";
467+ toolIntegrateList.add(selectedSongsList.get(randomInt));
312468 }
313- paneString = paneString + Messages.MSGThisPhrase.toString() + DelesteRandomSelector.this.property.getSongLimit() + Messages.MSGPlayPhrase.toString();
314- DelesteRandomSelector.this.textArea.setText(paneString);
469+ paneBuilder.append(Messages.MSGThisPhrase.toString())
470+ .append(this.property.getSongLimit())
471+ .append(Messages.MSGPlayPhrase.toString());
472+ DelesteRandomSelector.this.textArea.setText(paneBuilder.toString());
315473 DelesteRandomSelector.this.integratorBool = true;
316474 DelesteRandomSelector.this.logger.info("show up completed.");
317- });
318-
319- this.btnConfig = new JButton(Messages.MSGConfigurations.toString());
320- this.btnConfig.addActionListener(e -> {
321- ProcessBuilder builder = new ProcessBuilder("java", "-jar", "Configurations.jar");
322- try {
323- builder.start();
324- } catch (IOException e1) {
325- // TODO 自動生成された catch ブロック
326- e1.printStackTrace();
475+ labelCurrentSongOrderTool.setText("null");
476+ progressTool.setValue(0);
477+ listToolMapDataFuture = CompletableFuture.supplyAsync(() -> {
478+ List<String> data = toolIntegrateList.stream()
479+ .map(s -> s.getName())
480+ .collect(Collectors.toList());
481+ fetchData = new FetchFromAPI(data.toArray(new String[0]));
482+ return fetchData.getInformation();
483+ }, es);
484+ logger.debug("api fetch inquery published");
485+ }, es).whenCompleteAsync((ret, ex) -> {
486+ if(ex != null) {
487+ logger.error("Exception was thrown during concurrent process", ex);
488+ CrashHandler handle = new CrashHandler(new IllegalStateException(ex));
489+ handle.execute();
327490 }
328- });
329- this.panelEast.add(this.btnConfig, "1, 5");
330- this.btnStart.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
331- this.panelEast.add(this.btnStart, "1, 7, fill, fill");
332-
333- this.btnTwitterIntegration = new JButton(Messages.MSGTwitterIntegration.toString());
334- this.btnTwitterIntegration.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 11));
335- this.btnTwitterIntegration.addActionListener(e -> {
491+ }, es);
492+ });
493+ btnStart.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
494+ panelEastMain.add(btnStart, "2, 4, fill, fill");
495+
496+ btnManualUpdate = new JButton(Messages.MSGManualUpdate.toString());
497+ btnManualUpdate.addActionListener(e -> {
498+ impl = new ManualUpdateThreadImpl();
499+ CompletableFuture.runAsync(impl, es).whenCompleteAsync((t, u) -> {
500+ if(u != null) {
501+ logger.warn("Exception while processing update manually.", u);
502+ CrashHandler handle = new CrashHandler(new IllegalStateException(u));
503+ handle.execute();
504+ JOptionPane.showMessageDialog(null, "There was a problem during processing library update manually.\nIf this appears repeatedly, please contact developer with your app log.");
505+ }
506+ }, es);
507+ });
508+ panelEastMain.add(btnManualUpdate, "2, 8, fill, fill");
509+
510+ btnTwitterIntegration = new JButton(Messages.MSGTwitterIntegration.toString());
511+ btnTwitterIntegration.addActionListener(e -> {
512+ CompletableFuture.runAsync(() -> {
336513 boolean authorizationStatus = TwitterIntegration.authorization();
337514 String updatedStatus = Messages.MSGUsingThisAppPhrase.toString();
338515 int lengthLimit = updatedStatus.length();
@@ -377,43 +554,412 @@ public class DelesteRandomSelector extends JFrame {
377554 } else {
378555 DelesteRandomSelector.this.logger.info("seems to reject the permission.it should need try again.");
379556 }
380- });
381-
382- this.btnManualUpdate = new JButton(Messages.MSGManualUpdate.toString());
383- this.btnManualUpdate.addActionListener(e -> {
384- this.impl = new ManualUpdateThreadImpl();
385- es.submit(this.impl);
386- });
387- this.panelEast.add(this.btnManualUpdate, "1, 9");
388- this.panelEast.add(this.btnTwitterIntegration, "1, 11");
389-
390- this.btnExit = new JButton(Messages.MSGTerminate.toString());
391- this.btnExit.addActionListener(e -> {
392- if(DelesteRandomSelector.this.softwareUpdateFuture.isDone() || DelesteRandomSelector.this.albumTypeEstimateFuture.isDone() || !this.impl.getFlag()) {
393- DelesteRandomSelector.this.logger.info("Requested Exit by Button.");
394- this.logger.info("Shut down thread pool.");
395- es.shutdown();
396- System.exit(0);
397- } else {
398- JOptionPane.showMessageDialog(null, Messages.MSGInternalYpdateNotDoneYet.toString());
557+ }, es).whenCompleteAsync((ret, ex) -> {
558+ if(ex != null) {
559+ logger.error("Exception was thrown during concurrent process", ex);
560+ CrashHandler handle = new CrashHandler(new IllegalStateException(ex));
561+ handle.execute();
399562 }
400- });
401- this.btnExit.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
402- this.panelEast.add(this.btnExit, "1, 13");
403-
404- this.panelCentre = new JPanel();
405- this.contentPane.add(this.panelCentre, BorderLayout.CENTER);
406- this.panelCentre.setLayout(new BorderLayout(0, 0));
407-
408- this.textArea = new JTextArea();
409- this.textArea.setText(Messages.MSGNarrowDownProcedure.toString() + this.property.getSongLimit() + Messages.MSGCurrentAlbumType.toString() + this.albumType);
410- this.textArea.setEditable(false);
411-
412- this.scrollPane = new JScrollPane(this.textArea);
413- this.panelCentre.add(this.scrollPane, BorderLayout.CENTER);
414- if(isFirst || !this.property.isCheckLibraryUpdates()) {
415- setEnabled.run();
563+ }, es);
564+ });
565+ btnTwitterIntegration.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 11));
566+ panelEastMain.add(btnTwitterIntegration, "2, 10, fill, fill");
567+
568+ btnExit = new JButton(Messages.MSGTerminate.toString());
569+ btnExit.addActionListener(e -> {
570+ if(DelesteRandomSelector.this.softwareUpdateFuture.isDone() || DelesteRandomSelector.this.albumTypeEstimateFuture.isDone() || !this.impl.getFlag()) {
571+ DelesteRandomSelector.this.logger.info("Requested Exit by Button.");
572+ logger.info("Shut down thread pool.");
573+ es.shutdown();
574+ System.exit(0);
575+ } else {
576+ JOptionPane.showMessageDialog(null, Messages.MSGInternalYpdateNotDoneYet.toString());
416577 }
578+ });
579+ btnExit.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
580+ panelEastMain.add(btnExit, "2, 12, fill, fill");
581+
582+ panelCenterMain = new JPanel();
583+ panelMain.add(panelCenterMain, BorderLayout.CENTER);
584+ panelCenterMain.setLayout(new BorderLayout(0, 0));
585+
586+ scrollPane = new JScrollPane();
587+ panelCenterMain.add(scrollPane);
588+
589+ textArea = new JTextArea();
590+ textArea.setText(Messages.MSGNarrowDownProcedure.toString() + property.getSongLimit() + Messages.MSGCurrentAlbumType.toString() + albumType);
591+ textArea.setEditable(false);
592+ scrollPane.setViewportView(textArea);
593+
594+ tabbedPane = new JTabbedPane(JTabbedPane.TOP);
595+ tabbedPane.addChangeListener(e -> {
596+ CompletableFuture.runAsync(() -> {
597+ labelToolProgress.setText(Messages.MSGAPIWaitAPIFetch.toString());
598+ String currentTabName = tabbedPane.getTitleAt(tabbedPane.getSelectedIndex());
599+ if(currentTabName.equals("SongInfo") && labelCurrentSongOrderTool.getText().equals("null")) {
600+ logger.info("Detected switching tool tab");
601+ listToolMapData = listToolMapDataFuture.join();
602+ if(toolIntegrateList == null) {
603+ return;
604+ }
605+ Song firstSong = toolIntegrateList.get(0);
606+ Map<String, String> fetchMap = new HashMap<>();
607+ for(Map<String, String> tmpMap : listToolMapData) {
608+ String normalizeApiName = Normalizer.normalize(tmpMap.get("songname").toString(), Normalizer.Form.NFKD);
609+ String normalizeLocalName = Normalizer.normalize(firstSong.getName(), Normalizer.Form.NFKD);
610+ if(normalizeApiName.equals(normalizeLocalName)) {
611+ fetchMap = tmpMap;
612+ break;
613+ }
614+ }
615+ labelSongNameToolTip.setText(firstSong.getName());
616+ labelAttributeToolTip.setText(firstSong.getAttribute());
617+ labelDifficultyToolTip.setText(firstSong.getDifficulty());
618+ labelLevelToolTip.setText(String.valueOf(firstSong.getLevel()));
619+ labelNotesToolTip.setText(String.valueOf(firstSong.getNotes()));
620+ labelCurrentSongOrderTool.setText("1");
621+ labelLyricToolTip.setText(fetchMap.get("lyric"));
622+ labelComposerToolTip.setText(fetchMap.get("composer"));
623+ labelArrangeToolTip.setText(fetchMap.get("arrange"));
624+ labelMemberToolTip.setText("<html><body>" + fetchMap.get("member") + "</html></body>");
625+ }
626+ }, es).whenCompleteAsync((ret, ex) -> {
627+ labelToolProgress.setText("Information parse Complete.");
628+ if(ex != null) {
629+ logger.error("Exception was thrown during concurrent process", ex);
630+ CrashHandler handle = new CrashHandler(new IllegalStateException(ex));
631+ handle.execute();
632+ }
633+ }, es);
634+ });
635+ tabbedPane.addTab("Main", null, panelMain, null);
636+ contentPane.add(tabbedPane, "name_307238585319500");
637+
638+ panelInfo = new JPanel();
639+ tabbedPane.addTab("SongInfo", null, panelInfo, null);
640+ panelInfo.setLayout(new BorderLayout(0, 0));
641+
642+ panelNorthTool = new JPanel();
643+ panelInfo.add(panelNorthTool, BorderLayout.NORTH);
644+ panelNorthTool.setLayout(new FormLayout(new ColumnSpec[] {
645+ ColumnSpec.decode("center:max(524dlu;default)"),
646+ FormSpecs.RELATED_GAP_COLSPEC,
647+ ColumnSpec.decode("max(30dlu;default)"),},
648+ new RowSpec[] {
649+ RowSpec.decode("max(16dlu;default)"),}));
650+
651+ labelSubToolTitle = new JLabel("楽曲情報");
652+ labelSubToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 16));
653+ panelNorthTool.add(labelSubToolTitle, "1, 1");
654+
655+ labelVersionTool = new JLabel(CheckVersion.getVersion());
656+ labelVersionTool.setFont(new Font("SansSerif", Font.BOLD, 12));
657+ panelNorthTool.add(labelVersionTool, "3, 1");
658+
659+ panelCenterTool = new JPanel();
660+ panelInfo.add(panelCenterTool, BorderLayout.CENTER);
661+ panelCenterTool.setLayout(new FormLayout(new ColumnSpec[] {
662+ FormSpecs.RELATED_GAP_COLSPEC,
663+ ColumnSpec.decode("max(40dlu;default)"),
664+ FormSpecs.RELATED_GAP_COLSPEC,
665+ ColumnSpec.decode("10dlu"),
666+ FormSpecs.RELATED_GAP_COLSPEC,
667+ ColumnSpec.decode("10dlu"),
668+ FormSpecs.RELATED_GAP_COLSPEC,
669+ ColumnSpec.decode("max(12dlu;default)"),
670+ FormSpecs.RELATED_GAP_COLSPEC,
671+ ColumnSpec.decode("max(90dlu;default)"),
672+ FormSpecs.RELATED_GAP_COLSPEC,
673+ ColumnSpec.decode("max(14dlu;default)"),
674+ FormSpecs.RELATED_GAP_COLSPEC,
675+ FormSpecs.RELATED_GAP_COLSPEC,
676+ ColumnSpec.decode("max(14dlu;default)"),
677+ FormSpecs.RELATED_GAP_COLSPEC,
678+ ColumnSpec.decode("max(90dlu;default)"),
679+ FormSpecs.RELATED_GAP_COLSPEC,
680+ FormSpecs.DEFAULT_COLSPEC,
681+ FormSpecs.RELATED_GAP_COLSPEC,
682+ FormSpecs.DEFAULT_COLSPEC,
683+ FormSpecs.RELATED_GAP_COLSPEC,
684+ FormSpecs.DEFAULT_COLSPEC,
685+ FormSpecs.RELATED_GAP_COLSPEC,
686+ ColumnSpec.decode("max(90dlu;default)"),},
687+ new RowSpec[] {
688+ FormSpecs.RELATED_GAP_ROWSPEC,
689+ FormSpecs.DEFAULT_ROWSPEC,
690+ FormSpecs.RELATED_GAP_ROWSPEC,
691+ FormSpecs.DEFAULT_ROWSPEC,
692+ FormSpecs.RELATED_GAP_ROWSPEC,
693+ FormSpecs.DEFAULT_ROWSPEC,
694+ FormSpecs.RELATED_GAP_ROWSPEC,
695+ FormSpecs.DEFAULT_ROWSPEC,
696+ FormSpecs.RELATED_GAP_ROWSPEC,
697+ FormSpecs.DEFAULT_ROWSPEC,
698+ FormSpecs.RELATED_GAP_ROWSPEC,
699+ FormSpecs.DEFAULT_ROWSPEC,
700+ FormSpecs.RELATED_GAP_ROWSPEC,
701+ FormSpecs.DEFAULT_ROWSPEC,
702+ FormSpecs.RELATED_GAP_ROWSPEC,
703+ FormSpecs.DEFAULT_ROWSPEC,
704+ FormSpecs.RELATED_GAP_ROWSPEC,
705+ FormSpecs.DEFAULT_ROWSPEC,
706+ FormSpecs.RELATED_GAP_ROWSPEC,
707+ FormSpecs.DEFAULT_ROWSPEC,
708+ FormSpecs.RELATED_GAP_ROWSPEC,
709+ FormSpecs.DEFAULT_ROWSPEC,
710+ FormSpecs.RELATED_GAP_ROWSPEC,
711+ FormSpecs.DEFAULT_ROWSPEC,
712+ FormSpecs.RELATED_GAP_ROWSPEC,
713+ FormSpecs.DEFAULT_ROWSPEC,
714+ FormSpecs.RELATED_GAP_ROWSPEC,
715+ FormSpecs.DEFAULT_ROWSPEC,
716+ FormSpecs.RELATED_GAP_ROWSPEC,
717+ FormSpecs.DEFAULT_ROWSPEC,
718+ FormSpecs.RELATED_GAP_ROWSPEC,
719+ FormSpecs.DEFAULT_ROWSPEC,
720+ FormSpecs.RELATED_GAP_ROWSPEC,
721+ FormSpecs.DEFAULT_ROWSPEC,
722+ FormSpecs.RELATED_GAP_ROWSPEC,
723+ FormSpecs.DEFAULT_ROWSPEC,
724+ FormSpecs.RELATED_GAP_ROWSPEC,
725+ FormSpecs.DEFAULT_ROWSPEC,
726+ FormSpecs.RELATED_GAP_ROWSPEC,
727+ FormSpecs.DEFAULT_ROWSPEC,
728+ FormSpecs.RELATED_GAP_ROWSPEC,
729+ FormSpecs.DEFAULT_ROWSPEC,}));
730+
731+ labelInfoPlaySongs = new JLabel(Messages.MSGInfoPlayedSongs.toString());
732+ labelInfoPlaySongs.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
733+ panelCenterTool.add(labelInfoPlaySongs, "2, 2, center, default");
734+
735+ labelSongNameToolTitle = new JLabel(Messages.MSGInfoSongName.toString());
736+ labelSongNameToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
737+ panelCenterTool.add(labelSongNameToolTitle, "2, 6, center, default");
738+
739+ labelSongNameToolTip = new JLabel(Messages.MSGInfoWait.toString());
740+ labelSongNameToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
741+ panelCenterTool.add(labelSongNameToolTip, "10, 6, center, default");
742+
743+ labelLyricToolTitle = new JLabel(Messages.MSGInfoLyricsBy.toString());
744+ labelLyricToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
745+ panelCenterTool.add(labelLyricToolTitle, "17, 6, center, default");
746+
747+ labelLyricToolTip = new JLabel(Messages.MSGInfoWait.toString());
748+ labelLyricToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
749+ panelCenterTool.add(labelLyricToolTip, "25, 6, center, default");
750+
751+ labelAttributeToolTitle = new JLabel(Messages.MSGInfoSongAttribute.toString());
752+ labelAttributeToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
753+ panelCenterTool.add(labelAttributeToolTitle, "2, 10, center, default");
754+
755+ labelAttributeToolTip = new JLabel(Messages.MSGInfoWait.toString());
756+ labelAttributeToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
757+ panelCenterTool.add(labelAttributeToolTip, "10, 10, center, default");
758+
759+ labelComposerToolTitle = new JLabel(Messages.MSGInfoComposedBy.toString());
760+ labelComposerToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
761+ panelCenterTool.add(labelComposerToolTitle, "17, 10, center, default");
762+
763+ labelComposerToolTip = new JLabel(Messages.MSGInfoWait.toString());
764+ labelComposerToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
765+ panelCenterTool.add(labelComposerToolTip, "25, 10, center, default");
766+
767+ labelDifficultyToolTitle = new JLabel(Messages.MSGInfoSongDifficulty.toString());
768+ labelDifficultyToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
769+ panelCenterTool.add(labelDifficultyToolTitle, "2, 14, center, default");
770+
771+ labelDifficultyToolTip = new JLabel(Messages.MSGInfoWait.toString());
772+ labelDifficultyToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
773+ panelCenterTool.add(labelDifficultyToolTip, "10, 14, center, default");
774+
775+ labelArrangeToolTitle = new JLabel(Messages.MSGInfoArrangedBy.toString());
776+ labelArrangeToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
777+ panelCenterTool.add(labelArrangeToolTitle, "17, 14, center, default");
778+
779+ labelArrangeToolTip = new JLabel(Messages.MSGInfoWait.toString());
780+ labelArrangeToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
781+ panelCenterTool.add(labelArrangeToolTip, "25, 14, center, default");
782+
783+ labelLevelToolTitle = new JLabel(Messages.MSGInfoSongLevel.toString());
784+ labelLevelToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
785+ panelCenterTool.add(labelLevelToolTitle, "2, 18, center, default");
786+
787+ labelLevelToolTip = new JLabel(Messages.MSGInfoWait.toString());
788+ labelLevelToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
789+ panelCenterTool.add(labelLevelToolTip, "10, 18, center, default");
790+
791+ labelMemberToolTitle = new JLabel(Messages.MSGInfoMember.toString());
792+ labelMemberToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
793+ panelCenterTool.add(labelMemberToolTitle, "17, 18, center, default");
794+
795+ labelMemberToolTip = new JLabel(Messages.MSGInfoWait.toString());
796+ labelMemberToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
797+ panelCenterTool.add(labelMemberToolTip, "25, 18, center, default");
798+
799+ labelNotesToolTitle = new JLabel(Messages.MSGInfoSongNotes.toString());
800+ labelNotesToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
801+ panelCenterTool.add(labelNotesToolTitle, "2, 22, center, default");
802+
803+ labelNotesToolTip = new JLabel(Messages.MSGInfoWait.toString());
804+ labelNotesToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
805+ panelCenterTool.add(labelNotesToolTip, "10, 22, center, default");
806+
807+ btnNextSongTool = new JButton("next");
808+ btnNextSongTool.addActionListener(e -> {
809+ CompletableFuture.runAsync(() -> {
810+ int currentIndex = Integer.parseInt(labelCurrentSongOrderTool.getText()) - 1;
811+ if(currentIndex != property.getSongLimit() - 1) {
812+ Song nextSong = toolIntegrateList.get(currentIndex + 1);
813+ logger.info("currently : {} Next: {}", currentIndex + 1, currentIndex + 2);
814+ logger.info("nextSong: {}", nextSong);
815+ Map<String, String> fetchMap = new HashMap<>();
816+ for(Map<String, String> tmpMap : listToolMapData) {
817+ String normalizeApiName = Normalizer.normalize(tmpMap.get("songname").toString(), Normalizer.Form.NFKD);
818+ String normalizeLocalName = Normalizer.normalize(nextSong.getName(), Normalizer.Form.NFKD);
819+ if(normalizeApiName.equals(normalizeLocalName)) {
820+ fetchMap = tmpMap;
821+ break;
822+ }
823+ }
824+ labelSongNameToolTip.setText(nextSong.getName());
825+ labelAttributeToolTip.setText(nextSong.getAttribute());
826+ labelDifficultyToolTip.setText(nextSong.getDifficulty());
827+ labelLevelToolTip.setText(String.valueOf(nextSong.getLevel()));
828+ labelNotesToolTip.setText(String.valueOf(nextSong.getNotes()));
829+ labelCurrentSongOrderTool.setText(String.valueOf(currentIndex + 2));
830+ labelLyricToolTip.setText(fetchMap.get("lyric"));
831+ labelComposerToolTip.setText(fetchMap.get("composer"));
832+ labelArrangeToolTip.setText(fetchMap.get("arrange"));
833+ labelMemberToolTip.setText("<html><body>" + fetchMap.get("member") + "</html></body>");
834+ }
835+ }, es).whenCompleteAsync((ret, ex) -> {
836+ if(ex != null) {
837+ logger.error("Exception was thrown during concurrent process", ex);
838+ }
839+ }, es);
840+ });
841+
842+ btnPrevSongTool = new JButton("prev");
843+ btnPrevSongTool.addActionListener(e -> {
844+ CompletableFuture.runAsync(() -> {
845+ int currentIndex = Integer.parseInt(labelCurrentSongOrderTool.getText()) - 1;
846+ if(currentIndex != 0) {
847+ Song prevSong = toolIntegrateList.get(currentIndex - 1);
848+ logger.info("currently : {} Next: {}", currentIndex + 1, currentIndex);
849+ logger.info("prevSong: {}", prevSong);
850+ Map<String, String> fetchMap = new HashMap<>();
851+ for(Map<String, String> tmpMap : listToolMapData) {
852+ String normalizeApiName = Normalizer.normalize(tmpMap.get("songname").toString(), Normalizer.Form.NFKD);
853+ String normalizeLocalName = Normalizer.normalize(prevSong.getName(), Normalizer.Form.NFKD);
854+ if(normalizeApiName.equals(normalizeLocalName)) {
855+ fetchMap = tmpMap;
856+ break;
857+ }
858+ }
859+ labelSongNameToolTip.setText(prevSong.getName());
860+ labelAttributeToolTip.setText(prevSong.getAttribute());
861+ labelDifficultyToolTip.setText(prevSong.getDifficulty());
862+ labelLevelToolTip.setText(String.valueOf(prevSong.getLevel()));
863+ labelNotesToolTip.setText(String.valueOf(prevSong.getNotes()));
864+ labelCurrentSongOrderTool.setText(String.valueOf(currentIndex));
865+ labelLyricToolTip.setText(fetchMap.get("lyric"));
866+ labelComposerToolTip.setText(fetchMap.get("composer"));
867+ labelArrangeToolTip.setText(fetchMap.get("arrange"));
868+ labelMemberToolTip.setText("<html><body>" + fetchMap.get("member") + "</html></body>");
869+ }
870+ }, es).whenCompleteAsync((ret, ex) -> {
871+ if(ex != null) {
872+ logger.error("Exception was thrown during concurrent process", ex);
873+ }
874+ }, es);
875+ });
876+ btnPrevSongTool.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
877+ panelCenterTool.add(btnPrevSongTool, "10, 28");
878+
879+ labelCurrentSongOrderTool = new JLabel("null");
880+ panelCenterTool.add(labelCurrentSongOrderTool, "12, 28");
881+
882+ labelSlashTool = new JLabel("/");
883+ panelCenterTool.add(labelSlashTool, "14, 28");
884+
885+ labelSongLimitTool = new JLabel(String.valueOf(this.property.getSongLimit()));
886+ panelCenterTool.add(labelSongLimitTool, "15, 28");
887+ btnNextSongTool.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
888+ panelCenterTool.add(btnNextSongTool, "17, 28");
889+
890+ btnMoreInfoTool = new JButton(Messages.MSGInfoOpenBrowser.toString());
891+ btnMoreInfoTool.addActionListener(e -> {
892+ CompletableFuture.runAsync(() -> {
893+ int currentIndex = Integer.parseInt(labelCurrentSongOrderTool.getText()) - 1;
894+ Song currentSong = toolIntegrateList.get(currentIndex);
895+ Map<String, String> fetchMap = new HashMap<>();
896+ for(Map<String, String> tmpMap : listToolMapData) {
897+ String normalizeApiName = Normalizer.normalize(tmpMap.get("songname").toString(), Normalizer.Form.NFKD);
898+ String normalizeLocalName = Normalizer.normalize(currentSong.getName(), Normalizer.Form.NFKD);
899+ if(normalizeApiName.equals(normalizeLocalName)) {
900+ fetchMap = tmpMap;
901+ break;
902+ }
903+ }
904+ Desktop desk = Desktop.getDesktop();
905+ String api = fetchMap.get("link");
906+ URI uri;
907+ try {
908+ uri = new URI(api);
909+ logger.info("Opening default browser with : {}", uri);
910+ desk.browse(uri);
911+ } catch (URISyntaxException | IOException e1) {
912+ JOptionPane.showMessageDialog(null, "このメッセージは仮です。Exception : " + e1.getClass().getSimpleName());
913+ logger.error("Exception while opening default browser.", e1);
914+ }
915+ }, es).whenCompleteAsync((ret, ex) -> {
916+ if(ex != null) {
917+ logger.warn("Exception was thrown during action events.", ex);
918+ }
919+ }, es);
920+ });
921+ btnMoreInfoTool.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
922+ panelCenterTool.add(btnMoreInfoTool, "25, 28");
923+
924+ labelToolProgress = new JLabel(Messages.MSGAPIWaitAPIFetch.toString());
925+ labelToolProgress.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
926+ panelCenterTool.add(labelToolProgress, "10, 32, center, default");
927+
928+ progressTool = new JProgressBar();
929+ progressTool.setStringPainted(true);
930+ progressTool.setValue(0);
931+ progressTool.setMaximum(property.getSongLimit());
932+ panelCenterTool.add(progressTool, "17, 32");
933+
934+ labelInfoProgressSongName = new JLabel("Processing:");
935+ labelInfoProgressSongName.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
936+ panelCenterTool.add(labelInfoProgressSongName, "10, 34");
937+
938+ panelScore = new JPanel();
939+ tabbedPane.addTab("Scores", null, panelScore, null);
940+ panelScore.setLayout(new BorderLayout(0, 0));
941+
942+ panelScoreNorth = new JPanel();
943+ panelScore.add(panelScoreNorth, BorderLayout.NORTH);
944+ panelScoreNorth.setLayout(new FormLayout(new ColumnSpec[] {
945+ ColumnSpec.decode("828px"),
946+ FormSpecs.RELATED_GAP_COLSPEC,
947+ ColumnSpec.decode("max(53dlu;default)"),},
948+ new RowSpec[] {
949+ RowSpec.decode("20px"),}));
950+
951+ labelScoreTitle = new JLabel("スコア、ファン計算");
952+ labelScoreTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 16));
953+ panelScoreNorth.add(labelScoreTitle, "1, 1, center, center");
954+
955+ labelScoreVersion = new JLabel(CheckVersion.getVersion());
956+ labelScoreVersion.setFont(new Font("SansSerif", Font.BOLD, 12));
957+ panelScoreNorth.add(labelScoreVersion, "3, 1, center, default");
958+
959+ panelScoreCenter = new JPanel();
960+ panelScore.add(panelScoreCenter, BorderLayout.CENTER);
961+ if(isFirst || !this.property.isCheckLibraryUpdates()) {
962+ setEnabled.run();
417963 }
418-
964+ }
419965 }
--- a/src/com/ranfa/main/Messages.java
+++ b/src/com/ranfa/main/Messages.java
@@ -40,8 +40,20 @@ public enum Messages {
4040 MSGCurrentAlbumType,
4141 MSGManualUpdate,
4242 MSGManualUpdateNotCompleteYet,
43- MSGConfigurations;
44-
43+ MSGConfigurations,
44+ MSGAPIWaitAPIFetch,
45+ MSGInfoPlayedSongs,
46+ MSGInfoWait,
47+ MSGInfoSongName,
48+ MSGInfoLyricsBy,
49+ MSGInfoSongAttribute,
50+ MSGInfoComposedBy,
51+ MSGInfoSongDifficulty,
52+ MSGInfoArrangedBy,
53+ MSGInfoSongLevel,
54+ MSGInfoMember,
55+ MSGInfoSongNotes,
56+ MSGInfoOpenBrowser;
4557
4658 @Override
4759 public String toString() {
--- /dev/null
+++ b/src/test/CrashReportTest.java
@@ -0,0 +1,58 @@
1+package test;
2+
3+import static org.junit.Assert.*;
4+
5+import java.io.IOException;
6+import java.nio.file.Files;
7+import java.nio.file.Path;
8+import java.nio.file.Paths;
9+import java.util.Arrays;
10+import java.util.List;
11+
12+import org.junit.AfterClass;
13+import org.junit.BeforeClass;
14+import org.junit.Test;
15+
16+import com.ranfa.lib.handler.CrashHandler;
17+
18+public class CrashReportTest {
19+
20+ private static final String INPUT_DIR = "Crash-Report";
21+
22+ private static List<Path> before;
23+
24+ @BeforeClass
25+ public static void flushFolder() throws IOException {
26+ if(Files.notExists(Paths.get(INPUT_DIR)))
27+ Files.createDirectory(Paths.get(INPUT_DIR));
28+ before = Arrays.asList(Files.list(Paths.get(INPUT_DIR)).toArray(Path[]::new));
29+ }
30+
31+ @Test
32+ public void generateSystemReportTest() {
33+ CrashHandler handle = new CrashHandler();
34+ assertNotNull(handle.outSystemInfo());
35+ }
36+
37+ @Test
38+ public void generateCrashReportTest() {
39+ CrashHandler handle = new CrashHandler(new RuntimeException());
40+ assertEquals("Unexpected Error", handle.getDescription());
41+ assertEquals(Integer.MIN_VALUE, handle.getEstimateExitCode());
42+ assertEquals(handle.getThrowable().getClass(), RuntimeException.class);
43+ }
44+
45+ @AfterClass
46+ public static void deleteReport() throws IOException {
47+ List<Path> after = Arrays.asList(Files.list(Paths.get(INPUT_DIR)).toArray(Path[]::new));
48+ after.removeAll(before);
49+ after.stream().forEach(t -> {
50+ try {
51+ Files.delete(t);
52+ } catch (IOException e) {
53+ e.printStackTrace();
54+ }
55+ });
56+ }
57+
58+}
--- a/src/test/FileIOTest.java
+++ b/src/test/FileIOTest.java
@@ -5,8 +5,8 @@ import static org.junit.Assert.assertTrue;
55 import java.util.ArrayList;
66 import org.junit.Test;
77
8-import com.ranfa.lib.Scraping;
9-import com.ranfa.lib.Song;
8+import com.ranfa.lib.database.Scraping;
9+import com.ranfa.lib.database.Song;
1010
1111 public class FileIOTest {
1212
--- a/src/test/LanguageTest.java
+++ b/src/test/LanguageTest.java
@@ -1,6 +1,6 @@
11 package test;
22
3-import static org.junit.Assert.assertTrue;
3+import static org.junit.Assert.*;
44
55 import java.util.Locale;
66
@@ -22,36 +22,50 @@ public class LanguageTest {
2222 Locale.setDefault(this.jp);
2323
2424 // asserts
25- assertTrue(Messages.MSGCalcStart.toString().equals("開始!"));
26- assertTrue(Messages.MSGDatabaseNotExist.toString().equals("楽曲データベースが見つかりませんでした。自動的に作成されます…\n注意:初回起動ではなく、かつ、Jarファイルと同じ階層に\"database.json\"というファイルが存在するにも関わらず\nこのポップアップが出た場合、開発者までご一報ください。\nGithub URL: https://github.com/hizumiaoba/DelesteRandomSelector/issues"));
27- assertTrue(Messages.MSGAlbumTypeBeingCalculated.toString().equals("計算中..."));
28- assertTrue(Messages.MSGNarrowingDownSongs.toString().equals("<html><body>楽曲<br>絞り込み</body></html>"));
29- assertTrue(Messages.MSGTitle.toString().equals("デレステ課題曲セレクター"));
30- assertTrue(Messages.MSGSelectDifficulty.toString().equals("難易度選択"));
31- assertTrue(Messages.MSGNonSelected.toString().equals("指定なし"));
32- assertTrue(Messages.MSGSongLevel.toString().equals("楽曲Lv"));
33- assertTrue(Messages.MSGBelowSpecificLevel.toString().equals("指定Lv以下"));
34- assertTrue(Messages.MSGOverSpecificLevel.toString().equals("指定Lv以上"));
35- assertTrue(Messages.MSGLevelCheckboxInfo.toString().equals("<html><body>以下以上両方にチェックをつけることで指定レベルのみ絞り込むことができます</body></html>"));
36- assertTrue(Messages.MSGUpdatingDatabase.toString().equals("<html><body>データベース<br>更新中…</body></html>"));
37- assertTrue(Messages.MSGCompleteNarrowDown.toString().equals("絞り込み完了!「開始」をクリックすることで選曲できます!"));
38- assertTrue(Messages.MSGNumberOfSongs.toString().equals("曲目:"));
39- assertTrue(Messages.MSGThisPhrase.toString().equals("この"));
40- assertTrue(Messages.MSGPlayPhrase.toString().equals("曲をプレイしましょう!!!"));
41- assertTrue(Messages.MSGTwitterIntegration.toString().equals("Twitter連携"));
42- assertTrue(Messages.MSGUsingThisAppPhrase.toString().equals("デレステ課題曲セレクターで\n"));
43- assertTrue(Messages.MSGNotPlayYet.toString().equals("ちひろ「まだプレイを始めていないみたいですね」"));
44- assertTrue(Messages.MSGTwitterPlayOtherwisePhrase.toString().equals("…その他数曲\nをプレイしました!\n"));
45- assertTrue(Messages.MSGTwitterPlayOnlyPhrase.toString().equals("をプレイしました!"));
46- assertTrue(Messages.MSGTwitterIntegrationConfirm.toString().equals("Twitterへ以下の内容を投稿します。よろしいですか?\n\n"));
47- assertTrue(Messages.MSGStringLength.toString().equals("\n\n文字数:"));
48- assertTrue(Messages.MSGCompletePost.toString().equals("投稿が完了しました。"));
49- assertTrue(Messages.MSGTerminate.toString().equals("終了"));
50- assertTrue(Messages.MSGInternalYpdateNotDoneYet.toString().equals("内部更新処理が完了していません。少し待ってからやり直してください。"));
51- assertTrue(Messages.MSGNarrowDownProcedure.toString().equals("楽曲選択の手順\r\n1.難易度、属性、レベルを選択する\r\n2.「楽曲取り込み」ボタンを押す!\r\n3.「開始」ボタンを押す!\r\n4.選択された楽曲がここに表示されます!\r\n現在設定されている楽曲選択の最大数:"));
52- assertTrue(Messages.MSGCurrentAlbumType.toString().equals("\n現在のMASTER+アルバム周期(推定):"));
53- assertTrue(Messages.MSGManualUpdate.toString().equals("<html><body>手動更新</body></html>"));
54- assertTrue(Messages.MSGManualUpdateNotCompleteYet.toString().equals("手動更新が完了していません。もうしばらくお待ちください。"));
25+ assertEquals("開始!", Messages.MSGCalcStart.toString());
26+ assertEquals("楽曲データベースが見つかりませんでした。自動的に作成されます…\n注意:初回起動ではなく、かつ、Jarファイルと同じ階層に\"database.json\"というファイルが存在するにも関わらず\nこのポップアップが出た場合、開発者までご一報ください。\nGithub URL: https://github.com/hizumiaoba/DelesteRandomSelector/issues", Messages.MSGDatabaseNotExist.toString());
27+ assertEquals("計算中...", Messages.MSGAlbumTypeBeingCalculated.toString());
28+ assertEquals("<html><body>楽曲<br>絞り込み</body></html>", Messages.MSGNarrowingDownSongs.toString());
29+ assertEquals("デレステ課題曲セレクター", Messages.MSGTitle.toString());
30+ assertEquals("難易度選択", Messages.MSGSelectDifficulty.toString());
31+ assertEquals("指定なし", Messages.MSGNonSelected.toString());
32+ assertEquals("楽曲Lv", Messages.MSGSongLevel.toString());
33+ assertEquals("指定Lv以下", Messages.MSGBelowSpecificLevel.toString());
34+ assertEquals("指定Lv以上", Messages.MSGOverSpecificLevel.toString());
35+ assertEquals("<html><body>以下以上両方にチェックをつけることで指定レベルのみ絞り込むことができます</body></html>", Messages.MSGLevelCheckboxInfo.toString());
36+ assertEquals("<html><body>データベース<br>更新中…</body></html>", Messages.MSGUpdatingDatabase.toString());
37+ assertEquals("絞り込み完了!「開始」をクリックすることで選曲できます!", Messages.MSGCompleteNarrowDown.toString());
38+ assertEquals("曲目:", Messages.MSGNumberOfSongs.toString());
39+ assertEquals("この", Messages.MSGThisPhrase.toString());
40+ assertEquals("曲をプレイしましょう!!!", Messages.MSGPlayPhrase.toString());
41+ assertEquals("Twitter連携", Messages.MSGTwitterIntegration.toString());
42+ assertEquals("デレステ課題曲セレクターで\n", Messages.MSGUsingThisAppPhrase.toString());
43+ assertEquals("ちひろ「まだプレイを始めていないみたいですね」", Messages.MSGNotPlayYet.toString());
44+ assertEquals("…その他数曲\nをプレイしました!\n", Messages.MSGTwitterPlayOtherwisePhrase.toString());
45+ assertEquals("をプレイしました!", Messages.MSGTwitterPlayOnlyPhrase.toString());
46+ assertEquals("Twitterへ以下の内容を投稿します。よろしいですか?\n\n", Messages.MSGTwitterIntegrationConfirm.toString());
47+ assertEquals("\n\n文字数:", Messages.MSGStringLength.toString());
48+ assertEquals("投稿が完了しました。", Messages.MSGCompletePost.toString());
49+ assertEquals("終了", Messages.MSGTerminate.toString());
50+ assertEquals("内部更新処理が完了していません。少し待ってからやり直してください。", Messages.MSGInternalYpdateNotDoneYet.toString());
51+ assertEquals("楽曲選択の手順\r\n1.難易度、属性、レベルを選択する\r\n2.「楽曲取り込み」ボタンを押す!\r\n3.「開始」ボタンを押す!\r\n4.選択された楽曲がここに表示されます!\r\n現在設定されている楽曲選択の最大数:", Messages.MSGNarrowDownProcedure.toString());
52+ assertEquals("\n現在のMASTER+アルバム周期(推定):", Messages.MSGCurrentAlbumType.toString());
53+ assertEquals("<html><body>手動更新</body></html>", Messages.MSGManualUpdate.toString());
54+ assertEquals("手動更新が完了していません。もうしばらくお待ちください。", Messages.MSGManualUpdateNotCompleteYet.toString());
55+ assertEquals("設定", Messages.MSGConfigurations.toString());
56+ assertEquals("楽曲情報APIより取得中です。\nしばらくお待ちください。", Messages.MSGAPIWaitAPIFetch.toString());
57+ assertEquals("今回プレイした楽曲", Messages.MSGInfoPlayedSongs.toString());
58+ assertEquals("しばらくお待ちください…", Messages.MSGInfoWait.toString());
59+ assertEquals("曲名", Messages.MSGInfoSongName.toString());
60+ assertEquals("作詞者", Messages.MSGInfoLyricsBy.toString());
61+ assertEquals("曲タイプ", Messages.MSGInfoSongAttribute.toString());
62+ assertEquals("作曲者", Messages.MSGInfoComposedBy.toString());
63+ assertEquals("難易度", Messages.MSGInfoSongDifficulty.toString());
64+ assertEquals("編曲者", Messages.MSGInfoArrangedBy.toString());
65+ assertEquals("レベル", Messages.MSGInfoSongLevel.toString());
66+ assertEquals("登場メンバー", Messages.MSGInfoMember.toString());
67+ assertEquals("ノート数", Messages.MSGInfoSongNotes.toString());
68+ assertEquals("更に詳しい情報を見る", Messages.MSGInfoOpenBrowser.toString());
5569 }
5670
5771 @Test
@@ -60,36 +74,50 @@ public class LanguageTest {
6074 Locale.setDefault(this.us);
6175
6276 // asserts
63- assertTrue(Messages.MSGCalcStart.toString().equals("Start!"));
64- assertTrue(Messages.MSGDatabaseNotExist.toString().equals("Music database does not exist.\nIt will be automatically created.\nATTENTION:There is the JSON file named \"database.json\" in the same directory which executable is contained and you see this pop up,\nPlease contact the Developer.\nGithub URL: https://github.com/hizumiaoba/DelesteRandomSelector/issues"));
65- assertTrue(Messages.MSGAlbumTypeBeingCalculated.toString().equals("Simulating..."));
66- assertTrue(Messages.MSGNarrowingDownSongs.toString().equals("<html><body>Narrow down<br>songs</body></html>"));
67- assertTrue(Messages.MSGTitle.toString().equals("DelesteRandomSelector"));
68- assertTrue(Messages.MSGSelectDifficulty.toString().equals("Difficulty"));
69- assertTrue(Messages.MSGNonSelected.toString().equals("Non-Select"));
70- assertTrue(Messages.MSGSongLevel.toString().equals("Level"));
71- assertTrue(Messages.MSGBelowSpecificLevel.toString().equals("Below Lv"));
72- assertTrue(Messages.MSGOverSpecificLevel.toString().equals("Above Lv"));
73- assertTrue(Messages.MSGLevelCheckboxInfo.toString().equals("<html><body>Only specified level songs will be selected if you mark both checkbox.</body></html>"));
74- assertTrue(Messages.MSGUpdatingDatabase.toString().equals("<html><body>Updating<br>database</body></html>"));
75- assertTrue(Messages.MSGCompleteNarrowDown.toString().equals("Narrowing down complete! Click \"Start!\" to play!"));
76- assertTrue(Messages.MSGNumberOfSongs.toString().equals("tracks:"));
77- assertTrue(Messages.MSGThisPhrase.toString().equals("Let's play these"));
78- assertTrue(Messages.MSGPlayPhrase.toString().equals("songs!"));
79- assertTrue(Messages.MSGTwitterIntegration.toString().equals("<html><body>Post to Twitter</body></html>"));
80- assertTrue(Messages.MSGUsingThisAppPhrase.toString().equals("I played\n"));
81- assertTrue(Messages.MSGNotPlayYet.toString().equals("It seems that you don't start playing yet?"));
82- assertTrue(Messages.MSGTwitterPlayOtherwisePhrase.toString().equals("...and some songs!\n"));
83- assertTrue(Messages.MSGTwitterPlayOnlyPhrase.toString().equals("songs!"));
84- assertTrue(Messages.MSGTwitterIntegrationConfirm.toString().equals("Are you sure you want to post this?\n\n"));
85- assertTrue(Messages.MSGStringLength.toString().equals("\n\nNumber of Characters"));
86- assertTrue(Messages.MSGCompletePost.toString().equals("Complete to post."));
87- assertTrue(Messages.MSGTerminate.toString().equals("End"));
88- assertTrue(Messages.MSGInternalYpdateNotDoneYet.toString().equals("Internal update in progress. Please wait a moment."));
89- assertTrue(Messages.MSGNarrowDownProcedure.toString().equals("How to select songs\r\n1.Select difficulty, attribute, and level.\r\n2.Click [Narrow down songs] button.\r\n3.Click [start!] button.\r\n4.Selected songs will be shown here!\r\nThe maximum number of selected songs:"));
90- assertTrue(Messages.MSGCurrentAlbumType.toString().equals("\nCurrent MASTER+ ALBUM type(based on simulation):"));
91- assertTrue(Messages.MSGManualUpdate.toString().equals("<html><body>Manual<br>Update</body></html>"));
92- assertTrue(Messages.MSGManualUpdateNotCompleteYet.toString().equals("Manual Update has not been finished yet. Please wait a moment."));
77+ assertEquals("Start!", Messages.MSGCalcStart.toString());
78+ assertEquals("Music database does not exist.\nIt will be automatically created.\nATTENTION:There is the JSON file named \"database.json\" in the same directory which executable is contained and you see this pop up,\nPlease contact the Developer.\nGithub URL: https://github.com/hizumiaoba/DelesteRandomSelector/issues", Messages.MSGDatabaseNotExist.toString());
79+ assertEquals("Simulating...", Messages.MSGAlbumTypeBeingCalculated.toString());
80+ assertEquals("<html><body>Narrow down<br>songs</body></html>", Messages.MSGNarrowingDownSongs.toString());
81+ assertEquals("DelesteRandomSelector", Messages.MSGTitle.toString());
82+ assertEquals("Difficulty", Messages.MSGSelectDifficulty.toString());
83+ assertEquals("Non-Select", Messages.MSGNonSelected.toString());
84+ assertEquals("Level", Messages.MSGSongLevel.toString());
85+ assertEquals("Below Lv", Messages.MSGBelowSpecificLevel.toString());
86+ assertEquals("Above Lv", Messages.MSGOverSpecificLevel.toString());
87+ assertEquals("<html><body>Only specified level songs will be selected if you mark both checkbox.</body></html>", Messages.MSGLevelCheckboxInfo.toString());
88+ assertEquals("<html><body>Updating<br>database</body></html>", Messages.MSGUpdatingDatabase.toString());
89+ assertEquals("Narrowing down complete! Click \"Start!\" to play!", Messages.MSGCompleteNarrowDown.toString());
90+ assertEquals("tracks:", Messages.MSGNumberOfSongs.toString());
91+ assertEquals("Let's play these", Messages.MSGThisPhrase.toString());
92+ assertEquals("songs!", Messages.MSGPlayPhrase.toString());
93+ assertEquals("<html><body>Post to Twitter</body></html>", Messages.MSGTwitterIntegration.toString());
94+ assertEquals("I played\n", Messages.MSGUsingThisAppPhrase.toString());
95+ assertEquals("It seems that you don't start playing yet?", Messages.MSGNotPlayYet.toString());
96+ assertEquals("...and some songs!\n", Messages.MSGTwitterPlayOtherwisePhrase.toString());
97+ assertEquals("songs!", Messages.MSGTwitterPlayOnlyPhrase.toString());
98+ assertEquals("Are you sure you want to post this?\n\n", Messages.MSGTwitterIntegrationConfirm.toString());
99+ assertEquals("\n\nNumber of Characters", Messages.MSGStringLength.toString());
100+ assertEquals("Complete to post.", Messages.MSGCompletePost.toString());
101+ assertEquals("End", Messages.MSGTerminate.toString());
102+ assertEquals("Internal update in progress. Please wait a moment.", Messages.MSGInternalYpdateNotDoneYet.toString());
103+ assertEquals("How to select songs\r\n1.Select difficulty, attribute, and level.\r\n2.Click [Narrow down songs] button.\r\n3.Click [start!] button.\r\n4.Selected songs will be shown here!\r\nThe maximum number of selected songs:", Messages.MSGNarrowDownProcedure.toString());
104+ assertEquals("\nCurrent MASTER+ ALBUM type(based on simulation):", Messages.MSGCurrentAlbumType.toString());
105+ assertEquals("<html><body>Manual<br>Update</body></html>", Messages.MSGManualUpdate.toString());
106+ assertEquals("Manual Update has not been finished yet. Please wait a moment.", Messages.MSGManualUpdateNotCompleteYet.toString());
107+ assertEquals("Config", Messages.MSGConfigurations.toString());
108+ assertEquals("Getting informations from API. Please wait.", Messages.MSGAPIWaitAPIFetch.toString());
109+ assertEquals("The songs you played", Messages.MSGInfoPlayedSongs.toString());
110+ assertEquals("Please wait...", Messages.MSGInfoWait.toString());
111+ assertEquals("Song Name", Messages.MSGInfoSongName.toString());
112+ assertEquals("Lyrics By", Messages.MSGInfoLyricsBy.toString());
113+ assertEquals("Song Attribute", Messages.MSGInfoSongAttribute.toString());
114+ assertEquals("Composed By", Messages.MSGInfoComposedBy.toString());
115+ assertEquals("Difficulty", Messages.MSGInfoSongDifficulty.toString());
116+ assertEquals("Arranged By", Messages.MSGInfoArrangedBy.toString());
117+ assertEquals("Song Level", Messages.MSGInfoSongLevel.toString());
118+ assertEquals("Member", Messages.MSGInfoMember.toString());
119+ assertEquals("Notes", Messages.MSGInfoSongNotes.toString());
120+ assertEquals("More Information", Messages.MSGInfoOpenBrowser.toString());
93121 }
94122
95123 @After
--- /dev/null
+++ b/src/test/ObjectIOTest.java
@@ -0,0 +1,76 @@
1+package test;
2+
3+import static org.junit.Assert.*;
4+
5+import java.io.IOException;
6+import java.nio.file.Files;
7+import java.nio.file.Paths;
8+import java.util.ArrayList;
9+import java.util.LinkedHashMap;
10+import java.util.List;
11+import java.util.Map;
12+
13+import org.junit.AfterClass;
14+import org.junit.BeforeClass;
15+import org.junit.Test;
16+
17+import com.ranfa.lib.io.FileIO;
18+import com.ranfa.lib.io.OutputDataStructure;
19+
20+import test.mock.ObjectWriteMock;
21+
22+/**
23+ * songname
24+ * level
25+ * difficulty
26+ * attribute
27+ * score
28+ */
29+public class ObjectIOTest {
30+
31+ private static final String filename = "test.drs";
32+ private static Map<String, String> testMap;
33+ private static List<Map<String, String>> testList;
34+
35+ @BeforeClass
36+ public static void init() {
37+ testMap = new LinkedHashMap<>();
38+ testMap.put("songname", "testname001");
39+ testMap.put("level", "28");
40+ testMap.put("difficulty", "MASTER");
41+ testMap.put("attribute", "キュート");
42+ testMap.put("score", "1200000");
43+ testList = new ArrayList<>();
44+ testList.add(testMap);
45+ }
46+
47+
48+ @Test
49+ public void writeTest() {
50+ assertTrue(ObjectWriteMock.write(testList, filename));
51+ }
52+
53+ @Test
54+ public void readNonNullTest() {
55+ OutputDataStructure structure = FileIO.read(filename);
56+ assertNotNull(structure);
57+ }
58+
59+ @Test
60+ public void readEqualsTest() {
61+ OutputDataStructure structure = FileIO.read(filename);
62+ if(structure != null) {
63+ assertEquals(new OutputDataStructure(testList), structure);
64+ }
65+ }
66+
67+ @AfterClass
68+ public static void del() {
69+ try {
70+ Files.deleteIfExists(Paths.get(filename));
71+ } catch (IOException e) {
72+ e.printStackTrace();
73+ }
74+ }
75+
76+}
--- /dev/null
+++ b/src/test/VersionTest.java
@@ -0,0 +1,34 @@
1+package test;
2+
3+import static org.junit.Assert.*;
4+
5+import java.io.IOException;
6+import java.nio.file.Paths;
7+
8+import org.junit.Test;
9+
10+import com.fasterxml.jackson.databind.JsonNode;
11+import com.fasterxml.jackson.databind.ObjectMapper;
12+import com.ranfa.lib.CheckVersion;
13+
14+public class VersionTest {
15+
16+ @Test
17+ public void matchJSONandAnnotations() {
18+ String annotationVersion = CheckVersion.getVersion();
19+ int major, minor, patch;
20+ major = minor = patch = 0;
21+ try {
22+ JsonNode node = new ObjectMapper().readTree(Paths.get("version.json").toFile());
23+ major = node.get("major").asInt();
24+ minor = node.get("minor").asInt();
25+ patch = node.get("patch").asInt();
26+ } catch (IOException e) {
27+ e.printStackTrace();
28+ }
29+ String jsonVersion = String.format("v%d.%d.%d", major, minor, patch);
30+ // check if json version and annotation version are equal.
31+ assertTrue(jsonVersion.equals(annotationVersion));
32+ }
33+
34+}
--- a/src/test/WebFetchingTest.java
+++ b/src/test/WebFetchingTest.java
@@ -6,9 +6,9 @@ import java.util.ArrayList;
66
77 import org.junit.Test;
88
9-import com.ranfa.lib.EstimateAlbumTypeCycle;
10-import com.ranfa.lib.Scraping;
11-import com.ranfa.lib.Song;
9+import com.ranfa.lib.database.EstimateAlbumTypeCycle;
10+import com.ranfa.lib.database.Scraping;
11+import com.ranfa.lib.database.Song;
1212
1313 public class WebFetchingTest {
1414
--- /dev/null
+++ b/src/test/mock/ObjectWriteMock.java
@@ -0,0 +1,27 @@
1+package test.mock;
2+
3+import java.io.FileOutputStream;
4+import java.io.IOException;
5+import java.io.ObjectOutputStream;
6+import java.util.List;
7+import java.util.Map;
8+
9+import com.ranfa.lib.io.OutputDataStructure;
10+
11+public class ObjectWriteMock {
12+
13+ public static boolean write(List<Map<String, String>> songList, String filename) {
14+ try {
15+ ObjectOutputStream outStream = new ObjectOutputStream(new FileOutputStream(filename));
16+ OutputDataStructure structure = new OutputDataStructure(songList);
17+ outStream.writeObject(structure);
18+ outStream.flush();
19+ outStream.close();
20+ return true;
21+ } catch (IOException e) {
22+ e.printStackTrace();
23+ return false;
24+ }
25+ }
26+
27+}
Show on old repository browser