Click here to Skip to main content
Click here to Skip to main content

An Application to Keep Track of Your Article Ratings Over Time

, 23 Apr 2009
Rate this:
Please Sign up or sign in to vote.
Collects and records your article ratings plus a couple of new summary ratings
Click for full size screenshot

Click image for full size screenshot

Table of Contents

Introduction

I like to keep an eye on how my articles are doing, so I wrote a little application to keep track of them. I thought it might be of interest to other authors, so here it is...

Requirements

This WPF application was written in C# 3.0 using Visual Studio 2008 and requires .NET 3.5.

Caveat

Please do not abuse this tool by loading lots of members or fetching ratings too often. Chris has kindly allowed me to publish this, so please do not make him regret it by overloading the servers.

Quickstart

If you want to jump right in, this is the section to read. It's not rocket science.

From the User menu, choose Add User. This brings up a dialog box where you can enter a CodeProject member id. This is the number shown on the Who's Who page for the member. Repeat as required.

Press the Get Ratings button.

Save updated data to file.

Metrics

This is a short description of the metrics recorded by the app, both those calculated by CodeProject and a couple I have added.

Rating

This is calculated by CodeProject. I believe each vote is weighted depending on the "Status" of the voter, but I'm not sure about the details. As you know, it is a number between 1 and 5 inclusive.

Popularity

This is also calculated by CodeProject, but the formula is known. It is:

popularity = rating * log<sub>10</sub>( number of votes )

X-Rating

This is a new summary metric for each author over all his/her articles. It is basically the average of each article's rating, but weighted by the number of votes for the article. I should point out, therefore, that articles with zero votes do not contribute to the X-Rating metric.

xrating = [ sum over all articles of ( votes * rating ) ] / [ total number of votes ]

X-Popularity

This is also a new summary metric for each author. It is based on the formula for each article's popularity.

xpopularity = xrating * log<sub>10</sub>( total number of votes )

Highlighting

To make obvious any changes since you last downloaded, the cells in the grid turn yellow for changed metrics. So you can easily see when someone votes for one of your articles and drill into the grid to find the details.

Using the Application

Get Ratings

The "Get Ratings" button works on the currently selected user in the combo box. If "All Users" is selected, it downloads and parses a page for every loaded user. If a particular user is selected, it only gets info for that user.

If you collect your ratings every day or so, you will soon build up a history of statistics showing how your articles are being received over time.

Views

There are five views. The "All Authors" view lists all the summary ratings for all the authors in a file. Then there are two pairs of views. The first pair are the "Totals" and "History" views. These show the summary ratings for a particular author over time and the ratings on a particular date. The second pair are "Articles" and "Details". These show the current ratings for a particular author and the collected ratings for a particular article.

You can double click on a data row in the grid, or press the button, to change views. The view toggles between each view in each pair. You can press ctrl-A to select "All Authors" which shows the authors view again.

Persistance

You can save the data to a file as either a *.xml or *.bob file. The difference is that the *.bob file compresses the XML by using a GZipStream. This compression reduces the file size by a factor of about ten.

There is no "do you want to save your changes" dialog, so don't forget to save your file after updating.

Editing

Apart from adding a user, the only edit you can make is to delete a row. Just select a row and press the backspace or delete key. This functions in all views to remove either an author, an article, or a single detail. Of course you always have the choice of reloading your data from file, thus discarding all unsaved changes.

How it Works

Data from CodeProject

All the data is available on the article summary page for each member. The app fetches this page and parses it using RegEx's. This means it is quite fragile and will stop working if Chris changes so much as a space. However, he doesn't do this very often. I have only tweaked the RegEx's a few times during the two years I have been using this.

The RegEx's are in the CodeProject.cs file, if you want to take a look.

Persistance

When you save to a file, all collected data is persisted. Nothing is discarded. This means that by taking a snapshot every day or so, you can build up a history of ratings. This in turn enables the application to highlight new votes on articles.

The summary details are calculated whenever they are required from the article stats, so they always reflect your current data. There is some LINQ fun and games going on in Data.cs, if you're interested.

Xceed.Wpf.DataGrid

Xceed have written an excellent grid control for WPF and offer an "Express Edition" for free. At the time of writing, they have just released version 2.0 here [^]. They are another benevolent Canadian company, by the way.

Points of Interest

There are plenty of articles about WPF, so I won't dwell on it here. However, there are a couple of things worth mentioning.

Buttons

The little circles on the buttons come from a neat data template:

<DataTemplate x:Key="ButtonTemplate">
   
   <StackPanel Orientation="Horizontal">
       
       <StackPanel.Width>
           <Binding Path="Width" RelativeSource="{RelativeSource AncestorType=Button}" />
       </StackPanel.Width>

       <Ellipse Width="10" Height="10" Margin="0,0,10,0">
           <Ellipse.Fill>
               <RadialGradientBrush GradientOrigin="0.3, 0.3">
                   <GradientStop Offset="0.2" 
                          Color="{StaticResource FloralWhiteColour}" />
                   <GradientStop Offset="1" Color="{StaticResource OrangeColour}" />
               </RadialGradientBrush>
           </Ellipse.Fill>
       </Ellipse>

       <ContentPresenter Content="{TemplateBinding Content}" />
       
   </StackPanel>
   
</DataTemplate>

Hooking Events

Double-clicking a row in the grid swaps views. The obvious way I tried was this:

grid.MouseDoubleClick += ( s, a ) => SwapViews();

Unfortunately this also responds to double clicks in areas like the scroll bars.

So I decided to hook the event at the DataRow level. Luckily, the EventManager static class that you use to register a routed event, also has a method called RegisterClassHandler. This allows you to hook an event on all instances of a class:

EventManager.RegisterClassHandler(
   typeof( DataRow ),
   Control.MouseDoubleClickEvent,
   new RoutedEventHandler( ( s, a ) => SwapViews() ) );

Hooking Dependency Properties

If you want to know when a dependency property changes, you can use the DependencyPropertyDescriptor class:

DependencyPropertyDescriptor.FromProperty(
   DataGridControl.SelectedItemProperty,
   typeof( DataGridControl ) )
   .AddValueChanged( grid, grid_SelectedItemChanged );

Conclusion

Well, that's all folks. If you like this app, please vote. I'll be watching!

History

2008 March 06: First published
2009 April 23: Bug fix - code updated

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Nicholas Butler

United Kingdom United Kingdom

I built my first computer, a Sinclair ZX80, on my 11th birthday in 1980.
In 1992, I completed my Computer Science degree and built my first PC.
I discovered C# and .NET 1.0 Beta 1 in late 2000 and loved them immediately.
I have been writing concurrent software professionally, using multi-processor machines, since 1995.
 
In real life, I have spent 3 years travelling abroad,
I have held a UK Private Pilots Licence for 20 years,
and I am a PADI Divemaster.
 
I now live near idyllic Bournemouth in England.
 
If you would like help with multithreading, please contact me via my website:
 
 
I can work 'virtually' anywhere!

Comments and Discussions

 
QuestionBroken? Parse error PinmemberYvan Rodrigues28-Nov-11 11:22 
GeneralExcelent PinmvpAbhijit Jana14-Jun-09 10:21 
Generalvery cool PinmemberDonsw20-May-09 16:57 
GeneralAwesome! Pinmemberthund3rstruck29-Apr-09 8:07 
GeneralRe: Awesome! PinmemberNick Butler29-Apr-09 8:18 
NewsDownloads updated 13 April 2009 PinmemberNick Butler13-Apr-09 6:35 
The downloads have been updated with new RegEx's that work with the current HTML.
 
Nick
 
----------------------------------
Be excellent to each other Smile | :)

GeneralException PinmemberNinjaCross8-Apr-09 2:43 
GeneralRe: Exception PinmemberNick Butler11-Apr-09 23:44 
GeneralRe: Exception PinmemberNinjaCross12-Apr-09 10:30 
GeneralRe: Exception PinmemberNick Butler13-Apr-09 6:45 
GeneralRe: Exception PinmemberNinjaCross14-Apr-09 9:58 
AnswerRe: Exception PinmemberNick Butler14-Apr-09 10:54 
GeneralVery well done PinmvpRajesh R Subramanian9-May-08 4:58 
GeneralRe: Very well done PinmemberNick Butler9-May-08 5:05 
GeneralProxy support PinmemberAshutosh Bhawasinka6-Mar-08 19:46 
GeneralRe: Proxy support PinmemberNick Butler6-Mar-08 21:18 
GeneralRe: Proxy support PinmemberAshutosh Bhawasinka6-Mar-08 21:31 
GeneralRe: Proxy support PinmemberNick Butler7-Mar-08 2:40 
GeneralNice utility PinmemberBert delaVega6-Mar-08 7:04 
GeneralRe: Nice utility PinmemberNick Butler6-Mar-08 7:43 
GeneralRe: Nice utility PinmemberBert delaVega6-Mar-08 7:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140821.2 | Last Updated 23 Apr 2009
Article Copyright 2008 by Nicholas Butler
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid