/GolfSigma.Inventory/Model/TeeTime.cs
C# | 559 lines | 373 code | 87 blank | 99 comment | 47 complexity | 030f8879e376f33743d2900fbc7318f9 MD5 | raw file
1using System; 2using System.Collections.Generic; 3using System.Text; 4using System.Runtime.Serialization; 5using System.Xml.Serialization; 6 7using GolfSigma.Inventory.Extension; 8 9namespace GolfSigma.Inventory.Model 10{ 11 #region Enumerations tied directed to TeeTime(s) 12 13 public enum FeeEnum : int 14 { 15 UnKnown = 0, 16 Green = 1, 17 Cart = 2, 18 Booking = 3, 19 Tax = 4, 20 RackRate = 5 21 } 22 23 public enum TeeTimeAttributeEnum : int 24 { 25 Holes18 = 0, 26 Holes9 = 5, 27 Holes27 = 10, 28 Holes36 = 15, 29 ResidentRestriction = 20, 30 ResidentOnly = 25, 31 GPSIncluded = 30, 32 MembersOnly = 35, 33 MemberDiscount = 40, 34 PlayerCardDiscount = 45, 35 PlayerCardOnly = 50, 36 PracticeBalls = 55, 37 SeniorDiscount = 60, 38 SeniorOnly = 65, 39 Twilight = 70, 40 TaxIncluded = 75, 41 Walking = 80, 42 CartIncluded = 85, 43 CaddieIncluded = 90, 44 PullCartIncluded = 95, 45 Replay = 100, 46 Aerification = 105, 47 MilitaryDiscount = 110, 48 ShotgunStart = 115, 49 CourseAlert = 120, 50 FreeReplay = 125, 51 OverSeeding = 130, 52 BestRateGuarantee = 135, 53 CartPathOnly = 140, 54 PrePaidOnline = 145 55 } 56 57 [Flags] 58 public enum PlayerEnum : int 59 { 60 None = 0x0, 61 Single = 0x1, 62 Twosome = 0x2, 63 Threesome = 0x4, 64 Foursome = 0x8, 65 All = Single | Twosome | Threesome | Foursome 66 } 67 68 /// <summary> 69 /// Currencies and their official names 70 /// </summary> 71 public enum CurrencyEnum 72 { 73 /// <summary> 74 /// United States dollar 75 /// </summary> 76 USD = 0, 77 78 /// <summary> 79 /// British Pound 80 /// </summary> 81 GBP = 5, 82 83 /// <summary> 84 /// Canadian dollar 85 /// </summary> 86 CAD = 10, 87 88 /// <summary> 89 /// Euro 90 /// </summary> 91 EUR = 15, 92 93 /// <summary> 94 /// Australian dollar 95 /// </summary> 96 AUD = 20, 97 98 /// <summary> 99 /// Japanese yen 100 /// </summary> 101 JPY = 25, 102 103 /// <summary> 104 /// Swiss Franc 105 /// </summary> 106 CHF = 30, 107 108 /// <summary> 109 /// Hong Kong Dollar 110 /// </summary> 111 HKD = 35, 112 113 /// <summary> 114 /// Mexican Peso 115 /// </summary> 116 MXN = 40 117 } 118 119 #endregion 120 121 [XmlRoot("TeeTime")] 122 public class TeeTime : IXmlSerializable 123 { 124 #region Ids 125 126 /// <summary> 127 /// Id of the tee-time. Id will be dropped on insert(s) 128 /// </summary> 129 public UInt64 TeeTimeId { get; set; } 130 131 /// <summary> 132 /// Website for the specific tee-time. 133 /// </summary> 134 public UInt32 WebSiteId { get; set; } 135 136 /// <summary> 137 /// Course for the specific tee-time 138 /// </summary> 139 public UInt64 CourseId { get; set; } 140 141 #endregion 142 143 #region Time and Players 144 145 /// <summary> 146 /// Date and Time of the tee-time. 147 /// </summary> 148 public DateTime Time { get; set; } 149 150 /// <summary> 151 /// Number of players available for the current tee time. Use bitwise operators to determine the number 152 /// of players available. 153 /// </summary> 154 public PlayerEnum Players { get; set; } 155 156 /// <summary> 157 /// Miscellaneous data. Providers can store information used to regenerate lookups to their own tee-time ids etc. 158 /// </summary> 159 public string MiscData { get; set; } 160 161 #endregion 162 163 #region Fees 164 165 /// <summary> 166 /// Total searchType per player. Sum of GreenFee, CartFee, Tax and Booking Fee 167 /// </summary> 168 public float TotalPricePerPlayer { get; set; } 169 170 /// <summary> 171 /// Percentage of interval off the original green fee 172 /// </summary> 173 public double? Savings { get; set; } 174 175 /// <summary> 176 /// Detailed breakdown of fees for this tee-time 177 /// </summary> 178 public Dictionary<FeeEnum, float> Fees { get; set; } 179 180 /// <summary> 181 /// Currency of the fees and total price per player 182 /// </summary> 183 public CurrencyEnum Currency { get; set; } 184 185 #endregion 186 187 #region Dates 188 189 /// <summary> 190 /// DateTime of when this tee time was created. (UTC) (Item will be dropped on any insert or update.) 191 /// </summary> 192 public DateTime Created { get; set; } 193 194 /// <summary> 195 /// DateTime of when this tee-time was last updated. (UTC) (Item will be dropped on any insert or update.) 196 /// </summary> 197 public DateTime? Updated { get; set; } 198 199 /// <summary> 200 /// DateTime of when this tee-time was deleted. (UTC) (Item will be dropped on any insert or update.) 201 /// </summary> 202 public DateTime? Deleted { get; set; } 203 204 #endregion 205 206 #region Attributes 207 208 /// <summary> 209 /// Attributes for the given tee times. List of integers (comma separated when serialized) representing 210 /// all attributes that apply for the given tee time 211 /// </summary> 212 public List<TeeTimeAttributeEnum> Attributes { get; set; } 213 214 private int? _NumberOfHoles; 215 /// <summary> 216 /// The number of holes for this tee-time 217 /// ** ASSUME 18 HOLES!! ** 218 /// </summary> 219 public int NumberOfHoles 220 { 221 get 222 { 223 if (_NumberOfHoles.HasValue) 224 return _NumberOfHoles.Value; 225 226 if (this.Attributes == null || this.Attributes.Count < 1) 227 { 228 _NumberOfHoles = 18; 229 } 230 else 231 { 232 if (this.Attributes.Contains(TeeTimeAttributeEnum.Holes9)) 233 _NumberOfHoles = 9; 234 else if (this.Attributes.Contains(TeeTimeAttributeEnum.Holes27)) 235 _NumberOfHoles = 27; 236 else if (this.Attributes.Contains(TeeTimeAttributeEnum.Holes36)) 237 _NumberOfHoles = 36; 238 else 239 _NumberOfHoles = 18; 240 } 241 242 // Return the number of holes 243 return _NumberOfHoles.Value; 244 } 245 } 246 247 #endregion 248 249 #region IXmlSerializable Members 250 251 public System.Xml.Schema.XmlSchema GetSchema() 252 { 253 return null; 254 } 255 256 public void ReadXml(System.Xml.XmlReader reader) 257 { 258 // Check to see if we were provided an id 259 string teeTimeId = reader.GetAttribute("id"); 260 if (!string.IsNullOrEmpty(teeTimeId)) 261 { 262 UInt64 teeTimeIdParsed; 263 if (UInt64.TryParse(teeTimeId, out teeTimeIdParsed)) 264 TeeTimeId = teeTimeIdParsed; 265 else 266 throw new FormatException(); 267 } 268 269 bool breakRead = false; 270 while (breakRead == false) 271 { 272 reader.Read(); 273 string localName = reader.LocalName; 274 275 string elementAsString = string.Empty; 276 elementAsString = reader.ReadString(); 277 278 switch (localName) 279 { 280 case "WebSiteId": 281 UInt32? webSiteIdParsed = StringExtension.ToUInt32(elementAsString); 282 if (!webSiteIdParsed.HasValue) 283 throw new FormatException(); 284 else 285 WebSiteId = webSiteIdParsed.Value; 286 break; 287 288 case "CourseId": 289 UInt64? courseIdParsed = StringExtension.ToUInt64(elementAsString); 290 if (!courseIdParsed.HasValue) 291 throw new FormatException(); 292 else 293 CourseId = courseIdParsed.Value; 294 break; 295 296 case "Players": 297 int playersParsed = 0; 298 if (!int.TryParse(elementAsString, out playersParsed)) 299 throw new FormatException(); 300 else 301 Players = (PlayerEnum)playersParsed; 302 if (Players == PlayerEnum.None) 303 throw new FormatException(); 304 break; 305 306 case "Time": 307 DateTime timeParsed; 308 if (!DateTime.TryParseExact( 309 elementAsString, 310 Extension.StringExtension.DateTimeFormatShort, 311 System.Globalization.CultureInfo.InvariantCulture, 312 System.Globalization.DateTimeStyles.AssumeLocal | System.Globalization.DateTimeStyles.AllowWhiteSpaces, 313 out timeParsed)) 314 throw new FormatException(); 315 else 316 Time = timeParsed; 317 break; 318 319 case "Created": 320 DateTime createdParsed; 321 if (!DateTime.TryParseExact( 322 elementAsString, 323 Extension.StringExtension.DateTimeFormatUTC, 324 System.Globalization.CultureInfo.InvariantCulture, 325 System.Globalization.DateTimeStyles.AssumeUniversal | System.Globalization.DateTimeStyles.AllowWhiteSpaces, 326 out createdParsed)) 327 throw new FormatException(); 328 else 329 Created = createdParsed; 330 break; 331 332 case "Deleted": 333 DateTime deletedParsed; 334 if (!DateTime.TryParseExact( 335 elementAsString, 336 Extension.StringExtension.DateTimeFormatUTC, 337 System.Globalization.CultureInfo.InvariantCulture, 338 System.Globalization.DateTimeStyles.AssumeUniversal | System.Globalization.DateTimeStyles.AllowWhiteSpaces, 339 out deletedParsed)) 340 throw new FormatException(); 341 else 342 Deleted = deletedParsed; 343 break; 344 345 case "Price": 346 float priceParsed; 347 if (float.TryParse(elementAsString, out priceParsed)) 348 TotalPricePerPlayer = priceParsed; 349 else 350 // Failed (anything lower than -1 is a failure) 351 throw new FormatException(); 352 if (TotalPricePerPlayer < -1 || TotalPricePerPlayer > 1000) 353 throw new FormatException(); 354 break; 355 356 case "Currency": 357 try 358 { 359 CurrencyEnum currencyParsed = (CurrencyEnum)Enum.Parse( 360 typeof(CurrencyEnum), 361 elementAsString, 362 true); 363 364 Currency = currencyParsed; 365 } 366 catch 367 { 368 throw new FormatException(); 369 } 370 break; 371 372 case "Savings": 373 Double savingsParsed; 374 if (double.TryParse(elementAsString, out savingsParsed)) 375 Savings = savingsParsed; 376 else 377 throw new FormatException(); 378 break; 379 380 case "Fees": 381 // Create a new list 382 if (Fees == null) 383 Fees = new Dictionary<FeeEnum, float>(); 384 385 while (reader.IsStartElement("Fee")) 386 { 387 string feeType = reader.GetAttribute("type"); 388 string feeValue = reader.GetAttribute("value"); 389 390 // Skip if we don't have a fee AND value 391 if (string.IsNullOrEmpty(feeType) || string.IsNullOrEmpty(feeValue)) 392 { 393 reader.Read(); 394 continue; 395 } 396 397 FeeEnum feeTypeParsed = FeeEnum.UnKnown; 398 try 399 { 400 // Attempt to convert the feeType into an enum 401 feeTypeParsed = (FeeEnum)Enum.Parse(typeof(FeeEnum), feeType); 402 } 403 catch 404 { 405 throw new FormatException(); 406 } 407 408 // Attempt to parse the value 409 float feeValueParsed; 410 if (float.TryParse(feeValue, out feeValueParsed)) 411 Fees.Add(feeTypeParsed, feeValueParsed); 412 else 413 throw new FormatException(); 414 415 // Done reading this element 416 reader.Read(); 417 } 418 break; 419 420 case "Attributes": 421 // Make sure we have attributes 422 if (!string.IsNullOrEmpty(elementAsString)) 423 { 424 // Create a new list if it doesn't exist 425 if (Attributes == null) 426 Attributes = new List<TeeTimeAttributeEnum>(); 427 428 // Loop through each attribute and add it to the attribute list! 429 foreach (var attr in elementAsString.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) 430 { 431 try 432 { 433 // Attempt to parse the attribute 434 TeeTimeAttributeEnum attrParsed = 435 (TeeTimeAttributeEnum)Enum.Parse(typeof(TeeTimeAttributeEnum), attr, true); 436 437 if (StringExtension.IsNumber(attrParsed.ToString(), false)) 438 { 439 throw new FormatException(); 440 } 441 442 // Add to the list 443 Attributes.Add(attrParsed); 444 } 445 catch 446 { 447 throw new FormatException(); 448 } 449 } 450 } 451 break; 452 453 case "Misc": 454 if (!string.IsNullOrEmpty(elementAsString)) 455 MiscData = elementAsString; 456 break; 457 458 case "TeeTime": 459 // End reading this element 460 reader.ReadEndElement(); 461 breakRead = true; 462 break; 463 464 // Do nothing on any other attribute 465 default: break; 466 } 467 } 468 } 469 470 public void WriteXml(System.Xml.XmlWriter writer) 471 { 472 throw new NotImplementedException(); 473 } 474 475 #endregion 476 477 #region Post Parameters 478 479 public Dictionary<string, string> GetPostParamters() 480 { 481 return GetPostParamters(default(int?)); 482 } 483 484 public Dictionary<string, string> GetPostParamters(int? index) 485 { 486 string prefix = "teetime."; 487 488 // Create our result 489 Dictionary<string, string> result = new Dictionary<string, string>(); 490 491 result.Add(StringExtension.Prefix("websiteid", prefix, index), WebSiteId.ToString()); 492 result.Add(StringExtension.Prefix("courseid", prefix, index), CourseId.ToString()); 493 result.Add(StringExtension.Prefix("time", prefix, index), Time.ToString(Extension.StringExtension.DateTimeFormatShort)); 494 result.Add(StringExtension.Prefix("players", prefix, index), ((int)Players).ToString()); 495 result.Add(StringExtension.Prefix("currency", prefix, index), Currency.ToString()); 496 497 // Add our savings 498 if (Savings.HasValue) 499 result.Add(StringExtension.Prefix("savings", prefix, index), Savings.Value.ToString()); 500 501 // Convert our attributes to filters 502 if (Attributes != null && Attributes.Count > 0) 503 { 504 StringBuilder sbAttributes = new StringBuilder(); 505 foreach (var item in Attributes) 506 sbAttributes.AppendFormat("{0},", ((int)item).ToString()); 507 508 // Add without the trailing comma 509 result.Add(StringExtension.Prefix("attributes", prefix, index), sbAttributes.ToString(0, sbAttributes.Length - 1)); 510 } 511 512 // Convert our fees 513 if (Fees != null && Fees.Count > 0) 514 { 515 string feePrefix = "fee."; 516 int i = 1; 517 foreach (var item in Fees) 518 { 519 string keyPrefix = StringExtension.Prefix(StringExtension.Prefix("key", feePrefix, i), prefix, index); 520 string valuePrefix = StringExtension.Prefix(StringExtension.Prefix("value", feePrefix, i), prefix, index); 521 522 result.Add(keyPrefix, item.Key.ToString()); 523 result.Add(valuePrefix, item.Value.ToString()); 524 i++; 525 } 526 } 527 528 if (!string.IsNullOrEmpty(MiscData)) 529 result.Add(StringExtension.Prefix("miscdata", prefix, index), MiscData); 530 531 // Return the params 532 return result; 533 } 534 535 #endregion 536 537 public TeeTime() { } 538 public TeeTime(TeeTime input) : this() 539 { 540 if (input == null) 541 return; 542 543 this.Attributes = input.Attributes; 544 this.CourseId = input.CourseId; 545 this.Created = input.Created; 546 this.Currency = input.Currency; 547 this.Deleted = input.Deleted; 548 this.Fees = input.Fees; 549 this.MiscData = input.MiscData; 550 this.Players = input.Players; 551 this.Savings = input.Savings; 552 this.TeeTimeId = input.TeeTimeId; 553 this.Time = input.Time; 554 this.TotalPricePerPlayer = input.TotalPricePerPlayer; 555 this.Updated = input.Updated; 556 this.WebSiteId = input.WebSiteId; 557 } 558 } 559}