import java.io.IOException; import java.io.InputStreamReader; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.regex.Pattern; import java.awt.image.BufferedImage; public class ArcadeReader { /* * Important data we would like to know for all games: * Score * Rank (Probably implementation-specific) * Note accuracy [List] * Marvelous * Perfect * Great * Good * Bad * OK * Miss * Difficulty * Song Name / Title * Percentage (Can be EX Score, a percentage accuracy or survival percent) * Max Combo * Other (Not used by the auto detecter, used for storing misc. data.) * * Notes about Readers: * Love Live * - Does not use: Marvelous, OK * Project Diva * - Does not use: Marvelous, OK * - Fail condition is MISSxTAKE * DDR * - Does not use: Max Combo (Cannot calculate in combo carryover mode), Bad * - Fail condition is E rank. * Pop'n Music * - Does not use: Marvelous, Bad, OK * - Stores number of bars filled in Percentage. * - Fail condition is <17 in the meter (max is 24) * Sound Voltex * - Sound Voltex uses the note accuracy list slots as follows: * Early: * Error - Marvelous * Near - Perfect * Critical - Great * S-Critical - Good * Critical - Bad * Near - OK * Error - Miss * - Sound Voltex stores EX score in Percentage. * - Max Combo is Max Chain * - Sound Voltex will store additional data about accuracy of note types as such: * {"chip":{"scritical":0,"critical":0,"near":0,"error":0},"long":{"scritical":0,"error":0},"vol":{"scritical":0,"error":0},"gauge":,"gauge_pct":100} * //Also storing what type of clear gauge was met and the % of the gauge. * - Fail condition is <70% normal gauge. * IIDX * - Not going to support right now. * */ public static void retrieveData(Path img) { new LoveLiveReader().interpretBoxes(img); } } class Box{ int x,y,w,h; boolean ja_required; final static int BOX_THRESHOLD=8; //How many pixels outside the specified region the score can be. Box(int x,int y,int w, int h) { this.x=x; this.y=y; this.w=w; this.h=h; } boolean insideBox(int x,int y) { return this.x-BOX_THRESHOLD<=x&&this.x+this.w+BOX_THRESHOLD>=x&&this.y-BOX_THRESHOLD<=y&&this.y+this.h+BOX_THRESHOLD>=y; } } class LoveLiveReader extends Reader{ LoveLiveReader(){ readRegions.add(new Box(10,10,24,24)); //score[0] readRegions.add(new Box(10,40,24,24)); //rank[1] readRegions.add(new Box(10,70,24,24)); //notes[2] readRegions.add(new Box(10,70,24,24)); //notes[3] readRegions.add(new Box(10,70,24,24)); //notes[4] readRegions.add(new Box(10,70,24,24)); //notes[5] readRegions.add(new Box(10,70,24,24)); //notes[6] readRegions.add(new Box(10,70,24,24)); //notes[7] readRegions.add(new Box(10,70,24,24)); //notes[8] readRegions.add(new Box(10,70,24,24)); //difficulty[9] readRegions.add(new Box(10,70,24,24)); //title[10] readRegions.add(new Box(10,70,24,24)); //pct[11] readRegions.add(new Box(10,70,24,24)); //maxcombo[12] readRegions.add(new Box(10,70,24,24)); //other...[13] } void interpretBoxes(Path img){ String dataString = readAllBoxes(img); String[] data = dataString.split(Pattern.quote("\n")); String[] ja_data = data[0].split(Pattern.quote(")")); String[] en_data = data[2].split(Pattern.quote(")")); trimAllData(ja_data); trimAllData(en_data); System.out.println(Arrays.toString(ja_data)); System.out.println(Arrays.toString(en_data)); for (int i=0;i readRegions = new ArrayList<>(); String readAllBoxes(Path img) { try { Process p = Runtime.getRuntime().exec(new String[]{"python3","runocr.py","ja",img.toAbsolutePath().toString()}); while (p.isAlive()); InputStreamReader result = new InputStreamReader(p.getInputStream()); StringBuilder sb = new StringBuilder(); while (result.ready()) { sb.append((char)result.read()); } result.close(); sb.append("\n"); p = Runtime.getRuntime().exec(new String[]{"python3","runocr.py","en",img.toAbsolutePath().toString()}); while (p.isAlive()); result = new InputStreamReader(p.getInputStream()); while (result.ready()) { sb.append((char)result.read()); } return sb.toString(); } catch (IOException e) { e.printStackTrace(); } return ""; } void trimAllData(String[] data) { StringBuilder sb = new StringBuilder(); for (int i=0;i