Click here to Skip to main content
Click here to Skip to main content

FourSquare Analytics

, 30 Jun 2013
Rate this:
Please Sign up or sign in to vote.
FourSquare Analytics, a web based experimental project for analyzing the foursquare data based on the search criteria.

Introduction    

FourSquare Analytics is an experimental web based project developed in ASP.NET MVC4 and several other technologies which we will be discussing in this article. Please note, as of now the website shows minimal analytics, i.e., only Foursquare venue information. I have a plan to extend it further to the next level by integrating various Foursquare features and implementing an extensive analytics of Foursquare information.

The main goal of building this site is to share with you a few things on the latest technologies. How we can make use of and do some analytic's on Foursquare data.

Analytics is always interesting, I'm sure people would love analyzing information by various means. In this article we will see how to explore Foursquare data to show venue information, public photos, use Google map to show route information, make use of Chart.JS to show Bar, Line, and Radar charts. 

You can have a feel of the website by browsing the Azure hosted website - http://foursquareanalytics.azurewebsites.net.

Note - This project is developed in the VS 2013 Preview Edition. Please make sure you have installed this in order to run this website. However you could also copy the files and build it in VS 2012 or so.

The website is developed using the below mentioned technology

  1. ASP.NET MVC4
  2. Bootstrap Framework for theaming and little responsive design.
  3. Google Map scripts and related things to show maps.
  4. Chart.JS for rendering bar, line and radar charts.
  5. Makes use of FourSquare and Google Geo coding libraries.

Background

Basic understanding or knowledge of ASP.NET MVC.

Using the code 

We will see the view model for Foursquare Analytics. Below is the code snippet for that. 

The view model itself is composed of other entities for capturing the user data, to show web grid and chart.

public class FourSquareVenueVenueEntity
{
    [Required]
    [Display(Name = "Address")]
    public string LocationName { get; set; }
    [Required]
    [Display(Name = "Search Text")]
    public string Query { get; set; }
}

public class FourSquareVenueViewModel
{
    public FourSquareVenueViewModel()
    {
        this.FourSquareVenueEntity = new FourSquareVenueVenueEntity();
        this.FourSquareVenueList = new List<netsquare.foursquarevenue>();
        this.FourSquareVenueForChart = null;
    }
    public FourSquareVenueVenueEntity FourSquareVenueEntity { get; set; }
    public List<netsquare.foursquarevenue> FourSquareVenueList { get; set; }
    public FourSquareVenueForChart FourSquareVenueForChart { get; set; }
}

public class FourSquareVenueForChart
{
    public string Labels { get; set; }
    public string CheckIn { get; set; }       
}

public class FourSquareVenuePhotos
{
    public string PhotoUrl { get; set; }
}

Below is the controller logic:

[HttpGet]
public ActionResult Index()
{
  return View(new FourSquareVenueViewModel());
}

[HttpPost]
public ActionResult Index(FourSquareVenueViewModel viewModel)
{
   viewModel.FourSquareVenueList.Clear();
   SpotInfo sinfo = new SpotInfo();
   sinfo.Address = viewModel.FourSquareVenueEntity.LocationName.Trim();
   Geocoder geo = new Geocoder();
   GeoResult result = geo.GetGeoResult(sinfo);
   if(result.Status == GeoResultStatus.OK){
       string authToken = ConfigurationManager.AppSettings["authToken"].ToString();
       string lat = result.Results[0].Geometry.Location.Lat.ToString();
       string lang = result.Results[0].Geometry.Location.Lng.ToString();
       string latlang = lat + "," + lang;
       var recommentedVenues = NetSquare.VenueExplore(latlang, "", "", "", 
           "10000", "", viewModel.FourSquareVenueEntity.Query, 
           "", "", authToken);
       foreach (var place in recommentedVenues.places)
       {
           var recommendedValues = 
              ((List<netsquare.foursquarerecommendedvenues.recommends>)place.Value);
           foreach (var recommendedValue in recommendedValues)
           {
               viewModel.FourSquareVenueList.Add(new NetSquare.FourSquareVenue
               {
                   url = recommendedValue.venue.url,
                   name = recommendedValue.venue.name,
                   id = recommendedValue.venue.id,
                   location = new NetSquare.FourSquareLocation{
                     Lat = recommendedValue.venue.location.Lat,
                     Long = recommendedValue.venue.location.Long 
                   },
                   stats = new NetSquare.FourSquareStats
                   {
                      checkinsCount = recommendedValue.venue.stats.checkinsCount,
                      usersCount = recommendedValue.venue.stats.usersCount,
                   }
               });
             }
           }
        }

    if (viewModel.FourSquareVenueList.Count > 0)
    {
        var fourSquareHelper = new FourSquareVenueHelper();
        viewModel.FourSquareVenueForChart = 
          fourSquareHelper.GetViewModel(viewModel.FourSquareVenueList);
    }
    return View(viewModel);
}

