I read this post the other day: How To Compete Against Yourself: Don’t Do Your Best, Do Better Than Your Personal Average. It’s got some great points on how to establish better habits and be more productive.
One of the big points was to find measurable stats and track them, and try to beat your average (not your best, because you’re putting out a high level of effort constantly which will burn you out).
I though to myself, “self, what’s a good stat for coding?” Doesn’t have to be a perfect model, but something simple and traceable. I thought of grabbing lines changed per day.
I did a bunch of research, and there’s not an easy way to get that data, not from git tools, not from github stats.
So I wrote the following PowerShell snippet that grabs the entire git log by author and date, parses the insertion/deletion counts, and sums it all up:
git log --pretty=oneline --shortstat --no-notes -C --after 2016-01-22 --before 2016-01-23 --author=chris | # grab git log. replace dates and author
Select-String '(\d+) insertion.*?(\d+) deletion' -AllMatches | # find insertion/deletion line and capture values
ForEach-Object { $_.Matches } | # pull in the regex
ForEach-Object { New-Object psobject -Property @{ Adds = $_.Groups[1].Value; Deletes = $_.Groups[2].Value } } | # for each match, capture adds/deletes into a ps object
Measure-Object -Property @("Adds","Deletes") -Sum # sum up the values
Replace my name with yours and use the dates you want (after yesterday and before today) and you’ll get some useful output like:
Count : 7
Average :
Sum : 704
Maximum :
Minimum :
Property : Adds
Count : 7
Average :
Sum : 95
Maximum :
Minimum :
Property : Deletes
I’m sure someone with some better PowerShell-fu could simplify the snippet. If that’s you, let me know!
Microsoft’s Dynamic Linq library has been floating around the internet in one form or another for years. Its been distributed as a raw .cs file, not a NuGet or any sort of supported package. The most central location I’ve found for this is King Wilder’s System.Dynamic.Linq GitHub repo and NuGet package.
I needed support for a couple of things that weren’t included in the original version, namely Sum/Average/Min/Max functions, and that in a dynamically callable way. So I built that, cribbing off of a Sum function found on StackOverflow. The code takes the name of the function you want to call and the name of the property you want to aggregate. It then uses reflection to grab the extension method of the correct type based on the property type you specify and executes it against the IQueryable, returning the result.
After a bit of jiggering, I realized that Sum and Average have totally different signatures than Min/Max for some reason. Adding in separate branches to the code did the trick and I came up with:
/// <summary>
/// Dynamically runs an aggregate function on the IQueryable.
/// </summary>
/// <param name="source">The IQueryable data source.</param>
/// <param name="function">The name of the function to run. Can be Sum, Average, Min, Max.</param>
/// <param name="member">The name of the property to aggregate over.</param>
/// <returns>The value of the aggregate function run over the specified property.</returns>
public static object Aggregate(this IQueryable source, string function, string member)
{
if (source == null) throw new ArgumentNullException("source");
if (member == null) throw new ArgumentNullException("member");
// Properties
PropertyInfo property = source.ElementType.GetProperty(member);
ParameterExpression parameter = Expression.Parameter(source.ElementType, "s");
Expression selector = Expression.Lambda(Expression.MakeMemberAccess(parameter, property), parameter);
// We've tried to find an expression of the type Expression<Func<TSource, TAcc>>,
// which is expressed as ( (TSource s) => s.Price );
var methods = typeof(Queryable).GetMethods().Where(x => x.Name == function);
// Method
MethodInfo aggregateMethod = typeof(Queryable).GetMethods().SingleOrDefault(
m => m.Name == function
&& m.ReturnType == property.PropertyType // should match the type of the property
&& m.IsGenericMethod);
// Sum, Average
if (aggregateMethod != null)
{
return source.Provider.Execute(
Expression.Call(
null,
aggregateMethod.MakeGenericMethod(new[] { source.ElementType }),
new[] { source.Expression, Expression.Quote(selector) }));
}
// Min, Max
else
{
aggregateMethod = typeof(Queryable).GetMethods().SingleOrDefault(
m => m.Name == function
&& m.GetGenericArguments().Length == 2
&& m.IsGenericMethod);
return source.Provider.Execute(
Expression.Call(
null,
aggregateMethod.MakeGenericMethod(new[] { source.ElementType, property.PropertyType }),
new[] { source.Expression, Expression.Quote(selector) }));
}
}
I've submitted a pull request with this function to kahnau's repo, and he seems pretty responsive about accepting pull requests, so this will likely be in that NuGet soon.
I spent some time looking for a simple compound interest calculation function in .NET today. I couldn't find anything usable, so I grabbed the source formula and reduced it to .NET.
Here's the formula:
A = P * (1 + r / n) ^ n * t
A = final total amount
P = principal amount
r = interest rate (decimal)
n = number of periods per year
t = number of years
The C# code:
decimal CalculateTotalWithCompoundInterest(decimal principal, decimal interestRate, int compoundingPeriodsPerYear, double yearCount)
{
return principal * (decimal)Math.Pow((double)(1 + interestRate / compoundingPeriodsPerYear), compoundingPeriodsPerYear * yearCount);
}
For example, you can calculate the total loan amount for $10,000.00 (principal and interest), compounded daily for 2 years like so:
decimal total = CalculateTotalWithCompoundInterest(10000m, 8.5m, 365, 2);
The WiX docs on the topic (Integrating WiX Projects Into Daily Builds) give a good starting point, but are incomplete, at least for the recent builds. Two additional things they forget to mention: WixToolPath needs to be an absolute path for the Wix.targets project to function properly, and WixExtDir needs to be set to WixToolPath.
To build WiX from the binaries with MSBuild, do the following (requires MSBuild 4):
- Snag the binaries from the latest weekly build: WiX Weekly Releases
- Extract them into a folder you can access with a relative path inside your source control root
- Edit all of your .wixproj files and do the following snippet before the <Import Project="$(WixTargetsPath)" > tag:
<WixToolPath>$([System.IO.Path]::GetFullPath('RELATIVEPATHTOWIX\wix\'))</WixToolPath>
<WixTargetsPath>$(WixToolPath)Wix.targets</WixTargetsPath>
<WixTasksPath>$(WixToolPath)wixtasks.dll</WixTasksPath>
<WixExtDir>$(WixToolPath)</WixExtDir>
</PropertyGroup>
- Update the RELATIVEPATHTOWIX to be a relative path that points to the WiX binaries you extracted in step 2.
I just ran up against a requirement to do a deep file and folder/directory copy in .NET (C# to be exact). A quick google didn't turn up any code, so I figured I'd post what I came up with. This is a somewhat naive implementation that may run out of steam for very deep folders or 1000s of files, but works great for most things. This implementation takes a source folder and a destination folder and copies the entire structure including files and folders from the source folder to the destination.
So without further ado:
private void CopyFolder(string folder, string destFolder)
{
Directory.CreateDirectory(destFolder);
foreach (string file in Directory.GetFiles(folder, "*.*", SearchOption.AllDirectories))
{
string fileName = Path.GetFileName(file);
string filePath = Path.GetDirectoryName(file.Substring(folder.Length + (folder.EndsWith("\\") ? 0 : 1)));
string destFilePath;
if (!string.IsNullOrEmpty(filePath))
{
string destFolderPath = Path.Combine(destFolder, filePath);
Directory.CreateDirectory(destFolderPath);
destFilePath = Path.Combine(destFolderPath, fileName);
}
else
{
destFilePath = Path.Combine(destFolder, fileName);
}
File.Copy(file, destFilePath);
}
}