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.

Saturday, January 12, 2013

Removing SYSPRO Business Object Dependencies

Summary

Recently I was assigned the task of removing all dependencies on SYSPRO business objects inside an Asp.Net 2.0 application. These are the steps to find underlying SQL calls made by the business objects. 

 

SYSPRO Business Objects

SYSPRO Business objects are contained in the Interop.Encore.dll. The returned result is XML for the calls I dealt with.

 

The data items were, eventually, pulled out of the XML and used as single data points or as lists. You may choose to return XML from the new SQL calls you write.  This allows you to plug in the results and leave the rest of the legacy code.

 

Since the purpose of my task was to find any and all speed improvements, I removed the XML and dealt directly with SQL results. This required more data layer build-up but the benefit, beyond speed, was that I learned exactly what data was required and how it was ultimately used since I had to reverse engineer all the way to the level of usage. 

 

image

 

The most interesting part of this reverse engineering was that there was so much unnecessary data retrieval that even the barest of changes would have made a significant improvement. 

 

Working with the Code

Open the Visual Studio project and set break points right before and after all SYSPRO calls.

 

image

XML Results

Once the call returns from the SQL Server via the SYSPRO business object, you will need to capture the results in order to verify what data you need, versus what was returned.

 

Tip: Finding the SYSPRO Business Object Usage

If you aren’t sure where the SYSPRO calls are, remove the reference to the DLL and build. The Error Window list should now be related to just SYSPRO. Make sure to add the reference back. 

 

SQL Server Profiler

Open SQL Server Profiler and set up a new trace. Set the server name and database name. Don’t start the trace just yet. You want as small a sampling as possible in order to make finding the queries easier. You will probably know the parameters that were used for the SYSPRO request. That will help find the queries. 

 

Run to the First Break

Run the code to the first break point.

 

image

 

You are going to start the trace, and flip back over to Visual Studio as quickly as possible to run to the second breakpoint, then switch back to Profiler and stop the trace. Arrange you windows to make this as easy as possible.

 

Find The Queries

Use the Find tool inside of Profiler to choose either the unique parameter used by the SYSPRO business objects in the TextData field, or search for the Application Name of Microsoft Windows Operating System.  The bottom window of the Profile should now contain a query used by SYSPRO. Don’t stop at just once though. Keep looking. One of the calls to the SYSPRO business object I tracked down had many calls because it found the customer record then all invoices (maybe just open invoices) for the customer. That was a lot of unnecessary calls!

 

image

 

Save all the SQL queries and the resulting XML and put them in a folder with a single name. Verify the data points you need and rewrite the SQL queries to get just those. Several SYSPRO queries used poorly structured WHERE clauses bringing back many rows when only the top 1 row was the relevant row. If you don’t have the ability to rewrite the query, make sure to just return the top 1, when you only want one row.

 

Tip: SQL Server Analysis

If you use a product like Ignite to identify performance issues, make sure the ODBC connection string’s Application Name is set. This will allow queries that were previously attributed to Microsoft Windows Operating System to be associated with the correct application. This will help you identify what new queries per program, after removing the SYSPRO business object dependency, still need to be tuned.

 

image

Thursday, January 3, 2013

Cascading Dropdown Boxes with Data coming from XML

A friend from my days at Blackboard sent me the following code mockup and asked me how to make it work.

<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<asp:XmlDataSource ID="XmlDataSource1" DataFile="FeatureRequestDatasource.xml" runat="server" XPath="product/feature" ></asp:XmlDataSource>
<asp:XmlDataSource ID="XmlDataSource2" DataFile="FeatureRequestDatasource.xml" runat="server" XPath="product/feature/area"></asp:XmlDataSource>
<asp:XmlDataSource ID="XmlDataSource3" DataFile="FeatureRequestDatasource.xml" runat="server" ></asp:XmlDataSource>
   <h3>Sample Feedback Submit Form</h3>
       <div>
       Product Feature <asp:DropDownList ID="DropDownList1" 
               DataSourceID="XmlDataSource1" DataValueField="value" DataTextField="text"  
               Width="250" runat="server" 
               >         
       </asp:DropDownList><p />
       Feature Area <asp:DropDownList ID="DropDownList2" 
                   DataSourceID="XmlDataSource2" DataValueField="value" DataTextField="text"  
                   Width="300" runat="server" 
                   >
        </asp:DropDownList><p />
       Feature Subarea <asp:DropDownList ID="DropDownList3" DataSourceID="XmlDataSource3" DataValueField="value" DataTextField="text" Width="400" runat="server">
        </asp:DropDownList><p />
       <span style="vertical-align:top">Comments</span> <asp:TextBox ID="TextBox1"  TextMode="MultiLine" width="400" Height="200" runat="server"></asp:TextBox><p />
       Upload JPG screen shot&nbsp;&nbsp;<asp:FileUpload ID="FileUpload1" runat="server" /><p />
        <input id="Submit1" type="submit" value="submit" /><p />
      </div>
</asp:Content>

An example of the data source XML is shown below:

<product>
  <feature value="01" text="Case Management" >
    <area value="011" text="Opening a Case" />
    <area value="012" text="Closing a Case" />
    <area value="013" text="Re-Assigning a Case" >
      <subarea value="011" text="To Legal" />
      <subarea value="012" text="To Supervisor" />
    </area>
  </feature>

My initial take would be to use an ObjectDataSource that loads the XML instead because it allow me to use Control Parameters for Selects.

However, I thought it would be fun to try making the XMLDataSource work… and it was not much effort. An example of the result is shown below.

 

image

First, I needed to change the page a little by adding to the first two dropdowns

AutoPostBack="True" onselectedindexchanged="DropDownList1_SelectedIndexChanged" 
AutoPostBack="True" onselectedindexchanged="DropDownList2_SelectedIndexChanged" 

The rest is in the code behind. We need to do a little “pushing” on the initial load to get the initial cascade working

protected void Page_Load(object sender, EventArgs e)
{
    if(! IsPostBack)
    {
        DropDownList1.DataBind();
        DropDownList1_SelectedIndexChanged(sender, e);
        DropDownList2.DataBind();
        DropDownList2_SelectedIndexChanged(sender, e);
    }
}
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
    XmlDataSource2.XPath = String.Format("product/feature[@value='{0}']/area",DropDownList1.SelectedValue);
}
protected void DropDownList2_SelectedIndexChanged(object sender, EventArgs e)
{
    XmlDataSource3.XPath = String.Format("product/feature[@value='{0}']/area[@value='{1}']/subarea", DropDownList1.SelectedValue, DropDownList2.SelectedValue);
}
That’s it!

Wednesday, January 2, 2013

Interview Question: What are Wait Stats in SQL Server?

This should required only a short answer, such as “It provides statistics on what SQL Server is waiting for. For example, there is a Stat for Logging (LOGBUFFER, LOGMGR_QUEUE). One of the most important ones is the wait time for writing to media (WRITELOG).” Asking for the precise name is a bit unfair – such a question would be testing rote/memory abilities and not understand of what is going on. Some more important names are IO_COMPLETION, SOS_SCHEDULER_YIELD, PAGELATCH_XX, PAGEIOLATCH_XX, etc.

 

You could ask about general types, for example: Resource Waits (i.e. internal resources), External Waits and Queue Waits. However, a poor response may easily occur if the question is not very carefully phrased --

 

However, asking what you would do to resolve a high WRITELOG or LOGBUFFER statistics is a much better question. The typical answers could include:

  • If you are using a virtual machine, make sure that data disks are passthru and not virtual disks
  • Change the RAID configuration, add more storage Devices
  • Check the bandwidth to the storage devices
  • Isolate the Log files from the database files onto different storage devices
  • Install storage devices that are faster

A follow-up question could be “How do you get the stats?” This could be legitimately answered with “I have some TSQL code that I cut and paste..”  Some people may reference Sys.dm_os_wait_stats. For an example of such code, see Brent Ozar code example or Paul Randal code example.  As an interesting aside (unfair to ask), is that this code sample works with SQL Azure.

 

A common aspect of interviews are questions that may test irrelevant knowledge. Asking a MD to explain why mercury is used in a thermometer instead of water is really not asking about he needs to know.  Asking a family practice candidate MD to describe the difference in SPECT scans between an Alzheimer's patient and a Chronic Lyme patient is similarly irrelevant. The best questions that I have ever been asked are the ones that the interviewer are currently struggling with. I have been asked a lot of irrelevant to the job questions, way too many IMHO.

Tuesday, January 1, 2013

An old SQL Server Interview Question: What are Crow’s Feet?

I recall being asked that question at an interview long ago. In the circles that I had been working we had never used that (academic) term and had been using the diagramming tools in SQL Server Management Studio(SSMS). It was simply what we used. So what are crow’s feet?

 

It is a diagramming notation which, incidentally, is not supported in SQL Server Management Studio but is supported in third party tools. Since I had been working for Microsoft’s ITG SQL Server Team for several years prior without any third party tools --- I could not return a snappy answer. The origin of this was that the early adapters moved to Oracle, so this because an attitude issue with Microsoft.

 

Today, crow’s foot notation has become the non-Microsoft industry standard in stead of SSMS infinity key notation. The comical thing is that Microsoft Visio does support crow’s foot notation. A few example tools that uses this notation are: ARIS, System Architect, PowerDesigner, Toad Data Modeler, DeZign for Databases, Devgems Data Modeler, OmniGraffle, MySQL Workbench, SQL Developer Data Modeler and Information Engineering Facility.

 

For some short academic summaries see:

The difference is shown below, my own preference is still to use the  0…n: 0…n style notation because it is far easier to read by the user. For example, when you are doing a data model review. The use of crow’s foot notation creates obtuseness (and potentially misunderstandings and thus mis-implementations).

 

Crowsfeet

 

Conclusion

I did not get the job, likely because the interviewer used a “culturally bias” question. If he had asked me to diagram out a relationship, he would have seen that I used standard Microsoft DBMS diagramming notation instead of Oracle’s.