<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Łukasz Pawłowski</title>
    <description>The latest articles on DEV Community by Łukasz Pawłowski (@smoogie).</description>
    <link>https://dev.to/smoogie</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F150891%2F147b6c3c-9f85-4613-9c3d-de640016fca4.jpeg</url>
      <title>DEV Community: Łukasz Pawłowski</title>
      <link>https://dev.to/smoogie</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/smoogie"/>
    <language>en</language>
    <item>
      <title>Let's talk with web application</title>
      <dc:creator>Łukasz Pawłowski</dc:creator>
      <pubDate>Wed, 03 Apr 2019 15:46:59 +0000</pubDate>
      <link>https://dev.to/smoogie/let-s-talk-with-web-application-19j7</link>
      <guid>https://dev.to/smoogie/let-s-talk-with-web-application-19j7</guid>
      <description>&lt;p&gt;Many companies are adopting chatbots in context of client service and in-house support. Most of these solutions are connected with some messaging platform like Facebook Messanger, Whats App, Telegram, etc. At the same time, there are great voice assistants (like Alexa, Google assistant, etc.) used privately by non-company users. Not long ago, chatbots were just another interface for some application (mostly web apps), but now they are getting their own identity, humor, knowledge base, personality. They have become more like assistants, instead of question/answer interface, which collect and present data for your system. Voice interface is more natural to human than, any visual solution. Does this mean that standard websites will no longer be used? No. In most cases, chatbots and web pages will complement each other and in more complex situation, you will reuse your chatbot in your web application, what will improve user experience. Additionally, more and more attention is devoted to accessibility, which resulted in new trends in user experience. Voice interfaces are part of this movement.&lt;/p&gt;

&lt;p&gt;It is not easy to create good chatbot. Creating good voice assistant is even harder, but the real challenge is to integrate it with the web application. There are a lot of things which you need to do. First, your app needs to listen to the user, what can be achieved with &lt;em&gt;&amp;lt; audio &amp;gt;&lt;/em&gt; and &lt;em&gt;getUserMedia()&lt;/em&gt; or other audio API available in browsers. When audio will be caught, stream it to back-end. You can do it with websocket and node.js. Back-end need to create chunks of audio, based on what users says, but before that, you need to separate background noise from valuable parts of recording. When you get specific part of recording, you need to use speech recognition software to get transcript of what user said. There are ready to use libraries or services for it. When you will have text, use NLP to understand transcript. Again, there are lot of libraries and services for that. At the end, when you know what user said, select correct action and pass parameters supplied by user. Now you can use some basic code to get data, make calculation etc. When you are done, send data to front-end and make changes in visualization. Also, voice assistant should say something, so you use speech synthesis.&lt;/p&gt;

&lt;p&gt;Most of this require a lot of custom code. Sure, you can do large part of software in front-end and simplify it a little, but it requires a lot of hardware resources. Also, if you use some services for speech recognition and NLP, you do not want to make your private keys and passwords available for anyone. This is why you send users audio to your back-end and make requests to services there.&lt;/p&gt;

&lt;p&gt;There is a lot of things to cover, a lot of things to learn. How to start? How you can jump right in the topic without reading a lot of resources and writing a lot of code? Is it possible to test some of this technology with small effort? Is it possible to create proof of concept, to interest investors or your boss? Web Speech API to the rescue!&lt;/p&gt;




&lt;p&gt;Let’s start with something simple. I want to create a simple assistant, which will help me in presentation for my speech. During talk I like to walk and make gestures. To switch between slides and code, or to change slides, I need to get back to a computer and make few clicks. This makes me uncomfortable. I want to be close to my computer only when I code live and free when I talk. Let’s make a voice assistant, which will do all of this stuff for us. We will use: Web Speech API to receive voice commands and to make assistant talk; Dialogflow for NLP and reveal.js for presentation.&lt;/p&gt;

&lt;p&gt;In this example, we will create a simple presentation and the voice assistant will just switch slides. It will teach you basics to make more sophisticated solutions. Please keep in mind that, I want to present couple of technologies, not to teach you how make your app safe and how to configure server correctly. I will help you to start your journey in voice applications land and grasp general concept of such applications. During production of the app you should include some additional things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;put many things in some config file or read it from database&lt;/li&gt;
&lt;li&gt;handle errors and exceptions&lt;/li&gt;
&lt;li&gt;communication with dialogflow on your back-end&lt;/li&gt;
&lt;li&gt;make all credential safe&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will put most of logic in front-end. Code will be custom-made, based on my Chrome settings, you might need to change it a little bit to make it work with your browser. I use newest version of Chrome on desktop, but on Firefox not all functions worked as supposed.&lt;/p&gt;

&lt;p&gt;First, we will build simple presentation with &lt;a href="https://revealjs.com/" rel="noopener noreferrer"&gt;reveal.js&lt;/a&gt;. It will contain few slides with some dummy text. We start from running &lt;a href="http://www.vagrantup.com/" rel="noopener noreferrer"&gt;vagrant box&lt;/a&gt; with ubuntu 16 and apache. Project folder is mapped into &lt;em&gt;/var/www&lt;/em&gt;, which will be root folder for application. Now we must add some vhost and ssl, which will be needed later. To make it as simple as possible, log into vagrant box and create key with certificate placed in &lt;em&gt;/home/vagrant&lt;/em&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; openssl genrsa -out slides.key 2048
&amp;gt; openssl req -new -x509 -key slides.key -out slides.cert -days 3650 -subj /CN=slides
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We go to &lt;em&gt;/etc/apache2/sites-available&lt;/em&gt; and create configuration for virtual host. Again, to make it fast, we use defaults — copy one of default config and change it. We will use &lt;em&gt;&lt;a href="https://slides" rel="noopener noreferrer"&gt;https://slides&lt;/a&gt;&lt;/em&gt; as an url to our application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;VirtualHost *:443&amp;gt;
 SSLEngine on
 ServerName slides
 SSLCertificateFile /home/vagrant/slides.cert
 SSLCertificateKeyFile /home/vagrant/slides.key
 ServerAdmin webmaster@localhost
 DocumentRoot /var/www/public
 &amp;lt;Directory /var/www/public&amp;gt;
  Options Indexes FollowSymlinks MultiViews
  AllowOverride All
  Order allow,deny
  allow from all
 &amp;lt;/Directory&amp;gt;
&amp;lt;/VirtualHost&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we create public folder in our root, where we add index.html with random text. This way, we can make sure that everything works as expected. We also need to enable site, add ssl module to apache and restart it. It required a few more commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo a2ensite *
sudo a2enmod ssl
sudo service apache2 restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Last thing is to add virtual host on host machine. I use Windows, so I go to &lt;em&gt;C:\Windows\System32\drivers\etc\hosts&lt;/em&gt; and add line with IP of my virtual machine and slides domain. Now on Chrome, when we will open &lt;em&gt;&lt;a href="https://slides" rel="noopener noreferrer"&gt;https://slides&lt;/a&gt;&lt;/em&gt;, we see dummy page from &lt;em&gt;/var/www/public&lt;/em&gt; on virtual machine. Server is ready, now let’s write some code.&lt;/p&gt;

&lt;p&gt;In public folder, we add folders (css, js, lib, plugin) from &lt;a href="https://github.com/hakimel/reveal.js" rel="noopener noreferrer"&gt;https://github.com/hakimel/reveal.js&lt;/a&gt;. In &lt;em&gt;public/lib/js/&lt;/em&gt;, we add jsrsasign-all-min.js from &lt;a href="https://github.com/kjur/jsrsasign" rel="noopener noreferrer"&gt;https://github.com/kjur/jsrsasign&lt;/a&gt; and few empty files in &lt;em&gt;public/js/&lt;/em&gt; folder: google_token.js, slides.js, voice.js. We change index.html to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html class="sl-root decks export loaded ua-phantomjs reveal-viewport theme-font-montserrat theme-color-white-blue"&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&amp;gt;
    &amp;lt;meta charset="utf-8"&amp;gt;
    &amp;lt;meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"&amp;gt;
    &amp;lt;title&amp;gt;deck: Slides&amp;lt;/title&amp;gt;
    &amp;lt;meta name="description" content="Slides"&amp;gt;
    &amp;lt;link rel="stylesheet" href="/css/reveal.css"&amp;gt;
    &amp;lt;link rel="stylesheet" href="/css/theme/white.css"&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;div class="reveal"&amp;gt;
    &amp;lt;div class="slides"&amp;gt;
        &amp;lt;section&amp;gt;Some first slide&amp;lt;/section&amp;gt;
        &amp;lt;section&amp;gt;Single Horizontal Slide&amp;lt;/section&amp;gt;
        &amp;lt;section&amp;gt;
            &amp;lt;section&amp;gt;Vertical Slide 1&amp;lt;/section&amp;gt;
            &amp;lt;section&amp;gt;Vertical Slide 2&amp;lt;/section&amp;gt;
        &amp;lt;/section&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;script src="lib/js/jsrsasign.min.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src="js/google_token.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src="js/reveal.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src="js/slides.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src="js/voice.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;em&gt;public/js/slides.js&lt;/em&gt;, we initialize reveal.js slide engine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Reveal.initialize({
    controls: true,
    controlsLayout: 'edges',
    progress: true,
    transition: 'convex',
    backgroundTransition: 'convex',
    history: true
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Chrome, we go to &lt;a href="https://slides" rel="noopener noreferrer"&gt;https://slides&lt;/a&gt;. When we open the page for the first time, Chrome will inform us about certificate problems, but we are going to accept the risk and open the page. After that, we should see first slide and switch between them manually. If you followed me to this point, we can say basic setup is done, so let’s get to voice recognition.&lt;/p&gt;

