Introduction
A while back I made an app that tracks my spending
and after a while I realized that my tag system was lacking because I had multiple tags that were similar but letter case were different or I had a missing letter. That made my statistical evaluation of my spending go nuts.
I was promoted to make a solution and from that the "word-difference-calculator" was born.
Evaluating Missed Letter Cases
When typing on PC first letter is small by default, and I like my tags that way, but on mobile phone first letter is upper case by default and that is annoying.
So I addressed that problem with following code:
if (letter1 !== letter2) {
if (letter1.toLowerCase() === letter2.toLowerCase()) {
weightedDifference += caseWeight; // case difference
}
}
Evaluating Missed or Added Letter
Sometime while I type i forget to type one letter so that case must be covered, I did it using word horizontal search for missing letter.
Code goes something like this:
get(first, second, index){
look for letter first[index] in second[min delta index]
return min delta index
}
When that is done we keep the returned index so we don't penalize one missing or added letter for all remaining letters.
Keyboard misses
While typing on keyboard I frequently miss my keys so that was also accounted by:
const rowDirection = firstLetter.row - secondLetter.row;
const rowDiff = Math.abs(rowDirection);
const rowAdjust = rowDirection * 0.5;
const colDiff = Math.abs(pos1.col + rowAdjust - pos2.col);
return rowDiff + colDiff;
So now I can fat finger my keyboard I much as I want and there was not a problem in suggesting right tags from the list that is already defined.
Adding Tests with Realistic Scenarios
How to test something like this, well I tested it partial and in general:
Partial test would be:
// Test for distance on eyboard
assert.equal(getKeyboardDistance('a', 'a'), 0)
assert.equal(getKeyboardDistance('a', 'A'), 0)
assert.equal(getKeyboardDistance('a', 's'), 1)
assert.equal(getKeyboardDistance('a', 'd'), 2)
assert.equal(getKeyboardDistance('b', 't'), 3)
assert.equal(getKeyboardDistance('q', 'm'), 9)
Whole test would be:
for(let [first, second, expect] of tests){
let val = computeWordDifference(first, second)
assert.ok(Math.abs(val- expect)<0.03,first+' '+second + ' e: '+ expect+' v: '+val)
}
Integration into an Application for Tag Recognition
When I got to the app integration, it was easy, I just searched all the tags on every key, if any of the tags is similar I would showed it.
There were few unexpected behaviors that required some work so I had to make an idea of the problem, while classical method would not give results I turned to some unorthodox approaches.
Large-Scale Testing with 4000 Words
A while back I made an app that combines text typing game with tetris game so I had a pretty good word library and I figured that I can test every word with another and find the similar ones or the ones that brake my code. It gave me some results that looked like Gaussian bell function:
I learned how to make this graph but I learned nothing about my project, so I wanted to see more.
Graphical Representation
I wanted to see every relation of every word to another in 2d, I had an physics/game engine laying around that is easily extendable since it is ECS system, and I have a chain system implemented for testing chain mold effect:
On the other hand had perfect interface with new interaction function reedy to be employed:
The force function (x-1)*(x^-1)
in my system, and it says if something is too close <1 then push it hard, if something is too far then try to attract it slightly.
After just few hours I had something that I can play with, it was interesting to watch, but it was not enough. I added one input and my word from input would join all the words that were competing to be at the right spot in relation to its neighbors.
The end result:
Conclusion
Sometimes you just don't know where one project could lead. "word-difference-calculator" was part of one project, then it become a toy and a headache, then it inspired me to do some data science in the end it got its own game.
Final Thoughts
I feel very lucky that things panned out in this way, many project were touched in this journey, I had what was needed because I choose infrastructure and stick to it trough 10+ projects and 2+ years.
Thank you for reading!
Top comments (0)