1 package com.ranfa.main;
3 import java.awt.BorderLayout;
4 import java.awt.CardLayout;
5 import java.awt.Desktop;
6 import java.awt.EventQueue;
8 import java.io.IOException;
10 import java.net.URISyntaxException;
11 import java.nio.file.Files;
12 import java.nio.file.Paths;
13 import java.text.Normalizer;
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.List;
18 import java.util.Random;
19 import java.util.concurrent.CompletableFuture;
20 import java.util.concurrent.ExecutorService;
21 import java.util.concurrent.Executors;
22 import java.util.function.BiConsumer;
23 import java.util.stream.Collectors;
25 import javax.swing.DefaultComboBoxModel;
26 import javax.swing.JButton;
27 import javax.swing.JCheckBox;
28 import javax.swing.JComboBox;
29 import javax.swing.JFrame;
30 import javax.swing.JLabel;
31 import javax.swing.JOptionPane;
32 import javax.swing.JPanel;
33 import javax.swing.JScrollPane;
34 import javax.swing.JSpinner;
35 import javax.swing.JTabbedPane;
36 import javax.swing.JTextArea;
37 import javax.swing.border.EmptyBorder;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
42 import com.jgoodies.forms.layout.ColumnSpec;
43 import com.jgoodies.forms.layout.FormLayout;
44 import com.jgoodies.forms.layout.FormSpecs;
45 import com.jgoodies.forms.layout.RowSpec;
46 import com.ranfa.lib.CheckVersion;
47 import com.ranfa.lib.Easter;
48 import com.ranfa.lib.EstimateAlbumTypeCycle;
49 import com.ranfa.lib.ManualUpdateThreadImpl;
50 import com.ranfa.lib.Scraping;
51 import com.ranfa.lib.SettingJSONProperty;
52 import com.ranfa.lib.Settings;
53 import com.ranfa.lib.Song;
54 import com.ranfa.lib.TwitterIntegration;
55 import com.ranfa.lib.Version;
56 import com.ranfa.lib.concurrent.CountedThreadFactory;
57 import com.ranfa.lib.songinfo.FetchFromAPI;
59 @Version(major = 3, minor = 1, patch = 0)
60 public class DelesteRandomSelector extends JFrame {
62 private static ArrayList<Song> selectedSongsList = new ArrayList<>();
64 private JPanel contentPane;
65 private SettingJSONProperty property = new SettingJSONProperty();
66 private String[] integratorArray;
67 private boolean integratorBool = false;
68 private CompletableFuture<Void> softwareUpdateFuture = null;
69 private CompletableFuture<Void> albumTypeEstimateFuture = null;
70 private String albumType = Messages.MSGAlbumTypeBeingCalculated.toString();
71 private Logger logger = LoggerFactory.getLogger(DelesteRandomSelector.class);
72 private ManualUpdateThreadImpl impl;
73 private List<Song> toolIntegrateList;
74 private FetchFromAPI fetchData;
75 private List<Map<String, String>> listToolMapData;
76 private CompletableFuture<List<Map<String, String>>> listToolMapDataFuture;
77 private Easter easter;
78 private JPanel panelMain;
79 private JPanel panelNorthMain;
80 private JLabel labelTitle;
81 private JLabel labelVersion;
82 private JPanel panelWestMain;
83 private JLabel labelDifficulty;
84 private JComboBox<String[]> comboDifficultySelect;
85 private JComboBox<String[]> comboAttribute;
86 private JLabel labelLevel;
87 private JSpinner spinnerLevel;
88 private JCheckBox checkLessLv;
89 private JCheckBox checkMoreLv;
90 private JLabel labelLvCaution;
91 private JPanel panelEastMain;
92 private JButton btnImport;
93 private JButton btnConfig;
94 private JButton btnStart;
95 private JButton btnManualUpdate;
96 private JButton btnTwitterIntegration;
97 private JButton btnExit;
98 private JPanel panelCenterMain;
99 private JScrollPane scrollPane;
100 private JTextArea textArea;
101 private JTabbedPane tabbedPane;
102 private JPanel panelTool;
103 private JPanel panelNorthTool;
104 private JLabel labelSubToolTitle;
105 private JLabel labelVersionTool;
106 private JPanel panelCenterTool;
107 private JLabel lblNewLabel;
108 private JLabel labelSongNameToolTitle;
109 private JLabel labelSongNameToolTip;
110 private JLabel labelAttributeToolTitle;
111 private JLabel labelAttributeToolTip;
112 private JLabel labelDifficultyToolTitle;
113 private JLabel labelDifficultyToolTip;
114 private JLabel labelLevelToolTitle;
115 private JLabel labelLevelToolTip;
116 private JLabel labelNotesToolTitle;
117 private JLabel labelNotesToolTip;
118 private JButton btnPrevSongTool;
119 private JButton btnNextSongTool;
120 private JLabel labelSlashTool;
121 private JLabel labelCurrentSongOrderTool;
122 private JLabel labelSongLimitTool;
123 private JLabel labelLyricToolTitle;
124 private JLabel labelLyricToolTip;
125 private JLabel labelComposerToolTitle;
126 private JLabel labelArrangeToolTitle;
127 private JLabel labelComposerToolTip;
128 private JLabel labelArrangeToolTip;
129 private JLabel labelMemberToolTitle;
130 private JLabel labelMemberToolTip;
131 private JButton btnMoreInfoTool;
133 BiConsumer<ArrayList<Song>, ArrayList<Song>> updateConsumer = (list1, list2) -> {
134 this.logger.info("Checking database updates...");
135 if(list1.size() > list2.size()) {
136 long time = System.currentTimeMillis();
137 this.logger.info("{} Update detected.", (list1.size() - list2.size()));
138 Scraping.writeToJson(list1);
139 this.logger.info("Update completed in {} ms", (System.currentTimeMillis() - time));
140 this.logger.info("Updated database size: {}", list1.size());
142 this.logger.info("database is up-to-date.");
145 Runnable setEnabled = () -> {
147 Thread.sleep(3 * 1000L);
148 } catch (InterruptedException e1) {
149 this.logger.error("Thread has been interrupted during waiting cooldown.", e1);
151 this.btnImport.setEnabled(true);
152 this.btnImport.setText(Messages.MSGNarrowingDownSongs.toString());
156 * Launch the application.
158 public static void main(String[] args) {
159 EventQueue.invokeLater(() -> {
161 DelesteRandomSelector frame = new DelesteRandomSelector();
162 frame.setVisible(true);
163 } catch (Exception e) {
172 * this.getClass() + ":[LEVEL]: " +
178 public DelesteRandomSelector() {
179 ExecutorService es = Executors.newCachedThreadPool(new CountedThreadFactory(() -> "DRS", "AsyncEventInquerier", false));
180 this.contentPane = new JPanel();
181 boolean isFirst = !Scraping.databaseExists();
182 // database check phase
183 CompletableFuture.runAsync(() -> {
185 JOptionPane.showMessageDialog(this, Messages.MSGDatabaseNotExist.toString());
186 if(!Scraping.writeToJson(Scraping.getWholeData())) {
187 JOptionPane.showMessageDialog(this, "Exception:NullPointerException\nCannot Keep up! Please re-download this Application!");
188 throw new NullPointerException("FATAL: cannot continue!");
191 }, es).whenCompleteAsync((ret, ex) -> {
193 logger.error("Exception was thrown during concurrent process", ex);
194 if(ex instanceof NullPointerException) {
195 throw new RuntimeException(ex);
197 throw new IllegalStateException(ex);
200 CompletableFuture<ArrayList<Song>> getFromJsonFuture = CompletableFuture.supplyAsync(() -> Scraping.getFromJson(), es);
201 CompletableFuture<ArrayList<Song>> getWholeDataFuture = CompletableFuture.supplyAsync(() -> Scraping.getWholeData(), es);
202 // setting check phase
203 CompletableFuture.runAsync(() -> {
204 if(!Settings.fileExists() && !Settings.writeDownJSON()) {
205 JOptionPane.showMessageDialog(this, "Exception:NullPointerException\nCannot Keep up! Please re-download this Application!");
206 throw new NullPointerException("FATAL: cannot continue!");
208 }, es).whenCompleteAsync((ret, ex) -> {
210 logger.error("Exception was thrown during concurrent process", ex);
211 if(ex instanceof NullPointerException) {
212 throw new RuntimeException(ex);
214 throw new IllegalStateException(ex);
216 this.logger.debug("Loading settings...");
217 this.property.setCheckLibraryUpdates(Settings.needToCheckLibraryUpdates());
218 this.property.setCheckVersion(Settings.needToCheckVersion());
219 this.property.setWindowWidth(Settings.getWindowWidth());
220 this.property.setWindowHeight(Settings.getWindowHeight());
221 this.property.setSongLimit(Settings.getSongsLimit());
222 this.property.setSaveScoreLog(Settings.saveScoreLog());
223 this.logger.debug("Load settings done.");
224 this.logger.debug("Version check: {}", this.property.isCheckVersion());
225 this.logger.debug("Library update check: {}", this.property.isCheckLibraryUpdates());
226 this.logger.debug("Window Width: {}", this.property.getWindowWidth());
227 this.logger.debug("Window Height: {}", this.property.getWindowHeight());
228 this.logger.debug("Song Limit: {}", this.property.getSongLimit());
229 this.logger.debug("SaveScoreLog: {}", this.property.isSaveScoreLog());
230 if(this.property.isCheckVersion()) {
231 this.softwareUpdateFuture = CompletableFuture.runAsync(() -> CheckVersion.needToBeUpdated(), es);
233 if(this.property.isCheckLibraryUpdates()) {
234 CompletableFuture<Void> updatedFuture = getWholeDataFuture.thenAcceptBothAsync(getFromJsonFuture, updateConsumer, es);
235 updatedFuture.thenRunAsync(setEnabled, es);
238 CompletableFuture.runAsync(() -> {
239 EstimateAlbumTypeCycle.Initialization();
240 if(Files.exists(Paths.get("generated/albumCycle.json"))) {
241 this.albumType = EstimateAlbumTypeCycle.getCurrentCycle();
243 }, es).whenCompleteAsync((ret, ex) -> {
245 logger.error("Exception was thrown during concurrent process", ex);
246 throw new IllegalStateException(ex);
249 getWholeDataFuture.thenAcceptAsync(list -> this.logger.info("Scraping data size:" + list.size()), es);
250 getFromJsonFuture.thenAcceptAsync(list -> this.logger.info("Currently database size:" + list.size()), es);
252 CompletableFuture.runAsync(() -> {
253 this.easter = new Easter();
254 this.setTitle(this.easter.getTodaysBirth());
256 this.logger.debug("Version: {}", CheckVersion.getVersion());
257 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
258 // this.setBounds(100, 100, this.property.getWindowWidth(), this.property.getWindowHeight());
259 this.setBounds(100, 100, 960, 540);
260 this.contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
261 this.setContentPane(this.contentPane);
262 contentPane.setLayout(new CardLayout(0, 0));
264 panelMain = new JPanel();
265 panelMain.setLayout(new BorderLayout(0, 0));
267 panelNorthMain = new JPanel();
268 panelMain.add(panelNorthMain, BorderLayout.NORTH);
269 panelNorthMain.setLayout(new FormLayout(new ColumnSpec[] {
270 ColumnSpec.decode("829px"),
271 FormSpecs.LABEL_COMPONENT_GAP_COLSPEC,
272 ColumnSpec.decode("center:94px"),},
274 RowSpec.decode("20px"),}));
276 labelTitle = new JLabel(Messages.MSGTitle.toString());
277 labelTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 16));
278 panelNorthMain.add(labelTitle, "1, 1, center, top");
280 labelVersion = new JLabel(CheckVersion.getVersion());
281 labelVersion.setFont(new Font("SansSerif", Font.BOLD, 12));
282 panelNorthMain.add(labelVersion, "3, 1, center, center");
284 panelWestMain = new JPanel();
285 panelMain.add(panelWestMain, BorderLayout.WEST);
286 panelWestMain.setLayout(new FormLayout(new ColumnSpec[] {
287 FormSpecs.LABEL_COMPONENT_GAP_COLSPEC,
288 ColumnSpec.decode("120px"),},
290 FormSpecs.LINE_GAP_ROWSPEC,
291 RowSpec.decode("25px"),
292 FormSpecs.RELATED_GAP_ROWSPEC,
293 FormSpecs.DEFAULT_ROWSPEC,
294 FormSpecs.RELATED_GAP_ROWSPEC,
295 FormSpecs.DEFAULT_ROWSPEC,
296 FormSpecs.RELATED_GAP_ROWSPEC,
297 FormSpecs.DEFAULT_ROWSPEC,
298 FormSpecs.RELATED_GAP_ROWSPEC,
299 FormSpecs.DEFAULT_ROWSPEC,
300 FormSpecs.RELATED_GAP_ROWSPEC,
301 FormSpecs.DEFAULT_ROWSPEC,
302 FormSpecs.RELATED_GAP_ROWSPEC,
303 FormSpecs.DEFAULT_ROWSPEC,
304 FormSpecs.RELATED_GAP_ROWSPEC,
305 RowSpec.decode("max(41dlu;default)"),}));
307 labelDifficulty = new JLabel(Messages.MSGSelectDifficulty.toString());
308 labelDifficulty.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
309 panelWestMain.add(labelDifficulty, "2, 2, center, center");
311 comboDifficultySelect = new JComboBox<>();
312 comboDifficultySelect.setModel(new DefaultComboBoxModel(new String[] {Messages.MSGNonSelected.toString(), "DEBUT", "REGULAR", "PRO", "MASTER", "MASTER+", "ⓁMASTER+", "LIGHT", "TRICK", "PIANO", "FORTE", "WITCH"}));
313 comboDifficultySelect.setFont(new Font("Dialog", Font.BOLD, 12));
314 panelWestMain.add(comboDifficultySelect, "2, 4, fill, fill");
316 comboAttribute = new JComboBox<>();
317 comboAttribute.setModel(new DefaultComboBoxModel(new String[] {Messages.MSGNonSelected.toString(), "全タイプ", "キュート", "クール", "パッション"}));
318 comboAttribute.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
319 panelWestMain.add(comboAttribute, "2, 6, fill, top");
321 labelLevel = new JLabel(Messages.MSGSongLevel.toString());
322 labelLevel.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
323 panelWestMain.add(labelLevel, "2, 8, center, center");
325 spinnerLevel = new JSpinner();
326 panelWestMain.add(spinnerLevel, "2, 10, fill, center");
328 checkLessLv = new JCheckBox(Messages.MSGBelowSpecificLevel.toString());
329 checkLessLv.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
330 panelWestMain.add(checkLessLv, "2, 12, left, top");
332 checkMoreLv = new JCheckBox(Messages.MSGOverSpecificLevel.toString());
333 checkMoreLv.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
334 panelWestMain.add(checkMoreLv, "2, 14, left, top");
336 labelLvCaution = new JLabel(Messages.MSGLevelCheckboxInfo.toString());
337 labelLvCaution.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
338 panelWestMain.add(labelLvCaution, "2, 16, left, center");
340 panelEastMain = new JPanel();
341 panelMain.add(panelEastMain, BorderLayout.EAST);
342 panelEastMain.setLayout(new FormLayout(new ColumnSpec[] {
343 FormSpecs.LABEL_COMPONENT_GAP_COLSPEC,
344 ColumnSpec.decode("100px"),},
346 FormSpecs.LINE_GAP_ROWSPEC,
347 RowSpec.decode("77px"),
348 FormSpecs.RELATED_GAP_ROWSPEC,
349 FormSpecs.DEFAULT_ROWSPEC,
350 FormSpecs.RELATED_GAP_ROWSPEC,
351 FormSpecs.DEFAULT_ROWSPEC,
352 FormSpecs.RELATED_GAP_ROWSPEC,
353 FormSpecs.DEFAULT_ROWSPEC,
354 FormSpecs.RELATED_GAP_ROWSPEC,
355 RowSpec.decode("max(36dlu;default)"),
356 FormSpecs.RELATED_GAP_ROWSPEC,
357 FormSpecs.DEFAULT_ROWSPEC,}));
359 btnImport = new JButton(Messages.MSGUpdatingDatabase.toString());
360 btnImport.addActionListener(e -> {
361 CompletableFuture.runAsync(() -> {
363 if(!impl.getFlag()) {
364 JOptionPane.showMessageDialog(null, Messages.MSGManualUpdateNotCompleteYet.toString());
367 ArrayList<Song> fromJson = Scraping.getFromJson();
368 ArrayList<Song> specificlevelList = Scraping.getSpecificLevelSongs(fromJson, (Integer)DelesteRandomSelector.this.spinnerLevel.getValue(), DelesteRandomSelector.this.checkLessLv.isSelected(), DelesteRandomSelector.this.checkMoreLv.isSelected());
369 ArrayList<Song> specificDifficultyList = Scraping.getSpecificDifficultySongs(specificlevelList, DelesteRandomSelector.this.comboDifficultySelect.getSelectedItem().toString());
370 ArrayList<Song> specificAttributeList = Scraping.getSpecificAttributeSongs(specificDifficultyList, DelesteRandomSelector.this.comboAttribute.getSelectedItem().toString());
371 ArrayList<Song> specificTypeList = Scraping.getSpecificAlbumTypeSongs(specificAttributeList, EstimateAlbumTypeCycle.getCurrentCycle());
372 if(!selectedSongsList.isEmpty()) {
373 selectedSongsList.clear();
375 selectedSongsList.addAll((DelesteRandomSelector.this.comboDifficultySelect.getSelectedItem().equals(Scraping.MASTERPLUS) || DelesteRandomSelector.this.comboDifficultySelect.getSelectedItem().equals(Scraping.LEGACYMASTERPLUS)) ? specificTypeList : specificAttributeList);
376 DelesteRandomSelector.this.logger.info("Songs are selected.We are Ready to go.");
377 JOptionPane.showMessageDialog(null, Messages.MSGCompleteNarrowDown.toString());
378 }, es).whenCompleteAsync((ret, ex) -> {
380 logger.error("Exception was thrown during concurrent process", ex);
381 throw new IllegalStateException(ex);
385 btnImport.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
386 btnImport.setEnabled(false);
387 panelEastMain.add(btnImport, "2, 2, fill, fill");
389 btnConfig = new JButton(Messages.MSGConfigurations.toString());
390 btnConfig.addActionListener(e -> {
391 CompletableFuture.runAsync(() -> {
392 ProcessBuilder builder = new ProcessBuilder("java", "-jar", "Configurations.jar");
395 } catch (IOException e1) {
396 logger.error("Cannot start external jar file. maybe are you running this with mac or linux?", e);
398 }).whenCompleteAsync((ret, ex) -> {
400 logger.error("Exception was thrown during concurrent process", ex);
401 throw new RuntimeException(ex);
405 panelEastMain.add(btnConfig, "2, 6, fill, fill");
407 btnStart = new JButton(Messages.MSGCalcStart.toString());
408 btnStart.addActionListener(e -> {
409 CompletableFuture.runAsync(() -> {
410 Random random = new Random(System.currentTimeMillis());
411 toolIntegrateList = new ArrayList<>();
412 StringBuilder paneBuilder = new StringBuilder();
413 DelesteRandomSelector.this.integratorArray = new String[DelesteRandomSelector.this.property.getSongLimit()];
414 for(int i = 0; i < DelesteRandomSelector.this.property.getSongLimit(); i++) {
415 int randomInt = random.nextInt(selectedSongsList.size());
416 String typeString = DelesteRandomSelector.this.comboDifficultySelect.getSelectedItem().equals(Scraping.MASTERPLUS) || DelesteRandomSelector.this.comboDifficultySelect.getSelectedItem().equals(Scraping.LEGACYMASTERPLUS) ? EstimateAlbumTypeCycle.getCurrentCycle() : "";
417 paneBuilder.append(i + 1)
418 .append(Messages.MSGNumberOfSongs.toString())
420 .append(selectedSongsList.get(randomInt).getAttribute())
422 .append(selectedSongsList.get(randomInt).getDifficulty())
424 .append(selectedSongsList.get(randomInt).getName())
426 .append(selectedSongsList.get(randomInt).getLevel())
430 this.integratorArray[i] = selectedSongsList.get(randomInt).getName() + "(Lv" + selectedSongsList.get(randomInt).getLevel() + ")\n";
431 toolIntegrateList.add(selectedSongsList.get(randomInt));
433 paneBuilder.append(Messages.MSGThisPhrase.toString())
434 .append(this.property.getSongLimit())
435 .append(Messages.MSGPlayPhrase.toString());
436 DelesteRandomSelector.this.textArea.setText(paneBuilder.toString());
437 DelesteRandomSelector.this.integratorBool = true;
438 DelesteRandomSelector.this.logger.info("show up completed.");
439 labelCurrentSongOrderTool.setText("null");
440 listToolMapDataFuture = CompletableFuture.supplyAsync(() -> {
441 List<String> data = toolIntegrateList.stream()
442 .map(s -> s.getName())
443 .collect(Collectors.toList());
444 fetchData = new FetchFromAPI(data.toArray(new String[0]));
445 return fetchData.getInformation();
447 logger.debug("api fetch inquery published");
448 }, es).whenCompleteAsync((ret, ex) -> {
450 logger.error("Exception was thrown during concurrent process", ex);
454 btnStart.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
455 panelEastMain.add(btnStart, "2, 4, fill, fill");
457 btnManualUpdate = new JButton(Messages.MSGManualUpdate.toString());
458 btnManualUpdate.addActionListener(e -> {
459 impl = new ManualUpdateThreadImpl();
460 CompletableFuture.runAsync(impl, es).whenCompleteAsync((t, u) -> {
462 logger.warn("Exception while processing update manually.", e);
463 JOptionPane.showMessageDialog(null, "There was a problem during processing library update manually.\nIf this appears repeatedly, please contact developer with your app log.");
467 panelEastMain.add(btnManualUpdate, "2, 8, fill, fill");
469 btnTwitterIntegration = new JButton(Messages.MSGTwitterIntegration.toString());
470 btnTwitterIntegration.addActionListener(e -> {
471 CompletableFuture.runAsync(() -> {
472 boolean authorizationStatus = TwitterIntegration.authorization();
473 String updatedStatus = Messages.MSGUsingThisAppPhrase.toString();
474 int lengthLimit = updatedStatus.length();
475 boolean isBroken = false;
476 if(!DelesteRandomSelector.this.integratorBool) {
477 JOptionPane.showMessageDialog(null, Messages.MSGNotPlayYet.toString());
480 for (String element : DelesteRandomSelector.this.integratorArray) {
481 updatedStatus = updatedStatus + element;
482 lengthLimit += element.length();
483 if(lengthLimit > 69) {
489 updatedStatus = updatedStatus + Messages.MSGTwitterPlayOtherwisePhrase.toString() + "\n#DelesteRandomSelector #デレステ ";
491 updatedStatus = updatedStatus + Messages.MSGTwitterPlayOnlyPhrase.toString() + "\n#DelesteRandomSelector #デレステ ";
493 DelesteRandomSelector.this.logger.info("status message constructed.");
494 lengthLimit = updatedStatus.length();
495 if(authorizationStatus) {
496 int option = JOptionPane.showConfirmDialog(null, Messages.MSGTwitterIntegrationConfirm.toString() + updatedStatus + Messages.MSGStringLength.toString() + lengthLimit);
497 DelesteRandomSelector.this.logger.info("user seletced: " + option);
499 case JOptionPane.OK_OPTION:
500 TwitterIntegration.PostTwitter(updatedStatus);
501 DelesteRandomSelector.this.logger.info("Success to update the status.");
502 JOptionPane.showMessageDialog(null, Messages.MSGCompletePost.toString());
504 case JOptionPane.NO_OPTION:
505 DelesteRandomSelector.this.logger.info("There is no will to post.");
507 case JOptionPane.CANCEL_OPTION:
508 DelesteRandomSelector.this.logger.info("The Operation was canceled by user.");
514 DelesteRandomSelector.this.logger.info("seems to reject the permission.it should need try again.");
516 }, es).whenCompleteAsync((ret, ex) -> {
518 logger.error("Exception was thrown during concurrent process");
522 btnTwitterIntegration.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 11));
523 panelEastMain.add(btnTwitterIntegration, "2, 10, fill, fill");
525 btnExit = new JButton(Messages.MSGTerminate.toString());
526 btnExit.addActionListener(e -> {
527 if(DelesteRandomSelector.this.softwareUpdateFuture.isDone() || DelesteRandomSelector.this.albumTypeEstimateFuture.isDone() || !this.impl.getFlag()) {
528 DelesteRandomSelector.this.logger.info("Requested Exit by Button.");
529 logger.info("Shut down thread pool.");
533 JOptionPane.showMessageDialog(null, Messages.MSGInternalYpdateNotDoneYet.toString());
536 btnExit.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
537 panelEastMain.add(btnExit, "2, 12, fill, fill");
539 panelCenterMain = new JPanel();
540 panelMain.add(panelCenterMain, BorderLayout.CENTER);
541 panelCenterMain.setLayout(new BorderLayout(0, 0));
543 scrollPane = new JScrollPane();
544 panelCenterMain.add(scrollPane);
546 textArea = new JTextArea();
547 textArea.setText(Messages.MSGNarrowDownProcedure.toString() + property.getSongLimit() + Messages.MSGCurrentAlbumType.toString() + albumType);
548 textArea.setEditable(false);
549 scrollPane.setViewportView(textArea);
551 tabbedPane = new JTabbedPane(JTabbedPane.TOP);
552 tabbedPane.addChangeListener(e -> {
553 CompletableFuture.runAsync(() -> {
554 String currentTabName = tabbedPane.getTitleAt(tabbedPane.getSelectedIndex());
555 if(currentTabName.equals("SubTools") && labelCurrentSongOrderTool.getText().equals("null")) {
556 logger.info("Detected switching tool tab");
557 listToolMapData = listToolMapDataFuture.join();
558 Song firstSong = toolIntegrateList.get(0);
559 Map<String, String> fetchMap = new HashMap<>();
560 for(Map<String, String> tmpMap : listToolMapData) {
561 String normalizeApiName = Normalizer.normalize(tmpMap.get("songname").toString(), Normalizer.Form.NFKD);
562 String normalizeLocalName = Normalizer.normalize(firstSong.getName(), Normalizer.Form.NFKD);
563 if(normalizeApiName.equals(normalizeLocalName)) {
568 labelSongNameToolTip.setText(firstSong.getName());
569 labelAttributeToolTip.setText(firstSong.getAttribute());
570 labelDifficultyToolTip.setText(firstSong.getDifficulty());
571 labelLevelToolTip.setText(String.valueOf(firstSong.getLevel()));
572 labelNotesToolTip.setText(String.valueOf(firstSong.getNotes()));
573 labelCurrentSongOrderTool.setText("1");
574 labelLyricToolTip.setText(fetchMap.get("lyric"));
575 labelComposerToolTip.setText(fetchMap.get("composer"));
576 labelArrangeToolTip.setText(fetchMap.get("arrange"));
577 labelMemberToolTip.setText(fetchMap.get("member"));
579 }, es).whenCompleteAsync((ret, ex) -> {
581 logger.error("Exception was thrown during concurrent process", ex);
585 tabbedPane.addTab("Main", null, panelMain, null);
586 contentPane.add(tabbedPane, "name_307238585319500");
588 panelTool = new JPanel();
589 tabbedPane.addTab("SubTools", null, panelTool, null);
590 panelTool.setLayout(new BorderLayout(0, 0));
592 panelNorthTool = new JPanel();
593 panelTool.add(panelNorthTool, BorderLayout.NORTH);
594 panelNorthTool.setLayout(new FormLayout(new ColumnSpec[] {
595 ColumnSpec.decode("center:max(524dlu;default)"),
596 FormSpecs.RELATED_GAP_COLSPEC,
597 ColumnSpec.decode("max(30dlu;default)"),},
599 RowSpec.decode("max(16dlu;default)"),}));
601 labelSubToolTitle = new JLabel("補助ツール");
602 labelSubToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 16));
603 panelNorthTool.add(labelSubToolTitle, "1, 1");
605 labelVersionTool = new JLabel(CheckVersion.getVersion());
606 labelVersionTool.setFont(new Font("SansSerif", Font.BOLD, 12));
607 panelNorthTool.add(labelVersionTool, "3, 1");
609 panelCenterTool = new JPanel();
610 panelTool.add(panelCenterTool, BorderLayout.CENTER);
611 panelCenterTool.setLayout(new FormLayout(new ColumnSpec[] {
612 FormSpecs.RELATED_GAP_COLSPEC,
613 ColumnSpec.decode("max(40dlu;default)"),
614 FormSpecs.RELATED_GAP_COLSPEC,
615 ColumnSpec.decode("10dlu"),
616 FormSpecs.RELATED_GAP_COLSPEC,
617 ColumnSpec.decode("10dlu"),
618 FormSpecs.RELATED_GAP_COLSPEC,
619 ColumnSpec.decode("max(10dlu;default)"),
620 FormSpecs.RELATED_GAP_COLSPEC,
621 ColumnSpec.decode("max(90dlu;default)"),
622 FormSpecs.RELATED_GAP_COLSPEC,
623 FormSpecs.DEFAULT_COLSPEC,
624 FormSpecs.RELATED_GAP_COLSPEC,
625 FormSpecs.DEFAULT_COLSPEC,
626 FormSpecs.RELATED_GAP_COLSPEC,
627 FormSpecs.DEFAULT_COLSPEC,
628 FormSpecs.RELATED_GAP_COLSPEC,
629 ColumnSpec.decode("max(90dlu;default)"),
630 FormSpecs.RELATED_GAP_COLSPEC,
631 FormSpecs.DEFAULT_COLSPEC,
632 FormSpecs.RELATED_GAP_COLSPEC,
633 FormSpecs.DEFAULT_COLSPEC,
634 FormSpecs.RELATED_GAP_COLSPEC,
635 FormSpecs.DEFAULT_COLSPEC,
636 FormSpecs.RELATED_GAP_COLSPEC,
637 ColumnSpec.decode("max(90dlu;default)"),},
639 FormSpecs.RELATED_GAP_ROWSPEC,
640 FormSpecs.DEFAULT_ROWSPEC,
641 FormSpecs.RELATED_GAP_ROWSPEC,
642 FormSpecs.DEFAULT_ROWSPEC,
643 FormSpecs.RELATED_GAP_ROWSPEC,
644 FormSpecs.DEFAULT_ROWSPEC,
645 FormSpecs.RELATED_GAP_ROWSPEC,
646 FormSpecs.DEFAULT_ROWSPEC,
647 FormSpecs.RELATED_GAP_ROWSPEC,
648 FormSpecs.DEFAULT_ROWSPEC,
649 FormSpecs.RELATED_GAP_ROWSPEC,
650 FormSpecs.DEFAULT_ROWSPEC,
651 FormSpecs.RELATED_GAP_ROWSPEC,
652 FormSpecs.DEFAULT_ROWSPEC,
653 FormSpecs.RELATED_GAP_ROWSPEC,
654 FormSpecs.DEFAULT_ROWSPEC,
655 FormSpecs.RELATED_GAP_ROWSPEC,
656 FormSpecs.DEFAULT_ROWSPEC,
657 FormSpecs.RELATED_GAP_ROWSPEC,
658 FormSpecs.DEFAULT_ROWSPEC,
659 FormSpecs.RELATED_GAP_ROWSPEC,
660 FormSpecs.DEFAULT_ROWSPEC,
661 FormSpecs.RELATED_GAP_ROWSPEC,
662 FormSpecs.DEFAULT_ROWSPEC,
663 FormSpecs.RELATED_GAP_ROWSPEC,
664 FormSpecs.DEFAULT_ROWSPEC,
665 FormSpecs.RELATED_GAP_ROWSPEC,
666 FormSpecs.DEFAULT_ROWSPEC,
667 FormSpecs.RELATED_GAP_ROWSPEC,
668 FormSpecs.DEFAULT_ROWSPEC,
669 FormSpecs.RELATED_GAP_ROWSPEC,
670 FormSpecs.DEFAULT_ROWSPEC,
671 FormSpecs.RELATED_GAP_ROWSPEC,
672 FormSpecs.DEFAULT_ROWSPEC,
673 FormSpecs.RELATED_GAP_ROWSPEC,
674 FormSpecs.DEFAULT_ROWSPEC,}));
676 lblNewLabel = new JLabel("今回プレイした楽曲");
677 lblNewLabel.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
678 panelCenterTool.add(lblNewLabel, "2, 2, center, default");
680 labelSongNameToolTitle = new JLabel("Song Name");
681 labelSongNameToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
682 panelCenterTool.add(labelSongNameToolTitle, "2, 6, center, default");
684 labelSongNameToolTip = new JLabel("Please wait...");
685 labelSongNameToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
686 panelCenterTool.add(labelSongNameToolTip, "10, 6, center, default");
688 labelMemberToolTitle = new JLabel("Member");
689 labelMemberToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
690 panelCenterTool.add(labelMemberToolTitle, "18, 6, center, default");
692 labelMemberToolTip = new JLabel("Please wait...");
693 labelMemberToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
694 panelCenterTool.add(labelMemberToolTip, "26, 6, center, default");
696 labelAttributeToolTitle = new JLabel("Song Attribute");
697 labelAttributeToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
698 panelCenterTool.add(labelAttributeToolTitle, "2, 10, center, default");
700 labelAttributeToolTip = new JLabel("Please wait...");
701 labelAttributeToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
702 panelCenterTool.add(labelAttributeToolTip, "10, 10, center, default");
704 labelDifficultyToolTitle = new JLabel("Difficulty");
705 labelDifficultyToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
706 panelCenterTool.add(labelDifficultyToolTitle, "2, 14, center, default");
708 labelDifficultyToolTip = new JLabel("Please wait...");
709 labelDifficultyToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
710 panelCenterTool.add(labelDifficultyToolTip, "10, 14, center, default");
712 labelLevelToolTitle = new JLabel("Song Level");
713 labelLevelToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
714 panelCenterTool.add(labelLevelToolTitle, "2, 18, center, default");
716 labelLevelToolTip = new JLabel("Please wait...");
717 labelLevelToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
718 panelCenterTool.add(labelLevelToolTip, "10, 18, center, default");
720 labelNotesToolTitle = new JLabel("Notes");
721 labelNotesToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
722 panelCenterTool.add(labelNotesToolTitle, "2, 22, center, default");
724 labelNotesToolTip = new JLabel("Please wait...");
725 labelNotesToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
726 panelCenterTool.add(labelNotesToolTip, "10, 22, center, default");
728 btnPrevSongTool = new JButton("prev");
729 btnPrevSongTool.addActionListener(e -> {
730 CompletableFuture.runAsync(() -> {
731 int currentIndex = Integer.parseInt(labelCurrentSongOrderTool.getText()) - 1;
732 if(currentIndex != 0) {
733 Song prevSong = toolIntegrateList.get(currentIndex - 1);
734 logger.info("currently : {} Next: {}", currentIndex + 1, currentIndex);
735 logger.info("prevSong: {}", prevSong);
736 Map<String, String> fetchMap = new HashMap<>();
737 for(Map<String, String> tmpMap : listToolMapData) {
738 String normalizeApiName = Normalizer.normalize(tmpMap.get("songname").toString(), Normalizer.Form.NFKD);
739 String normalizeLocalName = Normalizer.normalize(prevSong.getName(), Normalizer.Form.NFKD);
740 if(normalizeApiName.equals(normalizeLocalName)) {
745 labelSongNameToolTip.setText(prevSong.getName());
746 labelAttributeToolTip.setText(prevSong.getAttribute());
747 labelDifficultyToolTip.setText(prevSong.getDifficulty());
748 labelLevelToolTip.setText(String.valueOf(prevSong.getLevel()));
749 labelNotesToolTip.setText(String.valueOf(prevSong.getNotes()));
750 labelCurrentSongOrderTool.setText(String.valueOf(currentIndex));
751 labelLyricToolTip.setText(fetchMap.get("lyric"));
752 labelComposerToolTip.setText(fetchMap.get("composer"));
753 labelArrangeToolTip.setText(fetchMap.get("arrange"));
754 labelMemberToolTip.setText(fetchMap.get("member"));
756 }, es).whenCompleteAsync((ret, ex) -> {
758 logger.error("Exception was thrown during concurrent process", ex);
763 labelLyricToolTitle = new JLabel("Lyrics By");
764 labelLyricToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
765 panelCenterTool.add(labelLyricToolTitle, "2, 26, center, default");
767 labelLyricToolTip = new JLabel("Please wait...");
768 labelLyricToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
769 panelCenterTool.add(labelLyricToolTip, "10, 26, center, default");
771 labelComposerToolTitle = new JLabel("Composed By");
772 labelComposerToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
773 panelCenterTool.add(labelComposerToolTitle, "2, 30, center, default");
775 labelComposerToolTip = new JLabel("Please wait...");
776 labelComposerToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
777 panelCenterTool.add(labelComposerToolTip, "10, 30, center, default");
779 labelArrangeToolTitle = new JLabel("Arranged By");
780 labelArrangeToolTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
781 panelCenterTool.add(labelArrangeToolTitle, "2, 34, center, default");
783 labelArrangeToolTip = new JLabel("Please wait...");
784 labelArrangeToolTip.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
785 panelCenterTool.add(labelArrangeToolTip, "10, 34, center, default");
786 btnPrevSongTool.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
787 panelCenterTool.add(btnPrevSongTool, "2, 36");
789 btnNextSongTool = new JButton("next");
790 btnNextSongTool.addActionListener(e -> {
791 CompletableFuture.runAsync(() -> {
792 int currentIndex = Integer.parseInt(labelCurrentSongOrderTool.getText()) - 1;
793 if(currentIndex != property.getSongLimit() - 1) {
794 Song nextSong = toolIntegrateList.get(currentIndex + 1);
795 logger.info("currently : {} Next: {}", currentIndex + 1, currentIndex + 2);
796 logger.info("nextSong: {}", nextSong);
797 Map<String, String> fetchMap = new HashMap<>();
798 for(Map<String, String> tmpMap : listToolMapData) {
799 String normalizeApiName = Normalizer.normalize(tmpMap.get("songname").toString(), Normalizer.Form.NFKD);
800 String normalizeLocalName = Normalizer.normalize(nextSong.getName(), Normalizer.Form.NFKD);
801 if(normalizeApiName.equals(normalizeLocalName)) {
806 labelSongNameToolTip.setText(nextSong.getName());
807 labelAttributeToolTip.setText(nextSong.getAttribute());
808 labelDifficultyToolTip.setText(nextSong.getDifficulty());
809 labelLevelToolTip.setText(String.valueOf(nextSong.getLevel()));
810 labelNotesToolTip.setText(String.valueOf(nextSong.getNotes()));
811 labelCurrentSongOrderTool.setText(String.valueOf(currentIndex + 2));
812 labelLyricToolTip.setText(fetchMap.get("lyric"));
813 labelComposerToolTip.setText(fetchMap.get("composer"));
814 labelArrangeToolTip.setText(fetchMap.get("arrange"));
815 labelMemberToolTip.setText(fetchMap.get("member"));
817 }, es).whenCompleteAsync((ret, ex) -> {
819 logger.error("Exception was thrown during concurrent process", ex);
824 labelCurrentSongOrderTool = new JLabel("null");
825 panelCenterTool.add(labelCurrentSongOrderTool, "4, 36");
827 labelSlashTool = new JLabel("/");
828 panelCenterTool.add(labelSlashTool, "6, 36");
830 labelSongLimitTool = new JLabel(String.valueOf(this.property.getSongLimit()));
831 panelCenterTool.add(labelSongLimitTool, "8, 36");
832 btnNextSongTool.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
833 panelCenterTool.add(btnNextSongTool, "10, 36");
835 btnMoreInfoTool = new JButton("More Information");
836 btnMoreInfoTool.addActionListener(e -> {
837 CompletableFuture.runAsync(() -> {
838 int currentIndex = Integer.parseInt(labelCurrentSongOrderTool.getText()) - 1;
839 Song currentSong = toolIntegrateList.get(currentIndex);
840 Map<String, String> fetchMap = new HashMap<>();
841 for(Map<String, String> tmpMap : listToolMapData) {
842 String normalizeApiName = Normalizer.normalize(tmpMap.get("songname").toString(), Normalizer.Form.NFKD);
843 String normalizeLocalName = Normalizer.normalize(currentSong.getName(), Normalizer.Form.NFKD);
844 if(normalizeApiName.equals(normalizeLocalName)) {
849 Desktop desk = Desktop.getDesktop();
850 String api = fetchMap.get("link");
854 logger.info("Opening default browser with : {}", uri);
856 } catch (URISyntaxException | IOException e1) {
857 JOptionPane.showMessageDialog(null, "このメッセージは仮です。Exception : " + e1.getClass().getSimpleName());
858 logger.error("Exception while opening default browser.", e1);
860 }, es).whenCompleteAsync((ret, ex) -> {
862 logger.warn("Exception was thrown during action events.", ex);
866 btnMoreInfoTool.setFont(new Font("UD デジタル 教科書体 NP-B", Font.PLAIN, 12));
867 panelCenterTool.add(btnMoreInfoTool, "18, 36");
868 if(isFirst || !this.property.isCheckLibraryUpdates()) {