The POST implementation makes use of the Geocoder class for getting the latitude and longitude values required for exploring the Foursquare venues. This project makes use of the Foursquare library named NetSquare which is an open-source project in CodePlex http://netsquare.codeplex.com/ for exploring the venue and performing other operations.

We are making a class to NetSquare VenueExplore, passing in the required parameter such as latitude, longitude, search text, and oauth authentication token. This method returns us the recommended venues for our search criteria. We will then loop though and build our view model entities for rendering the webgrid and chart.

Below is the code snippet of the Foursquare helper class which returns the view model required for rendering the chart. All we need is the chart label and data.

public class FourSquareVenueHelper
{
    FourSquareVenueViewModel fourSquareViewModel;
    public FourSquareVenueHelper()
    {
        fourSquareViewModel = new FourSquareVenueViewModel();           
    }

    private static string PutIntoQuotes(string value)
    {
        return "\"" + value + "\"";
    }

    public FourSquareVenueForChart GetViewModel(
           List<netsquare.foursquarevenue> FourSquareVenueList)
    {
        var chart = new FourSquareVenueForChart();
        // Get Labels
        string lables = "[";
        string checkInData = "[";

        foreach (NetSquare.FourSquareVenue venue in FourSquareVenueList)
        {
            lables = lables + PutIntoQuotes(venue.name) + ",";
            checkInData = checkInData + venue.stats.checkinsCount.ToString() + ",";
        }
        lables = lables.Substring(0, lables.Length - 1) + "]";
        checkInData = checkInData.Substring(0, checkInData.Length - 1) + "]";

        chart.Labels = lables.Replace(@"\", " ");
        chart.CheckIn = checkInData;

        return chart;
    }
}

Here's the controller code snippet for fetching the Foursquare venue photos based on the venue ID. The code is pretty straightforward. We are making a call to the NetSquare.VenuePhotos method passing in the required parameters to show the public images.

[HttpGet]
public ActionResult FourSquareVenuePhotos(string venueId)
{
     string authToken = ConfigurationManager.AppSettings["authToken"].ToString();
     var venuePhotos = NetSquare.VenuePhotos(venueId, "venue", "", "", authToken);
     List <foursquarevenuephotos>venuePhotoList = new List<foursquarevenuephotos>();
     foreach (var photo in venuePhotos)
     {
         venuePhotoList.Add(new FourSquareVenuePhotos
         {
              PhotoUrl = photo.url
         });
     }
     return PartialView("FourSquareVenuePhotos", venuePhotoList);
}

We will now see how we are rendering Google Maps in our website. First we need to reference the following scripts and CSS:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<link href="http://www.google.com/uds/css/gsearch.css" rel="stylesheet" type="text/css" />

Here's the Java script snippet for rendering the Google map. When the user clicks on the webgrid row, we are making a call to displayMap method passing in the latitude and longitude values in-order to render the map.  

// Our global state
var gMap;

function displayMap(latitude, longitude) {
    gMap = new google.maps.Map(document.getElementById("map"), {
        center: new google.maps.LatLng(latitude, longitude),
        zoom: 15,
        mapTypeId: 'roadmap'
    });

    var myLatlng = new google.maps.LatLng(latitude, longitude);
    var marker = new google.maps.Marker({
        position: myLatlng,
        map: gMap,
        title: "You are here!"
    });
}

Here's the code snippet for rendering the charts. Note – We are making use of an open source HTML canvas based chart library named chart.js. It's a very simple and easy to use library and we can make use of it to render a chart. 

First we need to have a reference to chart.js, the JavaScript library. As you can see below, we got chart data constructed based on the FoursquareVenueForChart entity. We will be making use of the chart data and make a call to the below mentioned methods for showing Bar, Line, and Radar charts.

<script src="~/Scripts/Chart.js"></script>

<script type="text/javascript">
    var ChartData = {
        labels: @Html.Raw(@Model.FourSquareVenueForChart.Labels),
         datasets: [
             {
                fillColor: "#F7464A",
                strokeColor: "rgba(220,220,220,1)",
                data: @Model.FourSquareVenueForChart.CheckIn
             }
         ]
    }
</script>

function ShowBarGraph() {
    var myLine = new Chart(document.getElementById("myChart").getContext(
      "2d")).Bar(ChartData, { renderBackground: false });        
}

function ShowLineGraph() {
    var myLine = new Chart(document.getElementById("myChart").getContext(
      "2d")).Line(ChartData, { rotateLabels: 6 });
   
}

function ShowRadarGraph() {
    var myLine = new Chart(document.getElementById(
      "myChart").getContext("2d")).Radar(ChartData, 
      { scaleShowLabels: false, pointLabelFontSize: 10 });        
}

Below is the jQuery AJAX code which makes a call to the controller to get the venue photos.

function VenuePhotos(button) {
    $.ajax({
        url: "/Home/FourSquareVenuePhotos",
        type: "GET",
        data: 'venueId='+ $(button).val(),
        success: function(response){
            $("#venuePhotos").html(response);      
            $("#venuePhotos").dialog("open");              
        },
        error: function (data) {
            $("#venuePhotos").html(data.responseText);
        }   
    }); 
}

Unit Testing

Before coding the controller implementation it's good to unit test our class library implementation and make sure it's working as expected. Below is the code snippet for unit testing the foursquare venue. The test methods exercise portion of the code that's required as part of this project.

[TestClass]
public class VenueTest
{
    [TestMethod]
    public void TestVenue()
    {
        string authToken = ConfigurationManager.AppSettings["authToken"].ToString();
        var recommentedVenues = NetSquare.VenueExplore("40.7,-74", "", "", 
            "", "", "", "Coffee", "", "", authToken);
        foreach (var place in recommentedVenues.places)
        {
            var recommendedValues = 
              ((List<netsquare.foursquarerecommendedvenues.recommends>)place.Value);
            foreach (var recommendedValue in recommendedValues)
            {
               Assert.AreNotEqual(recommendedValue.venue.name, string.Empty);
            }
        }
    }

    [TestMethod]
    public void TestVenueCategories()
    {
        string authToken = ConfigurationManager.AppSettings["authToken"].ToString();
        var venueCategories = NetSquare.VenueCategories(authToken);
        Assert.IsTrue(venueCategories.Count > 0);
    }

    [TestMethod]
    public void TestVenuePhotos()
    {
        string authToken = ConfigurationManager.AppSettings["authToken"].ToString();
        var venuePhotos = NetSquare.VenuePhotos("4b085df4f964a520300a23e3", 
            "venue", "", "", authToken);
    }
}

We will now see the unit testing of Google Geo coder. Below is the code snippet for that.

[TestClass]
public class GoogleApi
{
    [TestMethod]
    public void TestGoogleGeoCodingResponse()
    {
        SpotInfo sinfo = new SpotInfo();
        sinfo.Address = "1310 South White Oak Drive , Apt 714 , Waukegan";
        Geocoder geo = new Geocoder();
        GeoResult result = geo.GetGeoResult(sinfo);
        Assert.AreEqual(result.Status, GeoResultStatus.OK);
    }

    [TestMethod]
    public void TestCurrentLocation()
    {
        SpotInfo sinfo = new SpotInfo(42.370525571796215, -87.85941852461143);
        //sinfo.LatLng = new SpotLatLng(42.370525571796215, -87.85941852461143);
        sinfo.Sensor = true;
        Geocoder geo = new Geocoder();
        GeoResult geoResult = geo.GetGeoResult(sinfo);
        Assert.IsTrue(geoResult.Results.Count > 0);
    }
}

Points of Interest  

While working on this sample implementation I learnt a lot on how to get foursquare data, and how we can use it in a meaningful way in our website. I really enjoyed coding this stuff. Suggestions are most welcome.

Snapshots

History

