2 * Copyright 2022 the original author or authors.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * https://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.ranfa.main;
18 import java.awt.BorderLayout;
19 import java.awt.CardLayout;
20 import java.awt.Desktop;
21 import java.awt.EventQueue;
23 import java.awt.event.ActionEvent;
24 import java.awt.event.ActionListener;
25 import java.io.IOException;
27 import java.net.URISyntaxException;
28 import java.nio.file.Files;
29 import java.nio.file.Paths;
30 import java.text.Normalizer;
31 import java.util.ArrayList;
32 import java.util.HashMap;
33 import java.util.List;
35 import java.util.Random;
36 import java.util.concurrent.CompletableFuture;
37 import java.util.concurrent.ExecutorService;
38 import java.util.concurrent.Executors;
39 import java.util.function.BiConsumer;
40 import java.util.stream.Collectors;
42 import javax.swing.DefaultComboBoxModel;
43 import javax.swing.JButton;
44 import javax.swing.JCheckBox;
45 import javax.swing.JComboBox;
46 import javax.swing.JFrame;
47 import javax.swing.JLabel;
48 import javax.swing.JOptionPane;
49 import javax.swing.JPanel;
50 import javax.swing.JProgressBar;
51 import javax.swing.JScrollPane;
52 import javax.swing.JSpinner;
53 import javax.swing.JTabbedPane;
54 import javax.swing.JTextArea;
55 import javax.swing.JTextField;
56 import javax.swing.border.EmptyBorder;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
61 import com.jgoodies.forms.layout.ColumnSpec;
62 import com.jgoodies.forms.layout.FormLayout;
63 import com.jgoodies.forms.layout.FormSpecs;
64 import com.jgoodies.forms.layout.RowSpec;
65 import com.ranfa.lib.CheckVersion;
66 import com.ranfa.lib.Easter;
67 import com.ranfa.lib.ManualUpdateThreadImpl;
68 import com.ranfa.lib.SettingJSONProperty;
69 import com.ranfa.lib.Settings;
70 import com.ranfa.lib.Suffix;
71 import com.ranfa.lib.TwitterIntegration;
72 import com.ranfa.lib.Version;
73 import com.ranfa.lib.calc.FanCalc;
74 import com.ranfa.lib.concurrent.CountedThreadFactory;
75 import com.ranfa.lib.database.EstimateAlbumTypeCycle;
76 import com.ranfa.lib.database.Scraping;
77 import com.ranfa.lib.database.Song;
78 import com.ranfa.lib.handler.CrashHandler;
79 import com.ranfa.lib.songinfo.FetchFromAPI;
90 @Version(major = 4, minor = 0, patch = 3, suffix = Suffix.BETA)
91 public class DelesteRandomSelector extends JFrame {
94 * ランダムに選択された楽曲を格納するためのList。
96 * 選ばれた楽曲を使用する処理は基本的に全てここから取得する。
98 private static ArrayList<Song> selectedSongsList = new ArrayList<>();
100 private JPanel contentPane;
101 private SettingJSONProperty property = new SettingJSONProperty();
102 private String[] integratorArray;
103 private boolean integratorBool = false;
104 private CompletableFuture<Void> softwareUpdateFuture = null;
105 private CompletableFuture<Void> albumTypeEstimateFuture = null;
106 private String albumType = Messages.MSGAlbumTypeBeingCalculated.toString();
107 private Logger logger = LoggerFactory.getLogger(DelesteRandomSelector.class);
108 private ManualUpdateThreadImpl impl;
109 private List<Song> toolIntegrateList;
110 private FetchFromAPI fetchData;
111 private List<Map<String, String>> listToolMapData;
112 private CompletableFuture<List<Map<String, String>>> listToolMapDataFuture;
113 private Easter easter;
114 private JPanel panelMain;
115 private JPanel panelNorthMain;
116 private JLabel labelTitle;
117 private JLabel labelVersion;
118 private JPanel panelWestMain;
119 private JLabel labelDifficulty;
120 private JComboBox<String[]> comboDifficultySelect;
121 private JComboBox<String[]> comboAttribute;
122 private JLabel labelLevel;
123 private JSpinner spinnerLevel;
124 private JCheckBox checkLessLv;
125 private JCheckBox checkMoreLv;
126 private JLabel labelLvCaution;
127 private JPanel panelEastMain;
128 private JButton btnImport;
129 private JButton btnConfig;
130 private JButton btnStart;
131 private JButton btnManualUpdate;
132 private JButton btnTwitterIntegration;
133 private JButton btnExit;
134 private JPanel panelCenterMain;
135 private JScrollPane scrollPane;
136 private JTextArea textArea;
137 private JTabbedPane tabbedPane;
138 private JPanel panelInfo;
139 private JPanel panelNorthTool;
140 private JLabel labelSubToolTitle;
141 private JLabel labelVersionTool;
142 private JPanel panelCenterTool;
143 private JLabel labelInfoPlaySongs;
144 private JLabel labelSongNameToolTitle;
145 private JLabel labelSongNameToolTip;
146 private JLabel labelAttributeToolTitle;
147 private JLabel labelAttributeToolTip;
148 private JLabel labelDifficultyToolTitle;
149 private JLabel labelDifficultyToolTip;
150 private JLabel labelLevelToolTitle;
151 private JLabel labelLevelToolTip;
152 private JLabel labelNotesToolTitle;
153 private JLabel labelNotesToolTip;
154 private JButton btnPrevSongTool;
155 private JButton btnNextSongTool;
156 private JLabel labelSlashTool;
157 private JLabel labelCurrentSongOrderTool;
158 private JLabel labelSongLimitTool;
159 private JLabel labelLyricToolTitle;
160 private JLabel labelLyricToolTip;
161 private JLabel labelComposerToolTitle;
162 private JLabel labelArrangeToolTitle;
163 private JLabel labelComposerToolTip;
164 private JLabel labelArrangeToolTip;
165 private JLabel labelMemberToolTitle;
166 private JLabel labelMemberToolTip;
167 private JButton btnMoreInfoTool;
170 * アップデート処理用の{@link BiConsumer}。
172 * 実際は{@link CompletableFuture}によって使用される。
174 BiConsumer<ArrayList<Song>, ArrayList<Song>> updateConsumer = (list1, list2) -> {
175 this.logger.info("Checking database updates...");
176 if(list1.size() > list2.size()) {
177 long time = System.currentTimeMillis();
178 this.logger.info("{} Update detected.", (list1.size() - list2.size()));
179 Scraping.writeToJson(list1);
180 this.logger.info("Update completed in {} ms", (System.currentTimeMillis() - time));
181 this.logger.info("Updated database size: {}", list1.size());
183 this.logger.info("database is up-to-date.");
188 * ライブラリ関連の処理完了後に{@link JButton}を有効化するための{@link Runnable}。
191 * <li>{@link JButton}の有効化</li>
192 * <li>表示するテキストの更新</li>
196 Runnable setEnabled = () -> {
198 Thread.sleep(3 * 1000L);
199 } catch (InterruptedException e1) {
200 this.logger.error("Thread has been interrupted during waiting cooldown.", e1);
202 this.btnImport.setEnabled(true);
203 this.btnImport.setText(Messages.MSGNarrowingDownSongs.toString());
205 private JLabel labelToolProgress;
206 public static JProgressBar progressTool;
207 public static JLabel labelInfoProgressSongName;
208 private JPanel panelScore;
209 private JPanel panelScoreNorth;
210 private JPanel panelScoreCenter;
211 private JLabel labelScoreTitle;
212 private JLabel labelScoreVersion;
213 private JLabel labelScoreUserPlayed;
214 private JTextField fieldScoreUserPlayed;
215 private JLabel labelScoreEarnedFan;
216 private JTextField fieldScoreEarnedFan;
217 private JLabel lblSongname;
218 private JLabel labelScoreAttribute;
219 private JLabel labelScoreDifficulty;
220 private JLabel labelScoreLevel;
221 private JLabel labelScoreNotes;
222 private JLabel labelScoreSongnameDynamic;
223 private JLabel labelScoreAttributeDynamic;
224 private JLabel labelScoreDifficultyDynamic;
225 private JLabel labelScoreLevelDynamic;
226 private JLabel labelScoreNotesDynamic;
227 private JButton btnScorePrev;
228 private JButton btnScoreNext;
229 private JLabel labelScoreCurrentSongOrder;
230 private JLabel labelScoreSlash;
231 private JLabel labelScoreOrderMax;
232 private JLabel labelPlayerScore;
233 private JLabel labelPlayerFan;
234 private JLabel labelPlayerPRP;
235 private JLabel labelPlayerScoreDynamic;
236 private JLabel labelPlayerFanDynamic;
237 private JLabel labelPlayerPRPDynamic;
238 private JTextField fieldScoreRoom;
239 private JTextField fieldScoreCenter;
240 private JTextField fieldScoreProduce;
241 private JTextField fieldScorePremium;
242 private JLabel label;
243 private JLabel lblRoom;
244 private JLabel lblCenter;
245 private JLabel lblProduce;
246 private JLabel lblPremium;
247 private JButton button;
250 * Launch the application.
252 public static void main(String[] args) {
253 EventQueue.invokeLater(() -> {
255 DelesteRandomSelector frame = new DelesteRandomSelector();
256 frame.setVisible(true);
257 } catch (Exception e) {
267 public DelesteRandomSelector() {
268 ExecutorService es = Executors.newCachedThreadPool(new CountedThreadFactory(() -> "DRS", "AsyncEventInquerier", false));
269 this.contentPane = new JPanel();
270 // output system info phase
271 CompletableFuture.runAsync(() -> {
272 CrashHandler handle = new CrashHandler();
273 handle.outSystemInfo();
274 }, es).whenCompleteAsync((ret, ex) -> {
276 logger.error("Exception was thrown during concurrent process", ex);
277 CrashHandler handle = new CrashHandler(ex);
278 if(ex instanceof NullPointerException) {
281 handle = new CrashHandler(new IllegalStateException(ex));
285 boolean isFirst = !Scraping.databaseExists();
286 // database check phase
287 CompletableFuture.runAsync(() -> {
289 JOptionPane.showMessageDialog(this, Messages.MSGDatabaseNotExist.toString());
290 if(!Scraping.writeToJson(Scraping.getWholeData())) {
291 JOptionPane.showMessageDialog(this, "Exception:NullPointerException\nCannot Keep up! Please re-download this Application!");
292 throw new NullPointerException("FATAL: cannot continue!");
295 }, es).whenCompleteAsync((ret, ex) -> {
297 logger.error("Exception was thrown during concurrent process", ex);
298 CrashHandler handle = new CrashHandler(ex.getMessage(), ex);
299 if(ex instanceof NullPointerException) {
302 handle = new CrashHandler(ex.getMessage(), new IllegalStateException(ex));
306 CompletableFuture<ArrayList<Song>> getFromJsonFuture = CompletableFuture.supplyAsync(() -> Scraping.getFromJson(), es);
307 CompletableFuture<ArrayList<Song>> getWholeDataFuture = CompletableFuture.supplyAsync(() -> Scraping.getWholeData(), es);
308 // setting check phase
309 CompletableFuture.runAsync(() -> {
310 if(!Settings.fileExists() && !Settings.writeDownJSON()) {
311 JOptionPane.showMessageDialog(this, "Exception:NullPointerException\nPlease see crash report for more detail.");
312 CrashHandler handle = new CrashHandler("Failed to generate setting file.", new NullPointerException("FATAL: cannot continue!"));
315 }, es).whenCompleteAsync((ret, ex) -> {
317 logger.error("Exception was thrown during concurrent process", ex);
318 CrashHandler handle = new CrashHandler(ex.getMessage(), ex);
319 if(ex instanceof NullPointerException) {
322 handle = new CrashHandler(ex.getMessage(), new IllegalStateException(ex));
325 this.logger.debug("Loading settings...");
326 this.property.setCheckLibraryUpdates(Settings.needToCheckLibraryUpdates());
327 this.property.setCheckVersion(Settings.needToCheckVersion());
328 this.property.setWindowWidth(Settings.getWindowWidth());
329 this.property.setWindowHeight(Settings.getWindowHeight());
330 this.property.setSongLimit(Settings.getSongsLimit());
331 this.property.setSaveScoreLog(Settings.saveScoreLog());
332 this.logger.debug("Load settings done.");
333 this.logger.debug("Version check: {}", this.property.isCheckVersion());
334 this.logger.debug("Library update check: {}", this.property.isCheckLibraryUpdates());
335 this.logger.debug("Window Width: {}", this.property.getWindowWidth());
336 this.logger.debug("Window Height: {}", this.property.getWindowHeight());
337 this.logger.debug("Song Limit: {}", this.property.getSongLimit());
338 this.logger.debug("SaveScoreLog: {}", this.property.isSaveScoreLog());
339 this.setBounds(100, 100, this.property.getWindowWidth(), this.property.getWindowHeight());
340 if(this.property.isCheckVersion()) {
341 this.softwareUpdateFuture = CompletableFuture.runAsync(() -> CheckVersion.needToBeUpdated(), es);
343 if(this.property.isCheckLibraryUpdates()) {
344 CompletableFuture<Void> updatedFuture = getWholeDataFuture.thenAcceptBothAsync(getFromJsonFuture, updateConsumer, es);
345 updatedFuture.thenRunAsync(setEnabled, es);
348 CompletableFuture.runAsync(() -> {
349 EstimateAlbumTypeCycle.Initialization();
350 if(Files.exists(Paths.get("generated/albumCycle.json"))) {
351 this.albumType = EstimateAlbumTypeCycle.getCurrentCycle();
353 }, es).whenCompleteAsync((ret, ex) -> {
355 logger.error("Exception was thrown during concurrent process", ex);
356 CrashHandler handle = new CrashHandler(ex.getMessage(), new IllegalStateException(ex));
360 getWholeDataFuture.thenAcceptAsync(list -> this.logger.info("Scraping data size:" + list.size()), es);
361 getFromJsonFuture.thenAcceptAsync(list -> this.logger.info("Currently database size:" + list.size()), es);
363 CompletableFuture.runAsync(() -> {
364 this.easter = new Easter();
365 this.setTitle(this.easter.getTodaysBirth());
367 this.logger.debug("Version: {}", CheckVersion.getVersion());
368 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
369 this.setBounds(100, 100, 960, 643);
370 this.contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
371 this.setContentPane(this.contentPane);
372 contentPane.setLayout(new CardLayout(0, 0));
374 panelMain = new JPanel();
375 panelMain.setLayout(new BorderLayout(0, 0));
377 panelNorthMain = new JPanel();
378 panelMain.add(panelNorthMain, BorderLayout.NORTH);
379 panelNorthMain.setLayout(new FormLayout(new ColumnSpec[] {
380 ColumnSpec.decode("829px"),
381 FormSpecs.LABEL_COMPONENT_GAP_COLSPEC,
382 ColumnSpec.decode("center:94px"),},
384 RowSpec.decode("20px"),}));
386 labelTitle = new JLabel(Messages.MSGTitle.toString());
387 labelTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 16));
388 panelNorthMain.add(labelTitle, "1, 1, center, top");
390 labelVersion = new JLabel(CheckVersion.getVersion());
391 labelVersion.setFont(new Font("SansSerif", Font.BOLD, 12));
392 panelNorthMain.add(labelVersion, "3, 1, center, center");
394 panelWestMain = new JPanel();
395 panelMain.add(panelWestMain, BorderLayout.WEST);
396 panelWestMain.setLayout(new FormLayout(new ColumnSpec[] {
397 FormSpecs.LABEL_COMPONENT_GAP_COLSPEC,
398 ColumnSpec.decode("120px"),},
400 FormSpecs.LINE_GAP_ROWSPEC,
401 RowSpec.decode("25px"),
402 FormSpecs.RELATED_GAP_ROWSPEC,
403 FormSpecs.DEFAULT_ROWSPEC,
404 FormSpecs.RELATED_GAP_ROWSPEC,
405 FormSpecs.DEFAULT_ROWSPEC,
406 FormSpecs.RELATED_GAP_ROWSPEC,
407 FormSpecs.DEFAULT_ROWSPEC,
408 FormSpecs.RELATED_GAP_ROWSPEC,
409 FormSpecs.DEFAULT_ROWSPEC,
410 FormSpecs.RELATED_GAP_ROWSPEC,
411 FormSpecs.DEFAULT_ROWSPEC,
412 FormSpecs.RELATED_GAP_ROWSPEC,
413 FormSpecs.DEFAULT_ROWSPEC,
414 FormSpecs.RELATED_GAP_ROWSPEC,
415 RowSpec.decode("max(41dlu;default)"),}));
417 labelDifficulty = new JLabel(Messages.MSGSelectDifficulty.toString());
418 labelDifficulty.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
419 panelWestMain.add(labelDifficulty, "2, 2, center, center");
421 comboDifficultySelect = new JComboBox<>();
422 comboDifficultySelect.setModel(new DefaultComboBoxModel(new String[] {Messages.MSGNonSelected.toString(), "DEBUT", "REGULAR", "PRO", "MASTER", "MASTER+", "ⓁMASTER+", "LIGHT", "TRICK", "PIANO", "FORTE", "WITCH"}));
423 comboDifficultySelect.setFont(new Font("Dialog", Font.BOLD, 12));
424 panelWestMain.add(comboDifficultySelect, "2, 4, fill, fill");
426 comboAttribute = new JComboBox<>();
427 comboAttribute.setModel(new DefaultComboBoxModel(new String[] {Messages.MSGNonSelected.toString(), "全タイプ", "キュート", "クール", "パッション"}));
428 comboAttribute.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
429 panelWestMain.add(comboAttribute, "2, 6, fill, top");
431 labelLevel = new JLabel(Messages.MSGSongLevel.toString());
432 labelLevel.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
433 panelWestMain.add(labelLevel, "2, 8, center, center");
435 spinnerLevel = new JSpinner();
436 panelWestMain.add(spinnerLevel, "2, 10, fill, center");
438 checkLessLv = new JCheckBox(Messages.MSGBelowSpecificLevel.toString());
439 checkLessLv.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
440 panelWestMain.add(checkLessLv, "2, 12, left, top");
442 checkMoreLv = new JCheckBox(Messages.MSGOverSpecificLevel.toString());
443 checkMoreLv.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
444 panelWestMain.add(checkMoreLv, "2, 14, left, top");
446 labelLvCaution = new JLabel(Messages.MSGLevelCheckboxInfo.toString());
447 labelLvCaution.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
448 panelWestMain.add(labelLvCaution, "2, 16, left, center");
450 panelEastMain = new JPanel();
451 panelMain.add(panelEastMain, BorderLayout.EAST);
452 panelEastMain.setLayout(new FormLayout(new ColumnSpec[] {
453 FormSpecs.LABEL_COMPONENT_GAP_COLSPEC,
454 ColumnSpec.decode("100px"),},
456 FormSpecs.LINE_GAP_ROWSPEC,
457 RowSpec.decode("77px"),
458 FormSpecs.RELATED_GAP_ROWSPEC,
459 FormSpecs.DEFAULT_ROWSPEC,
460 FormSpecs.RELATED_GAP_ROWSPEC,
461 FormSpecs.DEFAULT_ROWSPEC,
462 FormSpecs.RELATED_GAP_ROWSPEC,
463 FormSpecs.DEFAULT_ROWSPEC,
464 FormSpecs.RELATED_GAP_ROWSPEC,
465 RowSpec.decode("max(36dlu;default)"),
466 FormSpecs.RELATED_GAP_ROWSPEC,
467 FormSpecs.DEFAULT_ROWSPEC,}));
469 btnImport = new JButton(Messages.MSGUpdatingDatabase.toString());
470 btnImport.addActionListener(e -> {
471 CompletableFuture.runAsync(() -> {
473 if(!impl.getFlag()) {
474 JOptionPane.showMessageDialog(null, Messages.MSGManualUpdateNotCompleteYet.toString());
477 ArrayList<Song> fromJson = Scraping.getFromJson();
478 ArrayList<Song> specificlevelList = Scraping.getSpecificLevelSongs(fromJson, (Integer)DelesteRandomSelector.this.spinnerLevel.getValue(), DelesteRandomSelector.this.checkLessLv.isSelected(), DelesteRandomSelector.this.checkMoreLv.isSelected());
479 ArrayList<Song> specificDifficultyList = Scraping.getSpecificDifficultySongs(specificlevelList, DelesteRandomSelector.this.comboDifficultySelect.getSelectedItem().toString());
480 ArrayList<Song> specificAttributeList = Scraping.getSpecificAttributeSongs(specificDifficultyList, DelesteRandomSelector.this.comboAttribute.getSelectedItem().toString());
481 ArrayList<Song> specificTypeList = Scraping.getSpecificAlbumTypeSongs(specificAttributeList, EstimateAlbumTypeCycle.getCurrentCycle());
482 if(!selectedSongsList.isEmpty()) {
483 selectedSongsList.clear();
485 selectedSongsList.addAll((DelesteRandomSelector.this.comboDifficultySelect.getSelectedItem().equals(Scraping.MASTERPLUS) || DelesteRandomSelector.this.comboDifficultySelect.getSelectedItem().equals(Scraping.LEGACYMASTERPLUS)) ? specificTypeList : specificAttributeList);
486 DelesteRandomSelector.this.logger.info("Songs are selected.We are Ready to go.");
487 JOptionPane.showMessageDialog(null, Messages.MSGCompleteNarrowDown.toString());
488 }, es).whenCompleteAsync((ret, ex) -> {
490 logger.error("Exception was thrown during concurrent process", ex);
491 if(ex instanceof IllegalArgumentException)
493 CrashHandler handle = new CrashHandler(ex.getMessage(), new IllegalStateException(ex));
498 btnImport.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
499 btnImport.setEnabled(false);
500 panelEastMain.add(btnImport, "2, 2, fill, fill");
502 btnConfig = new JButton(Messages.MSGConfigurations.toString());
503 btnConfig.addActionListener(e -> {
504 CompletableFuture.runAsync(() -> {
505 ProcessBuilder builder = new ProcessBuilder("java", "-jar", "Configurations.jar");
508 } catch (IOException e1) {
509 logger.error("Exception was thrown during concurrent process", e1);
510 CrashHandler handle = new CrashHandler(new IllegalStateException(e1));
513 }, es).whenCompleteAsync((ret, ex) -> {
515 logger.error("Exception was thrown during concurrent process", ex);
516 CrashHandler handle = new CrashHandler(ex.getMessage(), new IllegalStateException(ex));
521 panelEastMain.add(btnConfig, "2, 6, fill, fill");
523 btnStart = new JButton(Messages.MSGCalcStart.toString());
524 btnStart.addActionListener(e -> {
525 CompletableFuture.runAsync(() -> {
526 if(selectedSongsList.isEmpty()) {
527 logger.warn("User has not started playing yet.");
530 Random random = new Random(System.currentTimeMillis());
531 toolIntegrateList = new ArrayList<>();
532 StringBuilder paneBuilder = new StringBuilder();
533 DelesteRandomSelector.this.integratorArray = new String[DelesteRandomSelector.this.property.getSongLimit()];
534 for(int i = 0; i < DelesteRandomSelector.this.property.getSongLimit(); i++) {
535 int randomInt = random.nextInt(selectedSongsList.size());
536 String typeString = DelesteRandomSelector.this.comboDifficultySelect.getSelectedItem().equals(Scraping.MASTERPLUS) || DelesteRandomSelector.this.comboDifficultySelect.getSelectedItem().equals(Scraping.LEGACYMASTERPLUS) ? EstimateAlbumTypeCycle.getCurrentCycle() : "";
537 paneBuilder.append(i + 1)
538 .append(Messages.MSGNumberOfSongs.toString())
540 .append(selectedSongsList.get(randomInt).getAttribute())
542 .append(selectedSongsList.get(randomInt).getDifficulty())
544 .append(selectedSongsList.get(randomInt).getName())
546 .append(selectedSongsList.get(randomInt).getLevel())
550 this.integratorArray[i] = selectedSongsList.get(randomInt).getName() + "(Lv" + selectedSongsList.get(randomInt).getLevel() + ")\n";
551 toolIntegrateList.add(selectedSongsList.get(randomInt));
553 paneBuilder.append(Messages.MSGThisPhrase.toString())
554 .append(this.property.getSongLimit())
555 .append(Messages.MSGPlayPhrase.toString());
556 DelesteRandomSelector.this.textArea.setText(paneBuilder.toString());
557 DelesteRandomSelector.this.integratorBool = true;
558 DelesteRandomSelector.this.logger.info("show up completed.");
559 labelCurrentSongOrderTool.setText("null");
560 progressTool.setValue(0);
561 listToolMapDataFuture = CompletableFuture.supplyAsync(() -> {
562 List<String> data = toolIntegrateList.stream()
563 .map(s -> s.getName())
564 .collect(Collectors.toList());
565 fetchData = new FetchFromAPI(data.toArray(new String[0]));
566 return fetchData.getInformation();
568 logger.debug("api fetch inquery published");
569 }, es).whenCompleteAsync((ret, ex) -> {
571 logger.error("Exception was thrown during concurrent process", ex);
572 CrashHandler handle = new CrashHandler(ex.getMessage(), new IllegalStateException(ex));
577 btnStart.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
578 panelEastMain.add(btnStart, "2, 4, fill, fill");
580 btnManualUpdate = new JButton(Messages.MSGManualUpdate.toString());
581 btnManualUpdate.addActionListener(e -> {
582 impl = new ManualUpdateThreadImpl();
583 CompletableFuture.runAsync(impl, es).whenCompleteAsync((t, u) -> {
585 logger.warn("Exception while processing update manually.", u);
586 CrashHandler handle = new CrashHandler(u.getMessage(), new IllegalStateException(u));
588 JOptionPane.showMessageDialog(null, "There was a problem during processing library update manually.\nIf this appears repeatedly, please contact developer with your app log.");
592 panelEastMain.add(btnManualUpdate, "2, 8, fill, fill");
594 btnTwitterIntegration = new JButton(Messages.MSGTwitterIntegration.toString());
595 btnTwitterIntegration.addActionListener(e -> {
596 CompletableFuture.runAsync(() -> {
597 boolean authorizationStatus = TwitterIntegration.authorization();
598 String updatedStatus = Messages.MSGUsingThisAppPhrase.toString();
599 int lengthLimit = updatedStatus.length();
600 boolean isBroken = false;
601 if(!DelesteRandomSelector.this.integratorBool) {
602 JOptionPane.showMessageDialog(null, Messages.MSGNotPlayYet.toString());
605 for (String element : DelesteRandomSelector.this.integratorArray) {
606 updatedStatus = updatedStatus + element;
607 lengthLimit += element.length();
608 if(lengthLimit > 69) {
614 updatedStatus = updatedStatus + Messages.MSGTwitterPlayOtherwisePhrase.toString() + "\n#DelesteRandomSelector #デレステ ";
616 updatedStatus = updatedStatus + Messages.MSGTwitterPlayOnlyPhrase.toString() + "\n#DelesteRandomSelector #デレステ ";
618 DelesteRandomSelector.this.logger.info("status message constructed.");
619 lengthLimit = updatedStatus.length();
620 if(authorizationStatus) {
621 int option = JOptionPane.showConfirmDialog(null, Messages.MSGTwitterIntegrationConfirm.toString() + updatedStatus + Messages.MSGStringLength.toString() + lengthLimit);
622 DelesteRandomSelector.this.logger.info("user seletced: " + option);
624 case JOptionPane.OK_OPTION:
625 TwitterIntegration.PostTwitter(updatedStatus);
626 DelesteRandomSelector.this.logger.info("Success to update the status.");
627 JOptionPane.showMessageDialog(null, Messages.MSGCompletePost.toString());
629 case JOptionPane.NO_OPTION:
630 DelesteRandomSelector.this.logger.info("There is no will to post.");
632 case JOptionPane.CANCEL_OPTION:
633 DelesteRandomSelector.this.logger.info("The Operation was canceled by user.");
639 DelesteRandomSelector.this.logger.info("seems to reject the permission.it should need try again.");
641 }, es).whenCompleteAsync((ret, ex) -> {
643 logger.error("Exception was thrown during concurrent process", ex);
644 CrashHandler handle = new CrashHandler(ex.getMessage(), new IllegalStateException(ex));
649 btnTwitterIntegration.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 11));
650 panelEastMain.add(btnTwitterIntegration, "2, 10, fill, fill");
652 btnExit = new JButton(Messages.MSGTerminate.toString());
653 btnExit.addActionListener(e -> {
654 if(DelesteRandomSelector.this.softwareUpdateFuture.isDone() || DelesteRandomSelector.this.albumTypeEstimateFuture.isDone() || !this.impl.getFlag()) {
655 DelesteRandomSelector.this.logger.info("Requested Exit by Button.");
656 logger.info("Shut down thread pool.");
660 JOptionPane.showMessageDialog(null, Messages.MSGInternalYpdateNotDoneYet.toString());
663 btnExit.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
664 panelEastMain.add(btnExit, "2, 12, fill, fill");
666 panelCenterMain = new JPanel();
667 panelMain.add(panelCenterMain, BorderLayout.CENTER);
668 panelCenterMain.setLayout(new BorderLayout(0, 0));
670 scrollPane = new JScrollPane();
671 panelCenterMain.add(scrollPane);
673 textArea = new JTextArea();
674 textArea.setText(Messages.MSGNarrowDownProcedure.toString() + property.getSongLimit() + Messages.MSGCurrentAlbumType.toString() + albumType);
675 textArea.setEditable(false);
676 scrollPane.setViewportView(textArea);
678 tabbedPane = new JTabbedPane(JTabbedPane.TOP);
679 tabbedPane.addChangeListener(e -> {
680 CompletableFuture.runAsync(() -> {
681 labelToolProgress.setText(Messages.MSGAPIWaitAPIFetch.toString());
682 String currentTabName = tabbedPane.getTitleAt(tabbedPane.getSelectedIndex());
683 if(currentTabName.equals("SongInfo") && labelCurrentSongOrderTool.getText().equals("null")) {
684 logger.info("Detected switching tool tab");
685 if(listToolMapDataFuture == null) {
686 logger.warn("Async task has not initialized yet. Aborting...");
689 if(toolIntegrateList == null) {
692 listToolMapData = listToolMapDataFuture.join();
693 Song firstSong = toolIntegrateList.get(0);
694 Map<String, String> fetchMap = new HashMap<>();
695 for(Map<String, String> tmpMap : listToolMapData) {
696 String normalizeApiName = Normalizer.normalize(tmpMap.get("songname").toString(), Normalizer.Form.NFKD);
697 String normalizeLocalName = Normalizer.normalize(firstSong.getName(), Normalizer.Form.NFKD);
698 if(normalizeApiName.equals(normalizeLocalName)) {
703 labelSongNameToolTip.setText(firstSong.getName());
704 labelAttributeToolTip.setText(firstSong.getAttribute());
705 labelDifficultyToolTip.setText(firstSong.getDifficulty());
706 labelLevelToolTip.setText(String.valueOf(firstSong.getLevel()));
707 labelNotesToolTip.setText(String.valueOf(firstSong.getNotes()));
708 labelCurrentSongOrderTool.setText("1");
709 labelLyricToolTip.setText(fetchMap.get("lyric"));
710 labelComposerToolTip.setText(fetchMap.get("composer"));
711 labelArrangeToolTip.setText(fetchMap.get("arrange"));
712 labelMemberToolTip.setText("<html><body>" + fetchMap.get("member") + "</html></body>");
714 if(currentTabName.equals("Scores") && labelScoreCurrentSongOrder.getText().equals("null")) {
715 logger.info("Detected switching score tab");
716 if(toolIntegrateList == null)
718 Song firstSong = toolIntegrateList.get(0);
719 labelScoreCurrentSongOrder.setText("1");
720 labelScoreSongnameDynamic.setText("<html><body>" + firstSong.getName() + "</body></html>");
721 labelScoreAttributeDynamic.setText(firstSong.getAttribute());
722 labelScoreDifficultyDynamic.setText(firstSong.getDifficulty());
723 labelScoreLevelDynamic.setText(String.valueOf(firstSong.getLevel()));
724 labelScoreNotesDynamic.setText(String.valueOf(firstSong.getNotes()));
726 }, es).whenCompleteAsync((ret, ex) -> {
727 labelToolProgress.setText("Information parse Complete.");
729 logger.error("Exception was thrown during concurrent process", ex);
730 CrashHandler handle = new CrashHandler(ex.getMessage(), new IllegalStateException(ex));
735 tabbedPane.addTab("Main", null, panelMain, null);
736 contentPane.add(tabbedPane, "name_307238585319500");
738 panelInfo = new JPanel();
739 tabbedPane.addTab("SongInfo", null, panelInfo, null);
740 panelInfo.setLayout(new BorderLayout(0, 0));
742 panelNorthTool = new JPanel();
743 panelInfo.add(panelNorthTool, BorderLayout.NORTH);
744 panelNorthTool.setLayout(new FormLayout(new ColumnSpec[] {
745 ColumnSpec.decode("center:max(524dlu;default)"),
746 FormSpecs.RELATED_GAP_COLSPEC,
747 ColumnSpec.decode("max(30dlu;default)"),},
749 RowSpec.decode("max(16dlu;default)"),}));
751 labelSubToolTitle = new JLabel("楽曲情報");
752 labelSubToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 16));
753 panelNorthTool.add(labelSubToolTitle, "1, 1");
755 labelVersionTool = new JLabel(CheckVersion.getVersion());
756 labelVersionTool.setFont(new Font("SansSerif", Font.BOLD, 12));
757 panelNorthTool.add(labelVersionTool, "3, 1");
759 panelCenterTool = new JPanel();
760 panelInfo.add(panelCenterTool, BorderLayout.CENTER);
761 panelCenterTool.setLayout(new FormLayout(new ColumnSpec[] {
762 FormSpecs.RELATED_GAP_COLSPEC,
763 ColumnSpec.decode("max(40dlu;default)"),
764 FormSpecs.RELATED_GAP_COLSPEC,
765 ColumnSpec.decode("10dlu"),
766 FormSpecs.RELATED_GAP_COLSPEC,
767 ColumnSpec.decode("10dlu"),
768 FormSpecs.RELATED_GAP_COLSPEC,
769 ColumnSpec.decode("max(12dlu;default)"),
770 FormSpecs.RELATED_GAP_COLSPEC,
771 ColumnSpec.decode("max(90dlu;default)"),
772 FormSpecs.RELATED_GAP_COLSPEC,
773 ColumnSpec.decode("max(14dlu;default)"),
774 FormSpecs.RELATED_GAP_COLSPEC,
775 FormSpecs.RELATED_GAP_COLSPEC,
776 ColumnSpec.decode("max(14dlu;default)"),
777 FormSpecs.RELATED_GAP_COLSPEC,
778 ColumnSpec.decode("max(90dlu;default)"),
779 FormSpecs.RELATED_GAP_COLSPEC,
780 FormSpecs.DEFAULT_COLSPEC,
781 FormSpecs.RELATED_GAP_COLSPEC,
782 FormSpecs.DEFAULT_COLSPEC,
783 FormSpecs.RELATED_GAP_COLSPEC,
784 FormSpecs.DEFAULT_COLSPEC,
785 FormSpecs.RELATED_GAP_COLSPEC,
786 ColumnSpec.decode("max(90dlu;default)"),},
788 FormSpecs.RELATED_GAP_ROWSPEC,
789 FormSpecs.DEFAULT_ROWSPEC,
790 FormSpecs.RELATED_GAP_ROWSPEC,
791 FormSpecs.DEFAULT_ROWSPEC,
792 FormSpecs.RELATED_GAP_ROWSPEC,
793 FormSpecs.DEFAULT_ROWSPEC,
794 FormSpecs.RELATED_GAP_ROWSPEC,
795 FormSpecs.DEFAULT_ROWSPEC,
796 FormSpecs.RELATED_GAP_ROWSPEC,
797 FormSpecs.DEFAULT_ROWSPEC,
798 FormSpecs.RELATED_GAP_ROWSPEC,
799 FormSpecs.DEFAULT_ROWSPEC,
800 FormSpecs.RELATED_GAP_ROWSPEC,
801 FormSpecs.DEFAULT_ROWSPEC,
802 FormSpecs.RELATED_GAP_ROWSPEC,
803 FormSpecs.DEFAULT_ROWSPEC,
804 FormSpecs.RELATED_GAP_ROWSPEC,
805 FormSpecs.DEFAULT_ROWSPEC,
806 FormSpecs.RELATED_GAP_ROWSPEC,
807 FormSpecs.DEFAULT_ROWSPEC,
808 FormSpecs.RELATED_GAP_ROWSPEC,
809 FormSpecs.DEFAULT_ROWSPEC,
810 FormSpecs.RELATED_GAP_ROWSPEC,
811 FormSpecs.DEFAULT_ROWSPEC,
812 FormSpecs.RELATED_GAP_ROWSPEC,
813 FormSpecs.DEFAULT_ROWSPEC,
814 FormSpecs.RELATED_GAP_ROWSPEC,
815 FormSpecs.DEFAULT_ROWSPEC,
816 FormSpecs.RELATED_GAP_ROWSPEC,
817 FormSpecs.DEFAULT_ROWSPEC,
818 FormSpecs.RELATED_GAP_ROWSPEC,
819 FormSpecs.DEFAULT_ROWSPEC,
820 FormSpecs.RELATED_GAP_ROWSPEC,
821 FormSpecs.DEFAULT_ROWSPEC,
822 FormSpecs.RELATED_GAP_ROWSPEC,
823 FormSpecs.DEFAULT_ROWSPEC,
824 FormSpecs.RELATED_GAP_ROWSPEC,
825 FormSpecs.DEFAULT_ROWSPEC,
826 FormSpecs.RELATED_GAP_ROWSPEC,
827 FormSpecs.DEFAULT_ROWSPEC,
828 FormSpecs.RELATED_GAP_ROWSPEC,
829 FormSpecs.DEFAULT_ROWSPEC,}));
831 labelInfoPlaySongs = new JLabel(Messages.MSGInfoPlayedSongs.toString());
832 labelInfoPlaySongs.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
833 panelCenterTool.add(labelInfoPlaySongs, "2, 2, center, default");
835 labelSongNameToolTitle = new JLabel(Messages.MSGInfoSongName.toString());
836 labelSongNameToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
837 panelCenterTool.add(labelSongNameToolTitle, "2, 6, center, default");
839 labelSongNameToolTip = new JLabel(Messages.MSGInfoWait.toString());
840 labelSongNameToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
841 panelCenterTool.add(labelSongNameToolTip, "10, 6, center, default");
843 labelLyricToolTitle = new JLabel(Messages.MSGInfoLyricsBy.toString());
844 labelLyricToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
845 panelCenterTool.add(labelLyricToolTitle, "17, 6, center, default");
847 labelLyricToolTip = new JLabel(Messages.MSGInfoWait.toString());
848 labelLyricToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
849 panelCenterTool.add(labelLyricToolTip, "25, 6, center, default");
851 labelAttributeToolTitle = new JLabel(Messages.MSGInfoSongAttribute.toString());
852 labelAttributeToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
853 panelCenterTool.add(labelAttributeToolTitle, "2, 10, center, default");
855 labelAttributeToolTip = new JLabel(Messages.MSGInfoWait.toString());
856 labelAttributeToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
857 panelCenterTool.add(labelAttributeToolTip, "10, 10, center, default");
859 labelComposerToolTitle = new JLabel(Messages.MSGInfoComposedBy.toString());
860 labelComposerToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
861 panelCenterTool.add(labelComposerToolTitle, "17, 10, center, default");
863 labelComposerToolTip = new JLabel(Messages.MSGInfoWait.toString());
864 labelComposerToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
865 panelCenterTool.add(labelComposerToolTip, "25, 10, center, default");
867 labelDifficultyToolTitle = new JLabel(Messages.MSGInfoSongDifficulty.toString());
868 labelDifficultyToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
869 panelCenterTool.add(labelDifficultyToolTitle, "2, 14, center, default");
871 labelDifficultyToolTip = new JLabel(Messages.MSGInfoWait.toString());
872 labelDifficultyToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
873 panelCenterTool.add(labelDifficultyToolTip, "10, 14, center, default");
875 labelArrangeToolTitle = new JLabel(Messages.MSGInfoArrangedBy.toString());
876 labelArrangeToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
877 panelCenterTool.add(labelArrangeToolTitle, "17, 14, center, default");
879 labelArrangeToolTip = new JLabel(Messages.MSGInfoWait.toString());
880 labelArrangeToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
881 panelCenterTool.add(labelArrangeToolTip, "25, 14, center, default");
883 labelLevelToolTitle = new JLabel(Messages.MSGInfoSongLevel.toString());
884 labelLevelToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
885 panelCenterTool.add(labelLevelToolTitle, "2, 18, center, default");
887 labelLevelToolTip = new JLabel(Messages.MSGInfoWait.toString());
888 labelLevelToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
889 panelCenterTool.add(labelLevelToolTip, "10, 18, center, default");
891 labelMemberToolTitle = new JLabel(Messages.MSGInfoMember.toString());
892 labelMemberToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
893 panelCenterTool.add(labelMemberToolTitle, "17, 18, center, default");
895 labelMemberToolTip = new JLabel(Messages.MSGInfoWait.toString());
896 labelMemberToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
897 panelCenterTool.add(labelMemberToolTip, "25, 18, center, default");
899 labelNotesToolTitle = new JLabel(Messages.MSGInfoSongNotes.toString());
900 labelNotesToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
901 panelCenterTool.add(labelNotesToolTitle, "2, 22, center, default");
903 labelNotesToolTip = new JLabel(Messages.MSGInfoWait.toString());
904 labelNotesToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
905 panelCenterTool.add(labelNotesToolTip, "10, 22, center, default");
907 btnNextSongTool = new JButton("next");
908 btnNextSongTool.addActionListener(e -> {
909 CompletableFuture.runAsync(() -> {
910 int currentIndex = Integer.parseInt(labelCurrentSongOrderTool.getText()) - 1;
911 if(currentIndex != property.getSongLimit() - 1) {
912 Song nextSong = toolIntegrateList.get(currentIndex + 1);
913 logger.info("currently : {} Next: {}", currentIndex + 1, currentIndex + 2);
914 logger.info("nextSong: {}", nextSong);
915 Map<String, String> fetchMap = new HashMap<>();
916 for(Map<String, String> tmpMap : listToolMapData) {
917 String normalizeApiName = Normalizer.normalize(tmpMap.get("songname").toString(), Normalizer.Form.NFKD);
918 String normalizeLocalName = Normalizer.normalize(nextSong.getName(), Normalizer.Form.NFKD);
919 if(normalizeApiName.equals(normalizeLocalName)) {
924 labelSongNameToolTip.setText(nextSong.getName());
925 labelAttributeToolTip.setText(nextSong.getAttribute());
926 labelDifficultyToolTip.setText(nextSong.getDifficulty());
927 labelLevelToolTip.setText(String.valueOf(nextSong.getLevel()));
928 labelNotesToolTip.setText(String.valueOf(nextSong.getNotes()));
929 labelCurrentSongOrderTool.setText(String.valueOf(currentIndex + 2));
930 labelLyricToolTip.setText(fetchMap.get("lyric"));
931 labelComposerToolTip.setText(fetchMap.get("composer"));
932 labelArrangeToolTip.setText(fetchMap.get("arrange"));
933 labelMemberToolTip.setText("<html><body>" + fetchMap.get("member") + "</html></body>");
935 }, es).whenCompleteAsync((ret, ex) -> {
937 logger.error("Exception was thrown during concurrent process", ex);
942 btnPrevSongTool = new JButton("prev");
943 btnPrevSongTool.addActionListener(e -> {
944 CompletableFuture.runAsync(() -> {
945 int currentIndex = Integer.parseInt(labelCurrentSongOrderTool.getText()) - 1;
946 if(currentIndex != 0) {
947 Song prevSong = toolIntegrateList.get(currentIndex - 1);
948 logger.info("currently : {} Next: {}", currentIndex + 1, currentIndex);
949 logger.info("prevSong: {}", prevSong);
950 Map<String, String> fetchMap = new HashMap<>();
951 for(Map<String, String> tmpMap : listToolMapData) {
952 String normalizeApiName = Normalizer.normalize(tmpMap.get("songname").toString(), Normalizer.Form.NFKD);
953 String normalizeLocalName = Normalizer.normalize(prevSong.getName(), Normalizer.Form.NFKD);
954 if(normalizeApiName.equals(normalizeLocalName)) {
959 labelSongNameToolTip.setText(prevSong.getName());
960 labelAttributeToolTip.setText(prevSong.getAttribute());
961 labelDifficultyToolTip.setText(prevSong.getDifficulty());
962 labelLevelToolTip.setText(String.valueOf(prevSong.getLevel()));
963 labelNotesToolTip.setText(String.valueOf(prevSong.getNotes()));
964 labelCurrentSongOrderTool.setText(String.valueOf(currentIndex));
965 labelLyricToolTip.setText(fetchMap.get("lyric"));
966 labelComposerToolTip.setText(fetchMap.get("composer"));
967 labelArrangeToolTip.setText(fetchMap.get("arrange"));
968 labelMemberToolTip.setText("<html><body>" + fetchMap.get("member") + "</html></body>");
970 }, es).whenCompleteAsync((ret, ex) -> {
972 logger.error("Exception was thrown during concurrent process", ex);
976 btnPrevSongTool.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
977 panelCenterTool.add(btnPrevSongTool, "10, 28");
979 labelCurrentSongOrderTool = new JLabel("null");
980 panelCenterTool.add(labelCurrentSongOrderTool, "12, 28");
982 labelSlashTool = new JLabel("/");
983 panelCenterTool.add(labelSlashTool, "14, 28");
985 labelSongLimitTool = new JLabel(String.valueOf(this.property.getSongLimit()));
986 panelCenterTool.add(labelSongLimitTool, "15, 28");
987 btnNextSongTool.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
988 panelCenterTool.add(btnNextSongTool, "17, 28");
990 btnMoreInfoTool = new JButton(Messages.MSGInfoOpenBrowser.toString());
991 btnMoreInfoTool.addActionListener(e -> {
992 CompletableFuture.runAsync(() -> {
993 int currentIndex = Integer.parseInt(labelCurrentSongOrderTool.getText()) - 1;
994 Song currentSong = toolIntegrateList.get(currentIndex);
995 Map<String, String> fetchMap = new HashMap<>();
996 for(Map<String, String> tmpMap : listToolMapData) {
997 String normalizeApiName = Normalizer.normalize(tmpMap.get("songname").toString(), Normalizer.Form.NFKD);
998 String normalizeLocalName = Normalizer.normalize(currentSong.getName(), Normalizer.Form.NFKD);
999 if(normalizeApiName.equals(normalizeLocalName)) {
1004 Desktop desk = Desktop.getDesktop();
1005 String api = fetchMap.get("link");
1009 logger.info("Opening default browser with : {}", uri);
1011 } catch (URISyntaxException | IOException e1) {
1012 JOptionPane.showMessageDialog(null, "このメッセージは仮です。Exception : " + e1.getClass().getSimpleName());
1013 logger.error("Exception while opening default browser.", e1);
1015 }, es).whenCompleteAsync((ret, ex) -> {
1017 logger.warn("Exception was thrown during action events.", ex);
1021 btnMoreInfoTool.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
1022 panelCenterTool.add(btnMoreInfoTool, "25, 28");
1024 labelToolProgress = new JLabel(Messages.MSGAPIWaitAPIFetch.toString());
1025 labelToolProgress.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
1026 panelCenterTool.add(labelToolProgress, "10, 32, center, default");
1028 progressTool = new JProgressBar();
1029 progressTool.setStringPainted(true);
1030 progressTool.setValue(0);
1031 progressTool.setMaximum(property.getSongLimit());
1032 panelCenterTool.add(progressTool, "17, 32");
1034 labelInfoProgressSongName = new JLabel("Processing:");
1035 labelInfoProgressSongName.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
1036 panelCenterTool.add(labelInfoProgressSongName, "10, 34");
1038 panelScore = new JPanel();
1039 tabbedPane.addTab("Scores", null, panelScore, null);
1040 panelScore.setLayout(new BorderLayout(0, 0));
1042 panelScoreNorth = new JPanel();
1043 panelScore.add(panelScoreNorth, BorderLayout.NORTH);
1044 panelScoreNorth.setLayout(new FormLayout(new ColumnSpec[] {
1045 ColumnSpec.decode("828px"),
1046 FormSpecs.RELATED_GAP_COLSPEC,
1047 ColumnSpec.decode("max(53dlu;default)"),},
1049 RowSpec.decode("20px"),}));
1051 labelScoreTitle = new JLabel("スコア、ファン計算");
1052 labelScoreTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 16));
1053 panelScoreNorth.add(labelScoreTitle, "1, 1, center, center");
1055 labelScoreVersion = new JLabel(CheckVersion.getVersion());
1056 labelScoreVersion.setFont(new Font("SansSerif", Font.BOLD, 12));
1057 panelScoreNorth.add(labelScoreVersion, "3, 1, center, default");
1059 panelScoreCenter = new JPanel();
1060 panelScore.add(panelScoreCenter, BorderLayout.CENTER);
1061 panelScoreCenter.setLayout(new FormLayout(new ColumnSpec[] {
1062 FormSpecs.RELATED_GAP_COLSPEC,
1063 ColumnSpec.decode("max(60dlu;default)"),
1064 FormSpecs.RELATED_GAP_COLSPEC,
1065 ColumnSpec.decode("max(60dlu;default)"),
1066 FormSpecs.RELATED_GAP_COLSPEC,
1067 ColumnSpec.decode("max(60dlu;default):grow"),
1068 FormSpecs.RELATED_GAP_COLSPEC,
1069 ColumnSpec.decode("max(68dlu;default)"),
1070 FormSpecs.RELATED_GAP_COLSPEC,
1071 ColumnSpec.decode("max(59dlu;default)"),
1072 FormSpecs.RELATED_GAP_COLSPEC,
1073 ColumnSpec.decode("center:max(97dlu;default)"),
1074 FormSpecs.RELATED_GAP_COLSPEC,
1075 ColumnSpec.decode("max(25dlu;default)"),
1076 FormSpecs.RELATED_GAP_COLSPEC,
1077 ColumnSpec.decode("max(9dlu;default)"),
1078 FormSpecs.RELATED_GAP_COLSPEC,
1079 ColumnSpec.decode("max(25dlu;default)"),
1080 FormSpecs.RELATED_GAP_COLSPEC,
1081 ColumnSpec.decode("40dlu:grow"),},
1083 FormSpecs.RELATED_GAP_ROWSPEC,
1084 FormSpecs.DEFAULT_ROWSPEC,
1085 FormSpecs.RELATED_GAP_ROWSPEC,
1086 FormSpecs.DEFAULT_ROWSPEC,
1087 FormSpecs.RELATED_GAP_ROWSPEC,
1088 FormSpecs.DEFAULT_ROWSPEC,
1089 FormSpecs.RELATED_GAP_ROWSPEC,
1090 FormSpecs.DEFAULT_ROWSPEC,
1091 FormSpecs.RELATED_GAP_ROWSPEC,
1092 FormSpecs.DEFAULT_ROWSPEC,
1093 FormSpecs.RELATED_GAP_ROWSPEC,
1094 FormSpecs.DEFAULT_ROWSPEC,
1095 FormSpecs.RELATED_GAP_ROWSPEC,
1096 FormSpecs.DEFAULT_ROWSPEC,
1097 FormSpecs.RELATED_GAP_ROWSPEC,
1098 RowSpec.decode("max(13dlu;default)"),
1099 FormSpecs.RELATED_GAP_ROWSPEC,
1100 FormSpecs.DEFAULT_ROWSPEC,
1101 FormSpecs.RELATED_GAP_ROWSPEC,
1102 FormSpecs.DEFAULT_ROWSPEC,
1103 FormSpecs.RELATED_GAP_ROWSPEC,
1104 FormSpecs.DEFAULT_ROWSPEC,
1105 FormSpecs.RELATED_GAP_ROWSPEC,
1106 FormSpecs.DEFAULT_ROWSPEC,
1107 FormSpecs.RELATED_GAP_ROWSPEC,
1108 FormSpecs.DEFAULT_ROWSPEC,
1109 FormSpecs.RELATED_GAP_ROWSPEC,
1110 FormSpecs.DEFAULT_ROWSPEC,
1111 FormSpecs.RELATED_GAP_ROWSPEC,
1112 FormSpecs.DEFAULT_ROWSPEC,
1113 FormSpecs.RELATED_GAP_ROWSPEC,
1114 FormSpecs.DEFAULT_ROWSPEC,
1115 FormSpecs.RELATED_GAP_ROWSPEC,
1116 FormSpecs.DEFAULT_ROWSPEC,
1117 FormSpecs.RELATED_GAP_ROWSPEC,
1118 FormSpecs.DEFAULT_ROWSPEC,
1119 FormSpecs.RELATED_GAP_ROWSPEC,
1120 FormSpecs.DEFAULT_ROWSPEC,
1121 FormSpecs.RELATED_GAP_ROWSPEC,
1122 RowSpec.decode("default:grow"),}));
1124 labelScoreUserPlayed = new JLabel("Your score");
1125 panelScoreCenter.add(labelScoreUserPlayed, "4, 10, center, default");
1127 fieldScoreUserPlayed = new JTextField();
1128 panelScoreCenter.add(fieldScoreUserPlayed, "6, 10, fill, default");
1129 fieldScoreUserPlayed.setColumns(10);
1131 lblSongname = new JLabel("Songname");
1132 panelScoreCenter.add(lblSongname, "10, 10, center, default");
1134 labelScoreSongnameDynamic = new JLabel("<dynamic>");
1135 panelScoreCenter.add(labelScoreSongnameDynamic, "12, 10, center, default");
1137 labelScoreEarnedFan = new JLabel("Earned Fan");
1138 panelScoreCenter.add(labelScoreEarnedFan, "4, 14, center, default");
1140 fieldScoreEarnedFan = new JTextField();
1141 panelScoreCenter.add(fieldScoreEarnedFan, "6, 14, fill, default");
1142 fieldScoreEarnedFan.setColumns(10);
1144 labelScoreAttribute = new JLabel("Attribute");
1145 panelScoreCenter.add(labelScoreAttribute, "10, 14, center, default");
1147 labelScoreAttributeDynamic = new JLabel("<dynamic>");
1148 panelScoreCenter.add(labelScoreAttributeDynamic, "12, 14");
1150 lblRoom = new JLabel("room");
1151 panelScoreCenter.add(lblRoom, "4, 18, center, default");
1153 fieldScoreRoom = new JTextField();
1154 panelScoreCenter.add(fieldScoreRoom, "6, 18, fill, default");
1155 fieldScoreRoom.setColumns(10);
1157 labelScoreDifficulty = new JLabel("Difficulty");
1158 panelScoreCenter.add(labelScoreDifficulty, "10, 18, center, default");
1160 labelScoreDifficultyDynamic = new JLabel("<dynamic>");
1161 panelScoreCenter.add(labelScoreDifficultyDynamic, "12, 18");
1163 lblCenter = new JLabel("center");
1164 panelScoreCenter.add(lblCenter, "4, 22, center, default");
1166 fieldScoreCenter = new JTextField();
1167 panelScoreCenter.add(fieldScoreCenter, "6, 22, fill, default");
1168 fieldScoreCenter.setColumns(10);
1170 labelScoreLevel = new JLabel("Level");
1171 panelScoreCenter.add(labelScoreLevel, "10, 22, center, default");
1173 labelScoreLevelDynamic = new JLabel("<dynamic>");
1174 panelScoreCenter.add(labelScoreLevelDynamic, "12, 22");
1176 lblProduce = new JLabel("produce");
1177 panelScoreCenter.add(lblProduce, "4, 26, center, default");
1179 fieldScoreProduce = new JTextField();
1180 panelScoreCenter.add(fieldScoreProduce, "6, 26, fill, default");
1181 fieldScoreProduce.setColumns(10);
1183 labelScoreNotes = new JLabel("Notes");
1184 panelScoreCenter.add(labelScoreNotes, "10, 26, center, default");
1186 labelScoreNotesDynamic = new JLabel("<dynamic>");
1187 panelScoreCenter.add(labelScoreNotesDynamic, "12, 26");
1189 lblPremium = new JLabel("premium");
1190 panelScoreCenter.add(lblPremium, "4, 30, center, default");
1192 fieldScorePremium = new JTextField();
1193 panelScoreCenter.add(fieldScorePremium, "6, 30, fill, default");
1194 fieldScorePremium.setColumns(10);
1196 labelPlayerScore = new JLabel("Estimated Score");
1197 panelScoreCenter.add(labelPlayerScore, "10, 30, center, default");
1199 labelPlayerScoreDynamic = new JLabel("<dynamic>");
1200 panelScoreCenter.add(labelPlayerScoreDynamic, "12, 30");
1202 labelScoreCurrentSongOrder = new JLabel("null");
1203 panelScoreCenter.add(labelScoreCurrentSongOrder, "14, 30, center, default");
1205 labelScoreSlash = new JLabel("/");
1206 panelScoreCenter.add(labelScoreSlash, "16, 30, center, default");
1208 labelScoreOrderMax = new JLabel(String.valueOf(property.getSongLimit()));
1209 panelScoreCenter.add(labelScoreOrderMax, "18, 30, center, default");
1211 btnScorePrev = new JButton("Prev");
1212 btnScorePrev.addActionListener(new ActionListener() {
1214 public void actionPerformed(ActionEvent e) {
1215 CompletableFuture.runAsync(() -> {
1216 int currentIndex = Integer.parseInt(labelScoreCurrentSongOrder.getText()) - 1;
1217 if(currentIndex != 0) {
1218 Song prevSong = toolIntegrateList.get(currentIndex - 1);
1219 logger.info("currently : {} Next: {}", currentIndex + 1, currentIndex);
1220 logger.info("prevSong: {}", prevSong);
1221 labelScoreSongnameDynamic.setText("<html><body>" + prevSong.getName() + "</body></html>");
1222 labelScoreAttributeDynamic.setText(prevSong.getAttribute());
1223 labelScoreDifficultyDynamic.setText(prevSong.getDifficulty());
1224 labelScoreLevelDynamic.setText(String.valueOf(prevSong.getLevel()));
1225 labelScoreNotesDynamic.setText(String.valueOf(prevSong.getNotes()));
1226 labelScoreCurrentSongOrder.setText(String.valueOf(currentIndex));
1231 panelScoreCenter.add(btnScorePrev, "14, 32");
1233 btnScoreNext = new JButton("Next");
1234 btnScoreNext.addActionListener(new ActionListener() {
1236 public void actionPerformed(ActionEvent e) {
1237 CompletableFuture.runAsync(() -> {
1238 int currentIndex = Integer.parseInt(labelScoreCurrentSongOrder.getText()) - 1;
1239 if(currentIndex != property.getSongLimit() - 1) {
1240 Song nextSong = toolIntegrateList.get(currentIndex + 1);
1241 logger.info("currently : {} Next: {}", currentIndex + 1, currentIndex + 2);
1242 logger.info("nextSong: {}", nextSong);
1243 labelScoreSongnameDynamic.setText("<html><body>" + nextSong.getName() + "</body></html>");
1244 labelScoreAttributeDynamic.setText(nextSong.getAttribute());
1245 labelScoreDifficultyDynamic.setText(nextSong.getDifficulty());
1246 labelScoreLevelDynamic.setText(String.valueOf(nextSong.getLevel()));
1247 labelScoreNotesDynamic.setText(String.valueOf(nextSong.getNotes()));
1248 labelScoreCurrentSongOrder.setText(String.valueOf(currentIndex + 2));
1253 panelScoreCenter.add(btnScoreNext, "18, 32");
1255 labelPlayerFan = new JLabel("Estimated Fan");
1256 panelScoreCenter.add(labelPlayerFan, "10, 34, center, default");
1258 labelPlayerFanDynamic = new JLabel("<dynamic>");
1259 panelScoreCenter.add(labelPlayerFanDynamic, "12, 34");
1261 button = new JButton("自動計算");
1262 button.addActionListener(new ActionListener() {
1264 public void actionPerformed(ActionEvent e) {
1265 CompletableFuture.runAsync(() -> {
1266 String scoreStr = fieldScoreUserPlayed.getText();
1267 String fanStr = fieldScoreEarnedFan.getText();
1268 if(scoreStr.isEmpty() && fanStr.isEmpty()) {
1269 logger.warn("there is no data to calculate.");
1270 JOptionPane.showMessageDialog(null, "計算できるデータが存在しません。スコアかファン数のどちらかは必ず入力してください。");
1273 labelPlayerScoreDynamic.setText("Calculating...");
1274 labelPlayerFanDynamic.setText("Calculating...");
1275 String roomStr = fieldScoreRoom.getText();
1276 String centerStr = fieldScoreCenter.getText();
1277 String produceStr = fieldScoreProduce.getText();
1278 String premiumStr = fieldScorePremium.getText();
1279 if(!scoreStr.isEmpty()) {
1280 int score = Integer.parseInt(scoreStr);
1281 int room = roomStr.isEmpty() ? 100 : Integer.parseInt(roomStr);
1282 int center = centerStr.isEmpty() ? 100 : Integer.parseInt(centerStr);
1283 int produce = produceStr.isEmpty() ? 100 : Integer.parseInt(produceStr);
1284 int premium = premiumStr.isEmpty() ? 100 : Integer.parseInt(premiumStr);
1285 int res = FanCalc.fanAsync(score, room, center, produce, premium).join();
1286 labelPlayerScoreDynamic.setText(String.valueOf(res));
1287 labelPlayerFanDynamic.setText(scoreStr);
1289 int fan = Integer.parseInt(fanStr);
1290 int room = roomStr.isEmpty() ? 100 : Integer.parseInt(fanStr);
1291 int center = centerStr.isEmpty() ? 100 : Integer.parseInt(centerStr);
1292 int produce = produceStr.isEmpty() ? 100 : Integer.parseInt(produceStr);
1293 int premium = premiumStr.isEmpty() ? 100 : Integer.parseInt(premiumStr);
1294 int res = FanCalc.scoreAsync(fan, 1, room, center, produce, premium).join();
1295 labelPlayerFanDynamic.setText(String.valueOf(res));
1296 labelPlayerScoreDynamic.setText(scoreStr);
1298 }, es).whenComplete((ret, ex) -> {
1300 logger.error("Exception was thrown during concurrent process.", ex);
1301 JOptionPane.showMessageDialog(null, "イベント処理中に例外が発生しました。" + ex.getLocalizedMessage());
1306 panelScoreCenter.add(button, "18, 36");
1308 labelPlayerPRP = new JLabel("Estimated PRP");
1309 panelScoreCenter.add(labelPlayerPRP, "10, 38, center, default");
1311 labelPlayerPRPDynamic = new JLabel("<dynamic>");
1312 panelScoreCenter.add(labelPlayerPRPDynamic, "12, 38");
1314 label = new JLabel("<html><body>デレステに表示されている百分率をそのまま入力してください</body></html>");
1315 panelScoreCenter.add(label, "6, 40");
1316 if(isFirst || !this.property.isCheckLibraryUpdates()) {