4 import java.io.IOException;
5 import java.nio.file.Files;
6 import java.nio.file.Path;
7 import java.nio.file.Paths;
8 import java.util.ArrayList;
9 import java.util.concurrent.CompletableFuture;
10 import java.util.concurrent.ExecutionException;
11 import java.util.concurrent.ExecutorService;
12 import java.util.concurrent.Executors;
14 import javax.swing.JOptionPane;
16 import org.jsoup.Jsoup;
17 import org.jsoup.nodes.Document;
18 import org.jsoup.select.Elements;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
22 import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
23 import com.fasterxml.jackson.databind.ObjectMapper;
24 import com.fasterxml.jackson.databind.ObjectWriter;
25 import com.ranfa.lib.AlbumTypeEstimate.MASTERPLUS_TYPE;
26 import com.ranfa.main.Messages;
28 public class Scraping {
30 private final static String URI = "https://imascg-slstage-wiki.gamerch.com/%E6%A5%BD%E6%9B%B2%E8%A9%B3%E7%B4%B0%E4%B8%80%E8%A6%A7";
31 private final static String DBPATH = "generated/database.json";
32 private static Logger logger = LoggerFactory.getLogger(Scraping.class);
33 public final static String NONSELECTED = "指定なし";
34 public final static String ALL = "全タイプ";
35 public final static String CUTE = "キュート";
36 public final static String COOL = "クール";
37 public final static String PASSION = "パッション";
38 public final static String DEBUT = "DEBUT";
39 public final static String REGULAR = "REGULAR";
40 public final static String PRO = "PRO";
41 public final static String MASTER = "MASTER";
42 public final static String MASTERPLUS = "MASTER+";
43 public final static String LEGACYMASTERPLUS = "ⓁMASTER+";
44 public final static String LIGHT = "LIGHT";
45 public final static String TRICK = "TRICK";
46 public final static String PIANO = "PIANO";
47 public final static String FORTE = "FORTE";
48 public final static String WITCH = "WITCH";
50 public static boolean databaseExists() {
51 Path path = Paths.get(DBPATH);
52 return Files.exists(path);
55 public static String getDBPath() {
59 public static ArrayList<Song> getWholeData() {
60 long time = System.currentTimeMillis();
61 ExecutorService es = Executors.newWorkStealingPool();
62 CompletableFuture<ArrayList<ArrayList<Album>>> typeFetchFuture = CompletableFuture.supplyAsync(() -> AlbumTypeEstimate.getAlbumType(), es);
63 // if(databaseExists())
65 ArrayList<Song> res = new ArrayList<>();
68 Document document = Jsoup.connect(URI)
69 .userAgent("Java/DeresteRandomSelector More information is available at https://github.com/hizumiaoba/DeresteRandomSelector/")
73 Elements rows = document.getElementsByTag("tbody").get(0).select("tr");
74 ArrayList<ArrayList<Album>> typeLists = typeFetchFuture.get();
75 for(int i = 0; i < rows.size(); i++) {
76 String attribute = rows.get(i).select("td").get(0).text();
77 String name = rows.get(i).select("td").get(1).text();
78 String difficulty = rows.get(i).select("td").get(2).text();
79 int level = Integer.parseInt(rows.get(i).select("td").get(3).text());
81 if(rows.get(i).select("td").get(5).text().indexOf(",") == -1) {
82 notes = Integer.parseInt(rows.get(i).select("td").get(5).text());
84 String temp = rows.get(i).select("td").get(5).text();
85 String first = temp.substring(0, temp.indexOf(","));
86 String end = temp.substring(temp.indexOf(",") + 1);
87 notes = Integer.parseInt(first + end);
89 Song tmp = new Song();
90 tmp.setAttribute(attribute);
92 tmp.setDifficulty(difficulty);
95 if(difficulty.equals(LEGACYMASTERPLUS)) {
96 ArrayList<Album> newTypeList = typeLists.get(MASTERPLUS_TYPE.LEGACYMASTERPLUS.ordinal());
98 .filter(element -> element.getSongName().equals(name))
100 tmp.setAlbumType(element.getAlbumType());
102 } else if(difficulty.equals(MASTERPLUS)) {
103 ArrayList<Album> legacyTypeList = typeLists.get(MASTERPLUS_TYPE.NEWMASTERPLUS.ordinal());
104 legacyTypeList.stream()
105 .filter(element -> element.getSongName().equals(name))
106 .forEach(element -> {
107 tmp.setAlbumType(element.getAlbumType());
110 tmp.setAlbumType("Not-Implemented");
114 } catch (IOException | InterruptedException | ExecutionException e) {
115 logger.error("Exception was thrown during web scraping", e);
117 logger.info("scraping compeleted in {} ms", (System.currentTimeMillis() - time));
121 public static ArrayList<Song> getSpecificAttributeSongs(ArrayList<Song> data, String attribute) {
122 if(!attribute.equals(ALL)
123 && !attribute.equals(CUTE)
124 && !attribute.equals(COOL)
125 && !attribute.equals(PASSION)
126 && !attribute.equals(Messages.MSGNonSelected.toString())) {
127 throw new IllegalArgumentException("Illegal attribute value: " + attribute);
130 JOptionPane.showMessageDialog(null, "指定された属性の曲は存在しません。\n条件を変えてみてください");
131 throw new IllegalArgumentException("ArrayList must not empty.");
133 ArrayList<Song> res = new ArrayList<>();
134 if(attribute.equals(Messages.MSGNonSelected.toString())) {
138 .filter(element -> element.getAttribute().equals(attribute))
144 public static ArrayList<Song> getSpecificDifficultySongs(ArrayList<Song> data, String difficulty) {
145 if(!difficulty.equals(DEBUT)
146 && !difficulty.equals(REGULAR)
147 && !difficulty.equals(PRO)
148 && !difficulty.equals(MASTER)
149 && !difficulty.equals(MASTERPLUS)
150 && !difficulty.equals(LEGACYMASTERPLUS)
151 && !difficulty.equals(LIGHT)
152 && !difficulty.equals(TRICK)
153 && !difficulty.equals(PIANO)
154 && !difficulty.equals(FORTE)
155 && !difficulty.equals(WITCH)
156 && !difficulty.equals(Messages.MSGNonSelected.toString())) {
157 throw new IllegalArgumentException("Illegal difficulty value.");
160 throw new IllegalArgumentException("ArrayList must not empty.");
162 ArrayList<Song> res = new ArrayList<>();
163 if(difficulty.equals(Messages.MSGNonSelected.toString())) {
167 .filter(element -> element.getDifficulty().equals(difficulty))
173 public static ArrayList<Song> getSpecificLevelSongs(ArrayList<Song> data, int level, boolean isLess, boolean isMore) {
175 throw new IllegalArgumentException("Level must not negative.");
178 throw new IllegalArgumentException("ArrayList must not empty.");
180 if(!(isLess || isMore)) {
181 throw new IllegalArgumentException("Illegal boolean value.");
183 if(isLess && isMore) {
184 return getOnlyLevelSongs(data, level);
186 ArrayList<Song> res = new ArrayList<>();
189 .filter(element -> element.getLevel() < level)
193 .filter(element -> element.getLevel() > level)
199 public static ArrayList<Song> getSpecificAlbumTypeSongs(ArrayList<Song> data, String type) {
201 throw new IllegalArgumentException("type must not null.");
204 throw new IllegalArgumentException("ArrayList must not empty");
206 ArrayList<Song> res = new ArrayList<>();
208 .filter(element -> element.getAlbumType().equals(type))
213 private static ArrayList<Song> getOnlyLevelSongs(ArrayList<Song> data, int level) {
214 ArrayList<Song> res = new ArrayList<>();
216 .filter(element -> element.getLevel() == level)
222 public static ArrayList<Song> getFromJson() {
223 long time = System.currentTimeMillis();
224 SongJSONProperty property = null;
226 property = new ObjectMapper().readValue(new File(DBPATH), SongJSONProperty.class);
227 } catch (IOException e) {
228 logger.error("IOException was thrown during reading From JSON Database file.", e);
230 ArrayList<Song> res = new ArrayList<>();
231 if(property != null) {
232 res.addAll(property.getList());
234 throw new NullPointerException("json is null.");
236 logger.info("JSON reading compeleted in {} ms", (System.currentTimeMillis() - time));
240 public static boolean writeToJson(ArrayList<Song> list) {
242 SongJSONProperty property = new SongJSONProperty();
243 property.setList(list);
244 ObjectWriter writer = new ObjectMapper().writer(new DefaultPrettyPrinter());
246 if(Files.notExists(Paths.get("generated"))) {
247 Files.createDirectory(Paths.get("generated"));
249 writer.writeValue(Paths.get(DBPATH).toFile(), property);
250 } catch (IOException e) {
251 logger.error("IOException was thrown during writing to JSON database file.", e);