2018-01-30 04:14:17 -05:00
|
|
|
/* Reads a file of coordinates
|
|
|
|
*/
|
2018-01-30 08:15:20 -05:00
|
|
|
import java.awt.AWTException;
|
2018-01-30 04:14:17 -05:00
|
|
|
import java.awt.MouseInfo;
|
|
|
|
import java.awt.Point;
|
|
|
|
import java.awt.PointerInfo;
|
2018-01-30 08:15:20 -05:00
|
|
|
import java.awt.Robot;
|
2018-01-31 00:45:08 -05:00
|
|
|
import java.awt.event.InputEvent;
|
2018-01-30 04:14:17 -05:00
|
|
|
import java.io.BufferedReader;
|
|
|
|
import java.io.File;
|
|
|
|
import java.io.FileReader;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.HashMap;
|
2018-01-30 08:15:20 -05:00
|
|
|
import java.util.Random;
|
2018-01-30 04:14:17 -05:00
|
|
|
import java.util.regex.Matcher;
|
|
|
|
import java.util.regex.Pattern;
|
|
|
|
|
|
|
|
public class Cursor {
|
|
|
|
|
2018-01-30 08:15:20 -05:00
|
|
|
public static final int NUMBER_OF_DISTANCES = 1000;
|
2018-01-31 00:45:08 -05:00
|
|
|
public static final int MINIMUM_CLICK_LENGTH = 120;
|
|
|
|
public static final int MAXIMUM_CLICK_LENGTH = 240;
|
|
|
|
|
2018-01-31 09:05:34 -05:00
|
|
|
public static final int GAME_WINDOW_OFFSET_WIDTH = 100; // top left corner of main game screen, from top left corner of screen
|
|
|
|
public static final int GAME_WINDOW_OFFSET_HEIGHT = 81;
|
|
|
|
|
|
|
|
|
2018-01-30 08:15:20 -05:00
|
|
|
private Robot robot;
|
2018-01-31 00:45:08 -05:00
|
|
|
private Random random = new Random();
|
2018-01-30 04:14:17 -05:00
|
|
|
|
|
|
|
private ArrayList<ArrayList<CursorPath>> cursorPathsByDistance;
|
|
|
|
|
2018-01-30 08:15:20 -05:00
|
|
|
public Cursor() throws AWTException {
|
2018-02-02 06:27:29 -05:00
|
|
|
System.out.println("Initializing cursor...");
|
2018-01-31 00:45:08 -05:00
|
|
|
initializeCursorPathsByDistanceFromFile("/home/dpapp/GhostMouse/coordinates.txt");
|
|
|
|
|
|
|
|
robot = new Robot();
|
|
|
|
random = new Random();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void initializeCursorPathsByDistanceFromFile(String path) {
|
2018-01-30 04:14:17 -05:00
|
|
|
initializeCursorPathsByDistance();
|
2018-01-31 00:45:08 -05:00
|
|
|
ArrayList<CursorPath> cursorPaths = getArrayListOfCursorPathsFromFile(path);
|
2018-01-30 04:14:17 -05:00
|
|
|
assignCursorPathsByDistance(cursorPaths);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void initializeCursorPathsByDistance() {
|
|
|
|
this.cursorPathsByDistance = new ArrayList<ArrayList<CursorPath>>();
|
|
|
|
for (int i = 0; i < NUMBER_OF_DISTANCES; i++) {
|
|
|
|
this.cursorPathsByDistance.add(new ArrayList<CursorPath>());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private ArrayList<CursorPath> getArrayListOfCursorPathsFromFile(String path) {
|
|
|
|
CursorDataFileParser cursorDataFileParser = new CursorDataFileParser(path);
|
|
|
|
return cursorDataFileParser.getArrayListOfCursorPathsFromFile();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void assignCursorPathsByDistance(ArrayList<CursorPath> cursorPaths) {
|
|
|
|
for (CursorPath cursorPath : cursorPaths) {
|
|
|
|
if (cursorPath.isCursorPathReasonable()) {
|
|
|
|
addCursorPathToCursorPathsByDistance(cursorPath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void addCursorPathToCursorPathsByDistance(CursorPath cursorPath) {
|
|
|
|
this.cursorPathsByDistance.get(cursorPath.getCursorPathDistance()).add(cursorPath);
|
|
|
|
}
|
|
|
|
|
2018-01-31 00:45:08 -05:00
|
|
|
|
2018-02-02 12:56:34 -05:00
|
|
|
// TODO: make sure these are reasonable
|
2018-01-31 00:45:08 -05:00
|
|
|
private int getRandomClickLength() {
|
|
|
|
return random.nextInt(MAXIMUM_CLICK_LENGTH - MINIMUM_CLICK_LENGTH) + MINIMUM_CLICK_LENGTH;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void leftClickCursor() throws InterruptedException {
|
|
|
|
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
|
|
|
|
Thread.sleep(getRandomClickLength());
|
|
|
|
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
|
2018-02-02 06:27:29 -05:00
|
|
|
Thread.sleep(getRandomClickLength());
|
2018-01-31 00:45:08 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
public void rightClickCursor() throws InterruptedException {
|
|
|
|
robot.mousePress(InputEvent.BUTTON3_DOWN_MASK);
|
2018-02-02 12:56:34 -05:00
|
|
|
Thread.sleep(20 + getRandomClickLength());
|
2018-01-31 00:45:08 -05:00
|
|
|
robot.mouseRelease(InputEvent.BUTTON3_DOWN_MASK);
|
2018-02-02 06:27:29 -05:00
|
|
|
Thread.sleep(getRandomClickLength());
|
2018-01-31 00:45:08 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
public void moveAndLeftClickAtCoordinates(Point goalPoint) throws InterruptedException {
|
|
|
|
moveCursorToCoordinates(goalPoint);
|
|
|
|
leftClickCursor();
|
|
|
|
}
|
|
|
|
|
2018-02-02 12:17:47 -05:00
|
|
|
public Point moveAndLeftClickAtCoordinatesWithRandomness(Point goalPoint, int xTolerance, int yTolerance) throws InterruptedException {
|
2018-02-02 06:27:29 -05:00
|
|
|
Point randomizedGoalPoint = randomizePoint(goalPoint, xTolerance, yTolerance);
|
|
|
|
moveCursorToCoordinates(randomizedGoalPoint);
|
|
|
|
leftClickCursor();
|
2018-02-02 12:17:47 -05:00
|
|
|
return randomizedGoalPoint; // Return the point in case we need precise movement afterwards
|
2018-02-02 06:27:29 -05:00
|
|
|
}
|
|
|
|
|
2018-01-31 00:45:08 -05:00
|
|
|
public void moveAndRightClickAtCoordinates(Point goalPoint) throws InterruptedException {
|
|
|
|
moveCursorToCoordinates(goalPoint);
|
|
|
|
rightClickCursor();
|
|
|
|
}
|
2018-02-02 06:27:29 -05:00
|
|
|
|
2018-02-02 12:17:47 -05:00
|
|
|
public Point moveAndRightlickAtCoordinatesWithRandomness(Point goalPoint, int xTolerance, int yTolerance) throws InterruptedException {
|
2018-02-02 06:27:29 -05:00
|
|
|
Point randomizedGoalPoint = randomizePoint(goalPoint, xTolerance, yTolerance);
|
|
|
|
moveCursorToCoordinates(randomizedGoalPoint);
|
|
|
|
rightClickCursor();
|
2018-02-02 12:17:47 -05:00
|
|
|
return randomizedGoalPoint; // Return the point in case we need precise movement afterwards
|
2018-02-02 06:27:29 -05:00
|
|
|
}
|
2018-01-31 00:45:08 -05:00
|
|
|
|
2018-01-30 08:15:20 -05:00
|
|
|
public void moveCursorToCoordinates(Point goalPoint) throws InterruptedException {
|
|
|
|
Point startingCursorPoint = getCurrentCursorPoint();
|
|
|
|
int distanceToMoveCursor = calculateDistanceBetweenPoints(startingCursorPoint, goalPoint);
|
2018-02-02 12:17:47 -05:00
|
|
|
if (distanceToMoveCursor == 0) {
|
|
|
|
return;
|
|
|
|
}
|
2018-01-30 10:19:12 -05:00
|
|
|
double angleToMoveCursor = calculateThetaBetweenPoints(startingCursorPoint, goalPoint);
|
2018-02-02 12:17:47 -05:00
|
|
|
|
2018-01-31 00:45:08 -05:00
|
|
|
// TODO: check if exists
|
2018-01-30 08:15:20 -05:00
|
|
|
CursorPath cursorPathToFollow = chooseCursorPathToFollowBasedOnDistance(distanceToMoveCursor);
|
2018-01-30 10:19:12 -05:00
|
|
|
double angleToTranslatePathBy = angleToMoveCursor - cursorPathToFollow.getCursorPathTheta();
|
|
|
|
followCursorPath(startingCursorPoint, angleToTranslatePathBy, cursorPathToFollow);
|
2018-01-30 08:15:20 -05:00
|
|
|
}
|
|
|
|
|
2018-01-30 10:19:12 -05:00
|
|
|
private void followCursorPath(Point startingCursorPoint, double angleToTranslatePathBy, CursorPath cursorPathToFollow) throws InterruptedException {
|
|
|
|
for (CursorPoint untranslatedCursorPoint : cursorPathToFollow.getCursorPathPoints()) {
|
|
|
|
Point translatedPointToClick = translatePoint(startingCursorPoint, angleToTranslatePathBy, untranslatedCursorPoint);
|
|
|
|
robotMouseMove(translatedPointToClick);
|
2018-01-31 00:04:07 -05:00
|
|
|
Thread.sleep(untranslatedCursorPoint.postMillisecondDelay);
|
2018-01-30 08:15:20 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-30 10:19:12 -05:00
|
|
|
private Point translatePoint(Point startingCursorPoint, double angleToTranslateBy, CursorPoint untranslatedCursorPoint) {
|
|
|
|
int x = (int) (startingCursorPoint.x + Math.cos(angleToTranslateBy) * untranslatedCursorPoint.x - Math.sin(angleToTranslateBy) * untranslatedCursorPoint.y);
|
|
|
|
int y = (int) (startingCursorPoint.y + Math.sin(angleToTranslateBy) * untranslatedCursorPoint.x + Math.cos(angleToTranslateBy) * untranslatedCursorPoint.y);
|
2018-01-30 08:15:20 -05:00
|
|
|
return new Point(x, y);
|
|
|
|
}
|
|
|
|
|
2018-01-30 10:04:20 -05:00
|
|
|
public void robotMouseMove(Point pointToMoveCursorTo) {
|
2018-01-30 08:15:20 -05:00
|
|
|
robot.mouseMove(pointToMoveCursorTo.x, pointToMoveCursorTo.y);
|
|
|
|
}
|
|
|
|
|
|
|
|
private CursorPath chooseCursorPathToFollowBasedOnDistance(int distanceToMoveCursor) {
|
2018-02-04 12:18:34 -05:00
|
|
|
if (distanceToMoveCursor == 0) {
|
2018-02-02 12:17:47 -05:00
|
|
|
return new CursorPath(new ArrayList<CursorPoint>());
|
|
|
|
}
|
2018-02-04 12:18:34 -05:00
|
|
|
|
|
|
|
int newDistanceToMoveCursor = findNearestPathLengthThatExists(distanceToMoveCursor);
|
|
|
|
double scaleFactor = getScaleFactor(newDistanceToMoveCursor, distanceToMoveCursor);
|
|
|
|
|
|
|
|
ArrayList<CursorPath> cursorPathsWithSameDistance = cursorPathsByDistance.get(newDistanceToMoveCursor);
|
|
|
|
CursorPath scaledCursorPath = cursorPathsWithSameDistance.get(random.nextInt(cursorPathsWithSameDistance.size())).getScaledCopyOfCursorPath(1.0);
|
|
|
|
return scaledCursorPath;
|
2018-01-30 08:15:20 -05:00
|
|
|
}
|
|
|
|
|
2018-02-04 12:18:34 -05:00
|
|
|
private int findNearestPathLengthThatExists(int distanceToMoveCursor) {
|
|
|
|
int offset = 1;
|
|
|
|
while (cursorPathsByDistance.get(distanceToMoveCursor + offset).size() == 0) {
|
|
|
|
if (offset > 0) {
|
|
|
|
offset = -(offset + 1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
offset = -offset + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return distanceToMoveCursor + offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
private double getScaleFactor(int newDistanceToMoveCursor, int distanceToMoveCursor) {
|
|
|
|
return (1.0 * newDistanceToMoveCursor / distanceToMoveCursor);
|
|
|
|
}
|
|
|
|
|
2018-01-30 08:15:20 -05:00
|
|
|
private int calculateDistanceBetweenPoints(Point a, Point b) {
|
|
|
|
return (int) (Math.hypot(a.x - b.x, a.y - b.y));
|
|
|
|
}
|
|
|
|
|
|
|
|
public double calculateThetaBetweenPoints(Point a, Point b) {
|
2018-01-30 10:04:20 -05:00
|
|
|
return Math.atan2(1.0 * (b.y - a.y), 1.0 * (b.x - a.x));
|
2018-01-30 08:15:20 -05:00
|
|
|
}
|
|
|
|
|
2018-01-30 10:04:20 -05:00
|
|
|
public Point getCurrentCursorPoint() {
|
2018-01-30 08:15:20 -05:00
|
|
|
return MouseInfo.getPointerInfo().getLocation();
|
|
|
|
}
|
2018-02-02 06:27:29 -05:00
|
|
|
|
|
|
|
private int getRandomIntSigned(int tolerance) {
|
|
|
|
return random.nextInt(tolerance) - tolerance / 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
private Point randomizePoint(Point goalPoint, int xTolerance, int yTolerance) {
|
|
|
|
return new Point(goalPoint.x + getRandomIntSigned(xTolerance), goalPoint.y + getRandomIntSigned(yTolerance));
|
|
|
|
}
|
2018-02-02 12:17:47 -05:00
|
|
|
|
|
|
|
public void displayCursorPaths() {
|
|
|
|
for (int i = 0; i < 200; i++) {
|
|
|
|
System.out.println("There are " + cursorPathsByDistance.get(i).size() + " paths of size " + i);
|
|
|
|
}
|
|
|
|
System.out.println("--------------");
|
|
|
|
for (int i = 0; i < cursorPathsByDistance.get(1).size(); i++) {
|
|
|
|
cursorPathsByDistance.get(1).get(i).displayCursorPoints();
|
|
|
|
}
|
|
|
|
//cursorPathsByDistance.get(0).get(0).displayCursorPoints();
|
|
|
|
}
|
2018-01-30 04:14:17 -05:00
|
|
|
}
|