Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials

6719 Articles
article-image-8-recipes-to-master-promises-in-ecmascript-2018
Richa Tripathi
08 May 2018
17 min read
Save for later

8 recipes to master Promises in ECMAScript 2018

Richa Tripathi
08 May 2018
17 min read
What are Promises in ECMAScript? In earlier versions of JavaScript, the callback pattern was the most common way to organize asynchronous code. It got the job done, but it didn't scale well. With callbacks, as more asynchronous functions are added, the code becomes more deeply nested, and it becomes more difficult to add to, refactor, and understand the code. This situation is commonly known as callback hell. Promises were introduced to improve on this situation. Promises allow the relationships of asynchronous operations to be rearranged and organized with more freedom and flexibility. In this context, today we will learn about Promises and how to use it to create and organize asynchronous functions. We will also explore how to handle error conditions. Creating and waiting for Promises Promises provide a way to compose and combine asynchronous functions in an organized and easier to read way. This recipe demonstrates a very basic usage of promises. This recipe assumes that you already have a workspace that allows you to create and run ES modules in your browser for all the recipes given below: How to do it... Open your command-line application and navigate to your workspace. Create a new folder named 03-01-creating-and-waiting-for-promises. Copy or create an index.html that loads and runs a main function from main.js. Create a main.js file that creates a promise and logs messages before and after the promise is created, as well as while the promise is executing and after it has been resolved: // main.js export function main () { console.log('Before promise created'); new Promise(function (resolve) { console.log('Executing promise'); resolve(); }).then(function () { console.log('Finished promise'); }); console.log('After promise created'); } Start your Python web server and open the following link in your browser: http://localhost:8000/. You will see the following output: How it works... By looking at the order of the log messages, you can clearly see the order of operations. First, the initial log is executed. Next, the promise is created with an executor method. The executor method takes resolve as an argument. The resolve function fulfills the promise. Promises adhere to an interface named thenable. This means that we can chain then callbacks. The callback we attached with this method is executed after the resolve function is called. This function executes asynchronously (not immediately after the Promise has been resolved). Finally, there is a log after the promise has been created. The order the logs messages appear reveals the asynchronous nature of the code. All of the logs are seen in the order they appear in the code, except the Finished promise message. That function is executed asynchronously after the main function has exited! Resolving Promise results In the previous recipe, we saw how to use promises to execute asynchronous code. However, this code is pretty basic. It just logs a message and then calls resolve. Often, we want to use asynchronous code to perform some long-running operation, then return that value. This recipe demonstrates how to use resolve in order to return the result of a long-running operation. How to do it... Open your command-line application and navigate to your workspace.  Create a new folder named 3-02-resolving-promise-results. Copy or create an index.html that loads and runs a main function from main.js. Create a main.js file that creates a promise and logs messages before and after the promise is created: // main.js export function main () { console.log('Before promise created'); new Promise(function (resolve) { }); console.log('After promise created'); } Within the promise, resolve a random number after a 5-second timeout: new Promise(function (resolve) { setTimeout(function () { resolve(Math.random()); }, 5000); }) Chain a then call off the promise. Pass a function that logs out the value of its only argument: new Promise(function (resolve) { setTimeout(function () { resolve(Math.random()); }, 5000); }).then(function (result) { console.log('Long running job returned: %s', result); }); Start your Python web server and open the following link in your browser: http://localhost:8000/. You should see the following output: How it works... Just as in the previous recipe, the promise was not fulfilled until resolve was executed (this time after 5 seconds). This time however, we passed the called  resolve immediately with a random number for an argument. When this happens, the argument is provided to the callback for the subsequent then function. We'll see in future recipes how this can be continued to create promise chains. Rejecting Promise errors In the previous recipe, we saw how to use resolve to provide a result from a successfully fulfilled promise. Unfortunately, the code doesn't always run as expected. Network connections can be down, data can be corrupted, and uncountable other errors can occur. We need to be able to handle those situations as well. This recipe demonstrates how to use reject when errors arise. How to do it... Open your command-line application and navigate to your workspace. Create a new folder named 3-03-rejecting-promise-errors. Copy or create an index.html that loads and runs a main function from main.js. Create a main.js file that creates a promise, and logs messages before and after the promise is created and when the promise is fulfilled: new Promise(function (resolve) { resolve(); }).then(function (result) { console.log('Promise Completed'); }); Add a second argument to the promise callback named reject, and call reject with a new error: new Promise(function (resolve, reject) { reject(new Error('Something went wrong'); }).then(function (result) { console.log('Promise Completed'); }); Chain a catch call off the promise. Pass a function that logs out its only argument: new Promise(function (resolve, reject) { reject(new Error('Something went wrong'); }).then(function (result) { console.log('Promise Completed'); }).catch(function (error) { console.error(error); }); Start your Python web server and open the following link in your browser: http://localhost:8000/. You should see the following output: How it works... Previously we saw how to use resolve to return a value in the case of a successful fulfillment of a promise. In this case, we called reject before resolve. This means that the Promise finished with an error before it could resolve. When the Promise completes in an error state, the then callbacks are not executed. Instead we have to use catch in order to receive the error that the Promise rejects. You'll also notice that the catch callback is only executed after the main function has returned. Like successful fulfillment, listeners to unsuccessful ones execute asynchronously. See also Handle errors with Promise.catch Simulating finally with Promise.then Chaining Promises So far in this article, we've seen how to use promises to run single asynchronous tasks. This is helpful but doesn't provide a significant improvement over the callback pattern. The real advantage that promises offer comes when they are composed. In this recipe, we'll use promises to combine asynchronous functions in series. How to do it... Open your command-line application and navigate to your workspace. Create a new folder named 3-04-chaining-promises. Copy or create an index.html that loads and runs a main function from main.js. Create a main.js file that creates a promise. Resolve a random number from the promise: new Promise(function (resolve) { resolve(Math.random()); }); ); Chain a then call off of the promise. Return true from the callback if the random value is greater than or equal to 0.5: new Promise(function (resolve, reject) { resolve(Math.random()); }).then(function(value) { return value >= 0.5; }); Chain a final then call after the previous one. Log out a different message if the argument is true or false: new Promise(function (resolve, reject) { resolve(Math.random()); }).then(function (value) { return value >= 0.5; }).then(function (isReadyForLaunch) { if (isReadyForLaunch) { console.log('Start the countdown! '); } else { console.log('Abort the mission. '); } }); Start your Python web server and open the following link in your browser: http://localhost:8000/. If you are lucky, you'll see the following output: If you are unlucky, we'll see the following output: How it works... We've already seen how to use then to wait for the result of a promise. Here, we are doing the same thing multiple times in a row. This is called a promise chain. After the promise chain is started with the new promise, all of the subsequent links in the promise chain return promises as well. That is, the callback of each then function is resolve like another promise. See also Using Promise.all to resolve multiple Promises Handle errors with Promise.catch Simulating finally with a final Promise.then call Starting a Promise chain with Promise.resolve In this article's preceding recipes, we've been creating new promise objects with the constructor. This gets the jobs done, but it creates a problem. The first callback in the promise chain has a different shape than the subsequent callbacks. In the first callback, the arguments are the resolve and reject functions that trigger the subsequent then or catch callbacks. In subsequent callbacks, the returned value is propagated down the chain, and thrown errors are captured by catch callbacks. This difference adds mental overhead. It would be nice to have all of the functions in the chain behave in the same way. In this recipe, we'll see how to use Promise.resolve to start a promise chain. How to do it... Open your command-line application and navigate to your workspace. Create a new folder named 3-05-starting-with-resolve. Copy or create an index.html that loads and runs a main function from main.js. Create a main.js file that calls Promise.resolve with an empty object as the first argument: export function main () { Promise.resolve({}) } Chain a then call off of resolve, and attach rocket boosters to the passed object: export function main () { Promise.resolve({}).then(function (rocket) { console.log('attaching boosters'); rocket.boosters = [{ count: 2, fuelType: 'solid' }, { count: 1, fuelType: 'liquid' }]; return rocket; }) } Add a final then call to the chain that lets you know when the boosters have been added: export function main () { Promise.resolve({}) .then(function (rocket) { console.log('attaching boosters'); rocket.boosters = [{ count: 2, fuelType: 'solid' }, { count: 1, fuelType: 'liquid' }]; return rocket; }) .then(function (rocket) { console.log('boosters attached'); console.log(rocket); }) } Start your Python web server and open the following link in your browser: http://localhost:8000/. You should see the following output: How it works... Promise.resolve creates a new promise that resolves the value passed to it. The subsequent then method will receive that resolved value as it's argument. This method can seem a little roundabout but can be very helpful for composing asynchronous functions. In effect, the constituents of the promise chain don't need to be aware that they are in the chain (including the first step). This makes transitioning from code that doesn't use promises to code that does much easier. Using Promise.all to resolve multiple promises So far, we've seen how to use promises to perform asynchronous operations in sequence. This is useful when the individual steps are long-running operations. However, this might not always be the more efficient configuration. Quite often, we can perform multiple asynchronous operations at the same time. In this recipe, we'll see how to use Promise.all to start multiple asynchronous operations, without waiting for the previous one to complete. How to do it... Open your command-line application and navigate to your workspace. Create a new folder named 3-06-using-promise-all. Copy or create an index.html that loads and runs a main function from main.js. Create a main.js file that creates an object named rocket, and calls Promise.all with an empty array as the first argument: export function main() { console.log('Before promise created'); const rocket = {}; Promise.all([]) console.log('After promise created'); } Create a function named addBoosters that creates an object with boosters to an object: function addBoosters (rocket) { console.log('attaching boosters'); rocket.boosters = [{ count: 2, fuelType: 'solid' }, { count: 1, fuelType: 'liquid' }]; return rocket; } Create a function named performGuidanceDiagnostic that returns a promise of a successfully completed task: function performGuidanceDiagnostic (rocket) { console.log('performing guidance diagnostic'); return new Promise(function (resolve) { setTimeout(function () { console.log('guidance diagnostic complete'); rocket.guidanceDiagnostic = 'Completed'; resolve(rocket); }, 2000); }); } Create a function named loadCargo that adds a payload to the cargoBay: function loadCargo (rocket) { console.log('loading satellite'); rocket.cargoBay = [{ name: 'Communication Satellite' }] return rocket; } Use Promise.resolve to pass the rocket object to these functions within Promise.all: export function main() { console.log('Before promise created'); const rocket = {}; Promise.all([ Promise.resolve(rocket).then(addBoosters), Promise.resolve(rocket).then(performGuidanceDiagnostic), Promise.resolve(rocket).then(loadCargo) ]); console.log('After promise created'); } Attach a then call to the chain and log that the rocket is ready for launch: const rocket = {}; Promise.all([ Promise.resolve(rocket).then(addBoosters), Promise.resolve(rocket).then(performGuidanceDiagnostic), Promise.resolve(rocket).then(loadCargo) ]).then(function (results) { console.log('Rocket ready for launch'); console.log(results); }); Start your Python web server and open the following link in your browser: http://localhost:8000/. You should see the following output: How it works... Promise.all is similar to Promise.resolve; the arguments are resolved as promises. The difference is that instead of a single result, Promise.all accepts an iterable argument, each member of which is resolved individually. In the preceding example, you can see that each of the promises is initiated immediately. Two of them are able to complete while performGuidanceDiagnostic continues. The promise returned by Promise.all is fulfilled when all the constituent promises have been resolved. The results of the promises are combined into an array and propagated down the chain. You can see that three references to rocket are packed into the results argument. And you can see that the operations of each promise have been performed on the resulting object. There's more As you may have guessed, the results of the constituent promises don't have to return the same value. This can be useful, for example, when performing multiple independent network requests. The index of the result for each promise corresponds to the index of the operation within the argument to Promise.all. In these cases, it can be useful to use array destructuring to name the argument of the then callback: Promise.all([ findAstronomers, findAvailableTechnicians, findAvailableEquipment ]).then(function ([astronomers, technicians, equipment]) { // use results for astronomers, technicians, and equipment }); Handling errors with Promise.catch In a previous recipe, we saw how to fulfill a promise with an error state using reject, and we saw that this triggers the next catch callback in the promise chain. Because promises are relatively easy to compose, we need to be able to handle errors that are reported in different ways. Luckily promises are able to handle this seamlessly. In this recipe, we'll see how Promises.catch can handle errors that are reported by being thrown or through rejection. How to do it... Open your command-line application and navigate to your workspace.  Create a new folder named 3-07-handle-errors-promise-catch. Copy or create an index.html that loads and runs a main function from main.js. Create a main.js file with a main function that creates an object named rocket: export function main() { console.log('Before promise created'); const rocket = {}; console.log('After promise created'); } Create a function addBoosters that throws an error: function addBoosters (rocket) { throw new Error('Unable to add Boosters'); } Create a function performGuidanceDiagnostic that returns a promise that rejects an error: function performGuidanceDiagnostic (rocket) { return new Promise(function (resolve, reject) { reject(new Error('Unable to finish guidance diagnostic')); }); } Use Promise.resolve to pass the rocket object to these functions, and chain a catch off each of them: export function main() { console.log('Before promise created'); const rocket = {}; Promise.resolve(rocket).then(addBoosters) .catch(console.error); Promise.resolve(rocket).then(performGuidanceDiagnostic) .catch(console.error); console.log('After promise created'); } Start your Python web server and open the following link in your browser: http://localhost:8000/. You should see the following output: How it works... As we saw before, when a promise is fulfilled in a rejected state, the callback of the catch functions is triggered. In the preceding recipe, we see that this can happen when the reject method is called (as with performGuidanceDiagnostic). It also happens when a function in the chain throws an error (as will addBoosters). This has similar benefit to how Promise.resolve can normalize asynchronous functions. This handling allows asynchronous functions to not know about the promise chain, and announce error states in a way that is familiar to developers who are new to promises. This makes expanding the use of promises much easier. Simulating finally with the promise API In a previous recipe, we saw how catch can be used to handle errors, whether a promise has rejected, or a callback has thrown an error. Sometimes, it is desirable to execute code whether or not an error state has been detected. In the context of try/catch blocks, the finally block can be used for this purpose. We have to do a little more work to get the same behavior when working with promises In this recipe, we'll see how a final then call to execute some code in both successful and failing fulfillment states. How to do it... Open your command-line application and navigate to your workspace.  Create a new folder named 3-08-simulating-finally. Copy or create an index.html that loads and runs a main function from main.js. Create a main.js file with a main function that logs out messages for before and after promise creation: export function main() { console.log('Before promise created'); console.log('After promise created'); } Create a function named addBoosters that throws an error if its first parameter is false: function addBoosters(shouldFail) { if (shouldFail) { throw new Error('Unable to add Boosters'); } return { boosters: [{ count: 2, fuelType: 'solid' }, { count: 1, fuelType: 'liquid' }] }; } Use Promise.resolve to pass a Boolean value that is true if a random number is greater than 0.5 to addBoosters: export function main() { console.log('Before promise created'); Promise.resolve(Math.random() > 0.5) .then(addBoosters) console.log('After promise created'); } Add a then function to the chain that logs a success message: export function main() { console.log('Before promise created'); Promise.resolve(Math.random() > 0.5) .then(addBoosters) .then(() => console.log('Ready for launch: ')) console.log('After promise created'); } Add a catch to the chain and log out the error if thrown: export function main() { console.log('Before promise created'); Promise.resolve(Math.random() > 0.5) .then(addBoosters) .then(() => console.log('Ready for launch: ')) .catch(console.error) console.log('After promise created'); } Add a then after the catch, and log out that we need to make an announcement: export function main() { console.log('Before promise created'); Promise.resolve(Math.random() > 0.5) .then(addBoosters) .then(() => console.log('Ready for launch: ')) .catch(console.error) .then(() => console.log('Time to inform the press.')); console.log('After promise created'); } Start your Python web server and open the following link in your browser: http://localhost:8000/. If you are lucky and the boosters are added successfully, you'll see the following output: 12. If you are unlucky, you'll see an error message like the following: How it works... We can see in the preceding output that whether or not the asynchronous function completes in an error state, the last then callback is executed. This is possible because the catch method doesn't stop the promise chain. It simply catches any error states from the previous links in the chain, and then propagates a new value forward. The final then is then protected from being bypassed by an error state by this catch. And so, regardless of the fulfillment state of prior links in the chain, we can be sure that the callback of this final then will be executed. To summarize, we learned how to use the Promise API to organize asynchronous programs. We also looked at how to propagate results through promise chains and handle errors.  You read an excerpt from a book written by Ross Harrison, titled ECMAScript Cookbook. It’s a complete guide on how to become a better web programmer by writing efficient and modular code using ES6 and ES8. What’s new in ECMAScript 2018 (ES9)? ECMAScript 7 – What to expect? Modular Programming in ECMAScript 6  
Read more
  • 0
  • 0
  • 2860

article-image-internationalization-localization-node-js-app
Packt Editorial Staff
07 May 2018
15 min read
Save for later

How to implement Internationalization and localization in your Node.js app

