PageRenderTime 69ms CodeModel.GetById 28ms app.highlight 33ms RepoModel.GetById 2ms app.codeStats 0ms

/JTacticalSim.DataContext/XMLDataContext.cs

https://github.com/Queztionmark/JTacticalSim
C# | 1123 lines | 818 code | 220 blank | 85 comment | 25 complexity | 20f8603e956df84e27f96143444bbd41 MD5 | raw file
   1using System;
   2using System.Collections.Generic;
   3using System.Linq;
   4using System.Xml.Linq;
   5using System.Dynamic;
   6using System.IO;
   7using System.Transactions;
   8using JTacticalSim.API;
   9using JTacticalSim.API.DTO;
  10using JTacticalSim.Data.DTO;
  11using JTacticalSim.API.Data;
  12using JTacticalSim.API.Component;
  13using JTacticalSim.Utility;
  14
  15namespace JTacticalSim.DataContext
  16{
  17	/// <summary>
  18	/// File based data context
  19	/// </summary>
  20	public sealed class XMLDataContext : BaseDataContext
  21	{
  22		private DataFileFactory _dataFileFactory = DataFileFactory.Instance;
  23
  24		private static volatile IDataContext _instance = null;
  25		static readonly object padlock = new object();
  26
  27		public static IDataContext Instance
  28		{
  29			get
  30			{
  31				if (_instance == null)
  32				{
  33					lock (padlock)
  34						if (_instance == null) _instance = new XMLDataContext();
  35				}
  36
  37				return _instance;
  38			}
  39		}
  40		
  41		// Initialize Context
  42		private XMLDataContext()
  43		{}
  44
  45#region Save
  46
  47		public override IResult<IGameFileCopyable> SaveData(IGameFileCopyable currentData)
  48		{
  49			var r = new DataResult<IGameFileCopyable>{Status = ResultStatus.SUCCESS, Result = currentData};
  50
  51			using (var txn = new TransactionScope())
  52			{			
  53				// 1. Create a new file handler for the current game file directory
  54				IDataFileHandler<XDocument> dataFileHandler = null;
  55
  56				try
  57				{
  58					dataFileHandler = new DataFileHandler<XDocument>(_dataFileFactory.GetDataFiles<XDocument>(currentData.GameFileDirectory, currentData.IsScenario));
  59				
  60				}
  61				catch (Exception ex)
  62				{
  63					r.Status = ResultStatus.EXCEPTION;
  64					r.ex = ex;
  65					r.Messages.Add("Game data not saved. DataFileHandler could not be created.");
  66					return r;
  67				}
  68
  69				// 2. Backup Current Files
  70				if (dataFileHandler.GameDirectoryHasFiles())
  71				{
  72					try
  73					{
  74						BackupCurrentGameFiles(dataFileHandler);
  75					}
  76					catch (Exception ex)
  77					{
  78						r.Status = ResultStatus.EXCEPTION;
  79						r.ex = ex;
  80						r.Messages.Add("Game data not saved. Could not backup current game files.");
  81						return r;
  82					}
  83				}
  84
  85				// 3. Save data
  86				try
  87				{
  88					SaveGameData(dataFileHandler);
  89				}
  90				catch (Exception ex)
  91				{
  92					r.Status = ResultStatus.EXCEPTION;
  93					r.ex = ex;
  94					r.Messages.Add("Game data not saved.");
  95					return r;
  96				}
  97
  98				txn.Complete();
  99			}
 100
 101			r.Messages.Add("Game data saved.");
 102			return r;
 103		}
 104
 105		public override IResult<IGameFileCopyable> SaveDataAs(IGameFileCopyable currentData, IGameFileCopyable newData)
 106		{
 107			var r = new DataResult<IGameFileCopyable>{Status = ResultStatus.SUCCESS, Result = newData};
 108
 109			using (var txn = new TransactionScope())
 110			{	
 111				// 1. Create a new file handler for the current and new game file directories
 112				IDataFileHandler<XDocument> currentDataFileHandler = null;
 113				IDataFileHandler<XDocument> newDataFileHandler = null;
 114
 115				try
 116				{
 117					currentDataFileHandler = new DataFileHandler<XDocument>(_dataFileFactory.GetDataFiles<XDocument>(currentData.GameFileDirectory, currentData.IsScenario));
 118					newDataFileHandler = new DataFileHandler<XDocument>(_dataFileFactory.GetDataFiles<XDocument>(newData.GameFileDirectory, newData.IsScenario));
 119				}
 120				catch (Exception ex)
 121				{
 122					r.Status = ResultStatus.EXCEPTION;
 123					r.ex = ex;
 124					r.Messages.Add("Game data not saved. DataFileHandlers could not be created.");
 125					return r;
 126				}	
 127
 128				// 2. Verify game directory. Create if it does not exists.
 129				if (!newDataFileHandler.GameDirectoryExists())
 130				{
 131					try
 132					{
 133						newDataFileHandler.CreateNewGameDirectory();
 134					}
 135					catch (Exception ex)
 136					{
 137						r.Status = ResultStatus.EXCEPTION;
 138						r.ex = ex;
 139						r.Messages.Add("Game data not saved. Could not create new game directory.");
 140						return r;
 141					}
 142				}
 143
 144				// 3. Copy current files to new directory
 145				var result = (currentData.IsScenario) 
 146								? currentDataFileHandler.CopyScenarioFiles(newDataFileHandler.DataFiles.GameSaveDirectory)
 147								: currentDataFileHandler.CopyGameFiles(newDataFileHandler.DataFiles.GameSaveDirectory);				
 148
 149				if (result.Status == ResultStatus.EXCEPTION)
 150				{
 151					r.Status = ResultStatus.EXCEPTION;
 152					r.ex = result.ex;
 153					r.Messages.Add("Game data not saved. {0}.".F(result.Message));
 154					return r;
 155				}					
 156
 157				txn.Complete();
 158			}
 159
 160			r.Messages.Add("Game data saved.");
 161			return r;
 162		}
 163
 164		public override IResult<IGameFileCopyable> RemoveSavedGameData(IGameFileCopyable delData)
 165		{
 166			var r = new DataResult<IGameFileCopyable>{Status = ResultStatus.SUCCESS, Result = delData};
 167
 168			using (var txn = new TransactionScope())
 169			{
 170
 171				// 1. Create a new file handler for the game to be deleted.
 172				IDataFileHandler<XDocument> delDataFileHandler = null;
 173
 174				try
 175				{
 176					delDataFileHandler = new DataFileHandler<XDocument>(_dataFileFactory.GetDataFiles<XDocument>(delData.GameFileDirectory, delData.IsScenario));
 177				}
 178				catch (Exception ex)
 179				{
 180					r.Status = ResultStatus.EXCEPTION;
 181					r.ex = ex;
 182					r.Messages.Add("Game data not saved. DataFileHandlers could not be created.");
 183					return r;
 184				}
 185
 186				// 2. Verify game directory. Create if it does not exists.
 187				if (delDataFileHandler.GameRootDirectoryExists())
 188				{
 189					try
 190					{
 191						delDataFileHandler.DeleteGameDirectory();
 192					}
 193					catch (Exception ex)
 194					{
 195						r.Status = ResultStatus.EXCEPTION;
 196						r.ex = ex;
 197						r.Messages.Add("Game data not deleted. Could not delete game directory.");
 198						return r;
 199					}
 200				}
 201
 202				// 3. Save data
 203				try
 204				{
 205					SaveSavedGameFile(delDataFileHandler);
 206				}
 207				catch (Exception ex)
 208				{
 209					r.Status = ResultStatus.EXCEPTION;
 210					r.ex = ex;
 211					r.Messages.Add("Game data file not saved.");
 212					return r;
 213				}
 214
 215				txn.Complete();
 216			}
 217
 218			r.Messages.Add("Game data removed.");
 219			return r;
 220		}
 221
 222
 223		private void BackupCurrentGameFiles(IDataFileHandler<XDocument> dataFileHandler)
 224		{
 225			dataFileHandler.DataFiles.ScenarioFilePaths.ForEach(path =>	
 226			{ 
 227				File.Delete("{0}.BAK".F(path));
 228				File.Copy(path, "{0}.BAK".F(path));	
 229			});	
 230		
 231			// Back up the Saved Games file
 232			File.Delete("{0}.BAK".F(dataFileHandler.DataFiles.SavedGameDataFilePath));
 233			File.Copy(dataFileHandler.DataFiles.SavedGameDataFilePath, "{0}.BAK".F(dataFileHandler.DataFiles.SavedGameDataFilePath));
 234		}
 235
 236		private void SaveGameData(IDataFileHandler<XDocument> dataFileHandler)
 237		{
 238			SaveBoardDataFile(dataFileHandler);
 239			SaveUnitDataFile(dataFileHandler);
 240			SaveGameDataFile(dataFileHandler);
 241			SaveSavedGameFile(dataFileHandler);
 242		}
 243
 244		private void SaveBoardDataFile(IDataFileHandler<XDocument> dataFileHandler)
 245		{
 246			// Clear all nodes
 247			var nodes = dataFileHandler.DataFiles.BoardDataFile.Descendants("Nodes").Single();
 248			nodes.RemoveAll();
 249
 250			var attributes = dataFileHandler.DataFiles.BoardDataFile.Descendants("Attributes").Single();
 251
 252			// Clear the board
 253			var board = dataFileHandler.DataFiles.BoardDataFile.Descendants("GameBoard").Single();
 254			board.RemoveAll();
 255
 256			// Update attributes
 257			attributes.Attribute("Title").SetValue(Board.Title);
 258			attributes.Attribute("Width").SetValue(Board.Width);
 259			attributes.Attribute("Height").SetValue(Board.Height);
 260			attributes.Attribute("CellSize").SetValue(Board.CellSize);
 261			attributes.Attribute("CellMaxUnits").SetValue(Board.CellMaxUnits);
 262
 263			// Create Nodes for save
 264			foreach (var n in NodesTable.Records)
 265			{
 266				nodes.Add(n.ToXML());
 267			}
 268
 269			board.Add(attributes);
 270			board.Add(nodes);
 271			
 272			// Save back file
 273			board.Document.Save(dataFileHandler.DataFiles.BoardDataFilePath);
 274		}
 275
 276		private void SaveUnitDataFile(IDataFileHandler<XDocument> dataFileHandler)
 277		{
 278			// Remove all existing units
 279			var units = dataFileHandler.DataFiles.UnitDataFile.Descendants("Units").Single();
 280			units.RemoveAll();
 281
 282			// Create units for save
 283			foreach (var u in UnitsTable.Records)
 284			{
 285				units.Add(u.ToXML());				
 286			}
 287
 288			units.Document.Save(dataFileHandler.DataFiles.UnitDataFilePath);
 289		}
 290
 291		private void SaveGameDataFile(IDataFileHandler<XDocument> dataFileHandler)
 292		{
 293			// Remove all existing GameData
 294			var gameData = dataFileHandler.DataFiles.GameDataFile.Descendants("GameData").Single();
 295			gameData.RemoveAll();
 296
 297			// Create Factions for save
 298			XElement fs = new  XElement("Factions");
 299			foreach (var f in FactionsTable.Records)
 300			{
 301				fs.Add(f.ToXML());
 302			}
 303			gameData.Add(fs);
 304
 305			// Create Countries for save
 306			XElement cs = new  XElement("Countries");
 307			foreach (var c in CountriesTable.Records)
 308			{
 309				cs.Add(c.ToXML());
 310			}
 311			gameData.Add(cs);
 312
 313			// Create Players for save
 314			XElement ps = new  XElement("Players");
 315			foreach (var p in PlayersTable.Records)
 316			{
 317				ps.Add(p.ToXML());
 318			}
 319			gameData.Add(ps);
 320
 321			gameData.Add(new XComment("Conditions for winning the game for a faction. Winning is an OR proposition"));
 322			XElement fvcs = new XElement("FactionVictoryConditions");
 323			foreach (var fvc in FactionVictoryConditions)
 324			{
 325				XElement vc = new XElement("VictoryCondition");
 326				vc.Add(new XAttribute("Faction", fvc.Faction));
 327				vc.Add(new XAttribute("Condition", fvc.Condition));
 328				vc.Add(new XAttribute("Value", fvc.Value));
 329
 330				fvcs.Add(vc);
 331			}
 332			gameData.Add(fvcs);
 333
 334			gameData.Add(new XComment("Unit Assignments"));
 335			XElement uas = new XElement("UnitAssignments");
 336			foreach (var a in UnitAssignments)
 337			{
 338				XElement ua = new XElement("UnitAssignment");
 339				ua.Add(new XAttribute("Unit", a.Unit));
 340				ua.Add(new XAttribute("AssignedToUnit", a.AssignedToUnit));
 341
 342				uas.Add(ua);
 343			}
 344			gameData.Add(uas);
 345
 346
 347			gameData.Add(new XComment("Unit Transports"));
 348			XElement uts = new XElement("UnitTransports");
 349			foreach (var a in UnitTransports)
 350			{
 351				XElement ua = new XElement("UnitTransport");
 352				ua.Add(new XAttribute("Unit", a.Unit));
 353				ua.Add(new XAttribute("TransportUnit", a.TransportUnit));
 354
 355				uts.Add(ua);
 356			}
 357			gameData.Add(uts);
 358			
 359			gameData.Document.Save(dataFileHandler.DataFiles.GameDataFilePath);
 360		}
 361
 362		private void SaveSavedGameFile(IDataFileHandler<XDocument> dataFileHandler)
 363		{
 364			// Remove all existing GameData
 365			var gameData = dataFileHandler.DataFiles.SavedGameDataFile.Descendants("SavedGames").Single();
 366			gameData.RemoveAll();
 367
 368			foreach(var game in SavedGames.Records)
 369			{
 370				gameData.Add(game.ToXML());
 371			}
 372
 373			gameData.Document.Save(dataFileHandler.DataFiles.SavedGameDataFilePath);
 374		}
 375
 376#endregion
 377
 378#region Load
 379
 380		public override IResult<string> LoadData(string gameFileDirectory, bool IsScenario)
 381		{
 382			var r = new DataResult<string>{Status = ResultStatus.SUCCESS, Result = gameFileDirectory};
 383
 384			try
 385			{
 386				IDataFileHandler<XDocument> dataFileHandler = new DataFileHandler<XDocument>(_dataFileFactory.GetDataFiles<XDocument>(gameFileDirectory, IsScenario));
 387
 388				// ~~~~~~~~~~~~~~~~~~~~  Load up context
 389				// (Order is important for dependant objects)
 390
 391				LoadComponentData(dataFileHandler.DataFiles.ComponentDataFile);
 392				LoadLookupData(dataFileHandler.DataFiles.LookupDataFile);
 393				LoadGamedata(dataFileHandler.DataFiles.GameDataFile,
 394								dataFileHandler.DataFiles.BoardDataFile,
 395								dataFileHandler.DataFiles.UnitDataFile,
 396								dataFileHandler.DataFiles.ComponentDataFile);
 397
 398				// We need to make sure we have the last played game set correctly in the data file for saved games
 399				SaveSavedGameFile(dataFileHandler);
 400			}
 401			catch (Exception ex)
 402			{
 403				r.Status = ResultStatus.EXCEPTION;
 404				r.ex = ex;
 405				r.Messages.Add("Game data not loaded.");
 406			}
 407
 408			r.Messages.Add("Game data loaded.");
 409			return r;
 410			
 411		}
 412
 413		/// <summary>
 414		/// Load all static code data tables into context
 415		/// </summary>
 416		/// <param name="componentDataFile"></param>
 417		private void LoadComponentData(XDocument componentDataFile)
 418		{
 419			LoadBasePointValues(componentDataFile);
 420			LoadUnitBaseTypes(componentDataFile);
 421			LoadUnitGroupTypes(componentDataFile);
 422			LoadUnitTypes(componentDataFile);
 423			LoadUnitClasses(componentDataFile);
 424			LoadDemographicClasses(componentDataFile);
 425			LoadDemographicTypes(componentDataFile);
 426			LoadVictoryConditions(componentDataFile);
 427
 428			LoadMissionData(componentDataFile);
 429		}
 430
 431		/// <summary>
 432		/// Load all the lookup tables for code game code data into context
 433		/// </summary>
 434		/// <param name="lookupDataFile"></param>
 435		private void LoadLookupData(XDocument lookupDataFile)
 436		{
 437			LoadUnitBaseTypeUnitClasses(lookupDataFile);
 438			LoadUnitBaseTypeUnitGeogTypes(lookupDataFile);
 439			LoadUnitGeogTypeDemographicClasses(lookupDataFile);
 440			LoadUnitGroupTypeUnitTasks(lookupDataFile);
 441			LoadMissionObjectiveUnitTasks(lookupDataFile);
 442			LoadUnitTaskUnitClasses(lookupDataFile);
 443			LoadUnitGeogTypeMovementOverrides(lookupDataFile);
 444			LoadUnitTypeUnitGeogTypeBattleEffectives(lookupDataFile);
 445			LoadUnitTransportUnitTypeUnitClasses(lookupDataFile);
 446			LoadHybridDemographicClasses(lookupDataFile);
 447			LoadMovementHinderancesInDirection(lookupDataFile);
 448		}
 449
 450		private void LoadGamedata(	XDocument gameDataFile, 
 451									XDocument boardDataFile, 
 452									XDocument unitDataFile, 
 453									XDocument componentDataFile)
 454		{
 455			LoadBoard(boardDataFile);
 456			LoadUnits(unitDataFile);
 457			LoadFactions(gameDataFile);
 458			LoadCountries(gameDataFile);
 459			LoadPlayers(gameDataFile);
 460			LoadDemographics(gameDataFile, componentDataFile);
 461			LoadUnitAssignments(gameDataFile);
 462			LoadUnitTransports(gameDataFile);
 463			LoadFactionVictoryConditions(gameDataFile);
 464		}
 465
 466		private void LoadBasePointValues(XDocument staticDataFile)
 467		{
 468			var data = staticDataFile.Descendants("BasePointValues").Single();
 469
 470			var basePointValues = new BasePointValuesDTO
 471					(
 472						Convert.ToInt32(data.Attribute("Movement").Value),
 473						Convert.ToInt32(data.Attribute("CombatRoll").Value),
 474						Convert.ToInt32(data.Attribute("CombatBase").Value),
 475						Convert.ToInt32(data.Attribute("StealthRoll").Value),
 476						Convert.ToInt32(data.Attribute("StealthBase").Value),
 477						Convert.ToInt32(data.Attribute("MedicalSupportBase").Value),
 478						Convert.ToInt32(data.Attribute("WeightBase").Value),
 479						Convert.ToInt32(data.Attribute("CostBase").Value),
 480						Convert.ToInt32(data.Attribute("AIBaseRoll").Value),
 481						Convert.ToInt32(data.Attribute("AIAggressiveness").Value),
 482						Convert.ToInt32(data.Attribute("AIDefensiveness").Value),
 483						Convert.ToInt32(data.Attribute("AIIntelligence").Value),
 484						Convert.ToInt32(data.Attribute("ReinforcementCalcBaseCountry").Value),
 485						Convert.ToInt32(data.Attribute("ReinforcementCalcBaseFaction").Value),
 486						Convert.ToDouble(data.Attribute("ReinforcementCalcBaseVP").Value),
 487						Convert.ToDouble(data.Attribute("HQBonus").Value),
 488						Convert.ToDouble(data.Attribute("SuppliedBonus").Value),
 489						Convert.ToInt32(data.Attribute("MaxSupplyDistance").Value),
 490						Convert.ToDouble(data.Attribute("TargetAttachedUnitBonus").Value),
 491						Convert.ToDouble(data.Attribute("TargetMedicalUnitBonus").Value),
 492						Convert.ToDouble(data.Attribute("TargetSupplyUnitBonus").Value)
 493					) as IBasePointValues;
 494	
 495			this._basePointValues = basePointValues;
 496		}
 497
 498		private void LoadUnitBaseTypes(XDocument staticDataFile)
 499		{
 500			//Get base type with properties
 501			var unitBaseTypes = GetBaseComponentDTOs<UnitBaseTypeDTO>(staticDataFile.Descendants("UnitBaseType")).ToList();
 502
 503			unitBaseTypes.ForEach(o =>
 504				{
 505					o.Item1.CanReceiveMedicalSupport = Convert.ToBoolean(o.Item2.Attribute("CanReceiveMedicalSupport").Value);
 506				});
 507
 508			// Add to context
 509			this._unitBaseTypesTable.Records = unitBaseTypes.Select(p => p.Item1 as IUnitBaseTypeDTO).ToList();
 510		}
 511
 512		private void LoadVictoryConditions(XDocument staticDataFile)
 513		{
 514			var victoryConditions = GetBaseComponentDTOs<VictoryConditionDTO>(staticDataFile.Descendants("Condition"));
 515			this._victoryConditionsTable.Records = victoryConditions.Select(vc => vc.Item1 as IVictoryConditionDTO).ToList();
 516		}
 517
 518		private void LoadUnitGroupTypes(XDocument staticDataFile)
 519		{
 520			var unitGroupTypes = GetBaseComponentDTOs<UnitGroupTypeDTO>(staticDataFile.Descendants("UnitGroupType")).ToList();
 521
 522			// Set type specific properties
 523			unitGroupTypes.ForEach(o =>
 524				{
 525					o.Item1.TextDisplay = o.Item2.Attribute("TextDisplay").Value;
 526					o.Item1.Level = Convert.ToInt32(o.Item2.Attribute("Level").Value);
 527				});
 528
 529			// Add to context
 530			this._unitGroupTypesTable.Records = unitGroupTypes.Select(p => p.Item1 as IUnitGroupTypeDTO).ToList();
 531		}
 532
 533		private void LoadUnitGeogTypes(XDocument staticDataFile)
 534		{
 535			var unitGeogTypes = GetBaseComponentDTOs<UnitGeogTypeDTO>(staticDataFile.Descendants("UnitGeogType")).ToList();
 536
 537			// Add to context
 538			this._unitGeogTypesTable.Records = unitGeogTypes.Select(p => p.Item1 as IUnitGeogTypeDTO).ToList();
 539		}
 540
 541		private void LoadUnitTypes(XDocument staticDataFile)
 542		{
 543			// Get base type with properties
 544			var unitTypes = GetBaseComponentDTOs<UnitTypeDTO>(staticDataFile.Descendants("UnitType")).ToList();
 545
 546			// Set type specific properties
 547			unitTypes.ForEach(o =>
 548				{
 549					o.Item1.TextDisplay = o.Item2.Attribute("TextDisplay").Value;
 550					o.Item1.UnitBaseTypeID = Convert.ToInt32(o.Item2.Attribute("UnitBaseType").Value);
 551				});
 552
 553			// Load stat modifier data
 554			unitTypes.ForEach(o => LoadStatModifierData(o.Item2, o.Item1));
 555
 556			// Add to context
 557			this._unitTypesTable.Records = unitTypes.Select(p => p.Item1 as IUnitTypeDTO).ToList();
 558		}
 559
 560		private void LoadUnitClasses(XDocument staticDataFile)
 561		{
 562			// Get base type with properties
 563			var unitClasses = GetBaseComponentDTOs<UnitClassDTO>(staticDataFile.Descendants("UnitClass")).ToList();
 564
 565			// Set type specific properties
 566			unitClasses.ForEach(o =>
 567				{
 568					o.Item1.TextDisplay = o.Item2.Attribute("TextDisplay").Value;
 569				});
 570
 571			// Load stat modifier data
 572			unitClasses.ForEach(o => LoadStatModifierData(o.Item2, o.Item1));
 573
 574			// Add to context
 575			this._unitClassesTable.Records = unitClasses.Select(p => p.Item1 as IUnitClassDTO).ToList();
 576		}
 577
 578
 579		private void LoadMissionData(XDocument staticDataFile)
 580		{
 581			// UnitTasks
 582			var unitTasks = GetBaseComponentDTOs<UnitTaskDTO>(staticDataFile.Descendants("UnitTask")).ToList();
 583			this._unitTasksTable.Records = unitTasks.Select(p => p.Item1 as IUnitTaskDTO).ToList();
 584
 585			//MissionObjectives
 586			var missionObjectives = GetBaseComponentDTOs<MissionObjectiveDTO>(staticDataFile.Descendants("MissionObjective")).ToList();
 587
 588			missionObjectives.ForEach(o =>
 589				{
 590					o.Item1.Priority = Convert.ToInt32(o.Item2.Attribute("Priority").Value);
 591					o.Item1.TurnOrder = Convert.ToInt32(o.Item2.Attribute("TurnOrder").Value);
 592				});
 593
 594			this._missionObjectivesTable.Records = missionObjectives.Select(mo => mo.Item1 as IMissionObjectiveDTO).ToList();
 595		}
 596
 597		private void LoadDemographicClasses(XDocument staticDataFile)
 598		{
 599			// Get base type with properties
 600			var demographicClasses = GetBaseComponentDTOs<DemographicClassDTO>(staticDataFile.Descendants("DemographicClass")).ToList();
 601
 602			// Set type specific properties
 603			demographicClasses.ForEach(o =>
 604				{
 605					o.Item1.TextDisplay = o.Item2.Attribute("TextDisplay").Value;
 606					o.Item1.DemographicType = Convert.ToInt32(o.Item2.Attribute("DemographicType").Value);
 607				});
 608
 609			// Load stat modifier data
 610			demographicClasses.ForEach(o => LoadStatModifierData(o.Item2, o.Item1));
 611
 612
 613			// Add to context
 614			this._demographicClassesTable.Records = demographicClasses.Select(p => p.Item1 as IDemographicClassDTO).ToList();
 615		}
 616
 617		private void LoadDemographicTypes(XDocument staticDataFile)
 618		{
 619			// Get base type with properties
 620			var demographicTypes = GetBaseComponentDTOs<DemographicTypeDTO>(staticDataFile.Descendants("DemographicType")).ToList();
 621
 622			demographicTypes.ForEach(dt =>
 623				{
 624					dt.Item1.DisplayOrder = Convert.ToInt32(dt.Item2.Attribute("DisplayOrder").Value);
 625				});
 626
 627			// Add to context
 628			this._demographicTypesTable.Records = demographicTypes.Select(p => p.Item1 as IDemographicTypeDTO).ToList();
 629		}
 630
 631		private void LoadDemographics(XDocument gameDataFile, XDocument componentDataFile)
 632		{
 633			var defaultDemographicsList = GetBaseComponentDTOs<DemographicDTO>(componentDataFile.Descendants("Demographic")).ToList();
 634			var gameDemographicsList = GetBaseComponentDTOs<DemographicDTO>(gameDataFile.Descendants("Demographic")).ToList();
 635
 636			var demographicsList = defaultDemographicsList.Concat(gameDemographicsList).ToList();
 637
 638			// Set type specific properties
 639			demographicsList.ForEach(o =>
 640				{
 641					o.Item1.DemographicClass = Convert.ToInt32(o.Item2.Attribute("DemographicClass").Value);
 642					o.Item1.Value = o.Item2.Attribute("Value").Value;
 643				});
 644
 645			// Add to context
 646			this._demographicsTable.Records = demographicsList.Select(p => p.Item1 as IDemographicDTO).ToList();
 647		}
 648
 649
 650		private void LoadFactions(XDocument gameDataFile)
 651		{
 652			// Get base type with properties
 653			var factionList = GetBaseComponentDTOs<FactionDTO>(gameDataFile.Descendants("Faction")).ToList();
 654
 655			// Add to context
 656			this._factionsTable.Records = factionList.Select(p => p.Item1 as IFactionDTO).ToList();
 657		}
 658
 659		private void LoadCountries(XDocument gameDataFile)
 660		{
 661			// Get base type with properties
 662			var countryList = GetBaseComponentDTOs<CountryDTO>(gameDataFile.Descendants("Country")).ToList();
 663
 664			// Set type specific properties
 665			countryList.ForEach(o =>
 666				{
 667					o.Item1.Faction = Convert.ToInt32(o.Item2.Attribute("Faction").Value);
 668				});
 669
 670
 671			// Add to context
 672			this._countriesTable.Records = countryList.Select(p => p.Item1 as ICountryDTO).ToList();
 673		}
 674
 675		private void LoadPlayers(XDocument gameDataFile)
 676		{
 677			// Get base type with properties
 678			var playerList = GetBaseComponentDTOs<PlayerDTO>(gameDataFile.Descendants("Player")).ToList();
 679
 680			// Set type specific properties
 681			playerList.ForEach(o =>
 682				{
 683					var units = o.Item2.Descendants("Unit").ToList();
 684					units.ForEach(u => o.Item1.UnplacedReinforcements.Add(Convert.ToInt32(u.Attribute("ID").Value)));
 685					o.Item1.Country = Convert.ToInt32(o.Item2.Attribute("Country").Value);
 686					o.Item1.ReinforcementPoints = Convert.ToInt32(o.Item2.Attribute("ReinforcementPoints").Value);
 687					o.Item1.IsCurrentPlayer = (o.Item2.Attribute("IsCurrentPlayer") != null) && Convert.ToBoolean(o.Item2.Attribute(("IsCurrentPlayer")).Value);
 688					o.Item1.IsAIPlayer = (o.Item2.Attribute("IsAIPlayer") != null) && Convert.ToBoolean(o.Item2.Attribute(("IsAIPlayer")).Value);
 689				});
 690
 691
 692
 693
 694			// Add to context
 695			this._playersTable.Records = playerList.Select(p => p.Item1 as IPlayerDTO).ToList();
 696		}
 697
 698		private void LoadBoard(XDocument boardDataFile)
 699		{
 700			// Board Data
 701			var dimension = boardDataFile.Descendants("Attributes").SingleOrDefault();
 702			
 703			var board = new BoardDTO
 704					{
 705						Title = dimension.Attribute("Title").Value,
 706						Height = Convert.ToInt32(dimension.Attribute("Height").Value),
 707						Width = Convert.ToInt32(dimension.Attribute("Width").Value),
 708						CellSize = Convert.ToInt32(dimension.Attribute("CellSize").Value),
 709						CellMaxUnits = Convert.ToInt32(dimension.Attribute("CellSize").Value),
 710					} as IBoardDTO;			
 711
 712			var nodeList = boardDataFile.Descendants("Node");
 713			var nodesToSave = new List<INodeDTO>();
 714			var tilesToSave = new List<ITileDTO>();
 715
 716			foreach (var e in nodeList)
 717			{
 718				var c = new CoordinateDTO
 719					{
 720						X = Convert.ToInt32(e.Descendants("Coordinate").SingleOrDefault().Attribute("X").Value),
 721						Y = Convert.ToInt32(e.Descendants("Coordinate").SingleOrDefault().Attribute("Y").Value),
 722						Z = Convert.ToInt32(e.Descendants("Coordinate").SingleOrDefault().Attribute("Z").Value)
 723					} as ICoordinateDTO;
 724				
 725
 726				var dgs = e.Descendants("Demographics").Descendants("Demographic")
 727									.Select(d => 
 728										new DemographicDTO
 729											{
 730												ID = Convert.ToInt32(d.Attribute("ID").Value), 
 731												Orientation = (d.Attribute("Orientation") != null) ? d.Attribute("Orientation").Value : ""
 732											} as IDemographicDTO );								
 733						
 734
 735				var v = Convert.ToInt32(e.Descendants("Tile").SingleOrDefault().Attribute("VictoryPoints").Value);
 736
 737				var t = new TileDTO
 738							{
 739								UID = Guid.NewGuid(),
 740								VictoryPoints = v,
 741								Location = c,
 742								Demographics = dgs
 743							} as ITileDTO;
 744
 745				tilesToSave.Add(t);
 746
 747				
 748				var n = new NodeDTO
 749							{
 750								Name = "Node - {0}".F(c.ToString()),
 751								UID = Guid.NewGuid(),
 752								Location = c,
 753								Country = Convert.ToInt32(e.Descendants("Country").SingleOrDefault().Attribute("ID").Value),
 754								DefaultTile = t
 755							} as INodeDTO;
 756
 757
 758				nodesToSave.Add(n);
 759
 760			}
 761				
 762			// Add to context
 763			this._tilesTable.Records = tilesToSave;
 764			this._nodesTable.Records = nodesToSave;
 765			this._board = board;
 766		}
 767
 768		private void LoadUnits(XDocument unitDataFile)
 769		{
 770			var unitUnitList = unitDataFile.Descendants("Unit");
 771			var unitsToSave = new List<IUnitDTO>();
 772
 773			foreach (var e in unitUnitList)
 774			{
 775
 776				// No Location indicates unplaced unit
 777				var	c = (e.Descendants("Coordinate").SingleOrDefault() == null) ? null : new CoordinateDTO
 778																							{
 779																								X = Convert.ToInt32(e.Descendants("Coordinate").SingleOrDefault().Attribute("X").Value),
 780																								Y = Convert.ToInt32(e.Descendants("Coordinate").SingleOrDefault().Attribute("Y").Value),
 781																								Z = Convert.ToInt32(e.Descendants("Coordinate").SingleOrDefault().Attribute("Z").Value)
 782																							};
 783				
 784				
 785
 786				var m = new UnitDTO
 787							{
 788								ID = Convert.ToInt32(e.Attribute("ID").Value),
 789								UID = Guid.NewGuid(),
 790								Name = e.Attribute("Name").Value,
 791								SubNodeLocation = Convert.ToInt32(e.Descendants("SubNodeLocation").SingleOrDefault().Attribute("Value").Value),
 792								Location = c,
 793								Description = e.Attribute("Description").Value,
 794								Country = Convert.ToInt32(e.Descendants("Country").SingleOrDefault().Attribute("ID").Value),
 795								StackOrder = Convert.ToInt32(e.Attribute("StackOrder").Value),
 796								UnitClass = Convert.ToInt32(e.Descendants("UnitInfo").SingleOrDefault().Attribute("UnitClass").Value),
 797								UnitType = Convert.ToInt32(e.Descendants("UnitInfo").SingleOrDefault().Attribute("UnitType").Value),
 798								UnitGroupType = Convert.ToInt32(e.Descendants("UnitInfo").SingleOrDefault().Attribute("UnitGroupType").Value)
 799								
 800							};
 801
 802				// Movement stats if this is a saved game
 803				// Data saved mid-turn
 804				if (e.Descendants("MovementStats").SingleOrDefault() != null)
 805				{
 806					m.CurrentHasPerformedAction =
 807						Convert.ToBoolean(e.Descendants("MovementStats").SingleOrDefault().Attribute("CurrentHasPerformedAction").Value);
 808					m.CurrentMovementPoints =
 809						Convert.ToInt32(e.Descendants("MovementStats").SingleOrDefault().Attribute("CurrentMovementPoints").Value);
 810					m.CurrentRemoteFirePoints =
 811						Convert.ToInt32(e.Descendants("MovementStats").SingleOrDefault().Attribute("CurrentRemoteFirePoints").Value);
 812				}
 813					
 814
 815				var tu = new List<int>();
 816				unitsToSave.Add(m);
 817			}	
 818
 819
 820			this._unitsTable.Records = unitsToSave;
 821		}
 822
 823
 824		private void LoadUnitAssignments(XDocument gameDataFile)
 825		{
 826			var lookupTmp = gameDataFile.Descendants("UnitAssignment");
 827			var lookupListTmp = new List<dynamic>();
 828
 829			foreach (var e in lookupTmp)
 830			{
 831				dynamic d = new ExpandoObject();
 832				d.Unit = Convert.ToInt32(e.Attribute("Unit").Value);
 833				d.AssignedToUnit = Convert.ToInt32(e.Attribute("AssignedToUnit").Value);
 834
 835				lookupListTmp.Add(d);
 836			}
 837
 838			this._unitAssignments = lookupListTmp;
 839		}
 840
 841		private void LoadUnitTransports(XDocument gameDataFile)
 842		{
 843			var lookupTmp = gameDataFile.Descendants("UnitTransport");
 844			var lookupListTmp = new List<dynamic>();
 845
 846			foreach (var e in lookupTmp)
 847			{
 848				dynamic d = new ExpandoObject();
 849				d.Unit = Convert.ToInt32(e.Attribute("Unit").Value);
 850				d.TransportUnit = Convert.ToInt32(e.Attribute("TransportUnit").Value);
 851
 852				lookupListTmp.Add(d);
 853			}
 854
 855			this._unitTransports = lookupListTmp;
 856		}
 857
 858		private void LoadUnitBaseTypeUnitClasses(XDocument lookupDataFile)
 859		{
 860			var lookupTmp = lookupDataFile.Descendants("UnitBaseTypeUnitClass");
 861			var lookupListTmp = new List<dynamic>();
 862
 863			foreach (var e in lookupTmp)
 864			{
 865				dynamic d = new ExpandoObject();
 866				d.UnitBaseType = Convert.ToInt32(e.Attribute("UnitBaseType").Value);
 867				d.UnitClass = Convert.ToInt32(e.Attribute("UnitClass").Value);
 868
 869				lookupListTmp.Add(d);
 870			}
 871
 872			this._unitBaseTypeUnitClassesLookup = lookupListTmp;
 873		}
 874
 875		private void LoadUnitBaseTypeUnitGeogTypes(XDocument lookupDataFile)
 876		{
 877			var lookupTmp = lookupDataFile.Descendants("UnitBaseTypeUnitGeogType");
 878			var lookupListTmp = new List<dynamic>();
 879
 880			foreach (var e in lookupTmp)
 881			{
 882				dynamic d = new ExpandoObject();
 883				d.UnitBaseType = Convert.ToInt32(e.Attribute("UnitBaseType").Value);
 884				d.UnitGeogType = Convert.ToInt32(e.Attribute("UnitGeogType").Value);
 885
 886				lookupListTmp.Add(d);
 887			}
 888
 889			this._unitBaseTypeUnitGeogTypesLookup = lookupListTmp;
 890		}
 891
 892		private void LoadHybridDemographicClasses(XDocument lookupDataFile)
 893		{
 894			var lookupTmp = lookupDataFile.Descendants("HybridDemographicClass");
 895			var lookupListTmp = new List<int>();
 896
 897			foreach (var e in lookupTmp)
 898			{
 899				lookupListTmp.Add(Convert.ToInt32(e.Attribute("DemographicClass").Value));
 900			}
 901
 902			this._hybridDemographicClasses = lookupListTmp;
 903		}
 904
 905		private void LoadMovementHinderancesInDirection(XDocument lookupDataFile)
 906		{
 907			var lookupTmp = lookupDataFile.Descendants("MovementHinderance");
 908			var lookupListTmp = new List<dynamic>();
 909
 910			foreach (var e in lookupTmp)
 911			{
 912				dynamic d = new ExpandoObject();
 913				d.DemographicClass = Convert.ToInt32(e.Attribute("DemographicClass").Value);
 914				d.UnitGeogType = Convert.ToInt32(e.Attribute("UnitGeogType").Value);
 915				d.Direction = (Direction)Convert.ToInt32(e.Attribute("Direction").Value);
 916
 917				lookupListTmp.Add(d);
 918			}
 919
 920			this._movementHinderanceInDirection = lookupListTmp;
 921		}
 922
 923		private void LoadUnitGeogTypeDemographicClasses(XDocument lookupDataFile)
 924		{
 925			var lookupTmp = lookupDataFile.Descendants("UnitGeogTypeDemographicClass");
 926			var lookupListTmp = new List<dynamic>();
 927
 928			foreach (var e in lookupTmp)
 929			{
 930				dynamic d = new ExpandoObject();
 931				d.UnitGeogType = Convert.ToInt32(e.Attribute("UnitGeogType").Value);
 932				d.DemographicClass = Convert.ToInt32(e.Attribute("DemographicClass").Value);
 933
 934				lookupListTmp.Add(d);
 935			}
 936
 937			this._unitGeogTypeDemographicClassesLookup = lookupListTmp;
 938		}
 939
 940		private void LoadUnitGroupTypeUnitTasks(XDocument lookupDataFile)
 941		{
 942			var lookupTmp = lookupDataFile.Descendants("UnitGroupTypeUnitTask");
 943			var lookupListTmp = new List<dynamic>();
 944
 945			foreach (var e in lookupTmp)
 946			{
 947				dynamic d = new ExpandoObject();
 948				d.UnitGroupType = Convert.ToInt32(e.Attribute("UnitGroupType").Value);
 949				d.UnitTask = Convert.ToInt32(e.Attribute("UnitTask").Value);
 950
 951				lookupListTmp.Add(d);
 952			}
 953
 954			this._unitGroupTypeUnitTaskLookup = lookupListTmp;
 955		}
 956
 957		private void LoadMissionObjectiveUnitTasks(XDocument lookupDataFile)
 958		{
 959			var lookupTmp = lookupDataFile.Descendants("MissionObjectiveUnitTask");
 960			var lookupListTmp = new List<dynamic>();
 961
 962			foreach (var e in lookupTmp)
 963			{
 964				dynamic d = new ExpandoObject();
 965				d.MissionObjective = Convert.ToInt32(e.Attribute("MissionObjective").Value);
 966				d.UnitTask = Convert.ToInt32(e.Attribute("UnitTask").Value);
 967				d.StepOrder = Convert.ToInt32(e.Attribute("StepOrder").Value);
 968
 969				lookupListTmp.Add(d);
 970			}
 971
 972			this._missionObjectiveUnitTasks = lookupListTmp;
 973		}
 974
 975		private void LoadUnitTaskUnitClasses(XDocument lookupDataFile)
 976		{
 977			var lookupTmp = lookupDataFile.Descendants("UnitTaskUnitClass");
 978			var lookupListTmp = new List<dynamic>();
 979
 980			foreach (var e in lookupTmp)
 981			{
 982				dynamic d = new ExpandoObject();
 983				d.UnitClass = Convert.ToInt32(e.Attribute("UnitClass").Value);
 984				d.UnitTask = Convert.ToInt32(e.Attribute("UnitTask").Value);
 985
 986				lookupListTmp.Add(d);
 987			}
 988
 989			this._unitTaskUnitClassesLookup = lookupListTmp;
 990		}
 991
 992		private void LoadUnitGeogTypeMovementOverrides(XDocument lookupDataFile)
 993		{
 994			var lookupTmp = lookupDataFile.Descendants("UnitGeogTypeMovementOverrides").First().Descendants("Override");
 995			var lookupListTmp = new List<dynamic>();
 996
 997			foreach (var e in lookupTmp)
 998			{
 999				dynamic d = new ExpandoObject();
1000				d.UnitGeogType = Convert.ToInt32(e.Attribute("UnitGeogType").Value);
1001				d.Geography = Convert.ToInt32(e.Attribute("DemographicClassA").Value);
1002				d.Infrastructure = Convert.ToInt32(e.Attribute("DemographicClassB").Value);
1003
1004				lookupListTmp.Add(d);
1005			}
1006
1007			this._unitGeogTypeMovementOverrides = lookupListTmp;
1008		}
1009
1010		private void LoadUnitTypeUnitGeogTypeBattleEffectives(XDocument lookupDataFile)
1011		{
1012			var lookupTmp = lookupDataFile.Descendants("UnitTypeUnitGeogTypeBattleEffective").First().Descendants("BattleEffective");
1013			var lookupListTmp = new List<dynamic>();
1014
1015			foreach (var e in lookupTmp)
1016			{
1017				dynamic d = new ExpandoObject();
1018				d.UnitType = Convert.ToInt32(e.Attribute("UnitType").Value);
1019				d.UnitGeogType = Convert.ToInt32(e.Attribute("UnitGeogType").Value);
1020
1021				lookupListTmp.Add(d);
1022			}
1023
1024			this._unitBattleEffectiveLookup = lookupListTmp;
1025		}
1026
1027		private void LoadUnitTransportUnitTypeUnitClasses(XDocument lookupDataFile)
1028		{
1029			var lookupTmp = lookupDataFile.Descendants("UnitTransportUnitTypeUnitClasses").First().Descendants("TransportEffective");
1030			var lookupListTmp = new List<dynamic>();
1031
1032			foreach (var e in lookupTmp)
1033			{
1034				dynamic d = new ExpandoObject();
1035				d.TransportUnitType = Convert.ToInt32(e.Attribute("TransportUnitType").Value);
1036				d.CarriedUnitType = Convert.ToInt32(e.Attribute("CarriedUnitType").Value);
1037				d.CarriedUnitClass = Convert.ToInt32(e.Attribute("CarriedUnitClass").Value);
1038
1039				lookupListTmp.Add(d);
1040			}
1041
1042			this._unitTransportUnitTypeUnitClasses = lookupListTmp;
1043		}		
1044
1045		private void LoadFactionVictoryConditions(XDocument gameDataFile)
1046		{
1047			var lookupTmp = gameDataFile.Descendants("VictoryCondition");
1048			var lookupListTmp = new List<dynamic>();
1049
1050			foreach (var e in lookupTmp)
1051			{
1052				dynamic d = new ExpandoObject();
1053				d.Faction = Convert.ToInt32(e.Attribute("Faction").Value);
1054				d.Condition = Convert.ToInt32(e.Attribute("Condition").Value);
1055				d.Value = Convert.ToInt32(e.Attribute("Value").Value);
1056
1057				lookupListTmp.Add(d);
1058			}
1059
1060			this._factionVictoryConditions = lookupListTmp;
1061		}
1062
1063#endregion
1064
1065#region Helper Methods
1066
1067		/// <summary>
1068		/// Returns a list of IBaseGameComponentDTO and matching source elements with the properties set from the data source
1069		/// </summary>
1070		/// <typeparam name="T"></typeparam>
1071		/// <param name="elements"></param>
1072		/// <returns></returns>
1073		private IEnumerable<Tuple<T, XElement>> GetBaseComponentDTOs<T>(IEnumerable<XElement> elements)
1074			where T : class, IBaseGameComponentDTO, new() 
1075		{
1076			var retVal = elements
1077						.Select(c => new {element = c, pair = new Tuple<T, XElement>(GetBaseComponentDTO<T>(c), c)})
1078						.Select(p => p.pair);
1079
1080			return retVal;
1081		}
1082
1083		/// <summary>
1084		/// Returns an IBaseGameComponentDTO with the properties set from the data source
1085		/// </summary>
1086		/// <typeparam name="T"></typeparam>
1087		/// <param name="e"></param>
1088		/// <returns></returns>
1089		private T GetBaseComponentDTO<T>(XElement e) 
1090			where T : class, IBaseGameComponentDTO, new()
1091		{
1092			var retVal = new T
1093						{
1094							UID = Guid.NewGuid(),
1095							Name = e.Attribute("Name").Value, 
1096							Description = e.Attribute("Description").Value,
1097							ID = Convert.ToInt32(e.Attribute("ID").Value)
1098						} ;
1099
1100			return retVal;
1101		}
1102
1103		
1104		private void LoadStatModifierData(XElement e, IStatModifier dto)
1105		{
1106			dto.AttackModifier = (e.Attribute("AttackModifier") != null) ? Convert.ToDouble(e.Attribute("AttackModifier").Value) : 0;
1107			dto.AttackDistanceModifier = (e.Attribute("AttackDistanceModifier") != null) ? Convert.ToDouble(e.Attribute("AttackDistanceModifier").Value) : 0;
1108			dto.DefenceModifier = (e.Attribute("DefenceModifier") != null) ? Convert.ToDouble(e.Attribute("DefenceModifier").Value) : 0;
1109			dto.MovementModifier = (e.Attribute("MovementModifier") != null) ? Convert.ToDouble(e.Attribute("MovementModifier").Value) : 0;
1110			dto.UnitWeightModifier = (e.Attribute("UnitWeightModifier") != null) ? Convert.ToDouble(e.Attribute("UnitWeightModifier").Value) : 0;
1111			dto.AllowableWeightModifier = (e.Attribute("AllowableWeightModifier") != null) ? Convert.ToDouble(e.Attribute("AllowableWeightModifier").Value) : 0;
1112			dto.UnitCostModifier = (e.Attribute("UnitCostModifier") != null) ? Convert.ToDouble(e.Attribute("UnitCostModifier").Value) : 0;
1113			dto.StealthModifier = (e.Attribute("StealthModifier") != null) ? Convert.ToDouble(e.Attribute("StealthModifier").Value) : 0;
1114		}
1115
1116#endregion	
1117		
1118
1119	}
1120
1121
1122
1123}