Tuesday, December 31, 2013

Converting SalesForce SOQL results to a Linked Dataset for use by C#

In my last post, I illustrated the 'simple' way of getting the data back - by just creating a Xml Document from the results. This is not always efficient -- in fact, I have gotten out of system memory errors on some queries.

In this post I will take the same query and show a little slight of code. The query was:

SELECT Name, 
  (SELECT Name, Email FROM Contacts), 
  (SELECT CaseNumber, CreatedDate, Subject, Status, Resolution__c,  ClosedDate, SuppliedEmail,SuppliedName FROM Cases
   WHERE CreatedDate = LAST_N_DAYS:366 
   AND Origin != 'Internal' 
   AND OwnerId !=     '00G40000001RTyyEAG' 
   AND RecordTypeId IN ('01240000000UTWP', '01240000000UWxM', '01240000000UWxl', '01240000000UWxb')

  ) 
 FROM Account  


 WHERE ID IN (SELECT AccountId FROM Contact Where Email in ({0}))

Extension Method to Handle SOQL Result Columns

The code below takes the results from the query and creates a DataTable from one column. This is our fundamental building block suitable for all SalesForce queries.

You could call this in a nested manner if you have nested objects in your query -- but I assume just one layer deep.

    ///
    /// Converts a Salesforce style XMLElement into a datatable
    ///
    /// A "Column" returned from Salesforce
    /// DataTable
    public static DataTable SalesForceToDataTable(this XmlElement element)
    {
        var result = new DataTable(element.LocalName);
            if (element.ChildNodes.Count == 1)
            {
                if (!result.Columns.Contains(element.LocalName))
                {
                    result.Columns.Add(element.LocalName);
                }
                DataRow row = result.NewRow();
                row[element.LocalName] = element.InnerText;
                result.Rows.Add(row);
            }
            else
                foreach (XmlNode child in element.ChildNodes)
                {
                    switch (child.LocalName)
                    {
                        case "size":
                        case "queryLocator":
                        case "done": break;
                        case "records":
                            DataRow row = result.NewRow();

                            foreach (XmlElement field in child.ChildNodes)
                            {
                                var colName = element.LocalName + "_" + field.LocalName;

                                if (!result.Columns.Contains(colName))
                                {
                                    result.Columns.Add(colName);
                                }
                                row[colName] = field.InnerText;
                            }
                            result.Rows.Add(row);
                            break;
                    }
                }
        return result;
    }

Building and linking a DataSet across columns

As we saw in our last post, we have subqueries appearing in a single column, as illustrated below:

The routine above handles each column. To put it all together, we use the code below.

public static DataSet QueryCases(string myquery)
{
    var result = new DataSet();
        var binding = new AdminConsole.WebSalesForce.SforceService();
        binding.SessionHeaderValue = new AdminConsole.WebSalesForce.SessionHeader();
        var salesforce = SaleforceUrl;
        if (salesforce != null)
        {
            binding.SessionHeaderValue.sessionId = salesforce.sessionId;
            binding.Url = salesforce.serverUrl;

            binding.UseDefaultCredentials = true;
            var results = binding.query(myquery);
            var done = false;
            while (!done && results.size > 0)
            {
                var masterKey = 0;
                foreach (var record in results.records)
                {
                    var tableIndex = 0;
                    foreach (XmlElement key in record.Any)
                    {
                        var newTable = key.SalesForceToDataTable();
                        newTable.Columns.Add(DataSetKey, masterKey.GetType());
                        foreach (DataRow row in newTable.Rows)
                        {
                            row[DataSetKey] = masterKey;
                        }
                        // On the first table we ADD to dataset, on subsequent we append the records
                        if (masterKey > 0)
                        {
                            foreach (DataRow row in newTable.Rows)
                            {
                                result.Tables[tableIndex].ImportRow(row);
                            }
                        }
                        else
                        {
                            result.Tables.Add(newTable);
                        }
                        if (result.Tables.Count > 1)
                        {
                            result.Relations.Add(result.Tables[0].Columns[DataSetKey], newTable.Columns[DataSetKey]);
                        }
                        tableIndex++;
                    }
                }
                masterKey++;
                done = results.done;
            }
        }
    return result;
}

