- I used a free trial of RazorSQL for this - it's ok. Nothing to scream about, IMO, compared to PgAdmin III which I'm used to for this sort of thing.
- Extract the data from your db backup with a query like: SELECT title,artist,album,playcount,score FROM songs WHERE score > 0;
- Export the data to a tab-separated file
- Convert it to a bunch of update statements with a regex
- First replace all ' with ''
- Then s/{.*}\t{.*}\t{.*}\t{.*}\t{.*}/UPDATE songs SET playcount = \4, score = \5 WHERE title='\1' AND artist='\2' AND album='\3';/
- Run the resulting statements on your live database. I believe Clementine needs to not be running when you do this.
Monday, May 23, 2011
Migrating Playcount info in Clementine
Recently discovered Clementine, a fork of Amarok which used to be my music player of choice when I had a functioning linux box. It's been great. As it happens, I had to dump my database and re-scan my music collection - which causes all playcounts and scores to be lost (and other stats which I care less about). Here are the steps I took to restore them. Probably is a way to do this with less steps.
Monday, April 25, 2011
Spokane Hospitals vs Medicare statistics
Via this post from the Sunlight Foundation - http://reporting.sunlightfoundation.com/2011/medical-errors-2/ - I thought I'd see how the Spokane hospitals stack up in screwing up. I filtered each of the datasets to Spokane and sorted by name, not rate. Read the article for any disclaimers on the content of the data.
Falls and Trauma
Blood Infections
Urinary tract infections
Bed Sores
Poor Glycemic Control
Foreign objects left in body
Our hospitals each reported zero Air Embolisms and Wrong blood type.
Falls and Trauma
Blood Infections
Urinary tract infections
Bed Sores
Poor Glycemic Control
Foreign objects left in body
Our hospitals each reported zero Air Embolisms and Wrong blood type.
Wednesday, April 20, 2011
C# 4 Dynamics and XML
I've seen a couple of cool libraries for using dynamics to magically access your JSON. I knew similar things must be available for XML, and went looking. At this point, my usage is focused on read-only access to xml, of varying styles. Values may arbitrarily be in attributes or child nodes.
The two that I found that and decided to evaluate were Anoop Madhusudanan's ElasticObject and Aaron Powell's Dynamics library.
I set up a test application looking to evaluate performance and syntax. I accessed a handful of nodes, including one array of nodes and it's children. For the hand-built version, I set up a simple set of objects with simple properties and wrote code to extract values from XElements.
I had a bit of trouble with the API for the Dynamics library, but I saw some performance promise, so I went ahead to make modifications and support my needs. I went ahead and forked the project on bitbucket to share my changes here.
For the performance check, my Hand-Built code ended up at 6 milliseconds, Dynamics at 75 ms, and Elastic at 237 milliseconds (I pre-loaded the xml into an XElement and timed the parsing). So, the tradeoff here is time spent coding vs runtime. I don't expect my real usage to have a significant impact on the user's experience, so I'm ok with Dynamic's 12x slowdown for now. If it becomes a problem, I'll have a nice bottleneck to remove for version 2 :).
Here are some syntax comparisons:
The two that I found that and decided to evaluate were Anoop Madhusudanan's ElasticObject and Aaron Powell's Dynamics library.
I set up a test application looking to evaluate performance and syntax. I accessed a handful of nodes, including one array of nodes and it's children. For the hand-built version, I set up a simple set of objects with simple properties and wrote code to extract values from XElements.
I had a bit of trouble with the API for the Dynamics library, but I saw some performance promise, so I went ahead to make modifications and support my needs. I went ahead and forked the project on bitbucket to share my changes here.
For the performance check, my Hand-Built code ended up at 6 milliseconds, Dynamics at 75 ms, and Elastic at 237 milliseconds (I pre-loaded the xml into an XElement and timed the parsing). So, the tradeoff here is time spent coding vs runtime. I don't expect my real usage to have a significant impact on the user's experience, so I'm ok with Dynamic's 12x slowdown for now. If it becomes a problem, I'll have a nice bottleneck to remove for version 2 :).
Here are some syntax comparisons:
Attribute Access | |
Hand-Built | if (t.MizConfig.InstrumentPlatform != "TC") |
ElasticObject | if (t.MizConfig.InstrumentPlatform != "TC") |
Dynamics plus mod | Multi-level nesting was not possible as written, MizConfig was returning a string. Changed code to allowif (t.MizConfig.InstrumentPlatform != "TC") |
Iterating multiple same-named elements | |
Hand-Built | foreach (var ch in t.MizConfig.HWChannels) |
ElasticObject | foreach (var ch in t.MizConfig["HWChannel"]) |
Dynamics | foreach (var ch in t.MizConfig.HWChannels) |
Accessing Value (non-iterator) as a double. Note: hand-built is able to hide extraneous nodes from me | |
Hand-Built | d = t.PusherConfiguration.MaxForwardSpeed; |
ElasticObject | d = double.Parse(~t.PusherConfiguration.Speeds.Record_Speed.Max); |
Dynamics | d = double.Parse(t.PusherConfiguration.Speeds.Record_Speed.Max.Value); |
Dynamics plus mod | d = t.PusherConfiguration.Speeds.Record_Speed.Max.To |
Conditionally dealing with optional children | |
Hand-Built | if(xelement.Element("YoMama") != null) during parsing |
ElasticObject | if (~dyn.MizConfig.YoMama != null) |
Dynamics plus mod | Didn't find an easy was as implemented, probably would have had to do dyn.MizConfig.Element.Element("YoMama") mixing in XElement access. Instead, I modified the code to allowif (dyn.MizConfig.YoMama != null) |
Tuesday, January 04, 2011
Updates to Kent Boogaart's Resizer control
I've used and abandoned the Resizer control a few times over the last couple years for various reasons. This time it seems it will be finding a permanent home in one of my apps. I had to make a modification to it and Blogger says I have too much text for a comment, so I'll make a new post.
I'm using Resizer inside a docking panel, so I wanted the width to stay tied to its parent panel. With that use case, I've added North, South, East, and West to the ResizeDirection enum. It's a pretty simple change, so I'll just post a few parts that people might miss if they wanted to reproduce it.
in GripAlignmentConverter.Convert:
new cases in GripCursorConverter.Convert
in GripRotationConverter:
If I've left something out or you're having problems, let me know.
I'm using Resizer inside a docking panel, so I wanted the width to stay tied to its parent panel. With that use case, I've added North, South, East, and West to the ResizeDirection enum. It's a pretty simple change, so I'll just post a few parts that people might miss if they wanted to reproduce it.
private static void OnUpdateSizeCommand(object sender, ExecutedRoutedEventArgs e)
{
Resizer resizer = sender as Resizer;
Debug.Assert(resizer != null);
if (resizer._frameworkElement != null)
{
Point point = resizer._frameworkElement.PointToScreen(Mouse.GetPosition(resizer._frameworkElement));
//If we're not adjusting the width or height, we want to leave it alone so it has its default sizing characteristics
double? widthDelta = null;
double? heightDelta = null;
switch (resizer.ResizeDirection)
{
case ResizeDirection.North:
heightDelta = resizer._resizeOrigin.Y - point.Y;
break;
case ResizeDirection.East:
widthDelta = point.X - resizer._resizeOrigin.X;
break;
case ResizeDirection.South:
heightDelta = point.Y - resizer._resizeOrigin.Y;
break;
case ResizeDirection.West:
widthDelta = resizer._resizeOrigin.X - point.X;
break;
case ResizeDirection.NorthEast:
widthDelta = point.X - resizer._resizeOrigin.X;
heightDelta = resizer._resizeOrigin.Y - point.Y;
break;
case ResizeDirection.NorthWest:
widthDelta = resizer._resizeOrigin.X - point.X;
heightDelta = resizer._resizeOrigin.Y - point.Y;
break;
case ResizeDirection.SouthEast:
widthDelta = point.X - resizer._resizeOrigin.X;
heightDelta = point.Y - resizer._resizeOrigin.Y;
break;
case ResizeDirection.SouthWest:
widthDelta = resizer._resizeOrigin.X - point.X;
heightDelta = point.Y - resizer._resizeOrigin.Y;
break;
default:
Debug.Fail("Unexpected ResizeDirection: " + resizer.ResizeDirection);
break;
}
//update the width and height, making sure we don't set to below zero
if (widthDelta != null)
resizer.Width = Math.Max(0, resizer._originalWidth + widthDelta.Value);
if (heightDelta != null)
resizer.Height = Math.Max(0, resizer._originalHeight + heightDelta.Value);
}
e.Handled = true;
}
in GripAlignmentConverter.Convert:
switch (orientation)
{
case Orientation.Horizontal:
if (resizeDirection == ResizeDirection.NorthEast ||
resizeDirection == ResizeDirection.SouthEast ||
resizeDirection == ResizeDirection.South ||
resizeDirection == ResizeDirection.North)
{
return HorizontalAlignment.Right;
}
else
{
return HorizontalAlignment.Left;
}
case Orientation.Vertical:
if (resizeDirection == ResizeDirection.NorthEast ||
resizeDirection == ResizeDirection.NorthWest ||
resizeDirection == ResizeDirection.North)
{
return VerticalAlignment.Top;
}
else
{
return VerticalAlignment.Bottom;
}
}
new cases in GripCursorConverter.Convert
case ResizeDirection.North:
case ResizeDirection.South:
return Cursors.SizeNS;
case ResizeDirection.West:
case ResizeDirection.East:
return Cursors.SizeWE;
in GripRotationConverter:
switch (resizeDirection)
{
case ResizeDirection.SouthWest:
return 90;
case ResizeDirection.NorthWest:
case ResizeDirection.West:
return 180;
case ResizeDirection.NorthEast:
case ResizeDirection.North:
return 270;
}
If I've left something out or you're having problems, let me know.
Subscribe to:
Posts (Atom)