public
Last active

IComparer for our app - it compares shirt sizes, with overloads for a couple of DTOs.

  • Download Gist
PropertySizeComparer.cs
C#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Cubrd.Services.DTOs;
 
namespace Cubrd.Services.Utility
{
public class PropertySizeComparer : IComparer<ItemPropertyDTO>, IComparer<PropertyAllowedValueDTO>, IComparer<string>
{
private static readonly Dictionary<string, int> EasySizes = new Dictionary<string, int>(StringComparer.CurrentCultureIgnoreCase) { { "s", 10 }, { "m", 11 }, { "l", 12 } };
#region IComparer
public int Compare(ItemPropertyDTO x, ItemPropertyDTO y)
{
return DoCompare(new SizeProperty(x.OptionValue, x.SortOrder), new SizeProperty(y.OptionValue, y.SortOrder));
}
public int Compare(PropertyAllowedValueDTO x, PropertyAllowedValueDTO y)
{
return DoCompare(new SizeProperty(x.Value, null), new SizeProperty(y.Value, null));
}
public int Compare(string x, string y)
{
return DoCompare(new SizeProperty(x, null), new SizeProperty(y, null));
}
#endregion
 
#region private
 
private static int DoCompare(SizeProperty x, SizeProperty y)
{
var firstPass = CompareSortOrder(x, y);
if (firstPass != null)
return firstPass.Value;
//if we made it here..parse
 
x.SortOrder = EasySizes.ContainsKey(x.OptionValue) ? EasySizes[x.OptionValue] : getSizeValue(x);
y.SortOrder = EasySizes.ContainsKey(y.OptionValue) ? EasySizes[y.OptionValue] : getSizeValue(y);
var newResult = CompareSortOrder(x, y);
if (newResult.HasValue)
return newResult.Value;
return 0;
}
 
 
private static int getSizeValue(SizeProperty x)
{
int bonusNum = x.OptionValue.EndsWith("t", StringComparison.CurrentCultureIgnoreCase) ? 100 : 0;
var optionValue = x.OptionValue.ToLower().TrimEnd('t');
//we need regexes for 4xt, 4t, and 4xlt => 4x,4 and 4xl;
//4T => 4 => 4X
if (Regex.IsMatch(optionValue, @"^\d+$"))
{
//then it was in the form of 4t, most likely.
optionValue = optionValue + "x";
}
//5XT -> 5X -> 5XL
if (Regex.IsMatch(optionValue, @"^\d+x$"))
optionValue = optionValue + "l";
 
var match = Regex.Match(optionValue, @"^(\d+)x*([sl])");
//the multiplier: 5x => exes = 5. XXXL => exes = 3
int exes;
string theRest = "";
if (match.Success)
{
//will match 5l, 5s, 5xl, 5xxL, etc (because garbage data)
if (!int.TryParse(match.Groups[1].Value, out exes))
exes = 0;
theRest = match.Groups[2].Value;
}
else
{
//maybe it's just xxs or xxxl
exes = optionValue.TakeWhile(val => val == 'x').Count();
//is it an extra large?
theRest = optionValue.Substring(exes);
}
 
int heuristic = 0;
if (theRest.Equals("s"))
heuristic = 10 - exes;
else if (theRest.Equals("l"))
heuristic = 12 + exes;
 
//bonusNum is for Ts: they need to sorted, but after the normal sizes.
int returnVal = heuristic + bonusNum;
return returnVal;
}
 
private static int? CompareSortOrder(SizeProperty x, SizeProperty y)
{
if (x.SortOrder.HasValue && y.SortOrder.HasValue)
return x.SortOrder.Value == y.SortOrder.Value ? 0 : x.SortOrder.Value > y.SortOrder.Value ? 1 : -1;
if (x.SortOrder.HasValue && !y.SortOrder.HasValue)
return x.SortOrder.Value == 0 ? 0 : x.SortOrder.Value > 0 ? 1 : -1;
if (y.SortOrder.HasValue && !x.SortOrder.HasValue)
return y.SortOrder.Value == 0 ? 0 : y.SortOrder.Value > 0 ? 1 : -1;
return null;
}
#endregion
 
private class SizeProperty
{
public string OptionValue { get; set; }
public decimal? SortOrder { get; set; }
 
public SizeProperty(string OptionValue, decimal? SortOrder)
{
this.OptionValue = OptionValue;
this.SortOrder = SortOrder;
}
}
}
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.