# Monday, August 26, 2019

Episode 576

Dan Rey on Microsoft Surface

Dan Rey describes the different versions of Microsoft Surface and how you can use them to be more productive.

Monday, August 26, 2019 9:16:00 AM (GMT Daylight Time, UTC+01:00)
# Sunday, August 25, 2019

WhiteTeethWhite Teeth by Zadie Smith follows the lives of old friends Archie Jones and Samad Iqbal. They met when serving together in a tank in World War II, where they got lost, missed the end of the war, and sentenced a war criminal to death; they remained friends; married much younger women; had children; worked menial jobs in north London; and spend their free time in a filthy pub drinking beer and eating greasy food.

But they are very different. Archie is English and simple and easygoing; Samal is a fiery and opinionated Bangladeshi immigrant, who wants his family to maintain the traditions of his homeland.

Samal is so troubled by the English influence on his family that he sends his son Magid back to Bangladesh so he can learn his ancestral ways.

The plot becomes more complex as Smith introduces more characters and tells their backstories and their lives become more and more intertwined. In addition to Archie and Samad, she gives us:

Clara: Archie's young Jamaican wife, who is trying to escape the influence of her Jehovah's Witness mother.

Alsana: Samad's wife. She never forgives Samad for sending away their son.

Millat and Magid: Twin sons of Samad and Alsana. They grow up with very different personalities. After Magid is sent to Bangladesh, Millat turns to a life of pot-smoking and womanizing for a few years, before embracing Islam. Magid rejects religion and embraces intellectualism.

Irie: Archie and Clara's daughter. She is intelligent but lacks self-esteem and has a hopeless crush on Millat.

The Chalfens, an intellectual, liberal, well-meaning, dysfunctional family, who try (sometimes successfully) to mentor the Jones and Iqbal children.

There are other characters, and each has their backstory and their quirks, but the narrative revolves largely around the characters listed above. The book often jumps around in time to reveal the backstories of each character. But it does so succinctly and successfully. In the end, all the characters end up in the same room with different goals and an unexpected result.

Smith explores several conflicts including the struggle between immigrant assimilation and tradition to the role of race in society; the difficulty of parents and children to understand and relate to one another; and the meaning of religion in individual lives. She does so with a good story and with a witty prose, as in the following:

"Oh he loves her; just as the English loved India and Africa and Ireland; it is the love that is the problem, people treat their lovers badly."

I enjoyed the characters and I enjoyed the story.

White Teeth is one of the best novels I've read this year.

Sunday, August 25, 2019 7:38:00 PM (GMT Daylight Time, UTC+01:00)
# Saturday, August 24, 2019

Weinberg-10A jukebox (for those too young to remember) was a machine filled with black vinyl discs - each containing a different song. They could be found in a lot of bars and diners and patrons could insert one or more coins and select the songs they wanted to hear.

Max Weinberg's Jukebox works on the same principle. A screen next to the stage continuously scrolled a list of almost 200 songs and Max periodically went into the audience to ask what people wanted to hear. And then he and his band played those requests.

Weinberg (for those too young to remember) rose to fame as the drummer of Bruce Springsteen's legendary E Street Band; and later led Conan O'Brien's house band for both the Late Show and the Tonight Show.

Max Weinberg opened his City Winery show Friday evening with Cream's "White Room" and Tom Petty's "American Girl" before soliciting requests from the audience. Anything on the scrolling list was fair game and the list was packed with classic rock favourites from The Beatles, The Who, The Stones, Springsteen (of course), and a host of others. Max played the drums and was accompanied by 2 guitarists and a bass player - each of which took turns singing lead.

In 2+ hours, I counted 26 songs performed by the band, including "Lola", "Drift Away", and "Me and Julio" - each delivered with tight playing, high-quality musicianship and great enthusiasm.

It was like listening to a really good bar cover band with one famous guy in it.

Weinberg-22They closed the night with a trio of high-energy Springsteen songs: "Pink Cadillac", "Dancing in the Dark", and "Glory Days". For the final song, Max invited audience members to join the band onstage.

A great concert (for those too young to remember) happens when both the audience and the performers enjoy themselves. This was one of those evenings.


