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-03-07 00:51:47 -05:00
|
|
|
import java.awt.Rectangle;
|
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;
|
|
|
|
|
2018-03-07 00:51:47 -05:00
|
|
|
import org.opencv.core.Rect2d;
|
|
|
|
|
2018-01-30 04:14:17 -05:00
|
|
|
public class Cursor {
|
|
|
|
|
2018-02-15 06:27:12 -05:00
|
|
|
public static final int NUMBER_OF_DISTANCES = 2203; // For 1080p screen
|
2018-02-19 20:55:50 -05:00
|
|
|
public static final int MINIMUM_CLICK_LENGTH = 100;
|
|
|
|
public static final int MAXIMUM_CLICK_LENGTH = 230;
|
2018-01-31 00:45:08 -05:00
|
|
|
|
2018-01-30 08:15:20 -05:00
|
|
|
private Robot robot;
|
2018-02-04 15:34:27 -05:00
|
|
|
private Randomizer randomizer;
|
2018-02-12 19:40:09 -05:00
|
|
|
private Random 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-02-22 13:46:32 -05:00
|
|
|
initializeCursorPathsByDistanceFromFile(Paths.CURSOR_COORDINATES_FILE_PATH);
|
2018-01-31 00:45:08 -05:00
|
|
|
|
|
|
|
robot = new Robot();
|
2018-02-04 15:34:27 -05:00
|
|
|
randomizer = new Randomizer();
|
2018-02-12 19:40:09 -05:00
|
|
|
random = new Random();
|
2018-01-31 00:45:08 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
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-02-02 12:56:34 -05:00
|
|
|
// TODO: make sure these are reasonable
|
2018-01-31 00:45:08 -05:00
|
|
|
private int getRandomClickLength() {
|
2018-02-04 15:34:27 -05:00
|
|
|
return randomizer.nextGaussianWithinRange(MINIMUM_CLICK_LENGTH, MAXIMUM_CLICK_LENGTH);
|
2018-01-31 00:45:08 -05:00
|
|
|
}
|
|
|
|
|
2018-02-19 16:12:25 -05:00
|
|
|
private int getRandomClickReleaseLength() {
|
|
|
|
return randomizer.nextGaussianWithinRange(MINIMUM_CLICK_LENGTH + 5, MAXIMUM_CLICK_LENGTH + 10);
|
|
|
|
}
|
2018-02-19 16:25:11 -05:00
|
|
|
// END
|
2018-02-19 16:12:25 -05:00
|
|
|
|
2018-01-31 00:45:08 -05:00
|
|
|
public void leftClickCursor() throws InterruptedException {
|
2018-03-14 03:17:51 -04:00
|
|
|
Thread.sleep(30, 55);
|
2018-01-31 00:45:08 -05:00
|
|
|
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
|
|
|
|
Thread.sleep(getRandomClickLength());
|
|
|
|
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
|
2018-02-19 16:12:25 -05:00
|
|
|
Thread.sleep(getRandomClickReleaseLength());
|
2018-01-31 00:45:08 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
public void rightClickCursor() throws InterruptedException {
|
2018-03-12 05:54:47 -04:00
|
|
|
Thread.sleep(50, 80);
|
2018-01-31 00:45:08 -05:00
|
|
|
robot.mousePress(InputEvent.BUTTON3_DOWN_MASK);
|
2018-02-19 16:12:25 -05:00
|
|
|
Thread.sleep(getRandomClickLength() + 20);
|
2018-01-31 00:45:08 -05:00
|
|
|
robot.mouseRelease(InputEvent.BUTTON3_DOWN_MASK);
|
2018-02-19 16:12:25 -05:00
|
|
|
Thread.sleep(getRandomClickReleaseLength());
|
2018-01-31 00:45:08 -05:00
|
|
|
}
|
|
|
|
|
2018-02-19 14:25:10 -05:00
|
|
|
public void moveAndLeftClickAtCoordinates(Point goalPoint) throws Exception {
|
2018-01-31 00:45:08 -05:00
|
|
|
moveCursorToCoordinates(goalPoint);
|
|
|
|
leftClickCursor();
|
|
|
|
}
|
|
|
|
|
2018-02-19 14:25:10 -05:00
|
|
|
public void moveAndRightClickAtCoordinates(Point goalPoint) throws Exception {
|
2018-02-15 06:27:12 -05:00
|
|
|
moveCursorToCoordinates(goalPoint);
|
|
|
|
rightClickCursor();
|
|
|
|
}
|
|
|
|
|
2018-02-19 14:25:10 -05:00
|
|
|
public Point moveAndLeftClickAtCoordinatesWithRandomness(Point goalPoint, int xTolerance, int yTolerance) throws Exception {
|
2018-02-02 06:27:29 -05:00
|
|
|
Point randomizedGoalPoint = randomizePoint(goalPoint, xTolerance, yTolerance);
|
2018-02-19 16:12:25 -05:00
|
|
|
moveAndLeftClickAtCoordinates(randomizedGoalPoint);
|
|
|
|
return randomizedGoalPoint; // Return the point we moved to in case we need precise movement afterwards
|
|
|
|
}
|
|
|
|
|
2018-03-07 00:51:47 -05:00
|
|
|
public Point moveInsideBoundingRectangle(Rectangle boundingRectangle) throws Exception {
|
|
|
|
Point randomizedGoalPoint = getRandomPointInBoundingRectangle(boundingRectangle);
|
|
|
|
moveCursorToCoordinates(randomizedGoalPoint);
|
|
|
|
return randomizedGoalPoint;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Point moveAndLeftClickInBoundingRectangle(Rectangle boundingRectangle) throws Exception {
|
|
|
|
Point randomizedGoalPoint = getRandomPointInBoundingRectangle(boundingRectangle);
|
|
|
|
moveAndLeftClickAtCoordinates(randomizedGoalPoint);
|
|
|
|
return randomizedGoalPoint;
|
|
|
|
}
|
|
|
|
|
|
|
|
private Point getRandomPointInBoundingRectangle(Rectangle boundingRectangle) {
|
|
|
|
int x = randomizer.nextGaussianWithinRange(boundingRectangle.x, boundingRectangle.x + boundingRectangle.width);
|
|
|
|
int y = randomizer.nextGaussianWithinRange(boundingRectangle.y, boundingRectangle.y + boundingRectangle.height);
|
|
|
|
return new Point(x, y);
|
|
|
|
}
|
|
|
|
|
2018-02-19 16:12:25 -05:00
|
|
|
public Point moveAndLeftClickAtCoordinatesWithRandomness(Point goalPoint, int xToleranceLeft, int xToleranceRight, int yTolerance) throws Exception {
|
|
|
|
Point randomizedGoalPoint = randomizePoint(goalPoint, xToleranceLeft, xToleranceRight, yTolerance);
|
|
|
|
moveAndLeftClickAtCoordinates(randomizedGoalPoint);
|
2018-02-15 06:27:12 -05:00
|
|
|
return randomizedGoalPoint; // Return the point we moved to in case we need precise movement afterwards
|
2018-01-31 00:45:08 -05:00
|
|
|
}
|
2018-02-02 06:27:29 -05:00
|
|
|
|
2018-02-19 14:25:10 -05:00
|
|
|
public Point moveAndRightlickAtCoordinatesWithRandomness(Point goalPoint, int xTolerance, int yTolerance) throws Exception {
|
2018-02-02 06:27:29 -05:00
|
|
|
Point randomizedGoalPoint = randomizePoint(goalPoint, xTolerance, yTolerance);
|
2018-02-19 16:12:25 -05:00
|
|
|
moveAndRightClickAtCoordinates(randomizedGoalPoint);
|
|
|
|
return randomizedGoalPoint; // Return the point we moved to in case we need precise movement afterwards
|
|
|
|
}
|
|
|
|
|
|
|
|
public Point moveAndRightlickAtCoordinatesWithRandomness(Point goalPoint, int xToleranceLeft, int xToleranceRight, int yTolerance) throws Exception {
|
|
|
|
Point randomizedGoalPoint = randomizePoint(goalPoint, xToleranceLeft, xToleranceRight, yTolerance);
|
|
|
|
moveAndRightClickAtCoordinates(randomizedGoalPoint);
|
2018-02-15 06:27:12 -05:00
|
|
|
return randomizedGoalPoint; // Return the point we moved to in case we need precise movement afterwards
|
2018-02-02 06:27:29 -05:00
|
|
|
}
|
2018-01-31 00:45:08 -05:00
|
|
|
|
2018-02-23 09:26:15 -05:00
|
|
|
public Point moveCursorToCoordinatesWithRandomness(Point goalPoint, int xTolerance, int yTolerance) throws Exception {
|
|
|
|
Point randomizedGoalPoint = randomizePoint(goalPoint, xTolerance, yTolerance);
|
|
|
|
moveCursorToCoordinates(randomizedGoalPoint);
|
|
|
|
return randomizedGoalPoint; // Return the point we moved to in case we need precise movement afterwards
|
|
|
|
}
|
|
|
|
|
2018-02-19 14:25:10 -05:00
|
|
|
public void moveCursorToCoordinates(Point goalPoint) throws Exception {
|
2018-02-04 15:34:27 -05:00
|
|
|
Point startingPoint = getCurrentCursorPoint();
|
2018-02-12 19:40:09 -05:00
|
|
|
int distanceToMoveCursor = getDistanceBetweenPoints(startingPoint, goalPoint);
|
2018-02-15 06:27:12 -05:00
|
|
|
double angleToRotateCursorPathTo = getThetaBetweenPoints(startingPoint, goalPoint);
|
2018-02-19 16:12:25 -05:00
|
|
|
|
2018-02-02 12:17:47 -05:00
|
|
|
if (distanceToMoveCursor == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-02-15 06:27:12 -05:00
|
|
|
CursorPath cursorPathWithDistanceSet = chooseCursorPathToFollowBasedOnDistance(distanceToMoveCursor);
|
|
|
|
CursorPath cursorPathWithDistanceAndAngleSet = cursorPathWithDistanceSet.getRotatedCopyOfCursorPath(angleToRotateCursorPathTo);
|
2018-02-19 20:55:50 -05:00
|
|
|
// TODO: Add randomization by parabola or similar
|
|
|
|
// CursorPath randomizedCursorPath = cursorPathWithDistanceAndAngleSet.getCopyOfCursorPathTransformedByParabola();
|
2018-02-15 06:27:12 -05:00
|
|
|
followCursorPath(cursorPathWithDistanceAndAngleSet, startingPoint);
|
2018-01-30 08:15:20 -05:00
|
|
|
}
|
|
|
|
|
2018-02-12 19:40:09 -05:00
|
|
|
public int getDistanceBetweenPoints(Point startingPoint, Point goalPoint) {
|
|
|
|
return (int) (Math.hypot(goalPoint.x - startingPoint.x, goalPoint.y - startingPoint.y));
|
|
|
|
}
|
2018-02-04 15:34:27 -05:00
|
|
|
|
2018-02-12 19:40:09 -05:00
|
|
|
public double getThetaBetweenPoints(Point startingPoint, Point goalPoint) {
|
2018-02-15 06:27:12 -05:00
|
|
|
return Math.atan2((goalPoint.x - startingPoint.x), (goalPoint.y - startingPoint.y));
|
2018-02-04 15:34:27 -05:00
|
|
|
}
|
|
|
|
|
2018-02-15 06:27:12 -05:00
|
|
|
private void followCursorPath(CursorPath cursorPathToFollow, Point startingPoint) throws InterruptedException {
|
|
|
|
for (CursorPoint cursorPoint : cursorPathToFollow.getCursorPathPoints()) {
|
|
|
|
Point translatedPointToClick = new Point(cursorPoint.x + startingPoint.x, cursorPoint.y + startingPoint.y);
|
2018-01-30 10:19:12 -05:00
|
|
|
robotMouseMove(translatedPointToClick);
|
2018-02-15 06:27:12 -05:00
|
|
|
Thread.sleep(cursorPoint.delay);
|
2018-01-30 08:15:20 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2018-02-19 14:25:10 -05:00
|
|
|
private CursorPath chooseCursorPathToFollowBasedOnDistance(int distanceToMoveCursor) throws Exception {
|
2018-02-04 12:18:34 -05:00
|
|
|
int newDistanceToMoveCursor = findNearestPathLengthThatExists(distanceToMoveCursor);
|
|
|
|
ArrayList<CursorPath> cursorPathsWithSameDistance = cursorPathsByDistance.get(newDistanceToMoveCursor);
|
2018-02-19 16:12:25 -05:00
|
|
|
|
|
|
|
CursorPath randomlyChosenCursorPath = cursorPathsWithSameDistance.get(random.nextInt(cursorPathsWithSameDistance.size()));
|
|
|
|
if (newDistanceToMoveCursor == distanceToMoveCursor) {
|
|
|
|
return randomlyChosenCursorPath;
|
|
|
|
}
|
2018-02-19 14:25:10 -05:00
|
|
|
|
2018-02-19 16:12:25 -05:00
|
|
|
double scaleToFactorBy = getScaleToFactorBy(newDistanceToMoveCursor, distanceToMoveCursor);
|
|
|
|
return randomlyChosenCursorPath.getScaledCopyOfCursorPath(scaleToFactorBy);
|
2018-01-30 08:15:20 -05:00
|
|
|
}
|
|
|
|
|
2018-02-19 14:25:10 -05:00
|
|
|
public int findNearestPathLengthThatExists(int distanceToMoveCursor) throws Exception {
|
2018-02-19 16:12:25 -05:00
|
|
|
int closestShorterPathLength = Integer.MIN_VALUE;
|
|
|
|
int closestLongerPathLength = Integer.MAX_VALUE;
|
|
|
|
for (int i = distanceToMoveCursor; i >= 0; i--) {
|
|
|
|
if (cursorPathsByDistance.get(i).size() > 0) {
|
|
|
|
closestShorterPathLength = i;
|
|
|
|
break;
|
2018-02-19 14:25:10 -05:00
|
|
|
}
|
2018-02-19 16:12:25 -05:00
|
|
|
}
|
|
|
|
for (int i = distanceToMoveCursor; i < 2203; i++) {
|
|
|
|
if (cursorPathsByDistance.get(i).size() > 0) {
|
|
|
|
closestLongerPathLength = i;
|
|
|
|
break;
|
2018-02-04 12:18:34 -05:00
|
|
|
}
|
|
|
|
}
|
2018-02-19 16:12:25 -05:00
|
|
|
|
|
|
|
if (closestShorterPathLength == Integer.MIN_VALUE && closestLongerPathLength == Integer.MAX_VALUE) {
|
|
|
|
throw new Exception("No paths of any size exist.");
|
|
|
|
}
|
|
|
|
else if (closestShorterPathLength == Integer.MIN_VALUE) {
|
|
|
|
return closestLongerPathLength;
|
|
|
|
}
|
|
|
|
else if (closestLongerPathLength == Integer.MAX_VALUE) {
|
|
|
|
return closestShorterPathLength;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return (Math.abs(distanceToMoveCursor - closestShorterPathLength) <= Math.abs(distanceToMoveCursor - closestLongerPathLength)) ? closestShorterPathLength : closestLongerPathLength;
|
|
|
|
}
|
2018-02-04 12:18:34 -05:00
|
|
|
}
|
|
|
|
|
2018-02-12 19:40:09 -05:00
|
|
|
private double getScaleToFactorBy(int newDistanceToMoveCursor, int distanceToMoveCursor) {
|
2018-02-19 14:25:10 -05:00
|
|
|
return (1.0 * distanceToMoveCursor / newDistanceToMoveCursor);
|
2018-02-04 12:18:34 -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 Point randomizePoint(Point goalPoint, int xTolerance, int yTolerance) {
|
2018-02-04 15:34:27 -05:00
|
|
|
Randomizer randomizer = new Randomizer();
|
|
|
|
return new Point(goalPoint.x + randomizer.nextGaussianWithinRange(-xTolerance, xTolerance), goalPoint.y + randomizer.nextGaussianWithinRange(-yTolerance, yTolerance));
|
2018-02-02 06:27:29 -05:00
|
|
|
}
|
2018-02-02 12:17:47 -05:00
|
|
|
|
2018-02-19 16:12:25 -05:00
|
|
|
private Point randomizePoint(Point goalPoint, int xToleranceLeft, int xToleranceRight, int yTolerance) {
|
|
|
|
Randomizer randomizer = new Randomizer();
|
|
|
|
return new Point(goalPoint.x + randomizer.nextGaussianWithinRange(-xToleranceLeft, xToleranceRight), goalPoint.y + randomizer.nextGaussianWithinRange(-yTolerance, yTolerance));
|
|
|
|
}
|
|
|
|
|
2018-02-02 12:17:47 -05:00
|
|
|
public void displayCursorPaths() {
|
2018-02-19 14:25:10 -05:00
|
|
|
for (int i = 0; i < NUMBER_OF_DISTANCES; i++) {
|
2018-02-02 12:17:47 -05:00
|
|
|
System.out.println("There are " + cursorPathsByDistance.get(i).size() + " paths of size " + i);
|
|
|
|
}
|
|
|
|
System.out.println("--------------");
|
|
|
|
}
|
2018-03-12 05:54:47 -04:00
|
|
|
|
|
|
|
public Point getOffsetPoint(Point point) {
|
|
|
|
return new Point(point.x + Constants.GAME_WINDOW_OFFSET_X, point.y + Constants.GAME_WINDOW_OFFSET_Y);
|
|
|
|
}
|
2018-01-30 04:14:17 -05:00
|
|
|
}
|