OSDN Git Service

feat: Non-select mode add
[delesterandomselector/DelesteRandomSelector.git] / src / com / ranfa / main / DelesteRandomSelector.java
1 package com.ranfa.main;
2
3 import java.awt.BorderLayout;
4 import java.awt.EventQueue;
5 import java.awt.Font;
6 import java.awt.event.ActionEvent;
7 import java.awt.event.ActionListener;
8 import java.io.IOException;
9 import java.nio.file.Files;
10 import java.nio.file.Path;
11 import java.nio.file.Paths;
12 import java.util.ArrayList;
13 import java.util.Random;
14 import java.util.concurrent.CompletableFuture;
15 import java.util.concurrent.ExecutorService;
16 import java.util.concurrent.Executors;
17
18 import javax.swing.DefaultComboBoxModel;
19 import javax.swing.JButton;
20 import javax.swing.JCheckBox;
21 import javax.swing.JComboBox;
22 import javax.swing.JFrame;
23 import javax.swing.JLabel;
24 import javax.swing.JOptionPane;
25 import javax.swing.JPanel;
26 import javax.swing.JSpinner;
27 import javax.swing.JTextPane;
28 import javax.swing.border.EmptyBorder;
29
30 import com.jgoodies.forms.layout.ColumnSpec;
31 import com.jgoodies.forms.layout.FormLayout;
32 import com.jgoodies.forms.layout.FormSpecs;
33 import com.jgoodies.forms.layout.RowSpec;
34 import com.ranfa.lib.LimitedLog;
35 import com.ranfa.lib.Scraping;
36 import com.ranfa.lib.SettingJSONProperty;
37 import com.ranfa.lib.Settings;
38 import com.ranfa.lib.Song;
39 import com.ranfa.lib.Version;
40
41 @Version(major = 0, minor = 2, patch = 0)
42 public class DelesteRandomSelector extends JFrame {
43
44         private static ArrayList<Song> selectedSongsList = new ArrayList<Song>();
45
46         private JPanel contentPane;
47         private JPanel panelNorth;
48         private JPanel panelWest;
49         private JLabel labelVersion;
50         private JLabel labelTitle;
51         private JLabel labelDifficulty;
52         private JLabel labelLevel;
53         private JSpinner spinnerLevel;
54         private JCheckBox checkMoreLv;
55         private JCheckBox checkLessLv;
56         private JPanel panelEast;
57         private JPanel panelCentre;
58         private JButton btnImport;
59         private JButton btnStart;
60         private JButton btnExit;
61         private JTextPane textPane;
62         private JComboBox comboDifficultySelect;
63         private JLabel labelLvCaution;
64         private JComboBox comboAttribute;
65
66         private SettingJSONProperty property = new SettingJSONProperty();
67
68         /**
69          * Launch the application.
70          */
71         public static void main(String[] args) {
72                 EventQueue.invokeLater(new Runnable() {
73                         public void run() {
74                                 try {
75                                         DelesteRandomSelector frame = new DelesteRandomSelector();
76                                         frame.setVisible(true);
77                                 } catch (Exception e) {
78                                         e.printStackTrace();
79                                 }
80                         }
81                 });
82         }
83
84         /**
85          * log file prefix:
86          *  "[" + Thread.currentThread().toString() + "]:" + this.getClass() + ":[LEVEL]: " +
87          */
88
89         /**
90          * Create the frame.
91          */
92         public DelesteRandomSelector() {
93                 if(!Settings.fileExists() && !Settings.writeDownJSON()) {
94                         JOptionPane.showMessageDialog(this, "Exception:NullPointerException\nCannot Keep up! Please re-download this Application!");
95                         throw new NullPointerException("FATAL: cannot continue!");
96                 }
97                 LimitedLog.println("[" + Thread.currentThread().toString() + "]:" + this.getClass() + ":[DEBUG]: " + "Loading Settings...");
98                 property.setCheckLibraryUpdates(Settings.needToCheckLibraryUpdates());
99                 property.setCheckVersion(Settings.needToCheckVersion());
100                 property.setWindowWidth(Settings.getWindowWidth());
101                 property.setWindowHeight(Settings.getWindowHeight());
102                 property.setSongLimit(Settings.getSongsLimit());
103                 property.setSaveScoreLog(Settings.saveScoreLog());
104                 property.setOutputDebugSentences(Settings.outputDebugSentences());
105                 LimitedLog.println("[" + Thread.currentThread().toString() + "]:" + this.getClass() + ":[DEBUG]: " + "Loading Settings done."
106                                 + "\nVersion Check: " + property.isCheckVersion()
107                                 + "\nLibrary Update Check: " + property.isCheckLibraryUpdates()
108                                 + "\nWindow Width: " + property.getWindowWidth()
109                                 + "\nWindow Height: " + property.getWindowHeight()
110                                 + "\nSong Limit: " + property.getSongLimit()
111                                 + "\nSaveScoreLog: " + property.isSaveScoreLog()
112                                 + "\nOutputDebugSentences: " + property.isOutputDebugSentences());
113                 if(!Scraping.databaseExists()) {
114                         JOptionPane.showMessageDialog(this, "楽曲データベースが見つかりませんでした。自動的に作成されます…\n注意:初回起動ではなく、かつ、Jarファイルと同じ階層に\"database.json\"というファイルが存在するにも関わらず\nこのポップアップが出た場合、開発者までご一報ください。\nGithub URL: https://github.com/hizumiaoba/DelesteRandomSelector/issues");
115                         if(!Scraping.writeToJson(Scraping.getWholeData())) {
116                                 JOptionPane.showMessageDialog(this, "Exception:NullPointerException\\nCannot Keep up! Please re-download this Application!");
117                                 throw new NullPointerException("FATAL: cannot continue!");
118                         }
119                 } else if(Scraping.getFromJson().size() < Scraping.getWholeData().size()) {
120                         LimitedLog.println("[" + Thread.currentThread().toString() + "]:" + this.getClass() + ":[INFO]: " + "Update detected.Initiate update process...");
121                         Path path = Paths.get(Scraping.getDBPath());
122                         try {
123                                 Files.delete(path);
124                         } catch (IOException e1) {
125                                 LimitedLog.println("[" + Thread.currentThread().toString() + "]:" + this.getClass() + ":[FATAL]: " + "Exception while updating library.\n" + e1.getLocalizedMessage());
126                                 JOptionPane.showMessageDialog(null, "データベースファイルをアップデートできませんでした。ファイルの削除権限があるかどうか確認してください。\n" + e1.getLocalizedMessage());
127                         }
128                         Scraping.writeToJson(Scraping.getWholeData());
129                         LimitedLog.println("[" + Thread.currentThread().toString() + "]:" + this.getClass() + ":[INFO]: " + "Library update completed.");
130                 }
131                 ExecutorService es = Executors.newWorkStealingPool();
132                 CompletableFuture<ArrayList<Song>> getFromJsonFuture = CompletableFuture.supplyAsync(() -> Scraping.getFromJson(), es);
133                 CompletableFuture<ArrayList<Song>> getWholeDataFuture = CompletableFuture.supplyAsync(() -> Scraping.getWholeData(), es);
134                 getWholeDataFuture.thenAcceptAsync(list -> LimitedLog.println("[" + Thread.currentThread().toString() + "]:" + this.getClass() + ":[INFO]: Scraping data size:" + list.size()), es);
135                 getFromJsonFuture.thenAcceptAsync(list -> LimitedLog.println("[" + Thread.currentThread().toString() + "]:" + this.getClass() + ":[INFO] Currently database size:" + list.size()), es);
136                 LimitedLog.println("[" + Thread.currentThread().toString() + "]:" + this.getClass() + ":[DEBUG]: " + "Version:" + getVersion());
137                 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
138                 setBounds(100, 100, 640, 360);
139                 contentPane = new JPanel();
140                 contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
141                 setContentPane(contentPane);
142                 contentPane.setLayout(new BorderLayout(0, 0));
143
144                 panelNorth = new JPanel();
145                 contentPane.add(panelNorth, BorderLayout.NORTH);
146                 panelNorth.setLayout(new FormLayout(new ColumnSpec[] {
147                                 ColumnSpec.decode("max(302dlu;default)"),
148                                 FormSpecs.RELATED_GAP_COLSPEC,
149                                 ColumnSpec.decode("40px"),},
150                         new RowSpec[] {
151                                 RowSpec.decode("20px"),}));
152
153                 labelTitle = new JLabel("デレステ課題曲セレクター");
154                 labelTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 16));
155                 panelNorth.add(labelTitle, "1, 1, center, top");
156
157                 labelVersion = new JLabel(getVersion());
158                 labelVersion.setFont(new Font("SansSerif", Font.BOLD, 12));
159                 panelNorth.add(labelVersion, "3, 1, right, top");
160
161                 panelWest = new JPanel();
162                 contentPane.add(panelWest, BorderLayout.WEST);
163                 panelWest.setLayout(new FormLayout(new ColumnSpec[] {
164                                 FormSpecs.LABEL_COMPONENT_GAP_COLSPEC,
165                                 ColumnSpec.decode("112px:grow"),},
166                         new RowSpec[] {
167                                 FormSpecs.LINE_GAP_ROWSPEC,
168                                 RowSpec.decode("19px"),
169                                 FormSpecs.RELATED_GAP_ROWSPEC,
170                                 RowSpec.decode("max(12dlu;default)"),
171                                 FormSpecs.RELATED_GAP_ROWSPEC,
172                                 RowSpec.decode("max(12dlu;default)"),
173                                 FormSpecs.RELATED_GAP_ROWSPEC,
174                                 RowSpec.decode("12dlu"),
175                                 FormSpecs.RELATED_GAP_ROWSPEC,
176                                 RowSpec.decode("max(12dlu;default)"),
177                                 FormSpecs.RELATED_GAP_ROWSPEC,
178                                 RowSpec.decode("max(12dlu;default)"),
179                                 FormSpecs.RELATED_GAP_ROWSPEC,
180                                 RowSpec.decode("max(12dlu;default)"),
181                                 FormSpecs.RELATED_GAP_ROWSPEC,
182                                 RowSpec.decode("max(52dlu;default)"),}));
183
184                 labelDifficulty = new JLabel("難易度選択");
185                 labelDifficulty.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
186                 panelWest.add(labelDifficulty, "2, 2, center, default");
187
188                 comboDifficultySelect = new JComboBox();
189                 comboDifficultySelect.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
190                 comboDifficultySelect.setModel(new DefaultComboBoxModel(new String[] {"指定なし", "DEBUT", "REGULAR", "PRO", "MASTER", "MASTER+", "ⓁMASTER+", "LIGHT", "TRICK", "PIANO", "FORTE", "WITCH"}));
191                 panelWest.add(comboDifficultySelect, "2, 4, fill, default");
192
193                                 comboAttribute = new JComboBox();
194                                 comboAttribute.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
195                                 comboAttribute.setModel(new DefaultComboBoxModel(new String[] {"指定なし", "全タイプ", "キュート", "クール", "パッション"}));
196                                 panelWest.add(comboAttribute, "2, 6, fill, default");
197
198                                 labelLevel = new JLabel("楽曲Lv");
199                                 labelLevel.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
200                                 panelWest.add(labelLevel, "2, 8, center, default");
201
202                                 spinnerLevel = new JSpinner();
203                                 panelWest.add(spinnerLevel, "2, 10");
204
205                                 checkLessLv = new JCheckBox("指定Lv以下");
206                                 checkLessLv.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
207                                 panelWest.add(checkLessLv, "2, 12");
208
209                                 checkMoreLv = new JCheckBox("指定Lv以上");
210                                 checkMoreLv.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
211                                 panelWest.add(checkMoreLv, "2, 14");
212
213                                 labelLvCaution = new JLabel("<html><body>※以下以上両方にチェックをつけることで指定レベルのみ絞り込むことができます</body></html>");
214                                 labelLvCaution.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
215                                 panelWest.add(labelLvCaution, "2, 16, fill, fill");
216
217                 panelEast = new JPanel();
218                 contentPane.add(panelEast, BorderLayout.EAST);
219                 panelEast.setLayout(new FormLayout(new ColumnSpec[] {
220                                 ColumnSpec.decode("98px"),},
221                         new RowSpec[] {
222                                 RowSpec.decode("26px"),
223                                 FormSpecs.RELATED_GAP_ROWSPEC,
224                                 RowSpec.decode("max(50dlu;default)"),
225                                 FormSpecs.RELATED_GAP_ROWSPEC,
226                                 FormSpecs.DEFAULT_ROWSPEC,
227                                 FormSpecs.RELATED_GAP_ROWSPEC,
228                                 RowSpec.decode("max(50dlu;default)"),
229                                 FormSpecs.RELATED_GAP_ROWSPEC,
230                                 RowSpec.decode("max(15dlu;default)"),
231                                 FormSpecs.RELATED_GAP_ROWSPEC,
232                                 RowSpec.decode("max(11dlu;default)"),}));
233
234                 btnImport = new JButton("<html><body>楽曲<br>絞り込み</body></html>");
235                 btnImport.addActionListener(new ActionListener() {
236                         public void actionPerformed(ActionEvent e) {
237                                 ArrayList<Song> fromJson = Scraping.getFromJson();
238                                         ArrayList<Song> specificlevelList = Scraping.getSpecificLevelSongs(fromJson, (Integer)spinnerLevel.getValue(), checkLessLv.isSelected(), checkMoreLv.isSelected());
239                                         ArrayList<Song> specificDifficultyList = Scraping.getSpecificDifficultySongs(specificlevelList, comboDifficultySelect.getSelectedItem().toString());
240                                         ArrayList<Song> specificAttributeList = Scraping.getSpecificAttributeSongs(specificDifficultyList, comboAttribute.getSelectedItem().toString());
241                                         if(!selectedSongsList.isEmpty())
242                                         selectedSongsList.clear();
243                                 selectedSongsList.addAll(specificAttributeList);
244                                 LimitedLog.println("[" + Thread.currentThread().toString() + "]:" + this.getClass() + ":[INFO]: " +"Songs are selected.We are Ready to go.");
245                         }
246                 });
247                 btnImport.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
248                 panelEast.add(btnImport, "1, 3, fill, fill");
249
250                 btnStart = new JButton("開始!");
251                 btnStart.addActionListener(new ActionListener() {
252                         public void actionPerformed(ActionEvent e) {
253                                 Random random = new Random(System.currentTimeMillis());
254                                 String[] tmp = new String[property.getSongLimit()];
255                                 for(int i = 0; i < property.getSongLimit(); i++) {
256                                         int randomInt = random.nextInt(selectedSongsList.size());
257                                         tmp[i] = (i + 1) + "曲目: " + selectedSongsList.get(randomInt).getAttribute() + " [" + selectedSongsList.get(randomInt).getDifficulty() + "]「" + selectedSongsList.get(randomInt).getName() + "」!(Lv:" + selectedSongsList.get(randomInt).getLevel() + ")\n\n";
258                                 }
259                                 String paneString = "";
260                                 for (int i = 0; i < tmp.length; i++) {
261                                         paneString = paneString + tmp[i];
262                                 }
263                                 paneString = paneString + "この" + tmp.length + "曲をプレイしましょう!!!";
264                                 textPane.setText(paneString);
265                                 LimitedLog.println("[" + Thread.currentThread().toString() + "]:" + this.getClass() + ":[INFO]: " + "show up completed.");
266                         }
267                 });
268                 btnStart.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
269                 panelEast.add(btnStart, "1, 7, fill, fill");
270
271                 btnExit = new JButton("終了");
272                 btnExit.addActionListener(new ActionListener() {
273                         public void actionPerformed(ActionEvent e) {
274                                 LimitedLog.println("[" + Thread.currentThread().toString() + "]:" + this.getClass() + ":[INFO]: " +"Requested Exit by Button");
275                                 if(getWholeDataFuture.isDone()) {
276                                         System.exit(0);
277                                 } else {
278                                         JOptionPane.showMessageDialog(null, "非同期処理が完了していません。少し時間が経ってからやり直してください。");
279                                 }
280                         }
281                 });
282                 btnExit.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
283                 panelEast.add(btnExit, "1, 11");
284
285                 panelCentre = new JPanel();
286                 contentPane.add(panelCentre, BorderLayout.CENTER);
287                 panelCentre.setLayout(new BorderLayout(0, 0));
288
289                 textPane = new JTextPane();
290                 textPane.setText("楽曲選択の手順\r\n1.難易度、属性、レベルを選択する\r\n2.「楽曲取り込み」ボタンを押す!\r\n3.「開始」ボタンを押す!\r\n4.選択された楽曲がここに表示されます!\r\n現在設定されている楽曲選択の最大数:" + property.getSongLimit());
291                 textPane.setEditable(false);
292                 panelCentre.add(textPane);
293         }
294
295
296         /**
297          * アノテーションで記載されているバージョンを取得します
298          * @since v1.0.0
299          * @return アノテーションで定義されているバージョン
300          */
301         public static String getVersion() {
302                 String value = "v"
303                                 + getMajorVersion() + "."
304                                 + getMinorVersion() + "."
305                                 + getPatchVersion();
306                 return value;
307         }
308
309         public static int getMajorVersion() {
310                 Version version = (Version) DelesteRandomSelector.class.getAnnotation(Version.class);
311                 return version.major();
312         }
313
314         public static int getMinorVersion() {
315                 Version version = (Version) DelesteRandomSelector.class.getAnnotation(Version.class);
316                 return version.minor();
317         }
318
319         public static int getPatchVersion() {
320                 Version version = (Version) DelesteRandomSelector.class.getAnnotation(Version.class);
321                 return version.patch();
322         }
323 }