Monthly Archives: August 2019

Creating a Car Game in React – Part 6 – Adding High Scores

This is the sixth post of a series that starts here.

As with previous posts, if you wish to download the code, it’s here; and, as with previous posts, I won’t cover all the code changes here, so if you’re interested, then you should download the code.

In this post, we’re going to create a High Score table. We’ll create an Azure function as the server, and we’ll store the scores themselves in Azure Tables.

Let’s start with the table.

Create a new storage account in Azure, then add an Azure Table to it:

You’ll see a sign trying to persuade you to use Cosmos DB here. At the time of writing, using Cosmos was considerably more expensive than Table Storage. Obviously, you get increased throughput, distributed storage, etc with Cosmos. For this, we don’t need any of that.

Create a new table:

An Azure table is, in fact, a No SQL offering, as you have a key, and then an attribute – the attribute can be a JSON file, or whatever you choose. In our case, we’ll set the key as the user name, and the score as the attribute.

Once you’re created your table storage, you may wish to use the Storage Explorer to create the tables, although that isn’t necessary.

Finally, you’ll need to add a CORS rule:

Obviously, this should actually point to the domain that you’re using, rather than a blanket ‘allow’, but it’ll do for testing.

Adding a username

Before we can store a high score, the user needs a username. Let’s add one first.

In game status, we’ll add a text box:

<div style={containerStyle}>
	<input type='text' value={props.Username}
	onChange={props.onChangeUsername} />
</div>

The state is raised to the main Game.jsx:

<GameStatus Lives={this.state.playerLives} 
	Message={this.state.message} 
	Score={this.state.score} 
	RemainingTime={this.state.remainingTime}
	Level={this.state.level}
	Username={this.state.username} 
	onChangeUsername={this.onChangeUsername.bind(this)} 
/>

And onChangeUsername is here:

onChangeUsername(e) {
	this.updateUserName(e.target.value);
}

updateUserName(newUserName) {
	this.setState({
		username: newUserName
	});
}

Update High Score

We’ll create an Azure Function to update the table. In Visual Studio, create a new Windows Azure Function App (you will need to install the Azure Workload if you haven’t already):

You’ll be asked what the trigger should be for the function: we’ll go with HttpTrigger. This allows us to call our function whenever we please (rather than the function, being say scheduled.) Next, we’ll need to install a NuGet package into our project to let us use the Azure Storage Client:

Install-Package WindowsAzure.Storage

We need some access details from Azure:

Creating the Functions

We’re actually going to need two functions: update and retrieve (we won’t be using the retrieve in this post, but we’ll create it anyway). Let’s start with a helper method:

    public static class StorageAccountHelper
    {
        public static CloudStorageAccount Connect()
        {
            string accountName = Environment.GetEnvironmentVariable("StorageAccountName");
            string accountKey = Environment.GetEnvironmentVariable("StorageAccountKey");

            var storageAccount = new CloudStorageAccount(
                new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials(
                    accountName, accountKey), true);
            return storageAccount;
        }
    }

For testing purposes, add the account name and key into the local.settings.json:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet",
    "StorageAccountName": "pcmtest2",
    "StorageAccountKey": "C05h2SJNQOXE9xYRObGP5sMi2owfDy7EkaouClfeOSKRdijyTQPh1PIJgHS//kOJPK+Nl9v/9BlH4rleJ4UJ7A=="
  }
}

The values here are taken from above – where we copied the access keys from Azure (whilst these keys are genuine keys, they will be changed by the time the post is published – so don’t get any ideas!

First, let’s create a function to add a new high Score:

        [FunctionName("AddHighScores")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            var newScore = new HighScore(req.Query["name"], int.Parse(req.Query["score"]));            

            var storageAccount = StorageAccountHelper.Connect();

            CloudTableClient client = storageAccount.CreateCloudTableClient();
            var table = client.GetTableReference("HighScore");

            await table.ExecuteAsync(TableOperation.InsertOrReplace(newScore));

            return new OkResult();
        }

If you’ve seen the default example of this function, it’s actually not that different: it’s a POST method, we take the name and score parameters from the query string, build up a record and add the score. The function isn’t perfect: any conflicting names will result in overwritten score, but this is a copy of a spectrum game – so maybe that’s authentic!

The second function is to read them:

        [FunctionName("GetHighScores")]
        public static async Task<IList<HighScore>> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            var storageAccount = StorageAccountHelper.Connect();

            CloudTableClient client = storageAccount.CreateCloudTableClient();
            var table = client.GetTableReference("HighScore");
            var tq = new TableQuery<HighScore>();
            var continuationToken = new TableContinuationToken();
            var result = await table.ExecuteQuerySegmentedAsync(tq, continuationToken);
            
            return result.Results;
        }

All we’re really doing here is reading whatever’s in the table. This might not scale hugely well, but again, for testing, it’s fine. The one thing to note here is ExecuteQuerySegmentedAsync: there seems to be very little documentation around on it; and what there is seems to refer to ExecuteQueryAsync (which, as far as I can tell, doesn’t, or at least, no longer, exists).

Let’s run the Azure function locally and see what happens:

As you can see, Azure helpfully gives us some endpoints that we can use for testing. If you don’t have a copy already, then download Postman. Here you can create a request that calls the function.

I won’t go into the exact details of how Postman works, but the requests might look something like this:

http://localhost:7071/api/AddHighScores?name=test2&score=19
http://localhost:7071/api/GetHighScores?10

To prove to yourself that they are actually working, have a look in the table.

There is now an online Storage Explorer in the Azure Portal. Details of the desktop version can be found in this post.

Update High Score from the Application

Starting with adding the high score, let’s call the method to add the high score when the player dies (as that’s the only time we know what the final score is):

playerDies() { 
    this.setState({
        playerLives: this.state.playerLives - 1,
        gameLoopActive: false
    });

    if (this.state.playerLives <= 0) {
        this.updateHighScore();
        this.initiateNewGame();
    } else {
        this.startLevel(this.state.level);
    }

    this.repositionPlayer();
    this.setState({ 
        playerCrashed: false,
        gameLoopActive: true
    });
}

The updateHighScore function looks like this:

updateHighScore() {
	fetch('http://localhost:7071/api/AddHighScores?name=' + this.state.username + '&score=' + this.state.score, {
		method: 'POST'
	}); 
}

Note (obviously) that here I’m updating using my locally running instance of the Azure Function.

And that’s it – we now have a score updating when the player dies. Next we need to display the high scores – that’ll be the next post.

References

https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

https://facebook.github.io/react-native/docs/network

Using Blazor Components

Imagine that you’re writing a Blazor application – maybe it’s similar to this one. Now, imagine that you have a large chunk of HTML in your main view. You might think: I wish I was using React, then I could separate this into its own component.

You can also do this in Blazor. Here’s how.

Components in Blazor

Let’s start with moving your code. The first step is to cut your HTML and paste it into a new Razor Component:

The format of your new component, from scratch, will be:

&lt;h3&gt;Component Name&lt;/h3&gt;

@code {

}

Your existing code should go beneath, or instead of:

&lt;h3&gt;Component Name&lt;h3&gt;

Parameters

The @code section allows you to put all kinds of crazy C# code in a code behind type model – so you probably don’t want to use that, except for passing parameters; for example:

@code {
    [Parameter]
    private string MyParameter { get; set; }
}

This allows you to pass a string into your component; for example (in your main view):

&lt;MyComponent MyParameter=&quot;test&quot; /&gt;

Complex Parameters

So far so good. But what if you need a complex type? You could, for example, pass a View Model into your component:

[Parameter]
private MyViewModel MyViewModel { get; set; }

You can pass this into the component as though it were a primitive type:

&lt;MyComponent MyViewModel=&quot;@MyViewModel&quot; /&gt;

This means that you can lift and shift the code with no changes.

Using External Namespaces

As with standard C#, you can access anything within the current namespace. Should you need any classes that are not in your current namespace, you can declare them at the top of the file, like this:

@using MVVMShirt

&lt;h3&gt;My Component&lt;/h3&gt;

Summary

Blazor is still in its infancy, but hopefully, adding actual code to these @code sections will become as frowned upon as code-behind.

React Tips: 4 – Propagating State

One thing that’s worth remembering about React is that when you’re updating state, only the Render method gets re-executed.

It’s easy (as I did) to fall into the trap of doing something like this:

    const myStyle = {
        background: this.props.backgroundFlag == 1 ? "blue" : "yellow",
        display: 'inline-block',
        height: '100%',
    }

    public render() {
        return <>
            <div className="myDiv" style={myStyle}>
        </>
    }

Imagine that this.props.backgroundFlag is actually the state of the containing component; when you change it, you would expect your component to reflect your change. However, in the case above, what will actually happen is nothing – because only the render method is re-evaluated when the virtual DOM changes.

To correct this, you need whatever needs to be re-evaluated inside the render method; for example:

    public render() {
	    const myStyle = {
	        background: this.props.backgroundFlag == 1 ? "blue" : "yellow",
	        display: 'inline-block',
	        height: '100%',
	    }

        return <>
            <div className="myDiv" style={myStyle}>
        </>
    }

UWP using Unity and EF Core and Sqlite

If you intent to use IoC with a UWP application, there are a lot of options. Most of them come with MVVM packages, like MVVM Cross. These are excellent packages – I’ve used MVVM Cross and MVVM Light myself and can highly recommend them.

However, if you didn’t want all that baggage, how would you implement a very simple IoC system in UWP?

In this example, I’m using Unity, however, I believe this will work for any IoC container. I’m also using the IoC container to resolve a View Model – but you don’t need to use View Models (although IMHO, it makes your life so much easier.)

Secondly, I’ll be showing how to use Ef Core with your UWP app. This sounds very trivial, but there’s a bit of fiddling about to get it to work.

Entity Framework Core Set-up

In my project, I’ve separated the data access layer, but you don’t need to do that. Start by creating a data context:

public class MyDbContext : DbContext
{
    public DbSet<Data> MyData { get; set; }
 
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlite("Data Source=mydata.db");
    }
}

You’ll need the following packages:

Install-Package Microsoft.EntityFrameworkCore
Install-Package Microsoft.EntityFrameworkCore.Design
Install-Package Microsoft.EntityFrameworkCore.Tools
Install-Package Microsoft.EntityFrameworkCore.Sqlite

You’ll also need to create a console application – why? Because you can’t use any of the EF tools with UWP! If you set your UWP app as the start-up and create your migration, you’ll get this error:

Startup project ‘SendMessage.UWP’ is a Universal Windows Platform app. This version of the Entity Framework Core Package Manager Console Tools doesn’t support this type of project.

Set the console app as startup and add the migration:

Add-Migration "InitialDbCreate"

Don’t worry about updating the DB, we’ll get the app to do that (it just can’t use the tools, but it can perform a migration.)

UWP

From a new, blank, UWP app; in app.xaml.cs:

sealed partial class App : Application
{
    public static IUnityContainer Container { get; set; } = new UnityContainer();
 
    /// <summary>
    /// Initializes the singleton application object.  This is the first line of authored code
    /// executed, and as such is the logical equivalent of main() or WinMain().
    /// </summary>
    public App()
    {
        this.InitializeComponent();
        this.Suspending += OnSuspending;
 
        using (var db = new MyDbContext())
        {
            db.Database.Migrate();
        }
        
        Container.RegisterType<MainViewModel>();
    }

We’re creating a static UnityContainer in App.Xaml.cs. Register the type (in this case a MainViewModel, but it could as easily be an interface).

The next step is resolving the interface. Unfortunately, because of the way that the UWP navigate works, Unity won’t perform constructor injection for us. A little trick around this is to create a parameterless constructor and have that call the injected constructor. It’s not quite constructor injection, but semantically it’s the same thing. Here’s the code from my MainPage.xaml.cs:

public sealed partial class MainPage : Page
{
    public MainPage() : this(App.Container.Resolve<MainViewModel>()) { }
 
    public MainPage(MainViewModel mainViewModel)
    {
        this.InitializeComponent();
 
        this.DataContext = mainViewModel;
    }
}

That’s pretty much it; you can run this, and it’ll migrate the data, and resolve the dependency.

References

https://docs.microsoft.com/en-us/ef/core/get-started/uwp/getting-started

React Tips: 3 – Cloning a React Repository

After you clone a React repository, running npm start may give this error:

‘react-scripts’ is not recognized as an internal or external command

The reason, as explained here, is that you need to run:

npm install

This should be run inside the directory that you clone. For example:

git clone https://github.com/pcmichaels/react-demos.git
cd react-demos
npm install
npm start