Guest User

Untitled

a guest
Jul 12th, 2018
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 11.46 KB | None | 0 0
  1. import api.methods.Mouse;
  2.  
  3. import java.awt.*;
  4.  
  5. public class MouseHandler {
  6.     /**
  7.      * The amount of time (in ms) it takes per bit of difficulty (look up Fitts
  8.      * Law) to move the mouse. This appears to partially control the speed of
  9.      * mouse movement.
  10.      */
  11.     public static final int msPerBit = 105;
  12.  
  13.     /**
  14.      * The amount of time (in ms) it takes an average mouse user to realise the
  15.      * mouse needs to be moved
  16.      */
  17.     public static final int reactionTime = 0;
  18.  
  19.     private static java.util.Random staticRandom = new java.util.Random();
  20.  
  21.     /**
  22.      * Applies a midpoint algorithm to the Vector of points to ensure pixel to
  23.      * pixel movement
  24.      *
  25.      * @param points The vector of points to be manipulated
  26.      */
  27.     private static void adaptiveMidpoints(final java.util.Vector<Point> points) {
  28.         int i = 0;
  29.         while (i < points.size() - 1) {
  30.             final Point a = points.get(i++);
  31.             final Point b = points.get(i);
  32.             if ((Math.abs(a.x - b.x) > 1) || (Math.abs(a.y - b.y) > 1)) {
  33.                 if (Math.abs(a.x - b.x) != 0) {
  34.                     final double slope = (double) (a.y - b.y) / (double) (a.x - b.x);
  35.                     final double incpt = a.y - slope * a.x;
  36.                     for (int c = a.x < b.x ? a.x + 1 : b.x - 1; a.x < b.x ? c < b.x : c > a.x; c += a.x < b.x ? 1 : -1) {
  37.                         points.add(i++, new Point(c, (int) Math.round(incpt + slope * c)));
  38.                     }
  39.                 } else {
  40.                     for (int c = a.y < b.y ? a.y + 1 : b.y - 1; a.y < b.y ? c < b.y : c > a.y; c += a.y < b.y ? 1 : -1) {
  41.                         points.add(i++, new Point(a.x, c));
  42.                     }
  43.                 }
  44.             }
  45.         }
  46.     }
  47.  
  48.     /**
  49.      * Omits points along the spline in order to move in steps rather then pixel
  50.      * by pixel
  51.      *
  52.      * @param spline    The pixel by pixel spline
  53.      * @param msForMove The ammount of time taken to traverse the spline. should be a
  54.      *                  value from {@link #fittsLaw}
  55.      * @param msPerMove The ammount of time per each move
  56.      * @return The stepped spline
  57.      */
  58.     public static Point[] applyDynamism(final Point[] spline, final int msForMove, final int msPerMove) {
  59.         final int numPoints = spline.length;
  60.         final double msPerPoint = (double) msForMove / (double) numPoints;
  61.         final double undistStep = msPerMove / msPerPoint;
  62.         final int steps = (int) Math.floor(numPoints / undistStep);
  63.         final Point[] result = new Point[steps];
  64.         final double[] gaussValues = MouseHandler.gaussTable(result.length);
  65.         double currentPercent = 0;
  66.         for (int i = 0; i < steps; i++) {
  67.             currentPercent += gaussValues[i];
  68.             final int nextIndex = (int) Math.floor(numPoints * currentPercent);
  69.             if (nextIndex < numPoints) {
  70.                 result[i] = spline[nextIndex];
  71.             } else {
  72.                 result[i] = spline[numPoints - 1];
  73.             }
  74.         }
  75.         if (currentPercent < 1D) {
  76.             result[steps - 1] = spline[numPoints - 1];
  77.         }
  78.         return result;
  79.     }
  80.  
  81.     /**
  82.      * Binomial Coefficient.
  83.      *
  84.      * @param n The superset element count.
  85.      * @param k The subset size.
  86.      * @return <code>n</code> choose <code>k</code>.
  87.      */
  88.     private static double nCk(final int n, final int k) {
  89.         return MouseHandler.fact(n) / (MouseHandler.fact(k) * MouseHandler.fact(n - k));
  90.     }
  91.  
  92.     /**
  93.      * Factorial ("n!").
  94.      *
  95.      * @param n The integer.
  96.      * @return The factorial.
  97.      */
  98.     private static double fact(final int n) {
  99.         double result = 1;
  100.         for (int i = 1; i <= n; i++) {
  101.             result *= i;
  102.         }
  103.         return result;
  104.     }
  105.  
  106.     /**
  107.      * Calculates the ammount of time a movement should Mousetake based on
  108.      * Fitts' Law TIP: Do not add/subtract random values from this result,
  109.      * rather varry the targetSize value or do not move the same distance each
  110.      * time ;)
  111.      *
  112.      * @param targetDist The distance from the current position to the center of the
  113.      *                   target
  114.      * @param targetSize The maximum distence from the center of the target within
  115.      *                   which the end point could be
  116.      * @return the ammount of time (in ms) the movement should take
  117.      */
  118.     public static long fittsLaw(final double targetDist, final double targetSize) {
  119.         return (long) (MouseHandler.reactionTime + MouseHandler.msPerBit * Math.log10(targetDist / targetSize + 1) / Math.log10(2));
  120.     }
  121.  
  122.     /**
  123.      * Satisfies Integral[gaussian(t),t,0,1] == 1D Therefore can distribute a
  124.      * value as a bell curve over the intervel 0 to 1
  125.      *
  126.      * @param t = A value, 0 to 1, representing a percent along the curve
  127.      * @return The value of the gaussian curve at this position
  128.      */
  129.     private static double gaussian(double t) {
  130.         t = 10D * t - 5D;
  131.         return 1D / (Math.sqrt(5D) * Math.sqrt(2D * Math.PI)) * Math.exp(-t * t / 20D);
  132.     }
  133.  
  134.     /**
  135.      * Returns an array of gaussian values that add up to 1 for the number of
  136.      * steps Solves the problem of having using an intergral to distribute
  137.      * values
  138.      *
  139.      * @param steps Number of steps in the distribution
  140.      * @return An array of values that contains the percents of the distribution
  141.      */
  142.     private static double[] gaussTable(final int steps) {
  143.         final double[] table = new double[steps];
  144.         final double step = 1D / steps;
  145.         double sum = 0;
  146.         for (int i = 0; i < steps; i++) {
  147.             sum += MouseHandler.gaussian(i * step);
  148.         }
  149.         for (int i = 0; i < steps; i++) {
  150.             table[i] = MouseHandler.gaussian(i * step) / sum;
  151.         }
  152.         return table;
  153.     }
  154.  
  155.     /**
  156.      * Creates random control points for a spline. Written by Benland100
  157.      *
  158.      * @param sx           Begining X position
  159.      * @param sy           Begining Y position
  160.      * @param ex           Begining X position
  161.      * @param ey           Begining Y position
  162.      * @param ctrlSpacing  Distance between control origins
  163.      * @param ctrlVariance Max X or Y variance of each control point from its origin
  164.      * @return An array of Points that represents the control points of the
  165.      *         spline
  166.      */
  167.     public static Point[] generateControls(final int sx, final int sy, final int ex, final int ey, int ctrlSpacing, int ctrlVariance) {
  168.         final double dist = Math.sqrt((sx - ex) * (sx - ex) + (sy - ey) * (sy - ey));
  169.         final double angle = Math.atan2(ey - sy, ex - sx);
  170.         int ctrlPoints = (int) Math.floor(dist / ctrlSpacing);
  171.         ctrlPoints = ctrlPoints * ctrlSpacing == dist ? ctrlPoints - 1 : ctrlPoints;
  172.         if (ctrlPoints <= 1) {
  173.             ctrlPoints = 2;
  174.             ctrlSpacing = (int) dist / 3;
  175.             ctrlVariance = (int) dist / 2;
  176.         }
  177.         final Point[] result = new Point[ctrlPoints + 2];
  178.         result[0] = new Point(sx, sy);
  179.         for (int i = 1; i < ctrlPoints + 1; i++) {
  180.             final double radius = ctrlSpacing * i;
  181.             final Point cur = new Point((int) (sx + radius * Math.cos(angle)), (int) (sy + radius * Math.sin(angle)));
  182.             double percent = 1D - (double) (i - 1) / (double) ctrlPoints;
  183.             percent = percent > 0.5 ? percent - 0.5 : percent;
  184.             percent += 0.25;
  185.             final int curVariance = (int) (ctrlVariance * percent);
  186.             /**
  187.              * Hopefully {@link java.util.Random} is thread safe. (it is in Sun
  188.              * JVM 1.5+)
  189.              */
  190.             cur.x = (int) (cur.x + curVariance * 2 * MouseHandler.staticRandom.nextDouble() - curVariance);
  191.             cur.y = (int) (cur.y + curVariance * 2 * MouseHandler.staticRandom.nextDouble() - curVariance);
  192.             result[i] = cur;
  193.         }
  194.         result[ctrlPoints + 1] = new Point(ex, ey);
  195.         return result;
  196.     }
  197.  
  198.     /**
  199.      * Generates a spline that moves no more then one pixel at a time TIP: For
  200.      * most movements, this spline is not good, use <code>applyDynamism</code>
  201.      *
  202.      * @param controls An array of control points
  203.      * @return An array of Points that represents the spline
  204.      */
  205.     public static Point[] generateSpline(final Point[] controls) {
  206.         final double degree = controls.length - 1;
  207.         final java.util.Vector<Point> spline = new java.util.Vector<Point>();
  208.         boolean lastFlag = false;
  209.         for (double theta = 0; theta <= 1; theta += 0.01) {
  210.             double x = 0;
  211.             double y = 0;
  212.             for (double index = 0; index <= degree; index++) {
  213.                 final double probPoly = MouseHandler.nCk((int) degree, (int) index) * Math.pow(theta, index) * Math.pow(1D - theta, degree - index);
  214.                 x += probPoly * controls[(int) index].x;
  215.                 y += probPoly * controls[(int) index].y;
  216.             }
  217.             final Point temp = new Point((int) x, (int) y);
  218.             try {
  219.                 if (!temp.equals(spline.lastElement())) {
  220.                     spline.add(temp);
  221.                 }
  222.             } catch (final Exception e) {
  223.                 spline.add(temp);
  224.             }
  225.             lastFlag = theta != 1.0;
  226.         }
  227.         if (lastFlag) {
  228.             spline.add(new Point(controls[(int) degree].x, controls[(int) degree].y));
  229.         }
  230.         MouseHandler.adaptiveMidpoints(spline);
  231.         return spline.toArray(new Point[spline.size()]);
  232.     }
  233.  
  234.     private final java.util.Random random = new java.util.Random();
  235.  
  236.  
  237.     /**
  238.      * Moves the mouse from a position to another position with randomness
  239.      * applied.
  240.      *
  241.      * @param speed the speed to move the mouse.
  242.      * @param x1    from x
  243.      * @param y1    from y
  244.      * @param x2    to x
  245.      * @param y2    to y
  246.      * @param randX randomness in the x direction
  247.      * @param randY randomness in the y direction
  248.      */
  249.     public void moveMouse(final int speed, final int x1, final int y1, final int x2, final int y2, int randX, int randY) {
  250.         if ((x2 == -1) && (y2 == -1)) {
  251.             return;
  252.         }
  253.         if (randX <= 0) {
  254.             randX = 1;
  255.         }
  256.         if (randY <= 0) {
  257.             randY = 1;
  258.         }
  259.         try {
  260.             if ((x2 == x1) && (y2 == y1)) {
  261.                 return;
  262.             }
  263.             final Point[] controls = MouseHandler.generateControls(x1, y1, x2 + random.nextInt(randX), y2 + random.nextInt(randY), 50, 120);
  264.             final Point[] spline = MouseHandler.generateSpline(controls);
  265.             final long timeToMove = MouseHandler.fittsLaw(Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)), Mouse.getSpeed());
  266.             final Point[] path = MouseHandler.applyDynamism(spline, (int) timeToMove, 10);
  267.             for (final Point aPath : path) {
  268.                 Mouse.move(aPath.x, aPath.y);
  269.                 try {
  270.                     Thread.sleep(Math.max(0, speed - 2 + random.nextInt(4)));
  271.                 } catch (final InterruptedException e) {
  272.                     throw new RuntimeException(e);
  273.                 }
  274.             }
  275.         } catch (final Exception e) {
  276.             // MouseHandler.log.info("Error moving mouse: " + e);
  277.             // MouseHandler.log.info("Source: " + x1 + "," + y1);
  278.             // MouseHandler.log.info("Dest:   " + x2 + "," + y2);
  279.             // MouseHandler.log.info("Randx/Randy: " + randX + "/" + randY);
  280.             // e.printStackTrace();
  281.         }
  282.     }
  283. }
Add Comment
Please, Sign In to add comment