Day at the Office: Performance

I am working on a ticket where I have to augment data returned from an external system with some local overrides, without adversely affecting performance.  

Running the screen, it seemed a bit tardy to begin with.   So I pulled out one of the tools I love to use: a profiler.

I use the Ants Performance Profiler.  I paid for it with part of my Christmas bonus.  While I am a salaried employee, and my employer provides me with lots of stuff (awesome computer, pop, snacks, coffee, ReSharper, MSDN), there are additional things that I choose to use because I like who I am with them.  These include Ants, TeamViewer, nDepend, Beyond Compare, Fences, and VmWare, and a 3rd monitor.  Not all are paid for yet – two more christmas bonuses should cover it.

image

Well, that’s interesting.   Curiosity strikes:  What are those spikey areas about?  What’s going on?   How long is the initial query taking?  How long are the webservice calls taking?   If I add on to the end of the webservice call, how much would that grow?

Spike #1 – Query + Initial Screen Draw

Action: highlight the area and see where the time was spent.  If you’ve never seen this before, there’s some Windows GUI app running stuff to get out of the way:

image
image

  • The green highlights in the top image are times when the method under the cursor was fired. 
  • The stack trace is not so scary once you understand the internals of a running program a bit.
    • “A” is the part of the program which receives almost any kind of “this work needs to be done asynchronously” call.   This means Execute.OnUIThread(),  drawing events, bindings, etc – almost all get serviced here. 
    • “B” is where Task.Factory.Start() things get serviced.
    • “C” is any point where input needed to be handled, and ended up making the app do something.  Mouse movement, hover, clicks, etc – and part of whatever they ended up triggering.  That is what is highlighted in green
    • “D” we haven’t drilled into yet.
  • Unfortunately, if you Async a call from A to B, they show up in different parts of the performance stack traces (at least as of Ants version 7)

Drilling further into “D”:

image
image

  • Ah, I’ve seen this before.   “Measuring” usually means a grid has been set to “auto fit columns” mode – and as its drawing things, its figuring out how large they want to draw, how much to resize, and then redrawing.  

What about the actual query to get the data?   I found it way down in here (this time in bottom-up mode):

image
image

Wow, that was a lot of blurring.   Point being:  the query is fast, rendering the results in the grid is slow.

There’s another blog post that could be written here.  The stack trace above goes from “Get me stuff” to a IQueryable to a Project to … What, a Stored procedure?   Yep, it does, and it went from 25 seconds down to 2 seconds.  Sometimes, EF does not win.  

Spike #2: The Flat Plains of Update

imageimage

  • This is the result of getting “new information” from the external service, and trying to update the grid. 
  • What you are seeing is the NotifyOfPropertyUpdate() => saying “hey, UI, update yourself”  .. and waiting for the update to happen.   
  • -update- after a day of dinking around in this code, its simply a size issue.  There are 15000 rows of data in the grid – and we are updating every single one, with 4 columns of new data – and each each update “paints” itself on the screen.    This takes a while.   I couldn’t find any way to optimize this other than delaying the entire screen till we have all the data (ie, don’t paint twice).

Lets Try To Remove AutoFit: After Changes

before:

image

after removing AutoFit:

image

Not very different. 

image

Welcome to performance optimization.   Sometimes, you think you have found a smoking gun, but you haven’t.  I might have squeezed a 10% out of that, maybe.

I must now leave this blog post and really fix some things.   And get on with the original task, which was to add some local database overrides to an external web service call without making the system significantly slower.

-update- Its now the end of the day, and I have the additional lookup code written.  Here’s the impact:

image

  • The green highlight is the call to the external web service(s) (async) and the subsequent updating of the columns in the grid.
  • The pink/purple is the additional code that I wrote that patches up values from the local database.

Good enough. 

Day at the Office: A Tale of Testing

imageTL;DR:  Its really awesome when you understand the customer’s business language and can do thorough testing for them and document it.

I’ve been working on a bug for the last few days, which involves some math, and positive vs negative signs and such stuff.   Basically:

  • Customer sent me a screenshot where the math was obviously not working.
  • We figured out what was going on (boundary case not handled), and handled it.  

Normally, we’d be done at that point.  Except, this customer does not have a dedicated QA department; we are the first line QA department.  So.. we decided to be thorough.  Hence, this Test Document (screenshot; intentionally small so that details are illegible)

We posted the testing results of 7 types of things + 5 states of things, and highlighted any suspicious behavior (in yellow) for confirmation from the client —

And we have a brilliant customer, who gave us prompt feedback: (in blue)

Which we then fixed, in purple.

Time Creep

This 2-3 hour bug has now become a 2-3 day bug.   I feel a bit guilty about that, yet – if these situations had been discovered in the future, that would have been more angst, spread amongst more people; I’m glad we could figure this out now rather than later.

Also, by doing this testing and documenting it, I’m generating a snapshot-in-time of how the app is supposed to work. 

Unit Tests?

The only thing that would make this even more awesome would be to do these as unit tests.   But that would have been 3-4 days instead; also, we’re trying to wrap this project up.   Also, the customer doesn’t speak “unit tests”, but the customer definitely speaks “screenshots of the app”, so we’re choosing to converse in the latter language.

But how did it get Borged up to begin with?

I had shared the content of this post with a friend, and he asked the obvious question – why wasn’t this caught sooner?   The app has been used in production for over a year now. 

Reason Part 1:  this code (recalculating estimated cash balance in an account) was recently rewritten for performance optimization.  The old code (before my time on the project) was huge, complex, not documented, and slow – it was actually used for generating charts forecasting cash balance out into the future, and was designed to handle one portfolio at a time; the new code could do things in batches of portfolios, maximizing lookups of shared stocks and options, etc.    When we did the optimized calculations, we tested everything that we (and the client) knew of at the time.   No regrets.

Reason Part 2:  My client is also small enough that they don’t have a dedicated business guy who documents every rule around every calculation.   There’s a wealth of “common shared knowledge” amongst several people.  While we, as developers, try to understand that as much as possible, there’s a reason they do what they do very well – that stuff is complex.   Instead, our goal is to get 80%-90% close, “usable”, and then if there’s gaps remaining, those will get revealed, and patched later.  Reference concept Minimum Viable Product.   (Only doable with in-house applications; externally facing applications in a marketplace need more attention on polish and completeness.)

Frustrated about 3D Stuff

General feeling of frustration tonight (time of writing: Friday 5/9).  Hard to put into words.  But I could draw it.  (might need to zoom in)

3d printing roadmap

  • The Green things are things that I have figured out.
  • The Red things are things that definitely have not worked for me.
  • The Yellow Things are things I want to be able to to.
  • The Orange things are things that I haven’t yet figured out.   They depend on each other, there is usually a chain.
  • I forgot about Minecraft Prints.  Those fall under “Color print that I might could afford”, pretty much.

Latest Frustration Tonight

It turns out a Agisoft PhotoScan project file (.PSZ) looks like a ZIP file, with a doc.xml, which has the below structure – so I could write code to hunt through 1420+ images, and select the best 50, spread out.

image

The code looked like this (sorry, no LINQ, going old school here, command line parameters, etc)

image

Except that the PSZ not really a Zip file.  When I tried to stuff the modified doc.xml back into the .PSZ file, it came out as being corrupted.    Dead End?  Retry with 7Z?   Extra metadata?  older compression format? ?

I guess what I have is code that tells “which cameras I should enable”.   That’s workable, except that I need to grab frames/image[@path] so that a human could identify it. 

Future: Maybe I could write code to read the video, figure out the quality of the frames, and only extract the best frames?

Also: the $3000 version of Photoscan has a Python Scripting interface.  Sorry, I’d rather buy a color 3D printer than that.

However, good news, it looks like I might finally have a lens profile for a GoPro Hero3 in 720p (x120FPS) Wide mode.  I had to play with the focal length, for some reason numbers like 0.1mm and 2mm work way better than 7mm that folks advertise.   More to be proven later.

Slicing and Dicing with OpenSCAD

In my quest to make a cool coaster, I wanted a way I could slice up a model so that each face could be printed, well, “face-up”, so I don’t run into problems with overhangs and supports and stuff gumming the works.  I would then glue the model together later.   (In the case of Coasters, I can also swap filaments and have the design “pop” on each side)…

In the process, I learned some OpenSCAD:

  • F5 = “quick”, F6 = slow and build
  • No such thing as “export this object”, it just builds and then you can choose to export everything.
  • variables are lexically scoped, ie, more like constants.  There are some dynamic variables as well.
  • I had to remember some algebra.
  • I applied some D.R.Y.

Here’s the result as applied to http://www.thingiverse.com/thing:60728 – first in “ShowMe()” mode:

image

And then SliceEverything() mode without the full fledged CSG operations:

image

And then SliceEverything() in the way that I could export an STL:

Yeah, that crashed.   It was too complicated.  I hate to take out the // Slice Everything, and instead, here’s just the front and an ear, exported to STL, and viewed in NetFabb.

imageimageimageimage

Note: Its NOT fast, when doing the full build (F6).  It also crashes less if run from command line – apparently the crash is during rendering to the screen?)

Show Me The Code

Since its getting a bit long, I’m linking to github below; but this is what it looks like, approximately:

imageimageimage

link to code at github

update:  I’ve tried to use this approach for several things now, and … its very fragile.  So fragile, that I have successfully used it to create a print.  Almost every model is “too complex” and fails at render.  I might need to try a different language.. something that is rock solid. 

Day at the Office: Burndown on Ever Increasing Scope

When given a client who has a lot of work that needs to be done.. and as the work progresses, other ideas form, older ideas lose priority, etc – how does one show progress?  

The specific statement that spurred this was “You guys were supposed to be done N time ago”.  True, for the scope from N-1, the date agreed to was N.  How can I show you how things have changed since then?  How can we agree on when things will actually get done?

A Solution:  Add Months to the Burndown

image

What I started to do is keep track of work by when it was introduced into the queue.  Each month got its own mini-burndown.  In the picture above, pay attention to the spaces between the lines, not the lines themselves.  

I like that this graph shows:

  • That work is being done!     You can see work getting nibbled away from the top,  showing up at the bottom.
  • That I can calculate a velocity (slope of the green line)  — in fact, i can calculate a “slowest” and a “fastest” velocity.   Reality was somewhere in the middle.

An additional thing was to somehow show time taken by production issues – unplanned, un-estimated things.   Overall, quite slight – less than 10% of the project? 

Improvements

  • I tried to show work in progress on this graph; it was not useful.   I would not do that again; it would be better to have a mini graph showing ins and outs of things entering and leaving development.  If that was even needed.
  • I would probably put unplanned stuff not-stacked, so that changes in it could be seen easier.
  • If there was some way i could have the month retain its color on the “done” side, that would be awesome.  Then we would also be able to see “estimate vs actual” (the bottom part is all based on time reported, whereas the top stuff was based on estimates).

Before I let this post, I need to show it to the client to ensure that I’m not divulging too much information.

Day at the Office: I’m Optimizing UX with SPEECH

Note: Say the title of this post in the same way as you would  “She Blinded Me With Science”

image

The Problem

The customer has a screen, which is used for data entry.  The source of the entry is various pieces of papers with scribbles on them.  On observing the person doing the data entry, what I saw was:

  • Look at paper to see WHO it was for
  • Look at screen to find the same.  Usually its the next one in order
  • Switch to Mouse
  • Click once to select the who
  • Click to select the thingies inside the who
  • Click the button to start the data entry for the who
  • Look at paper
  • Find the number
  • Switch to keyboard
  • Type in the number
  • Look at screen
  • Verify number
  • Press Enter to save
  • Look at paper
  • Move Hands to Paper
  • Mark Paper as done.
  • Move Paper Aside
  • Look at next paper.

Ouch.  We could do better.

Our (Final) Proposed Solution

I think its pretty cool, I don’t know yet if the user(s) will adopt it, but this is what we came up with.

  • User can keep right hand on numeric keypad, and arrow up to the first entry.  (they sort paper and computer entries to match beforehand)
  • Numeric / (on the keypad) starts entering for the currently highlighted row (even if it not yet selected)
  • As the data entry screen opens, the computer “speaks” the relevant info about what is being entered.  This is so the user can keep eyes on paper, while listening to verify that the right row was selected
  • Still keeping eyes on paper, user can type in the numbers on the keypad, and then press numeric + (on the keypad) to “speak” the numbers that were entered, for verification, if they want.
  • In case the user wants to look at the computer screen, we also made the window bigger, text larger, and used color to highlight the various corroborating pieces of information.
  • If all is good, user hits enter on the numeric keypad to save, and now the next row is highlighted.

Blocked

This is well and good, except, this is what happened in testing:

  • /  34.5 +  <enter> / 45 <enter>
  • When the user got to the second /, the hotkey did not fire.

I spent many hours trying to figure this one out.  Its complicated, I still don’t know the full answer, but it has to do with a DockedWindow, a control suite, a Busy indicator,  a Ribbon suite, sub-ribbons, and document panels, and when the modal popup went away, focus did not return to the correct window. 

Bottom Line: all my attempts to set focus were ignored.  Seriously.  I even bound a hotkey at the Shell level (the whole application) “F10” to fire code that should set the focus back to the correct window.. and.. nothing.

This problem also extended to any window.   Any window, when it first came up, did not have focus, so any hotkeys bound inside that window, would not fire.   Till it was clicked in.  Then it was okay. 

Hacked Solution

I could still capture hotkeys via the Shell, so this is what I did:

  • Shell catches PreviewKeyDown
  • Shell looks at current active docked window (since it hosts the dock control, this is easy)
  • If current active window implements IReallyWantKeyDownStuff, then call the YoHeresAKeyForYou(). (Names changed because i don’t have intellisense writing at home, but you get the idea).
  • My window receives this, and if it was Numeric/, then it fires the button that starts the data entry process

I used the same code to also wire some other hotkeys for some other screens.

Office Visit Still Needed

I hope to (soon) visit my client’s office in person, and sit down with the folks who would use this “enhancement”, and show them what I had thought.   As someone once told me, I have to be careful how many strings I have attached to this:  I have to be okay with them taking my awesome idea and putting it in the trash.  No strings attached.  So I’m blogging about its coolness now, in case its a flop, because right now, I think its pretty cool.

Day at the Office: Syncing Systems

I have been on a coding adventure for the last two days. 

Customer has a system, which involves holdings, and then proposed trades on those holdings. However, there’s also a master system that sends a new list of holdings on a daily basis.  The master system does not know about the proposed trades, it says “here’s the new list”.

image

The algorithm when updating the list of holdings to the new holdings went like this:

  • delete anything that doesn’t have a proposed trade on it
  • copy in the stuff from master, creating new ones, except…
  • if an existing holding is found, instead of creating a new one, update the holding to look like what the master says it should (with various keys to try to grab the right one)

The Problem

There was a holding of Quantity = 20 that had proposed trades of –10 against it.  The incoming holdings were of quantity 3 and 15.   It updated 20 to 3, causing a math imbalance in the system.

Further problem on more investigation

It was also iterating the incoming list, so if I had trades against a holding H1, and H1 (or something like it) was not included in the new list, then the trades would get left behind against a stale holding.

My Solution Take 2

  • Delete any holding without a proposed trade on it
  • Figure out our maximum id so far
  • Always insert all data from master as new.   (Now we have duplicate copies)
  • Walk through all the old holdings and proposed trades; try to match the proposed trades up against the new holdings
    • If no match found, log it and delete the proposed trade
  • Having moved all the proposed stuff over to a new parent, now delete all old holdings <= maximum id (no more duplicates)

Why I thought it was Clever

Suppose the load fails. 

Since I’m only either updating or deleting proposed trades, I will not have any duplication of proposed trades.

Since I’m deleting all holdings prior to where I started inserting the new holdings, as long as I successfully complete a load, I will delete any old bad data from a previously failed load.

The Matching Algorithm

The general idea is:  Sort “available buckets”, sort “Proposed Trades”, and then start matching trades to buckets.

  • imageI tested this out on paper – as in, I cut out little pieces of paper, and tried the different options; I determined sorting low to high on buckets and high to low on trades was my best bet. 
  • I used a fit option of f(x1,y1,x2,y2):decimal to give me, for any trade, which bucket it would best fit in (after sizing was taken care of).  (the X’s and Y’s are acquisition dates and execution prices, both of which can be “touched up” on the master system, making an exact match every time non-feasible)

To Translate This To Code

Because the matching stuff could get complicated, I made its own little command for it (see command-query separation).

image

I was not shy about creating more DTO’s for the specific inputs and outputs needed by this command. 

image

I wrote enough tests to verify that it was doing the right thing.  When I do unit tests, Iassume only developers will read them, so I don’t spend a lot of time making the names super-descriptive.  Some-descriptive, yes, not super-descriptive.

Embedded image permalink image

And then I wired it up.   Turns out, I wired it into location #1, and that turned out to not work – transactions, entity framework, new transactions, missing ID’s, etc.   So I ended up wiring it into location #2 (after the fact), and that worked a lot better.   Good thing I had black-boxed its meaning, it was easy surgery.

Breaking the Recursive NotifyOfPropertyChange()

Another problem I ran into in the WPF world were controls whose side effects led to a endless loop of updates:

image

The outer one is called an “Order”, and the inner one is called a “Trade”

The problem goes like this:

  • Click on the outer one to select everything
    • Inner ones turn on
    • But clicking an inner one, if all of them are turned on
      • selects the Outer one.
        • recursive loop to infinity.

There’s probably some really crazy way to set this stuff up (there seems to be no end of the kind of hoops people will jump through for WPF), but here was my solution:

        private bool _onOrderCheckedFiring; 

        private void OrderChecked(CheckBoxListItemThreeState<OrderListItem> obj)
        {
            if (_onTradeCheckedFiring) return; // we are a result of a trade check, so don't do anything.
            try
            {
                _onOrderCheckedFiring = true;
                foreach (var t in obj.Value.AllTrades)
                {
                    t.IsChecked = true;
                }
                NotifySelectedOrdersChangeProperties();
            }
            finally
            {
                _onOrderCheckedFiring = false;
            }
        }
        protected virtual void OnTradeChecked(CheckBoxListItem<HoldingBase> item)
        {
            if (_onOrderCheckedFiring) return; // result of order check, so don't do any more logic. 
            try
            {
                _onTradeCheckedFiring = true;
                var theOrder = Orders.FirstOrDefault(o => o.Value.Order.OrderID == item.Value.OrderID);
                if (theOrder != null)
                {
                    var areAllTradesChecked = theOrder.Value.AreAllTradesChecked;
                    var newState = theOrder.IsChecked;

                    if (areAllTradesChecked)
                        //all trades are checked; set the order checkbox to true
                        newState = true;
                    else if (theOrder.Value.AreAnyTradesChecked)
                        //not all trades are checked, but some are; set the order checkbox to indeterminate
                        newState = null;
                    else if (!theOrder.Value.AreAnyTradesChecked)
                        //no trades are checked; set the order checkbox to false
                        newState = false;

                    // ReSharper disable RedundantCheckBeforeAssignment
                    //NO, ReShaper, this is NOT a redundant check, because if the value is the same, I don't
                    //  want the notification events firing.
                    if (theOrder.IsChecked != newState)
                        // ReSharper restore RedundantCheckBeforeAssignment

                        theOrder.IsChecked = newState;

                    theOrder.Value.NotifyAreAllTradesCheckedChanged();
                }
                NotifySelectedOrdersChangeProperties();
            } finally {
                _onTradeCheckedFiring = false;
            }
        }

 

This code is not complete, and it was reformatted to reduce the number of lines to paste.  Basically, I just flag that I’m doing something intricate in one routine, and in the other routine, I see if the intricateness is happening, and if so, I DO NOT fire the thing that would make it recursive.

I’m almost done with this WPF project, I’ll get to go back to the Web World probably next week.  Before I fully forget WPF, I would like to make a chart of all the stuff I’ve learned similar to what I did for MVC.

VisualTreeHelper

I seem to have gotten away from posting any coding things on this blog.   At first I thought its because I really haven’t done anything exciting; most of the work has been “figure out customer’s need, create something that solves that need”.   Then as I dug deeper, I rediscovered some fun things that I had created along the way:

The Problem

There’s a screen with a list of grids (this is a stock trading app) – when tabbing out of one grid, it needed to get to the next grid.  I also needed to jump left and right from master to detail easily.   (Sorry about all the blurring, but those were real numbers):

image

The screen, in and of itself, was a solution to “how to balance a portfolio to get it back in line with sector totals easily”.   The user could enter a proposed change in a holding, see how the math worked, and then click save positions to generate all the trade(s) necessary to make it happen.

Solution

I needed to write code that would take the grid that was currently focused, figure out what the next grid was, and focus there.    when solved, it looks like this:

image

Oy! What is this?  It’s a helper function that I wrote.   Basically, Starting with a known visual element, I look for “stuff that I’m interested in” (if the lambda returns true, then I’m interested in it):

image

This cuts down the (very) complicated visual control tree (see: http://www.codeproject.com/Articles/21495/Understanding-the-Visual-Tree-and-Logical-Tree-in) down into something much more manageable (this is the output of the Dump() function defined below with some additional comments thrown in)

image

Here’s the source that does it:

        public static VisualTreeInterestingNode GetInterestingNodes(this FrameworkElement topDependencyObject, Func<FrameworkElement, bool> isInteresting)
        {
            var timer = new Stopwatch();
            timer.Start(); 

            var topInterestingNode = new VisualTreeInterestingNode() { FrameworkElement = topDependencyObject, Parent = null };

            var nodesToVisit = new LinkedList<Tuple<DependencyObject, VisualTreeInterestingNode>>();
            nodesToVisit.AddLast(new Tuple<DependencyObject, VisualTreeInterestingNode>(topDependencyObject, topInterestingNode));

            while (nodesToVisit.Any())
            {
                var a = nodesToVisit.First();
                nodesToVisit.RemoveFirst();

                var currentDependencyObject = a.Item1;
                var currentInterestingNode = a.Item2;

                int childCount = VisualTreeHelper.GetChildrenCount(currentDependencyObject);
                for (int i = 0; i < childCount; i++)
                {
                    var childDependencyObject = VisualTreeHelper.GetChild(currentDependencyObject, i);
                    if (childDependencyObject == null) continue;

                    var childFrameworkElement = childDependencyObject as FrameworkElement;

                    if (childFrameworkElement != null)
                    {
                        if (isInteresting(childFrameworkElement))
                        {
                            var b = new VisualTreeInterestingNode() { FrameworkElement = childFrameworkElement, Parent = currentInterestingNode };
                            currentInterestingNode.InterestingChildNodes.Add(b);
                            nodesToVisit.AddLast(new Tuple<DependencyObject, VisualTreeInterestingNode>(childDependencyObject, b));
                        }
                        else
                        {
                            nodesToVisit.AddLast(new Tuple<DependencyObject, VisualTreeInterestingNode>(childDependencyObject, currentInterestingNode));
                        }
                    }
                    else
                    {
                        nodesToVisit.AddLast(new Tuple<DependencyObject, VisualTreeInterestingNode>(childDependencyObject, currentInterestingNode));
                    }
                }
            }

            timer.Stop(); 

            return topInterestingNode;
        }

And the VisualTreeNode class that the result is in:

    public class VisualTreeInterestingNode
    {
        private List<VisualTreeInterestingNode> _all;

        public VisualTreeInterestingNode()
        {
            InterestingChildNodes = new List<VisualTreeInterestingNode>();
        }
        public FrameworkElement FrameworkElement { get; set; }
        public List<VisualTreeInterestingNode> InterestingChildNodes { get; set; }
        public VisualTreeInterestingNode Parent { get; set; }

        public List<VisualTreeInterestingNode> Flatten
        {
            get
            {
                if (_all != null) return _all;

                _all = new List<VisualTreeInterestingNode> { this };
                foreach (var child in InterestingChildNodes)
                    _all.AddRange(child.Flatten);

                return _all;
            }
        }

        public StringBuilder Dump(StringBuilder prefix = null, StringBuilder result = null)
        {
            if (prefix == null) prefix = new StringBuilder();
            if (result == null) result = new StringBuilder();

            result.Append(prefix).Append(FrameworkElement.GetType().Name);
            result.Append(" ").Append(FrameworkElement.Name);
            result.AppendLine();

            var l = prefix.Length;
            prefix.Append("  ");
            foreach (var node in InterestingChildNodes)
            {
                node.Dump(prefix, result);
            }
            prefix.Length = l;
            return result;
        }
    }

Code Louisville 2.0, Shelving Various Things, New Tech

Tonight was my first night of mentoring at Code Louisville 2.0.  I don’t know if I’d mentioned it before; I volunteered to be a mentor in a program that the city is putting together.  The City’s viewpoint is, we need more skilled IT people (there’s a shortage).  My viewpoint is, I get to help somebody who wants to learn, to learn something, is good with me.

It went pretty well.  The program is using Treehouse for the source of instruction; the Louisville Free Public Library made a deal with Treehouse to make it available to all library patrons.    The quality of the instruction is pretty decent, and it takes the stress off me for being a source of instruction.  Instead, i just need to share my experience with folks.  Some of them are right at the level of the instruction, some are much more advanced.  It keeps it interesting.

To keep the mentoring / labs interesting, I’m trying to do a mini version of a standup at the start, and then circulate amongst everybody to keep things personal.   I’m trying to keep a live document editable by all going as class notes / links / what did we decide.  I hope its a good example for them, of how to use technology to collaborate.

As a result, though, I’ve had to shelve my architecture build.  I simply don’t have the 4-6 hours it would take for me to go to LVL1 and print out the 3D parts of my house model.  Each part.   Times 8 parts.   Times 4 levels.  Without being a hog.  

My current geeky project inventory:

  • A family project: old 35mm slides converted into slideshow project for delivery at Thanksgiving (where I’ll record everybody’s commentary about what the slides were about)
    • I need to find decent screencast recording software that will let me create a DVD later.  I think I’ll be trying SnagIt.
    • Planning on using Picasa as the presentation vehicle.  My wife has already scanned in all the slides from the negatives.
  • One more birthday song, for my stepson, coming up in December
  • One last soccer banquet slideshow, as requested by one of the kids I know.  He’s a good kid, and yes, I’d be honored. To be delivered probably late November or early December, i don’t know yet.

I’ve also had an infusion of new tech into my life:

  • Samsung_ATIV_Smart_PC_Pro_700T_35511640_06_610x436[1]A Samsung 700T that I got off a co-worker at about 50% of the list price.  This is a Windows 8.1 (thanks Anthony!) tablet device with a keyboard that makes it pass off as a laptop pretty well.  I’m writing this blog post on it.   However, while in tablet mode, the near field pen thingy works perfectly.  It even does the “hover” thing that mice do, that I really miss on the Apple.    And I’m getting used to the flexibility of reaching up and touching instead of trying to force the mouse to get to a certain spot on the screen.
  • A whole house water pressure regulator to cap water pressure at 75 psi.   What was happening was spikes up to the 150’s, which caused the pressure relief valve on the tankless water heater to dump scalding hot water onto the concrete basement floor.

Running wise, I (barely) ran my last half marathon of 2013 (time: 2h48m).  Due to a calf injury, i could not train much – my longest run the month prior was 5.5 miles – but thanks to Mr. Calvin Spears of Occupational Kinetics, I got put back together.  They also used a cool app – it seemed to be called SparkLines, but i can’t find it anywhere – to measure me while I was running, and detect that my form is lop sided when I’m in my right foot.   Good stuff to know.   They also say they can make me faster. 

My running schedule is currently clear of all races.  I intend to sign up for the Polar Express series (3k, 4k, 4mi) which runs Dec-Jan-Feb, as a way to have a goal to stay in shape over winter.