package readers ;
import java.awt.Color ;
import java.awt.Graphics2D ;
import java.awt.image.BufferedImage ;
import java.io.IOException ;
import java.nio.file.Path ;
import java.nio.file.Paths ;
import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.List ;
import java.util.regex.Pattern ;
import javax.imageio.ImageIO ;
public class LoveLiveReader extends Reader {
final static int REGION_PADDING = 32 ;
List < Box > extraRegions = new ArrayList < > ( ) ;
static int lastJump = 0 ;
public LoveLiveReader ( ) {
readRegions . add ( new Box ( 713 , 401 , 232 , 50 ) ) ; //score[0]
readRegions . add ( new Box ( 613 , 290 , 65 , 36 ) ) ; //rank[1]
extraRegions . add ( new Box ( 65 , 604 , 250 , 53 ) ) ; //perfect outline[0]
extraRegions . add ( new Box ( 65 , 680 , 250 , 53 ) ) ; //great outline[1]
extraRegions . add ( new Box ( 65 , 760 , 250 , 53 ) ) ; //good outline[2]
extraRegions . add ( new Box ( 65 , 840 , 250 , 53 ) ) ; //bad outline[3]
extraRegions . add ( new Box ( 65 , 920 , 250 , 53 ) ) ; //miss outline[4]
readRegions . add ( new Box ( 509 , 604 , 190 , 54 ) ) ; //notes[2]
readRegions . add ( new Box ( 509 , 680 , 190 , 54 ) ) ; //notes[3]
readRegions . add ( new Box ( 509 , 760 , 190 , 54 ) ) ; //notes[4]
readRegions . add ( new Box ( 509 , 840 , 190 , 54 ) ) ; //notes[5]
readRegions . add ( new Box ( 509 , 920 , 190 , 54 ) ) ; //notes[6]
readRegions . add ( new Box ( 26 , 374 , 265 , 36 ) ) ; //difficulty[7]
readRegions . add ( new Box ( 277 , 165 , 572 , 40 ) ) ; //title[8]
readRegions . add ( new Box ( 716 , 502 , 226 , 45 ) ) ; //pct[9]
readRegions . add ( new Box ( 782 , 452 , 158 , 50 ) ) ; //maxcombo[10]
}
void ColorFilter ( int [ ] arr , int region , int width ) {
switch ( region ) {
case 0 : {
final ColorRange TARGETCOLOR = new ColorRange ( 240 , 255 , 130 , 150 , 0 , 10 ) ;
final ColorRange SEEKINGCOLOR = new ColorRange ( 140 , 255 , 110 , 255 , 0 , 200 ) ;
final Color FINALCOLOR = Color . MAGENTA ;
for ( int i = 0 ; i < arr . length ; i + + ) {
Color col = new Color ( arr [ i ] , true ) ;
if ( TARGETCOLOR . colorInRange ( col ) ) {
seek ( arr , i , SEEKINGCOLOR , FINALCOLOR , width ) ;
}
}
for ( int i = 0 ; i < arr . length ; i + + ) {
Color col = new Color ( arr [ i ] , true ) ;
if ( ! col . equals ( Color . MAGENTA ) ) {
arr [ i ] = TRANSPARENT ;
}
}
} break ;
case 2 :
case 3 :
case 4 :
case 5 :
case 6 :
case 8 : {
final ColorRange TARGETCOLOR = new ColorRange ( 255 , 255 , 255 , 255 , 255 , 255 ) ;
final ColorRange SEEKINGCOLOR = new ColorRange ( 240 , 255 , 240 , 255 , 240 , 255 ) ;
final Color FINALCOLOR = Color . MAGENTA ;
for ( int i = 0 ; i < arr . length ; i + + ) {
Color col = new Color ( arr [ i ] , true ) ;
if ( TARGETCOLOR . colorInRange ( col ) ) {
seek ( arr , i , SEEKINGCOLOR , FINALCOLOR , width ) ;
}
}
for ( int i = 0 ; i < arr . length ; i + + ) {
Color col = new Color ( arr [ i ] , true ) ;
if ( ! col . equals ( Color . MAGENTA ) ) {
arr [ i ] = TRANSPARENT ;
}
}
} break ;
case 9 : {
final ColorRange TARGETCOLOR = new ColorRange ( 0 , 10 , 155 , 190 , 95 , 145 ) ;
final ColorRange SEEKINGCOLOR = new ColorRange ( 0 , 200 , 155 , 240 , 95 , 240 ) ;
final Color FINALCOLOR = Color . RED ;
for ( int i = 0 ; i < arr . length ; i + + ) {
Color col = new Color ( arr [ i ] , true ) ;
if ( TARGETCOLOR . colorInRange ( col ) ) {
seek ( arr , i , SEEKINGCOLOR , FINALCOLOR , width ) ;
}
}
final ColorRange SEEKINGCOLOR2 = new ColorRange ( 255 , 255 , 0 , 0 , 0 , 0 ) ;
final Color FINALCOLOR2 = new Color ( TRANSPARENT , true ) ;
for ( int x = 0 ; x < width ; x + + ) {
//30 pixels from top.
if ( arr [ 30 * width + x ] = = Color . RED . getRGB ( ) ) {
System . out . println ( "Start Jump: " + x ) ;
x = seek ( arr , 30 * width + x , SEEKINGCOLOR2 , FINALCOLOR2 , width , x ) ;
System . out . println ( "End Jump: " + x ) ;
}
}
for ( int i = 0 ; i < arr . length ; i + + ) {
Color col = new Color ( arr [ i ] , true ) ;
if ( ! col . equals ( Color . RED ) ) {
arr [ i ] = TRANSPARENT ;
} else {
arr [ i ] = Color . MAGENTA . getRGB ( ) ;
}
}
} break ;
case 10 : {
final ColorRange TARGETCOLOR = new ColorRange ( 240 , 255 , 30 , 50 , 0 , 5 ) ;
final ColorRange SEEKINGCOLOR = new ColorRange ( 180 , 255 , 10 , 120 , 0 , 120 ) ;
final Color FINALCOLOR = Color . MAGENTA ;
for ( int i = 0 ; i < arr . length ; i + + ) {
Color col = new Color ( arr [ i ] , true ) ;
if ( TARGETCOLOR . colorInRange ( col ) ) {
seek ( arr , i , SEEKINGCOLOR , FINALCOLOR , width ) ;
}
}
for ( int i = 0 ; i < arr . length ; i + + ) {
Color col = new Color ( arr [ i ] , true ) ;
if ( ! col . equals ( Color . MAGENTA ) ) {
arr [ i ] = TRANSPARENT ;
}
}
} break ;
case 402 : {
final ColorRange TARGETCOLOR = new ColorRange ( 80 , 120 , 100 , 130 , 100 , 140 ) ;
final ColorRange SEEKINGCOLOR = new ColorRange ( 220 , 255 , 220 , 255 , 220 , 255 ) ;
final Color FINALCOLOR = Color . MAGENTA ;
for ( int i = 0 ; i < arr . length ; i + + ) {
Color col = new Color ( arr [ i ] , true ) ;
if ( TARGETCOLOR . colorInRange ( col ) ) {
seek ( arr , i - width , SEEKINGCOLOR , FINALCOLOR , width ) ;
}
}
for ( int i = 0 ; i < arr . length ; i + + ) {
Color col = new Color ( arr [ i ] , true ) ;
if ( ! col . equals ( Color . MAGENTA ) ) {
arr [ i ] = TRANSPARENT ;
}
}
} break ;
case 400 :
case 401 :
case 403 :
case 404 : {
final ColorRange TARGETCOLOR = new ColorRange ( 255 , 255 , 255 , 255 , 255 , 255 ) ;
final ColorRange SEEKINGCOLOR = new ColorRange ( 220 , 255 , 220 , 255 , 220 , 255 ) ;
final Color FINALCOLOR = Color . RED ;
for ( int i = 0 ; i < arr . length ; i + + ) {
Color col = new Color ( arr [ i ] , true ) ;
if ( TARGETCOLOR . colorInRange ( col ) ) {
seek ( arr , i , SEEKINGCOLOR , FINALCOLOR , width ) ;
}
}
final ColorRange SEEKINGCOLOR2 = new ColorRange ( 255 , 255 , 0 , 0 , 0 , 0 ) ;
final Color FINALCOLOR2 = new Color ( TRANSPARENT , true ) ;
for ( int x = 0 ; x < width ; x + + ) {
//30 pixels from top.
if ( arr [ 30 * width + x ] = = Color . RED . getRGB ( ) ) {
System . out . println ( "Start Jump: " + x ) ;
x = seek ( arr , 30 * width + x , SEEKINGCOLOR2 , FINALCOLOR2 , width , x ) ;
System . out . println ( "End Jump: " + x ) ;
}
}
for ( int i = 0 ; i < arr . length ; i + + ) {
Color col = new Color ( arr [ i ] , true ) ;
if ( ! col . equals ( Color . RED ) ) {
arr [ i ] = TRANSPARENT ;
} else {
arr [ i ] = Color . MAGENTA . getRGB ( ) ;
}
}
} break ;
}
}
public 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 ) ) ; * /
int regionHeights = 0 ;
int maxWidth = 0 ;
for ( int i = 0 ; i < readRegions . size ( ) ; i + + ) {
regionHeights + = readRegions . get ( i ) . h + REGION_PADDING ;
if ( readRegions . get ( i ) . w > maxWidth ) {
maxWidth = readRegions . get ( i ) . w ;
}
}
try {
BufferedImage originalImg = ImageIO . read ( img . toFile ( ) ) ;
BufferedImage cutImg = new BufferedImage ( maxWidth , regionHeights , BufferedImage . TYPE_INT_ARGB ) ;
Graphics2D g = cutImg . createGraphics ( ) ;
int currentHeight = 0 ;
for ( int i = 0 ; i < readRegions . size ( ) ; i + + ) {
int [ ] arr = originalImg . getRGB ( readRegions . get ( i ) . x , readRegions . get ( i ) . y , readRegions . get ( i ) . w , readRegions . get ( i ) . h , null , 0 , readRegions . get ( i ) . w ) ;
//System.out.println(Arrays.toString(arr));
ColorFilter ( arr , i , readRegions . get ( i ) . w ) ;
//g.drawImage(originalImg, 0,currentHeight,readRegions.get(i).w,readRegions.get(i).h+currentHeight,readRegions.get(i).x, readRegions.get(i).y, readRegions.get(i).x+readRegions.get(i).w, readRegions.get(i).y+readRegions.get(i).h, null);
int leftMost = readRegions . get ( i ) . w ;
for ( int j = 0 ; j < arr . length ; j + + ) {
if ( arr [ j ] = = Color . MAGENTA . getRGB ( ) & & j % readRegions . get ( i ) . w < leftMost ) {
leftMost = j % readRegions . get ( i ) . w ;
}
}
if ( i > = 2 & & i < = 6 ) {
int [ ] arr2 = originalImg . getRGB ( extraRegions . get ( i - 2 ) . x , extraRegions . get ( i - 2 ) . y , extraRegions . get ( i - 2 ) . w , extraRegions . get ( i - 2 ) . h , null , 0 , extraRegions . get ( i - 2 ) . w ) ;
int rightMost = 0 ;
ColorFilter ( arr2 , 400 + i - 2 , extraRegions . get ( i - 2 ) . w ) ;
for ( int j = 0 ; j < arr2 . length ; j + + ) {
if ( arr2 [ j ] = = Color . MAGENTA . getRGB ( ) & & j % extraRegions . get ( i - 2 ) . w > rightMost ) {
rightMost = j % extraRegions . get ( i - 2 ) . w ;
}
}
//cutImg.setRGB(rightMost-leftMost,currentHeight,readRegions.get(i).w,readRegions.get(i).h,arr,0,readRegions.get(i).w);
cutImg . setRGB ( 0 , currentHeight , extraRegions . get ( i - 2 ) . w , extraRegions . get ( i - 2 ) . h , arr2 , 0 , extraRegions . get ( i - 2 ) . w ) ;
final int PADDING = 8 ;
for ( int x = leftMost ; x < readRegions . get ( i ) . w ; x + + ) {
for ( int y = 0 ; y < readRegions . get ( i ) . h ; y + + ) {
cutImg . setRGB ( x + rightMost - leftMost + PADDING , y + currentHeight , arr [ y * readRegions . get ( i ) . w + x ] ) ;
}
}
} else {
cutImg . setRGB ( 0 , currentHeight , readRegions . get ( i ) . w , readRegions . get ( i ) . h , arr , 0 , readRegions . get ( i ) . w ) ;
}
//System.out.println(i+": "+currentHeight+"-"+(currentHeight+readRegions.get(i).h+REGION_PADDING));
currentHeight + = readRegions . get ( i ) . h + REGION_PADDING ;
}
Path output = Paths . get ( "result.png" ) ;
ImageIO . write ( cutImg , "png" , output . toFile ( ) ) ;
String dataString = readAllBoxes ( output ) ;
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 ) ) ;
interpretOutput ( ja_data , en_data ) ;
g . dispose ( ) ;
} catch ( IOException e ) {
e . printStackTrace ( ) ;
}
//System.out.println(data[0]);
//System.out.println(data[2]);
}
@Override
String interpretOutput ( String [ ] jp_data , String [ ] en_data ) {
//[6, 0, 218, 0, 218, 48, 6, 48, 32 5 4 1 5, 0.9670235803680689]
//For each data point we want to first see if it's within the correct rectangular bounds and from there parse it as such.
double [ ] accuracy = new double [ readRegions . size ( ) ] ;
String [ ] finalData = new String [ readRegions . size ( ) ] ;
for ( int i = 0 ; i < finalData . length ; i + + ) {
finalData [ i ] = "" ;
}
for ( int i = 0 ; i < en_data . length ; i + = 10 ) {
int spacing = 0 ;
for ( int j = 0 ; j < readRegions . size ( ) ; j + + ) {
int midpoint = ( Integer . parseInt ( en_data [ i + 1 ] ) + Integer . parseInt ( en_data [ i + 5 ] ) ) / 2 ;
if ( midpoint > = spacing & & midpoint < = spacing + readRegions . get ( j ) . h + REGION_PADDING
/*&&accuracy[j]<Double.parseDouble(en_data[i+9]) Only for jp string testing.*/ ) {
System . out . print ( "[" ) ;
for ( int k = 0 ; k < 10 ; k + + ) {
if ( k ! = 0 ) {
System . out . print ( "," ) ;
}
System . out . print ( en_data [ i + k ] ) ;
}
System . out . print ( "]" ) ;
System . out . println ( " belongs to region " + j + "." ) ;
finalData [ j ] = finalData [ j ] + "\n" + en_data [ i + 8 ] ;
accuracy [ j ] = Double . parseDouble ( en_data [ i + 9 ] ) ;
break ;
}
spacing + = readRegions . get ( j ) . h + REGION_PADDING ;
}
}
for ( int i = 0 ; i < jp_data . length ; i + = 10 ) {
int spacing = 0 ;
for ( int j = 0 ; j < readRegions . size ( ) ; j + + ) {
int midpoint = ( Integer . parseInt ( jp_data [ i + 1 ] ) + Integer . parseInt ( jp_data [ i + 5 ] ) ) / 2 ;
if ( midpoint > = spacing & & midpoint < = spacing + readRegions . get ( j ) . h + REGION_PADDING
& & accuracy [ j ] < Double . parseDouble ( jp_data [ i + 9 ] ) ) {
System . out . print ( "JP[" ) ;
for ( int k = 0 ; k < 10 ; k + + ) {
if ( k ! = 0 ) {
System . out . print ( "," ) ;
}
System . out . print ( jp_data [ i + k ] ) ;
}
System . out . print ( "]" ) ;
System . out . println ( " belongs to region " + j + "." ) ;
if ( accuracy [ j ] ! = 0 ) {
finalData [ j ] = "" ;
}
finalData [ j ] = finalData [ j ] + "\n" + jp_data [ i + 8 ] ;
accuracy [ j ] = 0 ;
break ;
}
spacing + = readRegions . get ( j ) . h + REGION_PADDING ;
}
}
System . out . println ( Arrays . toString ( finalData ) ) ;
interpretResults ( finalData ) ;
return null ;
}
private void interpretResults ( String [ ] finalData ) {
for ( int i = 0 ; i < finalData . length ; i + + ) {
String [ ] splitter = finalData [ i ] . split ( Pattern . quote ( "\n" ) ) ;
switch ( i ) {
case 0 : {
score = convertToInt ( splitter ) ;
} break ;
case 1 : { } break ; //We will handle the grade with another system.
case 2 : {
notes [ 0 ] = convertToInt ( "PERFECT" , splitter ) ;
} break ;
case 3 : {
notes [ 1 ] = convertToInt ( "GREAT" , splitter ) ;
} break ;
case 4 : {
notes [ 2 ] = convertToInt ( "GOOD" , splitter ) ;
} break ;
case 5 : {
notes [ 3 ] = convertToInt ( "BAD" , splitter ) ;
} break ;
case 6 : {
notes [ 4 ] = convertToInt ( "MISS" , splitter ) ;
} break ;
case 7 : {
difficulty = getDifficulty ( convertToString ( splitter ) . toLowerCase ( ) ) ;
} break ;
case 8 : {
title = convertToString ( splitter ) ;
} break ;
case 9 : {
pct = convertToPct ( splitter ) ;
} break ;
case 10 : {
maxcombo = convertToInt ( splitter ) ;
} break ;
}
}
System . out . println ( this ) ;
}
double convertToPct ( String [ ] str ) {
int front = convertToInt ( new String [ ] { str [ 1 ] } ) ;
int decimal = convertToInt ( new String [ ] { str [ 2 ] } ) ;
double numb = 0 ;
int placeValue = 0 ;
int decimalPlaces = 0 ;
while ( decimal ! = 0 ) {
numb + = ( decimal % 10 ) * ( Math . pow ( 10 , placeValue + + ) ) ;
decimal / = 10 ;
decimalPlaces + + ;
}
while ( front ! = 0 ) {
numb + = ( front % 10 ) * ( Math . pow ( 10 , placeValue + + ) ) ;
front / = 10 ;
}
for ( int i = 0 ; i < decimalPlaces ; i + + ) {
numb / = 10 ;
}
return numb ;
}
int getDifficulty ( String str ) {
final String [ ] diffs = { "easy" , "normal" , "hard" , "master" , "challenge" } ;
for ( int i = 0 ; i < diffs . length ; i + + ) {
String diff = diffs [ i ] . toLowerCase ( ) ;
if ( str . contains ( diff ) ) {
return i ;
}
}
return - 1 ;
}
}