Saturday, September 1, 2012

.NET Simple Recursive ConfigurationElementCollections

I've seen plenty of quite complicated examples of how to load recursive configuration element collections from app.config. Here's a really simple example.

I have the app.config below. You'll see that a person can have children. Each child is also a person and so each child can have children, and so on.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
      <section name="myPeople" type="NestedCustomConfig.PeopleConfigSection, NestedCustomConfig" />
  </configSections>

  <myPeople>
    <people>
      <add name="Frank" />
      <add name="Stanley">
        <children>
          <add name="Pauline">
            <children>
              <add name="Augustus"/>
              <add name="Zebedee" />
            </children>
          </add>
        </children>
      </add>
    </people>
  </myPeople>
  
</configuration>
To load this, I have the following classes:


using System.Configuration;

namespace NestedCustomConfig
{
    public class PersonConfigurationElement : ConfigurationElement
    {
        [ConfigurationProperty("name", IsRequired = true, IsKey = true)]
        public string Name
        {
            get { return (string) base["name"]; }
            set { base["name"] = value; }
        }

        [ConfigurationProperty("children", IsDefaultCollection = false, IsRequired = false)]
        public People Children
        {
            get { return (People) base["children"]; }
            set { base["children"] = value; }
        }
    }

    public class People : ConfigurationElementCollection
    {
        protected override ConfigurationElement CreateNewElement()
        {
            return new PersonConfigurationElement();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((PersonConfigurationElement)element).Name;
        }
    }

    public class PeopleConfigSection : ConfigurationSection
    {
        [ConfigurationProperty("people", IsDefaultCollection = false)]
        public People People
        {
            get
            {
                return (People)base["people"];
            }
        }
    }
}
I created a Console App for the example and have the following in Program.cs:
using System.Configuration;

namespace NestedCustomConfig
{
    class Program
    {
        static void Main()
        {
            var peopleSection = ConfigurationManager.GetSection("myPeople");
        }
    }
}
Good luck.

Saturday, June 2, 2012

Swiss Mortgage Example

In case you fancy buying a 1,000,000 CHF residential property in beautiful Switzerland:

Purchase price: 1,000,000
20% Deposit: 200,000
First mortgage 66% of purchase price: 660,000 - renegotiate every 10 (max) years
Second mortgage 14% of purchase price: 140,000 - must be paid off in (max) 24 years

5% * First Mortgage amount has to be less than 30% of your gross income

Simple!

Thursday, May 17, 2012

Old laptop running hot after Windows 7 upgrade

So, I finally upgraded my aging Windows XP laptop to Windows 7. The Windows 7 Upgrade Advisor assured me my pc had enough resources to handle the (not so) new OS. The install went fine, but I noticed that the machine was getting very hot. Installing Speedfan allowed me to monitor the temp, which was over 90C at times.

A quick look at the Performance tab of the Task Manager (while watching an excellent talk on Reactive Extensions) showed me the CPU was maxing out. Next stop was the processes tab, showing processes from all users and ordering by CPU usage. Pretty close to the top was wmpnetwk.exe.

This is Windows Media Player Network Sharing Service, which, according to the its description in Services, "Shares Windows Media Player libraries to other networked players and media devices using Universal Plug and Play".

I decided I didn't need this, especially at the expense of running my CPU at over 90C (I already have a device for those kind of temperatures: a kettle). So, I went to Services, selected "Windows Media Player Network Sharing Service", right-clicked and chose properties from the context menu, set Start Up Type to disabled and stopped the service.

Since then, the temp has reduced to between 40 and 50C. Still fairly high maybe (need to clean the cooling system probably), but manageable.

Tuesday, August 11, 2009

TOAD - file extensions and highlighting.

It’s been bugging me for a while that *.vew files were opening in TOAD without keywords being highlighted as they were in *.vw files.

This can be fixed by adding the *.vew file-extension here:

View=> Toad Options=>Editor=>Behaviour

There is a “languages” frame in the middle at the bottom of the page. Select “PL/SQL” from the drop-down box and click on the button with three dots in it.

In the “General” tab on the form that opens, you can add file extensions, so add VEW, SPS, SPB and anything else you want formatted.

Hope this is of use.

Friday, June 12, 2009

NUnit Tip

When installing NUnit, choose the "complete" installation option, otherwise the tests for NUnit itself aren't installed...and your brain will fill with porridge.

Cruise Control

I spent a couple of days this week configuring NAnt and Cruise Control to build one of my projects. It's all running on my dev box, until I can find a server to run it on. Not ideal, I know.

I configured Cruise Control while running the ccnet.exe utility which handily outputs to a command window.

When I switched to using the Cruise Control Service proper (ccservice.exe), running under a user id with all the necessary permissions to access my VSS (don't start on the VSS debate!) database, I got the following error:

"No VSS database (srcsafe.ini) found. Use the SSDIR environment variable or run netsetup. "

So, I added the environment variables. And I still got the problem. I tore the remains of my hair out and my brain filled with porridge.

Eventually, I found the problem. I'd specified a drive-mapping rather than a UNC in the SSDIR tag in ccnet.config. The user running ccnetservice.exe has no knowledge about the drive-mappings on my machine.

The tag should look something like this:

< ssdir > \\Server\Directory\AnotherDirectory\Source Safe < /ssdir >

and NOT something like this:

< ssdir > V:\AnotherDirectory\Source Safe < /ssdir >

Hope this helps someone.

Tuesday, May 26, 2009

Disecting the disection of HardRock Cafe Memorabilia - Part 1

It all started when a friend showed me the Hardrock Memorabilia site. "That's cool," I thought, "I could build myself a nice photo website like that." So then I set about investigating how it worked. 

A quick search on the web led me to Wilfred Pinto's blog and his fantastic recreation of some of the Hardrock functionality. Thanks, Wilfred!

I downloaded the source and, fairly soon, I'd got it working with some of my own pictures. However, there were a couple of parts of the code that I just didn't understand. Armed with a brain made of porridge, I attempted to solve the problems.

Here's the first part that I've been tearing my hair out over:

1. How are the coordinates, width and height calculated for the new Rect object in GetSubImageRect?

Here's the code (thanks, Wilfred P): 

Rect GetSubImageRect(int indexSubImage)
{
   if (indexSubImage <>= msi.SubImages.Count)
return Rect.Empty;
MultiScaleSubImage subImage = msi.SubImages[indexSubImage];
double scaleBy = 1 / subImage.ViewportWidth;
            
return new Rect(-subImage.ViewportOrigin.X * scaleBy,-subImage.ViewportOrigin.Y * scaleBy,
1 * scaleBy, (1 / subImage.AspectRatio) * scaleBy);
}


I created a new DeepZoom project that contained only the functionality I was interested in and worked it out.

We want to create a rectangle the coordinates, width and height of which are "logical" or normalized to find out if the rectangle contains the logical point we're testing. For a definition of "logical", read MSDN.

I read Gerhard Lutz's blog. This guy knows his stuff, but it was too much for my peanut brain and I couldn't quite get it straight. If anyone thinks they can explain it to me in terms I'd understand, please get in touch. 

Luckily, Jaime Rodriguez had written something about subimages, which really helped. 

This is what I found out,it seems to work and it makes sense to me:

1. The SubImage.ViewPortWidth is relative to the the width of the MultiScaleImage control. 

For example, if SubImage.ViewPortWidth = 1 then it takes up the whole of the multiscale image width. If SubImage.ViewPortWidth = 2 then it takes up 1/2 the multiscale image width.

2. The SubImage.ViewPortOrigin.X and .Y values are relative to the logical width of the SubImage with the added twist that coordinates within the MultiScaleImage are negative.

Here's an example of a MultiScaleImage control containing 10 subimages. The images are numbered 0 to 9 from top left to bottom right. I added the numbers after I'd taken a snapshot of the page. Click on the image to see a bigger version.



Here's some info about each image. Click on the image to see a bigger version:


So, for image 0, ViewPortOrigin = (0,0). This means the top left hand corner of the SubImage (the ViewPortOrigin) is in the top left hand corner of the MultiScaleImage.

Let's create the rectangle for image 6.

Image 6 has ViewPortOrigin = (-2.5,-1.5).  The minus sign tells us the ViewPortOrigin coordinate is to the right and down of (0,0). But how much? Let's work it out.

As mentioned above, the ViewPortOrigin is relative to the logical width of the SubImage. The logical width of SubImage = 1/SubImage.ViewPortWidth. 

In the code example:  ScaleBy = 1/SubImage.ViewPortWidth.

In this case, ScaleBy = 1/5.5 = 0.181818181

So, SubImage.ViewPortOrigin.X as a logical point along the X axis of the MultiScaleImage is:

-1 * -2.5 * 0.181818181 = 0.4545454.

(We multiply by -1 otherwise the coordinates will be outside the MultiScaleImage. The negative coordinates are only used in the ViewPortOrigin of the SubImage.)

The Y coordinate of the rectangle will be:

-1 * -1.5 * 0.181818181 = 0.27272727

The width will be simply 1/SubImage.ViewPortWidth = ScaleBy = .181818181

The logical height is a little more complicated.

AspectRatio = Width/Height, so Height = Width/AspectRatio.

Logical Width = ScaleBy,
So, Height  = ScaleBy /AspectRatio  = 0.1818181/0.666666 = 0.272727

If you want the pixel coordinates (again, see MSDN for the definition), you can multiply the results of the above by the actual width of the MultiscaleImage.

For example, the pixel X coordinate of the rectange would be:

 0.4545454 * 400 = 181.818181