More photos

Saturday, August 24, 2019 7:01:42 AM (GMT Daylight Time, UTC+01:00)
# Friday, August 23, 2019

Recently, I was working on a VM that someone else provided me and I needed to download an executable from the Internet onto this VM. I discovered that the only installed browser on the VM was Internet Explorer 11 and that the browser was configured to prevent anyone from downloading files from the Internet.

I don't know if this is the default setting for IE 11, but here is how to change the setting to allow users to download files.

Open Internet Explorer.

From the menu, select Tools | Internet Options

The "Internet Options" dialog displays. Select the "Security" tab, as shown in Fig. 1.

IE01
Fig. 1

Click the [Custom Level] button. The "Security Settings" dialog displays. Scroll down to the "Downloads/File download" section, as shown in Fig. 2.

IE02
Fig. 2

Select the "Enable" radio button and click the [OK] button. If prompted for confirmation, click [Yes].

Click the [OK] button to close the "Internet Options" dialog.

Now you can download files linked within the browser.

Friday, August 23, 2019 11:17:00 AM (GMT Daylight Time, UTC+01:00)

GCast 62:

Sentiment Analysis Cognitive Service

This video explains the Sentiment Analysis service, which is part of the Text Analytics Cognitive Service.

Friday, August 23, 2019 4:47:19 AM (GMT Daylight Time, UTC+01:00)
# Wednesday, August 21, 2019

A data warehouse ("DW") is an ideal tool for collecting and associated disparate data.

A data warehouse has been a part of Microsoft SQL Server for decades, so it's not surprising that it is also included in Microsoft Azure.

To create a SQL Data Warehouse in Azure, navigate to the Azure Portal, sign in, and click the [Create a resource] button (Fig. 1).

dw01-CreateANewResourceButton
Fig. 1

From the menu, select Databases | SQL Data Warehouse, as shown in Fig. 2

dw02-SqlDataWarehouse
Fig. 2

The "SQL Data Warehouse" dialog displays, allowing you to enter information about your new data warehouse, as shown in Fig. 3

dw03-NewSqlDataWarehouse
Fig. 3

At the "Subscription" field, select the subscription in which you wish to create this data warehouse. Most of you will have only one subscription.

At the "Resource group" field, select an existing resource group or click the "Create new" link to create a new resource group in which to add this data warehouse. A resource group is an organizational unit to keep together related Azure resources.

At the "Data warehouse name" field, enter a unique name for your warehouse.

The "Server" field lists all SQL servers in the selected subscription. Every data warehouse is stored in one SQL Server. Select the SQL Server for this DW or click the "Create new" link to create a new SQL Server.

Clicking "Create new" displays the "New server" blade, as shown in Fig. 4. In this blade, you can enter the server name, location, and admin login credentials for a new server.

dw04-NewServer
Fig. 4

Click the [Review + create] button to display the "Review + create" tab of the "SQL Data Warehouse" dialog, as shown in Fig. 5.

dw05-ReviewCreate
Fig. 5

Click the [Create] button to create a new SQL Data Warehouse. This process may take a few minutes (longer if you also chose to create a new server).

After the Data Warehouse creation is complete, you can navigate to its management page. The "Overview" blade is shown in Fig. 6.

dw06-Overview
Fig. 6

In this article, you learned how to create a new Azure SQL Data Warehouse.

Wednesday, August 21, 2019 3:00:00 PM (GMT Daylight Time, UTC+01:00)
# Sunday, August 18, 2019

HerzogPoor Moses Herzog.

His wife convinced him to buy a house in Chicago; then tried to have him committed; then, left him for his best friend. On top of that, he is denied contact with either of his children.

Moses sets out for Chicago with his later father's antique pistol, 2 bullets, and murder on his mind. But nothing goes right, and his plans fall apart, and he is in an automobile accident and the police discover his loaded pistols.

The action does of Saul Bellow's Herzog does not happen until the novel is at least half over. But the author keeps us engaged through Moses's angst, as his life falls apart. Moses deals with his depression by writing letters - most of which are never sent and many of which are addressed to famous people such as Friedrich Nietzsche and (then-President) Dwight Eisenhower.

Herzog is unstable; but he is not crazy as his shrewish wife asserts. And his letter-writing decreases as he comes to terms with the cards he is dealt.

Bellow's writing is poignant and sad, but sometimes humorous, with lines such as

"Lead me into Penn Station"
and
"Will never understand what women want. What do they want? They eat green salad and drink human blood."

This book will appeal to anyone who has experienced the helplessness of a mid-life crisis; or the pain of betrayal; or the paralysis of uncertainty.

Sunday, August 18, 2019 4:19:00 PM (GMT Daylight Time, UTC+01:00)
# Saturday, August 17, 2019

UbikDeath is very different in the universe of Philip K. Dick's Ubik. Rather than simply ending life or transitioning to an afterlife, the recently dead remain cognizant. If properly preserved, technology exists that allows the living to communicate with the dead - sometimes for years. The consciousness slowly decays over time, after which the deceased finally cease to exist or are reborn anew.

Psychics are common enough in this universe to keep Glen Runciter busy. His company specializes in protecting people from psychic intrusion.

A group of powerful anti-psychics, led by Runciter, travel to the moon to meet with a potential client, where they are attacked and seemingly hurled back in time to the year 1939. But not everything is like the 1939 of their own past and they wonder exactly where they are.

Runciter is a good man and so is his employee Joe Chip. Chip is the perfect hero. He is loyal to his employer and dedicated to finding the truth; but he is financially irresponsible and always lacking funds (a problem when every appliance, device, and door requires a cash fee before it will operate).

Ubik is an imaginative tale of action and drama and speculative science fiction. Dick does an excellent job of taking far-fetched ideas and making them seem plausible. In under 250 pages he builds an entire world; then, destroys that world and creates another.

The story is both dark and humorous.

This novel influenced science fiction for many years after its 1969 publication. Douglas Adams must have read about the annoying talking doors when he wrote them into his Hitchhiker series. At times, we see nested realities, in a way that echoed in the 2010 film "Inception".

The narrative keeps changing our expectations. He keeps us guessing about reality versus illusion and life versus death and past versus present. And that's just the way Philip K. Dick wants it.

Saturday, August 17, 2019 8:21:00 AM (GMT Daylight Time, UTC+01:00)
# Friday, August 16, 2019

In the last article, I walked through the syntax of calling the Bing Spell Check service.

In this article, I will walk through a simple JavaScript application that calls this service.

If you want to follow along this sample is part of my Cognitive Services demos, which you can find on GitHub at https://github.com/DavidGiard/CognitiveSvcsDemos 

This project is found in the "SpellCheckDemo" folder.

Here is the main web page:

Listing 1:

<html>
<head>
    <title>Spell Check Demo</title>
    <script src="scripts/jquery-1.10.2.min.js"></script>
    <script src="scripts/script.js"></script>
    <script src="scripts/getkey.js"></script>
    <link rel="stylesheet" href="css/site.css">
</head>
 <body>
     <h1>Spell Check Demo</h1>
     <div>
         <textarea id="TextToCheck">Life ig buuutiful all the tyme
         </textarea>
     </div>
    <button id="SpellCheckButton">Check Spelling!</button>
     <div id="NewTextDiv"></div>
     <div id="OutputDiv"></div>

</body>
</html>
  

As you can see, the page consists of a text area with some misspelled text; a button; and 2 empty divs.

The page looks like this when rendered in a browser:

scjs01-PageOnLoad
Fig. 1

When the user clicks the button, we want to call the Spell Check service, sending it the text in the text area.

We want to display the values in the web service response in the OutputDiv div; and we want to display some of the raw information in the response in the NewTextDiv div.

Below is the screen after clicking the [Check Spelling] button

scjs02-PageAfterClick

Fig. 2

We need a reference to the outputDiv, so we can easily write to it.

Listing 2:

var outputDiv = document.getElementById("OutputDiv");
  

Next, we bind code to the button's click event, as shown in Listing 3.

Listing 3:

var spellCheckButton = document.getElementById("SpellCheckButton"); 
spellCheckButton.onclick = function () { 
    // Replace this with your Spell Check API key from Aure 
    var subscriptionKey = "xxxxxxxxxxxxxxxxxxxxxxxx"; 

    outputDiv.innerHTML = "Thinking...";

    var textToCheck = document.getElementById("TextToCheck").textContent; 
    var webSvcUrl = "https://api.cognitive.microsoft.com/bing/v7.0/spellcheck/?text=" + textToCheck; 
    webSvcUrl = webSvcUrl + "&mode=proof&mkt=en-US";

    var httpReq = new XMLHttpRequest(); 
    httpReq.open("GET", webSvcUrl, true); 
    httpReq.setRequestHeader("Ocp-Apim-Subscription-Key", subscriptionKey) 
    httpReq.setRequestHeader("contentType", "application/json") 
    httpReq.onload = onSpellCheckSuccess; 
    httpReq.onerror = onSpellCheckError; 
    httpReq.send(null); 
};
  

This code gets the text from the text area and makes an asynchronous HTTP GET request to the Spell Check API, passing the API key in the header. When the API sends a response, this will call the onSpellCheckSuccess or onSpellCheckError function, depending on the success of the call.

Listing 4 shows the onSpellCheckSuccess function:

Listing 4:

function onSpellCheckSuccess(evt) { 
    var req = evt.srcElement; 
    var resp = req.response; 
    var data = JSON.parse(resp);

    var flaggedTokens = data.flaggedTokens; 
    if (data.flaggedTokens.length > 0) { 
        var newText = document.getElementById("TextToCheck").textContent; 
        ; 
        var outputHtml = ""; 
         flaggedTokens.forEach(flaggedToken => { 
            var token = flaggedToken.token; 
            var tokenType = flaggedToken.type; 
            var offset = flaggedToken.offset; 
            var suggestions = flaggedToken.suggestions; 
            outputHtml += "<div>" 
            outputHtml += "<h3>Token: " + token + "</h3>"; 
            outputHtml += "Type: " + tokenType + "<br/>"; 
            outputHtml += "Offset: " + offset + "<br/>"; 
             outputHtml += "<div>Suggestions</div>"; 
            outputHtml += "<ul>";

            if (suggestions.length > 0) { 
                 suggestions.forEach(suggestion => { 
                     outputHtml += "<li>" + suggestion.suggestion; 
                     outputHtml += " (" + (suggestion.score * 100).toFixed(2) + "%)" 
                }); 
                outputHtml += "</ul>"; 
                outputHtml += "</div>";

                newText = replaceTokenWithSuggestion(newText, token, offset, suggestions[0].suggestion) 
            } 
            else { 
                 outputHtml += "<ul><li>No suggestions for this token</ul>"; 
            } 
        });

        newText = "<h2>New Text:</h2>" + newText; 
        var newTextDiv = document.getElementById("NewTextDiv"); 
        newTextDiv.innerHTML = newText;

        outputHtml = "<h2>Details</h2>" + outputHtml; 
        outputDiv.innerHTML = outputHtml;

    } 
    else { 
        outputDiv.innerHTML = "No errors found."; 
    } 
};
  

As you can see, we parse out the JSON object from the response and retrieve each flaggedToken from that object. For each flaggedToken, we output information, such as the original text (or token), the tokenType, and suggested replacements, along with the score of each replacement.

If an error occurs when calling the API service, the onSpellCheckError function is called, as shown in Listing 5.

Listing 5:

function onSpellCheckError(evt) { 
    outputDiv.innerHTML = "An error has occurred!!!"; 
};
  

Finally, we replace each token with the first suggestion, using the code in Listing 6.

Listing 6*:

function replaceTokenWithSuggestion(originalString, oldToken, offset, newWord) { 
    var textBeforeToken = originalString.substring(0, offset);

    var textAfterToken = ""; 
    if (originalString.length > textBeforeToken.length + oldToken.length) { 
        textAfterToken = originalString.substring(offset + oldToken.length, originalString.length); 
    }

    var newString = textBeforeToken + newWord + textAfterToken;

    return newString; 
 }
  

Here is the full JavaScript:

Listing 7:

window.onload = function () {

    var outputDiv = document.getElementById("OutputDiv");
    // var subscriptionKey = getKey();

    var spellCheckButton = document.getElementById("SpellCheckButton");
    spellCheckButton.onclick = function () {
        var subscriptionKey = getKey();
        var textToCheck = document.getElementById("TextToCheck").textContent;

        var webSvcUrl = "https://api.cognitive.microsoft.com/bing/v7.0/spellcheck/?text=" + textToCheck;
        webSvcUrl = webSvcUrl + "&mode=proof&mkt=en-US";

        outputDiv.innerHTML = "Thinking...";

        var httpReq = new XMLHttpRequest();
        httpReq.open("GET", webSvcUrl, true);
        httpReq.setRequestHeader("Ocp-Apim-Subscription-Key", subscriptionKey)
        httpReq.setRequestHeader("contentType", "application/json")
        httpReq.onload = onSpellCheckSuccess;
        httpReq.onerror = onSpellCheckError;
        httpReq.send(null);
    };

    function onSpellCheckSuccess(evt) {
        var req = evt.srcElement;
        var resp = req.response;
        var data = JSON.parse(resp);

        var flaggedTokens = data.flaggedTokens;
        if (data.flaggedTokens.length > 0) {
            var newText = document.getElementById("TextToCheck").textContent;
            ;
            var outputHtml = "";
            flaggedTokens.forEach(flaggedToken => {
                var token = flaggedToken.token;
                var tokenType = flaggedToken.type;
                var offset = flaggedToken.offset;
                var suggestions = flaggedToken.suggestions;
                outputHtml += "<div>"
                outputHtml += "<h3>Token: " + token + "</h3>";
                outputHtml += "Type: " + tokenType + "<br/>";
                outputHtml += "Offset: " + offset + "<br/>";
                outputHtml += "<div>Suggestions</div>";
                outputHtml += "<ul>";

                if (suggestions.length > 0) {
                    suggestions.forEach(suggestion => {
                        outputHtml += "<li>" + suggestion.suggestion;
                        outputHtml += " (" + (suggestion.score * 100).toFixed(2) + "%)" 
                    });
                    outputHtml += "</ul>";
                    outputHtml += "</div>";

                    newText = replaceTokenWithSuggestion(newText, token, offset, suggestions[0].suggestion)
                }
                else {
                    outputHtml += "<ul><li>No suggestions for this token</ul>";
                }
            });

            newText = "<h2>New Text:</h2>" + newText;
            var newTextDiv = document.getElementById("NewTextDiv");
            newTextDiv.innerHTML = newText;

            outputHtml = "<h2>Details</h2>" + outputHtml;
            outputDiv.innerHTML = outputHtml;

        }
        else {
            outputDiv.innerHTML = "No errors found.";
        }
    };

    function onSpellCheckError(evt) {
        outputDiv.innerHTML = "An error has occurred!!!";
    };

    function replaceTokenWithSuggestion(originalString, oldToken, offset, newWord) {
        var textBeforeToken = originalString.substring(0, offset);

        var textAfterToken = "";
        if (originalString.length > textBeforeToken.length + oldToken.length) {
            textAfterToken = originalString.substring(offset + oldToken.length, originalString.length);
        }

        var newString = textBeforeToken + newWord + textAfterToken;

        return newString;
    }

};
  

Hopefully, this sample gives you an idea how to get started building your first app that uses the Bing Spell Check API.



* This code currently has a bug in it: It only works if each suggestion is the same length as the token it replaces. I plan to fix this bug, but I'm publishing now because:

  1. It is not a fatal bug and
  2. It is not relevant to the call to the API, which is the primary point I'm showing in this article.
Friday, August 16, 2019 9:00:00 AM (GMT Daylight Time, UTC+01:00)
# Thursday, August 15, 2019

GCast 61:

Text Recognition C# Demo

In this video, I walk you through a C# application that calls the Text Recognition service, passing in an image of text and retrieving that text.

Thursday, August 15, 2019 8:47:00 AM (GMT Daylight Time, UTC+01:00)