Packt Editorial Staff
07 May 2018
15 min read
Internationalization, often abbreviated as i18n, implies a particular software design capable of adapting to the requirements of target local markets. In other words if we want to distribute our application to the markets other than USA we need to take care of translations, formatting of datetime, numbers, addresses, and such. In today’s post we will cover the concept of implementing Internationalization and localization in the Node.js app and look at context menu and system clipboard in detail. Date format by country Internationalization is a cross-cutting concern. When you are changing the locale it usually affects multiple modules. So I suggest going with the observer pattern that we already examined while working on DirService'. The ./js/Service/I18n.jsfile contains the following code: constEventEmitter=require("events"); classI18nServiceextendsEventEmitter{ constructor(){ super(); this.locale="en-US"; } notify(){ this.emit("update"); } } exports.I18nService=I18nService; As you see, we can change the locale by setting a new value to localeproperty. As soon as we call notifymethod, then all the subscribed modules immediately respond. But localeis a public property and therefore we have no control on its access and mutation. We can fix it by using overloading. The ./js/Service/I18n.jsfile contains the following code: //...constructor(){ super(); this._locale="en-US"; } getlocale(){ returnthis._locale; } setlocale(locale){ //validatelocale...this._locale=locale; } //... Now if we access localeproperty of I18ninstance it gets delivered by the getter (getlocale). When setting it a value, it goes through the setter (setlocale). Thus we can add extra functionality such as validation and logging on property access and mutation. Remember we have in the HTML, a combobox for selecting language. Why not give it a view? The ./js/View/LangSelector.jfile contains the following code: classLangSelectorView{ constructor(boundingEl,i18n){ boundingEl.addEventListener("change",this.onChanged.bind(this),false); this.i18n=i18n; } onChanged(e){ constselectEl=e.target;this.i18n.locale=selectEl.value;this.i18n.notify(); } } exports.LangSelectorView=LangSelectorView; In the preceding code, we listen for change events on the combobox. When the event occurs we change localeproperty of the passed in I18ninstance and call notifyto inform the subscribers. The ./js/app.jsfile contains the following code: consti18nService=newI18nService(), {LangSelectorView}=require("./js/View/LangSelector"); newLangSelectorView(document.querySelector("[data-bind=langSelector]"),i18nService); Well, we can change the locale and trigger the event. What about consuming modules? In FileListview we have static method formatTimethat formats the passed in timeStringfor printing. We can make it formated in accordance with currently chosen locale. The ./js/View/FileList.jsfile contains the following code: constructor(boundingEl,dirService,i18nService){ //... this.i18n=i18nService; //Subscribeoni18nServiceupdates i18nService.on("update",()=>this.update( dirService.getFileList())); } staticformatTime(timeString,locale){ constdate=newDate(Date.parse(timeString)),options={ year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"numeric",second:"numeric",hour12:false }; returndate.toLocaleString(locale,options); } update(collection){ //... this.el.insertAdjacentHTML("beforeend",`<liclass="file-listli"data-file="${fInfo.fileName}"> <spanclass="file-listliname">${fInfo.fileName}</span> <spanclass="file- listlisize">${filesize(fInfo.stats.size)}</span> <spanclass="file-listlitime">${FileListView.formatTime( fInfo.stats.mtime,this.i18n.locale)}</span> </li>`); //... } //... In the constructor, we subscribe for I18nupdate event and update the file list every time the locale changes. Static method formatTimeconverts passed in string into a Dateobject and uses Date.prototype.toLocaleString()method to format the datetime according to a given locale. This method belongs to so called ECMAScript Internationalization API (http://norbertlindenberg.com/2012/12/ecmascript-internationalization-api/index.html). The API describes methods of built-in object String, Dateand Numberdesigned to format and compare localized data. But what it really does is formatting a Dateinstance with toLocaleStringfor the English (United States) locale ("en-US") and it returns the date as follows: 3/17/2017, 13:42:23 However if we feed to the method German locale ("de-DE") we get quite a different result: 17.3.2017, 13:42:23 To put it into action we set an identifier to the combobox. The ./index.htmlfile contains the following code: .. <selectclass="footerselect"data-bind="langSelector"> .. And of course, we have to create an instance of I18nservice and pass it in LangSelectorViewand FileListView: ./js/app.js //... const{I18nService}=require("./js/Service/I18n"), {LangSelectorView}=require("./js/View/LangSelector"),i18nService=newI18nService(); newLangSelectorView(document.querySelector("[data-bind=langSelector]"),i18nService); //... newFileListView(document.querySelector("[data-bind=fileList]"),dirService,i18nService); Now we start the application. Yeah! As we change the language in the combobox the file modification dates adjust accordingly: Multilingual support Localization dates and number is a good thing, but it would be more exciting to provide translation to multiple languages. We have a number of terms across the application, namely the column titles of the file list and tooltips (via titleattribute) on windowing action buttons. What we need is a dictionary. Normally it implies sets of token translation pairs mapped to language codes or locales. Thus when you request from the translation service a term, it can correlate to a matching translation according to currently used language/locale. Here I have suggested making the dictionary as a static module that can be loaded with the required function. The ./js/Data/dictionary.jsfile contains the following code: exports.dictionary={"en-US":{ NAME:"Name",SIZE:"Size",MODIFIED:"Modified", MINIMIZE_WIN:"Minimizewindow", RESTORE_WIN:"Restorewindow",MAXIMIZE_WIN:"Maximizewindow",CLOSE_WIN:"Closewindow" }, "de-DE":{ NAME:"Dateiname",SIZE:"Grösse", MODIFIED:"Geändertam",MINIMIZE_WIN:"Fensterminimieren",RESTORE_WIN:"Fensterwiederherstellen",MAXIMIZE_WIN:"Fenstermaximieren", CLOSE_WIN:"Fensterschliessen" } }; So we have two locales with translations per term. We are going to inject the dictionary as a dependency into our I18nservice. The ./js/Service/I18n.jsfile contains the following code: //... constructor(dictionary){ super(); this.dictionary=dictionary; this._locale="en-US"; } translate(token,defaultValue){ constdictionary=this.dictionary[this._locale]; returndictionary[token]||defaultValue; } //... We also added a new method translate that accepts two parameters: tokenand defaulttranslation. The first parameter can be one of the keys from the dictionary like NAME. The second one is guarding value for the case when requested token does not yet exist in the dictionary. Thus we still get a meaningful text at least in English. Let's see how we can use this new method. The ./js/View/FileList.jsfile contains the following code: //... update(collection){ this.el.innerHTML=`<liclass="file-listlifile-listhead"> <spanclass="file-listliname">${this.i18n.translate("NAME","Name")}</span> <spanclass="file-listlisize">${this.i18n.translate("SIZE", "Size")}</span> <spanclass="file-listlitime">${this.i18n.translate("MODIFIED","Modified")}</span> </li>`; //... We change in FileListview hardcoded column titles with calls for translatemethod of I18ninstance, meaning that every time view updates it receives the actual translations. We shall not forget about TitleBarActionsview where we have windowing action buttons. The ./js/View/TitleBarActions.jsfile contains the following code: constructor(boundingEl,i18nService){ this.i18n=i18nService; //... //Subscribeoni18nServiceupdates i18nService.on("update",()=>this.translate()); } translate(){ this.unmaximizeEl.title=this.i18n.translate("RESTORE_WIN","Restorewindow"); this.maximizeEl.title=this.i18n.translate("MAXIMIZE_WIN","Maximizewindow"); this.minimizeEl.title=this.i18n.translate("MINIMIZE_WIN","Minimizewindow"); this.closeEl.title=this.i18n.translate("CLOSE_WIN","Closewindow"); } Here we add method translate, which updates button title attributes with actual translations. We subscribe for i18nupdate event to call the method every time user changes locale: Context menu Well, with our application we can already navigate through the file system and open files. Yet, one might expect more of a File Explorer. We can add some file related actions like delete, copy/paste. Usually these tasks are available via the context menu, what gives us a good opportunity to examine how to make it with NW.js. With the environment integration API we can create an instance of system menu (http://docs.nwjs.io/en/latest/References/Menu/). Then we compose objects representing menu items and attach them to the menu instance (http://docs.nwjs.io/en/latest/References/MenuItem/). This menucan be shown in an arbitrary position: constmenu=newnw.Menu(),menutItem=newnw.MenuItem({ label:"Sayhello", click:()=>console.log("hello!") }); menu.append(menu); menu.popup(10,10); Yet our task is more specific. We have to display the menu on the right mouse click in the position of the cursor. That is, we achieve by subscribing a handler to contextmenuDOM event: document.addEventListener("contextmenu",(e)=>{ console.log(`Showmenuinposition${e.x},${e.y}`); }); Now whenever we right-click within the application window the menu shows up. It's not exactly what we want, isn't it? We need it only when the cursor resides within a particular region. For an instance, when it hovers a file name. That means we have to test if the target element matches our conditions: document.addEventListener("contextmenu",(e)=>{ constel=e.target; if(elinstanceofHTMLElement&&el.parentNode.dataset.file){ console.log(`Showmenuinposition${e.x},${e.y}`); } }); Here we ignore the event until the cursor hovers any cell of file table row, given every row is a list item generated by FileListview and therefore provided with a value for data file attribute. This passage explains pretty much how to build a system menu and how to attach it to the file list. But before starting on a module capable of creating menu, we need a service to handle file operations. The ./js/Service/File.jsfile contains the following code: constfs=require("fs"), path=require("path"), //Copyfilehelper cp=(from,toDir,done)=>{ constbasename=path.basename(from),to=path.join(toDir,basename),write=fs.createWriteStream(to); fs.createReadStream(from) .pipe(write); write .on("finish",done); }; classFileService{ constructor(dirService){this.dir=dirService;this.copiedFile=null; } remove(file){ fs.unlinkSync(this.dir.getFile(file)); this.dir.notify(); } paste(){ constfile=this.copiedFile; if(fs.lstatSync(file).isFile()){ cp(file,this.dir.getDir(),()=>this.dir.notify()); } } copy(file){ this.copiedFile=this.dir.getFile(file); } open(file){ nw.Shell.openItem(this.dir.getFile(file)); } showInFolder(file){ nw.Shell.showItemInFolder(this.dir.getFile(file)); } }; exports.FileService=FileService; What's going on here? FileServicereceives an instance of DirServiceas a constructor argument. It uses the instance to obtain the full path to a file by name ( this.dir.getFile(file)). It also exploits notifymethod of the instance to request all the views subscribed to DirServiceto update. Method showInFoldercalls the corresponding method of nw.Shellto show the file in the parent folder with the system file manager. As you can recon method removedeletes the file. As for copy/paste we do the following trick. When user clicks copy we store the target file path in property copiedFile. So when user next time clicks paste we can use it to copy that file to the supposedly changed current location. Method openevidently opens file with the default associated program. That is what we do in FileListview directly. Actually this action belongs to FileService. So we rather refactor the view to use the service. The ./js/View/FileList.jsfile contains the following code: constructor(boundingEl,dirService,i18nService,fileService){ this.file=fileService; //... } bindUi(){ //... this.file.open(el.dataset.file); //... } Now we have a module to handle context menu for a selected file. The module will subscribe for contextmenuDOM event and build a menu when user right clicks on a file. This menu will contain items Show Item in the Folder, Copy, Paste, and Delete. Whereas copy and paste are separated from other items with delimiters. Besides, Paste will be disabled until we store a file with copy. Further goes the source code. The ./js/View/ContextMenu.jsfile contains the following code: classConextMenuView{ constructor(fileService,i18nService){ this.file=fileService;this.i18n=i18nService;this.attach(); } getItems(fileName){ constfile=this.file, isCopied=Boolean(file.copiedFile); return[ { label:this.i18n.translate("SHOW_FILE_IN_FOLDER","ShowItemintheFolder"), enabled:Boolean(fileName), click:()=>file.showInFolder(fileName) }, { type:"separator" }, { label:this.i18n.translate("COPY","Copy"),enabled:Boolean(fileName), click:()=>file.copy(fileName) }, { label:this.i18n.translate("PASTE","Paste"),enabled:isCopied, click:()=>file.paste() }, { type:"separator" }, { label:this.i18n.translate("DELETE","Delete"),enabled:Boolean(fileName), click:()=>file.remove(fileName) } ]; } render(fileName){ constmenu=newnw.Menu(); this.getItems(fileName).forEach((item)=>menu.append(newnw.MenuItem(item))); returnmenu; } attach(){ document.addEventListener("contextmenu",(e)=>{ constel=e.target; if(!(elinstanceofHTMLElement)){ return; } if(el.classList.contains("file-list")){ e.preventDefault(); this.render() .popup(e.x,e.y); } //Ifachildofanelementmatching[data-file] if(el.parentNode.dataset.file){ e.preventDefault(); this.render(el.parentNode.dataset.file) .popup(e.x,e.y); } }); } } exports.ConextMenuView=ConextMenuView; So in ConextMenuViewconstructor, we receive instances of FileServiceand I18nService. During the construction we also call attach method that subscribes for contextmenuDOM event, creates the menu and shows it in the position of the mouse cursor. The event gets ignored unless the cursor hovers a file or resides in empty area of the file list component. When user right clicks the file list, the menu still appears, but with all items disable except paste (in case a file was copied before). Method render create an instance of menu and populates it with nw.MenuItemscreated by getItemsmethod. The method creates an array representing menu items. Elements of the array are object literals. Property labelaccepts translation for item caption. Property enableddefines the state of item depending on our cases (whether we have copied file or not, whether the cursor on a file or not). Finally property clickexpects the handler for click event. Now we need to enable our new components in the main module. The ./js/app.jsfile contains the following code: const{FileService}=require("./js/Service/File"), {ConextMenuView}=require("./js/View/ConextMenu"),fileService=newFileService(dirService); newFileListView(document.querySelector("[data-bind=fileList]"),dirService,i18nService,fileService); newConextMenuView(fileService,i18nService); Let's now run the application, right-click on a file and voilà! We have the context menu and new file actions. System clipboard Usually Copy/Paste functionality involves system clipboard. NW.jsprovides an API to control it (http://docs.nwjs.io/en/latest/References/Clipboard/). Unfortunately it's quite limited, we cannot transfer an arbitrary file between applications, what you may expect of a file manager. Yet some things we are still available to us. Transferring text In order to examine text transferring with the clipboard we modify the method copy of FileService: copy(file){ this.copiedFile=this.dir.getFile(file);constclipboard=nw.Clipboard.get();clipboard.set(this.copiedFile,"text"); } What does it do? As soon as we obtained file full path, we create an instance of nw.Clipboardand save the file path there as a text. So now, after copying a file within the File Explorer we can switch to an external program (for example, a text editor) and paste the copied path from the clipboard. Transferring graphics It doesn't look very handy, does it? It would be more interesting if we could copy/paste a file. Unfortunately NW.jsdoesn't give us many options when it comes to file exchange. Yet we can transfer between NW.jsapplication and external programs PNG and JPEG images. The ./js/Service/File.jsfile contains the following code: //... copyImage(file,type){ constclip=nw.Clipboard.get(), //loadfilecontentasBase64 data=fs.readFileSync(file).toString("base64"), //imageasHTML html=`<imgsrc="file:///${encodeURI(data.replace(/^//,"") )}">`; //writebothoptions(rawimageandHTML)totheclipboardclip.set([ {type,data:data,raw:true}, {type:"html",data:html} ]); } copy(file){ this.copiedFile=this.dir.getFile(file); constext=path.parse(this.copiedFile).ext.substr(1); switch(ext){case"jpg":case"jpeg": returnthis.copyImage(this.copiedFile,"jpeg"); case"png": returnthis.copyImage(this.copiedFile,"png"); } } //... We extended our FileServicewith private method copyImage. It reads a given file, converts its contents in Base64 and passes the resulting code in a clipboard instance. In addition, it creates HTML with image tag with Base64-encoded image in data Uniform Resource Identifier (URI). Now after copying an image (PNG or JPEG) in the File Explorer, we can paste it in an external program such as graphical editor or text processor. Receiving text and graphics We've learned how to pass a text and graphics from our NW.jsapplication to external programs. But how can we receive data from outside? As you can guess it is accessible through get method of nw.Clipboard. Text can be retrieved that simple: constclip=nw.Clipboard.get(); console.log(clip.get("text")); When graphic is put in the clipboard we can get it with NW.js only as Base64-encoded content or as HTML. To see it in practice we add a few methods to FileService. The ./js/Service/File.jsfile contains the following code: //...hasImageInClipboard(){ constclip=nw.Clipboard.get(); returnclip.readAvailableTypes().indexOf("png")!==-1; } pasteFromClipboard(){ constclip=nw.Clipboard.get(); if(this.hasImageInClipboard()){ constbase64=clip.get("png",true), binary=Buffer.from(base64,"base64"),filename=Date.now()+"--img.png"; fs.writeFileSync(this.dir.getFile(filename),binary); this.dir.notify(); } } //... Method hasImageInClipboardchecks if the clipboard keeps any graphics. Method pasteFromClipboardtakes graphical content from the clipboard as Base64-encoded PNG. It converts the content into binary code, writes into a file and requests DirServicesubscribers to update. To make use of these methods we need to edit ContextMenuview. The ./js/View/ContextMenu.jsfile contains the following code: getItems(fileName){ constfile=this.file, isCopied=Boolean(file.copiedFile); return[ //... { label:this.i18n.translate("PASTE_FROM_CLIPBOARD","Pasteimagefromclipboard"), enabled:file.hasImageInClipboard(), click:()=>file.pasteFromClipboard() }, //... ]; } We add to the menu a new item Pasteimagefromclipboard, which is enabled only when there is any graphic in the clipboard. [box type="shadow" align="" class="" width=""]This article is an excerpt from the book Cross Platform Desktop Application Development: Electron, Node, NW.js and React written by Dmitry Sheiko. This book will help you build powerful cross-platform desktop applications with web technologies such as Node, NW.JS, Electron, and React.[/box] Read More: How to deploy a Node.js application to the web using Heroku How is Node.js Changing Web Development? With Node.js, it’s easy to get things done  
Read more
  • 0
  • 0
  • 11719

article-image-single-responsibility-principle-solid-net-core
Aaron Lazar
07 May 2018
7 min read
Save for later

Applying Single Responsibility principle from SOLID in .NET Core

Aaron Lazar
07 May 2018
7 min read
In today's tutorial, we'll learn how to apply the Single Responsibility principle from the SOLID principles, to .NET Core Applications. This brings us to another interesting concept in OOP called SOLID design principles. These design principles are applied to any OOP design and are intended to make software easier to understand, more flexible, and easily maintainable. [box type="shadow" align="" class="" width=""]This article is an extract from the book C# 7 and .NET Core Blueprints, authored by Dirk Strauss and Jas Rademeyer. The book is a step-by-step guide that will teach you the essential .NET Core and C# concepts with the help of real-world projects.[/box] The term SOLID is a mnemonic for: Single responsibility principle Open/closed principle Liskov substitution principle Interface segregation principle Dependency inversion principle In this article, we will take a look at the first of the principles—the single responsibility principle. Let's look at the single responsibility principle now. Single responsibility principle Simply put, a module or class should have the following characteristics only: It should do one single thing and only have a single reason to change It should do its one single thing well The functionality provided needs to be entirely encapsulated by that class or module What is meant when saying that a module must be responsible for a single thing? The Google definition of a module is: "Each of a set of standardized parts or independent units that can be used to construct a more complex structure, such as an item of furniture or a building." From this, we can understand that a module is a simple building block. It can be used or reused to create something bigger and more complex when used with other modules. In C# therefore, the module does closely resemble a class, but I will go so far as to say that a module can also be extended to be a method. The function that the class or module performs can only be one thing. That is to say that it has a narrow responsibility. It is not concerned with anything else other than doing that one thing it was designed to do. If we had to apply the single responsibility principle to a person, then that person would be only a software developer, for example. But what if a software developer also was a doctor and a mechanic and a school teacher? Would that person be effective in any of those roles? That would contravene the single responsibility principle. The same is true for code. Having a look at our AllRounder and Batsman classes, you will notice that in AllRounder, we have the following code: private double CalculateStrikeRate(StrikeRate strikeRateType) { switch (strikeRateType) { case StrikeRate.Bowling: return (BowlerBallsBowled / BowlerWickets); case StrikeRate.Batting: return (BatsmanRuns * 100) / BatsmanBallsFaced; default: throw new Exception("Invalid enum"); } } public override int CalculatePlayerRank() { return 0; } In Batsman, we have the following code: public double BatsmanBattingStrikeRate => (BatsmanRuns * 100) / BatsmanBallsFaced; public override int CalculatePlayerRank() { return 0; } Using what we have learned about the single responsibility principle, we notice that there is an issue here. To illustrate the problem, let's compare the code side by side: We are essentially repeating code in the Batsman and AllRounder classes. This doesn't really bode well for single responsibility, does it? I mean, the one principle is that a class must only have a single function to perform. At the moment, both the Batsman and AllRounder classes are taking care of calculating strike rates. They also both take care of calculating the player rank. They even both have exactly the same code for calculating the strike rate of a batsman! The problem comes in when the strike rate calculation changes (not that it easily would, but let's assume it does). We now know that we have to change the calculation in both places. As soon as the developer changes one calculation and not the other, a bug is introduced into our application. Let's simplify our classes. In the BaseClasses folder, create a new abstract class called Statistics. The code should look as follows: namespace cricketScoreTrack.BaseClasses { public abstract class Statistics { public abstract double CalculateStrikeRate(Player player); public abstract int CalculatePlayerRank(Player player); } } In the Classes folder, create a new derived class called PlayerStatistics (that is to say it inherits from the Statistics abstract class). The code should look as follows: using cricketScoreTrack.BaseClasses; using System; namespace cricketScoreTrack.Classes { public class PlayerStatistics : Statistics { public override int CalculatePlayerRank(Player player) { return 1; } public override double CalculateStrikeRate(Player player) { switch (player) { case AllRounder allrounder: return (allrounder.BowlerBallsBowled / allrounder.BowlerWickets); case Batsman batsman: return (batsman.BatsmanRuns * 100) / batsman.BatsmanBallsFaced; default: throw new ArgumentException("Incorrect argument supplied"); } } } } You will see that the PlayerStatistics class is now solely responsible for calculating player statistics for the player's rank and the player's strike rate. You will see that I have not included much of an implementation for calculating the player's rank. I briefly commented the code on GitHub for this method on how a player's rank is determined. It is quite a complicated calculation and differs for batsmen and bowlers. I have therefore omitted it for the purposes of this chapter on OOP. Your Solution should now look as follows: Swing back over to your Player abstract class and remove abstract public int CalculatePlayerRank(); from the class. In the IBowler interface, remove the double BowlerStrikeRate { get; } property. In the IBatter interface, remove the double BatsmanBattingStrikeRate { get; } property. In the Batsman class, remove public double BatsmanBattingStrikeRate and public override int CalculatePlayerRank() from the class. The code in the Batsman class will now look as follows: using cricketScoreTrack.BaseClasses; using cricketScoreTrack.Interfaces; namespace cricketScoreTrack.Classes { public class Batsman : Player, IBatter { #region Player public override string FirstName { get; set; } public override string LastName { get; set; } public override int Age { get; set; } public override string Bio { get; set; } #endregion #region IBatsman public int BatsmanRuns { get; set; } public int BatsmanBallsFaced { get; set; } public int BatsmanMatch4s { get; set; } public int BatsmanMatch6s { get; set; } #endregion } } Looking at the AllRounder class, remove the public enum StrikeRate { Bowling = 0, Batting = 1 } enum as well as the public double BatsmanBattingStrikeRate and public double BowlerStrikeRate properties. Lastly, remove the private double CalculateStrikeRate(StrikeRate strikeRateType) and public override int CalculatePlayerRank() methods. The code for the AllRounder class now looks as follows: using cricketScoreTrack.BaseClasses; using cricketScoreTrack.Interfaces; using System; namespace cricketScoreTrack.Classes { public class AllRounder : Player, IBatter, IBowler { #region Player public override string FirstName { get; set; } public override string LastName { get; set; } public override int Age { get; set; } public override string Bio { get; set; } #endregion #region IBatsman public int BatsmanRuns { get; set; } public int BatsmanBallsFaced { get; set; } public int BatsmanMatch4s { get; set; } public int BatsmanMatch6s { get; set; } #endregion #region IBowler public double BowlerSpeed { get; set; } public string BowlerType { get; set; } public int BowlerBallsBowled { get; set; } public int BowlerMaidens { get; set; } public int BowlerWickets { get; set; } public double BowlerEconomy => BowlerRunsConceded / BowlerOversBowled; public int BowlerRunsConceded { get; set; } public int BowlerOversBowled { get; set; } #endregion } } Looking back at our AllRounder and Batsman classes, the code is clearly simplified. It is definitely more flexible and is starting to look like a well-constructed set of classes. Give your solution a rebuild and make sure that it is all working. So now you know how to simplify your .NET Core applications by applying the Single Responsibility principle. If you found this tutorial helpful and you'd like to learn more, go ahead and pick up the book C# 7 and .NET Core Blueprints, authored by Dirk Strauss and Jas Rademeyer. What is ASP.NET Core? How to call an Azure function from an ASP.NET Core MVC application How to dockerize an ASP.NET Core application  
Read more
  • 0
  • 0
  • 5695

article-image-distributed-tensorflow-multiple-gpu-server
Kunal Chaudhari
07 May 2018
12 min read
Save for later

Distributed TensorFlow: Working with multiple GPUs and servers

Kunal Chaudhari
07 May 2018
12 min read
Some neural networks models are so large they cannot fit in memory of a single device (GPU). Such models need to be split over many devices, carrying out the training in parallel on the devices. This means anyone can now scale out distributed training to 100s of GPUs using TensorFlow. But that’s not the only advantage of distributed TensorFlow, you can also massively reduce your experimentation time by running many experiments in parallel on many GPUs and servers. Today, we will discuss about distributed TensorFlow and present a number of recipes to work with TensorFlow, GPUs, and multiple servers. Working with TensorFlow and GPUs We will learn how to use TensorFlow with GPUs: the operation performed is a simple matrix multiplication either on CPU or on GPU. Getting ready The first step is to install a version of TensorFlow that supports GPUs. The official TensorFlow Installation Instruction is your starting point . Remember that you need to have an environment supporting GPUs either via CUDA or CuDNN. How to do it... We proceed with the recipe as follows: Start by importing a few modules import sys import numpy as np import tensorflow as tf from datetime import datetime Get from command line the type of processing unit that you desire to use (either "gpu" or "cpu") device_name = sys.argv[1] # Choose device from cmd line. Options: gpu or cpu shape = (int(sys.argv[2]), int(sys.argv[2])) if device_name == "gpu": device_name = "/gpu:0" else: device_name = "/cpu:0" Execute the matrix multiplication either on GPU or on CPU. The key instruction is with tf.device(device_name). It creates a new context manager, telling TensorFlow to perform those actions on either the GPU or the CPU with tf.device(device_name): random_matrix = tf.random_uniform(shape=shape, minval=0, maxval=1) dot_operation = tf.matmul(random_matrix, tf.transpose(random_matrix)) sum_operation = tf.reduce_sum(dot_operation) startTime = datetime.now() with tf.Session(config=tf.ConfigProto(log_device_placement=True)) as session: result = session.run(sum_operation) print(result)  Print some debug timing just to verify what is the difference between CPU and GPU print("Shape:", shape, "Device:", device_name) print("Time taken:", datetime.now() - startTime) How it works... This recipe explains how to assign TensorFlow computations either to CPUs or to GPUs. The code is pretty simple and it will be used as a basis for the next recipe. Playing with Distributed TensorFlow: multiple GPUs and one CPU We will show an example of data parallelism where data is split across multiple GPUs Getting ready This recipe is inspired by a good blog posting written by Neil Tenenholtz and available online: https://clindatsci.com/blog/2017/5/31/distributed-tensorflow How to do it... We proceed with the recipe as follows: Consider this piece of code which runs a matrix multiplication on a single GPU. # single GPU (baseline) import tensorflow as tf # place the initial data on the cpu with tf.device('/cpu:0'): input_data = tf.Variable([[1., 2., 3.], [4., 5., 6.], [7., 8., 9.], [10., 11., 12.]]) b = tf.Variable([[1.], [1.], [2.]]) # compute the result on the 0th gpu with tf.device('/gpu:0'): output = tf.matmul(input_data, b) # create a session and run with tf.Session() as sess: sess.run(tf.global_variables_initializer()) print sess.run(output) Partition the code with in graph replication as in the following snippet between 2 different GPUs. Note that the CPU is acting as the master node distributing the graph and collecting the final results. # in-graph replication import tensorflow as tf num_gpus = 2 # place the initial data on the cpu with tf.device('/cpu:0'): input_data = tf.Variable([[1., 2., 3.], [4., 5., 6.], [7., 8., 9.], [10., 11., 12.]]) b = tf.Variable([[1.], [1.], [2.]]) # split the data into chunks for each gpu inputs = tf.split(input_data, num_gpus) outputs = [] # loop over available gpus and pass input data for i in range(num_gpus): with tf.device('/gpu:'+str(i)): outputs.append(tf.matmul(inputs[i], b)) # merge the results of the devices with tf.device('/cpu:0'): output = tf.concat(outputs, axis=0) # create a session and run with tf.Session() as sess: sess.run(tf.global_variables_initializer()) print sess.run(output) How it works... This is a very simple recipe where the graph is split in two parts by the CPU acting as master and distributed to two GPUs acting as distributed workers. The result of the computation is collected back to the CPU. Playing with Distributed TensorFlow: multiple servers We will learn how to distribute a TensorFlow computation across multiple servers. The key assumption is that the code is same for both the workers and the parameter servers. Therefore the role of each computation node is passed by a command line argument. Getting ready Again, this recipe is inspired by a good blog posting written by Neil Tenenholtz and available online: https://clindatsci.com/blog/2017/5/31/distributed-tensorflow How to do it... We proceed with the recipe as follows: Consider this piece of code where we specify the cluster architecture with one master running on 192.168.1.1:1111 and two workers running on 192.168.1.2:1111 and 192.168.1.3:1111 respectively. import sys import tensorflow as tf # specify the cluster's architecture cluster = tf.train.ClusterSpec({'ps': ['192.168.1.1:1111'], 'worker': ['192.168.1.2:1111', '192.168.1.3:1111'] }) Note that the code is replicated on multiple machines and therefore it is important to know what is the role of the current execution node. This information we get from the command line. A machine can be either a worker or a parameter server (ps). # parse command-line to specify machine job_type = sys.argv[1] # job type: "worker" or "ps" task_idx = sys.argv[2] # index job in the worker or ps list # as defined in the ClusterSpec Run the training server where given a cluster, we bless each computational with a role (either worker or ps), and an id. # create TensorFlow Server. This is how the machines communicate. server = tf.train.Server(cluster, job_name=job_type, task_index=task_idx) The computation is different according to the role of the specific computation node: If the role is a parameter server, then the condition is to join the server. Note that in this case there is no code to execute because the workers will continuously push updates and the only thing that the Parameter Server has to do is waiting. Otherwise the worker code is executed on a specific device within the cluster. This part of code is similar to the one executed on a single machine where we first build the model and then we train it locally. Note that all the distribution of the work and the collection of the updated results is done transparently by Tensoflow. Note that TensorFlow provides a convenient tf.train.replica_device_setter that automatically assigns operations to devices. # parameter server is updated by remote clients. # will not proceed beyond this if statement. if job_type == 'ps': server.join() else: # workers only with tf.device(tf.train.replica_device_setter( worker_device='/job:worker/task:'+task_idx, cluster=cluster)): # build your model here as if you only were using a single machine with tf.Session(server.target): # train your model here How it works... We have seen how to create a cluster with multiple computation nodes. A node can be either playing the role of a Parameter server or playing the role of a worker. In both cases the code executed is the same but the execution of the code is different according to parameters collected from the command line. The parameter server only needs to wait until the workers send updates. Note that tf.train.replica_device_setter(..) takes the role of automatically assigning operations to available devices, while tf.train.ClusterSpec(..) is used for cluster setup. There is more... An example of distributed training for MNIST is available online. In addition, to that you can decide to have more than one parameter server for efficiency reasons. Using parameters the server can provide better network utilization, and it allows to scale models to more parallel machines. It is possible to allocate more than one parameter server. The interested reader can have a look in here. Training a Distributed TensorFlow MNIST classifier In this we trained a full MNIST classifier in a distributed way. This recipe is inspired by the blog post in http://ischlag.github.io/2016/06/12/async-distributed- tensorflow/ and the code running on TensorFlow 1.2 is available here https://github. com/ischlag/distributed-tensorflow-example Getting ready This recipe is based on the previous one. So it might be convenient to read them in order. How to do it... We proceed with the recipe as follows: Import a few standard modules and define the TensorFlow cluster where the computation is run. Then start a server for a specific task import tensorflow as tf import sys import time # cluster specification parameter_servers = ["pc-01:2222"] workers = [ "pc-02:2222", "pc-03:2222", "pc-04:2222"] cluster = tf.train.ClusterSpec({"ps":parameter_servers, "worker":workers}) # input flags tf.app.flags.DEFINE_string("job_name", "", "Either 'ps' or 'worker'") tf.app.flags.DEFINE_integer("task_index", 0, "Index of task within the job")FLAGS = tf.app.flags.FLAGS # start a server for a specific task server = tf.train.Server( cluster, job_name=FLAGS.job_name, task_index=FLAGS.task_index) Read MNIST data and define the hyperparameters used for training # config batch_size = 100 learning_rate = 0.0005 training_epochs = 20 logs_path = "/tmp/mnist/1" # load mnist data set from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets('MNIST_data', one_hot=True) Check if your role is Parameter Server or Worker. If worker then define a simple dense neural network, define an optimizer, and the metric used for evaluating the classifier (for example accuracy). if FLAGS.job_name == "ps": server.join() elif FLAGS.job_name == "worker": # Between-graph replication with tf.device(tf.train.replica_device_setter( worker_device="/job:worker/task:%d" % FLAGS.task_index, cluster=cluster)): # count the number of updates global_step = tf.get_variable( 'global_step', [], initializer = tf.constant_initializer(0), trainable = False) # input images with tf.name_scope('input'): # None -> batch size can be any size, 784 -> flattened mnist image x = tf.placeholder(tf.float32, shape=[None, 784], name="x-input") # target 10 output classes y_ = tf.placeholder(tf.float32, shape=[None, 10], name="y-input") # model parameters will change during training so we use tf.Variable tf.set_random_seed(1) with tf.name_scope("weights"): W1 = tf.Variable(tf.random_normal([784, 100])) W2 = tf.Variable(tf.random_normal([100, 10])) # bias with tf.name_scope("biases"): b1 = tf.Variable(tf.zeros([100])) b2 = tf.Variable(tf.zeros([10])) # implement model with tf.name_scope("softmax"): # y is our prediction z2 = tf.add(tf.matmul(x,W1),b1) a2 = tf.nn.sigmoid(z2) z3 = tf.add(tf.matmul(a2,W2),b2) y = tf.nn.softmax(z3) # specify cost function with tf.name_scope('cross_entropy'): # this is our cost cross_entropy = tf.reduce_mean( -tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1])) # specify optimizer with tf.name_scope('train'): # optimizer is an "operation" which we can execute in a session grad_op = tf.train.GradientDescentOptimizer(learning_rate) train_op = grad_op.minimize(cross_entropy, global_step=global_step) with tf.name_scope('Accuracy'): # accuracy correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) # create a summary for our cost and accuracy tf.summary.scalar("cost", cross_entropy) tf.summary.scalar("accuracy", accuracy) # merge all summaries into a single "operation" which we can execute in a session summary_op = tf.summary.merge_all() init_op = tf.global_variables_initializer() print("Variables initialized ...") Start a supervisor which acts as a Chief machine for the distributed setting. The chief is the worker machine which manages all the rest of the cluster. The session is maintained by the chief and the key instruction is sv = tf.train.Supervisor(is_chief=(FLAGS.task_index == 0)). Also, with prepare_or_wait_for_session(server.target) the supervisor will wait for the model to be ready for use. Note that each worker will take care of different batched models and the final model is then available for the chief. sv = tf.train.Supervisor(is_chief=(FLAGS.task_index == 0), begin_time = time.time() frequency = 100 with sv.prepare_or_wait_for_session(server.target) as sess: # create log writer object (this will log on every machine) writer = tf.summary.FileWriter(logs_path, graph=tf.get_default_graph()) # perform training cycles start_time = time.time() for epoch in range(training_epochs): # number of batches in one epoch batch_count = int(mnist.train.num_examples/batch_size) count = 0 for i in range(batch_count): batch_x, batch_y = mnist.train.next_batch(batch_size) # perform the operations we defined earlier on batch _, cost, summary, step = sess.run( [train_op, cross_entropy, summary_op, global_step], feed_dict={x: batch_x, y_: batch_y}) writer.add_summary(summary, step) count += 1 if count % frequency == 0 or i+1 == batch_count: elapsed_time = time.time() - start_time start_time = time.time() print("Step: %d," % (step+1), " Epoch: %2d," % (epoch+1), " Batch: %3d of %3d," % (i+1, batch_count), " Cost: %.4f," % cost, "AvgTime:%3.2fms" % float(elapsed_time*1000/frequency)) count = 0 print("Test-Accuracy: %2.2f" % sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels})) print("Total Time: %3.2fs" % float(time.time() - begin_time)) print("Final Cost: %.4f" % cost) sv.stop() print("done") How it works... This recipe describes an example of distributed MNIST classifier. In this example, TensorFlow allows us to define a cluster of three machines. One acts as parameter server and two more machines are used as workers working on separate batches of the training data. If you enjoyed this excerpt, check out the book TensorFlow 1.x Deep Learning Cookbook, to become an expert in implementing deep learning techniques in real-world applications. Emoji Scavenger Hunt showcases TensorFlow.js The 5 biggest announcements from TensorFlow Developer Summit 2018 Setting up Logistic Regression model using TensorFlow  
Read more
  • 0
  • 0
  • 18870

article-image-implementing-3-naive-bayes-classifiers-in-scikit-learn
Packt Editorial Staff
07 May 2018
13 min read
Save for later

Implementing 3 Naive Bayes classifiers in scikit-learn

Packt Editorial Staff
07 May 2018
13 min read
Scikit-learn provide three naive Bayes implementations: Bernoulli, multinomial and Gaussian. The only difference is about the probability distribution adopted. The first one is a binary algorithm particularly useful when a feature can be present or not. Multinomial naive Bayes assumes to have feature vector where each element represents the number of times it appears (or, very often, its frequency). This technique is very efficient in natural language processing or whenever the samples are composed starting from a common dictionary. The Gaussian Naive Bayes, instead, is based on a continuous distribution and it's suitable for more generic classification tasks. Ok, now that we have established naive Bayes variants are a handy set of algorithms to have in our machine learning arsenal and that Scikit-learn is a good tool to implement them, let’s rewind a bit. What is Naive Bayes? Naive Bayes are a family of powerful and easy-to-train classifiers, which determine the probability of an outcome, given a set of conditions using the Bayes' theorem. In other words, the conditional probabilities are inverted so that the query can be expressed as a function of measurable quantities. The approach is simple and the adjective naive has been attributed not because these algorithms are limited or less efficient, but because of a fundamental assumption about the causal factors that we will discuss. Naive Bayes are multi-purpose classifiers and it's easy to find their application in many different contexts. However, the performance is particularly good in all those situations when the probability of a class is determined by the probabilities of some causal factors. A good example is given by natural language processing, where a text can be considered as a particular instance of a dictionary and the relative frequencies of all terms provide enough information to infer a belonging class. Our examples may be generic, so to let you understand the application of naive Bayes in various context. The Bayes' theorem Let's consider two probabilistic events A and B. We can correlate the marginal probabilities P(A) and P(B) with the conditional probabilities P(A|B) and P(B|A) using the product rule: Considering that the intersection is commutative, the first members are equal, so we can derive the Bayes' theorem: This formula has very deep philosophical implications and it's a fundamental element of statistical learning. First of all, let's consider the marginal probability P(A): this is normally a value that determines how probable a target event is, like P(Spam) or P(Rain). As there are no other elements, this kind of probability is called Apriori, because it's often determined by mathematical considerations or simply by a frequency count. For example, imagine we want to implement a very simple spam filter and we've collected 100 emails. We know that 30 are spam and 70 are regular. So we can say that P(Spam) = 0.3. However, we'd like to evaluate using some criteria (for simplicity, let's consider a single one), for example, e-mail text is shorter than 50 characters. Therefore, our query becomes: The first term is similar to P(Spam) because it's the probability of spam given a certain condition. For this reason, it's called a posteriori (in other words, it's a probability that can estimate after knowing some additional elements). On the right side, we need to calculate the missing values, but it's simple. Let's suppose that 35 emails have a text shorter than 50 characters, P(Text < 50 chars) = 0.35 and, looking only into our spam folder, we discover that only 25 spam emails have a short text, so that P(Text < 50 chars|Spam) = 25/30 = 0.83. The result is: So, after receiving a very short email, there is 71% probability that it's a spam. Now we can understand the role of P(Text < 50 chars|Spam): as we have actual data, we can measure how probable is our hypothesis given the query, in other words, we have defined a likelihood (compare this with logistic regression) which is a weight between the Apriori probability and the a posteriori one (the term on the denominator is less important because it works as normalizing factor): The normalization factor is often represented by the Greek letter alpha, so the formula becomes: The last step is considering the case when there are more concurrent conditions (that is more realistic in real-life problems): A common assumption is called conditional independence (in other words, the effects produced by every cause are independent among each other) and allows us to write a simplified expression: Naive Bayes classifiers A naive Bayes classifier is called in this way because it's based on a naive condition, which implies the conditional independence of causes. This can seem very difficult to accept in many contexts where the probability of a particular feature is strictly correlated to another one. For example, in spam filtering, a text shorter than 50 characters can increase the probability of the presence of an image, or if the domain has been already blacklisted for sending the same spam emails to million users, it's likely to find particular keywords. In other words, the presence of a cause isn't normally independent from the presence of other ones. However, in Zhang H., The Optimality of Naive Bayes, AAAI 1, no. 2 (2004): 3, the author showed that under particular conditions (not so rare to happen), different dependencies clears one another, and a naive Bayes classifier succeeds in achieving very high performances even if its naiveness is violated. Let's consider a dataset: Every feature vector, for simplicity, will be represented as: We need also a target dataset: where each y can belong to one of P different classes. Considering the Bayes' theorem under conditional independence, we can write: The values of the marginal Apriori probability P(y) and of the conditional probabilities P(xi|y) is obtained through a frequency count, therefore, given an input vector x, the predicted class is the one which a posteriori probability is maximum. Naive Bayes in scikit-learn scikit-learn implements three naive Bayes variants based on the same number of different probabilistic distributions: Bernoulli, multinomial, and Gaussian. The first one is a binary distribution useful when a feature can be present or absent. The second one is a discrete distribution used whenever a feature must be represented by a whole number (for example, in natural language processing, it can be the frequency of a term), while the latter is a continuous distribution characterized by its mean and variance. Bernoulli naive Bayes If X is random variable Bernoulli-distributed, it can assume only two values (for simplicity, let's call them 0 and 1) and their probability is: To try this algorithm with scikit-learn, we're going to generate a dummy dataset. Bernoulli naive Bayes expects binary feature vectors, however, the class BernoulliNB has a binarize parameter which allows specifying a threshold that will be used internally to transform the features: from sklearn.datasets import make_classification >>> nb_samples = 300 >>> X, Y = make_classification(n_samples=nb_samples, n_features=2, n_informative=2, n_redundant=0) We have a generated the bidimensional dataset shown in the following figure: We have decided to use 0.0 as a binary threshold, so each point can be characterized by the quadrant where it's located. Of course, this is a rational choice for our dataset, but Bernoulli naive Bayes is thought for binary feature vectors or continuous values which can be precisely split with a predefined threshold. from sklearn.naive_bayes import BernoulliNB from sklearn.model_selection import train_test_split >>> X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.25) >>> bnb = BernoulliNB(binarize=0.0) >>> bnb.fit(X_train, Y_train) >>> bnb.score(X_test, Y_test) 0.85333333333333339 The score in rather good, but if we want to understand how the binary classifier worked, it's useful to see how the data have been internally binarized: Now, checking the naive Bayes predictions we obtain: >>> data = np.array([[0, 0], [0, 1], [1, 0], [1, 1]]) >>> bnb.predict(data) array([0, 0, 1, 1]) Which is exactly what we expected. Multinomial naive Bayes A multinomial distribution is useful to model feature vectors where each value represents, for example, the number of occurrences of a term or its relative frequency. If the feature vectors have n elements and each of them can assume k different values with probability pk, then: The conditional probabilities P(xi|y) are computed with a frequency count (which corresponds to applying a maximum likelihood approach), but in this case, it's important to consider the alpha parameter (called Laplace smoothing factor) which default value is 1.0 and prevents the model from setting null probabilities when the frequency is zero. It's possible to assign all non-negative values, however, larger values will assign higher probabilities to the missing features and this choice could alter the stability of the model. In our example, we're going to consider the default value of 1.0. For our purposes, we're going to use the DictVectorizer. There are automatic instruments to compute the frequencies of terms, but we're going to discuss them later. Let's consider only two records: the first one representing a city, while the second one countryside. Our dictionary contains hypothetical frequencies, like if the terms were extracted from a text description: from sklearn.feature_extraction import DictVectorizer >>> data = [ {'house': 100, 'street': 50, 'shop': 25, 'car': 100, 'tree': 20}, {'house': 5, 'street': 5, 'shop': 0, 'car': 10, 'tree': 500, 'river': 1} ] >>> dv = DictVectorizer(sparse=False) >>> X = dv.fit_transform(data) >>> Y = np.array([1, 0]) >>> X array([[ 100., 100., 0., 25., 50., 20.], [ 10., 5., 1., 0., 5., 500.]]) Note that the term 'river' is missing from the first set, so it's useful to keep alpha equal to 1.0 to give it a small probability. The output classes are 1 for city and 0 for the countryside. Now we can train a MultinomialNB instance: from sklearn.naive_bayes import MultinomialNB >>> mnb = MultinomialNB() >>> mnb.fit(X, Y) MultinomialNB(alpha=1.0, class_prior=None, fit_prior=True) To test the model, we create a dummy city with a river and a dummy country place without any river. >>> test_data = data = [ {'house': 80, 'street': 20, 'shop': 15, 'car': 70, 'tree': 10, 'river': 1}, ] {'house': 10, 'street': 5, 'shop': 1, 'car': 8, 'tree': 300, 'river': 0} >>> mnb.predict(dv.fit_transform(test_data)) array([1, 0]) As expected the prediction is correct. Later on, when discussing some elements of natural language processing, we're going to use multinomial naive Bayes for text classification with larger corpora. Even if the multinomial distribution is based on the number of occurrences, it can be successfully used with frequencies or more complex functions. Gaussian Naive Bayes Gaussian Naive Bayes is useful when working with continuous values which probabilities can be modeled using a Gaussian distribution: The conditional probabilities P(xi|y) are also Gaussian distributed and, therefore, it's necessary to estimate mean and variance of each of them using the maximum likelihood approach. This quite easy, in fact, considering the property of a Gaussian, we get: Where the k index refers to the samples in our dataset and P(xi|y) is a Gaussian itself. By minimizing the inverse of this expression (in Russel S., Norvig P., Artificial Intelligence: A Modern Approach, Pearson there's a complete analytical explanation), we get mean and variance for each Gaussian associated to P(xi|y) and the model is hence trained. As an example, we compare Gaussian Naive Bayes with logistic regression using the ROC curves. The dataset has 300 samples with two features. Each sample belongs to a single class: from sklearn.datasets import make_classification >>> nb_samples = 300 >>> X, Y = make_classification(n_samples=nb_samples, n_features=2, n_informative=2, n_redundant=0) A plot of the dataset is shown in the following figure: Now we can train both models and generate the ROC curves (the Y scores for naive Bayes are obtained through the predict_proba method): from sklearn.naive_bayes import GaussianNB from sklearn.linear_model import LogisticRegression from sklearn.metrics import roc_curve, auc from sklearn.model_selection import train_test_split >>> X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.25) >>> gnb = GaussianNB() >>> gnb.fit(X_train, Y_train) >>> Y_gnb_score = gnb.predict_proba(X_test) >>> lr = LogisticRegression() >>> lr.fit(X_train, Y_train) >>> Y_lr_score = lr.decision_function(X_test) >>> fpr_gnb, tpr_gnb, thresholds_gnb = roc_curve(Y_test, Y_gnb_score[:, 1]) >>> fpr_lr, tpr_lr, thresholds_lr = roc_curve(Y_test, Y_lr_score) The resulting ROC curves are shown in the following figure: Naive Bayes performances are slightly better than logistic regression, however, the two classifiers have similar accuracy and Area Under the Curve (AUC). It's interesting to compare the performances of Gaussian and multinomial naive Bayes with the MNIST digit dataset. Each sample (belonging to 10 classes) is an 8x8 image encoded as an unsigned integer (0 - 255), therefore, even if each feature doesn't represent an actual count, it can be considered like a sort of magnitude or frequency. from sklearn.datasets import load_digits from sklearn.model_selection import cross_val_score >>> digits = load_digits() >>> gnb = GaussianNB() >>> mnb = MultinomialNB() >>> cross_val_score(gnb, digits.data, digits.target, scoring='accuracy', cv=10).mean() 0.81035375835678214 >>> cross_val_score(mnb, digits.data, digits.target, scoring='accuracy', cv=10).mean() 0.88193962163008377 The multinomial naive Bayes performs better than the Gaussian variant and the result is not really surprising. In fact, each sample can be thought as a feature vector derived from a dictionary of 64 symbols. The value can be the count of each occurrence, so a multinomial distribution can better fit the data, while a Gaussian is slightly more limited by its mean and variance. We've exposed the generic naive Bayes approach starting from the Bayes' theorem and its intrinsic philosophy. The naiveness of such algorithm is due to the choice to assume all the causes to be conditional independent. It means that each contribution is the same in every combination and the presence of a specific cause cannot alter the probability of the other ones. This is not so often realistic, however, under some assumptions; it's possible to show that internal dependencies clear each other so that the resulting probability appears unaffected by their relations. [box type="note" align="" class="" width=""]You read an excerpt from the book, Machine Learning Algorithms, written by Giuseppe Bonaccorso. This book will help you build strong foundation to enter the world of machine learning and data science. You will learn to build a data model and see how it behaves using different ML algorithms, explore support vector machines, recommendation systems, and even create a machine learning architecture from scratch. Grab your copy today![/box] What is Naïve Bayes classifier? Machine Learning Algorithms: Implementing Naive Bayes with Spark MLlib Implementing Apache Spark MLlib Naive Bayes to classify digital breath test data for drunk driving  
Read more
  • 0
  • 0
  • 36689

article-image-unit-testing-in-net-core-with-visual-studio-2017-for-better-code-quality
Kunal Chaudhari
07 May 2018
12 min read
Save for later

Unit Testing in .NET Core with Visual Studio 2017 for better code quality

Kunal Chaudhari
07 May 2018
12 min read
The famous Java programmer, Bruce Eckel, came up with a slogan which highlights the importance of testing software: If it ain't tested, it's broken. Though a confident programmer may challenge this, it beautifully highlights the ability to determine that code works as expected over and over again, without any exception. How do we know that the code we are shipping to the end user or customer is of good quality and all the user requirements would work? By testing? Yes, by testing, we can be confident that the software works as per customer requirements and specifications. If there are any discrepancies between expected and actual behavior, it is referred to as a bug/defect in the software. The earlier the discrepancies are caught, the more easily they can be fixed before the software is shipped, and the results are good quality. No wonder software testers are also referred to as quality control analysts in various software firms. The mantra for a good software tester is: In God we trust, the rest we test. In this article, we will understand the testing deployment model of .NET Core applications, the Live Unit Testing feature of Visual Studio 2017. We will look at types of testing methods briefly and write our unit tests, which a software developer must write after writing any program. Software testing is conducted at various levels: Unit testing: While coding, the developer conducts tests on a unit of a program to validate that the code they have written is error-free. We will write a few unit tests shortly. Integration testing: In a team where a number of developers are working, there may be different components that the developers are working on. Even if all developers perform unit testing and ensure that their units are working fine, there is still a need to ensure that, upon integration of these components, they work without any error. This is achieved through integration testing. System testing: The entire software product is tested as a whole. This is accomplished using one or more of the following: Functionality testing: Test all the functionality of the software against the business requirement document. Performance testing: To test how performant the software is. It tests the average time, resource utilization, and so on, taken by the software to complete a desired business use case. This is done by means of load testing and stress testing, where the software is put under high user and data load. Security testing: Tests how secure the software is against common and well-known security threats. Accessibility testing: Tests if the user interface is accessible and user-friendly to specially-abled people or not. User acceptance testing: When the software is ready to be handed over to the customer, it goes through a round of testing by the customer for user interaction and response. Regression testing: Whenever a piece of code is added/updated in the software to add a new functionality or fix an existing functionality, it is tested to detect if there are any side-effects from the newly added/updated code. Of all these different types of testing, we will focus on unit testing, as it is done by the developer while coding the functionality. Unit testing .NET Core has been designed with testability in mind. .NET Core 2.0 has unit test project templates for VB, F#, and C#. We can also pick the testing framework of our choice amongst xUnit, NUnit, and MSTest. Unit tests that test single programming parts are the most minimal-level tests. Unit tests should just test code inside the developer's control, and ought to not test infrastructure concerns, for example, databases, filesystems, or network resources. Unit tests might be composed utilizing test-driven development (TDD) or they can be added to existing code to affirm its accuracy. The naming convention of Test class names should end with Test and reside in the same namespace as the class being tested. For instance, the unit tests for the Microsoft.Example.AspNetCore class would be in the Microsoft.Example.AspNetCoreTest class in the test assembly. Also, unit test method names must be descriptive about what is being tested, under what conditions, and what the expectations are. A good unit test has three main parts to it in the following specified order: Arrange Act Assert We first arrange the code and then act on it and then do a series of asserts to check if the actual output matches the expected output. Let's have a look at them in detail: Arrange: All the parameter building, and method invocations needed for making a call in the act section must be declared in the arrange section. Act: The act stage should be one statement and as simple as possible. This one statement should be a call to the method that we are trying to test. Assert: The only reason method invocation may fail is if the method itself throws an exception, else, there should always be some state change or output from any meaningful method invocation. When we write the act statement, we anticipate an output and then do assertions if the actual output is the same as expected. If the method under test should throw an exception under normal circumstances, we can do assertions on the type of exception and the error message that should be thrown. We should be watchful while writing unit test cases, that we don't inject any dependencies on the infrastructure. Infrastructure dependencies should be taken care of in integration test cases, not in unit tests. We can maintain a strategic distance from these shrouded dependencies in our application code by following the Explicit Dependencies Principle and utilizing Dependency Injection to request our dependencies on the framework. We can likewise keep our unit tests in a different project from our integration tests and guarantee our unit test project doesn't have references to the framework. Testing using xUnit In this section, we will learn to write unit and integration tests for our controllers. There are a number of options available to us for choosing the test framework. We will use xUnit for all our unit tests and Moq for mocking objects. Let's create an xUnit test project by doing the following: Open the Let's Chat project in Visual Studio 2017 Create a new folder named  Test Right-click the Test folder and click Add | New Project Select xUnit Test Project (.NET Core) under Visual C# project templates, as shown here: Delete the default test class that gets created with the template Create a test class inside this project AuthenticationControllerUnitTests for the unit test We need to add some NuGet packages. Right-click the project in VS 2017 to edit the project file and add the references manually, or use the NuGet Package Manager to add these packages: // This package contains dependencies to ASP.NET Core <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" /> // This package is useful for the integration testing, to build a test host for the project to test. <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.0.0" /> // Moq is used to create fake objects <PackageReference Include="Moq" Version="4.7.63" /> With this, we are now ready to write our unit tests. Let's start doing this, but before we do that, here's some quick theory about xUnit and Moq. The documentation from the xUnit website and Wikipedia tells us that xUnit.net is a free, open source, community-focused unit testing tool for the .NET Framework. It is the latest technology for unit testing C#, F#, Visual Basic .NET, and other .NET languages. All xUnit frameworks share the following basic component architecture: Test runner: It is an executable program that runs tests implemented using an xUnit framework and reports the test results. Test case: It is the most elementary class. All unit tests are inherited from here. Test fixtures: Test fixures (also known as a test context) are the set of preconditions or state needed to run a test. The developer should set up a known good state before the tests, and return to the original state after the tests. Test suites: It is a set of tests that all share the same fixture. The order of the tests shouldn't matter. xUnit.net includes support for two different major types of unit test: Facts: Tests which are always true. They test invariant conditions, that is, data-independent tests. Theories: Tests which are only true for a particular set of data. Moq is a mocking framework for C#/.NET. It is used in unit testing to isolate the class under test from its dependencies and ensure that the proper methods on the dependent objects are being called. Recall that in unit tests, we only test a unit or a layer/part of the software in isolation and hence do not bother about external dependencies, so we assume they work fine and just mock them using the mocking framework of our choice. Let's put this theory into action by writing a unit test for the following action in AuthenticationController: public class AuthenticationController : Controller { private readonly ILogger<AuthenticationController> logger; public AuthenticationController(ILogger<AuthenticationController> logger) { this.logger = logger; } [Route("signin")] public IActionResult SignIn() { logger.LogInformation($"Calling {nameof(this.SignIn)}"); return Challenge(new AuthenticationProperties { RedirectUri = "/" }); } } The unit test code depends on how the method to be tested is written. To understand this, let's write a unit test for a SignIn action. To test the SignIn method, we need to invoke the SignIn action in AuthenticationController. To do so, we need an instance of the AuthenticationController class, on which the SignIn action can be invoked. To create the instance of AuthenticationController, we need a logger object, as the AuthenticationController constructor expects it as a parameter. Since we are only testing the SignIn action, we do not bother about the logger and so we can mock it. Let's do it: /// <summary> /// Authentication Controller Unit Test - Notice the naming convention {ControllerName}Test /// </summary> public class AuthenticationControllerTest { /// <summary> /// Mock the dependency needed to initialize the controller. /// </summary> private Mock<ILogger<AuthenticationController>> mockedLogger = new Mock<ILogger<AuthenticationController>>(); /// <summary> /// Tests the SignIn action. /// </summary> [Fact] public void SignIn_Pass_Test() { // Arrange - Initialize the controller. Notice the mocked logger object passed as the parameter. var controller = new AuthenticationController(mockedLogger.Object); // Act - Invoke the method to be tested. var actionResult = controller.SignIn(); // Assert - Make assertions if actual output is same as expected output. Assert.NotNull(actionResult); Assert.IsType<ChallengeResult>(actionResult); Assert.Equal(((ChallengeResult)actionResult). Properties.Items.Count, 1); } } Reading the comments would explain the unit test code. The previous example shows how easy it is to write a unit test. Agreed, depending on the method to be tested, things can get complicated. But it is likely to be around mocking the objects and, with some experience on the mocking framework and binging around, mocking should not be a difficult task. The unit test for the SignOut action would be a bit complicated in terms of mocking as it uses HttpContext. The unit test for the SignOut action is left to the reader as an exercise. Let's explore a new feature introduced in Visual Studio 2017 called Live Unit Testing. Live Unit Testing It may disappoint you but Live Unit Testing (LUT) is available only in the Visual Studio 2017 Enterprise edition and not in the Community edition. What is Live Unit Testing? It's a new productivity feature, introduced in the Visual Studio 2017 Enterprise edition, that provides real-time feedback directly in the Visual Studio editor on how code changes are impacting unit tests and code coverage. All this happens live, while you write the code and hence it is called Live Unit Testing. This will help in maintaining the quality by keeping tests passing as changes are made. It will also remind us when we need to write additional unit tests, as we are making bug fixes or adding features. To start Live Unit Testing: Go to the Test menu item Click Live Unit Testing Click Start, as shown here: On clicking this, your CPU usage may go higher as Visual Studio spawns the MSBuild and tests runner processes in the background. In a short while, the editor will display the code coverage of the individual lines of code that are covered by the unit test. The following image displays the lines of code in AuthenticationController that are covered by the unit test. On clicking the right icon, it displays the tests covering this line of code and also provides the option to run and debug the test: Similarly, if we open the test file, it will show the indicator there as well. Super cool, right! If we navigate to Test|Live Unit Testing now, we would see the options to Stop and Pause. So, in case we wish to save  our resources after getting the data once, we can pause or stop Live Unit Testing: There are numerous icons which indicates the code coverage status of individual lines of code. These are: Red cross: Indicates that the line is covered by at least one failing test Green check mark: Indicates that the line is covered by only passing tests Blue dash: Indicates that the line is not covered by any test If you see a clock-like icon just below any of these icons, it indicates that the data is not up to date. With this productivity-enhancing feature, we conclude our discussion on basic unit testing. Next, we will learn about containers and how we can do the deployment and testing of our .NET Core 2.0 applications in containers. To summarize, we learned the importance of testing and how we can write unit tests using Moq and xUnit. We saw a new productivity-enhancing feature introduced in Visual Studio 2017 Enterprise edition called Live Unit Testing and how it helps us write better-quality code. You read an excerpt from a book written by Rishabh Verma and Neha Shrivastava, titled  .NET Core 2.0 By Example. This book will help you build cross-platform solutions with .NET Core 2.0 through real-life scenarios.   More on Testing: Unit Testing and End-To-End Testing Testing RESTful Web Services with Postman Selenium and data-driven testing: Interview insights
Read more
  • 0
  • 0
  • 5175
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at €14.99/month. Cancel anytime
article-image-this-week-on-packt-hub-4-may-2018
Aarthi Kumaraswamy
04 May 2018
4 min read
Save for later

This week on Packt Hub – 4 May 2018

Aarthi Kumaraswamy
04 May 2018
4 min read
May’s opened with a bang! Plenty of big announcements and major new releases in Web (Angular 6, Node 10, Flask 1.0), programming (Scala 3) and data science (PyTorch 1.0, Neo4j 3.4 among others). Also, read our coverage of key conferences that happened this week: Facebook’s F8, Angular’s ng-conf and KubeCon + CloudNativeCon Europe in our tech news section this week. Tutorials this week are all about building bots and apps from a JavaScript foodie bot, to a Kotlin weather app to an interactive Twilio chatbot. Also learn all about Angular pipes, JavaScript design patterns, creating multithreaded apps in Qt, lighting, and effects in Unity 2018 and more in this week’s tutorials. In this week’s tech insights, we focus on trends in digital forensics such as IoT forensics and take a closer look at serverless computing. Learn why 2018 is the year of graph databases, why Kotlin is better than Java and more. Without further ado, here’s what you may have missed in the last 7 days – Tech news, insights and tutorials… Tech news Tech conferences this week Facebook’s F8 Conference – 5 key announcements [Editor’s Pick] ng-conf 2018 highlights, the popular angular conference Big vendor announcements at KubeCon + CloudNativeCon Europe Data news in depth Swift for TensorFlow is now open source [Editor’s Pick] Can a production-ready Pytorch 1.0 give TensorFlow a tough time? [Editor’s Pick] Thanks to DeepCode, AI can help you write cleaner code Splunk leverages AI in its monitoring tools Neo4j 3.4 aims to make connected data even more accessible Development & programming news in depth Angular 6 is here packed with exciting new features! [Editor’s Pick] Node 10.0.0 released, packed with exciting new features [Editor’s Pick] Flask 1.0 is here: updates and improvements What Scala 3.0 Roadmap looks like! [Editor’s Pick] npm v6 is out! Oculus Go, the first stand-alone VR headset arrives! Someone made a program to make it look like you’re typing on Slack when someone else is Cloud & networking news in depth Introducing Azure Sphere – A secure way of running your Internet of Things devices  Nvidia Tesla V100 GPUs publicly available in beta on Google Compute Engine and Kubernetes Engine Tutorials Data tutorials How to create multithreaded applications in Qt [Editor’s Pick] Implementing Automation Process with Salesforce CRM Build a custom Admin Home page in Salesforce CRM Lightning Experience Development & programming tutorials Web development tutorials  8 built-in Angular Pipes in Angular 4 that you should know [Editor’s Pick] Using Amazon Simple Notification Service (SNS) to create an SNS topic Build a foodie (restaurant recommendation) bot with JavaScript How to build a weather app using Kotlin for JavaScript [Editor’s Pick] Building a two-way interactive chatbot with Twilio: A step-by-step guide Game and Mobile development tutorials How Android app developers can convert iPhone apps Implementing lighting & camera effects in Unity 2018 Programming tutorials  Implementing 5 Common Design Patterns in JavaScript (ES8) Seven wrongs don’t make the one right: Solving a problem with Functional Javascript [Editor’s Pick] How to call an Azure function from an ASP.NET Core MVC application Other Tutorials How to build a sensor application to measure Ambient Light [Editor’s Pick] Amazon S3 Security access and policies This week’s opinions, analysis, and insights Learn all about MYSQL performance benchmarks, what is active learning, what are hybrid apps, what is mob programming and more in this week’s insights. Data Insights 2018 is the year of graph databases. Here’s why. [Editor’s Pick] 12 most common MySQL errors you should be aware of ICLR 2018 Paper in Two minutes: Zero-Shot learning for Visual Imitation [Editor’s Pick] You can now make music with AI thanks to Magenta.js Development & Programming Insights 5 reasons to choose Kotlin over Java 5 reasons you should learn to code Other Insights Tech hype cycles: do they deserve your attention? IoT Forensics: Security in an always-connected world where things talk [Editor’s Pick] What is Digital Forensics? Should you go with Arduino Uno or Raspberry Pi 3 for your next IoT project Align your product experience strategy with business needs Serverless computing wars: AWS Lambdas vs Azure Functions Missed what happened in April? Here's a quick Recap. Last week on Packt Hub – 27 April 2018 See discussions around GDPR, major updates for Tableau 2018.1, MySQL 8, Bootstrap 4.1 and Salesforce spring 18 in tech news this week. See why Hadoop is dying, learn about Mob programming, Hybrid apps, Progressive web apps, and more from this week’s insights. Build an ARCore app in Android, learn advanced Rust programming, see how data scientists test hypothesis, and more in this week’s tutorials. That week on Packt Hub – 20 April 2018 That week on Packt Hub – 13 April 2018 That Week on Packt Hub – 6 April  2018
Read more
  • 0
  • 0
  • 1810

article-image-building-two-way-interactive-chatbot-twilio
Gebin George
04 May 2018
4 min read
Save for later

Building a two-way interactive chatbot with Twilio: A step-by-step guide

Gebin George
04 May 2018
4 min read
To build a chatbot that can communicate both ways we need to do two things: build the chatbot into the web app and modify setup configurations in Twilio. To do these, follow these steps: Create an index.js file in the root directory of the project. Install the express and body-parser libraries. These libraries will be used to make a web app: npm install body-parser --save npm install express --save Create a web app in index.js: // Two-way SMS Bot const express = require('express') const bodyParser = require('body-parser') const twilio = require('twilio') const app = express() app.set('port', (process.env.PORT || 5000)) Chapter 5 [ 185 ] // Process application/x-www-form-urlencoded app.use(bodyParser.urlencoded({extended: false})) // Process application/json app.use(bodyParser.json()) // Spin up the server app.listen(app.get('port'), function() { console.log('running on port', app.get('port')) }) // Index route app.get('/', function (req, res) { res.send('Hello world, I am SMS bot.') }) //Twilio webhook app.post('/sms/', function (req, res) { var botSays = 'You said: ' + req.body.Body; var twiml = new twilio.TwimlResponse(); twiml.message(botSays); res.writeHead(200, {'Content-Type': 'text/xml'}); res.end(twiml.toString()); }) The preceding code creates a web app that looks for incoming messages from users and responds to them. The response is currently to repeat what the user has said. Push it onto the cloud: git add . git commit -m webapp git push heroku master Now we have a web app on the cloud at https://ms-notification-bot.herokuapp.com/sms/ that can be called when an incoming SMS message arrives. This app will generate an appropriate chatbot response to the incoming message. Go to the Twilio Programmable SMS Dashboard page at https://www.twilio.com/ console/sms/dashboard. Select Messaging Services on the menu and click Create new Messaging Service: Give it a name and select Chat Bot/Interactive 2-Way as the use case: This will take you to the Configure page with a newly-assigned service ID: Under Inbound Settings, specify the URL of the web app we have created in the REQUEST URL field (that is, https://sms-notification-bot.herokuapp.com/sms/): Now all the inbound messages will be routed to this web app. Go back to the SMS console page at https://www.twilio com/console/sms/services. Here you will notice your new messaging service listed along with the inbound request URL: Click the service to attach a number to the service: You can either add a new number, in which case you need to buy one or choose the number you already have. We already have one sending notifications that can be reused. Click Add an Existing Number. Select the number by checking the box on the right and click Add Selected: Once added, it will be listed on the Numbers page as follows: In Advanced settings, we can add multiple numbers for serving different geographic regions and have them respond as if the chatbot is responding over a local number. The final step is to try sending an SMS message to the number and receive a response. Send a message using any SMS app on your phone and observe the response: Congratulations! You now have a two-way interactive chatbot. This tutorial is an excerpt from the book, Hands-On Chatbots and Conversational UI Development written by  Srini Janarthanam. If you found our post useful, do check out this book to get real-world examples of voice-enabled UIs for personal and home assistance. How to build a basic server side chatbot using Go Build a generative chatbot using recurrent neural networks (LSTM RNNs) Top 4 chatbot development frameworks for developers    
Read more
  • 0
  • 0
  • 4870

article-image-how-to-build-weather-app-using-kotlin-for-javascript
Sugandha Lahoti
04 May 2018
19 min read
Save for later

How to build a weather app using Kotlin for JavaScript

Sugandha Lahoti
04 May 2018
19 min read
In this tutorial, we will be covering JavaScript from a browser perspective. We will create a single page web app that will show the weather forecast for seven days from the current date. The user will provide a ZIP code as input for which the weather will be displayed. We will display all the basic information about the weather on a given day. We believe in learning by doing practicals. Let's see the power of Kotlin from a browser perspective. [box type="shadow" align="" class="" width=""]This article is an excerpt from the book,  Kotlin Blueprints, written by Ashish Belagali, Hardik Trivedi, and Akshay Chordiya. This book is a practical guide to building industry-grade web, mobile, and desktop applications in Kotlin using frameworks such as Spring Boot and Node.js[/box] Conceptually, we will cover the following points while making a web app: Setting up a project to use Kotlin along with JavaScript Showing simple text using Kotlin code Interacting with Document Object Model (DOM) using Kotlin DSL and usage of kotlinx.html Creating your first Kotlin and JavaScript project Tighten your shoelaces! As a first step, we will do the setup and create a simple app that prints on a console and changes the background color of a page. Choosing an IDE From Microsoft Visual Studio, NetBeans to Eclipse and Code::Blocks, we have a series of great and powerful IDEs. Each of them has their own pros and cons. JetBrains is one of the giants that is famous for its cutting-edge software and IntelliJ IDEA Ultimate is considered among one of the most intelligent IDEs for Java. It supports Kotlin and JavaScript by default. There is no other hassle in setting up the environments. Just install it from https://www.jetbrains.com/idea and you are all set to create your first JavaScript project using Kotlin. Creating a project If you are all done with setting up an IDE, launch IntelliJ IDEA and select Create New Project. You will then have the following screen opened. Select Kotlin | Kotlin (JavaScript) options as shown in the following screenshot: Make sure you select Kotlin (JavaScript) as highlighted in the preceding screenshot. The next step is to provide your Project name and choose a destination for your project directory: Creating an HTML page No browser project is complete without an HTML page. Create an index.html page in the root directory of your project. And write the following lines in a <body> tag: <body> <script type="text/javascript" src="out/production/KotlinWeb/lib/kotlin.js"></script> <script type="text/javascript" src="out/production/KotlinWeb/KotlinWeb.js"></script> </body> Creating a Main.kt file After creating our index.html page. Let's create our first Kotlin file. Name it as Main.kt or provide any desired name. Create a file in the src folder and write the following function inside: fun main(args: Array<String>) { document.bgColor="FF0000" val message = "Kotlin Blueprints" println("Your first JS code using Kotlin") } Build the project, by selecting the Build | Build Project menu option. On expanding the project explorer on the left of your workspace you will have the following type of directory structure: Make sure you double-check that the <script> tags are added in the <body>. They should match the name with the files created inside out/production/KotlinBluePrintsJSDemo/. Running the project If you have followed all the steps simply execute your index.html file in any browser and you should see the following output on your console and a red colored page rendered on your DOM: Congratulations! You have executed your first Kotlin code on the browser. Since we have code written in Kotlin, source code needs to recompile every time we update the code. Simply reloading an HTML page will not work. So build your project from the Build | Build Project menu option. Developing a weather forecast web app It was fun writing Kotlin code for a browser and seeing it working, wasn't it? Now we should target bigger goals. Let's develop another app step by step. We will build a weather forecast app, where the user will enter a ZIP code and can see the weather details (seven-day forecast) for the provided region. We will use the OpenWeatherMap API to get the weather details. Please find more details at https://openweathermap.org/api. Before we move to the next step we should create a new project named KotlinBluePrintsJSDemo. Some quick steps to follow: Create a Kotlin+JavaScript project named KotlinBluePrintsJSDemo. Create an index.html page under the root directory. Create a Main.kt file inside the src directory. Add script tags to add two JavaScript files, kotlin.js and KotlinBluePrintsJSDemo.js. Build a project. We want to create an app that will look like this at the end. Entirely in Kotlin: Creating a UI with dummy data The very first thing we do is to create a dummy view and get a clear idea of how our HTML page will look. We will also use a bit of CSS to give basic styles to our <div> tags. Simple HTML approach Now we shall look at the index.html file that we created by writing the following code. It's boring plain HTML tags: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Kotlin BluePrints JS Demo</title> </head> <body> <link rel="stylesheet" type="text/css" href="css/main.css"> <div id="container"> <label>Enter zip code : <input id="zipCode" type="number"> </label> <button id="submitZipCode" type="button">Get Weather</button> <div class="weatherContainer"> <div class="weatherBlock"> <div>13 Oct, 2017</div> <img src="images/weather_img.png" height="40px" width="40px"> <div> <span>35</span> <span>20</span> </div> </div> <div class="weatherBlock"> <div>13 Oct, 2017</div> <img src="images/weather_img.png" height="40px" width="40px"> <div> <span>35</span> <span>20</span> </div> </div> <!-- Similarly you can have remaining divs here --> </div> </div> <script src="out/production/KotlinBluePrintsJSDemo/lib/kotlin.js"> </script> <script src="out/production/KotlinBluePrintsJSDemo /KotlinBluePrintsJSDemo.js"></script> </body> </html> Observe two tags, <script> and <link>. We haven't added CSS yet. Let's create a CSS folder under the root directory and create a main.css file inside. The main.css will contain the following code for now: .weatherContainer { width: 90%; background: #EEEEEE; margin: 10px auto; position: relative; text-align:center; } .weatherBlock { background: #FFFFFF; height: 100px; width: 100px; display:inline-block; margin: 10px; } In a source code, we have also created an images directory and put some weather images in it to make the UI more beautiful. Creating UI using Kotlin The index.html page contains all the HTML code. We need to now move that HTML code to Kotlin. Kotlin has the capability to manipulate the DOM element and it can also deal with the tree elements and their hierarchy. Simply put two <script> tags and a parent <div> tag in an HTML page and everything will go to a Kotlin page: <div id="container"> </div> Now, in Main.kt we will write the HTML code that we previously wrote inside index.html. Main.kt and it will look as follows: fun main(args: Array<String>) { createUserInput() } fun createUserInput() { val root = document.getElementById("container") root?.innerHTML = "<label>Enter zip code : <input id="zipCode" type="number"></label>" + "<button id="submitZipCode" type="button">Get Weather</button>" + "<div class="weatherContainer">" + "<div class="weatherBlock">" + "<div>13 Oct, 2017</div>" + "<img src="images/weather_img.png" height="40px" width="40px">"+ "<div>" + "<span>35</span>" + "<span>20</span>" + "</div>" + "</div>" + "<div class="weatherBlock">" + "<div>13 Oct, 2017</div>" + "<img src="images/weather_img.png" height="40px" width="40px">"+ "<div>" + "<span>35</span>" + "<span>20</span>" + "</div>" + "</div>" // Similarly add remaining divs } Take a note of the document object and its function getElementById. This is coming from the kotlin.browser.document package. Also org.w3c.dom as companion classes for all HTML elements. With object root, we get access to an innerHTML property and we can assign any valid HTML strings to it and it will get rendered. It is noteworthy that the nullability of root objects is handled with Null Safety operator ? of Kotlin. What is DSL? Now, the previous approach doesn't create much difference. Kotlin would want to do better! Let us introduce you to the beautiful concept of DSL. DSL stands for Domain Specific Language. As the name indicates, it gives you the feeling that you are writing code in a language, using terminology particular to a given domain, without being geeky, but then this terminology is cleverly embedded as a syntax in a powerful language. If you are from the Groovy community you must be aware of builders. Groovy builders allow defining data in a semi declarative way. It's a kind of mini-language of its own. Builders are considered good for generating XML and laying out UI components. Kotlin DSL uses Lambdas a lot. DSL in Kotlin are type-safe builders. It means we can detect compilation errors in IntelliJ's beautiful IDE. The type-check builders are much better than the dynamically-typed builders of Groovy. Using Kotlinx.html The DSL to build HTML trees is a pluggable dependency. We, therefore, need to set it up and configure it for our project. For now, we will keep things simple and add the dependency in them in the form of a .jar file. We will keep this .jar file in the lib folder, which will reside at the root level. The library is created by the JetBrains team only and it's open source. You can find it at https://github.com/Kotlin/kotlinx.html. You can simply visit the URL https://dl.bintray.com/kotlin/kotlinx.html/org/jetbrains/kotlinx/kotlinx-html-js/0.6.4/ and download the .jar file from there. For this demo app, we have used v 0.6.4. The .jar repository page can look as follows: To set up the kotlinx.html dependency in your app please follow these steps: In our app, we are using v 0.6.4. Make sure you download the JAR file named  kotlinx-html-js-0.6.4.jar. Please verify that you have kept the .jar file inside the lib directory. Also, do not forget to add the .jar file as a library. Right-click on the .jar file and select Add As Library…. Select classes as a category while adding them as a library. Or you can simply choose to add the dependency via Gradle, in that, you need to add the following things to your build.gradle file: repositories { jcenter() } dependencies { //Fill this in with the version of kotlinx in use in your project def kotlinx_html_version = "your_version_here" // include for client-side compile "org.jetbrains.kotlinx:kotlinx-html- js:${kotlinx_html_version}" } Refactoring the HTML code using DSL The DSL code to make a button with the title "Get Weather" looks as follows: button { +"Get Weather" type = ButtonType.button onClickFunction = { // Your code to handle button click goes here. } } Simple and clean code. Similarly, let's create a function that will display an entire div, which has a label, text input, and button: fun getInputDiv(): HTMLDivElement { val inputDiv = document.create.div { label { +"Enter zip code : " input { id = "zipCode" type = InputType.number value = 411021.toString() } } button { +"Get Weather" type = ButtonType.button onClickFunction = { // Your code to handle button click goes here } } } return inputDiv } Observe how we have provided ID, input types, and a default ZIP code value. A default ZIP code value is optional. Let's spend some time understanding the previous code. label, input, button, type, id, and onClickFunction are nothing but functions. They are basically Lambda functions. Some of the functions that use Lambda parameters and call variations can be as follows: someFunction({}) someFunction("KotlinBluePrints",1,{}) someFunction("KotlinBluePrints",1){} someFunction{} Let's run the code. You may get an error on the console saying: Error Uncaught Error: Error loading module 'KotlinBluePrintsJSDemo'. Its dependency 'kotlinx-html-js' was not found. Please, check whether 'kotlinx-html-js' is loaded prior to 'KotlinBluePrintsJSDemo'. This is because kotlinx-html-js is missing, which is required to process the DSL generated code. You can see the kotlinx-html-js file generated under the out/production/KotlinBluePrintsJSDemo/lib path. Calling a weather API Now it's time to get the weather data and display it on the page. We will use XMLHttpRequest to achieve this. Register yourself at http://openweathermap.org/appid and get your application ID. Your application ID will be appended to the actual URL to make the authenticated call to the weather API. Once you get the app ID let's keep that information in the Constants.kt file: const val IMAGE_URL = "http://openweathermap.org/img/w/%s.png" const val BASE_URL = "https://api.openweathermap.org/data/2.5/forecast/daily? mode=json&units=metric&cnt=7" const val APP_ID = "Your open weather map application id" const val FULL_URL = "$BASE_URL&appid=$APP_ID&q=" The Constants.kt file is not as simple as it looks. Check how we have stored different values. We have used const val, which is equivalent to const and static used combined. Also defining FULL_URL uses the concept of string interpolation. String interpolation is used to concatenate static strings along with string objects. You can also call functions in string interpolation as follows: h4 { +"Weather info for ${forecastResult.city.name}, (${forecastResult.city.country})" } Now, in onClickFunction we write the following code to perform the API call and on the successful response we call a showData function, which takes a forecastResult object: onClickFunction = { val zipCode = document.getElementById("zipCode") as HTMLInputElement val xmlHttpRequest = XMLHttpRequest() xmlHttpRequest.open("GET", FULL_URL + zipCode.value, false) xmlHttpRequest.send() println(xmlHttpRequest.responseText) val forecastResult = JSON.parse<ForecastResult> (xmlHttpRequest.responseText) showData(forecastResult) } Reading data from input elements See how we read data from input elements: document.getElementById("zipCode") as HTMLInputElement The as HTMLInputElement construct is basically casting a result into the HTMLInputElement class. Using as directly is not advisable because it can give you ClassCastException; a proper way to use it is as? HTMLInputElement. This returns null if the class cast fails. And Kotlin will force you to use a Null Safety operator from that very moment. Data classes We are maintaining ForecastResult, which is our model. For this purpose, we have data classes in Kotlin. One of the coolest features in Kotlin is data classes. All the pain that we used to endure to create and maintain POJO classes in Java is gone. No need to have those dedicated packages to hold your model class. Any Kotlin file can hold your data class. By default it provides you methods such as toString(), equals(), copy(), and hashCode() method implementation. In Android, we mostly use these types of classes to hold our JSON responses in the form of model classes. You can check out the data classes we created in ServerResponses.kt: data class ForecastResult(val city: City, val list: Array<Forecast>) data class City(val id: Long, val name: String, val coord: Coordinates, val country: String, val population: Int) data class Coordinates(val lon: Float, val lat: Float) data class Forecast(val dt: Long, val temp: Temperature, val pressure: Float, val humidity: Int, val weather: Array<Weather>, val speed: Float, val deg: Int, val clouds: Int) data class Temperature(val day: Float, val min: Float, val max: Float, val night: Float, val eve: Float, val morn: Float) data class Weather(val id: Long, val main: String, val description: String, val icon: String) Some of the points to consider while using data classes are: The primary constructor needs to have at least one parameter All primary constructor parameters need to be marked as val or var Data classes cannot be abstract, open, sealed, or inner (Before version 1.1) data classes may only implement interfaces Showing data to the user Now comes the interesting part. We gate a ForecastResult object, which holds all the records. The list object holds records for seven days. Let's create a showData function that takes a ForecastResult object and display title text in <h4>.  The code will look like the following snippet. Also, it has yet again one more example of string interpolation: fun showData(forecastResult: ForecastResult) { val root = document.getElementById("container") root?.appendChild(document.create.div(classes = "currentTemp") { h4 { +"Weather info for ${forecastResult.city.name (${forecastResult.city.country})" } }) } This is simple now, quickly create a showForecast function that will be called from showData and will display the weather forecast for seven days. The showForecast is used with a function from Kotlin.  thewith() is one of those functions that is liked by the developer community a lot; it makes use of Kotlin sweeter. The with() function accepts the receiver and the code written inside the function automatically applies to the receiver object. It's an inline function. Check out the following document: /** * Calls the specified function [block] with the given [receiver] as its receiver and returns its result. */ public inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block() In the code, observe how each iteration is using a with block. We have removed some of the lines from the original code, so that we can have the clean code snippet here: forecastResult.list.forEachIndexed { index, forecast -> with(forecast) { weatherContainer.appendChild(document.create.div(classes = "weatherBlock") { div { p(classes = "currentTemp") { +"${Math.round(temp.day)} °C" } } img(classes = "weatherImage") { src = "images/weather_img.png" } div { span(classes = "secondaryText") { +weather[0].main } } div { with(temp) { span(classes = "primaryText") { +"${Math.round(max)} °C" } span(classes = "secondaryText") { +" /${Math.round(min)} °C" } } } onClickFunction = { showDetailedForecast(forecastResult.city, forecast) } }) } } DSL and Kotlin code are now beautifully gelled. Also, notice the onClickFunction that we wrote on div.  Sweet, isn't it? Showing weather details A very small part of the app is left now. Let's show some more details to the user. Along with this, we will also learn a few more features of Kotlin. We have created a showDetailedForecast function that takes the City and Forecast objects as parameters. The following code snippets provide two things to learn: fun showDetailedForecast(city: City, forecast: Forecast) { val root = document.getElementById("container") val weatherDetailDiv = document.create.div(classes = "detailsContainer") val basicDetailDiv = document.create.div { p(classes = "secondaryText") { +"${city.name}, ${city.country} (${city.coord.lat},${city.coord.lon})" } p(classes = "secondaryText") { +forecast.dt.getFullDate() } p(classes = "secondaryText") { +"${forecast.weather[0].main}, ${forecast.weather[0].description}" } } val otherDetailsDiv = document.create.div { div { id = "leftDiv" span(classes = "currentTemp") { +"${Math.round(forecast.temp.day)} °C" } img { src = "images/weather_img.png" width = 90.toString() height = 90.toString() } } div { id = "rightDiv" p(classes = "secondaryText") { +"Pressure: ${forecast.pressure} mb" } p(classes = "secondaryText") { +"Humidity: ${forecast.humidity} %" } p(classes = "secondaryText") { +"Wind: ${forecast.speed} mph" } p(classes = "secondaryText") { +"Cloudiness: ${forecast.clouds} %" } } div(classes = "clearBoth") } weatherDetailDiv.appendChild(basicDetailDiv) weatherDetailDiv.appendChild(otherDetailsDiv) root?.appendChild(weatherDetailDiv) } Named parameters In Kotlin, we can call/bind a parameter with their name for any function. We can call the preceding function by interchanging the parameter sequence as well. Something like the following: showDetailedForecast(forecast = forecast, city = forecastResult.city) Observe that we swapped the place of the variable. And no wonder, all CSS classes that we have applied so far have a named parameter. Check all previous <div>, <h>, and <p> tags. Consider the following examples: val weatherDetailDiv = document.create.div(classes = "detailsContainer") button(classes = "getWeatherButton") span(classes = "primaryText") { +"${Math.round(max)} °C" } Extension functions Extension functions are a beautiful feature of Kotlin. Extension functions allow us to add the functions in the native class sets. All extension functions are statically resolved. Check out DateExtension.kt, it has three extension functions written for Long objects. They return different date formats. The code inside it may look a bit strange, which we will discuss in the following section: fun Long.getShortDate(): String { val getFormattedDate: dynamic = js("window.getShortDate") return getFormattedDate(this) } fun Long.getFullDate(): String { val getFormattedDate: dynamic = js("window.getFullDate") return getFormattedDate(this) } fun Long.getFullWeekDay(): String { val getFormattedDate: dynamic = js("window.getFullWeekDay") return getFormattedDate(this) } We don't need to write utility methods in Kotlin. We should prefer extension functions over Utils. Do not try to have any heavy methods as extension functions, instance functions are always good. Writing extension functions to format dates and to have some validation functions is OK. But it's not good to write an API calling function for any string class. Remember they are statically resolved. A project loaded with static is not good for memory. Giving final touches We wrote many lines of code so far. We also refactored them periodically. Once again it's a time to refactor and look for the possible improvements. Let's take a look back and see if there is any possibility of refactoring the code further. Adding CSS Let's add some custom font and style some of the missed HTML elements. We have used Robot font, you can use any font of your desire. It's a simple one-liner code to mention the font in the app. Add the following line to your index.html page just after the <body> tag: <link href="https://fonts.googleapis.com/css? family=Roboto+Condensed" rel="stylesheet"> And in main.css apply the font to an entire HTML page: html * { font-family: 'Roboto Condensed', sans-serif; } Reload the page. Looks beautiful now, doesn't it? To summarize, we learned various elements of Kotlin such as setting up Kotlin for JavaScript projects, interacting with DOM elements, DSL, and so on. The purpose of this article was to show that Kotlin's support for JavaScript is no more an experiment. It's already production ready. You can see what can be done using the benefits of statically typed programming languages and powerful JavaScript ecosystems. To know more about how to use Kotlin code for writing a Node.js application, you may refer to this book Kotlin Blueprints. Build your first Android app with Kotlin How to convert Java code into Kotlin 5 application development tools that will matter in 2018  
Read more
  • 0
  • 0
  • 7017

article-image-lighting-camera-effects-unity-2018
Amarabha Banerjee
04 May 2018
12 min read
Save for later

Implementing lighting & camera effects in Unity 2018

Amarabha Banerjee
04 May 2018
12 min read
Today, we will explore lighting & camera effects in Unity 2018. We will start with cameras to include perspectives, frustums, and Skyboxes. Next, we will learn a few uses of multiple cameras to include mini-maps. We will also cover the different types of lighting, explore reflection probes, and conclude with a look at shadows. Working with cameras Cameras render scenes so that the user can view them. Think about the hidden complexity of this statement. Our games are 3D, but people playing our games view them on 2D displays such as television, computer monitors, or mobile devices. Fortunately for us, Unity makes implementing cameras easy work. Cameras are GameObjects and can be edited using transform tools in the Scene view as well as in the Inspector panel. Every scene must have at least one camera. In fact, when a new scene is created, Unity creates a camera named Main Camera. As you will see later in this chapter, a scene can have multiple cameras. In the Scene view, cameras are indicated with a white camera silhouette, as shown in the following screenshot: When we click our Main Camera in the Hierarchy panel, we are provided with a Camera Preview in the Scene view. This gives us a preview of what the camera sees as if it were in game mode. We also have access to several parameters via the Inspector panel. The Camera component in the Inspector panel is shown here: Let's look at each of these parameters with relation to our Cucumber Beetle game: The Clear Flags parameter lets you switch between Skybox, Solid Color, Depth Only, and Don't Clear. The selection here informs Unity which parts of the screen to clear. We will leave this setting as Skybox. You will learn more about Skyboxes later in this chapter. The Background parameter is used to set the default background fill (color) of your game world. This will only be visible after all game objects have been rendered and if there is no Skybox. Our Cucumber Beetle game will have a Skybox, so this parameter can be left with the default color. The Culling Mask parameter allows you to select and deselect the layers you want the camera to render. The default selection options are Nothing, Everything, Default, TransparentFX, Ignore Raycast, Water, and UI. For our game, we will select Everything. If you are not sure which layer a game object is associated with, select it and look at the Layer parameter in the top section of the Inspector panel. There you will see the assigned layer. You can easily change the layer as well as create your own unique layers. This gives you finite rendering control. The Projection parameter allows you to select which projection, perspective or orthographic, you want for your camera. We will cover both of those projections later in this chapter. When perspective projection is selected, we are given access to the Field of View parameter. This is for the width of the camera's angle of view. The value range is 1-179°. You can use the slider to change the values and see the results in the Camera Preview window. When orthographic projection is selected, an additional Size parameter is available. This refers to the viewport size. For our game, we will select perspective projection with the Field of View set to 60. The Clipping Planes parameters include Near and Far. These settings set the closest and furthest points, relative to the camera, that rendering will happen at. For now, we will leave the default settings of 0.3 and 1000 for the Near and Far parameters, respectively. The Viewport Rect parameter has four components – X, Y, W, and H – that determine where the camera will be drawn on the screen. As you would expect, the X and Y components refer to horizontal and vertical positions, and the W and H components refer to width and height. You can experiment with these values and see the changes in the Camera Preview. For our game, we will leave the default settings. The Depth parameter is used when we implement more than one camera. We can set a value here to determine the camera's priority in relation to others. Larger values indicate a higher priority. The default setting is sufficient for our game. The Rendering Path parameter defines what rendering methods our camera will use. The options are Use Graphics Settings, Forward, Deferred, Legacy Vertex Lit, and Legacy Deferred (light prepass). We will use the Use Graphics Settings option for our game, which also uses the default setting. The Target Texture parameter is not something we will use in our game. When a render texture is set, the camera is not able to render to the screen. The Occlusion Culling parameter is a powerful setting. If enabled, Unity will not render objects that are occluded, or not seen by the camera. An example would be objects inside a building. If the camera can currently only see the external walls of the building, then none of the objects inside those walls can be seen. So, it makes sense to not render those. We only want to render what is absolutely necessary to help ensure our game has smooth gameplay and no lag. We will leave this as enabled for our game. The Allow HDR parameter is a checkbox that toggles a camera's High Dynamic Range (HDR) rendering. We will leave the default setting of enabled for our game. The Allow MSAA parameter is a toggle that determines whether our camera will use a Multisample Anti-Aliasing (MSAA) render target. MSAA is a computer graphics optimization technique and we want this enabled for our game. Understanding camera projections There are two camera projections used in Unity: perspective and orthographic. With perspective projection, the camera renders a scene based on the camera angle, as it exists in the scene. Using this projection, the further away an object is from the camera, the smaller it will be displayed. This mimics how we see things in the real world. Because of the desire to produce realistic games, or games that approximate the realworld, perspective projection is the most commonly used in modern games. It is also what we will use in our Cucumber Beetle game. The other projection is orthographic. An orthographic perspective camera renders a scene uniformly without any perspective. This means that objects further away will not be displayed smaller than objects closer to the camera. This type of camera is commonly used for top-down games and is the default camera projection used in 2D and Unity's UI system. We will use perspective projection for our Cucumber Beetle game. Orientating your frustum When a camera is selected in the Hierarchy view, its frustum is visible in the Scene view. A frustum is a geometric shape that looks like a pyramid that has had its top cut off, as illustrated here: The near, or top, plane is parallel to its base. The base is also referred to as the far plane. The frustum's shape represents the viable region of your game. Only objects in that region are rendered. Using the camera object in Scene view, we can change our camera's frustum shape. Creating a Skybox When we create game worlds, we typically create the ground, buildings, characters, trees, and other game objects. What about the sky? By default, there will be a textured blue sky in your Unity game projects. That sky is sufficient for testing but does not add to an immersive gaming experience. We want a bit more realism, such as clouds, and that can be accomplished by creating a Skybox. A Skybox is a six-sided cube visible to the player beyond all other objects. So, when a player looks beyond your objects, what they see is your Skybox. As we said, Skyboxes are six-sided cubes, which means you will need six separate images that can essentially be clamped to each other to form the cube. The following screenshot shows the Default Skybox that Unity projects start with as well as the completed Custom Skybox you will create in this section: Perform the following steps to create a Skybox: In the Project panel, create a Skybox subfolder in the Assets folder. We will use this folder to store our textures and materials for the Skybox. Drag the provided six Skybox images, or your own, into the new Skybox folder. Ensure the Skybox folder is selected in the Project panel. From the top menu, select Assets | Create | Material. In the Project panel, name the material Skybox. With the Skybox material selected, turn your attention to the Inspector panel. Select the Shader drop-down menu and select SkyBox | 6 Sided. Use the Select button for each of the six images and navigate to the images you added in step 2. Be sure to match the appropriate texture to the appropriate cube face. For example, the SkyBox_Front texture matches the Front[+Z] cube face on the Skybox Material. In order to assign our new Skybox to our scene, select Window | Lighting | Settings from the top menu. This will bring up the Lighting settings dialog window. In the Lighting settings dialog window, click on the small circle to the right of the Skybox Material input field. Then, close the selection window and the Lighting window. Refer to the following screenshot: You will now be able to see your Skybox in the Scene view. When you click on the Camera in the Hierarchy panel, you will also see the Skybox as it will appear from the camera's perspective. Be sure to save your scene and your project. Using multiple cameras Our Unity games must have a least one camera, but we are not limited to using just one. As you will see we will attach our main camera, or primary camera, to our player character. It will be as if the camera is following the character around the game environment. This will become the eyes of our character. We will play the game through our character's view. A common use of a second camera is to create a mini-map that can be seen in a small window on top of the game display. These mini-maps can be made to toggle on and off or be permanent/fixed display components. Implementations might consist of a fog-of-war display, a radar showing enemies, or a global top-down view of the map for orientation purposes. You are only limited by your imagination. Another use of multiple cameras is to provide the player with the ability to switch between third-person and first-person views. You will remember that the first-person view puts the player's arms in view, while in the third-person view, the player's entire body is visible. We can use two cameras in the appropriate positions to support viewing from either camera. In a game, you might make this a toggle—say, with the C keyboard key—that switches from one camera to the other. Depending on what is happening in the game, the player might enjoy this ability. Some single-player games feature multiple playable characters. Giving the player the ability to switch between these characters gives them greater control over the game strategy. To achieve this, we would need to have cameras attached to each playable character and then give the player the ability to swap characters. We would do this through scripting. This is a pretty advanced implementation of multiple characters. Another use of multiple cameras is adding specialty views in a game. These specialty views might include looking through a door's peep-hole, looking through binoculars at the top of a skyscraper, or even looking through a periscope. We can attach cameras to objects and change their viewing parameters to create unique camera use in our games. We are only limited by our own game designs and imagination. We can also use cameras as cameras. That's right! We can use the camera game object to simulate actual in-game cameras. One example is implementing security cameras in a prison-escape game. Working with lighting In the previous sections, we explored the uses of cameras for Unity games. Just like in the real world, cameras need lights to show us objects. In Unity games, we use multiple lights to illuminate the game environment. In Unity, we have both dynamic lighting techniques as well as light baking options for better performance. We can add numerous light sources throughout our scenes and selectively enable or disable an object's ability to cast or receive shadows. This level of specificity gives us tremendous opportunity to create realistic game scenes. Perhaps the secret behind Unity's ability to so realistically render light and shadows is that Unity models the actual behavior of lights and shadows. Real-time global illumination gives us the ability to instantiate multiple lights in each scene, each with the ability to directly or indirectly impact objects in the scene that are within range of the light sources. We can also add and manipulate ambient light in our game scenes. This is often done with Skyboxes, a tri-colored gradient, or even a single color. Each new scene in Unity has default ambient lighting, which we can control by editing the values in the Lighting window. In that window, you have access to the following settings: Environment Real-time Lighting Mixed Lighting Lightmapping Settings Other Settings Debug Settings No changes to these are required for our game at this time. We have already set the environmental lighting to our Skybox. When we create our scenes in Unity, we have three options for lighting. We can use real-time dynamic light, use the baked lighting approach, or use a mixture of the two. Our games perform more efficiently with baked lighting, compared to real-time dynamic lighting, so if performance is a concern, try using baked lighting where you can. To summarize, we have discussed how to create interesting lighting and camera effects using Unity 2018. This article is an extract from the book Getting Started with Unity 2018 written by Dr. Edward Lavieri. This book will help you create fun filled real world games with Unity 2018. Game Engine Wars: Unity vs Unreal Engine Unity plugins for augmented reality application development How to create non-player Characters (NPC) with Unity 2018    
Read more
  • 0
  • 0
  • 6355
article-image-azure-function-asp-net-core-mvc-application
Aaron Lazar
03 May 2018
10 min read
Save for later

How to call an Azure function from an ASP.NET Core MVC application

Aaron Lazar
03 May 2018
10 min read
In this tutorial, we'll learn how to call an Azure Function from an ASP.NET Core MVC application. [box type="shadow" align="" class="" width=""]This article is an extract from the book C# 7 and .NET Core Blueprints, authored by Dirk Strauss and Jas Rademeyer. This book is a step-by-step guide that will teach you essential .NET Core and C# concepts with the help of real-world projects.[/box] We will get started with creating an ASP.NET Core MVC application that will call our Azure Function to validate an email address entered into a login screen of the application: This application does no authentication at all. All it is doing is validating the email address entered. ASP.NET Core MVC authentication is a totally different topic and not the focus of this post. In Visual Studio 2017, create a new project and select ASP.NET Core Web Application from the project templates. Click on the OK button to create the project. This is shown in the following screenshot: On the next screen, ensure that .NET Core and ASP.NET Core 2.0 is selected from the drop-down options on the form. Select Web Application (Model-View-Controller) as the type of application to create. Don't bother with any kind of authentication or enabling Docker support. Just click on the OK button to create your project: After your project is created, you will see the familiar project structure in the Solution Explorer of Visual Studio: Creating the login form For this next part, we can create a plain and simple vanilla login form. For a little bit of fun, let's spice things up a bit. Have a look on the internet for some free login form templates: I decided to use a site called colorlib that provided 50 free HTML5 and CSS3 login forms in one of their recent blog posts. The URL to the article is: https://colorlib.com/wp/html5-and-css3-login-forms/. I decided to use Login Form 1 by Colorlib from their site. Download the template to your computer and extract the ZIP file. Inside the extracted ZIP file, you will see that we have several folders. Copy all the folders in this extracted ZIP file (leave the index.html file as we will use this in a minute): Next, go to the solution for your Visual Studio application. In the wwwroot folder, move or delete the contents and paste the folders from the extracted ZIP file into the wwwroot folder of your ASP.NET Core MVC application. Your wwwroot folder should now look as follows: 4. Back in Visual Studio, you will see the folders when you expand the wwwroot node in the CoreMailValidation project. 5. I also want to focus your attention to the Index.cshtml and _Layout.cshtml files. We will be modifying these files next: Open the Index.cshtml file and remove all the markup (except the section in the curly brackets) from this file. Paste the HTML markup from the index.html file from the ZIP file we extracted earlier. Do not copy the all the markup from the index.html file. Only copy the markup inside the <body></body> tags. Your Index.cshtml file should now look as follows: @{ ViewData["Title"] = "Login Page"; } <div class="limiter"> <div class="container-login100"> <div class="wrap-login100"> <div class="login100-pic js-tilt" data-tilt> <img src="images/img-01.png" alt="IMG"> </div> <form class="login100-form validate-form"> <span class="login100-form-title"> Member Login </span> <div class="wrap-input100 validate-input" data-validate="Valid email is required: [email protected]"> <input class="input100" type="text" name="email" placeholder="Email"> <span class="focus-input100"></span> <span class="symbol-input100"> <i class="fa fa-envelope" aria-hidden="true"></i> </span> </div> <div class="wrap-input100 validate-input" data-validate="Password is required"> <input class="input100" type="password" name="pass" placeholder="Password"> <span class="focus-input100"></span> <span class="symbol-input100"> <i class="fa fa-lock" aria-hidden="true"></i> </span> </div> <div class="container-login100-form-btn"> <button class="login100-form-btn"> Login </button> </div> <div class="text-center p-t-12"> <span class="txt1"> Forgot </span> <a class="txt2" href="#"> Username / Password? </a> </div> <div class="text-center p-t-136"> <a class="txt2" href="#"> Create your Account <i class="fa fa-long-arrow-right m-l-5" aria-hidden="true"></i> </a> </div> </form> </div> </div> </div> The code for this chapter is available on GitHub here: Next, open the Layout.cshtml file and add all the links to the folders and files we copied into the wwwroot folder earlier. Use the index.html file for reference. You will notice that the _Layout.cshtml file contains the following piece of code—@RenderBody(). This is a placeholder that specifies where the Index.cshtml file content should be injected. If you are coming from ASP.NET Web Forms, think of the _Layout.cshtml page as a master page. Your Layout.cshtml markup should look as follows: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>@ViewData["Title"] - CoreMailValidation</title> <link rel="icon" type="image/png" href="~/images/icons/favicon.ico" /> <link rel="stylesheet" type="text/css" href="~/vendor/bootstrap/css/bootstrap.min.css"> <link rel="stylesheet" type="text/css" href="~/fonts/font-awesome-4.7.0/css/font-awesome.min.css"> <link rel="stylesheet" type="text/css" href="~/vendor/animate/animate.css"> <link rel="stylesheet" type="text/css" href="~/vendor/css-hamburgers/hamburgers.min.css"> <link rel="stylesheet" type="text/css" href="~/vendor/select2/select2.min.css"> <link rel="stylesheet" type="text/css" href="~/css/util.css"> <link rel="stylesheet" type="text/css" href="~/css/main.css"> </head> <body> <div class="container body-content"> @RenderBody() <hr /> <footer> <p>© 2018 - CoreMailValidation</p> </footer> </div> <script src="~/vendor/jquery/jquery-3.2.1.min.js"></script> <script src="~/vendor/bootstrap/js/popper.js"></script> <script src="~/vendor/bootstrap/js/bootstrap.min.js"></script> <script src="~/vendor/select2/select2.min.js"></script> <script src="~/vendor/tilt/tilt.jquery.min.js"></script> <script> $('.js-tilt').tilt({ scale: 1.1 }) </script> <script src="~/js/main.js"></script> @RenderSection("Scripts", required: false) </body> </html> If everything worked out right, you will see the following page when you run your ASP.NET Core MVC application. The login form is obviously totally non-functional: However, the login form is totally responsive. If you had to reduce the size of your browser window, you will see the form scale as your browser size reduces. This is what you want. If you want to explore the responsive design offered by Bootstrap, head on over to https://getbootstrap.com/ and go through the examples in the documentation:   The next thing we want to do is hook this login form up to our controller and call the Azure Function we created to validate the email address we entered. Let's look at doing that next. Hooking it all up To simplify things, we will be creating a model to pass to our controller: Create a new class in the Models folder of your application called LoginModel and click on the Add button:  2. Your project should now look as follows. You will see the model added to the Models folder: The next thing we want to do is add some code to our model to represent the fields on our login form. Add two properties called Email and Password: namespace CoreMailValidation.Models { public class LoginModel { public string Email { get; set; } public string Password { get; set; } } } Back in the Index.cshtml view, add the model declaration to the top of the page. This makes the model available for use in our view. Take care to specify the correct namespace where the model exists: @model CoreMailValidation.Models.LoginModel @{ ViewData["Title"] = "Login Page"; } The next portion of code needs to be written in the HomeController.cs file. Currently, it should only have an action called Index(): public IActionResult Index() { return View(); } Add a new async function called ValidateEmail that will use the base URL and parameter string of the Azure Function URL we copied earlier and call it using an HTTP request. I will not go into much detail here, as I believe the code to be pretty straightforward. All we are doing is calling the Azure Function using the URL we copied earlier and reading the return data: private async Task<string> ValidateEmail(string emailToValidate) { string azureBaseUrl = "https://core-mail- validation.azurewebsites.net/api/HttpTriggerCSharp1"; string urlQueryStringParams = $"? code=/IS4OJ3T46quiRzUJTxaGFenTeIVXyyOdtBFGasW9dUZ0snmoQfWoQ ==&email={emailToValidate}"; using (HttpClient client = new HttpClient()) { using (HttpResponseMessage res = await client.GetAsync( $"{azureBaseUrl}{urlQueryStringParams}")) { using (HttpContent content = res.Content) { string data = await content.ReadAsStringAsync(); if (data != null) { return data; } else return ""; } } } } Create another public async action called ValidateLogin. Inside the action, check to see if the ModelState is valid before continuing. For a nice explanation of what ModelState is, have a look at the following article—https://www.exceptionnotfound.net/asp-net-mvc-demystified-modelstate/. We then do an await on the ValidateEmail function, and if the return data contains the word false, we know that the email validation failed. A failure message is then passed to the TempData property on the controller. The TempData property is a place to store data until it is read. It is exposed on the controller by ASP.NET Core MVC. The TempData property uses a cookie-based provider by default in ASP.NET Core 2.0 to store the data. To examine data inside the TempData property without deleting it, you can use the Keep and Peek methods. To read more on TempData, see the Microsoft documentation here: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/app-state?tabs=aspnetcore2x. If the email validation passed, then we know that the email address is valid and we can do something else. Here, we are simply just saying that the user is logged in. In reality, we will perform some sort of authentication here and then route to the correct controller. So now you know how to call an Azure Function from an ASP.NET Core application. If you found this tutorial helpful and you'd like to learn more, go ahead and pick up the book C# 7 and .NET Core Blueprints. What is ASP.NET Core? Why ASP.NET makes building apps for mobile and web easy How to dockerize an ASP.NET Core application    
Read more
  • 0
  • 2
  • 15500

article-image-build-a-foodie-bot-with-javascript
Gebin George
03 May 2018
7 min read
Save for later

Build a foodie bot with JavaScript

Gebin George
03 May 2018
7 min read
Today, we are going to build a chatbot that can search for restaurants based on user goals and preferences. Let us begin by building Node.js modules to get data from Zomato based on user preferences. Create a file called zomato.js. Add a request module to the Node.js libraries using the following command in the console: This tutorial has been taken from Hands-On Chatbots and Conversational UI Development. > npm install request --save In zomato.js, add the following code to begin with: var request = require('request'); var baseURL = 'https://developers.zomato.com/api/v2.1/'; var apiKey = 'YOUR_API_KEY'; var catergories = null; var cuisines = null; getCategories(); getCuisines(76); Replace YOUR_API_KEY with your Zomato key. Let's build functions to get the list of categories and cuisines at startup. These queries need not be run when the user asks for a restaurant search because this information is pretty much static: function getCuisines(cityId){ var options = { uri: baseURL + 'cuisines', headers: { 'user-key': apiKey }, qs: {'city_id':cityId}, method: 'GET' } var callback = function(error, response, body) { if (error) { console.log('Error sending messages: ', error) } else if (response.body.error) { console.log('Error: ', response.body.error) } else { console.log(body); cuisines = JSON.parse(body).cuisines; } } request(options,callback); } The preceding code will fetch a list of cuisines available in a particular city (identified by a Zomato city ID). Let us add the code for identifying the list of categories: function getCategories(){ var options = { uri: baseURL + 'categories', headers: { 'user-key': apiKey }, qs: {}, method: 'GET' } var callback = function(error, response, body) { if (error) { console.log('Error sending messages: ', error) } else if (response.body.error) { console.log('Error: ', response.body.error) } else { categories = JSON.parse(body).categories; } } request(options,callback); } Now that we have the basic functions out of our way, let us code in the restaurant search code: function getRestaurant(cuisine, location, category){ var cuisineId = getCuisineId(cuisine); var categoryId = getCategoryId(category); var options = { uri: baseURL + 'locations', headers: { 'user-key': apiKey }, qs: {'query':location}, method: 'GET' } var callback = function(error, response, body) { if (error) { console.log('Error sending messages: ', error) } else if (response.body.error) { console.log('Error: ', response.body.error) } else { console.log(body); locationInfo = JSON.parse(body).location_suggestions; search(locationInfo[0], cuisineId, categoryId); } } request(options,callback); } function search(location, cuisineId, categoryId){ var options = { uri: baseURL + 'search', headers: { 'user-key': apiKey }, qs: {'entity_id': location.entity_id, 'entity_type': location.entity_type, 'cuisines': [cuisineId], 'categories': [categoryId]}, method: 'GET' } var callback = function(error, response, body) { if (error) { console.log('Error sending messages: ', error) } else if (response.body.error) { console.log('Error: ', response.body.error) } else { console.log('Found restaurants:') var results = JSON.parse(body).restaurants; console.log(results); } } request(options,callback); } The preceding code will look for restaurants in a given location, cuisine, and category. For instance, you can search for a list of Indian restaurants in Newington, Edinburgh that do delivery. We now need to integrate this with the chatbot code. Let us create a separate file called index.js. Let us begin with the basics: var restify = require('restify'); var builder = require('botbuilder'); var request = require('request'); var baseURL = 'https://developers.zomato.com/api/v2.1/'; var apiKey = 'YOUR_API_KEY'; var catergories = null; var cuisines = null; Chapter 6 [ 247 ] getCategories(); //setTimeout(function(){getCategoryId('Delivery')}, 10000); getCuisines(76); //setTimeout(function(){getCuisineId('European')}, 10000); // Setup Restify Server var server = restify.createServer(); server.listen(process.env.port || process.env.PORT || 3978, function () { console.log('%s listening to %s', server.name, server.url); }); // Create chat connector for communicating with // the Bot Framework Service var connector = new builder.ChatConnector({ appId: process.env.MICROSOFT_APP_ID, appPassword: process.env.MICROSOFT_APP_PASSWORD }); // Listen for messages from users server.post('/foodiebot', connector.listen()); Add the bot dialog code to carry out the restaurant search. Let us design the bot to ask for cuisine, category, and location before proceeding to the restaurant search: var bot = new builder.UniversalBot(connector, [ function (session) { session.send("Hi there! Hungry? Looking for a restaurant?"); session.send("Say 'search restaurant' to start searching."); session.endDialog(); } ]); // Search for a restaurant bot.dialog('searchRestaurant', [ function (session) { session.send('Ok. Searching for a restaurant!'); builder.Prompts.text(session, 'Where?'); }, function (session, results) { session.conversationData.searchLocation = results.response; builder.Prompts.text(session, 'Cuisine? Indian, Italian, or anything else?'); }, function (session, results) { session.conversationData.searchCuisine = results.response; builder.Prompts.text(session, 'Delivery or Dine-in?'); }, function (session, results) { session.conversationData.searchCategory = results.response; session.send('Ok. Looking for restaurants..'); getRestaurant(session.conversationData.searchCuisine, session.conversationData.searchLocation, session.conversationData.searchCategory, session); } ]) .triggerAction({ matches: /^search restaurant$/i, confirmPrompt: 'Your restaurant search task will be abandoned. Are you sure?' }); Notice that we are calling the getRestaurant() function with four parameters. Three of these are ones that we have already defined: cuisine, location, and category. To these, we have to add another: session. This passes the session pointer that can be used to send messages to the emulator when the data is ready. Notice how this changes the getRestaurant() and search() functions: function getRestaurant(cuisine, location, category, session){ var cuisineId = getCuisineId(cuisine); var categoryId = getCategoryId(category); var options = { uri: baseURL + 'locations', headers: { 'user-key': apiKey }, qs: {'query':location}, method: 'GET' } var callback = function(error, response, body) { if (error) { console.log('Error sending messages: ', error) } else if (response.body.error) { console.log('Error: ', response.body.error) } else { console.log(body); locationInfo = JSON.parse(body).location_suggestions; search(locationInfo[0], cuisineId, categoryId, session); } } request(options,callback); } function search(location, cuisineId, categoryId, session){ var options = { uri: baseURL + 'search', headers: { 'user-key': apiKey }, qs: {'entity_id': location.entity_id, 'entity_type': location.entity_type, 'cuisines': [cuisineId], 'category': categoryId}, method: 'GET' } var callback = function(error, response, body) { if (error) { console.log('Error sending messages: ', error) } else if (response.body.error) { console.log('Error: ', response.body.error) } else { console.log('Found restaurants:') console.log(body); //var results = JSON.parse(body).restaurants; //console.log(results); var resultsCount = JSON.parse(body).results_found; console.log('Found:' + resultsCount); session.send('I have found ' + resultsCount + ' restaurants for you!'); session.endDialog(); } } request(options,callback); } Once the results are obtained, the bot responds using session.send() and ends the dialog: Now that we have the results, let's present them in a more visually appealing way using cards. To do this, we need a function that can take the results of the search and turn them into an array of cards: function presentInCards(session, results){ var msg = new builder.Message(session); msg.attachmentLayout(builder.AttachmentLayout.carousel) var heroCardArray = []; var l = results.length; if (results.length > 10){ l = 10; } for (var i = 0; i < l; i++){ var r = results[i].restaurant; var herocard = new builder.HeroCard(session) .title(r.name) .subtitle(r.location.address) .text(r.user_rating.aggregate_rating) .images([builder.CardImage.create(session, r.thumb)]) .buttons([ builder.CardAction.imBack(session, "book_table:" + r.id, "Book a table") ]); heroCardArray.push(herocard); } msg.attachments(heroCardArray); return msg; } And we call this function from the search() function: function search(location, cuisineId, categoryId, session){ var options = { uri: baseURL + 'search', headers: { 'user-key': apiKey }, qs: {'entity_id': location.entity_id, 'entity_type': location.entity_type, 'cuisines': [cuisineId], 'category': categoryId}, method: 'GET' } var callback = function(error, response, body) { if (error) { console.log('Error sending messages: ', error) } else if (response.body.error) { console.log('Error: ', response.body.error) } else { console.log('Found restaurants:') console.log(body); var results = JSON.parse(body).restaurants; var msg = presentInCards(session, results); session.send(msg); session.endDialog(); } } request(options,callback); } Here is how it looks: We saw how to build a restaurant search bot, that gives you restaurant suggestions as per your preference. If you found our post useful check out Chatbots and Conversational UI Development. Top 4 chatbot development frameworks for developers How to create a conversational assistant using Python My friend, the robot: Artificial Intelligence needs Emotional Intelligence    
Read more
  • 0
  • 0
  • 6314

article-image-amazon-s3-security-access-policies
Savia Lobo
03 May 2018
7 min read
Save for later

Amazon S3 Security access and policies

Savia Lobo
03 May 2018
7 min read
In this article, you will get to know about Amazon S3, and the security access and policies associated with it.  AWS provides you with S3 as the object storage, where you can store your object files from 1 KB to 5 TB in size at a low cost. It's highly secure, durable, and scalable, and has unlimited capacity. It allows concurrent read/write access to objects by separate clients and applications. You can store any type of file in AWS S3 storage. [box type="shadow" align="" class="" width=""]This article is an excerpt taken from the book,' Cloud Security Automation', written by Prashant Priyam.[/box] AWS keeps multiple copies of all the data stored in the standard S3 storage, which are replicated across devices in the region to ensure the durability of 99.999999999%. S3 cannot be used as block storage. AWS S3 storage is further categorized into three different sections: S3 Standard: This is suitable when we need durable storage for files with frequent access. Reduced Redundancy Storage: This is suitable when we have less critical data that is persistent in nature. Infrequent Access (IA): This is suitable when you have durable data with nonfrequent access. You can opt for Glacier. However, in Glacier, you have a very long retrieval time. So, S3 IA becomes a suitable option. It provides the same performance as the S3 Standard storage. AWS S3 has inbuilt error correction and fault tolerance capabilities. Apart from this, in S3 you have an option to enable versioning and cross-region replication (cross-origin resource sharing (CORS)). If you want to enable versioning on any existing bucket, versioning will be enabled only for new objects in that bucket, not for existing objects. This also happens in the case of CORS, where you can enable cross-region replication, but it will be applicable only for new objects. Security in Amazon S3 S3 is highly secure storage. Here, we can enable fine-grained access policies for resource access and encryption. To enable access-level security, you can use the following: S3 bucket policy IAM access policy MFA for object deletion The S3 bucket policy is a JSON code that defines what will be accessed by whom and at what level: { "Version": "2008-10-17", "Statement": [ { "Sid": "AllowPublicRead", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": [ "s3:GetObject" ], "Resource": [ "arn:aws:s3:::prashantpriyam/*" ] } ] } In the preceding JSON code, we have just allowed read-only access to all the objects (as defined in the Action section) for an S3 bucket named prashantpriyam (defined in the Resource section). Similar to the S3 bucket policy, we can also define an IAM policy for S3 bucket access: { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetBucketLocation", "s3:ListAllMyBuckets" ], "Resource": "arn:aws:s3:::*" }, { "Effect": "Allow", "Action": ["s3:ListBucket"], "Resource": ["arn:aws:s3:::prashantpriyam"] }, { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:DeleteObject" ], "Resource": ["arn:aws:s3:::prashantpriyam/*"] } ] } In the preceding policy, we want to give the user full permissions on the S3 bucket from the AWS console as well. In the following section of policy (JSON code), we have granted permission to the user to get the bucket location and list all the buckets for traversal, but here we cannot perform other operations, such as getting object details from the bucket: { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetBucketLocation", "s3:ListAllMyBuckets" ], "Resource": "arn:aws:s3:::*" }, { "Effect": "Allow", "Action": ["s3:ListBucket"], "Resource": ["arn:aws:s3:::prashantpriyam"] }, While in the second section of the policy (specified as follows), we have given permission to users to traverse into the prashantpriyam bucket and perform PUT, GET, and DELETE operations on the object: { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:DeleteObject" ], "Resource": ["arn:aws:s3:::prashantpriyam/*"] } MFA enables additional security on your account where, after password-based authentication, it asks you to provide the temporary code generated from AWS MFA. We can also use a virtual MFA such as Google Authenticator. AWS S3 supports MFA-based API, which helps to enforce MFA-based access policy on S3 bucket. Let's look at an example where we are giving users read-only access to a bucket while all other operations require an MFA token, which will expire after 600 seconds: { "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Deny", "Principal": "*", "Action": "s3:*", "Resource": "arn:aws:s3:::prashantpriyam/priyam/*", "Condition": {"Null": {"aws:MultiFactorAuthAge": true }} }, { "Sid": "", "Effect": "Deny", "Principal": "*", "Action": "s3:*", "Resource": "arn:aws:s3:::prashantpriyam/priyam/*", "Condition": {"NumericGreaterThan": {"aws:MultiFactorAuthAge": 600 }} }, { "Sid": "", "Effect": "Allow", "Principal": "*", "Action": ["s3:GetObject"], "Resource": "arn:aws:s3:::prashantpriyam/*" } ] } In the preceding code, you can see that we have allowed all the operations on the S3 bucket if they have an MFA token whose life is less than 600 seconds. Apart from MFA, we can enable versioning so that S3 can automatically create multiple versions of the object to eliminate the risk of unwanted modification of data. This can be enabled with the AWS Console only. You can also enable cross-region replication so that the S3 bucket content can be replicated to the other selected regions. This option is mostly used when you want to deliver static content into two different regions, but it also gives you redundancy. For infrequently accessed data you can enable a lifecycle policy, which helps you to transfer the objects to a low-cost archival storage called Glacier. Let's see how to secure the S3 bucket using the AWS Console. To do this, we need to log in to the S3 bucket and search for S3. Now, click on the bucket you want to secure: In the screenshot, we have selected the bucket called velocis-manali-trip-112017 and, in the bucket properties, we can see that we have not enabled the security options that we have learned so far. Let's implement the security. Now, we need to click on the bucket and then on the Properties tab. From here, we can enable Versioning, Default encryption, Server access logging, and Object-level logging: To enable Server access logging, you need to specify the name of the bucket and a prefix for the logs: To enable encryption, you need to specify whether you want to use AES 256 or AWS KMS based encryption. Now, click on the Permission tab. From here, you will be able to define the Access Control List, Bucket Policy, and CORS configuration: In Access Control List, you can define who will access what and to what extent, in Bucket Policy you define resource-based permissions on the bucket (like we have seen in the example for bucket policy), and in CORS configuration we define the rule for CORS. Let's look at a sample CORS file: <!-- Sample policy --> <CORSConfiguration> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <AllowedMethod>GET</AllowedMethod> <MaxAgeSeconds>3000</MaxAgeSeconds> <AllowedHeader>Authorization</AllowedHeader> </CORSRule> </CORSConfiguration> It's an XML script that allows read-only permission to all the origins. In the preceding code, instead of a URL, the origin is the wildcard *, which means anyone. Now, click on the Management section. From here, we define the life cycle rule, replication, and so on: In life cycle rules, an S3 bucket object is transferred to the Standard-IA tier after 30 days and transferred to Glacier after 60 days. This is how we define security on the S3 bucket. To summarize, we learned about security access and policies in Amazon S3. If you've enjoyed reading this, do check out this book, 'Cloud Security Automation' to know how private cloud security functions can be automated for better time and cost-effectiveness. Creating and deploying an Amazon Redshift cluster Amazon Sagemaker makes machine learning on the cloud easy How cybersecurity can help us secure cyberspace
Read more
  • 0
  • 0
  • 4797