&lt;p&gt;Before we move on, we need to plug in microphone into computer. When we are ready, let’s change &lt;em&gt;public/js/voice.js&lt;/em&gt; file. First, we create voice recognition object and set it to operate continuously. It will catch voice and try to match it with patterns. If we would not do set it to operate continuously, it would turn off after first match. Additionally we set language to &lt;em&gt;en-US&lt;/em&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var SpeechRecognition = SpeechRecognition || webkitSpeechRecognition;
var speechRecognizer = new SpeechRecognition();
speechRecognizer.continuous = true;
speechRecognizer.lang = "en-US";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our listener is ready to activate, so we write function to make it active:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function startListener() {
    speechRecognizer.start();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now our app will listen, but would not do anything with that what it heard. We need to define what to do when something happens. We can achieve this by setting callbacks for SpeechRecognition events. First, we want to log all start/stop events. We want to restart listener on stop event. You may ask “why to restart it if we set speech recognition to work continuously?” and that would be a good question. You see, in this case “continuously” means “do not stop after first recognized sentence, just listen as long as you can and when you catch something, throw it into event”. After some time, Chrome just shut down listener and your speech recognition will stop to work. Also, if some error happen, speech recognition is turned off and in that case, we also want to turn it on again. Here is code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;speechRecognizer.onaudiostart = function(event) {
    console.log('onaudiostart');
};
speechRecognizer.onaudioend = function(event) {
    console.log('onaudioend');
};
speechRecognizer.onend = function(event) {
    console.log('onend');
    speechRecognizer.start(); 
};
speechRecognizer.onnomatch = function(event) {
    console.log('onnomatch');
};
speechRecognizer.onsoundstart = function(event) {
    console.log('onsoundstart');
};
speechRecognizer.onsoundend = function(event) {
    console.log('onsoundend');
};
speechRecognizer.onspeechstart = function(event) {
    console.log('onspeechstart');
};
speechRecognizer.onspeechend = function(event) {
    console.log('onspeechend');
    speechRecognizer.stop();
};
speechRecognizer.onerror = function(event){
    console.log(event)
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to do something with caught sounds and recognized speech. We will listen to &lt;em&gt;onresult&lt;/em&gt; event, which is fired when SpeechRecognizer create transcript. Here is something important — speech recognition constantly changes results during parsing your voice. You will get access to results before process will finish to build final transcript. We need to check results and only if it is final, we will use it. Transcript is simple text, so we can operate on it as on text input. We will log all caught responses and if it matches our action, we will run it. Remember that we are operating on string, so any whitespaces, char size (lowercase/uppercase) will change it to something different. We create such code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;speechRecognizer.onresult = event =&amp;gt; {
    for(var i=event.resultIndex; i&amp;lt;event.results.length; i++){
        var transcript = event.results[i][0].transcript;
        if(event.results[i].isFinal){
            transcript = transcript.trim().toLowerCase();
            console.log(transcript);
            switch (transcript) {
                case "right":
                    Reveal.right();
                    break;
                case "left":
                    Reveal.left();
                    break;
                case "down":
                    Reveal.down();
                    break;
                case "up":
                    Reveal.up();
                    break;
            }
        }
    };
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can run a little test — we open &lt;a href="https://slides" rel="noopener noreferrer"&gt;https://slides&lt;/a&gt;. In Chrome we see, that in navbar (close to my url) some icon showed up, which indicate, that web app tries to get access to microphone and as user I need to set permissions for web page. I can set permissions only for specific url and if my app is served through https, I can set it permanently. If it is not secured with ssl, app will require acceptance each time it ask for access to microphone. We set up vhosts and added ssl, so we can set it once and forget it. After all settings are done, we refresh the page and start to give voice commands through microphone. If you followed me and created all required code, you should be able to change slides with simple words like “right”, “left”, “down”, “up”. If there are some problems, open console to see if any warnings or errors were caught and try to say command a little slower or louder. Do not give few commands to fast, because system will create one transcript, which represent sentence composed of a several words. If parsing takes too long, try to play a little with microphone’s settings and try to reduce background noise.&lt;/p&gt;

&lt;p&gt;We made it… but something is wrong. We can say “right”, “left”, “down”, “up” and it will switch slides, but we want to say “change slide to next” or maybe “next slide” or anything else. With current solution we would need to write all options in switch… What if my speech recognition would create wrong transcript ex. “app” instead of “up”? I am not native English speaker and speech recognition is not perfect too. Trying to cover all possible cases I would end up with thousands of lines of code. I need a real chat bot solution.&lt;/p&gt;




&lt;p&gt;Let’s move on and add some NLP. I mentioned to put your NLP on back-end, but here we will connect with dialogflow on front-end. First, we need to configure an agent in dialogflow. We open &lt;a href="https://dialogflow.com/" rel="noopener noreferrer"&gt;https://dialogflow.com/&lt;/a&gt;, sign in with our google account and we create new agent. In it we create new entity “slide” with 4 entries. Each entry has some value (something like id) and synonyms (additional pointer for specific entry). It looks like that:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fz04ig8aswnmmdlo7yfg9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fz04ig8aswnmmdlo7yfg9.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we need intent, which represent dialog option. For that, we add new intent &lt;em&gt;chng_slide&lt;/em&gt;. We add three training phrases “next slide”, “get next slide”, “please change slide for next” and we connect word “next” with entity “slide” (when you select part of text, pop-up will be displayed with option to select entity). We remove text payload and add custom payload with json (use “Add responses” button and select “Custom payload”):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "action": "change_slide",
  "params": {
    "new": "$slide"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our custom payload will be sent as response on API call. Training phrases will be used as text examples for texts comparator. Connection between text and entity informs NLP processor which part of our example is dynamic and can be used as parameters to define entity. Configuration looks like that:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F6c0ze7cvd911c552iuuu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F6c0ze7cvd911c552iuuu.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now our bot is configured and we need to connect it with front-end. For that, we need to get access to dialogflow REST API, which use OAuth. Let’s get through this together. First we need to create Service Account with access to our bot from google cloud service. In dialogflow in agent configuration options, in “Google project” section, we have “Project Id” and “Service Account” — note it somewhere, we’ll need that later.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fvm9g3milpk3njamodieh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fvm9g3milpk3njamodieh.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Service Account is linked to google project settings — open it. In new window with google cloud platform administration (page which opens from “Service Account” link), we need to add new service account. For that, we need to set role: dialogflow client. We can find dialogflow on left column and select client on right column, or just start to type “dialogflow API client”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F1bpxtrjd01awp5hxq2d3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F1bpxtrjd01awp5hxq2d3.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On bottom, there are two checkboxes, select first with option to share new private key and select JSON as key type.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Feazz0sdd1tvx5dbx1cf7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Feazz0sdd1tvx5dbx1cf7.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we save it, we will also get json file with data to access our service. Let’s assume that our json look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "type": "service_account",
  "project_id": "my_project_id",
  "private_key_id": "some_long_private_key",
  "private_key": "-----BEGIN PRIVATE KEY-----\nLOTOFCHARINHERE==\n-----END PRIVATE KEY-----\n",
  "client_email": "slides@my_project_id.iam.gserviceaccount.com",
  "client_id": "my_client_id",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://accounts.google.com/o/oauth2/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/slides%40my_project_id.iam.gserviceaccount.com"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we get back to our code. To communicate with REST API, we need OAuth token, what we can achieve by making request to &lt;a href="https://www.googleapis.com/oauth2/v4/token" rel="noopener noreferrer"&gt;https://www.googleapis.com/oauth2/v4/token&lt;/a&gt; and add JWT token. For JWT token we use data from JSON file, which we get when we created Service Account in google cloud platform. Received OAuth token will be stored globally. This is not safe approach and do not use it on production.&lt;/p&gt;

&lt;p&gt;All code required to receive token will be kept in &lt;em&gt;public/js/google_token.js&lt;/em&gt;. First, we create JWT token with jsrsasign 8.0.12. Based on code, which I presented for JSON key, our js should look like that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const unix = Math.round(+new Date()/1000);
const privatekey = "-----BEGIN PRIVATE KEY-----\nLOTOFCHARINHERE==\n-----END PRIVATE KEY-----\n";
const jwtHeader = {
    alg: "RS256",
    typ: "JWT"
};
const jwtPayload = {
    iss: "slides@my_project_id.iam.gserviceaccount.com",
    scope:"https://www.googleapis.com/auth/cloud-platform",
    sub: "slides@my_project_id.iam.gserviceaccount.com",
    aud: "https://www.googleapis.com/oauth2/v4/token",
    iat: unix,
    exp: unix + 3600
};
const jwtToken = KJUR.jws.JWS.sign('RS256',jwtHeader, jwtPayload, privatekey);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we create post data and send it with request to google API. In global variable we save OAuth token, which we get from response. We start to listen to user voice, after dialogflow token is received. This way, we make sure, that we do not make any call to dialogflow without Oauth token. This is our code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var gapiToken = 0;
var tokenRequestBody = "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&amp;amp;assertion="+jwtToken;
fetch('https://www.googleapis.com/oauth2/v4/token', {
    method: 'POST',
    body: tokenRequestBody,
    headers: {
        'content-type': 'application/x-www-form-urlencoded'
    }
})
.then(response =&amp;gt; response.json())
.then(jsonData =&amp;gt; {gapiToken=jsonData.access_token; startListener()})
.catch(err =&amp;gt; {});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nice, we can communicate with API. So let’s change our code in &lt;em&gt;public/js/voice.js&lt;/em&gt; starting from onresult action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;speechRecognizer.onresult = event =&amp;gt; {
    for (var i = event.resultIndex; i &amp;lt; event.results.length; i++) {
        var transcript = event.results[i][0].transcript;
        if (event.results[i].isFinal) {
            transcript = transcript.trim().toLowerCase();
            analizeData(transcript);
        }
    }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In function &lt;em&gt;analizaData&lt;/em&gt;, we make call to dialogflow API. We need to send request to specific url, which include project id and session id: &lt;a href="https://dialogflow.googleapis.com/v2/projects/your_project_id/agent/sessions/yuor_session_id:detectIntent" rel="noopener noreferrer"&gt;https://dialogflow.googleapis.com/v2/projects/your_project_id/agent/sessions/yuor_session_id:detectIntent&lt;/a&gt;. Project id can be taken from dialogflow project settings (you remember that we note it few minutes ago). &lt;em&gt;Session&lt;/em&gt; is session id, created by us and it must be individual for each our client, because dialogflow keep in session data like context. For testing purpose we will hardcode session id:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function analizeData(text) {
    console.log(text)
    let query = {
        "queryInput": {
            "text": {
                "text": text,
                "languageCode": "en-US"
            }
        }
    };
    fetch('https://dialogflow.googleapis.com/v2/projects/my_project_id/agent/sessions/test_session:detectIntent', {
        method: 'POST',
        body: JSON.stringify(query),
        headers: {
            'content-type': 'application/json',
            'Authorization': 'Bearer ' + gapiToken
        }
    }).then(response =&amp;gt; response.json()).then(serveResponse);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response from dialogflow must be parsed. Based on in it, we will make some action in application. We are interested in custom payloads, which contains action name and its parameters. We use action as function name and params as arguments (again when you work on production application be sure to check response, validate it and parse it properly):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function serveResponse(data) {
    data.queryResult.fulfillmentMessages.forEach(fullfilment =&amp;gt; {
        if (fullfilment.payload != undefined){
            window[fullfilment.payload.action](fullfilment.payload.params);
        }
    });
}
 function change_slide(params) {
     Reveal[params.new]();
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when you test it, it still work, but you can use more phrases to activate action. Also when you log in to dialogflow, check training section. There you will find all incoming messages and you can use them to “teach” your bot. You can assign new phrases to existing intents and create new intents to do more or react properly on incoming messages.&lt;/p&gt;




&lt;p&gt;There is one more thing, which we want to add. As you remember, we want to create assistant which does not just follow your order, it also talks to you. We would not do any fancy thing now — we’ll just add voice to our application. Any time response from dialogflow will contain text payload, we want to hear it.&lt;/p&gt;

&lt;p&gt;First, we need to initialize speech synthesis and create text to be read. To do that, we change a little &lt;em&gt;serveResponse&lt;/em&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function serveResponse(data) {
    data.queryResult.fulfillmentMessages.forEach(fullfilment =&amp;gt; {
        if(fullfilment.text != undefined) {
            fullfilment.text.text.forEach(text =&amp;gt; {
                let utterThis = new SpeechSynthesisUtterance(text);
                utterThis.voice = voice;
                speechSynthesis.speak(utterThis);
            })
        }
        if (fullfilment.payload != undefined){
            window[fullfilment.payload.action](fullfilment.payload.params);
        }
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now each time we get text, it is read. I’m using Windows, so when I test speech synthesis, I get default system voice in my locals. I want to use English voice, which sounds more naturally. First I need to know what I can use, for that I log all available voices, which I get with &lt;em&gt;speechSynthesis.getVoices()&lt;/em&gt;. When I know what voices I have, I can test them and select one… I suggest you do the same.&lt;/p&gt;

&lt;p&gt;I selected ‘Google UK English Female’. We know that available options will not change now, so we can hardcode its name. At the top of ourpublic/js/voice.js we add few lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var voice = undefined;
var voices = undefined;
function getVoices() {
    if (typeof speechSynthesis === 'undefined') {
        return;
    }
    voices = speechSynthesis.getVoices();
    if(voices.length &amp;gt; 0) {
        selectVoice('Google UK English Female');
    }
}
function selectVoice(name) {
    for (i = 0; i &amp;lt; voices.length; i++) {
        if (voices[i].name === name) {
            voice = voices[i];
        }
    }
}
getVoices();
if (typeof speechSynthesis !== 'undefined' &amp;amp;&amp;amp; speechSynthesis.onvoiceschanged !== undefined) {
    speechSynthesis.onvoiceschanged = getVoices;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nice. Now we can chat with our presentation. We can easily add more functionality served by assistant — we just need to add new methods in js and create more intents in dialogflow. Also we can teach our bot to recognize new phrases, without changing code of our application.&lt;/p&gt;




&lt;p&gt;What’s next? You can start from moving your communication with NLP into back-end, cleaning code, adding error handling. Next, you can add more actions like: change background, start/stop, fullscreen, read slide text.&lt;/p&gt;

&lt;p&gt;When you will finish playing with the app, you can think about more useful projects. Of course you need to remember, that this solution is limited to specific webbrowser and specific languages (for now). It is not very fast and have some problems with recognizing speech, but it is enough to create prototype and to present your idea to clients. With good developer team you can create your own solution for voice application. To make your app available for other browsers, you will need stream audio to back-end and parse it there.&lt;/p&gt;

&lt;p&gt;I hope this article was useful and helped you start your journey with web voice application. I hope that you will test other possibilities and follow your ideas to create interesting solutions, which will make Internet more interactive and also that your work will inspire others.&lt;/p&gt;




&lt;p&gt;As an additon, let’s get through some example to describe when we can use such solution.&lt;/p&gt;

&lt;p&gt;Olga is owner of online clothes shop, which has a lot of followers on Facebook. She added chatbot for Facebook Messanger, which offer few functionality: suggestion of some clothes and creation of full stylization based on communication with the client (chat bot stylist), option to make orders or check order’s status. When her shop had became popular, she created online changing room based on WebAR, with virtual stylist, which has been based on voice recognition and chat bot. Now users can open her web page and activate change room app, in which they are able to talk with virtual stylist and try some clothes or even full stylizations, which can be ordered later with simple voice order.&lt;/p&gt;

&lt;p&gt;Let’s think about other use case, for example Bob’s construction company, which builds prize-winning buildings. Some time ago, Bob created dedicated web application for his team, which is based on WebVR, WebAR and speech recognition. With help of WebGL module, architect can create projects, which is used by marketing team during presentation with WebVR module. Also construction team uses WebAR module to compare reality with plans and locate walls, doors, electricity, etc. The appliaction has standard inputs and speech recognition interface, which made virtual assistans possible to implement. System change project based on voice commands supplied by architect. It is also used during presnatation in front of investors, when presenter is changing lights, furniture, wall decoration etc. only by asking assistant to do it. Construction team does not need any fancy remote-controled devices or joysticks to operate AR, they just talk with assistant like “where window should be”, “what kind of wall should stand here”, “where should I put cable” etc.&lt;/p&gt;

&lt;p&gt;Think about car workshop, owned by Luis. He created fancy web app with AR, image recognition and voice assistant. He looks under hood, pulls some old cable, but he’s not sure where to connect it. He can ask “Where this cable should be connected?” and his assistant gives him instructions, while app visualize where the cable should be connected.&lt;/p&gt;

&lt;p&gt;Let me present one last example — city guide page, which has voice support for disabled and blind people. Speech recognition and bot are responsible for navigate through the page based on voice commands, while Speech Synthesis presents page’s content to user.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/front-end-weekly/lets-talk-with-web-application-684214d34bdc" rel="noopener noreferrer"&gt;original post on  medium&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I’ve got some comment for you</title>
      <dc:creator>Łukasz Pawłowski</dc:creator>
      <pubDate>Wed, 03 Apr 2019 14:53:33 +0000</pubDate>
      <link>https://dev.to/smoogie/i-ve-got-some-comment-for-you-3jid</link>
      <guid>https://dev.to/smoogie/i-ve-got-some-comment-for-you-3jid</guid>
      <description>&lt;p&gt;Code’s comments are always overlooked subject. Many times developers add them chaotically, ignore or misuse them. Bad comments can be harmful, while good one can be a very useful tool. In this article I want to summarize most important things, which I discussed with other developers in our company. I also want to present my personal approach for commenting code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TLDR&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You should use comments in few situations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use annotations and dock blocks to create documentation of your API&lt;/li&gt;
&lt;li&gt;explain unintuitive code solutions — say why, not how&lt;/li&gt;
&lt;li&gt;explain complex algorithms — mostly say why, not how. If situation required, add links for materials which explain algorithm in depth&lt;/li&gt;
&lt;li&gt;describe configuration options&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes comments will be better and more accurate documentation, than any documentation created separately. Good comments will help you get back to your old code and can be useful for other people to understand your code.&lt;/p&gt;

&lt;p&gt;You can use comment as tool for your development:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;add to-do list&lt;/li&gt;
&lt;li&gt;make a comment about technical debt&lt;/li&gt;
&lt;li&gt;add annotations inside functions, to get better autocompletion and code’s support in your IDE&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can even push them into code repository if you have WIP commit/branch. Remember to remove such comments before sending Merge Request or before adding your code to master branch.&lt;/p&gt;

&lt;p&gt;Do not add too many comments. This can be indicator of problems or bad practices. Many times you can find some better equivalent. Here are a few examples of situation, which you should avoid:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;do not use comments for discussion — use &lt;a href="https://slack.com/"&gt;slack&lt;/a&gt; or other tools instead&lt;/li&gt;
&lt;li&gt;do not use comments for Code Review — there are better solutions e.g. &lt;a href="https://docs.gitlab.com/ee/user/project/merge_requests/#commenting-on-any-file-line-in-merge-requests"&gt;discussions on Merge Request&lt;/a&gt; in gitlab, &lt;a href="https://www.jetbrains.com/upsource/"&gt;Jetbrains Upsource&lt;/a&gt; etc.&lt;/li&gt;
&lt;li&gt;do not describe all variables and each step of your code — name your variables/functions/classes correctly and use type hints&lt;/li&gt;
&lt;li&gt;do not use comments to divide your code — divide code into multiple functions/classes/files&lt;/li&gt;
&lt;li&gt;do not describe each use case and each step of function — if you have multiple use case write multiple tests which will be better documentation than big wall of text in comment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A completely different topic is how to use comments. Comments, like code, should be consistent across whole project. Discuss them with your team and create guidelines. Decide when you use comments and how to format them. Remember to create comments during coding not after. When you use any bundlers or preprocessors, add steps with minimalization and comment removement e.g. when your parse sass to css, or during bundling js with &lt;a href="https://webpack.js.org/"&gt;webpack&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comments as documentation
&lt;/h2&gt;

&lt;p&gt;As developer you probably heard that “Your code should be self explanatory”. It is true, but it does not mean that you should not use comments. They can significantly increase the intelligibility of the code. You should use them as documentation for our code. Let me explain how I use it.&lt;/p&gt;

&lt;p&gt;In most IDE when you generate file from &lt;a href="https://www.jetbrains.com/help/phpstorm/using-file-and-code-templates.html"&gt;templates&lt;/a&gt;, IDE will automatically add comments. That comments describe who, when and how generated file. While I prefer to change templates and remove comments, it’s good idea to add some general description of what file contains. Such high view of your files, can significantly speed up code analysis. Description should shortly explain what file contain and what is purpose of included elements. In most cases it does not matter who created file and when, because multiple users will change it later and original code can be long time forgotten. If you use any control version system, you will have this information there. On the other hand, when you build some library and create distribution file, it is still a good idea to include license at the beginning of file with information about author.&lt;/p&gt;

&lt;p&gt;In our company we expect to add comment block to most of classes and functions. Such comments take form of annotations and short description. While many times it is enough to read code, in most cases developer does not have time to get through dozens of code’s lines to find out what specific argument in function is used for. It is good to have explanation of each argument in function: what is it and what are accepted values. We also add information about returning value and short description what functions do, what are side effects of function, what error it can throw etc. We can argue that part of this is covered by code itself e.g. by type hints, but sometimes you accept multiple type of value, return multiple type of values (which should not happen), or you throw many different exceptions in many places in code and comments help to organized this information. Here is simple example in php:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
* function validate if user has specific premissions
* @param User $user user for whom we check permissions
* @param string[]|Permission[] $perms names of permissions or permissions objects to validate
* @param bool $atLeastOne if true - user can have at least one permission, if false - user must have all permissions
* @return bool true if has permissions
* @throws ObjectDoesNotExistException if permission does not exist in the system
*/
function checkParmission(User $user, array $perms, bool $atLeastOne = true): bool { ... }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For classes, we expect at least short description and list of all public methods and public fields. Such short description of class will help you use new elements and will be good documentation of your API. There are also many situations when you have hidden methods or fields. You can use magick methods which hide it before user, or you create model to keep data which are hidrated automatically in it from DB. Good example are Laravel Eloquent Models. Here is simple example of &lt;a href="https://laravel.com/docs/5.8/eloquent"&gt;Laravel Eloquent Model&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* Class which represent user model
*
* @property int $id user id - autoincremental
* @property Carbon $created_at
* @property Carbon $updated_at
* @property string $email
* @property Role $role
* @property int $role_id
* @property int $status status of user: 0 - deleted; 1 - active; 2 - not verified
*
*/
class User extends Illuminate\Database\Eloquent\Model {...}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Many times you will need to build some documentation of your code. Writing separate documents and keeping it up to date is huge time consuming task. Properly commented code will be much better in this case, because it will be updated automatically during refactoring, fixing bugs and building new things. Also it will be easier to use — you can immediately check what is what and how to use it, without finding correct spot in docs. If you need to create user readable docs, you can use tools like &lt;a href="https://www.phpdoc.org/"&gt;PHPDocumentor&lt;/a&gt;, &lt;a href="http://usejsdoc.org/"&gt;JSDocs&lt;/a&gt;, &lt;a href="https://dotnet.github.io/docfx/"&gt;DocFX&lt;/a&gt; or &lt;a href="https://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html"&gt;JavaDoc&lt;/a&gt;. They will create web page describing your API, based on your comments.&lt;/p&gt;

&lt;p&gt;In context of documentation, it is also very important to present your configuration properly, that users/developers understand all available configuration options. It is always great idea to add some good README, but there is no better solution, than commenting configuration in configuration example. You can add all available options with default values and short descriptions. Comment out all options which are not required, but do not remove them from example file. I believe this is only place where code in comment make sense. Here is part of defualt &lt;a href="https://jestjs.io/"&gt;jest&lt;/a&gt; configuration file as an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
  // All imported modules in your tests should be mocked automatically
  // automock: false,
// Stop running tests after `n` failures
  // bail: 0,
// Respect "browser" field in package.json when resolving modules
  // browser: false,
// The directory where Jest should store its cached dependency information
  // cacheDirectory: "C:\\Users\\Łukasz\\AppData\\Local\\Temp\\jest",
// Automatically clear mock calls and instances between every test
  clearMocks: true,
// Indicates whether the coverage information should be collected while executing the test
  // collectCoverage: false,
// An array of glob patterns indicating a set of files for which coverage information should be collected
  // collectCoverageFrom: null,
// The directory where Jest should output its coverage files
  coverageDirectory: "coverage",
...
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Comments as explanation
&lt;/h2&gt;

&lt;p&gt;We discussed documentation with annotations, but what’s with comments which explain how something work, or what something does? First of all, do not describe what next lines of code will do (this make sense only in doc block at the beginning of function/class). Instead, describe why you use specific values, algorithm or some specific solution. This can save you insane amount of time, when you need to change something or you are debugging code. Sometimes you use specific solution, which is not intuitive or seems to be little odd, but from some specific reason it must stay that way e.g. you write some js for app which support old browsers and you need to add little hack to make it work with old IE. If you do not comment it properly, you would lose time to understand or remind yoursef, why specific part was done that way. Sometimes, to avoid potential errors, you will decide to not change specific part of code. In worst-case scenario, someone will not see sense of specific solution and will change it later or remove it, what will breakdown the app.&lt;/p&gt;

&lt;p&gt;The situation is a little bit different, when you are using complex algorithm in your code. It would be helpful to describe algorithm and add some links for future readings and deeper understanding of a problem.&lt;/p&gt;

&lt;p&gt;Such approach is useful mostly for code maintainers and ourselves. For sure, you know what you are doing now, but if you go back to code after few months, would you remember it? You go this, but will others know why specific value was used, what use case you cover?&lt;/p&gt;

&lt;p&gt;At the same time, do not add too much descriptions and explanations. Comments should shortly explain why something is done, what class or function can be used for, but does not need to explain details of implementation. You should not describe each line of your code or even each block of your code. There are some exceptions. If you create complex library reused by thousands, it would be nice to add little more comments, to help user understand what is going on. If you are working on specific app, you do not need it, explain only specific situation and add documentation of the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comments as developer’s tool
&lt;/h2&gt;

&lt;p&gt;You already know that comments are useful for documentation purposes and help to explain complex situation to avoid adding new bugs. You can also think about it as your tool, which support you in building app during development. There are three main areas where you can use comments.&lt;/p&gt;

&lt;p&gt;First, you can use comments in developer’s tools. Many IDE support code hinting. Most of hints and autocompletes are based on annotations mentioned above. Additionally many linters, code sniffers, test tools use comment to change default behavior. E.g. you can select specific part of code which should not be tested or linted, you can also change rules for specific part of code. Here is example of ESLint exclusion and rule changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/* eslint-disable */

thisIsNotCheckedByLint();

/* eslint-enable */
/* eslint eqeqeq: 2 */
$thisLineReturnESLintError == true;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Second useful tip is to use comments to plan your code. Many times when I code something, I start from building skeleton of specific thing. It includes folders and files with interfaces, abstract classes, classes etc. Methods and fields are declared in each class. Type hint and annotations comments are added, to declare what each method should get, return and probably throw. Inside each class, I put comments for each step, which will be written in code. Such skeleton present flow of data and some logic with comments inside code. Later I exchange comments with correct code. Here is simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class TimeReport {
  constructor(projectId) {
    this.projectId = projectId;
  }
  generateReport() {
    this.initData();
    this.analizeData();
    this.getFile();
  }
  initData() {
    //find project in DB if notexist throw ObjectNotExistsError
    //find all stages and corresponding tasks for project
    //get schedule for project
  }
  analizeData() {
    // foreach task calculate spent time and compare to estimation
    // foreach stage sort tasks by status, count them
    // foreach stage check timeline and verify if stage is closed 
    // calculate when stage ended (if ended) or can end based on task's statuses and estimations
    // sum up how many hours we are after/before schedule
  }
  getFile() {
    //get file template and propagate data
    //create PDFFile
    //encode file to base64
    //return base64
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Third situation occur when I work on code and I see the need to change or add something later. E.g. some functionality is not done yet, but I know it will be added later. Comments not only indicate which work must be done, but also adds information about technical debt. In this situation I use tag TODO in comment. It is also good idea to use them to indicate your state of mind when you take break during development e.g. when you leaving office or you going on lunch break. Such comments can help you to get back into code after break.&lt;/p&gt;

&lt;p&gt;There is one very important thing about using comments as a tool — use them locally. It is fine if you push it to git for WIP branch, but remove them from final version of your code by resolving issues. Only thing which can stay are rare TODOs. Your code should not include any WIP comments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comments as code smell and bad practice
&lt;/h2&gt;

&lt;p&gt;Now you know what you can get from using comments and when you should use them. When do not use comments? There are a lot of situations which you will find during code reviews or checking someone’s code (or even your own). Here are few examples where you can use better solutions than comments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do not use comments for discussions. There are much better places to discuss something — arrange meeting, talk during Code Review, use Slack etc. If you need to discuss some part of code, there are really good tools e.g. git lab has nice CR tools for Merge Requests.&lt;/li&gt;
&lt;li&gt;Comments are not versioning system! Many times I stumbled upon old code, which was left as a comment by developer. Use versioning system and push multiple commits. Committed code will not be lost.&lt;/li&gt;
&lt;li&gt;Do not divide code into sections using comments. If you need such things, you have bad code. If it is config/translation file, divid it into smaller files. If it is one big class or function, also split it into smaller functions/classes.&lt;/li&gt;
&lt;li&gt;Do not repeat yourself. This make no sense. Here is example of what I’m talking about:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//Here I set avatar for user
$user-&amp;gt;avatar = $avatar;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Do not explain each variable. If you need to do this, change its name. If you need to explain specific lines, what they do, refactor code. Correct naming and better code will decrease number of comments. Here is simple example of code before refactoring:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const articles = (new Date(user.membershipEndDate) &amp;gt; new Date() &amp;amp;&amp;amp; user.membershipLevel &amp;gt;= User.GOLD_LEVEL) ?
await db.execute('SELECT * FROM articles WHERE published = 1') //IF USER HAS ACTIVE GOLD MEMBERSHIP RETURN ALL ARTICLES
: await db.execute('SELECT * FROM articles WHERE published = 1 AND public = 1') //ELSE RETURN ONLY PUBLIC ARTICLES
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And after&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class User {
  ...
  get isActiveGoldMember() {
    const now = new Date();
    const membershipEnd = new Date(this.membershipEndDate);
    const isGoldMember = this.membershipLevel &amp;gt;= User.GOLD_LEVEL;
    return membershipEnd &amp;gt; now &amp;amp;&amp;amp; isGoldMember;
  }
}
--------------------------------------------------------
let query = 'SELECT * FROM articles WHERE published = 1';
if (!user.isActiveGoldMember) {
  query += ' AND public = 1';
}
const articles = await db.execute(query);

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Use type hint for your methods/functions and add annotations comments, this will save you lot of inline comments. If you need inline comment with annotations, that mean you did something wrong. Here is example of this what I am talking about:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/** @var User $user **/
$user = app-&amp;gt;auth()-&amp;gt;user();
/** @var Company $sompany **/
$company = $user-&amp;gt;getCompany();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Sometimes you need to describe what code do, when there are multiple dependencies or complex logic. It is better to cut loose dependencies and think if your code does not need refactoring. If you need too many explanations for it, you should rewrite part of the code.&lt;/li&gt;
&lt;li&gt;Use comments to describe your API, but do not describe all possible use cases. It is much better to provide detailed use cases within tests, because it will explain your code much better than big text wall (with abstract descriptions).&lt;/li&gt;
&lt;li&gt;Clean after yourself, do not leave development comments, which supposed to help you during development. If you have some comments left, most likely you did not finished task or you created technical debt.&lt;/li&gt;
&lt;li&gt;Put all imports on top of your file, use namespaces etc. This also can save some comments.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Comments as guideline’s subject
&lt;/h2&gt;

&lt;p&gt;Next important thing is how to use comments — they should be understandable and consistent. User should know what comment is used for, only by looking at it. First of all, you should discuss commenting strategy in specific project. Decide what kind of comments you use and when. Define how to format each comment type. Keep it consistent through entire project. Here are few things that can be useful when you first approach problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In most cases inline comments are code smell.&lt;/li&gt;
&lt;li&gt;Use block comments. They should be at the beginning of file, before classes and functions as documentation. One-line comments can be used for short tags like TODO, or simple descriptions inside functions.&lt;/li&gt;
&lt;li&gt;Define order of annotations to keep it consistent. For classes I start from description, then methods and fields are presented. For functions/methods I also start from description, then list arguments, returns and at the end all errors/exceptions thrown by function.&lt;/li&gt;
&lt;li&gt;Remember to use correct intents. Comment should be intended the same way as code which it comments. E.g.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 * Here is comment for Class
 */
class MyClass
{
    /**
     * Here is comment for my method
     */
    public function myMethod() {}
} 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Put comment before commented code in separate line. Do not add empty line between comment and comented code. Put it before comment. E.g.:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//this is good place to comment why I use console.log()
console.log(serviceResponse)

console.log(oops)
//this is bad place to comment console.log(oops)
console.log(ouch)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;When you use doc block start with /**. In each new line add * at the beginning of comments line. E.g.:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 * This is
 * multiline
 * doc block
 *
 * @param string $text
 * @return bool
 */
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Make your comment professional — no stupid jokes, no controversial words etc. Make sure you use correct spelling. Use the same language in whole comments in code — I use English.&lt;/li&gt;
&lt;li&gt;Do not nests comments e.g.:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 * So you should not comment this comment
 * // but you do
 * /* And it is wrong */
 */
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;At the end it is worth mentioned two additional tips. First of all try to create comments while you code, not after you finish. This way they will be most accurate and fresh. Secondary — when you use preprocessors, compilers or bundlers, check if there is some option to minimize code and remove comments before creating distribution file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;It is worth to remember, that comments are very useful when you work on big code base, which you and other developers maintain. Use them as documentation for your code. You can even build some html docs from comments. Use them as tool during development. Remember at the same time, that code is still more important than comments. It is tool, not target.&lt;/p&gt;

&lt;p&gt;When you are using too many comments — readability goes down, file size grows etc. They supposed to help you, not slows you down. You should not have too many comments which explain step by step how something work, you should not have explanation for each function call, variable etc. If there are too many of them, it means that there is something wrong with your code.&lt;/p&gt;

&lt;p&gt;I hope this reading was useful for you and help you rethink comments in your code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/@LPawlowski/ive-got-some-comment-for-you-a259218b8b68"&gt;original post on medium&lt;/a&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
