Jump to content

SmartKeyboard - better human typing


Bobrocket

Recommended Posts

Alright, so after reading the "My Ban Theory" thread, I decided to take the idea of a normal distribution to keyboard typing. What I have made is experimental and may not work as expected to. All I aim to do with this is help to educate those with typing correctly.

 

How it works:

  • Calculating based on words per minute, it sleeps a variable amount based on the value (assuming the average word has 6 characters)
  • With the help of normal distributions, the mean is the mode and the median (which is also usually the midpoint), so we can calculate a normal distribution of sleeping using the mean.
  • It types character per character
  • It wraps the Script sleep function to pause the appropriate time frame
  • (Version 1.1 and onwards) now makes typing errors based on the words per minute setting!

Version 1.1 (newest; typos included):

import java.util.ArrayList;
import java.util.Random;

import org.osbot.rs07.api.Keyboard;
import org.osbot.rs07.script.Script;

public class SmartKeyboard {
	
	public int wordsPM, charsPM, charsPS, msPC, minMS, maxMS, typoRate = 0;
	public Random rand;
	public Script baseScript;
	public Keyboard kb;
	
	public int typoConstant = 100000; //You can change this if needed
	
	//This is a huge array of all potential typos for every alphabet character
	public String[][] typos = new String[][] { { "q", "s", "z" }, //a
		{ "v", "g", "n" }, { "x", "d", "v" }, { "s", "e", "f", "c" }, //bcd
		{ "w", "d", "r" }, { "d", "r", "g", "v" }, { "f", "t", "h", "b" }, //efg
		{ "g", "y", "j", "n" }, { "u", "k", "o" }, { "h", "m", "k", "u" }, //hij
		{ "j", ",", "l", "i" }, { "k", ".", ";", "o" }, { "n", "j", "," }, //klm
		{ "b", "h", "m" }, { "i", "l", "p" }, { "o", ";", "[" }, //nop
		{ "w", "a", "s" }, { "e", "f", "t", "4" }, { "w", "a", "d", "x" },//qrs
		{ "r", "g", "y", "5" }, { "y", "j", "i", "8" }, { "c", "f", "b" },//tuv
		{ "q", "s", "e" }, { "z", "s", "c", "d" }, { "t", "h", "u", "j" }, //wxy
		{ "a", "s", "x", "\\" }//z
		};
	
	public String alphabet = "abcdefghijklmnopqrstuvwxyz";
	
	public SmartKeyboard(Script base, int wpm) {
		baseScript = base;
		kb = base.getKeyboard();
		wordsPM = wpm;
		charsPM = (wpm * 6);
		charsPS = charsPM / 60;
		msPC = 1000 / charsPS;
		
		rand = new Random();
		minMS = msPC - (wordsPM / 2) + rand.nextInt(15); //Make this a little bit more random to simulate real key presses
		maxMS = msPC + (wordsPM / 2) + rand.nextInt(15);
	}
	
	public boolean typeString(String toType, boolean enter, boolean typos) throws InterruptedException {
		int x = calculateTypo();
		ArrayList<TypoChar> indexes = new ArrayList<TypoChar>();
		int index = 0;
		for (char ch : toType.toCharArray()) {
			
			//Here we are going to erase any typos
			if (typos && rand.nextInt(2) == 1) {
				for (TypoChar tc : indexes) {
					if (tc.index == (index - 1)) { //We're going to erase this fucker
						kb.typeKey((char)8); //8 is the backspace character (or 127 which is delete, not sure here)
						sleep(rand(minMS, maxMS, msPC));
						kb.typeKey(tc.original);
						sleep(rand(minMS, maxMS, msPC));
					}
				}
			}
			
			char old = ch;
			if (typos && (rand.nextInt(x) == (x / 2))) {
				ch = toTypo(String.valueOf(ch)).toCharArray()[0];
				indexes.add(new TypoChar(index, old)); //We're going to see
			}
			kb.typeKey(ch);
			sleep(rand(minMS, maxMS, msPC));
			index++;
		}
		
		if (enter) {
			pressEnter();
		}
		
		return true;
	}
	
	public boolean typeCharacter(String character, boolean enter) throws InterruptedException {
		kb.typeKey(character.toCharArray()[0]);
		sleep(rand(minMS, maxMS, msPC));
		
		if (enter) {
			pressEnter();
		}
		
		return true;
	}
	
	public boolean typeInteger(int integer, boolean enter) throws InterruptedException {
		kb.typeKey(Character.forDigit(integer, 10));
		sleep(rand(minMS, maxMS, msPC));
		
		if (enter) {
			pressEnter();
		}
		
		return true;
	}
	
	public boolean pressEnter() {
		kb.typeKey((char)13);
		kb.typeKey((char)10);
		return true;
	}
	
	public int calculateTypo() {
		int temp = typoConstant / (wordsPM * 10);
		temp += rand.nextInt(6);
		return temp;
	}
	
	public String toTypo(String toTypo) { //TODO: preserve uppercase (if wanted)
		toTypo = toTypo.toLowerCase();
		int index = alphabet.indexOf(toTypo.charAt(0)); //Get the index to get typos for
		
		String[] charTypos = typos[index]; //We have our typos stored in the order abcdef...z
		int len = charTypos.length;
		toTypo = charTypos[getRandom(0, len - 1)]; //We do len - 1 as Java uses zero-based arrays.
		
		return toTypo;
	}
	
	public int rand(int min, int max, int mean) { //Edited slightly; in a normal distribution, mean = mode = median = midpoint of graph
		int n;
		//int mean = (min + max) / 2;
		int std = (max - mean) / 3;
		Random r = new Random();
		
		do {
			double val = r.nextGaussian() * std + mean;
			n = (int) Math.round(val);
		} while (n < min || n > max);
		
		return n;
	}
	
