Created
October 29, 2015 11:00
-
-
Save PseudoSky/601190fe6e8c1cbe0587 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.Arrays; | |
import java.util.Collections; | |
import android.view.MotionEvent; | |
import java.lang.reflect.Method; | |
class Gestures { | |
int maxOffset, minLength,st,et,tOff; | |
String functionName; | |
PVector startPos, endPos; | |
PApplet pApp; | |
Method[] m; | |
Gestures(int minimum,int offSet,int timeOffset,PApplet theApplet) { | |
m=new Method[4]; | |
pApp = theApplet; | |
maxOffset=offSet; //number pixels you are allowed to travel off the axis and still being counted as a swipe | |
minLength=minimum; // number of pixels you need to move your finger to count as a swipe | |
tOff=timeOffset; | |
} | |
// where did our motion start | |
void setStartPos(PVector pos) { | |
startPos=pos; | |
} | |
// where did our motion start | |
void setStartTime(int t) { | |
st=t; | |
} | |
void setEndTime(int t) { | |
et=t; | |
} | |
// where did it end and also call to check if it was a valid swipe | |
void setEndPos(PVector pos) { | |
endPos=pos; | |
checkSwipe(); | |
endPos=new PVector(); | |
startPos=new PVector(); | |
} | |
// check if it is a valid swipe that has been performed and if soperformthe attached function | |
void checkSwipe() { | |
print(et-st); | |
if (et-st< tOff){ | |
if (abs(startPos.x-endPos.x)>minLength && abs(startPos.y-endPos.y) < maxOffset) { | |
if (startPos.x < endPos.x) { | |
performAction(2); // a swipe right | |
return; | |
} | |
else { | |
performAction(0); // a swipe left | |
return; | |
} | |
} | |
else { | |
if (abs(startPos.y-endPos.y)>minLength && abs(startPos.x-endPos.x) < maxOffset) { | |
if (startPos.y < endPos.y) { | |
performAction(3); // a swipe downwards | |
return; | |
} | |
else { | |
performAction(1); // a swipe upwards | |
return; | |
} | |
} | |
} | |
} | |
epx=endPos.x; | |
epy=endPos.y; | |
print("mouseX: " + mouseX+" mouseY: "+mouseY+"\n"); | |
if (didMouseClick(0, 200, 215, 400)) //check if click occured in letter area | |
{ | |
currentLetter = 'a'; | |
}else if (didMouseClick(200+15, 200, 8, 400)){ | |
currentLetter ='b'; | |
}else if (didMouseClick(200+23, 200, 10, 400)){ | |
currentLetter ='c'; | |
}else if (didMouseClick(200+33, 200, 10, 400)){ | |
currentLetter ='d'; | |
}else if (didMouseClick(200+43, 200, 14, 400)){ | |
currentLetter ='e'; | |
}else if (didMouseClick(200+57, 200, 16, 400)){ | |
currentLetter ='f'; | |
}else if (didMouseClick(200+73, 200, 19, 400)){ | |
currentLetter ='g'; | |
}else if (didMouseClick(200+92, 200, 19, 400)){ | |
currentLetter ='h'; | |
}else if (didMouseClick(200+113, 200, 23, 400)){ | |
currentLetter ='i'; | |
}else if (didMouseClick(200+136, 200, 20, 400)){ | |
currentLetter ='j'; | |
}else if (didMouseClick(200+156, 200, 29, 400)){ | |
currentLetter ='k'; | |
}else if (didMouseClick(200+185, 200, 20, 400)){ | |
currentLetter ='l'; | |
}else if (didMouseClick(200+205, 200, 15, 400)){ | |
currentLetter ='m'; | |
}else if (didMouseClick(200+236, 200, 21, 400)){ | |
currentLetter ='n'; | |
}else if (didMouseClick(200+258, 200, 22, 400)){ | |
currentLetter ='o'; | |
}else if (didMouseClick(200+283, 200, 25, 400)){ | |
currentLetter ='p'; | |
}else if (didMouseClick(200+307, 200, 24, 400)){ | |
currentLetter ='q'; | |
}else if (didMouseClick(200+328, 200, 22, 400)){ | |
currentLetter ='r'; | |
}else if (didMouseClick(200+350, 200, 20, 400)){ | |
currentLetter ='s'; | |
}else if (didMouseClick(200+370, 200, 14, 400)){ | |
currentLetter ='t'; | |
}else if (didMouseClick(200+384, 200, 15, 400)){ | |
currentLetter ='u'; | |
}else if (didMouseClick(200+399, 200, 11, 400)){ | |
currentLetter ='v'; | |
}else if (didMouseClick(200+410, 200, 9, 400)){ | |
currentLetter ='w'; | |
}else if (didMouseClick(200+419, 200, 6, 400)){ | |
currentLetter ='x'; | |
}else if (didMouseClick(200+425, 200, 7, 400)){ | |
currentLetter ='y'; | |
}else if (didMouseClick(200+432, 200, 222, 400)){ | |
currentLetter ='z'; | |
} | |
currentTyped+=currentLetter; | |
//You are allowed to have a next button outside the 2" area | |
if (didMouseClick(800, 00, 200, 200)) //check if click is in next button | |
{ | |
nextTrial(); //if so, advance to next trial | |
} | |
} | |
// call the function that we have defined with setAction | |
void performAction(int direction) { | |
if (m[direction] == null) | |
return; | |
try { | |
m[direction].invoke(pApp); | |
} | |
catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
// define a function that should get called when the different swipes is done | |
void setAction(int direction, String method) { | |
if (method != null && !method.equals("")) { | |
try { | |
m[direction] = pApp.getClass().getMethod(method); | |
} | |
catch (SecurityException e) { | |
e.printStackTrace(); | |
} | |
catch (NoSuchMethodException e) { | |
e.printStackTrace(); | |
} | |
} | |
} | |
// attach a function to a left swipe | |
void setSwipeLeft(String _funcName) { | |
setAction(0, _funcName); | |
} | |
void setSwipeUp(String _funcName) { | |
setAction(1, _funcName); | |
} | |
void setSwipeRight(String _funcName) { | |
setAction(2, _funcName); | |
} | |
void setSwipeDown(String _funcName) { | |
setAction(3, _funcName); | |
} | |
} | |
// android touch event. | |
public boolean surfaceTouchEvent(MotionEvent event) { | |
// check what that was triggered | |
switch(event.getAction()) { | |
case MotionEvent.ACTION_DOWN: // ACTION_DOWN means we put our finger down on the screen | |
g.setStartTime(millis()); | |
g.setStartPos(new PVector(event.getX(), event.getY())); // set our start position | |
break; | |
case MotionEvent.ACTION_UP: // ACTION_UP means we pulled our finger away from the screen | |
g.setEndTime(millis()); | |
g.setEndPos(new PVector(event.getX(), event.getY())); // set our end position of the gesture and calculate if it was a valid one | |
break; | |
} | |
return super.surfaceTouchEvent(event); | |
} | |
// function that is called when we areswipingupwards | |
void swipeUp() { | |
println("a swipe up"); | |
println("a swipe right"); | |
currentTyped = currentTyped+" "; | |
} | |
void swipeDown() { | |
println("a swipe down"); | |
println("a swipe left"); | |
if(currentTyped.length()>0)currentTyped = currentTyped.substring(0,currentTyped.length()-1); | |
} | |
void swipeLeft() { | |
println("a swipe left"); | |
if(currentTyped.length()>0)currentTyped = currentTyped.substring(0,currentTyped.length()-1); | |
} | |
void swipeRight() { | |
println("a swipe right"); | |
currentTyped = currentTyped+" "; | |
} | |
Gestures g; | |
float epy=0; | |
float epx=0; | |
String[] phrases; //contains all of the phrases | |
int totalTrialNum = 4; //the total number of phrases to be tested - set this low for testing. Might be ~10 for the real bakeoff! | |
int currTrialNum = 0; // the current trial number (indexes into trials array above) | |
float startTime = 0; // time starts when the first letter is entered | |
float finishTime = 0; // records the time of when the final trial ends | |
float lastTime = 0; //the timestamp of when the last trial was completed | |
float lettersEnteredTotal = 0; //a running total of the number of letters the user has entered (need this for final WPM computation) | |
float lettersExpectedTotal = 0; //a running total of the number of letters expected (correct phrases) | |
float errorsTotal = 0; //a running total of the number of errors (when hitting next) | |
String currentPhrase = ""; //the current target phrase | |
String currentTyped = ""; //what the user has typed so far | |
final int DPIofYourDeviceScreen = 441; //you will need to look up the DPI or PPI of your device to make sure you get the right scale!! | |
//http://en.wikipedia.org/wiki/List_of_displays_by_pixel_density | |
final float sizeOfInputArea = DPIofYourDeviceScreen*1; //aka, 1.0 inches square! | |
boolean firstClick = false; | |
//Variables for my silly implementation. You can delete this: | |
char currentLetter = 'a'; | |
char selectedLetter = 'a'; | |
//You can modify anything in here. This is just a basic implementation. | |
void setup() | |
{ | |
g=new Gestures(70,100,115,this); // iniate the gesture object first value is minimum swipelengthin pixel and second is the diagonal offset allowed | |
g.setSwipeUp("swipeUp"); // attach the function called swipeUp to the gesture ofswipingupwards | |
g.setSwipeDown("swipeDown"); // attach the function called swipeDown to the gesture ofswipingdownwards | |
g.setSwipeLeft("swipeLeft"); // attach the function called swipeLeft to the gesture ofswipingleft | |
g.setSwipeRight("swipeRight"); | |
phrases = loadStrings("phrases2.txt"); //load the phrase set into memory | |
Collections.shuffle(Arrays.asList(phrases)); //randomize the order of the phrases | |
orientation(PORTRAIT); //can also be LANDSCAPE -- sets orientation on android device | |
size(1000, 1000); //Sets the size of the app. You may want to modify this to your device. Many phones today are 1080 wide by 1920 tall. | |
textFont(createFont("Arial", 24)); //set the font to arial 24 | |
noStroke(); //my code doesn't use any strokes. | |
} | |
//You can modify anything in here. This is just a basic implementation. | |
void draw() | |
{ | |
background(0); //clear background | |
// image(watch,-200,200); | |
fill(100); | |
rect(200, 200, sizeOfInputArea, sizeOfInputArea); //input area should be 2" by 2" | |
if (finishTime!=0) | |
{ | |
fill(255); | |
textAlign(CENTER); | |
text("Finished", 280, 150); | |
return; | |
} | |
if (startTime==0 & !mousePressed) | |
{ | |
fill(255); | |
textAlign(CENTER); | |
text("Click to start time!", 280, 150); //display this messsage until the user clicks! | |
} | |
if (startTime==0 & mousePressed) | |
{ | |
nextTrial(); //start the trials! | |
firstClick = true; | |
} | |
if (startTime!=0) | |
{ | |
//you will need something like the next 10 lines in your code. Output does not have to be within the 2 inch area! | |
textAlign(LEFT); //align the text left | |
fill(128); | |
textSize(20); | |
text("Phrase " + (currTrialNum+1) + " of " + totalTrialNum, 70, 50); //draw the trial count | |
fill(255); | |
textSize(20); | |
text("Target: " + currentPhrase, 70, 100); //draw the target string | |
text("Entered: " + currentTyped, 70, 140); //draw what the user has entered thus far | |
fill(255, 0, 0); | |
rect(800, 00, 200, 200); //drag next button | |
fill(255); | |
textSize(20); | |
text("NEXT > ", 850, 100); //draw next label | |
//my draw code | |
textAlign(CENTER); | |
if (didMouseClick(0, 200, 215, 400)) //check if click occured in letter area | |
{ | |
selectedLetter = 'a'; | |
//if (currentLetter=='_') //if underscore, consider that a space bar | |
// currentTyped+=" "; | |
//else if (currentLetter=='`' & currentTyped.length()>0) //if `, treat that as a delete command | |
// currentTyped = currentTyped.substring(0, currentTyped.length()-1); | |
//else if (currentLetter!='`') //if not any of the above cases, add the current letter to the typed string | |
// currentTyped+=currentLetter; | |
}else if (didMouseClick(200+15, 200, 8, 400)){ | |
selectedLetter ='b'; | |
}else if (didMouseClick(200+23, 200, 10, 400)){ | |
selectedLetter ='c'; | |
}else if (didMouseClick(200+33, 200, 10, 400)){ | |
selectedLetter ='d'; | |
}else if (didMouseClick(200+43, 200, 14, 400)){ | |
selectedLetter ='e'; | |
}else if (didMouseClick(200+57, 200, 16, 400)){ | |
selectedLetter ='f'; | |
}else if (didMouseClick(200+73, 200, 19, 400)){ | |
selectedLetter ='g'; | |
}else if (didMouseClick(200+92, 200, 19, 400)){ | |
selectedLetter ='h'; | |
}else if (didMouseClick(200+113, 200, 23, 400)){ | |
selectedLetter ='i'; | |
}else if (didMouseClick(200+136, 200, 20, 400)){ | |
selectedLetter ='j'; | |
}else if (didMouseClick(200+156, 200, 29, 400)){ | |
selectedLetter ='k'; | |
}else if (didMouseClick(200+185, 200, 20, 400)){ | |
selectedLetter ='l'; | |
}else if (didMouseClick(200+205, 200, 15, 400)){ | |
selectedLetter ='m'; | |
}else if (didMouseClick(200+236, 200, 21, 400)){ | |
selectedLetter ='n'; | |
}else if (didMouseClick(200+258, 200, 22, 400)){ | |
selectedLetter ='o'; | |
}else if (didMouseClick(200+283, 200, 25, 400)){ | |
selectedLetter ='p'; | |
}else if (didMouseClick(200+307, 200, 24, 400)){ | |
selectedLetter ='q'; | |
}else if (didMouseClick(200+328, 200, 22, 400)){ | |
selectedLetter ='r'; | |
}else if (didMouseClick(200+350, 200, 20, 400)){ | |
selectedLetter ='s'; | |
}else if (didMouseClick(200+370, 200, 14, 400)){ | |
selectedLetter ='t'; | |
}else if (didMouseClick(200+384, 200, 15, 400)){ | |
selectedLetter ='u'; | |
}else if (didMouseClick(200+399, 200, 11, 400)){ | |
selectedLetter ='v'; | |
}else if (didMouseClick(200+410, 200, 9, 400)){ | |
selectedLetter ='w'; | |
}else if (didMouseClick(200+419, 200, 6, 400)){ | |
selectedLetter ='x'; | |
}else if (didMouseClick(200+425, 200, 7, 400)){ | |
selectedLetter ='y'; | |
}else if (didMouseClick(200+432, 200, 422, 400)){ | |
selectedLetter ='z'; | |
} | |
String[] names = {"z","y","x","w","v","u","t","s","r","q","p","o","n","m","l","k","j","i","h","g","f","e","d","c","b","a"}; | |
float delta = -PI / names.length; | |
int radius = names.length *8; | |
for(int i = 0; i<names.length; i++) { | |
if ((""+selectedLetter).equals(names[i])){ | |
fill(0,250,0); | |
textSize(50); | |
//fill(209); | |
//ellipse(width/2+radius * cos(i* delta)-80, height/2+radius * sin(i*delta)-30, 60,60); | |
} | |
else{ | |
fill(0,0,0); | |
textSize(18); | |
} | |
text(names[i],width/2+radius * cos(i* delta)-80, height/2+radius * sin(i*delta) -30); | |
} | |
fill(0,250,0); | |
textSize(100); | |
text("" + selectedLetter, 200+sizeOfInputArea/2, 200+sizeOfInputArea/3); //draw current letter | |
} | |
} | |
boolean didMouseClick(float x, float y, float w, float h) //simple function to do hit testing | |
{ | |
return (mouseX > x && mouseX<x+w && mouseY>y && mouseY<y+h); //check to see if it is in button bounds | |
} | |
void mouseReleased() | |
{ | |
if(firstClick){ | |
firstClick = false; | |
return; | |
} | |
print("mouseX:" + mouseX+" mouseY:"+mouseY+"\n"); | |
//print("width:" + width); | |
//print((atan((mouseY*1.0)/(1.0*mouseX) )*180.0)/PI+"\n"); | |
//if (didMouseClick(200, 200+sizeOfInputArea/2, sizeOfInputArea/2, sizeOfInputArea/2)) //check if click in left button | |
//{ | |
// currentLetter --; | |
// if (currentLetter<'_') //wrap around to z | |
// currentLetter = 'z'; | |
//} | |
//if (didMouseClick(200+sizeOfInputArea/2, 200+sizeOfInputArea/2, sizeOfInputArea/2, sizeOfInputArea/2)) //check if click in right button | |
//{ | |
// currentLetter ++; | |
// if (currentLetter>'z') //wrap back to space (aka underscore) | |
// currentLetter = '_'; | |
//} | |
//if (didMouseClick(200, 200, sizeOfInputArea, sizeOfInputArea/2)) //check if click occured in letter area | |
//{ | |
if (didMouseClick(0, 200, 215, 400)) //check if click occured in letter area | |
{ | |
currentLetter = 'a'; | |
//if (currentLetter=='_') //if underscore, consider that a space bar | |
// currentTyped+=" "; | |
//else if (currentLetter=='`' & currentTyped.length()>0) //if `, treat that as a delete command | |
// currentTyped = currentTyped.substring(0, currentTyped.length()-1); | |
//else if (currentLetter!='`') //if not any of the above cases, add the current letter to the typed string | |
// currentTyped+=currentLetter; | |
}else if (didMouseClick(200+15, 200, 8, 400)){ | |
currentLetter ='b'; | |
}else if (didMouseClick(200+23, 200, 10, 400)){ | |
currentLetter ='c'; | |
}else if (didMouseClick(200+33, 200, 10, 400)){ | |
currentLetter ='d'; | |
}else if (didMouseClick(200+43, 200, 14, 400)){ | |
currentLetter ='e'; | |
}else if (didMouseClick(200+57, 200, 16, 400)){ | |
currentLetter ='f'; | |
}else if (didMouseClick(200+73, 200, 19, 400)){ | |
currentLetter ='g'; | |
}else if (didMouseClick(200+92, 200, 19, 400)){ | |
currentLetter ='h'; | |
}else if (didMouseClick(200+113, 200, 23, 400)){ | |
currentLetter ='i'; | |
}else if (didMouseClick(200+136, 200, 20, 400)){ | |
currentLetter ='j'; | |
}else if (didMouseClick(200+156, 200, 29, 400)){ | |
currentLetter ='k'; | |
}else if (didMouseClick(200+185, 200, 20, 400)){ | |
currentLetter ='l'; | |
}else if (didMouseClick(200+205, 200, 15, 400)){ | |
currentLetter ='m'; | |
}else if (didMouseClick(200+236, 200, 21, 400)){ | |
currentLetter ='n'; | |
}else if (didMouseClick(200+258, 200, 22, 400)){ | |
currentLetter ='o'; | |
}else if (didMouseClick(200+283, 200, 25, 400)){ | |
currentLetter ='p'; | |
}else if (didMouseClick(200+307, 200, 24, 400)){ | |
currentLetter ='q'; | |
}else if (didMouseClick(200+328, 200, 22, 400)){ | |
currentLetter ='r'; | |
}else if (didMouseClick(200+350, 200, 20, 400)){ | |
currentLetter ='s'; | |
}else if (didMouseClick(200+370, 200, 14, 400)){ | |
currentLetter ='t'; | |
}else if (didMouseClick(200+384, 200, 15, 400)){ | |
currentLetter ='u'; | |
}else if (didMouseClick(200+399, 200, 11, 400)){ | |
currentLetter ='v'; | |
}else if (didMouseClick(200+410, 200, 9, 400)){ | |
currentLetter ='w'; | |
}else if (didMouseClick(200+419, 200, 6, 400)){ | |
currentLetter ='x'; | |
}else if (didMouseClick(200+425, 200, 7, 400)){ | |
currentLetter ='y'; | |
}else if (didMouseClick(200+432, 200, 522, 400)){ | |
currentLetter ='z'; | |
} | |
} | |
void nextTrial() | |
{ | |
if (currTrialNum >= totalTrialNum) //check to see if experiment is done | |
return; //if so, just return | |
if (startTime!=0 && finishTime==0) //in the middle of trials | |
{ | |
System.out.println("=================="); | |
System.out.println("Phrase " + (currTrialNum+1) + " of " + totalTrialNum); //output | |
System.out.println("Target phrase: " + currentPhrase); //output | |
System.out.println("Phrase length: " + currentPhrase.length()); //output | |
System.out.println("User typed: " + currentTyped); //output | |
System.out.println("User typed length: " + currentTyped.length()); //output | |
System.out.println("Number of errors: " + computeLevenshteinDistance(currentTyped.trim(), currentPhrase.trim())); //trim whitespace and compute errors | |
System.out.println("Time taken on this trial: " + (millis()-lastTime)); //output | |
System.out.println("Time taken since beginning: " + (millis()-startTime)); //output | |
System.out.println("=================="); | |
lettersExpectedTotal+=currentPhrase.length(); | |
lettersEnteredTotal+=currentTyped.length(); | |
errorsTotal+=computeLevenshteinDistance(currentTyped.trim(), currentPhrase.trim()); | |
} | |
if (currTrialNum == totalTrialNum-1) //check to see if experiment just finished | |
{ | |
finishTime = millis(); | |
System.out.println("=================="); | |
System.out.println("Trials complete!"); //output | |
System.out.println("Total time taken: " + (finishTime - startTime)); //output | |
System.out.println("Total letters entered: " + lettersEnteredTotal); //output | |
System.out.println("Total letters expected: " + lettersExpectedTotal); //output | |
System.out.println("Total errors entered: " + errorsTotal); //output | |
System.out.println("WPM: " + (lettersEnteredTotal/5.0f)/((finishTime - startTime)/60000f)); //output | |
System.out.println("=================="); | |
currTrialNum++; //increment by one so this mesage only appears once when all trials are done | |
return; | |
} | |
if (startTime==0) //first trial starting now | |
{ | |
System.out.println("Trials beginning! Starting timer..."); //output we're done | |
startTime = millis(); //start the timer! | |
} | |
else | |
{ | |
currTrialNum++; //increment trial number | |
} | |
lastTime = millis(); //record the time of when this trial ended | |
currentTyped = ""; //clear what is currently typed preparing for next trial | |
currentPhrase = phrases[currTrialNum]; // load the next phrase! | |
//currentPhrase = "abc"; // uncomment this to override the test phrase (useful for debugging) | |
} | |
//=========SHOULD NOT NEED TO TOUCH THIS METHOD AT ALL!============== | |
int computeLevenshteinDistance(String phrase1, String phrase2) //this computers error between two strings | |
{ | |
int[][] distance = new int[phrase1.length() + 1][phrase2.length() + 1]; | |
for (int i = 0; i <= phrase1.length(); i++) | |
distance[i][0] = i; | |
for (int j = 1; j <= phrase2.length(); j++) | |
distance[0][j] = j; | |
for (int i = 1; i <= phrase1.length(); i++) | |
for (int j = 1; j <= phrase2.length(); j++) | |
distance[i][j] = min(min(distance[i - 1][j] + 1, distance[i][j - 1] + 1), distance[i - 1][j - 1] + ((phrase1.charAt(i - 1) == phrase2.charAt(j - 1)) ? 0 : 1)); | |
return distance[phrase1.length()][phrase2.length()]; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment