DEV Community

Cover image for Tag Recommendation to Game Design: A True Story of Word-Difference-Calculator
Slobi
Slobi

Posted on

Tag Recommendation to Game Design: A True Story of Word-Difference-Calculator

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.

Old app preview

I was promoted to make a solution and from that the "word-difference-calculator" was born.

Tag editor

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
    }
}
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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)
}
Enter fullscreen mode Exit fullscreen mode

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:

Gaussian bell function off word differnce

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:

Chain mould
Interactive chain mold sim

On the other hand had perfect interface with new interaction function reedy to be employed:

Words competing for place
Interactive math plotter

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:

Grouping of the words

Interactive words 2d

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)