OSDN Git Service

refactor: apply some translation
[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.nio.file.Files;
7 import java.nio.file.Paths;
8 import java.util.ArrayList;
9 import java.util.Random;
10 import java.util.concurrent.CompletableFuture;
11 import java.util.concurrent.ExecutorService;
12 import java.util.concurrent.Executors;
13 import java.util.function.BiConsumer;
14
15 import javax.swing.DefaultComboBoxModel;
16 import javax.swing.JButton;
17 import javax.swing.JCheckBox;
18 import javax.swing.JComboBox;
19 import javax.swing.JFrame;
20 import javax.swing.JLabel;
21 import javax.swing.JOptionPane;
22 import javax.swing.JPanel;
23 import javax.swing.JScrollPane;
24 import javax.swing.JSpinner;
25 import javax.swing.JTextArea;
26 import javax.swing.border.EmptyBorder;
27
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 import com.jgoodies.forms.layout.ColumnSpec;
32 import com.jgoodies.forms.layout.FormLayout;
33 import com.jgoodies.forms.layout.FormSpecs;
34 import com.jgoodies.forms.layout.RowSpec;
35 import com.ranfa.lib.CheckVersion;
36 import com.ranfa.lib.EstimateAlbumTypeCycle;
37 import com.ranfa.lib.Scraping;
38 import com.ranfa.lib.SettingJSONProperty;
39 import com.ranfa.lib.Settings;
40 import com.ranfa.lib.Song;
41 import com.ranfa.lib.TwitterIntegration;
42 import com.ranfa.lib.Version;
43
44 @Version(major = 2, minor = 0, patch = 3)
45 public class DelesteRandomSelector extends JFrame {
46
47         private static ArrayList<Song> selectedSongsList = new ArrayList<>();
48
49         private JPanel contentPane;
50         private JPanel panelNorth;
51         private JPanel panelWest;
52         private JLabel labelVersion;
53         private JLabel labelTitle;
54         private JLabel labelDifficulty;
55         private JLabel labelLevel;
56         private JSpinner spinnerLevel;
57         private JCheckBox checkMoreLv;
58         private JCheckBox checkLessLv;
59         private JPanel panelEast;
60         private JPanel panelCentre;
61         private JButton btnImport;
62         private JButton btnStart;
63         private JButton btnExit;
64         private JComboBox comboDifficultySelect;
65         private JLabel labelLvCaution;
66         private JComboBox comboAttribute;
67         private SettingJSONProperty property = new SettingJSONProperty();
68         private JButton btnTwitterIntegration;
69         private String[] integratorArray;
70         private boolean integratorBool = false;
71         private JTextArea textArea;
72         private JScrollPane scrollPane;
73         private CompletableFuture<Void> softwareUpdateFuture = null;
74         private CompletableFuture<Void> albumTypeEstimateFuture = null;
75         private String albumType = Messages.MSGAlbumTypeBeingCalculated.toString();
76         private Logger logger = LoggerFactory.getLogger(DelesteRandomSelector.class);
77
78         /**
79          * Launch the application.
80          */
81         public static void main(String[] args) {
82                 EventQueue.invokeLater(() -> {
83                         try {
84                                 DelesteRandomSelector frame = new DelesteRandomSelector();
85                                 frame.setVisible(true);
86                         } catch (Exception e) {
87                                 e.printStackTrace();
88                         }
89                 });
90         }
91
92         /**
93          * log file prefix:
94          *  this.getClass() + ":[LEVEL]: " +
95          */
96
97         /**
98          * Create the frame.
99          */
100         public DelesteRandomSelector() {
101                 boolean isFirst = !Scraping.databaseExists();
102                 if(isFirst) {
103                         JOptionPane.showMessageDialog(this, Messages.MSGDatabaseNotExist.toString());
104                         if(!Scraping.writeToJson(Scraping.getWholeData())) {
105                                 JOptionPane.showMessageDialog(this, "Exception:NullPointerException\nCannot Keep up! Please re-download this Application!");
106                                 throw new NullPointerException("FATAL: cannot continue!");
107                         }
108                 }
109                 ExecutorService es = Executors.newWorkStealingPool();
110                 CompletableFuture<ArrayList<Song>> getFromJsonFuture = CompletableFuture.supplyAsync(() -> Scraping.getFromJson(), es);
111                 CompletableFuture<ArrayList<Song>> getWholeDataFuture = CompletableFuture.supplyAsync(() -> Scraping.getWholeData(), es);
112                 if(!Settings.fileExists() && !Settings.writeDownJSON()) {
113                         JOptionPane.showMessageDialog(this, "Exception:NullPointerException\nCannot Keep up! Please re-download this Application!");
114                         throw new NullPointerException("FATAL: cannot continue!");
115                 }
116                 this.logger.debug("Loading settings...");
117                 this.property.setCheckLibraryUpdates(Settings.needToCheckLibraryUpdates());
118                 this.property.setCheckVersion(Settings.needToCheckVersion());
119                 this.property.setWindowWidth(Settings.getWindowWidth());
120                 this.property.setWindowHeight(Settings.getWindowHeight());
121                 this.property.setSongLimit(Settings.getSongsLimit());
122                 this.property.setSaveScoreLog(Settings.saveScoreLog());
123                 this.logger.debug("Load settings done.");
124                 this.logger.debug("Version check: {}", this.property.isCheckVersion());
125                 this.logger.debug("Library update check: {}", this.property.isCheckLibraryUpdates());
126                 this.logger.debug("Window Width: {}", this.property.getWindowWidth());
127                 this.logger.debug("Window Height: {}", this.property.getWindowHeight());
128                 this.logger.debug("Song Limit: {}", this.property.getSongLimit());
129                 this.logger.debug("SaveScoreLog: {}", this.property.isSaveScoreLog());
130                 EstimateAlbumTypeCycle.Initialization();
131                 if(Files.exists(Paths.get("generated/albumCycle.json"))) {
132                         this.albumType = EstimateAlbumTypeCycle.getCurrentCycle();
133                 }
134                 if(this.property.isCheckVersion()) {
135                         this.softwareUpdateFuture = CompletableFuture.runAsync(() -> CheckVersion.needToBeUpdated(), es);
136                 }
137                 BiConsumer<ArrayList<Song>, ArrayList<Song>> updateConsumer = (list1, list2) -> {
138                         this.logger.info("Checking database updates...");
139                         if(list1.size() > list2.size()) {
140                                 long time = System.currentTimeMillis();
141                                 this.logger.info("{} Update detected.", (list1.size() - list2.size()));
142                                 Scraping.writeToJson(list1);
143                                 this.logger.info("Update completed in {} ms", (System.currentTimeMillis() - time));
144                                 this.logger.info("Updated database size: {}", list1.size());
145                         } else {
146                                 this.logger.info("database is up-to-date.");
147                         }
148                 };
149                 Runnable setEnabled = () -> {
150                         try {
151                                 Thread.sleep(1000);
152                         } catch (InterruptedException e1) {
153                                 // TODO 自動生成された catch ブロック
154                                 e1.printStackTrace();
155                         }
156                         this.btnImport.setEnabled(true);
157                         this.btnImport.setText(Messages.MSGNarrowingDownSongs.toString());
158                 };
159                 getWholeDataFuture.thenAcceptAsync(list -> this.logger.info("Scraping data size:" + list.size()), es);
160                 getFromJsonFuture.thenAcceptAsync(list -> this.logger.info("Currently database size:" + list.size()), es);
161                 if(this.property.isCheckLibraryUpdates()) {
162                         CompletableFuture<Void> updatedFuture = getWholeDataFuture.thenAcceptBothAsync(getFromJsonFuture, updateConsumer, es);
163                         updatedFuture.thenRunAsync(setEnabled, es);
164                 }
165                 this.logger.debug("Version: {}", CheckVersion.getVersion());
166                 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
167                 this.setBounds(100, 100, this.property.getWindowWidth(), this.property.getWindowHeight());
168                 // this.setBounds(100, 100, 640, 360);
169                 this.contentPane = new JPanel();
170                 this.contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
171                 this.setContentPane(this.contentPane);
172                 this.contentPane.setLayout(new BorderLayout(0, 0));
173
174                 this.panelNorth = new JPanel();
175                 this.contentPane.add(this.panelNorth, BorderLayout.NORTH);
176                 this.panelNorth.setLayout(new FormLayout(new ColumnSpec[] {
177                                 ColumnSpec.decode("max(302dlu;default)"),
178                                 FormSpecs.RELATED_GAP_COLSPEC,
179                                 ColumnSpec.decode("40px"),},
180                                 new RowSpec[] {
181                                                 RowSpec.decode("20px"),}));
182
183                 this.labelTitle = new JLabel("デレステ課題曲セレクター");
184                 this.labelTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 16));
185                 this.panelNorth.add(this.labelTitle, "1, 1, center, top");
186
187                 this.labelVersion = new JLabel(CheckVersion.getVersion());
188                 this.labelVersion.setFont(new Font("SansSerif", Font.BOLD, 12));
189                 this.panelNorth.add(this.labelVersion, "3, 1, right, top");
190
191                 this.panelWest = new JPanel();
192                 this.contentPane.add(this.panelWest, BorderLayout.WEST);
193                 this.panelWest.setLayout(new FormLayout(new ColumnSpec[] {
194                                 FormSpecs.LABEL_COMPONENT_GAP_COLSPEC,
195                                 ColumnSpec.decode("112px:grow"),},
196                                 new RowSpec[] {
197                                                 FormSpecs.LINE_GAP_ROWSPEC,
198                                                 RowSpec.decode("19px"),
199                                                 FormSpecs.RELATED_GAP_ROWSPEC,
200                                                 RowSpec.decode("max(12dlu;default)"),
201                                                 FormSpecs.RELATED_GAP_ROWSPEC,
202                                                 RowSpec.decode("max(12dlu;default)"),
203                                                 FormSpecs.RELATED_GAP_ROWSPEC,
204                                                 RowSpec.decode("12dlu"),
205                                                 FormSpecs.RELATED_GAP_ROWSPEC,
206                                                 RowSpec.decode("max(12dlu;default)"),
207                                                 FormSpecs.RELATED_GAP_ROWSPEC,
208                                                 RowSpec.decode("max(12dlu;default)"),
209                                                 FormSpecs.RELATED_GAP_ROWSPEC,
210                                                 RowSpec.decode("max(12dlu;default)"),
211                                                 FormSpecs.RELATED_GAP_ROWSPEC,
212                                                 RowSpec.decode("max(52dlu;default)"),}));
213
214                 this.labelDifficulty = new JLabel("難易度選択");
215                 this.labelDifficulty.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
216                 this.panelWest.add(this.labelDifficulty, "2, 2, center, default");
217
218                 this.comboDifficultySelect = new JComboBox();
219                 this.comboDifficultySelect.setFont(new Font("Dialog", Font.BOLD, 12));
220                 this.comboDifficultySelect.setModel(new DefaultComboBoxModel(new String[] {"指定なし", "DEBUT", "REGULAR", "PRO", "MASTER", "MASTER+", "ⓁMASTER+", "LIGHT", "TRICK", "PIANO", "FORTE", "WITCH"}));
221                 this.panelWest.add(this.comboDifficultySelect, "2, 4, fill, default");
222
223                 this.comboAttribute = new JComboBox();
224                 this.comboAttribute.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
225                 this.comboAttribute.setModel(new DefaultComboBoxModel(new String[] {"指定なし", "全タイプ", "キュート", "クール", "パッション"}));
226                 this.panelWest.add(this.comboAttribute, "2, 6, fill, default");
227
228                 this.labelLevel = new JLabel("楽曲Lv");
229                 this.labelLevel.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
230                 this.panelWest.add(this.labelLevel, "2, 8, center, default");
231
232                 this.spinnerLevel = new JSpinner();
233                 this.panelWest.add(this.spinnerLevel, "2, 10");
234
235                 this.checkLessLv = new JCheckBox("指定Lv以下");
236                 this.checkLessLv.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
237                 this.panelWest.add(this.checkLessLv, "2, 12");
238
239                 this.checkMoreLv = new JCheckBox("指定Lv以上");
240                 this.checkMoreLv.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
241                 this.panelWest.add(this.checkMoreLv, "2, 14");
242
243                 this.labelLvCaution = new JLabel("<html><body>※以下以上両方にチェックをつけることで指定レベルのみ絞り込むことができます</body></html>");
244                 this.labelLvCaution.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
245                 this.panelWest.add(this.labelLvCaution, "2, 16, fill, fill");
246
247                 this.panelEast = new JPanel();
248                 this.contentPane.add(this.panelEast, BorderLayout.EAST);
249                 this.panelEast.setLayout(new FormLayout(new ColumnSpec[] {
250                                 ColumnSpec.decode("98px"),},
251                                 new RowSpec[] {
252                                                 RowSpec.decode("26px"),
253                                                 FormSpecs.RELATED_GAP_ROWSPEC,
254                                                 RowSpec.decode("max(36dlu;default)"),
255                                                 FormSpecs.RELATED_GAP_ROWSPEC,
256                                                 FormSpecs.DEFAULT_ROWSPEC,
257                                                 FormSpecs.RELATED_GAP_ROWSPEC,
258                                                 RowSpec.decode("max(30dlu;default)"),
259                                                 FormSpecs.RELATED_GAP_ROWSPEC,
260                                                 RowSpec.decode("max(15dlu;default)"),
261                                                 FormSpecs.RELATED_GAP_ROWSPEC,
262                                                 RowSpec.decode("max(11dlu;default)"),
263                                                 FormSpecs.RELATED_GAP_ROWSPEC,
264                                                 FormSpecs.DEFAULT_ROWSPEC,
265                                                 FormSpecs.RELATED_GAP_ROWSPEC,
266                                                 FormSpecs.DEFAULT_ROWSPEC,
267                                                 FormSpecs.RELATED_GAP_ROWSPEC,
268                                                 FormSpecs.DEFAULT_ROWSPEC,}));
269
270                 this.btnImport = new JButton("<html><body>データベース<br>更新中…</body></html>");
271                 this.btnImport.setEnabled(false);
272                 this.btnImport.addActionListener(e -> {
273                         ArrayList<Song> fromJson = Scraping.getFromJson();
274                         ArrayList<Song> specificlevelList = Scraping.getSpecificLevelSongs(fromJson, (Integer)DelesteRandomSelector.this.spinnerLevel.getValue(), DelesteRandomSelector.this.checkLessLv.isSelected(), DelesteRandomSelector.this.checkMoreLv.isSelected());
275                         ArrayList<Song> specificDifficultyList = Scraping.getSpecificDifficultySongs(specificlevelList, DelesteRandomSelector.this.comboDifficultySelect.getSelectedItem().toString());
276                         ArrayList<Song> specificAttributeList = Scraping.getSpecificAttributeSongs(specificDifficultyList, DelesteRandomSelector.this.comboAttribute.getSelectedItem().toString());
277                         ArrayList<Song> specificTypeList = Scraping.getSpecificAlbumTypeSongs(specificAttributeList, EstimateAlbumTypeCycle.getCurrentCycle());
278                         if(!selectedSongsList.isEmpty()) {
279                                 selectedSongsList.clear();
280                         }
281                         selectedSongsList.addAll((DelesteRandomSelector.this.comboDifficultySelect.getSelectedItem().equals(Scraping.MASTERPLUS) || DelesteRandomSelector.this.comboDifficultySelect.getSelectedItem().equals(Scraping.LEGACYMASTERPLUS)) ? specificTypeList : specificAttributeList);
282                         DelesteRandomSelector.this.logger.info("Songs are selected.We are Ready to go.");
283                         JOptionPane.showMessageDialog(null, "絞り込み完了!「開始」をクリックすることで選曲できます!");
284                 });
285                 this.btnImport.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
286                 this.panelEast.add(this.btnImport, "1, 3, fill, fill");
287
288                 this.btnStart = new JButton(Messages.MSGCalcStart.toString());
289                 this.btnStart.addActionListener(e -> {
290                         Random random = new Random(System.currentTimeMillis());
291                         String paneString = "";
292                         DelesteRandomSelector.this.integratorArray = new String[DelesteRandomSelector.this.property.getSongLimit()];
293                         for(int i = 0; i < DelesteRandomSelector.this.property.getSongLimit(); i++) {
294                                 int randomInt = random.nextInt(selectedSongsList.size());
295                                 String typeString = DelesteRandomSelector.this.comboDifficultySelect.getSelectedItem().equals(Scraping.MASTERPLUS) || DelesteRandomSelector.this.comboDifficultySelect.getSelectedItem().equals(Scraping.LEGACYMASTERPLUS) ? EstimateAlbumTypeCycle.getCurrentCycle() : "";
296                                 paneString = paneString + (i + 1) + "曲目: " + selectedSongsList.get(randomInt).getAttribute() + " [" + selectedSongsList.get(randomInt).getDifficulty() + "]「" + selectedSongsList.get(randomInt).getName() + "」!(Lv:" + selectedSongsList.get(randomInt).getLevel() + " " + typeString + ")\n\n";
297                                 DelesteRandomSelector.this.integratorArray[i] = selectedSongsList.get(randomInt).getName() + "(Lv" + selectedSongsList.get(randomInt).getLevel() + ")\n";
298                         }
299                         paneString = paneString + "この" + DelesteRandomSelector.this.property.getSongLimit() + "曲をプレイしましょう!!!";
300                         DelesteRandomSelector.this.textArea.setText(paneString);
301                         DelesteRandomSelector.this.integratorBool = true;
302                         DelesteRandomSelector.this.logger.info("show up completed.");
303                 });
304                 this.btnStart.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
305                 this.panelEast.add(this.btnStart, "1, 7, fill, fill");
306
307                 this.btnTwitterIntegration = new JButton("Twitter連携");
308                 this.btnTwitterIntegration.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 11));
309                 this.btnTwitterIntegration.addActionListener(e -> {
310                         boolean authorizationStatus = TwitterIntegration.authorization();
311                         String updatedStatus = "デレステ課題曲セレクターで\n";
312                         int lengthLimit = updatedStatus.length();
313                         boolean isBroken = false;
314                         if(!DelesteRandomSelector.this.integratorBool) {
315                                 JOptionPane.showMessageDialog(null, "ちひろ「まだプレイを始めていないみたいですね」");
316                                 return;
317                         }
318                         for (String element : DelesteRandomSelector.this.integratorArray) {
319                                 updatedStatus = updatedStatus + element;
320                                 lengthLimit += element.length();
321                                 if(lengthLimit > 69) {
322                                         isBroken = true;
323                                         break;
324                                 }
325                         }
326                         if(isBroken) {
327                                 updatedStatus = updatedStatus + "…その他数曲\nをプレイしました!\n#DelesteRandomSelector #デレステ ";
328                         } else {
329                                 updatedStatus = updatedStatus + "をプレイしました!\n#DelesteRandomSelector #デレステ ";
330                         }
331                         DelesteRandomSelector.this.logger.info("status message constructed.");
332                         lengthLimit = updatedStatus.length();
333                         if(authorizationStatus) {
334                                 int option = JOptionPane.showConfirmDialog(null, "Twitterへ以下の内容を投稿します。よろしいですか?\n\n" + updatedStatus + "\n\n文字数:" + lengthLimit);
335                                 DelesteRandomSelector.this.logger.info("user seletced: " + option);
336                                 switch(option) {
337                                 case JOptionPane.OK_OPTION:
338                                         TwitterIntegration.PostTwitter(updatedStatus);
339                                         DelesteRandomSelector.this.logger.info("Success to update the status.");
340                                         JOptionPane.showMessageDialog(null, "投稿が完了しました。");
341                                         break;
342                                 case JOptionPane.NO_OPTION:
343                                         DelesteRandomSelector.this.logger.info("There is no will to post.");
344                                         break;
345                                 case JOptionPane.CANCEL_OPTION:
346                                         DelesteRandomSelector.this.logger.info("The Operation was canceled by user.");
347                                         break;
348                                 default:
349                                         break;
350                                 }
351                         } else {
352                                 DelesteRandomSelector.this.logger.info("seems to reject the permission.it should need try again.");
353                         }
354                 });
355                 this.panelEast.add(this.btnTwitterIntegration, "1, 11");
356
357                 this.btnExit = new JButton("終了");
358                 this.btnExit.addActionListener(e -> {
359                         if(DelesteRandomSelector.this.softwareUpdateFuture.isDone() || DelesteRandomSelector.this.albumTypeEstimateFuture.isDone()) {
360                                 DelesteRandomSelector.this.logger.info("Requested Exit by Button");
361                                 System.exit(0);
362                         } else {
363                                 JOptionPane.showMessageDialog(null, "内部更新処理が完了していません。少し待ってからやり直してください。");
364                         }
365                 });
366                 this.btnExit.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
367                 this.panelEast.add(this.btnExit, "1, 13");
368
369                 this.panelCentre = new JPanel();
370                 this.contentPane.add(this.panelCentre, BorderLayout.CENTER);
371                 this.panelCentre.setLayout(new BorderLayout(0, 0));
372
373                 this.textArea = new JTextArea();
374                 this.textArea.setText("楽曲選択の手順\r\n1.難易度、属性、レベルを選択する\r\n2.「楽曲取り込み」ボタンを押す!\r\n3.「開始」ボタンを押す!\r\n4.選択された楽曲がここに表示されます!\r\n現在設定されている楽曲選択の最大数:" + this.property.getSongLimit() + "\n現在のMASTER+アルバム周期(推定):" + this.albumType);
375                 this.textArea.setEditable(false);
376
377                 this.scrollPane = new JScrollPane(this.textArea);
378                 this.panelCentre.add(this.scrollPane, BorderLayout.CENTER);
379                 if(isFirst || !this.property.isCheckLibraryUpdates()) {
380                         setEnabled.run();
381                 }
382         }
383
384 }