	public int getRandom(int min, int max) {
		int range = (max - min) + 1;
		return rand.nextInt(range) + min;
	}
	
	public void sleep(int t) throws InterruptedException {
		Script.sleep(t);
	}

}

class TypoChar { //We'll make an arraylist of these bad boys
	public int index;
	public char original;
	
	public TypoChar(int i, char o) {
		original = o;
		index = i;
	}
}

 

 

Version 1.0 (old; no typos included):

import java.util.Random;

import org.osbot.rs07.api.Keyboard;
import org.osbot.rs07.script.Script;

public class SmartKeyboard {

public int wordsPM, charsPM, charsPS, msPC, minMS, maxMS = 0;
public Random rand;
public Script baseScript;
public Keyboard kb;

public SmartKeyboard(Script base, int wpm) {
baseScript = base;
kb = base.getKeyboard();
wordsPM = wpm;
charsPM = (wpm * 6);
charsPS = charsPM / 60;
msPC = 1000 / charsPS;

rand = new Random();
minMS = msPC - (wordsPM / 2) + rand.nextInt(15); //Make this a little bit more random to simulate real key presses
maxMS = msPC + (wordsPM / 2) + rand.nextInt(15);
}

public boolean typeString(String toType, boolean enter) throws InterruptedException {
for (char ch : toType.toCharArray()) {
kb.typeKey(ch);
sleep(rand(minMS, maxMS, msPC));
}

if (enter) {
pressEnter();
}

return true;
}

public boolean typeCharacter(String character, boolean enter) throws InterruptedException {
kb.typeKey(character.toCharArray()[0]);
sleep(rand(minMS, maxMS, msPC));

if (enter) {
pressEnter();
}

return true;
}

public boolean typeInteger(int integer, boolean enter) throws InterruptedException {
kb.typeKey(Character.forDigit(integer, 10));
sleep(rand(minMS, maxMS, msPC));

if (enter) {
pressEnter();
}

return true;
}

public boolean pressEnter() {
kb.typeKey((char)13);
kb.typeKey((char)10);
return true;
}

public int rand(int min, int max, int mean) { //Edited slightly; in a normal distribution, mean = mode = median = midpoint of graph
int n;
//int mean = (min + max) / 2;
int std = (max - mean) / 3;
Random r = new Random();

do {
double val = r.nextGaussian() * std + mean;
n = (int) Math.round(val);
} while (n < min || n > max);

return n;
}

public void sleep(int t) throws InterruptedException {
Script.sleep(t);
}

}

Usage example:

SmartKeyboard sk = new SmartKeyboard(this, 60); //60 words per minute
if (sk.typeString("The quick brown fox jumped over the lazy dog", true, true)) { //Third parameter to true -> enables typos
	log("Typed the string and pressed enter!");
}

if (sk.typeCharacter("g")) {
	log("Typed the character 'g'");
}

if (sk.typeInteger(4)) {
	log("Typed the number 4!");
}
sk.typoConstant = 10000; //Default 100000; lower = more likely to cause a typo; equation ((typoConstant / (words per minute * 10))+ rand.nextInt(6))

If there are any problems with this, let me know. Jagex may be smart, but we're smarter.

 

Proof of typos:

fed614e6aed00d7145319d5171ed04b9.png (set at 125wpm; original text "The quick brown fox jumped over the lazy dog the quick brown")

 

Feel free to use the SmartKeyboard class however you want, but credit is always nice biggrin.png

Edited by Bobrocket
  • Like 9
Link to comment
Share on other sites

Looks pretty nice smile.png

 

Inb4 make and correct typos doge.png

I was thinking about typos. What I'm going to do is make a little keychar map with nested arrays (for example, "a" typos could be "q", "s", "z") and then have a chance to see and correct it before typing (pressing backspace x amount of times and then pressing the correct key) or simply not noticing and then in a new message doing the classic "word*".

 

Edit: the equation for a random typo could just be (100000 / (wordsPM * 10) - rand.nextInt(5))? This way it still has a degree of randomness, but it still scales nicely with the words per minute factor (ofc you're not going to make many or any typos at 1wpm but you will at 120wpm)

 

Edit 2: working typos!

fed614e6aed00d7145319d5171ed04b9.png

Set at 125wpm in the example, with the original text "The quick brown fox jumped over the lazy dog the quick brown".

Currently, there is a 33% chance that the controller will actually fix the typo. You can change this in the typeString method (where it says if (typos && rand.nextInt(2) == 1 ) {)

 

Good luck everyone, and happy botting :D

Edited by Bobrocket
  • Like 1
Link to comment
Share on other sites

I was thinking about typos. What I'm going to do is make a little keychar map with nested arrays (for example, "a" typos could be "q", "s", "z") and then have a chance to see and correct it before typing (pressing backspace x amount of times and then pressing the correct key) or simply not noticing and then in a new message doing the classic "word*".

 

Edit: the equation for a random typo could just be (100000 / (wordsPM * 10) - rand.nextInt(5))? This way it still has a degree of randomness, but it still scales nicely with the words per minute factor (ofc you're not going to make many or any typos at 1wpm but you will at 120wpm)

 

Edit 2: working typos!

fed614e6aed00d7145319d5171ed04b9.png

Set at 125wpm in the example, with the original text "The quick brown fox jumped over the lazy dog the quick brown".

Currently, there is a 33% chance that the controller will actually fix the typo. You can change this in the typeString method (where it says if (typos && rand.nextInt(2) == 1 ) {)

 

Good luck everyone, and happy botting biggrin.png

 

Have my babies, sir

 

  • Like 1
Link to comment
Share on other sites

  • 8 months later...
  • 4 weeks later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...