article-image-how-android-app-developers-can-convert-iphone-apps
Michael Kordvani
02 May 2018
5 min read
Save for later

How Android app developers can convert iPhone apps

Michael Kordvani
02 May 2018
5 min read
Businesses like to cast their nets as wide as possible in search of new customers. This type of broad outreach requires designing mobile apps for both iOS and Android phones. Although iPhones are very popular in the U.S. market, if you want to step up and attract global customers, you need to expand your product to the Android platform. Most Android app developers will face this challenge at some point: how to create an Android app from an iPhone app, and make it at least as successful as the primary product. It's not surprising that developers tend to concentrate on building up their skills for one platform in particular. Both platforms have their challenges. Spreading yourself too thin in an effort to meet the requirements for both phones can mean that the user experience suffers. But the challenges can be overcome. iPhone apps are great, but limited in terms of market size. Android apps are the biggest market players, and companies often ask the same team of Android app developers to take on both projects at once. With a few tips and tricks to help you along, you’ll be able to make your project a success. What are the benefits of redesigning an iPhone App into an Android App? Before converting your iPhone app into an Android app, it’s important to keep in mind that enlarging the customer base is not the only benefit. You will also get the chance to add more features, diversify money-making methods with new options for in-app purchasing and advertisements, as well as get a full product overhaul at only a fraction of the cost of starting from scratch. These are the obvious reasons why companies usually don’t overlook the possibility of iPhone app conversion. When a company has a team of iPhone and Android app developers and can save on new projects, it often pays off handsomely in the end. Hiring a product manager to oversee the process is not a bad idea if you have the budget for it. A manager can help the team understand the similar elements of these otherwise different platforms. Despite the UX/UI design differences in terms of navigation, icons and app architecture, you still need to code with customer requirements in mind. Also, before you start redesigning the product, keep in mind that the business model may need to be tweaked and the store submission process is quite different. UX and UI design differences between Android and iOS The platforms have significant differences in terms of design. You cannot simply copy the elements from an iPhone to an Android phone environment, at least not in a clear-cut way. You must design with the already-set styles in mind. For example, Android apps use a specific icon library, which is different from the one used for iOS. Android app developers and designers work with a wider color palette, varying in nuances and shades, while iPhone apps are more standardized. Roboto is the preferred Android font, and San Francisco is its iPhone counterpart. The hierarchical typography is not the same either. Because of the variations in the navigation tools, the user interface looks very different on Android phones. iPhone navigation is concentrated at the bottom; Android phones use more side and top navigation bars. Don’t forget about the thumb issue. iPhones are generally built around an average-sized thumb. With Android, you have a bit more leeway to accommodate all thumb sizes. Even if you focus only on these design basics, the user interface on an iPhone will still look different than the one on an Android smartphone. If we factor in button styles (flat on iOS vs. flat/floating on Android), grids and action sheets, as well as dropdown menus, things get even more complex. This guide offers a helpful comparison overview you can use when converting iPhone apps into Android apps. Sizing and resolution on Android phones also present their own challenges. Designers need to include different Android screen resolutions, which is already significantly more challenging than designing for the unified iPhone layout. iPhone app developers use points, and Android app developers use pixels when measuring screen objects, such as fonts and icons. The pt/px ratio is 0.75. At the same time, clients need some degree of standardization for brand recognition. They don’t want to confuse users with two apps that don’t appear to be from the same company. Further considerations Android app developers need to make about code and external libraries It can be challenging to find a team of Android app developers who also know how to code in iOS-friendly languages. However, it may be more efficient and cost-effective than working with two different teams. Programming languages that work for both Android apps and iOS apps are Kotlin and C-languages. Nonetheless, both platforms have widely preferred languages: Swift for iPhone apps and Java for Android apps. Android app developers should also check for compatibility before using external libraries and tools in the conversion project. Although challenging, converting iPhone apps for the Android OS platform is far from impossible. After all, people do it every day, as dual-platform apps are the rule rather than the exception. All you need to do to make a great product is to understand the key differences and make the necessary adjustments. Build your first Android app with Kotlin How to Secure and Deploy an Android App Why are Android developers switching from Java to Kotlin?
Read more
  • 0
  • 0
  • 2794

