De nombreux projets utilise la cartographie pour présenter des données plus ou moins complexes dans des scénarios toujours plus avancées mais nous avons parfois l’occasion d’utiliser ces contrôles dans des cas bien plus drôles.

Bing Maps AJAX V7.0 treasure maps

Le concept et exemples de réalisation

L’idée principale est de fournir une expérience autour d’une carte interactive permettant de rechercher des éléments cachés qui ne s’afficheront uniquement lorsque l’utilisateur sera positionné au dessus de l’objet en question et à un niveau de zoom avancé.

Bing Maps et cartes au trésor

Plusieurs expériences similaires ont déjà été réalisées par Microsoft (MSN) dans le cadre d’une campagne autour de l’artiste Jay-2 et d’autres projets en étant parfois accompagné de partenaires français tels qu’Itelios pour le jeu de la Marine Nationale :

Bing Maps Jay-Z implementation chasse aux indicesItelios Bing Maps Marine nationale

 

Processus technique

En pratique, une telle utilisation est relativement simple à développer en utilisant le contrôle AJAX v7.0 de Bing Maps. Naturellement cette approche peut être adaptée à toute plateforme (Bing Maps, Google Maps, Nokia Maps…) ou tout contrôle (AJAX, Windows Phone, Windows 8…) puisque la logique est la même.

Il suffit de détecter et effectuer une action de vérification lors de changement de la vue effectué à travers le contrôle : position (à partir de bounds) et niveau de zoom.

image

Plusieurs approches sont possibles pour traiter cette vérification puisqu’en fonction de la sécurité que l’on souhaite sur les informations, il faudra éventuellement effectuer cette vérification sur un serveur distant appelé en asynchrone à travers un appel AJAX.

 

Solution simple : utilisation de code client uniquement

Dans cette première implémentation, nous ne souhaitons pas apporter de sécurité particulière sur les données mais nous nous concentrons sur l’implémentation technique et la mise en place de la logique évènementiel autour du contrôle AJAX v7.0.

  • Evènement de changement de vue et vérification
// -- Implements view change end
bm.globals.logic.viewChangeEndHandler = Microsoft.Maps.Events.addHandler(
    bm.globals.geo.map,
    'viewchangeend', 
    function () {
        if (bm.globals.geo.map.getZoom() > bm.constants.logic.zoomMini) {
            var bounds = bm.globals.geo.map.getBounds();
            var nw = bounds.getNorthwest();
            var se = bounds.getSoutheast();

            // Check if the bounds are covering the items
            if ((nw.latitude > bm.constants.logic.itemLocationLatitude)
                && (se.latitude < bm.constants.logic.itemLocationLatitude)
                && (nw.longitude < bm.constants.logic.itemLocationLongitude)
                && (se.longitude > bm.constants.logic.itemLocationLongitude)) {
            
                // Add the item on the map
                addItem(bm.constants.logic.itemLocationLatitude, 
                        bm.constants.logic.itemLocationLongitude);

                // Clear the time limit
                clearTimeout(bm.globals.logic.timer);
                bm.globals.logic.timer = null;

                // Remove the event if already found
                Microsoft.Maps.Events.removeHandler(bm.globals.logic.viewChangeEndHandler);
            }
        }
    }
);
 

 

Code complet :

Un exemple d’implémentation est alors disponible via ce lien : http://www.boonaert.net/element/bingmaps/samples/Treasure/index-simple.htm

Bing Maps rené la taupe et chasse aux indices

 

Solution avancée : utilisation de code client et service distant

Au sein de cette seconde implémentation, nous nous intéressons de manière plus précise à la sécurité des coordonnées au moment de la vérification qui s’effectue désormais sur le serveur.

Cette vérification peut être réalisée depuis des coordonnées statiques où dynamiques, la logique autour du stockage des données n’est pas abordé dans cet article mais il va de soit qu’il est possible d’utiliser tous moyens de stockage en fonction du besoin avec une préférence sur les bases spatiales (Type géographique sur SQL Server, PostgreSQL…) pour des raisons évidentes de performances en cas de fortes volumétries de données et/ou de requêtes.

La logique applicative en termes d’évènement n’est pas grandement modifié et la seule différence notable concerne la vérification qui effectue désormais un appel à un service de manière asynchrone.

  • Evènement de changement de vue et vérification

Code client :

// -- Implements view change end
bm.globals.logic.viewChangeEndHandler = Microsoft.Maps.Events.addHandler(
    bm.globals.geo.map,
    'viewchangeend', 
    function () {
        var mapZoom = bm.globals.geo.map.getZoom();

        if (bm.globals.geo.map.getZoom() > bm.constants.logic.zoomMini) {
            var bounds = bm.globals.geo.map.getBounds();
            var nw = bounds.getNorthwest();
            var se = bounds.getSoutheast();

            var data = {
                zoom: mapZoom,
                topLeftLat: nw.latitude,
                topLeftLng: nw.longitude,
                botRightLat: se.latitude,
                botRightLng: se.longitude
            };
        
            // Abort the previous call
            if (bm.globals.logic.ajaxCall) bm.globals.logic.ajaxCall.abort();
        
            // Call the WS
            bm.globals.logic.ajaxCall = $.ajax({
                url: 'Services/GeoService.svc/CheckPosition',
                data: JSON.stringify(data),
                type: 'POST',
                dataType: 'json',
                contentType: 'application/json; charset=utf-8'
            }).done(function (result) {
                if (result.d) {
                    // Add the item on the map
                    addItem(result.d.Latitude, result.d.Longitude);

                    // Clear the time limit
                    clearTimeout(bm.globals.logic.timer);
                    bm.globals.logic.timer = null;

                    // Remove the event if already found
                    Microsoft.Maps.Events.removeHandler(bm.globals.logic.viewChangeEndHandler);
                }
            });
        }
    }
);

 

Code serveur :

[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class GeoService
{
    [OperationContract]
    public GeoItem CheckPosition(int zoom,
                                 double topLeftLat, double topLeftLng,
                                 double botRightLat, double botRightLng)
    {
        GeoItem item = null;

        if (zoom >= 12)
        {
            var itemLat = double.Parse(ConfigurationManager.AppSettings["itemLat"],
                                       CultureInfo.InvariantCulture.NumberFormat);
            var itemLng = double.Parse(ConfigurationManager.AppSettings["itemLng"],
                                       CultureInfo.InvariantCulture.NumberFormat);

            if ((topLeftLat > itemLat)
                && (botRightLat < itemLat)
                && (topLeftLng < itemLng)
                && (botRightLng > itemLng))
            {
                item = new GeoItem(itemLat, itemLng);
            }
        }

        return item;
    }
}

 

Il est important de considérer également un ordonnanceur d’appel client permettant de réduire le nombre d’appel envoyés au serveur.

 

Bing Maps code source d'exempleLe code complet peut être récupéré ici : http://www.boonaert.net/element/bingmaps/samples/
Treasure/BingMaps.TreasureMap.zip

 

Considérations sur la sécuritéBing MAps securité et web services

Un point supplémentaire à considérer dans le cadre d’un développement d’une telle expérience pour une opération de communication ou un jeu concours réside dans la sécurité de la plateforme.

Il est indéniable que la sécurité optimale n’existe pas et qu’il sera toujours possible d’avoir des malins cherchant à exploiter les services de vérification directement de manière automatique afin de trouver les lieux concernés.

Voici quelques pistes de considérations techniques sur la sécurité :

  • Journaliser (logs) les IPs d’appels et les requêtes associées afin de limiter les appels à un nombre raisonnable pour chaque jour (1000 appels) et étudier les métriques pour ajuster ces limites
  • Génération de jeton temporaire pour les appels
  • Utiliser une session avec connexion login/password : peut limiter la portée de l’opération

Il est plus qu’important de mesurer, sur des opérations grand publics, l’impact d’une action conjointe sur l’infrastructure et sur le déroulement même de l’opération.

Il est en effet assez délicat d’éviter ce genre de détournement pouvant même être volontairement orchestré pour détourner l’opération (cas du concours Monopoly ou plus récemment le concours Virgin Radio) et possiblement pire, pour nuire à la stabilité de la plateforme mise en place.

 

Conclusions

A travers cet article, nous avons étudié les bases de réalisation d’une application permettant de créer une expérience de carte au trésor, de “Où est Charlie ?” ou encore de piste aux indices.

Il parait évident que cette expérience doit être accompagné d’une réelle réflexion de parcours et d’ergonomie sur lesquels viennent se greffer de l’information utile sur la carte et de contenu éditorial pour susciter l’intérêt et ainsi transformer l’expérience en une réussite.

Enfin, pour conclure, dans ces cas d’usage où la volumétrie d’utilisateur peut totalement variée au fil du déroulement de l’opération, Windows Azure et ses capacités d’hébergement peuvent être une option plus qu’intéressante garantissant la haute disponibilité et les couts réduits. C’est une solution d’autant plus intéressante qu’elle utilise les technologies de Microsoft telles que SQL Sevrer pour mettre à disposition ces fonctionnalités.

Tresor

 

N’hésitez pas à me contacter si vous avez un besoin similaire ou si vous avez des questions techniques concernant ce genre d’implémentation.