Tilt-sensing foosball

Foosball matches could have rules against tilting the table. To facilitate this we need an accelerometer attached to the table . We didn’t have a standalone accelerometer, but worked around this with an HTC One phone and some tape.

When the software on the phone receives signals form the accelerometer above a certain threshold, it triggers an alarm by signalling to the live score web system, as demonstrated in the video below.

With this submission we’re aiming for the Embedding Dumbnut badge

1

Where the hell is my document

We have a lot of customers and a lot of documents all over our SharePoint site.
Our employees are complaining over how difficult it is to find the right document,

We therefore created a search driven datagrid which is also filterable.
The datagrid is based on the Datatables.net project.
We use the Search rest apis to crawl our site for documents.
The grid can be placed anywhere in the structure and will populate the grid with documents below where it is placed.

docgrid1

docgrid2

Query against the rest API:

 var query = _spPageContextInfo.webAbsoluteUrl + "/_api/search/query?querytext='path:\""+_spPageContextInfo.webAbsoluteUrl+"\" AND ContentClass=\"STS_ListItem_DocumentLibrary\" IsDocument=True'&selectproperties='Url,ModifiedBy,Title,ModifiedOWSDATE,FileExtension,SitePath,SiteTitle,SPSiteUrl,FileName,EditorOWSUSER,ParentLink,write'&rowlimit=500&sortlist='write:descending'&trimduplicates=false";

Another example where the result is filtered by the logged in user:

$(document).ready(function () {

var userid = _spPageContextInfo.userId;

function GetCurrentUser() {
    var requestUri = _spPageContextInfo.webAbsoluteUrl + "/_api/web/getuserbyid(" + userid + ")";

    var requestHeaders = { "accept" : "application/json;odata=verbose" };

    $.ajax({
      url : requestUri,
      contentType : "application/json;odata=verbose",
      headers : requestHeaders,
      success : onSuccess,
      error : onError
    });
    }

    function onSuccess(data, request){
      var loginName = data.d.LoginName.split('|')[2];
      var query = _spPageContextInfo.webAbsoluteUrl + "/_api/search/query?querytext='path:\""+escapeProperly(_spPageContextInfo.webAbsoluteUrl)+"\" EditorOWSUSER:\""+loginName+"\" AND ContentClass=\"STS_ListItem_DocumentLibrary\" IsDocument=True'&selectproperties='Url,ModifiedBy,Title,ModifiedOWSDATE,FileExtension,SitePath,SiteTitle,SPSiteUrl,FileName,EditorOWSUSER,ParentLink,write'&rowlimit=500&sortlist='write:descending'&trimduplicates=false"
      loadGrid(query,"#searchGridMine"); 
    }

    function onError(error) {
      log(error);
    }

    GetCurrentUser();

});
</script>

:Badge-Crawler

Media services – Stairway to heaven

We are hosting a lot of media content about matches being played around the world on our app.

All the videos are hosted in Azure Media Services, including our final submission for ASPC 2014.

 A console app uploads our movies to our Media Services account.media services upload

The Media Services DashBoard:

(All our clients videos are hidden in this screendump)media services

 

We hereby claim the stairway to heaven badge. All the rest of our infrastructure is also hosted in Azure or Offcie 365. Ref post: http://blog-aspc.azurewebsites.net/todays-work/

 

clip_image0018.png

Designing the foosball application

Badge-GlossyPixels

We would like people to be reminded of football when they use our application. What better design inspiration than the flag of Brazil? We use their colours in all our design. As we also have jackets with more or less the same colours, we’ve borrowed the pink from them as well. Black and white are also included in the palette to provide some neutrality when needed.

Before we set off, we created a simple design manual based on the colours mentioned. This has been used by the whole team to create familiarity for the user throughout the application.

design-color-guidelines

Screenshots from the actual application

00-register-player

10-new-match

20-select-players

25-last-results

30-scoring

35-currently-playing

40-match-over

 

 

The Android app uses the same colours as well.

2014-03-28 18.08.08

Mining for foosball-weather

Aiming for Dataminer

Aiming for Dataminer

This small client web part provides a quick answer to the question “is the weather ideal for playing foosball?”. The app retrieves the latest forecast from yr.no and presents it to a potential foosball player with a recommendation.

Screenshot of the foosball weather app in action

Screenshot of the foosball weather app in action

 <div>
        <h1>Do we have FOOSBALL weather?</h1>
        <span id="weatherAnswer"></span>
        <br />
        <span id="spanWeatherdata"></span>
    </div>

    <script type="text/javascript" src="../_layouts/15/SP.Runtime.js"></script>
    <script type="text/javascript" src="../_layouts/15/SP.js"></script>
    <script type="text/javascript">
        (function () {
            "use strict";

            var context = SP.ClientContext.get_current();
            var request = new SP.WebRequestInfo();
            request.set_url("http://www.yr.no/sted/Norge/Oslo/Oslo/Oslo/forecast.xml");
            request.set_method("GET");

            request.set_headers({ "Accept": "application/json;odata=verbose" });
            var response = SP.WebProxy.invoke(context, request);

            context.executeQueryAsync(successHandler, errorHandler);

            function successHandler() {

                if (response.get_statusCode() == 200) {
                    var weatherData;
                    var output;

                    var weatherDataXML = response.get_body();

                    var xml = $.parseXML(weatherDataXML);

                    document.getElementById("spanWeatherdata").innerHTML += $(xml).find("forecast").find("body").contents()[0].textContent;

                    var symbol = $(xml).find("forecast").find("tabular").find("symbol")[0].getAttribute("var");
                    document.getElementById("spanWeatherdata").innerHTML += "<br/><img src='../Images/Yr/" + symbol + ".png'/><br/>";
                    document.getElementById("spanWeatherdata").innerHTML += "<br/><br/><p>Brought to you by <img src='../Images/Yr/yr-logo.png'><p/>";

                    //No conditions here - any weather is foosball weather
                    document.getElementById("weatherAnswer").innerHTML += "<h1>YES! GO PLAY!</h1>";
                }
            }
            function errorHandler() {
                document.getElementById("spanWeatherdata").innerHTML = response.get_body();
            }

        })();
    </script>

We’ve got the power

From time to time we need to spin up an onprem enviroment.

We of course do that in Azure.
We have created some powershell scripts that helps us do this so we can focus on playing foosball instead of configuring the servers. We want the servers to be part of a domain and have the proper ip adresses etc.

First we need some XML that defines our internal network:

<?xml version="1.0" encoding="utf-8"?>
<NetworkConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchem
a" xmlns="http://schemas.microsoft.com/ServiceHosting/2011/07/NetworkConfiguration">
  <VirtualNetworkConfiguration>
    <VirtualNetworkSites>
      <VirtualNetworkSite name="ADVNET" AffinityGroup="adag">
        <AddressSpace>
          <AddressPrefix>192.168.0.0/16</AddressPrefix>
        </AddressSpace>
        <Subnets>
          <Subnet name="ADSubnet">
            <AddressPrefix>192.168.1.0/24</AddressPrefix>
          </Subnet>
          <Subnet name="AppSubnet">
            <AddressPrefix>192.168.2.0/24</AddressPrefix>
          </Subnet>
        </Subnets>
      </VirtualNetworkSite>
    </VirtualNetworkSites>
  </VirtualNetworkConfiguration>
</NetworkConfiguration>

Then we create the Vnet with the above xml as input:

$subscriptionName = "My Azure Subscription"
$storageAccount = "My storage account"
Select-AzureSubscription $subscriptionName
Set-AzureSubscription $subscriptionName -CurrentStorageAccount $storageAccount

# Affinity Group parameters
$AGLocation = "West Europe"
$AGDesc = "AG Description"
$AGName = "adag"
$AGLabel = "adag"

# Create a new affinity Group
New-AzureAffinityGroup -Location $AGLocation -Description $AGDesc `
                                        -Name $AGName -Label $AGLabel 

# Clear current settings
Remove-AzureVNetConfig -ErrorAction SilentlyContinue

# Apply new network 
$configPath = (Split-Path -Path $MyInvocation.MyCommand.Definition -Parent) `
                    + "\ad-VNET.xml"

Set-AzureVNetConfig -ConfigurationPath $configPath

# Check results
Get-AzureVNetConfig | Select -ExpandProperty XMLConfiguration

And then we finally create the virtual machine and connect them to the Azure Ad and give them IP numbers:

Import-AzurePublishSettingsFile "c:\yoursettings.publishsettings"

Set-AzureSubscription -SubscriptionName ‘Pay-As-You-Go’ -CurrentStorageAccount ‘storageaccountname’
$dns1 = New-AzureDns -Name ‘ad-dc’ -IPAddress ‘192.168.1.4’
$dns2 = New-AzureDns -Name ‘ad-dc’ -IPAddress ‘192.168.1.5’
$imgname = ‘c6e0f177abd8496e934234bd27f46c5d__SharePoint-2013-Trial-1-7-2014’
$cloudsvc = ‘PointTakenAllStars’
$vmname1 = ‘PointTakenIntra’
$subnet = ‘ADSubnet’
$vnet = ‘ADVNET’
$pwd = ‘pass@word1’
# Configuring VM to Automatically Join Domain
$advm1 = New-AzureVMConfig -Name $vmname1 -InstanceSize X-Large -ImageName $imgname |
Add-AzureProvisioningConfig -WindowsDomain -Password $pwd `
-Domain ‘pointtaken.no’ -DomainPassword $pwd `
-DomainUserName ‘administrator’ -JoinDomain ‘pointtaken.no’ |
Set-AzureSubnet -SubnetNames ‘AppSubnet’
$advm2 = New-AzureVMConfig -Name $vmname1 -InstanceSize X-Large -ImageName $imgname |
Add-AzureProvisioningConfig -WindowsDomain -Password $pwd `
-Domain ‘pointtaken.no’ -DomainPassword $pwd `
-DomainUserName ‘administrator’ -JoinDomain ‘pointtaken.no’ |
Set-AzureSubnet -SubnetNames ‘AppSubnet’

# New Cloud Service with VNET and DNS settings
New-AzureVM -ServiceName $cloudsvc -AffinityGroup ‘adag’ `
-VMs $advm1 -DnsSettings $dns1 -VNetName $vnet
New-AzureVM -ServiceName $cloudsvc -AffinityGroup ‘adag’ `
-VMs $advm1 -DnsSettings $dns1 -VNetName $vnet

Badge-Powershell

Yammer integration

We post messages to our Yammer feed when a game has started so the employees can have a well deserved break.

They can of course choose to watch the live coverage in their own space, or they can move their bodies over to the real action.

yammerWe have used Nintex to accomplish this.

 

yam-yam-gimme-some

 

 

 

Hipstering our way to an Android app

So no Foosball tournament system is complete without mobile apps supporting it. I have some experience developing Android apps the normal way, but I decided to take a more console-based hipster approach this time:

I launched Console2 and started up by initializing a HG Mercurial source control repository. (git’s become too mainstream) I followed up by installing the Yeoman web app scaffolding tool through Node.js package manager, so that I could get a template of a PhoneGap project up and running.

phonegap

Commands executed:

npm install -g yo
npm install -g phonegap
npm install -g generator-phonegap
yo phonegap

What I like best about Yeoman is the cool ASCII-art it flashes when launching. Way to few apps have that today:

foosball-install

So now I have basically generated an cross-platform app which incidentally also compiles to a native Android app by the power of Phone Gap. I believe that may qualify for a “Thieving bastard” badge. It didn’t do much yet though – but I quickly implemented a view which renders the latest match results.

2014-03-28 18.08.08

I felt the app lacked a bit of “schwung” though, so the final touch was to find some audio to place the user in the right mood. I was looking for something that screamed “Football” “Brazil”, “Beach” and “Ladies in skimpy bikinis”, and landed on the tune you hear in the video at the bottom of the post. It was a bit of challenge to find the tune though, but good’ol pirate bay came to the rescue.

 pirate

I’m afraid this may qualify for thieving bastards as well 🙁

I completed the final details in IntelliJ IDEA, built and deployed it to my HTC One. Demo:

Some may say the music functionality is a useless one, qualifying for “doh”. The complete list of badges we’re aiming for in this post is:

null3
1
4

Don’t try this at home!!

doh doh

Our leaderboard can also show live data in SharePoint 2010.

2010

And to do something totally pointless (DOH!!), this site was created based on a custom sitetemplate. I guess everybody is missing this path:

C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\SiteTemplates where the good old onet.xml file is located.

onet