700 lines
26 KiB
Java
700 lines
26 KiB
Java
package com.pokemongo;
|
||
|
||
import java.awt.AWTException;
|
||
import java.awt.GraphicsDevice;
|
||
import java.awt.GraphicsEnvironment;
|
||
import java.awt.Point;
|
||
import java.awt.Rectangle;
|
||
import java.awt.Robot;
|
||
import java.awt.event.InputEvent;
|
||
import java.awt.image.BufferedImage;
|
||
import java.io.IOException;
|
||
import java.util.ArrayList;
|
||
import java.util.List;
|
||
|
||
import javax.imageio.ImageIO;
|
||
|
||
/**
|
||
* Automatizační nástroj pro Pokémon GO.
|
||
* Najde běžící aplikaci, označí všechny Pokémony a stiskne tlačítko Transfer.
|
||
*/
|
||
public class PokemonGoAutomation {
|
||
|
||
private Robot robot;
|
||
private Rectangle windowBounds;
|
||
private BufferedImage t1Template; // TRANSFER button template
|
||
private BufferedImage t2Template; // Confirmation button template
|
||
private BufferedImage t3Template;
|
||
private BufferedImage pok1Template; // Pokemon detection template
|
||
private BufferedImage includeTemplate; // Include button template
|
||
private static final int DELAY_BETWEEN_CLICKS = 100; // ms
|
||
private static final int DELAY_AFTER_ACTION = 100; // ms
|
||
private int transferredPokemonCount = 0; // Počet transfernutých pokémonů
|
||
|
||
public PokemonGoAutomation() throws AWTException {
|
||
this.robot = new Robot();
|
||
this.robot.setAutoDelay(50);
|
||
this.robot.setAutoWaitForIdle(true);
|
||
loadButtonTemplates();
|
||
}
|
||
|
||
/**
|
||
* Vrátí počet dosud transfernutých pokémonů
|
||
*/
|
||
public int getTransferredCount() {
|
||
return transferredPokemonCount;
|
||
}
|
||
|
||
/**
|
||
* Resetuje počítadlo transfernutých pokémonů
|
||
*/
|
||
public void resetTransferredCount() {
|
||
transferredPokemonCount = 0;
|
||
}
|
||
|
||
/**
|
||
* Pořídí screenshot oblasti okna
|
||
*/
|
||
private BufferedImage captureScreen(Rectangle area) {
|
||
return robot.createScreenCapture(area);
|
||
}
|
||
|
||
/**
|
||
* Načte templaty pro tlačítka TRANSFER (t1.png) a confirmation (t2.png)
|
||
*/
|
||
private void loadButtonTemplates() {
|
||
try {
|
||
String t1Paths = "/t1.png";
|
||
|
||
t1Template = ImageIO.read(getClass().getResourceAsStream(t1Paths));
|
||
System.out.println("✅ Template TRANSFER načten z: " + t1Paths);
|
||
|
||
String t2Paths = "/t2.png";
|
||
|
||
t2Template = ImageIO.read(getClass().getResourceAsStream(t2Paths));
|
||
System.out.println("✅ Template Potvrzení načten z: " + t2Paths);
|
||
|
||
String t3Paths = "/t3.png";
|
||
|
||
t3Template = ImageIO.read(getClass().getResourceAsStream(t3Paths));
|
||
System.out.println("✅ Template Potvrzení načten z: " + t3Paths);
|
||
|
||
String pok1Paths = "/pok1.png";
|
||
|
||
pok1Template = ImageIO.read(getClass().getResourceAsStream(pok1Paths));
|
||
System.out.println("✅ Template Pokémon načten z: " + pok1Paths);
|
||
|
||
String includePaths = "/include.png";
|
||
|
||
includeTemplate = ImageIO.read(getClass().getResourceAsStream(includePaths));
|
||
System.out.println("✅ Template INCLUDE načten z: " + includePaths);
|
||
|
||
if (t1Template == null) {
|
||
System.out.println("⚠️ Template t1.png nebyl nalezen");
|
||
}
|
||
if (t2Template == null) {
|
||
System.out.println("⚠️ Template t2.png nebyl nalezen");
|
||
}
|
||
if (pok1Template == null) {
|
||
System.out.println("⚠️ Template pok1.png nebyl nalezen");
|
||
}
|
||
if (includeTemplate == null) {
|
||
System.out.println("⚠️ Template include.png nebyl nalezen");
|
||
}
|
||
} catch (IOException e) {
|
||
System.err.println("⚠️ Chyba při načítání templates: " + e.getMessage());
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Porovnává template s oblastí v obrázku - jednoduché pixelové porovnání s
|
||
* optimalizací
|
||
*/
|
||
private double templateMatch(BufferedImage screenshot, int startX, int startY, BufferedImage template,
|
||
int tolerance) {
|
||
if (template == null)
|
||
return 0.0;
|
||
|
||
int tWidth = template.getWidth();
|
||
int tHeight = template.getHeight();
|
||
|
||
// Kontrola hranic
|
||
if (startX + tWidth > screenshot.getWidth() || startY + tHeight > screenshot.getHeight()) {
|
||
return 0.0;
|
||
}
|
||
if (startX < 0 || startY < 0) {
|
||
return 0.0;
|
||
}
|
||
|
||
int matchingPixels = 0;
|
||
int totalPixels = tWidth * tHeight;
|
||
int requiredMatch = (int) (totalPixels * 0.75); // 75% shody
|
||
|
||
for (int y = 0; y < tHeight; y++) {
|
||
for (int x = 0; x < tWidth; x++) {
|
||
int templateRGB = template.getRGB(x, y);
|
||
int screenRGB = screenshot.getRGB(startX + x, startY + y);
|
||
|
||
// Rozdělit RGB hodnoty
|
||
int tR = (templateRGB >> 16) & 0xFF;
|
||
int tG = (templateRGB >> 8) & 0xFF;
|
||
int tB = templateRGB & 0xFF;
|
||
|
||
int sR = (screenRGB >> 16) & 0xFF;
|
||
int sG = (screenRGB >> 8) & 0xFF;
|
||
int sB = screenRGB & 0xFF;
|
||
|
||
// Porovnat barvy - zvýšená tolerance pro lepší detekci
|
||
int rDiff = Math.abs(tR - sR);
|
||
int gDiff = Math.abs(tG - sG);
|
||
int bDiff = Math.abs(tB - sB);
|
||
|
||
if (rDiff < tolerance && gDiff < tolerance && bDiff < tolerance) {
|
||
matchingPixels++;
|
||
|
||
// Early exit - pokud jsme nedosáhli minima, skončit
|
||
if (matchingPixels < requiredMatch / 2 && (y * tWidth + x) > (totalPixels / 2)) {
|
||
return 0.0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// Vrátit procentuální shodu (0.0-1.0)
|
||
return (double) matchingPixels / totalPixels;
|
||
}
|
||
|
||
/**
|
||
* Detekuje pozice Pokémonů pomocí template matchingu s pok1.png
|
||
* Hledá v oblasti od vrchu obrazovky do 75% výšky
|
||
* Může najít až 9 Pokémonů
|
||
*/
|
||
private List<Point> detectPokemonsByTemplateMatching2() {
|
||
List<Point> positions = new ArrayList<>();
|
||
|
||
System.out.println("\n=== Detekce Pokémonů pomocí template matchingu (pok1.png) ===");
|
||
|
||
if (pok1Template == null) {
|
||
System.out.println("⚠️ Template pok1.png není dostupný");
|
||
return positions;
|
||
}
|
||
|
||
BufferedImage screenshot = captureScreen(windowBounds);
|
||
|
||
int tWidth = pok1Template.getWidth();
|
||
int tHeight = pok1Template.getHeight();
|
||
System.out.println("Template velikost: " + tWidth + "x" + tHeight);
|
||
|
||
// Grid parametry - 3x3 (9 Pokémonů) - pevné pozice podle layoutu aplikace
|
||
int gridStartY = (int) (windowBounds.height * 0.15);
|
||
int gridEndY = (int) (windowBounds.height * 0.75);
|
||
int gridHeight = gridEndY - gridStartY;
|
||
|
||
int gridMargin = (int) (windowBounds.width * 0.05);
|
||
int gridStartX = gridMargin;
|
||
int gridWidth = windowBounds.width - (2 * gridMargin);
|
||
|
||
int columns = 3;
|
||
int rows = 3; // 3x3 grid = 9 Pokémonů
|
||
|
||
int columnWidth = gridWidth / columns;
|
||
int rowHeight = gridHeight / rows;
|
||
|
||
System.out.println("Hledám Pokémony v gridu 3x3 (9 pozic)");
|
||
|
||
// Pro každou buňku v gridu hledat template
|
||
for (int row = 0; row < rows; row++) {
|
||
for (int col = 0; col < columns; col++) {
|
||
int cellX = gridStartX + (col * columnWidth);
|
||
int cellY = gridStartY + (row * rowHeight);
|
||
|
||
double bestScore = 0.0;
|
||
int bestX = cellX + columnWidth / 2;
|
||
int bestY = cellY + rowHeight / 2;
|
||
|
||
// Skenovat buňku s jemností
|
||
for (int sy = cellY; sy < cellY + rowHeight - tHeight; sy += 3) {
|
||
for (int sx = cellX; sx < cellX + columnWidth - tWidth; sx += 3) {
|
||
double score = templateMatch(screenshot, sx, sy, pok1Template, 115); // Zvýšená tolerance
|
||
if (score > bestScore) {
|
||
bestScore = score;
|
||
bestX = sx + tWidth / 2;
|
||
bestY = sy + tHeight / 2;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Pokud jsme našli match (skóre > 75%), považovat za Pokémona
|
||
if (bestScore > 0.98) {
|
||
int x = windowBounds.x + bestX;
|
||
int y = windowBounds.y + bestY;
|
||
positions.add(new Point(x, y));
|
||
System.out.println(" Detekován Pokémon na [" + row + "," + col + "] -> (" + x + ", " + y
|
||
+ ") skóre=" + String.format("%.1f", bestScore * 100) + "%");
|
||
}
|
||
}
|
||
}
|
||
|
||
System.out.println("Celkem detekováno: " + positions.size() + " Pokémonů");
|
||
System.out.println("=================================\n");
|
||
|
||
return positions;
|
||
}
|
||
|
||
/**
|
||
* Najde a vrátí pozici transferu tlačítka bez kliknutí
|
||
*/
|
||
private Point findTransferButtonPosition() {
|
||
System.out.println("Hledám tlačítko TRANSFER pomocí template matchingu (t1.png)...");
|
||
|
||
BufferedImage screenshot = captureScreen(windowBounds);
|
||
|
||
int tWidth = t1Template.getWidth();
|
||
int tHeight = t1Template.getHeight();
|
||
|
||
// Template je celý řádek - zkusíme matchovat od 75% do 95% (kde by měl být
|
||
// TRANSFER řádek)
|
||
int searchStartY = (int) (windowBounds.height * 0.75);
|
||
int searchEndY = (int) (windowBounds.height * 0.95);
|
||
|
||
double bestScore = 0.0;
|
||
int bestX = 0;
|
||
int bestY = 0;
|
||
|
||
// Skenovat Y-ové pozice s větším krokem - 15px místo 5px pro zrychlení
|
||
for (int y = searchStartY; y <= searchEndY - tHeight; y += 15) {
|
||
// Skenovat také X pozice pro nalezení středu shody
|
||
for (int x = 0; x <= windowBounds.width - tWidth; x += 30) {
|
||
double score = templateMatch(screenshot, x, y, t1Template, 90);
|
||
|
||
if (score > bestScore) {
|
||
bestScore = score;
|
||
bestX = x;
|
||
bestY = y;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (bestScore > 0.92) {
|
||
Point bestMatch = new Point(
|
||
windowBounds.x + bestX + (tWidth / 2),
|
||
windowBounds.y + bestY + (tHeight / 2));
|
||
System.out.println("✅ Nalezeno TRANSFER tlačítko (template match) na: " + bestMatch + " (shoda: "
|
||
+ String.format("%.1f", bestScore * 100) + "%)");
|
||
return bestMatch;
|
||
}
|
||
|
||
System.out.println("Template nenalezen");
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* Najde a vrátí pozici potvrzovacího tlačítka bez kliknutí
|
||
*/
|
||
private Point findConfirmTransferButtonPosition(BufferedImage template, int tolerance) {
|
||
System.out.println("Hledám potvrzovací TRANSFER tlačítko pomocí template matchingu...");
|
||
|
||
BufferedImage screenshot = captureScreen(windowBounds);
|
||
|
||
int tWidth = template.getWidth();
|
||
int tHeight = template.getHeight();
|
||
|
||
// Dialog je obvykle v horní polovině po TRANSFER kliknutí
|
||
int searchStartY = (int) (windowBounds.height * 0.40);
|
||
int searchEndY = (int) (windowBounds.height * 0.75);
|
||
|
||
double bestScore = 0.0;
|
||
int bestX = 0;
|
||
int bestY = 0;
|
||
|
||
// Skenovat Y-ové pozice s větším krokem - 15px místo 5px pro zrychlení
|
||
for (int y = searchStartY; y <= searchEndY - tHeight; y += 15) {
|
||
// Skenovat také X pozice pro nalezení středu shody
|
||
for (int x = 0; x <= windowBounds.width - tWidth; x += 30) {
|
||
double score = templateMatch(screenshot, x, y, template, tolerance);
|
||
|
||
if (score > bestScore) {
|
||
bestScore = score;
|
||
bestX = x;
|
||
bestY = y;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (bestScore > 0.85) {
|
||
Point bestMatch = new Point(
|
||
windowBounds.x + bestX + (tWidth / 2),
|
||
windowBounds.y + bestY + (tHeight / 2));
|
||
System.out.println("✅ Nalezeno potvrzovací tlačítko (template match) na: " + bestMatch + " (shoda: "
|
||
+ String.format("%.1f", bestScore * 100) + "%)");
|
||
return bestMatch;
|
||
}
|
||
|
||
System.out.println("Template nenalezen");
|
||
return null;
|
||
}
|
||
|
||
private Point findIncludeButtonPosition(int tolerance) {
|
||
System.out.println("Hledám tlačítko INCLUDE pomocí template matchingu (include.png)...");
|
||
|
||
BufferedImage screenshot = captureScreen(windowBounds);
|
||
|
||
int tWidth = includeTemplate.getWidth();
|
||
int tHeight = includeTemplate.getHeight();
|
||
|
||
// Dialog je obvykle v horní polovině po TRANSFER kliknutí
|
||
int searchStartY = (int) (windowBounds.height * 0.40);
|
||
int searchEndY = (int) (windowBounds.height * 0.75);
|
||
|
||
double bestScore = 0.0;
|
||
int bestX = 0;
|
||
int bestY = 0;
|
||
|
||
// Skenovat Y-ové pozice s větším krokem - 15px místo 5px pro zrychlení
|
||
for (int y = searchStartY; y <= searchEndY - tHeight; y += 15) {
|
||
// Skenovat také X pozice pro nalezení středu shody
|
||
for (int x = 0; x <= windowBounds.width - tWidth; x += 30) {
|
||
double score = templateMatch(screenshot, x, y, includeTemplate, tolerance);
|
||
|
||
if (score > bestScore) {
|
||
bestScore = score;
|
||
bestX = x;
|
||
bestY = y;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (bestScore > 0.80) {
|
||
Point bestMatch = new Point(
|
||
windowBounds.x + bestX + (tWidth / 2),
|
||
windowBounds.y + bestY + (tHeight / 2));
|
||
System.out.println("✅ Nalezeno tlačítko INCLUDE (template match) na: " + bestMatch + " (shoda: "
|
||
+ String.format("%.1f", bestScore * 100) + "%)");
|
||
return bestMatch;
|
||
}
|
||
|
||
System.out.println("Template nenalezen");
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* Najde okno s názvem obsahujícím "Pokémon" nebo "Pokemon"
|
||
*/
|
||
public boolean findPokemonGoWindow() {
|
||
try {
|
||
// Pro Linux - hledání okna pomocí xdotool
|
||
// Nejdříve najít ID okna, pak získat jeho geometrii
|
||
Process searchProcess = Runtime.getRuntime().exec(
|
||
new String[] { "bash", "-c", "xdotool search --name \"Lenovo|L78032\" | head -1" });
|
||
|
||
java.io.BufferedReader searchReader = new java.io.BufferedReader(
|
||
new java.io.InputStreamReader(searchProcess.getInputStream()));
|
||
|
||
String windowId = searchReader.readLine();
|
||
searchProcess.waitFor();
|
||
|
||
if (windowId != null && !windowId.trim().isEmpty()) {
|
||
System.out.println("Nalezeno okno s ID: " + windowId);
|
||
|
||
// Získat geometrii okna
|
||
Process geomProcess = Runtime.getRuntime().exec(
|
||
new String[] { "bash", "-c", "xdotool getwindowgeometry " + windowId.trim() });
|
||
|
||
java.io.BufferedReader geomReader = new java.io.BufferedReader(
|
||
new java.io.InputStreamReader(geomProcess.getInputStream()));
|
||
|
||
String line;
|
||
int x = 0, y = 0, width = 0, height = 0;
|
||
|
||
while ((line = geomReader.readLine()) != null) {
|
||
System.out.println("xdotool výstup: " + line);
|
||
if (line.contains("Position:")) {
|
||
String[] parts = line.split("Position: ")[1].split(",");
|
||
x = Integer.parseInt(parts[0].trim());
|
||
y = Integer.parseInt(parts[1].trim().split(" ")[0]);
|
||
} else if (line.contains("Geometry:")) {
|
||
String[] parts = line.split("Geometry: ")[1].split("x");
|
||
width = Integer.parseInt(parts[0].trim());
|
||
height = Integer.parseInt(parts[1].trim());
|
||
}
|
||
}
|
||
|
||
geomProcess.waitFor();
|
||
|
||
if (width > 0 && height > 0) {
|
||
windowBounds = new Rectangle(x, y, width, height);
|
||
System.out.println("Nalezeno okno: " + windowBounds);
|
||
return true;
|
||
}
|
||
}
|
||
|
||
// Fallback - použití celé obrazovky
|
||
System.out.println("Okno nenalezeno, použiji celou obrazovku");
|
||
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
|
||
windowBounds = gd.getDefaultConfiguration().getBounds();
|
||
return true;
|
||
|
||
} catch (Exception e) {
|
||
System.err.println("Chyba při hledání okna: " + e.getMessage());
|
||
e.printStackTrace();
|
||
// Použití celé obrazovky jako záložní varianta
|
||
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
|
||
windowBounds = gd.getDefaultConfiguration().getBounds();
|
||
return true;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Aktivuje okno aplikace
|
||
*/
|
||
public void activateWindow() {
|
||
try {
|
||
// Kliknutí na horní panel okna (title bar) pro aktivaci
|
||
// Title bar je obvykle 30-40px vysoký v horní části okna
|
||
int centerX = windowBounds.x + windowBounds.width / 2;
|
||
int titleBarY = windowBounds.y + 15; // 15px od vrcholu okna = horní panel
|
||
|
||
System.out.println("Aktivuji okno kliknutím na title bar: (" + centerX + ", " + titleBarY + ")");
|
||
|
||
robot.mouseMove(centerX, titleBarY);
|
||
robot.delay(200);
|
||
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
|
||
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
|
||
robot.delay(DELAY_AFTER_ACTION);
|
||
|
||
System.out.println("Okno aktivováno");
|
||
} catch (Exception e) {
|
||
System.err.println("Chyba při aktivaci okna: " + e.getMessage());
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Stiskne tlačítko Transfer na spodní části obrazovky
|
||
*/
|
||
public void clickTransferButton() {
|
||
// Použít detekci tlačítka
|
||
// Point buttonPos = findTransferButtonPosition();
|
||
Point buttonPos = getAbsolutePoint(307, 1100);
|
||
|
||
if (buttonPos == null) {
|
||
System.err.println("Tlačítko TRANSFER nebylo nalezeno!");
|
||
return;
|
||
}
|
||
|
||
robot.mouseMove(buttonPos.x, buttonPos.y);
|
||
robot.delay(DELAY_AFTER_ACTION);
|
||
|
||
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
|
||
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
|
||
|
||
System.out.println("Tlačítko TRANSFER stisknuto!");
|
||
robot.delay(DELAY_AFTER_ACTION);
|
||
}
|
||
|
||
/**
|
||
* Potvrdí transfer (pokud je potřeba potvrzovací dialog)
|
||
*/
|
||
public void clickConfirmTransferButton(BufferedImage template, int tolerance) {
|
||
System.out.println("Potvrzuji transfer - hledám confirmation button...");
|
||
|
||
robot.delay(100); // Počkat na zobrazení dialogu
|
||
|
||
// Najít zelené TRANSFER tlačítko v potvrzovacím dialogu
|
||
Point buttonPos = findConfirmTransferButtonPosition(template, tolerance);
|
||
if (buttonPos == null) {
|
||
System.out.println("Potvrzovací tlačítko nebylo nalezeno, přeskočím potvrzení.");
|
||
return;
|
||
}
|
||
|
||
robot.mouseMove(buttonPos.x, buttonPos.y);
|
||
robot.delay(DELAY_BETWEEN_CLICKS);
|
||
|
||
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
|
||
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
|
||
|
||
System.out.println("Transfer finálně potvrzen!");
|
||
robot.delay(DELAY_AFTER_ACTION);
|
||
}
|
||
|
||
public boolean clickIncludeButton(int tolerance) {
|
||
System.out.println("Potvrzuji transfer - hledám include.png (confirmation button)...");
|
||
|
||
robot.delay(100); // Počkat na zobrazení dialogu
|
||
|
||
// Najít zelené INCLUDE tlačítko v potvrzovacím dialogu
|
||
Point buttonPos = findIncludeButtonPosition(tolerance);
|
||
if (buttonPos == null) {
|
||
System.out.println("INCLUDE tlačítko nebylo nalezeno, přeskočím potvrzení.");
|
||
return false;
|
||
}
|
||
|
||
robot.mouseMove(buttonPos.x, buttonPos.y);
|
||
robot.delay(DELAY_BETWEEN_CLICKS);
|
||
|
||
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
|
||
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
|
||
|
||
System.out.println("Transfer finálně potvrzen!");
|
||
robot.delay(DELAY_AFTER_ACTION);
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Spustí Transfer automatizaci s konkrétním počtem pokémonů
|
||
*
|
||
* @param totalPokemonCount Celkový počet pokémonů k transferu
|
||
* @param delaySeconds Čekání mezi iteracemi (v sekundách)
|
||
*/
|
||
public void runWithCount(int totalPokemonCount, int delaySeconds) {
|
||
System.out.println("Spouštím Transfer automatizaci - Počet pokémonů: " + totalPokemonCount + ", Čekání: "
|
||
+ delaySeconds + "s");
|
||
|
||
if (!findPokemonGoWindow()) {
|
||
System.err.println("Nepodařilo se najít okno Pokémon GO!");
|
||
return;
|
||
}
|
||
|
||
activateWindow();
|
||
|
||
System.out.println("Čekám 1 sekundu před začátkem...");
|
||
robot.delay(1000);
|
||
|
||
int transferredCount = 0;
|
||
|
||
// Transferovat dokud nedosáhneme požadovaného počtu
|
||
while (transferredCount < totalPokemonCount) {
|
||
// Kontrola přerušení
|
||
if (Thread.currentThread().isInterrupted()) {
|
||
System.out.println("\n⚠️ Automatizace byla přerušena!");
|
||
return;
|
||
}
|
||
|
||
int pokemonThisRound = Math.min(12, totalPokemonCount - transferredCount);
|
||
|
||
System.out.println(
|
||
"\n=== Iterace " + (transferredCount / 9 + 1) + " - Transferuji maximálně " + pokemonThisRound
|
||
+ " pokémonů ===");
|
||
|
||
// Vybrat pokémony a získat skutečný počet vybraných
|
||
int actualTransferredCount = selectAllPokemonCount(pokemonThisRound);
|
||
|
||
System.out.println("Čekám na TRANSFER...");
|
||
clickTransferButton();
|
||
|
||
System.out.println("Čekám na INCLUDE dialog...");
|
||
robot.delay(100);
|
||
if (clickIncludeButton(110)) {
|
||
System.out.println("Čekám na potvrzovací dialog t3...");
|
||
robot.delay(100);
|
||
clickConfirmTransferButton(t3Template, 70);
|
||
} else {
|
||
System.out.println("Čekám na potvrzovací dialog t2...");
|
||
robot.delay(100);
|
||
clickConfirmTransferButton(t2Template, 70);
|
||
}
|
||
|
||
transferredCount += actualTransferredCount;
|
||
transferredPokemonCount += actualTransferredCount;
|
||
|
||
System.out.println("Transferováno v této iteraci: " + actualTransferredCount + " pokémonů (celkem: "
|
||
+ transferredCount + ")");
|
||
|
||
// Pokud ještě zbývá co transferovat, počkat
|
||
if (transferredCount < totalPokemonCount) {
|
||
System.out.println("Přestávka: " + delaySeconds + " sekund...");
|
||
// Čekat s kontrolou přerušení
|
||
long endTime = System.currentTimeMillis() + (delaySeconds * 1000L);
|
||
while (System.currentTimeMillis() < endTime) {
|
||
if (Thread.currentThread().isInterrupted()) {
|
||
System.out.println("\n⚠️ Automatizace byla přerušena během přestávky!");
|
||
return;
|
||
}
|
||
robot.delay(100);
|
||
}
|
||
}
|
||
}
|
||
|
||
System.out.println("\n✅ Transfer automatizace dokončena! Transferováno: " + transferredCount + " pokémonů");
|
||
}
|
||
|
||
/**
|
||
* Označí konkrétní počet pokémonů
|
||
*
|
||
* @return Skutečný počet vybraných pokémonů
|
||
*/
|
||
private int selectAllPokemonCount(int count) {
|
||
System.out.println("Začínám označovat " + count + " pokémonů (pouze template matching)...");
|
||
|
||
List<Point> positions = getPossitionsAbsolute();
|
||
|
||
int maxPokemon = Math.min(count, positions.size());
|
||
System.out.println("Budu označovat " + maxPokemon + " pokémonů...");
|
||
|
||
for (int i = 0; i < maxPokemon; i++) {
|
||
Point pos = positions.get(i);
|
||
System.out.println("Klikám na Pokémona " + (i + 1) + "/" + maxPokemon + " na pozici: " + pos);
|
||
|
||
robot.mouseMove(pos.x, pos.y);
|
||
|
||
if (i == 0) {
|
||
System.out.println(" -> Dlouhé podržení (aktivace multi-select)");
|
||
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
|
||
robot.delay(700);
|
||
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
|
||
robot.delay(DELAY_AFTER_ACTION);
|
||
} else {
|
||
System.out.println(" -> Normální klik");
|
||
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
|
||
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
|
||
}
|
||
|
||
robot.delay(DELAY_BETWEEN_CLICKS);
|
||
}
|
||
|
||
System.out.println("Označeno " + maxPokemon + " pokémonů!");
|
||
System.out.println("Čekám před kliknutím na TRANSFER...");
|
||
robot.delay(800);
|
||
|
||
return maxPokemon;
|
||
}
|
||
|
||
private List<Point> getPossitionsAbsolute() {
|
||
List<Point> possitions = new ArrayList<>();
|
||
|
||
possitions.add(getAbsolutePoint(115, 240));
|
||
possitions.add(getAbsolutePoint(307, 240));
|
||
possitions.add(getAbsolutePoint(496, 240));
|
||
|
||
possitions.add(getAbsolutePoint(115, 460));
|
||
possitions.add(getAbsolutePoint(307, 460));
|
||
possitions.add(getAbsolutePoint(496, 460));
|
||
|
||
possitions.add(getAbsolutePoint(115, 680));
|
||
possitions.add(getAbsolutePoint(307, 680));
|
||
possitions.add(getAbsolutePoint(496, 680));
|
||
|
||
possitions.add(getAbsolutePoint(115, 900));
|
||
possitions.add(getAbsolutePoint(307, 900));
|
||
possitions.add(getAbsolutePoint(496, 900));
|
||
return possitions;
|
||
}
|
||
|
||
/**
|
||
* Převede relativní pozici v okně (0.0-1.0) na absolutní souřadnice obrazovky
|
||
*
|
||
* @param relativeX Relativní X pozice (0.0 = levý okraj, 1.0 = pravý okraj)
|
||
* @param relativeY Relativní Y pozice (0.0 = horní okraj, 1.0 = dolní okraj)
|
||
* @return Absolutní pozice na obrazovce
|
||
*/
|
||
private Point getAbsolutePoint(int relativeX, int relativeY) {
|
||
int absoluteX = windowBounds.x + relativeX;
|
||
int absoluteY = windowBounds.y + relativeY;
|
||
return new Point(absoluteX, absoluteY);
|
||
}
|
||
|
||
public static void main(String[] args) {
|
||
System.out.println("=== Pokémon GO Automatizační Nástroj ===");
|
||
System.out.println("Ujistěte se, že je aplikace Pokémon GO spuštěná...");
|
||
}
|
||
}
|