Created
August 13, 2010 04:46
-
-
Save silverjam/522307 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
abstract class Classification { | |
double frequency() | |
boolean isComplete() | |
boolean isPartial() | |
... | |
class Complete extends Classification ... | |
class Partial extends Classification ... | |
class Partialish extends Classification ... | |
class Nothing extends Classification ... | |
class WordSet { | |
void populate(String filename) | |
Classification classify(String word) | |
... |
This file contains hidden or 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
class SwipeState | |
{ | |
Keyboard _keyboard; | |
WordSet _wordset; | |
KeyHitCollector _keyCollector; | |
... | |
void mouseDragged() { ... } | |
void mouseReleased() { ... } | |
void draw() { ... } | |
} |
This file contains hidden or 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
ArrayList<String> words() { | |
HashMap<String, Double> complete = new HashMap(); | |
ArrayList<String> prefixes = new ArrayList(); | |
ArrayList<String> ls = new ArrayList(); | |
if ( _keys.isEmpty() ) | |
return ls; | |
prefixes.add(_keys.get(0)); | |
Classification klass = _wordset.classify(prefixes.get(0)); | |
if ( klass.isComplete() ) | |
complete.put(prefixes.get(0), klass.frequency()); | |
for (int i = 1; i < _keys.size(); i++) | |
{ | |
String ch = _keys.get(i); | |
ArrayList<String> newPrefixes = new ArrayList(); | |
for (int j = 0; j < prefixes.size(); j++) { | |
String prefix = prefixes.get(j) + ch; | |
klass = _wordset.classify(prefix); | |
if ( klass.isComplete() ) | |
complete.put(prefix, klass.frequency()); | |
if ( klass.isPartial() ) | |
newPrefixes.add(prefix); | |
} | |
prefixes.addAll(newPrefixes); | |
} | |
ls = new ArrayList(complete.keySet()); | |
Collections.sort(ls, new Comparator() { /* Sort by length */ }); | |
while ( ls.size() > MAX_WORD_COUNT ) | |
ls.remove(ls.size() - 1); | |
Collections.sort(ls, new FreqCmp(complete)); | |
return ls; | |
} |
This file contains hidden or 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
// Data: http://drop.io/vnb0bwj | |
PFont font; | |
SwipeState state; | |
void setup() | |
{ | |
fill(#ffffff); | |
stroke(#ffffff); | |
size(450, 400); | |
frameRate(60); | |
state = new SwipeState(); | |
font = loadFont("AharoniBold-20.vlw"); | |
textFont(font); | |
background(0); | |
state.draw(); | |
} | |
void mouseReleased() | |
{ | |
state.mouseReleased(); | |
} | |
void mouseDragged() | |
{ | |
state.mouseDragged(); | |
} | |
void draw() { } | |
class SwipeState | |
{ | |
Keyboard _keyboard; | |
WordSet _wordset; | |
KeyHitCollector _keyCollector; | |
int _prevMouseX = -1; | |
int _prevMouseY = -1; | |
SwipeState() | |
{ | |
_keyboard = new Keyboard(30, 330); | |
_wordset = new WordSet(); | |
_wordset.populate("words.txt"); | |
_wordset.populate("freq.txt"); | |
_keyCollector = new KeyHitCollector(_keyboard, _wordset); | |
} | |
void mouseDragged() | |
{ | |
pushStyle(); | |
fill(#ff0000); | |
stroke(#ff0000); | |
strokeWeight(3); | |
if ( _prevMouseX == -1 ) | |
point(mouseX, mouseY); | |
else | |
line(_prevMouseX, _prevMouseY, mouseX, mouseY); | |
_prevMouseX = mouseX; | |
_prevMouseY = mouseY; | |
popStyle(); | |
_keyCollector.detect(mouseX, mouseY); | |
} | |
void mouseReleased() | |
{ | |
background(0); | |
fill(#ffffff); | |
stroke(#ffffff); | |
_prevMouseX = -1; | |
_prevMouseY = -1; | |
_keyboard.draw(); | |
int y = 30; | |
for ( String word : _keyCollector.words() ) | |
{ | |
text(word, 170, y); y += 20; | |
} | |
_keyCollector.reset(); | |
} | |
void draw() | |
{ | |
_keyboard.draw(); | |
} | |
} | |
final int MAX_WORD_COUNT = 12; | |
abstract class Classification | |
{ | |
double _freq; | |
Classification() { _freq = 0; } | |
Classification(double freq) { | |
//print(Double.toString(freq)); print(" "); | |
_freq = freq; | |
} | |
double frequency() { | |
//print(Double.toString(_freq)); print(" "); | |
return _freq; | |
} | |
boolean isComplete() { return false; } | |
boolean isPartial() { return false; } | |
} | |
class Complete extends Classification { | |
Complete(double freq) { super(freq); } | |
boolean isComplete() { return true; } | |
} | |
class Partial extends Classification { | |
boolean isPartial() { return true; } | |
} | |
class Partialish extends Classification { | |
Partialish(double freq) { super(freq); } | |
boolean isPartial() { return true; } | |
boolean isComplete() { return true; } | |
} | |
class Nothing extends Classification { | |
boolean isNothing() { return true; } | |
} | |
class WordSet | |
{ | |
HashMap<String, Classification> _map; | |
Partial _partial; | |
Nothing _nothing; | |
WordSet() | |
{ | |
_map = new HashMap(); | |
_partial = new Partial(); | |
_nothing = new Nothing(); | |
} | |
Classification exists(String s, Classification klass) | |
{ | |
Classification existing = _map.get(s); | |
if ( existing != null && existing.isComplete() ) | |
klass = new Partialish(existing.frequency()); | |
return klass; | |
} | |
void populate(String filename) | |
{ | |
String words[] = loadStrings(filename); | |
for(int i=0; i < words.length; i++) | |
{ | |
String word; | |
double freq = 0.0; | |
String[] parts = words[i].split(" ", 2); | |
word = parts[0].toUpperCase(); | |
if ( parts.length == 2 ) | |
{ | |
freq = Double.parseDouble(parts[0]); | |
word = parts[1].toUpperCase(); | |
} | |
for(int j=1; j < word.length(); j++) | |
{ | |
String partial = word.substring(0, j); | |
_map.put(partial, exists(partial, _partial)); | |
} | |
_map.put(word, new Complete(freq)); | |
} | |
} | |
Classification classify(String word) | |
{ | |
Classification klass = _map.get(word); | |
if ( klass == null ) | |
klass = _nothing; | |
//print(Double.toString(klass.frequency())); print(" "); | |
return klass; | |
} | |
} | |
class Key | |
{ | |
static final int _dx = 4, _dy = 16; | |
static final int _boxDx = 28, _boxDy = 20; | |
String _c; int _x, _y; | |
Key(String c, int x, int y) { _c = c; _x = x; _y = y; } | |
void draw() | |
{ | |
text(_c, _x, _y); | |
noFill(); | |
bezierRect(_x - _dx, _y - _dy, _boxDx, _boxDy, -2, -2); | |
} | |
int left() { return _x - _dx; } | |
int top() { return _y - _dy; } | |
int right() { return left() + _boxDx; } | |
int bottom() { return top() + _boxDy; } | |
String c() { return _c; } | |
boolean hit(int x, int y) | |
{ | |
return x > left() && x < right() && y > top() && y < bottom(); | |
} | |
} | |
class Keyboard | |
{ | |
static final String _row1 = "QWERTYUIOP[]\\"; | |
static final String _row2 = "ASDFGHJKL;'"; | |
static final String _row3 = "ZXCVBNM,./"; | |
static final int _keySpacing = 30, _rowSpacing = 25, | |
_2ndOffset = 15, _3rdOffset = _2ndOffset+10; | |
ArrayList<Key> _row1Keys; | |
ArrayList<Key> _row2Keys; | |
ArrayList<Key> _row3Keys; | |
int _x, _y; | |
void populate(String row, ArrayList ls, int x, int y) | |
{ | |
for (int i = 0; i < row.length(); i++) { | |
ls.add(new Key(row.substring(i, i+1), x, y)); | |
x += _keySpacing; | |
} | |
} | |
void drawRow(ArrayList<Key> row) | |
{ | |
for (int i = 0; i < row.size(); i++) { | |
Key k = row.get(i); | |
k.draw(); | |
} | |
} | |
Keyboard(int x, int y) | |
{ | |
_x = x; _y = y; | |
_row1Keys = new ArrayList(); | |
_row2Keys = new ArrayList(); | |
_row3Keys = new ArrayList(); | |
populate(_row1, _row1Keys, x, y); | |
populate(_row2, _row2Keys, x + _2ndOffset, y + _rowSpacing); | |
populate(_row3, _row3Keys, x + _3rdOffset, y + 2 * _rowSpacing); | |
} | |
Key rowHit(ArrayList<Key> row, int x, int y) | |
{ | |
for (int i = 0; i < row.size(); i++) { | |
Key k = row.get(i); | |
if ( k.hit(x, y) ) | |
return k; | |
} | |
return null; | |
} | |
Key hit(int x, int y) | |
{ | |
Key c = null; | |
c = rowHit(_row1Keys, x, y); | |
if ( c != null ) return c; | |
c = rowHit(_row2Keys, x, y); | |
if ( c != null ) return c; | |
c = rowHit(_row3Keys, x, y); | |
if ( c != null ) return c; | |
return null; | |
} | |
void draw() | |
{ | |
drawRow(_row1Keys); | |
drawRow(_row2Keys); | |
drawRow(_row3Keys); | |
} | |
} | |
class KeyHitCollector | |
{ | |
Key _lastKey; | |
Keyboard _keyboard; | |
WordSet _wordset; | |
ArrayList<String> _keys; | |
KeyHitCollector(Keyboard k, WordSet w) | |
{ | |
_keys = new ArrayList(); | |
_keyboard = k; | |
_wordset = w; | |
} | |
void reset() { _keys.clear(); } | |
void detect(int x, int y) | |
{ | |
Key k = _keyboard.hit(mouseX, mouseY); | |
if ( k != null && k != _lastKey ) { | |
_keys.add(k.c()); | |
} | |
_lastKey = k; | |
} | |
ArrayList<String> words() | |
{ | |
HashMap<String, Double> complete = new HashMap(); | |
ArrayList<String> prefixes = new ArrayList(); | |
ArrayList<String> ls = new ArrayList(); | |
if ( _keys.isEmpty() ) | |
return ls; | |
prefixes.add(_keys.get(0)); | |
Classification klass = _wordset.classify(prefixes.get(0)); | |
if ( klass.isComplete() ) | |
complete.put(prefixes.get(0), klass.frequency()); | |
for (int i = 1; i < _keys.size(); i++) | |
{ | |
String ch = _keys.get(i); | |
ArrayList<String> newPrefixes = new ArrayList(); | |
for (int j = 0; j < prefixes.size(); j++) | |
{ | |
String prefix = prefixes.get(j) + ch; | |
klass = _wordset.classify(prefix); | |
if ( klass.isComplete() ) | |
complete.put(prefix, klass.frequency()); | |
if ( klass.isPartial() ) | |
newPrefixes.add(prefix); | |
} | |
prefixes.addAll(newPrefixes); | |
} | |
ls = new ArrayList(complete.keySet()); | |
Collections.sort(ls, new Comparator() { | |
public int compare(Object o1, Object o2) | |
{ return -(((String)o1).length() - ((String)o2).length()); } | |
public boolean equals(Object o) { return false; } | |
}); | |
while ( ls.size() > MAX_WORD_COUNT ) | |
ls.remove(ls.size() - 1); | |
Collections.sort(ls, new FreqCmp(complete)); | |
return ls; | |
} | |
} | |
class FreqCmp implements Comparator | |
{ | |
HashMap<String, Double> _freqs; | |
FreqCmp(HashMap<String, Double> freqs) { _freqs = freqs; } | |
public int compare(Object o1, Object o2) | |
{ | |
double d = _freqs.get((String)o1) - _freqs.get((String)o2); | |
if ( d < 0 ) return 1; else if ( d > 0 ) return -1; | |
return 0; | |
} | |
public boolean equals(Object o) | |
{ return false; } | |
} | |
void bezierRect(float x, float y, float w, float h, float xr, float yr) | |
{ | |
float w2=w/2f, h2=h/2f, cx=x+w2, cy=y+h2; | |
beginShape(); | |
vertex(cx,cy-h2); | |
bezierVertex(cx+w2-xr, cy-h2, cx+w2, cy-h2+yr, cx+w2, cy); | |
bezierVertex(cx+w2, cy+h2-yr, cx+w2-xr, cy+h2, cx, cy+h2); | |
bezierVertex(cx-w2+xr, cy+h2, cx-w2, cy+h2-yr, cx-w2, cy); | |
bezierVertex(cx-w2, cy-h2+yr, cx-w2+xr, cy-h2, cx, cy-h2); | |
endShape(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment