CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

TeamColorManager.cs (3321B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // The Command & Conquer Map Editor and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // The Command & Conquer Map Editor and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 using System.Collections.Generic;
     16 using System.Linq;
     17 using System.Xml;
     18 
     19 namespace MobiusEditor.Utility
     20 {
     21     public class TeamColorManager
     22     {
     23         private readonly Dictionary<string, TeamColor> teamColors = new Dictionary<string, TeamColor>();
     24 
     25         private readonly MegafileManager megafileManager;
     26 
     27         public TeamColor this[string key] => !string.IsNullOrEmpty(key) ? teamColors[key] : null;
     28 
     29         public TeamColorManager(MegafileManager megafileManager)
     30         {
     31             this.megafileManager = megafileManager;
     32         }
     33 
     34         public void Reset()
     35         {
     36             teamColors.Clear();
     37         }
     38 
     39         public void Load(string xmlPath)
     40         {
     41             XmlDocument xmlDoc = new XmlDocument();
     42             xmlDoc.Load(megafileManager.Open(xmlPath));
     43 
     44             foreach (XmlNode teamColorNode in xmlDoc.SelectNodes("/*/TeamColorTypeClass"))
     45             {
     46                 var teamColor = new TeamColor(this, megafileManager);
     47                 teamColor.Load(teamColorNode.OuterXml);
     48 
     49                 teamColors[teamColorNode.Attributes["Name"].Value] = teamColor;
     50             }
     51 
     52             foreach (var teamColor in TopologicalSortTeamColors())
     53             {
     54                 teamColor.Flatten();
     55             }
     56         }
     57 
     58         private IEnumerable<TeamColor> TopologicalSortTeamColors()
     59         {
     60             var nodes = teamColors.Values.ToList();
     61             HashSet<(TeamColor, TeamColor)> edges = new HashSet<(TeamColor, TeamColor)>();
     62             foreach (var node in nodes)
     63             {
     64                 if (!string.IsNullOrEmpty(node.Variant))
     65                 {
     66                     edges.Add((this[node.Variant], node));
     67                 }
     68             }
     69 
     70             var sorted = new List<TeamColor>();
     71             var openSet = new HashSet<TeamColor>(nodes.Where(n => edges.All(e => !e.Item2.Equals(n))));
     72             while (openSet.Count > 0)
     73             {
     74                 var node = openSet.First();
     75                 openSet.Remove(node);
     76                 sorted.Add(node);
     77 
     78                 foreach (var edge in edges.Where(e => e.Item1.Equals(node)).ToArray())
     79                 {
     80                     var node2 = edge.Item2;
     81                     edges.Remove(edge);
     82 
     83                     if (edges.All(edge2 => !edge2.Item2.Equals(node2)))
     84                     {
     85                         openSet.Add(node2);
     86                     }
     87                 }
     88             }
     89 
     90             return (edges.Count == 0) ? sorted : null;
     91         }
     92     }
     93 }