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" : < excessive | normal > , "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 . size ( ) ; i + + ) {
}
//System.out.println(data[0]);
//System.out.println(data[2]);
}
}
abstract class Reader {
int score ;
int rank ;
int [ ] notes = new int [ 7 ] ;
int difficulty ;
String title ;
int pct ;
int maxcombo ;
String other ;
List < Box > 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 < data . length ; i + + ) {
sb . delete ( 0 , sb . length ( ) ) ;
for ( int j = 0 ; j < data [ i ] . length ( ) ; j + + ) {
if ( data [ i ] . charAt ( j ) ! = '[' & & data [ i ] . charAt ( j ) ! = '(' & & data [ i ] . charAt ( j ) ! = ')' & & data [ i ] . charAt ( j ) ! = ']' ) {
sb . append ( data [ i ] . charAt ( j ) ) ;
}
}
data [ i ] = sb . toString ( ) ;
}
}
}