article-image-salesforce-crm-lightning-experience
Richa Tripathi
02 May 2018
4 min read
Save for later

Build a custom Admin Home page in Salesforce CRM Lightning Experience

Richa Tripathi
02 May 2018
4 min read
Today, we will learn how to build a custom Admin Home page and a Home page template with the Salesforce Lightning App Builder. [box type="note" align="" class="" width=""]This article is an excerpt from a book written by Paul Goodey, titled Salesforce CRM Admin Cookbook - Second Edition. This book will help you implement advanced user interface techniques to improve the look and feel of Salesforce CRM.[/box] The sales performance or opportunity top deals components, which are provided out of the box on the Homepage, give sales people a very good insight into their sale activities. However, sales performance may not necessarily be relevant to or desired by non-sales users with job functions in other areas, such as marketing, service, finance, or even Salesforce system administration. Rather than presenting the default Home page to all users in all business functions, you can create custom Home pages with features relevant to specific types of users, and assign the customized pages to different user profiles with Lightning App Builder in Lightning Experience. There are two methods of creating custom Home pages in Salesforce CRM Lightning Experience. These methods involve either editing an existing Home page or creating a new page using a Home page template. In this recipe, we will create a new custom Home page using Lightning App Builder and a Home page template. How to do it... Carry out the following steps to build a new custom Home page using Lightning App Builder: Click on the Setup gear icon at the top right of the main Home page, as shown in the following screenshot:      Click the Setup option, as shown in the following screenshot: Type app builder in the Quick Find search box, as shown in the following screenshot: Select the Lightning App Builder option. Click the New button, as shown in the following screenshot: In the resulting Create a New Lightning Page dialog, choose the Home page Lightning Experience page type, as shown in the following screenshot: Click on Next. Now enter Admin in the Label box presented in the next dialog and then click on Next. In the final dialog, keep the tab option set as CHOOSE PAGE TEMPLATE, which shows the selection of Standard Home Page  as default, as shown in the following screenshot: 10. Click on Finish. 11. In the resulting Home page Layout screen, drag the desired components from the left-hand components pane, which contains all the standard components available for the Home page, onto the canvas section. Here, we will drag the Recent Items to the top section, the Chatter Feed to the bottom left, the Chatter Publisher to the bottom right, and the App Launcher component to the right-hand section. 12. Enter This is a custom Home page created for use by Salesforce CRM Administrators in the Description box of the page, as shown in the following screenshot: 13. Finally, click on Save, as shown in the following screenshot: 14. After the page has been saved, the Home page must be activated. Upon saving the page, the Activation... option will be visible, as shown in the following screenshot: 15. Click on Activation... . When clicking on Save for the very first time you will be presented with a Page Saved dialog that provides an Activate button to active the page. The dialog also presents a message saying Activate this page to make it visible to your users along with a checkbox with the caption Don't show this message again, which, when checked, prevents the dialog from reappearing. 16. In the resulting Activation dialog, choose the Assign this Home page to specific profiles option, as shown in the following screenshot: 17. Click on Next. 18. In the resulting Select Profiles dialog, choose the System Administrator profile, as shown in the following screenshot: 19. Click on Next. 20. Finally, in the resulting Review Assignments confirmation dialog, click on Activate, as shown in the following screenshot: How it works... When system administrators navigate to the Salesforce CRM Home page, they are presented with a custom Home page, as shown in the following screenshot: If you found our post useful, do check out this book Salesforce CRM Admin Cookbook - Second Edition, to explore advanced features of the Salesforce CRM’s Lightning interface. Getting Started with Salesforce Lightning Experience How to create and prepare your first dataset in Salesforce Einstein  
Read more
  • 0
  • 0
  • 4379