Converting Linked DataSet to DataTable

What we are doing is adding a new key to tie the data in each column together and adding it as a relationship to the dataset. This is generic code still -- works for almost any query.

The last step is flattening this dataset into a data table so I may display it in a Telerik Grid. I need to match case to contact (which would be easy with a proper SQL language). My solution is shown below:


private DataTable FlattenDataSet(DataSet dataset)
{
        var result = new DataTable();
        try
        {
            // Create all columns
            foreach (DataTable table in dataset.Tables)
            {
                foreach (DataColumn col in table.Columns)
                {
                    if (!result.Columns.Contains(col.ColumnName))
                        result.Columns.Add(col.ColumnName);
                }
            }
            //Import the 1:1 relationships into the table
            foreach (DataRow row in dataset.Tables["Cases"].Rows)
            {
                result.ImportRow(row);
            }
            // Import the 1: of the 1:m relationship
            foreach (DataRow master in dataset.Tables["Name"].Rows)
            {
                DataRow[] rd = result.Select(DAL.daSalesForce.DataSetKey + "=" + master[DAL.daSalesForce.DataSetKey]);
                foreach (DataRow row in rd)
                {
                    foreach (DataColumn col in dataset.Tables[0].Columns)
                    {
                        row[col.ColumnName] = master[col.ColumnName];
                    }
                }
            }
            // For each contact (expected to be fewer than cases) We lookup the cases they submitted
            foreach (DataRow master in dataset.Tables["Contacts"].Rows)
            {
                DataRow[] rd = result.Select("Cases_ContactId='" + master["Contacts_Id"] + "'");
                foreach (DataRow row in rd)
                {
                    foreach (DataColumn col in dataset.Tables["Contacts"].Columns)
                    {
                        row[col.ColumnName] = master[col.ColumnName];
                    }
                }
            }
     return result;
    }
    else
    {
        return (DataTable)Session["SalesForce"];
    }
}

Bottom Line

Salesforce SOQL results can be handled in .Net using an extension and moving the data into a DataSet.  Once the data is there, you may have a little dataset grunting to get it transformed into the appropriate format.

Monday, December 30, 2013

Handing Salesforce SOQL Relationship aka Joins in C#

Salesforce SOQL is not SQL which often causes great frustrations to experienced database developers when they work with it. Being of the generation that worked with Network Data Models and Hierarchical Data Model  - i.e. pre-Relational Databases! (as well as database on Tape!), I actually find a lot of "familiar tones" in SOQL.

Recently I was needing to build a query that in SQL would be:

SELECT Account.Name AS AccountName, 
  Contact.Name, Contact.Email, 
  Case.CaseNumber, Case.CreatedDate, Case.Subject, Case.Status, Case.Resolution__c,  Case.ClosedDate, Case.SuppliedEmail,      Case.SuppliedName 
 FROM Account  JOIN Case ON ... JOIN Contact ON ....
 WHERE Contact.Email in ({0})
  AND Case.CreatedDate = LAST_N_DAYS:366 
   AND Case.Origin != 'Internal' 
   AND Case.OwnerId !=     '00G40000001RTyyEAG' 
   AND Case.RecordTypeId IN ('01240000000UTWP', '01240000000UWxM', '01240000000UWxl', '01240000000UWxb')

The equivalent query in SOQL turned out to be less complex to read (because of the intrinsic joins that exists in Salesforce). Understanding these intrinsic - relationships is essential for writing queries!

SELECT Name, 
  (SELECT Name, Email FROM Contacts), 
  (SELECT CaseNumber, CreatedDate, Subject, Status, Resolution__c,  ClosedDate, SuppliedEmail,SuppliedName FROM Cases
   WHERE CreatedDate = LAST_N_DAYS:366 
   AND Origin != 'Internal' 
   AND OwnerId !=     '00G40000001RTyyEAG' 
   AND RecordTypeId IN ('01240000000UTWP', '01240000000UWxM', '01240000000UWxl', '01240000000UWxb')

  ) 
 FROM Account  
 WHERE ID IN (SELECT AccountId FROM Contact Where Email in ({0}))

The next piece is dealing with the query results. When you execute the above in the developer's console, you will see that the data returns as JSON.
This means a little magic when the response is received. What we have received is a dataset consisting of three linked tables. There are two approaches that seem obvious:
  • Explode the dataset into a single data table
  • Use the dataset as a linked table
In my case, I needed to display the results in a flat grid of cases, so I went down the first path. There's a little magic that needed to be done because one account has many contacts(1:n) and many cases (1:m). This means that you need to walk the cases, and lookup the contact for each case record. As a result, I have to include the ContactId in Cases to flatten the data structure and get the matching contact ID. The result should be a table with m rows.


SELECT Name, 
  (SELECT Id, Name, Email FROM Contacts), 
  (SELECT ContactId, CaseNumber, CreatedDate, Subject, Status, Resolution__c,  ClosedDate, SuppliedEmail,SuppliedName FROM Cases
   WHERE CreatedDate = LAST_N_DAYS:366 
   AND Origin != 'Internal' 
   AND OwnerId !=     '00G40000001RTyyEAG' 
   AND RecordTypeId IN ('01240000000UTWP', '01240000000UWxM', '01240000000UWxl', '01240000000UWxb')

  ) 
 FROM Account  
 WHERE ID IN (SELECT AccountId FROM Contact Where Email in ({0}))

Examining the results reveal that we are dealing with XML and can thus convert them easily via XML activites
I noticed that applying LINQ to SOQL results seems to be difficult for some, but if you work at the XML level, some of the pain disappears quickly.

The code below uses the "fat" XmlDocument (and thus should not be used in real systems) for purposes of illustration:

        public static XmlDocument QueryCases(string myquery)
        {
            XmlDocument dom = new XmlDocument();
            dom.LoadXml("");
            XmlNode recordNode;
            try
            {
                var binding = new AdminConsole.WebSalesForce.SforceService();
                binding.SessionHeaderValue = new AdminConsole.WebSalesForce.SessionHeader();
                var salesforce = SaleforceUrl;
                if (salesforce != null)
                {
                    binding.SessionHeaderValue.sessionId = salesforce.sessionId;
                    binding.Url = salesforce.serverUrl;

                    binding.UseDefaultCredentials = true;
                    var results = binding.query(myquery);
                    var done = false;
                    while (!done && results.size > 0)
                    {
                        dom.DocumentElement.AppendChild(recordNode = dom.CreateElement("record"));
                        foreach (var record in results.records)
                        {
                            foreach (XmlElement key in record.Any)
                            {
                                recordNode.AppendChild(dom.ImportNode(key, true));
                            }
                        }
                        done = results.done;
                    }
                }
            }
            catch (Exception ex)
            {
                AdminConsole.Diagnostics.SplunkLogger.Error(ex);
            }           
            return dom;
        }

Now you have your data is a format that you can proceed easily with via LINQ etc.

Wednesday, October 16, 2013

Doing Tests and Unit Tests of AspForm Web Applications: Setup

This is the beginning of a series of post dealing with AspForm unit tests.

We have two options for running Unit Tests. Both have advantages and disadvantages.

Running Unit Tests Against your local development Box

A test would be written as shown below



This will produce a result such as


To have the test work we MUST configure IIS to provide the appropriate site, for example on 666


Check list:
  • Physical Path is pointing to the image you wish to test
  • IIS port and path are matching
  • IIS Server is running

Running Unit Tests Against a Development Server

Note: You need to STOP the above server for the following to work.
Our test is now written as:


The AspNetDevelopmentServerHost must be pointing at the source folder you wish to test.
We must now change the Web Application project to be found and available:


Again the test will run (with ability to debug into the web application if needed)

Gotcha of this approach

The Web.Config is rewritten at the start and at the end of running unit tests. Occasionally you will get error messages about web.config being locked by another process.

Recommended Approach

The following template is recommended:


That is
        [TestMethod]
        [HostType("ASP.NET")]
        [UrlToTest("http://localhost:666/default.aspx?unittest=devadmin@avalara.com?Unittestlogin=devadmin@avalara.com")]
       // [AspNetDevelopmentServerHost("C:\\GitHub\\develop\\AdminConsole", "/")]
This has the following advantages:
  • If you have multiple branches, then by just changing the IIS settings to point at each branch, you can run the tests against each branch without touching the files.
  • If there is a team working on the project, then there is no dependency on the physical location of the files (a big plus!)
  • If there is a problem that needs investigation,
    • Turn off IIS
    • Uncomment the AspNetDevelopmentServerHost line and adjust the path (if needed)

Tuesday, March 26, 2013

Missed placed your installation MSI and need to move Application to another machine?

I was working away from my home office and my library of MSIs was not accessible. I wanted to install some software on a new machine NOW, instead of waiting until I got home in a few weeks.

 

I remembered that everything that is installed has a copy of the installation MSI copied to C:\Windows\Installer (so programs can be uninstalled later). looking in this folder, I saw {temp file names}.msi and not the original MSI names – rats!  Wait a minute, the MSI’s likely contains information on what it is in its properties.

  1. Left clicking on the file list allows you to select what is displayed.

image

Clicking More… gives you “Subject” which is what I am looking for:

image

Now I see what all of the MSI are!
image

Now, I just copy (NOT move) the desired MSI’s to another folder, and renamed them appropriately.  If you move them, then you will cause problems if you wish to adjust features at a later time.

 

I can now install the stuff that I want, now!

Wednesday, March 13, 2013

Android Low Energy Bluetooth or a feature that I would love to see in C#

Recently I have been playing with BLE on Android (Samsung S3). One of the issues is no exposed BLE API in the current version of Android. I said, exposed, because by reflection you can find them! Or at least some of them, in some cases, you need to access the BLE library that was supplied to the phone (but not connected to the Android OS.

 

The process is very simple to identified the library:

 

First, add the following to the manifest:

 

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <uses-library
        android:name="com.broadcom.bt.le"
        android:required="false" />
    <uses-library
        android:name="com.csr.bluetooth.BluetoothExt"
        android:required="false" />
    <uses-library
        android:name="com.htc.android.bluetooth.le"
        android:required="false" />
    <uses-library
        android:name="android.server.BluetoothGattService"
        android:required="false" />
    <uses-library
        android:name="com.samsung.bluetoothle.BluetoothLEClientProfile"
        android:required="false" />

 

Then create an enumeration. This is very much a Java enumeration (you don’t see this in C#)

 

public enum HardwareEnum {
    Motorola("android.server.BluetoothGattService"), Broadcom(
            "com.broadcom.bt.le.api.BleAdapter"), Csr(
            "com.csr.bluetooth.BluetoothExt"), Htc(
            "com.htc.android.bluetooth.le"), Samsung(
            "com.samsung.bluetoothle.BluetoothLEClientProfile"), None("");
    private final String value;

    HardwareEnum(String value) {
        this.value = value;
    }

    public String getClassName() {
        return value;
    }
}

Next you need to write a detector, which is very simple with the above enumeration.

 

public class HardwareDetector {
    /*
     * Each of the class names MUST be in the Manifest. as <uses-library
     * android:name="com.broadcom.bt.le" android:required="false" />
     */
    private static final String TAG = "HardwareDetector";

    public static HardwareEnum detectHardware() {

        HardwareEnum result = HardwareEnum.None;
        for (HardwareEnum item : HardwareEnum.values())
            try {
                Log.i(TAG, "testing:" + item);
                Class.forName(item.getClassName());// , false, null);
                result = item;
                Log.i(TAG, "found:" + item);
                return result;
            } catch (Exception exc) {
                Log.w(TAG, exc.toString());
            }
        return result;
    }
}

Now, you know the library that talks to the BLE on your phone. You may wish to use reflection to explore what is in the library and develop code from there.

 

What is the missing feature from C#?

Simple, being able to do enumerations consisting of objects. While working with Android code, I found that this pattern allowed massive simplification of code and much improved clarity…   Microsoft folks, please add something like this!

Sunday, February 24, 2013

Are Android implementations lightweight/superficial?

Recently I found that two feature sets of Android to be seriously lacking. There is also a feeling that other features (motion sensors) are “punt ware”. The biggest short fall has been implementation of Low Energy Bluetooth --- something that runs find on apple devices– is totally lacking.

    Issue 43473: Bluetooth Smart (Low Energy) on Android

    Issue 37525:android api support for Bluetooth

    Issue 33371: Support for Bluetooth 4.0 Low Energy Profile on Galaxy Nexus

Recently, I did some work with a friend on Near Field Communications. The Android libraries work – sort of, they allow demo code showing simple operations to be written but fail to fully implement the complete specification.

 

Recently I have also been working hard to use the motion sensors and found that they work adequately for game play but if you are wishing to use them for internal navigation , there is great angst in code-ville…

 

Having spent time in Microsoft Developer’s Division of days of old, I see the trend to do agile development/sprints as part of the cause. Sprints tend to cherry-pick the essential or easiest items to implement. The result is that given a specification (like BLE or NFC),  the top 80-90% of the specification gets done and the rest falls below the radar and is never implemented. In the old traditional world, there was often a goal to insure 100% compliance and possible certification. Certification is no longer a significant marketing aspect; “We support XYZ” no longer means we implement all of XYZ – instead, it is “We do some of the things in the specification – the IMPORTANT ones…”

 

I believe that this is just a phrase, one that will run it course in time….but until that happens, beware of marketing hype of what is supported!

Thursday, February 14, 2013

Object-Relational Mapping (ORM) Frameworks–knowing the price tags!

I own Telerik’s OpenAccess ORM, I have consulted professionally on Microsoft Entity Framework, this week I had a long conversation with senior types on Hibernate issues. My experience with ORM or ORM-like implementations, go back to 2001, when I was joined Vision Compass and had to immediately investigate and fix major performance problems. While the C++/SQL Server application was not generated by a ORM tool, the design followed what a ORM tool would produce.

 

Wikipedia wise, it has been described as

“(ORM) is a programming technique for converting data between incompatible type systems in relational databases and object-oriented programming languages. This creates, in effect, a "virtual object database," which can be used from within the programming language. There are both free and commercial packages available that perform object-relational mapping, although some programmers opt to create their own ORM tools.”

Humanware wise: the lack of availability of skilled database people (as well as communication issues between OOP types and RDBMS types) has resulted in a na├»ve layering of a database with templates on how to access the data. For many systems, this is sufficient to get the system built and released. The OOP types move on to their next project with a “success” notched on their belts.

 

I said “for many”, the problem is that for high load systems (relative to hardware supporting it) the side effect may be 4 to 10 times more hardware expense then needed if a good database person was involved that knows their stuff.  Often, when scaling issues arrived, techniques like sharding will remove blockage and contention issues. While sharding allows better scaling, it can also make it more difficult/time consuming to build reporting or investigative components on the system.

 

Other issues can arrive when one database is shared by multiple applications, each with their own versioned ORM. While these can be reduces by moving the ORM into a common library that is shared by all of the applications, the problem remains of having to retest all of the applications with each ORM drop; and then, potentially having to update all of the live applications concurrently. If one has to be rolled back, then all may need to be rolled back.

 

The real cost of the ORM is that much of the internal business logic that would be in triggers and stored procedures is moved to higher levels with the result that the core data may become very corrupted in some circumstances. There is no longer a moat and high walls around the cities, instead, the walls are torn down so every street runs into the country side.  It is much easier for a thief to make a living; or a vandal to paint bomb store fronts. In one case, the city is much more secure and safe but commerce may suffer from having to go through a few guarded gates; in the other case, commerce may thrive but then every merchant may have to hire their own guards.

 

The real question is what happened when an enemy comes knocking (corporate espionage, spying), if the city is wide open then the pickings are good, a troop of raiders can ride in and carry out much easily. If the city is gated and guarded, success is much less likely.

 

Just like outsourcing and offshoring seemed like a good idea 15 years ago because it appeared to save money, the trend is increasing to on-shore or repatriate work. ORM saves money and reduce the time to delivery – just like offshoring promised. When you look at long life, evolving systems that keep adding applications, the maintenance costs and complexities start to multiple. You can pay upfront or down the road (or discard the system in 4 years and build your next short lived implementation).

Saturday, February 2, 2013

Facebook: Reducing Advertisements

This post arose from several friends asking for help because the number of ads that were appearing on Facebook almost made it unusable (too much to wade through for the benefit received).  These are normal people and not nerds. The common root cause was doing “Likes” that result in add appearing.  The selling of this feature to business is described here. This is an older problem that was reported by the likes of NBC in stories.  In a recent story, Zuckerberg reports that more and more ads are being done this way.The bottom line is NOT to like anything except actual posts (not reposts or shares or….).  Like People you know posts and not products or firms.

 

The solution is to be kind to your friends (as shown below), ask your friend to do the same (and if they do not, then you may need to unfriend them if their facebook friendship continues to spam you). You may wish to FORWARD this page to them first…

 

SPAM because of Friends!

If you friends like stuff, the ads will appear in THEIR newsfeed to you. There are a few things that you could do…

  • Click on the down error on the left and pick “Report story or Spam”
    • This may have limited effect – after all Facebook is making money from showing it!

image

SPAM Coming from a PAGE

If you click the name, a dialog appears …  You can UNLIKE it….

image

As each irritating item appears, change your Liked to Unliked.

 

A Friend that “does TOO much sharing”

Click on THEIR NAME on any of they posts, this will change to THEIR page.

 

Then click as shown below.

image
Uncheck as much as you feel appropriate.

image

For example, only Status Updates and Photos. SHARED items will appear  unless you select Important Only

 

Apps Posting

  • Often ads appear because you granted some app to post on your behalf (often in the long distant past) in exchange for playing a game, etc. You will see on the left side of the page,
    image
    • Click App Center. A new page will appear, on the left side of the page you will see:
      image
    • Clicking this will show your applications.
      image
    • You want to reduce them to only the ones that your REALLY want to have available NOW.  You can always re-install them
    • If you click “Settings” you may be shocked with what the application is allowed to do!
      image
    • On the RIGHT side  under “This app can also” are some “x”, if you click each one of them, the permissions disappear (one by one --- remember, those permissions make money for Facebook – so they will not make it easy!).
    • An additional item that you should do ON BEHALF of all of your friends, is change “Posts on your behalf” to “Only Me”
      image
    • If you want to REMOVE the application, then it more steps still (remember – Facebook makes money from keeping this!). Click on the App Name, this will take you to the app page. Now on the left side at the bottom you will see:
      image
    • Click “Remove”… You may then be notified: ---Ugh, they get to keep YOUR Information unless you jump through more and more loops….
      image
    • Click Remove..
  • If you return to your app page, https://www.facebook.com/appcenter/my the application should now be removed. You can speed direct app removal from this page by hovering over an app and then a small “x” will appear:
    image
  • This results in immediate removal.
    image
  • You REALLY want to reduce the number of Apps to as few as possible
  • You REALLY want to review the permissions for each to just those you REALLY want to give!
  • You REALLY want to NOT SPAM friends, so set posts to go to yourself only

Deleting Past Likes

This is where paying the piper happens!  You have to go to the page that you liked and unlike it!  -  To do this, click your name. You will see

image

Just click the Likes and start to UNLIKE them. As expected, the critical ones are at the bottom of the page… group year by year.
image

 

Cutting Other Spams

An alternative starting point is

https://www.facebook.com/settings?tab=blocking
image

It allows you to get rid of some spam (like requests that you are not interested in)

image

And get down to a simpler:
image

Put yourself elsewhere in the world!

You will notice above that I am using English(UK).  Some “cut the ads” routines would be to move to somewhere else in the world, You may need to be ruthless (for example remove Mobile Phone – which identifies your country and thus an advertising scope!).

 

Click [Your Name] at the top of the page and then [Update Info].

 

I will use maps.google.com to locate a small town or city elsewhere in the world and then “move there virtually”.
image

For telephone numbers, you may get an invalid telephone number.  Fear not, go to http://en.wikipedia.org/wiki/List_of_mobile_phone_number_series_by_country

and look for an appropriate match.  US and Canada have a NSN of 10.   You may need to locate a country that also match your Area Code. In my case, Mali did not work, but ITALY did Smile

BOTTOM LINE

Facebook is a business that seeks to make a profit (unlike Wikipedia) from your friendship, the correct term is exploit. In time, I expect Facebook will fade away like MySpace (so do not buy stock in it… it will fade).

Sunday, January 27, 2013

Android getOrientation()

 

I spend some time today trying to understand getOrientation()  and found a few notes when I googled, but most of the notes left things fuzzier than needed. The author’s appear to know what they were talking about – but failed to express it with a good clarity…

 

The documentation states:

 

getOrientation(float[] R, float[] values)

Computes the device's orientation based on the rotation matrix.

 

Not exactly a rich description! When I attempted to write code, the expected results did not occur….

 

The core of the code is:

SensorManager.getRotationMatrix(rotationMatrix, null, accelVals, magVals);            
SensorManager.getOrientation(rotationMatrix, orientationVals); textView1.setText(" 0:"+orientationVals[0]+ " 1:"+orientationVals[1]+" 2:"+orientationVals[2]);
Where the values are supplied by (I’ve omitted the code for stabilizing the values)
@Override
public void onSensorChanged(SensorEvent se) {
case Sensor.TYPE_MAGNETIC_FIELD:
     magVals = se.values.clone();
     break;
case Sensor.TYPE_ACCELEROMETER:
    accelVals = se.values.clone();
break;
}

So far, so good, but what do the orientationVals  mean?  The simplest way is to just run thru same sample data gathering.

 

Device Flat

Putting the device on a flat table and going to the 4 compass points.

image

The numbers were not what I was expecting…

Direction orientationVals[0] orientationVals[1] orientationVals[2]
N 2.8 -0.04 0.002
W 2.2 -0.04 0.002
S 1.5 -0.03 0.04
E 1.1 -0.04 0.04

Ugh … this is not what I was expecting…

Device Vertical:

image

Direction orientationVals[0] orientationVals[1] orientationVals[2]
N -1.6 -1.5 2.2
W 0.2 -1.53 2.2
S -1.4 -1.5 1.72
E -1 -1.5 2.3

Device Horizontal

image

Direction orientationVals[0] orientationVals[1] orientationVals[2]
N -0.7 -0.04 1.6
W -0.4 -0.04 1.6
S -2 -0.04 1.6
E -1.2 -0.02 1.6

 

OrientationVal[0] is the main item that changes with each experiment. The range from max-value to min-value seems is be about Pi/2 (3.14/2 = 1.57), so the values appear to be angle measures and not vector lengths (which I had assumed)…

 

In various forums, I finally found the text below – which forgot to mention that the values are angles in radians…

Computes the device's orientation based on the rotation matrix.
When it returns, the array values is filled with the result:
values[0]: azimuth, rotation around the Z axis.
values[1]: pitch, rotation around the X axis.
values[2]: roll, rotation around the Y axis.
Parameters
R        rotation matrix see getRotationMatrix(float[], float[], float[],
float[]).
values        an array of 3 floats to hold the result.
Returns
The array values passed as argument.

I now understand that values[0]: azimuth, rotation around the Z axis with 0.0 being magnetic north (another omission in the documentation).

Interview: A question from when I did CS 101…

Look at the following code:

static int OpPerf_0(int x, int y, int z)
        {
            return x + y + z;
        }
        static int OpPerf_1(int x, int y, int z)
        {
            return sum(x,sum(y,z));
        }
        static int sum(int x, int y)
        {
            return x + y;
        }

First estimate the difference of performance between OpPerf_0 and OpPerf_1?

Write out pseudo-machine code on what will be executed with OpPerf_0 and OpPerf_1.

 

This is a C#, Java, C++, neutral question that tests the person’s understanding of what actually happens when code is executed.

 

OpPerf_0

LOADADDR OpPerf_O

PUSH ReturnAddress

PUSH X

PUSH Y

PUSH Z

CALL  LoadAddress

POP X

POP Y

POP Z

MOVE X, ACC-1

MOVE Y, ACC-0

ADD

MOVE Z, ACC-1

ADD

PUSH ACC-1

CALL ReturnAddress

 

I will leave OpPerf_1 to the reader….

 

OpPerf_1

LOADADDR OpPerf_1

PUSH ReturnAddress

PUSH X

PUSH Y

PUSH Z

CALL LoadAddress

POP X

POP Y

POP Z

LOADADDR sum

PUSH X

PUSH Y

PUSH This.Address_1

CALL LoadAddress

POP X

POP Y

MOVE X, ACC-1

MOVE Y, ACC-0

ADD

PUSH ACC-0

CALL This.Address_1

POP TEMP

PUSH This.Address_2

LOADADDR sum

PUSH TEMP

PUSH Z

CALL LoadAddress

POP X

POP Y

MOVE X, ACC-1

MOVE Y, ACC-0

ADD

PUSH ACC-0

CALL This.Address_2

POP TEMP

PUSH TEMP

CALL ReturnAddress

 

So one is ~ 35 steps and the other is 14 steps, or 250% more steps. Or, a style that instead of needing 10 servers, you need 25 servers….

Saturday, January 26, 2013

Interview: Find Kth Largest in two arrays of ordered integers

This one is actually an improvement over the usual proforma CS-101 questions. A possible solution is below

One of the key item is whether the answerer address boundary conditions (which is half the solution!)

 

public int FindKthLargest(int[] list1, int[] list2, int kth)
        {
            if ((list1 == null && list2.Length < kth) ||
                (list2 == null && list1.Length < kth) ||
                (list1 != null && list2 != null && (list1.Length + list2.Length) < kth))
            {
                throw new ArgumentException("Lists are too short");
            }
            if (list1 == null)
            {
                return list2[list2.Length - kth];
            }
            if (list2 == null)
            {
                return list1[list1.Length - kth];
            }

            int pt1 = list1.Length - 1;
            int pt2 = list2.Length - 1;
            int maxValue = (list1[pt1] > list2[pt2]) ? list1[pt1--]: list2[pt2--];
            kth--;      
            while (kth > 0)
            {
                maxValue = (list1[pt1] > list2[pt2]) ? list1[pt1--] : list2[pt2--];
                kth--;                    
            }
            return maxValue;
        }

Friday, January 25, 2013

Interview: Find the Number that repeats the most times in a row in an array of integers

This is another one of these not related to job functions questions that get asked.

The solution is simple:

public static int MaxRepeatInArray(int[] arr)
{
    //Input checks
    if (arr == null || arr.Length < 1)
    {
        throw new DataException("Empty Array");
    }
    int bestChoice = arr[0];
    int bestCounter = 1;
    int currentChoice = arr[0];
    int currentCounter = 1;
    for (int i = 0; i < arr.Length; ++i)
    {
        if (currentChoice == arr[i])
        {
            currentCounter++;                    
        }
        else
        {
            if (currentCounter > bestCounter)
            {
                bestChoice = currentChoice;
                bestCounter = currentCounter;
            }
            currentChoice = arr[i];
            currentCounter = 1;
        }
    }
    // Incase sequence is at end
    if (currentCounter > bestCounter)
    {
        bestChoice = currentChoice;
        bestCounter = currentCounter;
    }
    return bestChoice;   
}

 

It takes just one pass of the data O(n). The time could be shortened a little by seeing if the number of remaining items

if (currentCounter > bestCounter)
  {
      bestChoice = currentChoice;
      bestCounter = currentCounter;
      if (arr.Length - i < bestCounter)
          return bestChoice;
  }
Which needs to be done when the choice changes and not on every pass.

Thursday, January 24, 2013

Interview: Efficiently implement x^y for positive integers using basic operators.

There are three solutions that come to mind..

public static int PowerOfY_0(int x, int y)
 {
     int result = 1;
     for (int i = 0; i < y; i++)
         result *= x;
     return result;
 }

The second solution is a bit of fun, because you are not using the power function but other math functions. Definitely efficient in terms of lines of code.

 

public static int PowerOfY_1(int x, int y)
     {
         return (int) Math.Round( Math.Exp(y* Math.Log(x, Math.E)));
     }

The expected function is something like this:


public static int PowerOfY(int x, int y)
{
    int result = 1;
    while (y > 0)
    {
        if (y % 2 == 1)
            result *= x;
        y = y / 2;
        x *= x;
    }
    return result;
}
Of course, this is a bad question – you are really testing if the person can remember prior canned solutions and not their ability to think.  IMHO, the interviewer asking the question is suspect on their ability to think. It has no relationship to any job function.