  • Version 1.0 - Created FourSquare Analytics MVC4 based websites that show venue information, maps, and charts. Also shows venue pictures.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Ranjan.D
Web Developer
United States United States
Profile
 
Around 9 years of professional software development experience in analysis, design, development, testing and implementation of enterprise web applications for healthcare domain with good exposure to object-oriented design, software architectures, design patterns, test-driven development and agile practices.
 
In Brief
 
Analyse and create High Level , Detailed Design documents.
Use UML Modelling and create Use Cases , Class Diagram , Component Model , Deployment Diagram, Sequence Diagram in HLD.
 
Area of Working : Dedicated to Microsoft .NET Technologies
Experience with : C# , J2EE , J2ME, Windows Phone 8, Windows Store App
Proficient in: C# , XML , XHTML, XML, HTML5, Javascript, Jquery, CSS, SQL, LINQ, EF
 
Software Development
 
Database: Microsoft SQL Server, FoxPro
Development Frameworks: Microsoft .NET 1.1, 2.0, 3.5, 4.5
UI: Windows Forms, Windows Presentation Foundation, ASP.NET Web Forms and ASP.NET MVC3, MVC4
Coding: WinForm , Web Development, Windows Phone, WinRT Programming, WCF, WebAPI
 
Healthcare Domain Experience
 
CCD, CCR, QRDA, HIE, HL7 V3, Healthcare Interoperability
 
Others:
 
TTD, BDD
 
Education
 
B.E (Computer Science)
 
CodeProject Contest So Far:
 
1. Windows Azure Developer Contest - HealthReunion - A Windows Azure based healthcare product , link - http://www.codeproject.com/Articles/582535/HealthReunion-A-Windows-Azure-based-healthcare-pro
 
2. DnB Developer Contest - DNB Business Lookup and Analytics , link - http://www.codeproject.com/Articles/618344/DNB-Business-Lookup-and-Analytics
 
3. Intel Ultrabook Contest - Journey from development, code signing to publishing my App to Intel AppUp , link - http://www.codeproject.com/Articles/517482/Journey-from-development-code-signing-to-publishin
 
4. Intel App Innovation Contest 2013 - eHealthCare - http://www.codeproject.com/Articles/635815/eHealthCare
 
5. Grand Prize Winner of CodeProject HTML5 &CSS3 Article Content 2014

Comments and Discussions

 
BugExcellent [modified] PinmemberLouisGia31-Mar-14 21:53 
QuestionSuch a good idea! PinmemberGregoryW30-Sep-13 21:37 
AnswerRe: Such a good idea! PinprofessionalRanjan.D1-Oct-13 4:04 
QuestionMy Vote of 5!! PinmemberAbhishek Nandy1-Jul-13 22:31 
AnswerRe: My Vote of 5!! PinprofessionalRanjan.D3-Jul-13 9:38 
GeneralMy vote of 5 Pinmemberrjgadag30-Jun-13 18:09 
GeneralRe: My vote of 5 PinprofessionalRanjan.D1-Jul-13 0:46 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140827.1 | Last Updated 30 Jun 2013
Article Copyright 2013 by Ranjan.D
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid