OSDN Git Service

fix: fix not applying window size properties
[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.Easter;
37 import com.ranfa.lib.EstimateAlbumTypeCycle;
38 import com.ranfa.lib.ManualUpdateThreadImpl;
39 import com.ranfa.lib.Scraping;
40 import com.ranfa.lib.SettingJSONProperty;
41 import com.ranfa.lib.Settings;
42 import com.ranfa.lib.Song;
43 import com.ranfa.lib.TwitterIntegration;
44 import com.ranfa.lib.Version;
45
46 @Version(major = 3, minor = 0, patch = 0)
47 public class DelesteRandomSelector extends JFrame {
48
49         private static ArrayList<Song> selectedSongsList = new ArrayList<>();
50
51         private JPanel contentPane;
52         private JPanel panelNorth;
53         private JPanel panelWest;
54         private JLabel labelVersion;
55         private JLabel labelTitle;
56         private JLabel labelDifficulty;
57         private JLabel labelLevel;
58         private JSpinner spinnerLevel;
59         private JCheckBox checkMoreLv;
60         private JCheckBox checkLessLv;
61         private JPanel panelEast;
62         private JPanel panelCentre;
63         private JButton btnImport;
64         private JButton btnStart;
65         private JButton btnExit;
66         private JComboBox comboDifficultySelect;
67         private JLabel labelLvCaution;
68         private JComboBox comboAttribute;
69         private SettingJSONProperty property = new SettingJSONProperty();
70         private JButton btnTwitterIntegration;
71         private String[] integratorArray;
72         private boolean integratorBool = false;
73         private JTextArea textArea;
74         private JScrollPane scrollPane;
75         private CompletableFuture<Void> softwareUpdateFuture = null;
76         private CompletableFuture<Void> albumTypeEstimateFuture = null;
77         private String albumType = Messages.MSGAlbumTypeBeingCalculated.toString();
78         private Logger logger = LoggerFactory.getLogger(DelesteRandomSelector.class);
79         private ManualUpdateThreadImpl impl;
80         private Thread manualUpdateThread;
81         private JButton btnManualUpdate;
82         private Easter easter;
83
84         /**
85          * Launch the application.
86          */
87         public static void main(String[] args) {
88                 EventQueue.invokeLater(() -> {
89                         try {
90                                 DelesteRandomSelector frame = new DelesteRandomSelector();
91                                 frame.setVisible(true);
92                         } catch (Exception e) {
93                                 e.printStackTrace();
94                         }
95                 });
96         }
97
98         /**
99          * log file prefix:
100          *  this.getClass() + ":[LEVEL]: " +
101          */
102
103         /**
104          * Create the frame.
105          */
106         public DelesteRandomSelector() {
107                 boolean isFirst = !Scraping.databaseExists();
108                 if(isFirst) {
109                         JOptionPane.showMessageDialog(this, Messages.MSGDatabaseNotExist.toString());
110                         if(!Scraping.writeToJson(Scraping.getWholeData())) {
111                                 JOptionPane.showMessageDialog(this, "Exception:NullPointerException\nCannot Keep up! Please re-download this Application!");
112                                 throw new NullPointerException("FATAL: cannot continue!");
113                         }
114                 }
115                 ExecutorService es = Executors.newWorkStealingPool();
116                 CompletableFuture<ArrayList<Song>> getFromJsonFuture = CompletableFuture.supplyAsync(() -> Scraping.getFromJson(), es);
117                 CompletableFuture<ArrayList<Song>> getWholeDataFuture = CompletableFuture.supplyAsync(() -> Scraping.getWholeData(), es);
118                 if(!Settings.fileExists() && !Settings.writeDownJSON()) {
119                         JOptionPane.showMessageDialog(this, "Exception:NullPointerException\nCannot Keep up! Please re-download this Application!");
120                         throw new NullPointerException("FATAL: cannot continue!");
121                 }
122                 this.logger.debug("Loading settings...");
123                 this.property.setCheckLibraryUpdates(Settings.needToCheckLibraryUpdates());
124                 this.property.setCheckVersion(Settings.needToCheckVersion());
125                 this.property.setWindowWidth(Settings.getWindowWidth());
126                 this.property.setWindowHeight(Settings.getWindowHeight());
127                 this.property.setSongLimit(Settings.getSongsLimit());
128                 this.property.setSaveScoreLog(Settings.saveScoreLog());
129                 this.logger.debug("Load settings done.");
130                 this.logger.debug("Version check: {}", this.property.isCheckVersion());
131                 this.logger.debug("Library update check: {}", this.property.isCheckLibraryUpdates());
132                 this.logger.debug("Window Width: {}", this.property.getWindowWidth());
133                 this.logger.debug("Window Height: {}", this.property.getWindowHeight());
134                 this.logger.debug("Song Limit: {}", this.property.getSongLimit());
135                 this.logger.debug("SaveScoreLog: {}", this.property.isSaveScoreLog());
136                 EstimateAlbumTypeCycle.Initialization();
137                 if(Files.exists(Paths.get("generated/albumCycle.json"))) {
138                         this.albumType = EstimateAlbumTypeCycle.getCurrentCycle();
139                 }
140                 if(this.property.isCheckVersion()) {
141                         this.softwareUpdateFuture = CompletableFuture.runAsync(() -> CheckVersion.needToBeUpdated(), es);
142                 }
143                 BiConsumer<ArrayList<Song>, ArrayList<Song>> updateConsumer = (list1, list2) -> {
144                         this.logger.info("Checking database updates...");
145                         if(list1.size() > list2.size()) {
146                                 long time = System.currentTimeMillis();
147                                 this.logger.info("{} Update detected.", (list1.size() - list2.size()));
148                                 Scraping.writeToJson(list1);
149                                 this.logger.info("Update completed in {} ms", (System.currentTimeMillis() - time));
150                                 this.logger.info("Updated database size: {}", list1.size());
151                         } else {
152                                 this.logger.info("database is up-to-date.");
153                         }
154                 };
155                 Runnable setEnabled = () -> {
156                         try {
157                                 Thread.sleep(3 * 1000L);
158                         } catch (InterruptedException e1) {
159                                 this.logger.error("Thread has been interrupted during waiting cooldown.", e1);
160                         }
161                         this.btnImport.setEnabled(true);
162                         this.btnImport.setText(Messages.MSGNarrowingDownSongs.toString());
163                 };
164                 getWholeDataFuture.thenAcceptAsync(list -> this.logger.info("Scraping data size:" + list.size()), es);
165                 getFromJsonFuture.thenAcceptAsync(list -> this.logger.info("Currently database size:" + list.size()), es);
166                 if(this.property.isCheckLibraryUpdates()) {
167                         CompletableFuture<Void> updatedFuture = getWholeDataFuture.thenAcceptBothAsync(getFromJsonFuture, updateConsumer, es);
168                         updatedFuture.thenRunAsync(setEnabled, es);
169                 }
170                 this.easter = new Easter();
171                 this.setTitle(this.easter.getTodaysBirth());
172                 this.logger.debug("Version: {}", CheckVersion.getVersion());
173                 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
174                 this.setBounds(100, 100, this.property.getWindowWidth(), this.property.getWindowHeight());
175                 // this.setBounds(100, 100, 640, 360);
176                 this.contentPane = new JPanel();
177                 this.contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
178                 this.setContentPane(this.contentPane);
179                 this.contentPane.setLayout(new BorderLayout(0, 0));
180
181                 this.panelNorth = new JPanel();
182                 this.contentPane.add(this.panelNorth, BorderLayout.NORTH);
183                 this.panelNorth.setLayout(new FormLayout(new ColumnSpec[] {
184                                 ColumnSpec.decode("max(302dlu;default)"),
185                                 FormSpecs.RELATED_GAP_COLSPEC,
186                                 ColumnSpec.decode("40px"),},
187                                 new RowSpec[] {
188                                                 RowSpec.decode("20px"),}));
189
190                 this.labelTitle = new JLabel(Messages.MSGTitle.toString());
191                 this.labelTitle.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 16));
192                 this.panelNorth.add(this.labelTitle, "1, 1, center, top");
193
194                 this.labelVersion = new JLabel(CheckVersion.getVersion());
195                 this.labelVersion.setFont(new Font("SansSerif", Font.BOLD, 12));
196                 this.panelNorth.add(this.labelVersion, "3, 1, right, top");
197
198                 this.panelWest = new JPanel();
199                 this.contentPane.add(this.panelWest, BorderLayout.WEST);
200                 this.panelWest.setLayout(new FormLayout(new ColumnSpec[] {
201                                 FormSpecs.LABEL_COMPONENT_GAP_COLSPEC,
202                                 ColumnSpec.decode("112px:grow"),},
203                                 new RowSpec[] {
204                                                 FormSpecs.LINE_GAP_ROWSPEC,
205                                                 RowSpec.decode("19px"),
206                                                 FormSpecs.RELATED_GAP_ROWSPEC,
207                                                 RowSpec.decode("max(12dlu;default)"),
208                                                 FormSpecs.RELATED_GAP_ROWSPEC,
209                                                 RowSpec.decode("max(12dlu;default)"),
210                                                 FormSpecs.RELATED_GAP_ROWSPEC,
211                                                 RowSpec.decode("12dlu"),
212                                                 FormSpecs.RELATED_GAP_ROWSPEC,
213                                                 RowSpec.decode("max(12dlu;default)"),
214                                                 FormSpecs.RELATED_GAP_ROWSPEC,
215                                                 RowSpec.decode("max(12dlu;default)"),
216                                                 FormSpecs.RELATED_GAP_ROWSPEC,
217                                                 RowSpec.decode("max(12dlu;default)"),
218                                                 FormSpecs.RELATED_GAP_ROWSPEC,
219                                                 RowSpec.decode("max(52dlu;default)"),}));
220
221                 this.labelDifficulty = new JLabel(Messages.MSGSelectDifficulty.toString());
222                 this.labelDifficulty.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
223                 this.panelWest.add(this.labelDifficulty, "2, 2, center, default");
224
225                 this.comboDifficultySelect = new JComboBox();
226                 this.comboDifficultySelect.setFont(new Font("Dialog", Font.BOLD, 12));
227                 this.comboDifficultySelect.setModel(new DefaultComboBoxModel(new String[] {Messages.MSGNonSelected.toString(), "DEBUT", "REGULAR", "PRO", "MASTER", "MASTER+", "ⓁMASTER+", "LIGHT", "TRICK", "PIANO", "FORTE", "WITCH"}));
228                 this.panelWest.add(this.comboDifficultySelect, "2, 4, fill, default");
229
230                 this.comboAttribute = new JComboBox();
231                 this.comboAttribute.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
232                 this.comboAttribute.setModel(new DefaultComboBoxModel(new String[] {Messages.MSGNonSelected.toString(), "全タイプ", "キュート", "クール", "パッション"}));
233                 this.panelWest.add(this.comboAttribute, "2, 6, fill, default");
234
235                 this.labelLevel = new JLabel(Messages.MSGSongLevel.toString());
236                 this.labelLevel.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
237                 this.panelWest.add(this.labelLevel, "2, 8, center, default");
238
239                 this.spinnerLevel = new JSpinner();
240                 this.panelWest.add(this.spinnerLevel, "2, 10");
241
242                 this.checkLessLv = new JCheckBox(Messages.MSGBelowSpecificLevel.toString());
243                 this.checkLessLv.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
244                 this.panelWest.add(this.checkLessLv, "2, 12");
245
246                 this.checkMoreLv = new JCheckBox(Messages.MSGOverSpecificLevel.toString());
247                 this.checkMoreLv.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
248                 this.panelWest.add(this.checkMoreLv, "2, 14");
249
250                 this.labelLvCaution = new JLabel(Messages.MSGLevelCheckboxInfo.toString());
251                 this.labelLvCaution.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
252                 this.panelWest.add(this.labelLvCaution, "2, 16, fill, fill");
253
254                 this.panelEast = new JPanel();
255                 this.contentPane.add(this.panelEast, BorderLayout.EAST);
256                 this.panelEast.setLayout(new FormLayout(new ColumnSpec[] {
257                                 ColumnSpec.decode("98px"),},
258                                 new RowSpec[] {
259                                                 RowSpec.decode("26px"),
260                                                 FormSpecs.RELATED_GAP_ROWSPEC,
261                                                 RowSpec.decode("max(36dlu;default)"),
262                                                 FormSpecs.RELATED_GAP_ROWSPEC,
263                                                 FormSpecs.DEFAULT_ROWSPEC,
264                                                 FormSpecs.RELATED_GAP_ROWSPEC,
265                                                 RowSpec.decode("max(30dlu;default)"),
266                                                 FormSpecs.RELATED_GAP_ROWSPEC,
267                                                 RowSpec.decode("max(15dlu;default)"),
268                                                 FormSpecs.RELATED_GAP_ROWSPEC,
269                                                 RowSpec.decode("max(11dlu;default)"),
270                                                 FormSpecs.RELATED_GAP_ROWSPEC,
271                                                 FormSpecs.DEFAULT_ROWSPEC,
272                                                 FormSpecs.RELATED_GAP_ROWSPEC,
273                                                 FormSpecs.DEFAULT_ROWSPEC,
274                                                 FormSpecs.RELATED_GAP_ROWSPEC,
275                                                 FormSpecs.DEFAULT_ROWSPEC,}));
276
277                 this.btnImport = new JButton(Messages.MSGUpdatingDatabase.toString());
278                 this.btnImport.setEnabled(false);
279                 this.btnImport.addActionListener(e -> {
280                         if(this.impl != null) {
281                                 if(!this.impl.getFlag()) {
282                                         JOptionPane.showMessageDialog(null, Messages.MSGManualUpdateNotCompleteYet.toString());
283                                 }
284                         }
285                         ArrayList<Song> fromJson = Scraping.getFromJson();
286                         ArrayList<Song> specificlevelList = Scraping.getSpecificLevelSongs(fromJson, (Integer)DelesteRandomSelector.this.spinnerLevel.getValue(), DelesteRandomSelector.this.checkLessLv.isSelected(), DelesteRandomSelector.this.checkMoreLv.isSelected());
287                         ArrayList<Song> specificDifficultyList = Scraping.getSpecificDifficultySongs(specificlevelList, DelesteRandomSelector.this.comboDifficultySelect.getSelectedItem().toString());
288                         ArrayList<Song> specificAttributeList = Scraping.getSpecificAttributeSongs(specificDifficultyList, DelesteRandomSelector.this.comboAttribute.getSelectedItem().toString());
289                         ArrayList<Song> specificTypeList = Scraping.getSpecificAlbumTypeSongs(specificAttributeList, EstimateAlbumTypeCycle.getCurrentCycle());
290                         if(!selectedSongsList.isEmpty()) {
291                                 selectedSongsList.clear();
292                         }
293                         selectedSongsList.addAll((DelesteRandomSelector.this.comboDifficultySelect.getSelectedItem().equals(Scraping.MASTERPLUS) || DelesteRandomSelector.this.comboDifficultySelect.getSelectedItem().equals(Scraping.LEGACYMASTERPLUS)) ? specificTypeList : specificAttributeList);
294                         DelesteRandomSelector.this.logger.info("Songs are selected.We are Ready to go.");
295                         JOptionPane.showMessageDialog(null, Messages.MSGCompleteNarrowDown.toString());
296                 });
297                 this.btnImport.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
298                 this.panelEast.add(this.btnImport, "1, 3, fill, fill");
299
300                 this.btnStart = new JButton(Messages.MSGCalcStart.toString());
301                 this.btnStart.addActionListener(e -> {
302                         Random random = new Random(System.currentTimeMillis());
303                         String paneString = "";
304                         DelesteRandomSelector.this.integratorArray = new String[DelesteRandomSelector.this.property.getSongLimit()];
305                         for(int i = 0; i < DelesteRandomSelector.this.property.getSongLimit(); i++) {
306                                 int randomInt = random.nextInt(selectedSongsList.size());
307                                 String typeString = DelesteRandomSelector.this.comboDifficultySelect.getSelectedItem().equals(Scraping.MASTERPLUS) || DelesteRandomSelector.this.comboDifficultySelect.getSelectedItem().equals(Scraping.LEGACYMASTERPLUS) ? EstimateAlbumTypeCycle.getCurrentCycle() : "";
308                                 paneString = paneString + (i + 1) + Messages.MSGNumberOfSongs.toString() + " " + selectedSongsList.get(randomInt).getAttribute() + " [" + selectedSongsList.get(randomInt).getDifficulty() + "]「" + selectedSongsList.get(randomInt).getName() + "」!(Lv:" + selectedSongsList.get(randomInt).getLevel() + " " + typeString + ")\n\n";
309                                 DelesteRandomSelector.this.integratorArray[i] = selectedSongsList.get(randomInt).getName() + "(Lv" + selectedSongsList.get(randomInt).getLevel() + ")\n";
310                         }
311                         paneString = paneString + Messages.MSGThisPhrase.toString() + DelesteRandomSelector.this.property.getSongLimit() + Messages.MSGPlayPhrase.toString();
312                         DelesteRandomSelector.this.textArea.setText(paneString);
313                         DelesteRandomSelector.this.integratorBool = true;
314                         DelesteRandomSelector.this.logger.info("show up completed.");
315                 });
316                 this.btnStart.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
317                 this.panelEast.add(this.btnStart, "1, 7, fill, fill");
318
319                 this.btnTwitterIntegration = new JButton(Messages.MSGTwitterIntegration.toString());
320                 this.btnTwitterIntegration.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 11));
321                 this.btnTwitterIntegration.addActionListener(e -> {
322                         boolean authorizationStatus = TwitterIntegration.authorization();
323                         String updatedStatus = Messages.MSGUsingThisAppPhrase.toString();
324                         int lengthLimit = updatedStatus.length();
325                         boolean isBroken = false;
326                         if(!DelesteRandomSelector.this.integratorBool) {
327                                 JOptionPane.showMessageDialog(null, Messages.MSGNotPlayYet.toString());
328                                 return;
329                         }
330                         for (String element : DelesteRandomSelector.this.integratorArray) {
331                                 updatedStatus = updatedStatus + element;
332                                 lengthLimit += element.length();
333                                 if(lengthLimit > 69) {
334                                         isBroken = true;
335                                         break;
336                                 }
337                         }
338                         if(isBroken) {
339                                 updatedStatus = updatedStatus + Messages.MSGTwitterPlayOtherwisePhrase.toString() + "\n#DelesteRandomSelector #デレステ ";
340                         } else {
341                                 updatedStatus = updatedStatus + Messages.MSGTwitterPlayOnlyPhrase.toString() + "\n#DelesteRandomSelector #デレステ ";
342                         }
343                         DelesteRandomSelector.this.logger.info("status message constructed.");
344                         lengthLimit = updatedStatus.length();
345                         if(authorizationStatus) {
346                                 int option = JOptionPane.showConfirmDialog(null, Messages.MSGTwitterIntegrationConfirm.toString() + updatedStatus + Messages.MSGStringLength.toString() + lengthLimit);
347                                 DelesteRandomSelector.this.logger.info("user seletced: " + option);
348                                 switch(option) {
349                                 case JOptionPane.OK_OPTION:
350                                         TwitterIntegration.PostTwitter(updatedStatus);
351                                         DelesteRandomSelector.this.logger.info("Success to update the status.");
352                                         JOptionPane.showMessageDialog(null, Messages.MSGCompletePost.toString());
353                                         break;
354                                 case JOptionPane.NO_OPTION:
355                                         DelesteRandomSelector.this.logger.info("There is no will to post.");
356                                         break;
357                                 case JOptionPane.CANCEL_OPTION:
358                                         DelesteRandomSelector.this.logger.info("The Operation was canceled by user.");
359                                         break;
360                                 default:
361                                         break;
362                                 }
363                         } else {
364                                 DelesteRandomSelector.this.logger.info("seems to reject the permission.it should need try again.");
365                         }
366                 });
367
368                 this.btnManualUpdate = new JButton(Messages.MSGManualUpdate.toString());
369                 this.btnManualUpdate.addActionListener(e -> {
370                         this.impl = new ManualUpdateThreadImpl();
371                         es.submit(this.impl);
372                 });
373                 this.panelEast.add(this.btnManualUpdate, "1, 9");
374                 this.panelEast.add(this.btnTwitterIntegration, "1, 11");
375
376                 this.btnExit = new JButton(Messages.MSGTerminate.toString());
377                 this.btnExit.addActionListener(e -> {
378                         if(DelesteRandomSelector.this.softwareUpdateFuture.isDone() || DelesteRandomSelector.this.albumTypeEstimateFuture.isDone() || !this.impl.getFlag()) {
379                                 DelesteRandomSelector.this.logger.info("Requested Exit by Button.");
380                                 this.logger.info("Shut down thread pool.");
381                                 es.shutdown();
382                                 System.exit(0);
383                         } else {
384                                 JOptionPane.showMessageDialog(null, Messages.MSGInternalYpdateNotDoneYet.toString());
385                         }
386                 });
387                 this.btnExit.setFont(new Font("UD デジタル 教科書体 NP-B", Font.BOLD, 13));
388                 this.panelEast.add(this.btnExit, "1, 13");
389
390                 this.panelCentre = new JPanel();
391                 this.contentPane.add(this.panelCentre, BorderLayout.CENTER);
392                 this.panelCentre.setLayout(new BorderLayout(0, 0));
393
394                 this.textArea = new JTextArea();
395                 this.textArea.setText(Messages.MSGNarrowDownProcedure.toString() + this.property.getSongLimit() + Messages.MSGCurrentAlbumType.toString() + this.albumType);
396                 this.textArea.setEditable(false);
397
398                 this.scrollPane = new JScrollPane(this.textArea);
399                 this.panelCentre.add(this.scrollPane, BorderLayout.CENTER);
400                 if(isFirst || !this.property.isCheckLibraryUpdates()) {
401                         setEnabled.run();
402                 }
403         }
404
405 }