 is from a touch typing competition and the guy called Sean has won the competition typing 124 words per minute. Can you touch type? Raise your hand if you can touch type. Keep your hand raised if when you touch type and you press the keys with the correct finger. Okay, almost everyone. Good job. I have a friend and I've noticed that when he is touch typing he is placing his right hand one row of set to the right. So he is index finger sitting on K letter and he is touch typing like that and then whenever he needs to press keys in the middle of Y, H and N he has to move his hand type those letters and move them back and I was starting to wonder if if there is a way to to tell people when they're learning to touch type on the early stage whether they're placing their fingers on the right keys. My name is Tetyana Dushonkivska and I'm here to share with you my journey on building a touch typing system. To build a system like that you need to go through a few steps. First you need to display text to type then you need to record the key press events from the keyboard. Also you need to record finger events somehow and you have to analyze those events and then as the result you need to show it to the user. Okay let's go through those steps and I would like to share with you the tools I have chosen to build such system. First display text. For that I've chosen a browser as I'm familiar how to work with other applications. To record key press events I'm using JavaScript. To record finger events I'm going to use Arduino a little bit of C program and the senses but I'll get to that later and to analyze events I'm going to use Alexia but how am I going to use it. When I first started to build this system which was on one of the hack events I was a variable hack event. My Alexia part was a Phoenix application which did lots of things which was great for the hack event and it worked but then when I got accepted for this talk I thought maybe it's not quite right maybe I should do better and I've learned how to do better when I joined the company I'm working for now Informatics. Informatics specializes in combining monitoring modeling and control of water supply networks with embedded computing and data management resulting in integrated solutions for resilient adaptive and calm networks. To put it simply we help water companies prevent leaks and extend life of the water pipes. So I've learned that this company a lot of good practices and in particular that it's good to structure your applications into different umbrella applications. So my structure looks like that I'm going to have the logic co-application which is going to be dealing with all of the matching results then I'm going to have the serial umbrella applications which are going to be dealing with getting all of the events from Arduino and passing them to the logic application and the Phoenix application which is going to be dealing with getting all of the key events and passing them to the logic application. And if you would notice on the slide how good that Phoenix looks like? This is my second attempt. First attempt in the cafe, when I didn't have internet, looked like that. I dare you not to look how the Phoenix looked like and try to draw it and maybe tweet it or something. I'll be quite interested to see if you could do it from the memory. The full architecture looks like that. And let's go down to implementation. First, we need to generate our umbrella project. Now with the crisis keynote, I know that it's easier to do it with a Phoenix umbrella application in place already. But I didn't know that, so I did it the long way. And then within our umbrella application structure, I could generate my first umbrella application, which is going to use Phoenix. And then we could talk about what Phoenix is going to do. So the goal for this part is whenever we load the browser, we are going to have a phaser sending the join message to the Phoenix channel. And the Phoenix channel returning OK. And then a phaser is going to render a start button just to tell our user that, OK, it's ready. This is how it looks like. And how do we implement it? It's not too hard. So we have our socket. We connect to it. Then we send message to the channel, join message. And when we receive OK, we just generate that message or button. But we don't have orbit channel. Well, OK, let's generate it. And we call it games lobby. OK, great. And then we are listening to games lobby message and joining. OK, great. That's done. So you could see here, when we load our browser, we get our start button. And we log in in our console that we joined the channel. And then whenever we press the start button, we have the message which we are going to type. So let's go to rendering the message. So from phaser, we are sending start game message to Phoenix channel. And the channel passing it through to the core. Core is our umbrella application, which is responsible for getting the events and passing them through. And core is going to accept the socket because it would need on a later stage to send back the result. And it needs a way to communicate with the Phoenix channel so it has to have the socket in. The next step is to get the text and pass it back to the channel. And channel passing it back to the phasing phasing, just rendering it on the screen. How do we implement it? JavaScript part is easy. Thanks to Keith, who looks quite tidy. So we destroyed our initial start button, then we pushed the message to the, send the message to the channel. And then we're listening in the Phoenix to that message and whenever we get it, then we're going to call our logic application and get back the text and pass it through to the phaser. Whenever we call our core application, we haven't created it yet. So it's time to do that. So we generate another umbrella application and within that umbrella application, we implement the init callback which is going to store a text in a state. And for now, we're just going to have an empty socket in it. And whenever we get our start game message, we are going to return back the text which we have in the state now and we are going to store the socket in the state so we could communicate to the Phoenix in the later stage. To be able to communicate from one umbrella application to another, we need to have some kind of dependencies. So we add our core application as a dependency of the web application. And the JavaScript is listening to the message and then it's rendering text to the screen. Great, the next step is to start sending the key events. The full looks like that. So we phaser listening for the key events. Whenever we get the event, it adds the ID for that event. So it's going to be an event ID. Then it passes through to the Phoenix channel, passes through to the core and then core delegating this message to the event handler. And the one handler is the guy who's going to do all of the work of defining whether it's matching or not. But we're going to get this little bit later. For now, let's just talk about how we send those messages. So this is similar, we just push the event to the channel with the particular message key. And within our channel, we are going to listen to that key message. And what we get is a key and ID, okay? And then we call our core application with those key and ID, just pass it in. And our core application collecting it, passing it through to the guy who is doing all of the hard work. And with this in place, we have one part of our architecture complete, the part which is sending messages. The other part is to send thing events. Okay, how do we do that? So when I come up to the challenge of finding the way to register with which finger you're pressing the key, I looked at various different technologies. One of them was looking at different software which is going to record the video and tell you what you're doing. But it was a little bit hard to determine whether you're actually pressing the key or not. Then I looked at lip motion, which was really fun, but it didn't quite work. And I looked at, then I went crazy and I thought, okay, what if I build a keyboard which is going to listen to the fingerprints? And then it'll tell you from the fingerprints which we can finger it and it's like, this is amazing, but I have to build a keyboard like that and I have to buy a bunch of senses, like they exist, but they're very hard to find when you're in China. And I just thought it's a little bit too crazy idea. So then I found a little bit easier solution. To build a senses, a precious senses which are going to be sitting on the fingertips and they would be doing all of the job and Arduino and CE are there to communicate and tell what those precious, to treat from those. How do we build those senses like that? So the sensor has to be small enough so it would go on a fingertip and it also has to be flexible so it feels nice on the finger. It is possible to build a sensor like that. All you need is Velostat, which is a material which get conductive when you press on it and if you place it between two conductive materials which are also flexible, then you get the sensor. Conductive material, this is something pretty exciting. I didn't know that you could have electronics which you could sell but you could actually have conductive materials, conductive threads, you could sew your pieces which is blind-blowing. So this is the sensor. I have placed it next to my finger so this is how tiny it is and if we put this Velostat between two conductive materials then that's our sensor, it's ready to go. But we need to plug it into Arduino in order to test it. So here we go, we plug it in. The way we plug it in one end should go to the power and then another one should go to one of the analog ports on Arduino and also should go to the ground so it's all working as expected. And we need to write a little C program for Arduino to tell that we are going to listen to analog port, specific one and that we in this case we're just taking all of the signals which are coming from that port and for test number one, we're just going to print it in our Arduino console. This is the result of the test so I'm just swogging the result. So I'm pressing the sensor and you could see that when it's not pressed the values are in the range of zero to 20 and whenever I press it, it comes up to five and more depending on how hard I press. So this is good but there was a little bit of I was missing something. Whenever I would hold the sensor it would keep constantly sending the pressure values which wasn't ideal. So I needed to send it only once, whenever I press it and whenever I just press it again, it sends it again. So adding a trigger which is going to tell us if it has been pressed, then send the event then if you unpress it then reset the trigger and then do it again. And there was test for one sensor to build for all fingers. You need sensor for each finger and then it was sensible to put it in a glove, plug it all together, test it, duplicate the C code blocks for each of them and that's done. And then there is a little test with the whole sensors building to one glove. So if you see I'm just tapping one finger and other and this is the events I get. So at this stage I'm not sending the values but I'm sending the finger numbers. So if like I said it, I'm counting from index finger. I know that in UK people counting from thumb but this is one for me. And with this in place this is few parts of our architecture complete. By this point I felt like that. I was pretty proud that it worked. But we are here to talk about Elixir. So let's do that. Before we dive in, let's talk about terminology I'm using in my slides so you could catch up. When I say finger or finger event I'm talking about finger number which you got sent from Arduino. When I say key, this is the key which user has pressed so it's the letter, I don't know age if we type in hello, a letter is the current letter in the text which a user whoever is learning to type are supposed to press. Now let's talk about how we get those finger events from Arduino to our Elixir. So we have the value coming from Arduino which is just the finger number. Then I'm going to introduce the serial umbrella application which I mentioned, which is going to add to that data an ID event. So we could then map it with the key event. So we're adding the ID events and then we pass it to the co-application from there. We pass it to event handler and then event handler doing the job of matching it all. Okay, let's talk about the serial application. Serial application here is to just getting all of the events from finger and pass it to the core. This is its own responsibility. Possibly do some formatting if needed but it's on the responsibility to just take the event, pass it through. So we generate another umbrella application. This is the last one we need. We add a dependency, a serial, which allows us to communication to ports. We add our co-application as a dependency so we could talk to it. And in our innate callback, we need to say the serial port which we are going to use for communication. Here you need to be careful to make sure that the port you're specifying here is actually the one which is enabled because I've stumbled across that and it was a long time trying to understand why I don't get the events but it all was that the port wasn't the correct one. And then we set in the speed, connecting and it's done. And the next important part is to actually listen to those events. So what we get here is data. Data is our data which come in from Arduino. So in my case, I'm just passing the finger number. So here I'm passing a pattern matching on finger number and then I'm passing it through to the core application with the correct finger number and the finger ID event. And with this in place, we have only one last piece left to implement and this is our logic part. It's going to have a lot of clicks here. So to recap, we get events from the serial to the core from the core to IvanHandler and we get events from the channel to the core and to the IvanHandler. So we get all of the events get to the IvanHandler. So IvanHandler is the one who knows all about events. To help us decide on events matching, I come up with idea to introduce an event struct which is going to contain a key events and a finger events. So whenever we get an event from finger, it's going to look if the associated with this event ID key exist. If it doesn't, it just stores it in the map and waits and then on the latest stage, if we get the key event coming in, it's going to check if the associated to this finger event exist. If it finds the same ID, then it's going to do the processing. If it doesn't, it just stores it in the map and waits for the associated event. I'm sorry, the image is not big enough, but I'll talk through it. So once we get two events together, we are going to decide whether our finger with which we press the key match the letter we supposed to be pressing. If yes, then we are going to continue doing the matching with asking if the key is the one we supposed to be pressing with for this letter we see on the screen. And the same, so we do set of matches and the result of this could be that the key is correct and the finger is correct. So this is all much, then nothing much and there are two other options when someone presses with the right finger but wrong key or wrong finger but right key. And after that, we need to clear that event struct so it doesn't get extended and then it'll be harder to extract the values from the struct or map. So we clear the processed event to recap those match results. So let's see how this works. So we go to our cool application, the key event. We pass it to our event handler. We do the same with the finger and then event handler has a struct event which has a key events and the finger events to start with is just empty maps. We initialize the event handler with empty struct and the next part is interesting. So when we get key event, then we are going to see if we have associative finger event. So we try to fetch the event from the map. If we, there are two possibilities. We either have it in the map or not. If we don't have it, it's going to be new. If we do have it, it's going to be an event. Then we pass it to our process key function. So if you look at this, we either pass in new or we pass in the event. If we pass in new, then that's mean that this is the first one which come through. So we just store it in the struct and we continue. So we add it to our keys event struct and wait for the finger event to come in. If it does exist, then we need to take it out and do off the matching logic. So we take it out and then we call our match a match. This is the module which is doing off the matching logic. We pass in the key, the finger and the current letter. We don't know here anything about text or current letter. So we go to the core which knows about it and get it. And it just returns us the first letter in the text. And then we call the function and it goes to our match module. In our match module, we're going to have a few steps. First, we need to match on the key. So we have a current letter and we have a key and we need to compare them. This method is very easy. We just say it's true or false. Okay, the next step is to see if the finger is correct for this current letter. So we have another function which is going to return true or false. But to be able to say with which finger, which finger should be for which key, we need to have some kind of knowledge about it. So there is a finger number, which is just a constant. And then there is a map. This is for clarity, but it's arguably the best way out for programmers having a lot of load on our pinky fingers, but this is for clarity. So then we do the match and we get true or false for correctness of the finger or key. And we pass it to the total match function which is going to return us one of the results which is all match, nothing match or some of them match. Then the next step would be to notify the UI. So for now just print it to the console and I'll come back to notifying the UI on the later stage. But what's important after that is to clear the struct from the events which we have processed already. To do that, we're just taking it out by the ID window, by the key window. And don't forget to send a no reply for the handle cast. The same happens for finger event. The logic is just the same. So I wouldn't talk through all of this again, but the logic is the same. We get the finger event, then we see if we have corresponding key event. If we do, then we do the processing. If we don't, we start in the map and we wait for the corresponding event to come through. Let's talk about notifying the UI of the match result. So once we have the result, which comes in, well, for this, in this case I do it that it has the result which is the item of all match, not match or something match. And event ID, pass it through to the call, pass it through to Phoenix channel, goes to a phase and phase it and renders the result in the browser. So we call even handle result with the result in ID and handle cast for this function, looks like that. So if we get all match, then we should clear the current letter. So that's mean that the person who has been typing the text, he got it right. So we need to take it out from the whole text, which is just getting the first letter and taking out from the text. If he hasn't got it right, then we don't take it out. We leave it there for him to try again. And we send the result to the channel, Phoenix channel. Phoenix channel is listening for those messages. Then he broadcast it, push it to the socket and then it renders to the browser. Okay, and I did record a little demo. I'm not daring to do any live demos. I'm not that brave. So that's me trying it out. There is a text to type in and then I was, the green is the keys I get right and then I get some of them wrong, no match. That's it. Thank you. To summarize all of this talk, first I wanted to say that when people talk about Elixir, when they describe it in Elixir, they usually use adjectives like full-tower and conquer and distribute it. But I think there is one adjective which is missing. It's inspiring. Elixir has inspired me to do some of the interesting projects I've been doing recently. So I think inspiring is missing there. Getting a hardware involved in your project is fun. It's not that scary. I thought it was, it looks quite a little bit scary, but when you actually start trying and when you get your first LED flashing, it's really rewarding and then you get more sensors and you find out about all of the chips and boards and it's really fun. I've been to Narav's workshop yesterday and that was really good and we built this amazing badge. So I think if you want to feel rewarded, like being a software developer and what you're doing, it's worth going and getting some sensors and plugging them together and feeling good about it. Another point to take is whenever you think about your Elixir application, it helps to think in the way you may structure them into umbrella applications. So you then start to think which pieces of your application are isolated from each other and then you try to identify your dependencies, which helps on the later stage to test and to see what's happening. And data for diagrams were very, very helpful. On the early stage, after Hacking Event, when it was all working and it was like, great, okay, it's working, but then when I had to put it nice and structure it into umbrella applications, defining the responsibility of each application and defining those APIs was a little bit hard and when I start to draw those data for diagrams, then it helped me to see what should be when how it's going to all work together. Thank you for coming and listening. This project is on GitHub if you want to check it out. I'm on Twitter if you want to pin me, give me a feedback, I'm quite happy to hear. Thank you. I think I have a little bit of time left. So if you have any questions.