jythonsikulisikuli-script

Can't figure out, why script on Jython working differently from script on Pascal


Long story short: I'm writing script, which should move mouse and do clicks like human (it's a bot, actually), using SikuliX. SikuliX uses Jython 2.7 as lang for scritps. I found nice lib for my purposes (moving mouse like human): mouse.simba written in Pascal-like lang, and rewrite function _humanWindMouse() in jython. It works, but not like I expected it would be.

Test run of my script, drawing rectangle:

https://prtscr.cx.ua/storage/5b/5b2203.jpg

Result of using original function with same coords:

https://prtscr.cx.ua/storage/bb/bb3ff5.jpg

sorry for links, I can't post images yet (

My code:

import random
import time
import math
from time import sleep
from math import sqrt
from math import ceil
from math import hypot

from java.awt import Robot

def distance(x1, y1, x2, y2):
    return math.hypot(x2 - x1, y2 - y1)

def myrandom(x):
    return random.randint(0, x-1)

def myround(x):
    return int(round(x))

# function MMouseMove (MyMouseMove) for moving mouse using only coord
def MMouseMove(x,y):
    robot = Robot()
    robot.mouseMove(x,y)

# function HumanWindMouse by BenLand100 & Flight, python implementation
def humanWindMouse(xs, ys, xe, ye, gravity, wind):
    veloX = veloY = windX=windY=veloMag=dist=randomDist=lastDist=D=0
    lastX=lastY=MSP=W=TDist=0

    mouseSpeed = 20
    MSP = mouseSpeed
    sqrt2 = sqrt(2)
    sqrt3 = sqrt(3)
    sqrt5 = sqrt(5)

    TDist = distance(myround(xs), myround(ys), myround(xe), myround(ye))
    t = time.time() + 10000
    while True:
        if time.time() > t:
            break

        dist = hypot(xs - xe, ys - ye)
        wind = min(wind, dist)
        if dist < 1:
            dist = 1

        D = (myround((myround(TDist)*0.3))/7)
        if D > 25:
            D = 25
        if D < 5:
            D = 5

        rCnc = myrandom(6)
        if rCnc == 1:
            D = random.randint(2,3)

        if D <= myround(dist):
            maxStep = D
        else:
            maxStep = myround(dist)

        windX= windX / sqrt2
        windY= windY / sqrt2

        veloX= veloX + windX
        veloY= veloY + windY
        veloX= veloX + gravity * (xe - xs) / dist
        veloY= veloY + gravity * (ye - ys) / dist

        if hypot(veloX, veloY) > maxStep:
            temp = int(myround(maxStep) // 2)
            if temp == 0:
                temp = 1
            randomDist= maxStep / 2.0 + myrandom(temp)
            veloMag= sqrt(veloX * veloX + veloY * veloY)
            veloX= (veloX / veloMag) * randomDist
            veloY= (veloY / veloMag) * randomDist

        lastX= myround(xs)
        lastY= myround(ys)
        xs= xs + veloX
        ys= ys + veloY

        if lastX <> myround(xs) or lastY <> myround(ys):
            MMouseMove(myround(xs), myround(ys))

        W = (myrandom((myround(100/MSP)))*6)
        if W < 5:
            W = 5
        W = myround(W*0.9)
        sleep(W/1000.0)
        lastdist= dist

        if hypot(xs - xe, ys - ye) < 1:
            break

    if myround(xe) <> myround(xs) or myround(ye) <> myround(ys):
        MMouseMove(myround(xe), myround(ye)) 
    mouseSpeed = MSP    
    return;

def MMouse(x,y):
    mouseSpeed = 20
    randSpeed = (myrandom(mouseSpeed) / 2.0 + mouseSpeed) / 10.0
    curPos = Mouse.at()
    x1 = curPos.x
    y1 = curPos.y
    humanWindMouse(x1, y1, x, y, 5, 10.0/randSpeed)
    return;

And I used this in such a way:

MMouseMove(227, 146)

mouseDown(Button.LEFT)
MMouse(396, 146)
MMouse(396, 252)
MMouse(227, 252)
MMouse(227, 146)
mouseUp(Button.LEFT)

exit()

mouseDown() and mouseUp() are built-in functions in SikuliX
And I didn't use built-in mouseMove(), because with it going from A to B is too slow.

Any help would be appreciated


Solution

  • After few hours of debugging i figured out the problem: in source code for unknowing reason author passed constant called MOUSE_HUMAN to variable named gravity when caling his function _humanWindMouse(), this looks like an error to me. Thats why I decided to fix this in my code, and throw out one argument of the function and a few lines of code (and that was wrong move). After re-adding needed code my function working, as I expected.

    So, here's the working code:

    # function HumanWindMouse by BenLand100 & Flight, 
    # python implementation by Nokse
    def humanWindMouse(xs, ys, xe, ye, gravity, wind, targetArea):
        veloX = veloY = windX=windY=veloMag=dist=randomDist=lastDist=D=0
        lastX=lastY=MSP=W=TDist=0
    
        mouseSpeed = 20
        MSP = mouseSpeed
        sqrt2 = sqrt(2)
        sqrt3 = sqrt(3)
        sqrt5 = sqrt(5)
    
        TDist = distance(myround(xs), myround(ys), myround(xe), myround(ye))
        t = time.time() + 10000
        while True:
            if time.time() > t:
                break
    
            dist = hypot(xs - xe, ys - ye)
            wind = min(wind, dist)
            if dist < 1:
                dist = 1
    
            D = (myround((myround(TDist)*0.3))/7)
            if D > 25:
                D = 25
            if D < 5:
                D = 5
    
            rCnc = myrandom(6)
            if rCnc == 1:
                D = random.randint(2,3)
    
            if D <= myround(dist):
                maxStep = D
            else:
                maxStep = myround(dist)
    
            if dist >= targetArea:
                windX = windX / sqrt3 + (myrandom(myround(wind) * 2 + 1) - wind) / sqrt5
                windY = windY / sqrt3 + (myrandom(myround(wind) * 2 + 1) - wind) / sqrt5
            else:
                windX = windX / sqrt2
                windY = windY / sqrt2
    
            veloX = veloX + windX
            veloY = veloY + windY
            veloX = veloX + gravity * (xe - xs) / dist
            veloY = veloY + gravity * (ye - ys) / dist
    
            if hypot(veloX, veloY) > maxStep:
                halfSteps = int(myround(maxStep) // 2)
                if halfSteps == 0:
                    halfSteps = 1
                randomDist = maxStep / 2.0 + myrandom(halfSteps)
                veloMag = sqrt(veloX * veloX + veloY * veloY)
                veloX = (veloX / veloMag) * randomDist
                veloY = (veloY / veloMag) * randomDist
    
            lastX = myround(xs)
            lastY = myround(ys)
            xs = xs + veloX
            ys = ys + veloY
    
            if lastX <> myround(xs) or lastY <> myround(ys):
                MMouseMove(myround(xs), myround(ys))
    
            W = (myrandom((myround(100/MSP)))*6)
            if W < 5:
                W = 5
            W = myround(W*0.9)
            sleep(W/1000.0)
            lastdist = dist
            #condition for exiting while loop
            if hypot(xs - xe, ys - ye) < 1:
                break
    
        if myround(xe) <> myround(xs) or myround(ye) <> myround(ys):
            MMouseMove(myround(xe), myround(ye)) 
        mouseSpeed = MSP    
        return; 
    

    I tested it with different parameters, and choose this one:

    humanWindMouse(xs, ys, x, y, 9, 10.0/randSpeed, 10.0*randSpeed)
    

    but I recommend to play with parameters first, to understand, how do they affect the behavior of the mouse.

    How to calc randSpeed, what should be imported, and sub-functions, such as myround(), could be found at my first post. Hope, this code will help somebody someday)