mirror of
				https://github.com/Nioux/AideDeJeu.git
				synced 2025-10-31 07:26:09 +00:00 
			
		
		
		
	Début nettoyage
This commit is contained in:
		
							parent
							
								
									dbe163a487
								
							
						
					
					
						commit
						9b8f86ab63
					
				
					 9 changed files with 1 additions and 1407 deletions
				
			
		|  | @ -8,7 +8,6 @@ namespace AideDeJeuLib.Monsters | ||||||
| { | { | ||||||
|     public class Monster : Item |     public class Monster : Item | ||||||
|     { |     { | ||||||
|         public string Power { get; set; } |  | ||||||
|         public string Type { get; set; } |         public string Type { get; set; } | ||||||
|         public string Size { get; set; } |         public string Size { get; set; } | ||||||
|         public string Alignment { get; set; } |         public string Alignment { get; set; } | ||||||
|  | @ -33,198 +32,10 @@ namespace AideDeJeuLib.Monsters | ||||||
|         public string Languages { get; set; } |         public string Languages { get; set; } | ||||||
|         public string Challenge { get; set; } |         public string Challenge { get; set; } | ||||||
|         public string Description { get; set; } |         public string Description { get; set; } | ||||||
|         private string _Picture = null; |  | ||||||
|         public string Picture |  | ||||||
|         { |  | ||||||
|             get |  | ||||||
|             { |  | ||||||
|                 if(_Picture != null) |  | ||||||
|                 { |  | ||||||
|                     return "https://raw.githubusercontent.com/Nioux/AideDeJeu/master/Data/Monsters" + _Picture.Substring(_Picture.LastIndexOf('/')); |  | ||||||
|                 } |  | ||||||
|                 return null; |  | ||||||
|             } |  | ||||||
|             set |  | ||||||
|             { |  | ||||||
|                 _Picture = value; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         public IEnumerable<string> SpecialFeatures { get; set; } |         public IEnumerable<string> SpecialFeatures { get; set; } | ||||||
|         [IgnoreDataMember] |  | ||||||
|         public IEnumerable<XmlNode> SpecialFeaturesNodes |  | ||||||
|         { |  | ||||||
|             set |  | ||||||
|             { |  | ||||||
|                 SpecialFeatures = NodeListToStringList(value); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public IEnumerable<string> Actions { get; set; } |         public IEnumerable<string> Actions { get; set; } | ||||||
|         [IgnoreDataMember] |  | ||||||
|         public IEnumerable<XmlNode> ActionsNodes |  | ||||||
|         { |  | ||||||
|             set |  | ||||||
|             { |  | ||||||
|                 Actions = NodeListToStringList(value); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public IEnumerable<string> Reactions { get; set; } |         public IEnumerable<string> Reactions { get; set; } | ||||||
| 
 |  | ||||||
|         public IEnumerable<string> LegendaryActions { get; set; } |         public IEnumerable<string> LegendaryActions { get; set; } | ||||||
|         [IgnoreDataMember] |  | ||||||
|         public IEnumerable<XmlNode> LegendaryActionsNodes |  | ||||||
|         { |  | ||||||
|             set |  | ||||||
|             { |  | ||||||
|                 LegendaryActions = NodeListToStringList(value); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|         public void ParseHtml() |  | ||||||
|         { |  | ||||||
|             var pack = new XmlDocument(); |  | ||||||
|             pack.LoadXml(this.Html); |  | ||||||
|             var divSpell = pack.DocumentElement.SelectSingleNode("//div[contains(@class,'bloc')]"); |  | ||||||
|             ParseNode(divSpell); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         //public static Monster FromHtml(HtmlNode divBloc) |  | ||||||
|         //{ |  | ||||||
|         public void ParseNode(XmlNode divBloc) |  | ||||||
|         { |  | ||||||
|             //monster.Html = divBloc.OuterHtml; |  | ||||||
|             var divMonster = divBloc?.SelectSingleNode("div[contains(@class,'monstre')]"); |  | ||||||
|             this.Name = divMonster?.SelectSingleNode("h1").InnerText; |  | ||||||
| 
 |  | ||||||
|             var divTrad = divMonster.SelectSingleNode("div[@class='trad']"); |  | ||||||
| 
 |  | ||||||
|             var linkVO = divTrad.SelectSingleNode("a").Attributes["href"].InnerText; |  | ||||||
|             var matchIdVF = new Regex(@"\?vf=(?<idvf>.*)").Match(linkVO); |  | ||||||
|             this.IdVF = matchIdVF?.Groups["idvf"]?.Value; |  | ||||||
|             var matchIdVO = new Regex(@"\?vo=(?<idvo>.*)").Match(linkVO); |  | ||||||
|             this.IdVO = matchIdVO?.Groups["idvo"]?.Value; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|             var altNames = divTrad?.InnerText; |  | ||||||
|             if (altNames != null) |  | ||||||
|             { |  | ||||||
|                 var matchNames = new Regex(@"\[ (?<vo>.*?) \](?: \[ (?<alt>.*?) \])?").Match(altNames); |  | ||||||
|                 this.NameVO = matchNames.Groups["vo"].Value; |  | ||||||
|                 this.NamePHB = string.IsNullOrEmpty(matchNames.Groups["alt"].Value) ? this.Name : matchNames.Groups["alt"].Value; |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 this.NamePHB = this.Name; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             var divSansSerif = divMonster?.SelectSingleNode("div[contains(@class,'sansSerif')]"); |  | ||||||
|             var typeSizeAlignment = divSansSerif?.SelectSingleNode("h2/em")?.InnerText; |  | ||||||
|             if (typeSizeAlignment != null) |  | ||||||
|             { |  | ||||||
|                 var matchesTypeSizeAlignment = new Regex("(?<type>.*) de taille (?<size>.*), (?<alignment>.*)").Match(typeSizeAlignment); |  | ||||||
|                 this.Type = matchesTypeSizeAlignment?.Groups["type"]?.Value?.Trim(); |  | ||||||
|                 this.Size = matchesTypeSizeAlignment?.Groups["size"]?.Value?.Trim(); |  | ||||||
|                 this.Alignment = matchesTypeSizeAlignment?.Groups["alignment"]?.Value?.Trim(); |  | ||||||
| 
 |  | ||||||
|                 if (string.IsNullOrEmpty(this.Type)) |  | ||||||
|                 { |  | ||||||
|                     matchesTypeSizeAlignment = new Regex("(?<size>.*) (?<type>.*), (?<alignment>.*)").Match(typeSizeAlignment); |  | ||||||
|                     this.Type = matchesTypeSizeAlignment?.Groups["type"]?.Value?.Trim(); |  | ||||||
|                     this.Size = matchesTypeSizeAlignment?.Groups["size"]?.Value?.Trim(); |  | ||||||
|                     this.Alignment = matchesTypeSizeAlignment?.Groups["alignment"]?.Value?.Trim(); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             var divRed = divSansSerif?.SelectSingleNode("div[contains(@class,'red')]"); |  | ||||||
|             this.ArmorClass = divRed?.SelectSingleNode("strong[contains(text(),'armure') or contains(text(),'Armor Class')]")?.NextSibling?.InnerText; |  | ||||||
|             this.HitPoints = divRed?.SelectSingleNode("strong[contains(text(),'Points de vie') or contains(text(),'Hit Points')]")?.NextSibling?.InnerText; |  | ||||||
|             this.Speed = divRed?.SelectSingleNode("strong[contains(text(),'Vitesse') or contains(text(),'Speed')]")?.NextSibling?.InnerText; |  | ||||||
| 
 |  | ||||||
|             this.Strength = divRed?.SelectSingleNode("div[contains(@class,'carac')]/strong[contains(text(),'FOR') or contains(text(),'STR')]")?.NextSibling?.NextSibling?.InnerText; |  | ||||||
|             this.Dexterity = divRed?.SelectSingleNode("div[contains(@class,'carac')]/strong[contains(text(),'DEX')]")?.NextSibling?.NextSibling?.InnerText; |  | ||||||
|             this.Constitution = divRed?.SelectSingleNode("div[contains(@class,'carac')]/strong[contains(text(),'CON')]")?.NextSibling?.NextSibling?.InnerText; |  | ||||||
|             this.Intelligence = divRed?.SelectSingleNode("div[contains(@class,'carac')]/strong[contains(text(),'INT')]")?.NextSibling?.NextSibling?.InnerText; |  | ||||||
|             this.Wisdom = divRed?.SelectSingleNode("div[contains(@class,'carac')]/strong[contains(text(),'SAG') or contains(text(),'WIS')]")?.NextSibling?.NextSibling?.InnerText; |  | ||||||
|             this.Charisma = divRed?.SelectSingleNode("div[contains(@class,'carac')]/strong[contains(text(),'CHA')]")?.NextSibling?.NextSibling?.InnerText; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|             this.SavingThrows = divRed?.SelectSingleNode("strong[contains(text(),'Jets de sauvegarde') or contains(text(),'Saving Throws')]")?.NextSibling?.InnerText; |  | ||||||
|             this.Skills = divRed?.SelectSingleNode("strong[contains(text(),'Compétences') or contains(text(),'Skills')]")?.NextSibling?.InnerText; |  | ||||||
|              |  | ||||||
|             this.DamageVulnerabilities = divRed?.SelectSingleNode("strong[contains(text(),'Vulnérabilités aux dégâts') or contains(text(),'Damage vulnerabilities')]")?.NextSibling?.InnerText; |  | ||||||
|             this.DamageResistances = divRed?.SelectSingleNode("strong[contains(text(),'Résistances aux dégâts') or contains(text(),'Damage Resistances')]")?.NextSibling?.InnerText; |  | ||||||
|             this.DamageImmunities = divRed?.SelectSingleNode("strong[contains(text(),'Immunités aux dégâts') or contains(text(),'Damage Immunities')]")?.NextSibling?.InnerText; |  | ||||||
|             this.ConditionImmunities = divRed?.SelectSingleNode("strong[contains(text(),'Immunités aux conditions') or contains(text(),'Conditions Immunities')]")?.NextSibling?.InnerText; |  | ||||||
| 
 |  | ||||||
|             this.Senses = divRed?.SelectSingleNode("strong[contains(text(),'Sens') or contains(text(),'Senses')]")?.NextSibling?.InnerText; |  | ||||||
|             this.Languages = divRed?.SelectSingleNode("strong[contains(text(),'Langues') or contains(text(),'Languages')]")?.NextSibling?.InnerText; |  | ||||||
|             this.Challenge = divRed?.SelectSingleNode("strong[contains(text(),'Puissance') or contains(text(),'Challenge')]")?.NextSibling?.InnerText; |  | ||||||
| 
 |  | ||||||
|             List<XmlNode> nodes = new List<XmlNode>(); |  | ||||||
|             List<XmlNode> specialFeatures = null; |  | ||||||
|             List<XmlNode> actions = null; |  | ||||||
|             List<XmlNode> legendaryActions = null; |  | ||||||
|             var node = divSansSerif.SelectSingleNode("p"); |  | ||||||
|             while(node != null) |  | ||||||
|             { |  | ||||||
|                 if(node.NodeType == XmlNodeType.Element && node.Name == "div") |  | ||||||
|                 { |  | ||||||
|                     if(node.InnerText == "ACTIONS") |  | ||||||
|                     { |  | ||||||
|                         specialFeatures = nodes; |  | ||||||
|                         nodes = new List<XmlNode>(); |  | ||||||
|                     } |  | ||||||
|                     else if (node.InnerText == "ACTIONS LÉGENDAIRES" || node.InnerText == "LEGENDARY ACTIONS") |  | ||||||
|                     { |  | ||||||
|                         actions = nodes; |  | ||||||
|                         nodes = new List<XmlNode>(); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     nodes.Add(node); |  | ||||||
|                 } |  | ||||||
|                 node = node.NextSibling; |  | ||||||
|             } |  | ||||||
|             if(actions == null) |  | ||||||
|             { |  | ||||||
|                 if(specialFeatures == null) |  | ||||||
|                 { |  | ||||||
|                     specialFeatures = nodes; |  | ||||||
|                 } |  | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     actions = nodes; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 legendaryActions = nodes; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             this.SpecialFeaturesNodes = specialFeatures; |  | ||||||
|             this.ActionsNodes = actions; |  | ||||||
|             //this.ReactionsNodes = actions; |  | ||||||
|             this.LegendaryActionsNodes = legendaryActions; |  | ||||||
| 
 |  | ||||||
|             var divDescription = divBloc?.SelectSingleNode("div[contains(@class,'description')]"); |  | ||||||
|             this.Description = divDescription?.InnerText; |  | ||||||
| 
 |  | ||||||
|             var divSource = divBloc?.SelectSingleNode("div[contains(@class,'source')]"); |  | ||||||
|             this.Source = divSource?.InnerText; |  | ||||||
| 
 |  | ||||||
|             var img = divBloc?.SelectSingleNode("div[contains(@class,'center')]/img[contains(@class,'picture')]"); |  | ||||||
|             this.Picture = img?.Attributes["src"].InnerText; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public static Monster FromHtml(XmlNode node) |  | ||||||
|         { |  | ||||||
|             var monster = new Monster(); |  | ||||||
|             monster.Html = node.OuterXml; |  | ||||||
|             monster.ParseNode(node); |  | ||||||
|             return monster; |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,138 +0,0 @@ | ||||||
| using System; |  | ||||||
| using System.Collections.Generic; |  | ||||||
| using System.Linq; |  | ||||||
| using System.Net.Http; |  | ||||||
| using System.Text; |  | ||||||
| using System.Text.RegularExpressions; |  | ||||||
| using System.Threading.Tasks; |  | ||||||
| using System.Xml; |  | ||||||
| 
 |  | ||||||
| namespace AideDeJeuLib.Monsters |  | ||||||
| { |  | ||||||
|     public class MonstersScrappers : IDisposable |  | ||||||
|     { |  | ||||||
|         private HttpClient _Client = null; |  | ||||||
|         public HttpClient GetHttpClient() |  | ||||||
|         { |  | ||||||
|             if (_Client == null) |  | ||||||
|             { |  | ||||||
|                 var client = new HttpClient(); |  | ||||||
|                 client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("text/html")); |  | ||||||
|                 client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/xhtml+xml")); |  | ||||||
|                 client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/xml")); |  | ||||||
|                 client.DefaultRequestHeaders.AcceptLanguage.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("fr")); |  | ||||||
|                 client.DefaultRequestHeaders.AcceptLanguage.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("fr-FR")); |  | ||||||
|                 _Client = client; |  | ||||||
|             } |  | ||||||
|             return _Client; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         #region IDisposable Support |  | ||||||
|         private bool disposedValue = false; // Pour détecter les appels redondants |  | ||||||
| 
 |  | ||||||
|         protected virtual void Dispose(bool disposing) |  | ||||||
|         { |  | ||||||
|             if (!disposedValue) |  | ||||||
|             { |  | ||||||
|                 if (disposing) |  | ||||||
|                 { |  | ||||||
|                     // TODO: supprimer l'état managé (objets managés). |  | ||||||
|                     if (_Client != null) |  | ||||||
|                     { |  | ||||||
|                         _Client.Dispose(); |  | ||||||
|                         _Client = null; |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 // TODO: libérer les ressources non managées (objets non managés) et remplacer un finaliseur ci-dessous. |  | ||||||
|                 // TODO: définir les champs de grande taille avec la valeur Null. |  | ||||||
| 
 |  | ||||||
|                 disposedValue = true; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // TODO: remplacer un finaliseur seulement si la fonction Dispose(bool disposing) ci-dessus a du code pour libérer les ressources non managées. |  | ||||||
|         // ~SpellsScrappers() { |  | ||||||
|         //   // Ne modifiez pas ce code. Placez le code de nettoyage dans Dispose(bool disposing) ci-dessus. |  | ||||||
|         //   Dispose(false); |  | ||||||
|         // } |  | ||||||
| 
 |  | ||||||
|         // Ce code est ajouté pour implémenter correctement le modèle supprimable. |  | ||||||
|         public void Dispose() |  | ||||||
|         { |  | ||||||
|             // Ne modifiez pas ce code. Placez le code de nettoyage dans Dispose(bool disposing) ci-dessus. |  | ||||||
|             Dispose(true); |  | ||||||
|             // TODO: supprimer les marques de commentaire pour la ligne suivante si le finaliseur est remplacé ci-dessus. |  | ||||||
|             // GC.SuppressFinalize(this); |  | ||||||
|         } |  | ||||||
|         #endregion |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|         public async Task<IEnumerable<Monster>> GetMonsters(string category = "", string type = "", string minPower = "", string maxPower = "", string size = "", string legendary = "", string source = "srd") |  | ||||||
|         { |  | ||||||
|             string html = null; |  | ||||||
|             var client = GetHttpClient(); |  | ||||||
|             // https://www.aidedd.org/regles/monstres/?min=.25&max=20&c=M&sz=TP&lg=si&t=Humano%C3%AFde&s=srd |  | ||||||
| 
 |  | ||||||
|             //html = await client.GetStringAsync(string.Format($"https://www.aidedd.org/regles/monstres/?c={category}&t={type}&min={minPower}&max={maxPower}&sz={size}&lg={legendary}&s={source}", category, type, minPower, maxPower, size, legendary, source)); |  | ||||||
|             var url = string.Format($"https://www.aidedd.org/dnd-filters/monstres.php?c={category}&t={type}&min={minPower}&max={maxPower}&sz={size}&lg={legendary}&s={source}", category, type, minPower, maxPower, size, legendary, source); |  | ||||||
|             html = await client.GetStringAsync(url); |  | ||||||
| 
 |  | ||||||
|             var pack = new XmlDocument(); |  | ||||||
|             pack.LoadXml(html); |  | ||||||
|             //var trs = pack.GetElementbyId("liste").Element("table").Elements("tr").ToList(); |  | ||||||
|             var trs = pack.DocumentElement.SelectSingleNode("//table[contains(@class,'liste')]").SelectNodes("tr"); |  | ||||||
|             var monsters = new List<Monster>(); |  | ||||||
|             foreach (var tro in trs) |  | ||||||
|             { |  | ||||||
|                 var tr = tro as XmlNode; |  | ||||||
|                 var tds = tr.SelectNodes("td"); |  | ||||||
|                 if (tds.Count > 0) |  | ||||||
|                 { |  | ||||||
|                     var monster = new Monster(); |  | ||||||
|                     var aname = tds[1].SelectSingleNode("a"); |  | ||||||
|                     var spanname = aname.SelectSingleNode("span"); |  | ||||||
|                     if (spanname != null) |  | ||||||
|                     { |  | ||||||
|                         monster.NamePHB = spanname.Attributes["title"].InnerText; |  | ||||||
|                         monster.Name = spanname.InnerText; |  | ||||||
|                     } |  | ||||||
|                     else |  | ||||||
|                     { |  | ||||||
|                         monster.NamePHB = aname.InnerText; |  | ||||||
|                         monster.Name = aname.InnerText; |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                     //monster.Name = tds[0].InnerText; |  | ||||||
|                     var href = aname.Attributes["href"].InnerText; |  | ||||||
|                     var regex = new Regex("vf=(?<id>.*)"); |  | ||||||
|                     monster.Id = regex.Match(href).Groups["id"].Value; |  | ||||||
|                     monster.Power = tds[2].InnerText; |  | ||||||
|                     monster.Type = tds[3].InnerText; |  | ||||||
|                     monster.Size = tds[4].InnerText; |  | ||||||
|                     monster.Alignment = tds[5].InnerText; |  | ||||||
|                     monster.Legendary = tds[6].InnerText; |  | ||||||
|                     monsters.Add(monster); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             return monsters; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public async Task<Monster> GetMonster(string id) |  | ||||||
|         { |  | ||||||
|             string html = null; |  | ||||||
|             var client = GetHttpClient(); |  | ||||||
|             // https://www.aidedd.org/dnd/monstres.php?vf=aarakocra |  | ||||||
| 
 |  | ||||||
|             html = await client.GetStringAsync(string.Format($"https://www.aidedd.org/dnd/monstres.php?vf={id}", id)); |  | ||||||
| 
 |  | ||||||
|             var pack = new XmlDocument(); |  | ||||||
|             pack.LoadXml(html); |  | ||||||
|             var divBloc = pack.DocumentElement.SelectSingleNode("//div[contains(@class,'bloc')]"); |  | ||||||
|             var monster = Monster.FromHtml(divBloc); |  | ||||||
|             monster.Id = id; |  | ||||||
|             return monster; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -87,54 +87,5 @@ namespace AideDeJeuLib.Spells | ||||||
|         public string NoOverflow { get; set; } |         public string NoOverflow { get; set; } | ||||||
|         public string Source { get; set; } |         public string Source { get; set; } | ||||||
| 
 | 
 | ||||||
|         public void ParseHtml() |  | ||||||
|         { |  | ||||||
|             var pack = new XmlDocument(); |  | ||||||
|             pack.LoadXml(this.Html); |  | ||||||
|             var divSpell = pack.DocumentElement.SelectSingleNode("//div[contains(@class,'bloc')]"); |  | ||||||
|             ParseNode(divSpell); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public void ParseNode(XmlNode nodeSpell) |  | ||||||
|         { |  | ||||||
|             this.Name = nodeSpell.SelectSingleNode("h1").InnerText; |  | ||||||
|             var divTrad = nodeSpell.SelectSingleNode("div[@class='trad']"); |  | ||||||
|              |  | ||||||
|             var linkVO = divTrad.SelectSingleNode("a").Attributes["href"].InnerText; |  | ||||||
|             var matchIdVF = new Regex(@"\?vf=(?<idvf>.*)").Match(linkVO); |  | ||||||
|             this.IdVF = matchIdVF?.Groups["idvf"]?.Value; |  | ||||||
|             var matchIdVO = new Regex(@"\?vo=(?<idvo>.*)").Match(linkVO); |  | ||||||
|             this.IdVO = matchIdVO?.Groups["idvo"]?.Value; |  | ||||||
|             var altNames = divTrad?.InnerText; |  | ||||||
|             if (altNames != null) |  | ||||||
|             { |  | ||||||
|                 var matchNames = new Regex(@"\[ (?<vo>.*?) \](?: \[ (?<alt>.*?) \])?").Match(altNames); |  | ||||||
|                 this.NameVO = matchNames.Groups["vo"].Value; |  | ||||||
|                 this.NamePHB = string.IsNullOrEmpty(matchNames.Groups["alt"].Value) ? this.Name : matchNames.Groups["alt"].Value; |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 this.NamePHB = this.Name; |  | ||||||
|             } |  | ||||||
|             this.LevelType = nodeSpell.SelectSingleNode("h2/em").InnerText; |  | ||||||
|             this.Level = this.LevelType.Split(new string[] { " - " }, StringSplitOptions.None)[0].Split(' ')[1]; |  | ||||||
|             this.Type = this.LevelType.Split(new string[] { " - " }, StringSplitOptions.None)[1]; |  | ||||||
|             this.CastingTime = nodeSpell.SelectSingleNode("div[@class='paragraphe']").InnerText.Split(new string[] { ": " }, StringSplitOptions.None)[1]; |  | ||||||
|             this.Range = nodeSpell.SelectSingleNode("div[strong/text()='Portée' or strong/text()='Range']").InnerText.Split(new string[] { ": " }, StringSplitOptions.None)[1]; |  | ||||||
|             this.Components = nodeSpell.SelectSingleNode("div[strong/text()='Composantes' or strong/text()='Components']")?.InnerText?.Split(new string[] { ": " }, StringSplitOptions.None)?[1]; |  | ||||||
|             this.Duration = nodeSpell.SelectSingleNode("div[strong/text()='Durée' or strong/text()='Duration']").InnerText.Split(new string[] { ": " }, StringSplitOptions.None)[1]; |  | ||||||
|             this.DescriptionDiv = nodeSpell.SelectSingleNode("div[contains(@class,'description')]"); |  | ||||||
|             this.Overflow = nodeSpell.SelectSingleNode("div[@class='overflow']")?.InnerText; |  | ||||||
|             this.NoOverflow = nodeSpell.SelectSingleNode("div[@class='nooverflow']")?.InnerText; |  | ||||||
|             this.Source = nodeSpell.SelectSingleNode("div[@class='source']").InnerText; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public static Spell FromHtml(XmlNode nodeSpell) |  | ||||||
|         { |  | ||||||
|             var spell = new Spell(); |  | ||||||
|             spell.Html = nodeSpell.OuterXml; |  | ||||||
|             spell.ParseNode(nodeSpell); |  | ||||||
|             return spell; |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,302 +0,0 @@ | ||||||
| using System; |  | ||||||
| using System.Collections.Generic; |  | ||||||
| using System.Linq; |  | ||||||
| using System.Net.Http; |  | ||||||
| using System.Text.RegularExpressions; |  | ||||||
| using System.Threading.Tasks; |  | ||||||
| using System.Xml; |  | ||||||
| using System.Xml.Linq; |  | ||||||
| 
 |  | ||||||
| namespace AideDeJeuLib.Spells |  | ||||||
| { |  | ||||||
|     public class SpellsScrappers : IDisposable |  | ||||||
|     { |  | ||||||
|         private HttpClient _Client = null; |  | ||||||
|         public HttpClient GetHttpClient() |  | ||||||
|         { |  | ||||||
|             if (_Client == null) |  | ||||||
|             { |  | ||||||
|                 var client = new HttpClient(); |  | ||||||
|                 client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("text/html")); |  | ||||||
|                 client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/xhtml+xml")); |  | ||||||
|                 client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/xml")); |  | ||||||
|                 client.DefaultRequestHeaders.AcceptLanguage.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("fr")); |  | ||||||
|                 client.DefaultRequestHeaders.AcceptLanguage.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("fr-FR")); |  | ||||||
|                 _Client = client; |  | ||||||
|             } |  | ||||||
|             return _Client; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         #region IDisposable Support |  | ||||||
|         private bool disposedValue = false; // Pour détecter les appels redondants |  | ||||||
| 
 |  | ||||||
|         protected virtual void Dispose(bool disposing) |  | ||||||
|         { |  | ||||||
|             if (!disposedValue) |  | ||||||
|             { |  | ||||||
|                 if (disposing) |  | ||||||
|                 { |  | ||||||
|                     // TODO: supprimer l'état managé (objets managés). |  | ||||||
|                     if (_Client != null) |  | ||||||
|                     { |  | ||||||
|                         _Client.Dispose(); |  | ||||||
|                         _Client = null; |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 // TODO: libérer les ressources non managées (objets non managés) et remplacer un finaliseur ci-dessous. |  | ||||||
|                 // TODO: définir les champs de grande taille avec la valeur Null. |  | ||||||
| 
 |  | ||||||
|                 disposedValue = true; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // TODO: remplacer un finaliseur seulement si la fonction Dispose(bool disposing) ci-dessus a du code pour libérer les ressources non managées. |  | ||||||
|         // ~SpellsScrappers() { |  | ||||||
|         //   // Ne modifiez pas ce code. Placez le code de nettoyage dans Dispose(bool disposing) ci-dessus. |  | ||||||
|         //   Dispose(false); |  | ||||||
|         // } |  | ||||||
| 
 |  | ||||||
|         // Ce code est ajouté pour implémenter correctement le modèle supprimable. |  | ||||||
|         public void Dispose() |  | ||||||
|         { |  | ||||||
|             // Ne modifiez pas ce code. Placez le code de nettoyage dans Dispose(bool disposing) ci-dessus. |  | ||||||
|             Dispose(true); |  | ||||||
|             // TODO: supprimer les marques de commentaire pour la ligne suivante si le finaliseur est remplacé ci-dessus. |  | ||||||
|             // GC.SuppressFinalize(this); |  | ||||||
|         } |  | ||||||
|         #endregion |  | ||||||
| 
 |  | ||||||
|         public async Task<IEnumerable<Spell>> GetSpells(string classe = "", string niveauMin = "", string niveauMax = "", string ecole = "", string rituel = "", string source = "srd") |  | ||||||
|         { |  | ||||||
|             string html = null; |  | ||||||
|             var client = GetHttpClient(); |  | ||||||
|             // https://www.aidedd.org/regles/sorts/ |  | ||||||
| 
 |  | ||||||
|             //var url = string.Format("https://www.aidedd.org/regles/sorts/?c={0}&min={1}&max={2}&e={3}&r={4}&s={5}", classe, niveauMin, niveauMax, ecole, rituel, source); |  | ||||||
|             var url = string.Format("https://www.aidedd.org/dnd-filters/sorts.php?c={0}&min={1}&max={2}&e={3}&r={4}&s={5}", classe, niveauMin, niveauMax, ecole, rituel, source); |  | ||||||
|             html = await client.GetStringAsync(url); |  | ||||||
| 
 |  | ||||||
|             var pack = new XmlDocument(); |  | ||||||
|             pack.LoadXml(html); |  | ||||||
|             //var tdssort = pack.GetElementbyId("liste").Element("table").Elements("tr").ToList(); |  | ||||||
|             var tdssort = pack.DocumentElement.SelectSingleNode("//table[contains(@class,'liste')]").SelectNodes("tr"); |  | ||||||
|             var spells = new List<Spell>(); |  | ||||||
|             foreach (var tdsortt in tdssort) |  | ||||||
|             { |  | ||||||
|                 var tdsort = tdsortt as XmlNode; |  | ||||||
|                 var thssort = tdsort.SelectNodes("td"); |  | ||||||
|                 if (thssort.Count > 0) |  | ||||||
|                 { |  | ||||||
|                     Spell spell = new Spell(); |  | ||||||
|                     var aname = thssort[1].SelectSingleNode("a"); |  | ||||||
|                     var spanname = aname.SelectSingleNode("span"); |  | ||||||
|                     if(spanname != null) |  | ||||||
|                     { |  | ||||||
|                         spell.NamePHB = spanname.Attributes["title"].InnerText; |  | ||||||
|                         spell.Name = spanname.InnerText; |  | ||||||
|                     } |  | ||||||
|                     else |  | ||||||
|                     { |  | ||||||
|                         spell.NamePHB = aname.InnerText; |  | ||||||
|                         spell.Name = aname.InnerText; |  | ||||||
|                     } |  | ||||||
|                     var href = aname.Attributes["href"].InnerText; |  | ||||||
|                     var regex = new Regex("vf=(?<id>.*)"); |  | ||||||
|                     spell.Id = regex.Match(href).Groups["id"].Value; |  | ||||||
| 
 |  | ||||||
|                     spell.Level = thssort[2].InnerText; |  | ||||||
|                     spell.Type = thssort[3].InnerText; |  | ||||||
|                     spell.CastingTime = thssort[4].InnerText; |  | ||||||
|                     spell.Concentration = thssort[5].InnerText; |  | ||||||
|                     spell.Rituel = thssort[6].InnerText; |  | ||||||
|                     spells.Add(spell); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             return spells; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public async Task<Spell> GetSpell(string id) |  | ||||||
|         { |  | ||||||
|             string html = null; |  | ||||||
|             var client = GetHttpClient(); |  | ||||||
|             // https://www.aidedd.org/dnd/sorts.php?vo=ray-of-frost |  | ||||||
|             // https://www.aidedd.org/dnd/sorts.php?vf=rayon-de-givre |  | ||||||
| 
 |  | ||||||
|             html = await client.GetStringAsync(string.Format("https://www.aidedd.org/dnd/sorts.php?vf={0}", id)); |  | ||||||
| 
 |  | ||||||
|             var pack = new XmlDocument(); |  | ||||||
|             pack.LoadXml(html); |  | ||||||
|             var divSpell = pack.DocumentElement.SelectSingleNode("//div[contains(@class,'bloc')]"); |  | ||||||
|             var spell = Spell.FromHtml(divSpell); |  | ||||||
|             spell.Id = id; |  | ||||||
|             return spell; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public async Task<IEnumerable<string>> GetSpellIds(string classe, string niveauMin = "Z", string niveauMax = "9") |  | ||||||
|         { |  | ||||||
|             string html = null; |  | ||||||
|             var client = GetHttpClient(); |  | ||||||
|             // https://www.aidedd.org/dnd/sorts.php?vo=ray-of-frost |  | ||||||
|             // https://www.aidedd.org/dnd/sorts.php?vf=rayon-de-givre |  | ||||||
|             // https://www.aidedd.org/regles/sorts/ |  | ||||||
| 
 |  | ||||||
|             html = await client.GetStringAsync(string.Format("https://www.aidedd.org/adj/livre-sorts/?c={0}&min={1}&max={2}", classe, niveauMin, niveauMax)); |  | ||||||
| 
 |  | ||||||
|             var pack = new XmlDocument(); |  | ||||||
|             pack.LoadXml(html); |  | ||||||
|             return pack.DocumentElement.SelectNodes("//input[@name='select_sorts[]']").Cast<XmlNode>().Select(node => node.Attributes["value"].InnerText); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public async Task<IEnumerable<Spell>> GetSpells(IEnumerable<string> spellIds) |  | ||||||
|         { |  | ||||||
|             string html = null; |  | ||||||
|             var client = GetHttpClient(); |  | ||||||
|             var content = new MultipartFormDataContent(); |  | ||||||
|             content.Add(new StringContent("card"), "format"); |  | ||||||
|             foreach (var spellId in spellIds) |  | ||||||
|             { |  | ||||||
|                 content.Add(new StringContent(spellId), "select_sorts[]"); |  | ||||||
|             } |  | ||||||
|             var response = await client.PostAsync("http://www.aidedd.org/dnd/sorts.php", content); |  | ||||||
|             html = await response.Content.ReadAsStringAsync(); |  | ||||||
| 
 |  | ||||||
|             var pack = new XmlDocument(); |  | ||||||
|             pack.LoadXml(html); |  | ||||||
|             var newSpells = new List<Spell>(); |  | ||||||
|             var spells = pack.DocumentElement.SelectNodes("//div[contains(@class,'blocCarte')]"); |  | ||||||
|             foreach (var spell in spells) |  | ||||||
|             { |  | ||||||
|                 //var newSpell = new Spell(); |  | ||||||
|                 var newSpell = Spell.FromHtml(spell as XmlNode); |  | ||||||
|                 //newSpell.Name = spell.SelectSingleNode("h1").InnerText; |  | ||||||
|                 //newSpell.NameVO = spell.SelectSingleNode("div[@class='trad']").InnerText; |  | ||||||
|                 //newSpell.LevelType = spell.SelectSingleNode("h2/em").InnerText; |  | ||||||
|                 //newSpell.Level = newSpell.LevelType.Split(new string[] { " - " }, StringSplitOptions.None)[0].Split(' ')[1]; |  | ||||||
|                 //newSpell.Type = newSpell.LevelType.Split(new string[] { " - " }, StringSplitOptions.None)[1]; |  | ||||||
|                 //newSpell.CastingTime = spell.SelectSingleNode("div[@class='paragraphe']").InnerText.Split(new string[] { " : " }, StringSplitOptions.None)[1]; |  | ||||||
|                 //newSpell.Range = spell.SelectSingleNode("div[strong/text()='Portée']").InnerText.Split(new string[] { " : " }, StringSplitOptions.None)[1]; |  | ||||||
|                 //newSpell.Components = spell.SelectSingleNode("div[strong/text()='Composantes']").InnerText.Split(new string[] { " : " }, StringSplitOptions.None)[1]; |  | ||||||
|                 //newSpell.Duration = spell.SelectSingleNode("div[strong/text()='Durée']").InnerText.Split(new string[] { " : " }, StringSplitOptions.None)[1]; |  | ||||||
|                 //newSpell.DescriptionDiv = spell.SelectSingleNode("div[contains(@class,'description')]"); |  | ||||||
|                 ////newSpell.DescriptionHtml = newSpell.DescriptionDiv.InnerHtml; |  | ||||||
|                 ////newSpell.Description = newSpell.DescriptionDiv.InnerText; |  | ||||||
|                 //newSpell.Overflow = spell.SelectSingleNode("div[@class='overflow']")?.InnerText; |  | ||||||
|                 //newSpell.NoOverflow = spell.SelectSingleNode("div[@class='nooverflow']")?.InnerText; |  | ||||||
|                 //newSpell.Source = spell.SelectSingleNode("div[@class='source']").InnerText; |  | ||||||
|                 newSpells.Add(newSpell); |  | ||||||
|             } |  | ||||||
|             return newSpells; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /* |  | ||||||
|         public async Task<string> OnGetAsync(IReadOnlyDictionary<string, string> context) |  | ||||||
|         { |  | ||||||
|             var client = new HttpClient(); |  | ||||||
|             //client.DefaultRequestHeaders.UserAgent.Add(new System.Net.Http.Headers.ProductInfoHeaderValue(new System.Net.Http.Headers.ProductHeaderValue("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0"))); |  | ||||||
|             client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("text/html")); |  | ||||||
|             client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/xhtml+xml")); |  | ||||||
|             client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/xml")); |  | ||||||
|             client.DefaultRequestHeaders.AcceptLanguage.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("fr")); |  | ||||||
|             client.DefaultRequestHeaders.AcceptLanguage.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("fr-FR")); |  | ||||||
|             //client.DefaultRequestHeaders.AcceptEncoding.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("gzip")); |  | ||||||
|             //client.DefaultRequestHeaders.AcceptEncoding.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("deflate")); |  | ||||||
|             //client.DefaultRequestHeaders.AcceptEncoding.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("br")); |  | ||||||
|             var content = new MultipartFormDataContent(); |  | ||||||
|             //content.Add(new StringContent("Afficher+%28FR%29"), "displayFR"); |  | ||||||
|             content.Add(new StringContent("card"), "format"); |  | ||||||
|             //content.Add(new StringContent("%27amis%27"), "select_sorts%5B%5D"); |  | ||||||
|             //content.Add(new StringContent("\"amis\""), "select_sorts[]"); |  | ||||||
|             //var bod = await content.ReadAsStringAsync(); |  | ||||||
|             //Debug.WriteLine(bod); |  | ||||||
| 
 |  | ||||||
|             // https://www.aidedd.org/dnd/sorts.php?vo=ray-of-frost |  | ||||||
|             // https://www.aidedd.org/dnd/sorts.php?vf=rayon-de-givre |  | ||||||
|             // https://www.aidedd.org/regles/sorts/ |  | ||||||
| 
 |  | ||||||
|              |  | ||||||
|             //<option value="b">Barde</option> |  | ||||||
|             //<option value="c">Clerc</option> |  | ||||||
|             //<option value="d">Druide</option> |  | ||||||
|             //<option value="s">Ensorceleur</option> |  | ||||||
|             //<option value="w">Magicien</option> |  | ||||||
|             //<option value="p">Paladin</option> |  | ||||||
|             //<option value="r">Rôdeur</option> |  | ||||||
|             //<option value="k">Sorcier</option> |  | ||||||
|              |  | ||||||
|             string c = context["c"]; |  | ||||||
|             var htmlSpellBook = await client.GetStringAsync("https://www.aidedd.org/adj/livre-sorts/?c=" + c + "&min=10&max=19"); |  | ||||||
|             var pack = new HtmlDocument(); |  | ||||||
|             pack.LoadHtml(htmlSpellBook); |  | ||||||
|             var selectSorts = pack.DocumentNode.SelectNodes("//input[@name='select_sorts[]']").ToList(); |  | ||||||
|             foreach (var selectSort in selectSorts) |  | ||||||
|             { |  | ||||||
|                 content.Add(new StringContent(selectSort.GetAttributeValue("value", "")), "select_sorts[]"); |  | ||||||
|             } |  | ||||||
|             var response = await client.PostAsync("http://www.aidedd.org/dnd/sorts.php", content); |  | ||||||
|             var htmlSpell = await response.Content.ReadAsStringAsync(); |  | ||||||
|             pack.LoadHtml(htmlSpell); |  | ||||||
|             var newSpells = new List<Spell>(); |  | ||||||
|             var cardDatas = new List<CardData>(); |  | ||||||
|             var spells = pack.DocumentNode.SelectNodes("//div[contains(@class,'blocCarte')]").ToList(); |  | ||||||
|             foreach (var spell in spells) |  | ||||||
|             { |  | ||||||
|                 var newSpell = new Spell(); |  | ||||||
|                 newSpell.Title = spell.SelectSingleNode("h1").InnerText; |  | ||||||
|                 newSpell.TitleUS = spell.SelectSingleNode("div[@class='trad']").InnerText; |  | ||||||
|                 newSpell.LevelType = spell.SelectSingleNode("h2/em").InnerText; |  | ||||||
|                 newSpell.Level = newSpell.LevelType.Split(new string[] { " - " }, StringSplitOptions.None)[0].Split(' ')[1]; |  | ||||||
|                 newSpell.Type = newSpell.LevelType.Split(new string[] { " - " }, StringSplitOptions.None)[1]; |  | ||||||
|                 newSpell.CastingTime = spell.SelectSingleNode("div[@class='paragraphe']").InnerText.Split(new string[] { " : " }, StringSplitOptions.None)[1]; |  | ||||||
|                 newSpell.Range = spell.SelectSingleNode("div[strong/text()='Portée']").InnerText.Split(new string[] { " : " }, StringSplitOptions.None)[1]; |  | ||||||
|                 newSpell.Components = spell.SelectSingleNode("div[strong/text()='Composantes']").InnerText.Split(new string[] { " : " }, StringSplitOptions.None)[1]; |  | ||||||
|                 newSpell.Duration = spell.SelectSingleNode("div[strong/text()='Durée']").InnerText.Split(new string[] { " : " }, StringSplitOptions.None)[1]; |  | ||||||
|                 newSpell.DescriptionDiv = spell.SelectSingleNode("div[contains(@class,'description')]"); |  | ||||||
|                 //newSpell.Description = newSpell.DescriptionDiv.InnerHtml; |  | ||||||
|                 newSpell.Overflow = spell.SelectSingleNode("div[@class='overflow']")?.InnerText; |  | ||||||
|                 newSpell.NoOverflow = spell.SelectSingleNode("div[@class='nooverflow']")?.InnerText; |  | ||||||
|                 newSpell.Source = spell.SelectSingleNode("div[@class='source']").InnerText; |  | ||||||
|                 newSpells.Add(newSpell); |  | ||||||
|                 cardDatas.AddRange(Converters.ToCardDatas(context, newSpell)); |  | ||||||
|             } |  | ||||||
|             //Debug.WriteLine(htmlSpell); |  | ||||||
| 
 |  | ||||||
|             var sampleCardDatas = cardDatas.Take(4).ToArray(); |  | ||||||
|             foreach (var scd in sampleCardDatas) |  | ||||||
|             { |  | ||||||
|                 int totalHeight = 0; |  | ||||||
|                 foreach (var cc in scd.Contents) |  | ||||||
|                 { |  | ||||||
|                     totalHeight += cc.Height; |  | ||||||
|                     Debug.WriteLine(string.Format("{0} - {1} => {2}", cc.Height, totalHeight, cc.ToString())); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             //var own = new CardDataOwner() { CardDatas = cardDatas.ToArray() }; |  | ||||||
|             MemoryStream stream = new MemoryStream(); |  | ||||||
|             DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(CardData[])); |  | ||||||
|             serializer.WriteObject(stream, cardDatas.ToArray()); |  | ||||||
|             stream.Seek(0, SeekOrigin.Begin); |  | ||||||
|             StreamReader sr = new StreamReader(stream, System.Text.Encoding.UTF8); |  | ||||||
|             //context.Response.Headers["encoding"] |  | ||||||
|             return await sr.ReadToEndAsync(); |  | ||||||
|             //Result = await sr.ReadToEndAsync(); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|             //JavaScriptSerializer serializer = new JavaScriptSerializer(); |  | ||||||
|             //string json = serializer.Serialize((object)yourDictionary); |  | ||||||
|             //Debug.WriteLine(result); |  | ||||||
| 
 |  | ||||||
|             //using (var file = new FileStream(@"C:\Users\yanma\Downloads\_\JdR\Chroniques Oubliées\crobi-rpg-cards-065974f\generator\data\out.js", FileMode.Create, FileAccess.ReadWrite, FileShare.Read)) |  | ||||||
|             //{ |  | ||||||
|             //    var bytes = System.Text.Encoding.UTF8.GetBytes(result); |  | ||||||
|             //    Response.Body.Write(bytes, 0, bytes.Length); |  | ||||||
|             //    //await file.WriteAsync(bytes, 0, bytes.Length); |  | ||||||
|             //} |  | ||||||
| 
 |  | ||||||
|         } |  | ||||||
|         */ |  | ||||||
| 
 |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -198,85 +198,6 @@ namespace AideDeJeu.ViewModels | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|         //public FormattedString Description |  | ||||||
|         //{ |  | ||||||
|         //    get |  | ||||||
|         //    { |  | ||||||
|         //        var fs = new FormattedString(); |  | ||||||
|         //        if (Item?.DescriptionDiv != null) |  | ||||||
|         //        { |  | ||||||
|         //            FormatedTextHelpers.HtmlToFormatedString(Item?.DescriptionDiv, fs, FontAttributes.None); |  | ||||||
|         //        } |  | ||||||
|         //        return fs; |  | ||||||
|         //    } |  | ||||||
|         //} |  | ||||||
| 
 |  | ||||||
|         //public FormattedString TypeLevel |  | ||||||
|         //{ |  | ||||||
|         //    get |  | ||||||
|         //    { |  | ||||||
|         //        var fd = FormatedTextHelpers.FontData.FromResource("contentital"); |  | ||||||
|         //        var fs = new FormattedString(); |  | ||||||
|         //        var capType = Item.Type.First().ToString().ToUpper() + Item.Type.Substring(1); |  | ||||||
|         //        fs.Spans.Add(new Span() { Text = string.Format("{0} de niveau {1}", capType, Item.Level), FontFamily = fd.FontFamily, FontAttributes = fd.FontAttributes, FontSize = fd.FontSize, ForegroundColor = fd.TextColor}); |  | ||||||
|         //        return fs; |  | ||||||
|         //    } |  | ||||||
|         //} |  | ||||||
| 
 |  | ||||||
|         //public FormattedString CastingTime |  | ||||||
|         //{ |  | ||||||
|         //    get |  | ||||||
|         //    { |  | ||||||
|         //        var fd = FormatedTextHelpers.FontData.FromResource("content"); |  | ||||||
|         //        var fdb = FormatedTextHelpers.FontData.FromResource("contentbold"); |  | ||||||
|         //        var fs = new FormattedString(); |  | ||||||
|         //        fs.Spans.Add(new Span() { Text = "Durée d'incantation : ", FontFamily = fdb.FontFamily, FontAttributes = fdb.FontAttributes, FontSize = fdb.FontSize, ForegroundColor = fdb.TextColor }); |  | ||||||
|         //        fs.Spans.Add(new Span() { Text = Item.CastingTime, FontFamily = fd.FontFamily, FontAttributes = fd.FontAttributes, FontSize = fd.FontSize, ForegroundColor = fd.TextColor }); |  | ||||||
|         //        return fs; |  | ||||||
|         //    } |  | ||||||
|         //} |  | ||||||
| 
 |  | ||||||
|         //public FormattedString Range |  | ||||||
|         //{ |  | ||||||
|         //    get |  | ||||||
|         //    { |  | ||||||
|         //        var fd = FormatedTextHelpers.FontData.FromResource("content"); |  | ||||||
|         //        var fdb = FormatedTextHelpers.FontData.FromResource("contentbold"); |  | ||||||
|         //        var fs = new FormattedString(); |  | ||||||
|         //        fs.Spans.Add(new Span() { Text = "Portée : ", FontFamily = fdb.FontFamily, FontAttributes = fdb.FontAttributes, FontSize = fdb.FontSize, ForegroundColor = fdb.TextColor }); |  | ||||||
|         //        fs.Spans.Add(new Span() { Text = Item.Range, FontFamily = fd.FontFamily, FontAttributes = fd.FontAttributes, FontSize = fd.FontSize, ForegroundColor = fd.TextColor }); |  | ||||||
|         //        return fs; |  | ||||||
|         //    } |  | ||||||
|         //} |  | ||||||
| 
 |  | ||||||
|         //public FormattedString Components |  | ||||||
|         //{ |  | ||||||
|         //    get |  | ||||||
|         //    { |  | ||||||
|         //        var fd = FormatedTextHelpers.FontData.FromResource("content"); |  | ||||||
|         //        var fdb = FormatedTextHelpers.FontData.FromResource("contentbold"); |  | ||||||
|         //        var fs = new FormattedString(); |  | ||||||
|         //        fs.Spans.Add(new Span() { Text = "Composantes : ", FontFamily = fdb.FontFamily, FontAttributes = fdb.FontAttributes, FontSize = fdb.FontSize, ForegroundColor = fdb.TextColor }); |  | ||||||
|         //        fs.Spans.Add(new Span() { Text = Item.Components, FontFamily = fd.FontFamily, FontAttributes = fd.FontAttributes, FontSize = fd.FontSize, ForegroundColor = fd.TextColor }); |  | ||||||
|         //        return fs; |  | ||||||
|         //    } |  | ||||||
|         //} |  | ||||||
| 
 |  | ||||||
|         //public FormattedString Duration |  | ||||||
|         //{ |  | ||||||
|         //    get |  | ||||||
|         //    { |  | ||||||
|         //        var fd = FormatedTextHelpers.FontData.FromResource("content"); |  | ||||||
|         //        var fdb = FormatedTextHelpers.FontData.FromResource("contentbold"); |  | ||||||
|         //        var fs = new FormattedString(); |  | ||||||
|         //        fs.Spans.Add(new Span() { Text = "Durée : ", FontFamily = fdb.FontFamily, FontAttributes = fdb.FontAttributes, FontSize = fdb.FontSize, ForegroundColor = fdb.TextColor }); |  | ||||||
|         //        fs.Spans.Add(new Span() { Text = Item.Duration, FontFamily = fd.FontFamily, FontAttributes = fd.FontAttributes, FontSize = fd.FontSize, ForegroundColor = fd.TextColor }); |  | ||||||
|         //        return fs; |  | ||||||
|         //    } |  | ||||||
|         //} |  | ||||||
| 
 |  | ||||||
|         public Command LoadItemCommand { get; set; } |         public Command LoadItemCommand { get; set; } | ||||||
| 
 | 
 | ||||||
|         public MonsterDetailViewModel(Monster item = null) |         public MonsterDetailViewModel(Monster item = null) | ||||||
|  | @ -287,31 +208,6 @@ namespace AideDeJeu.ViewModels | ||||||
|         } |         } | ||||||
|         async Task ExecuteLoadItemCommand() |         async Task ExecuteLoadItemCommand() | ||||||
|         { |         { | ||||||
|             if (IsBusy) |  | ||||||
|                 return; |  | ||||||
| 
 |  | ||||||
|             IsBusy = true; |  | ||||||
| 
 |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 //Item.ParseHtml(); |  | ||||||
|                 //Item = _Item; |  | ||||||
|                 //Items.Clear(); |  | ||||||
|                 //var item = await new MonstersScrappers().GetMonster(Item.Id); |  | ||||||
|                 //Item = item; |  | ||||||
|                 //foreach (var item in items) |  | ||||||
|                 //{ |  | ||||||
|                 //    Items.Add(item); |  | ||||||
|                 //} |  | ||||||
|             } |  | ||||||
|             catch (Exception ex) |  | ||||||
|             { |  | ||||||
|                 Debug.WriteLine(ex); |  | ||||||
|             } |  | ||||||
|             finally |  | ||||||
|             { |  | ||||||
|                 IsBusy = false; |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -96,13 +96,6 @@ | ||||||
|             <!--<Label FormattedText="{Binding Item.LegendaryActions, Converter={StaticResource HtmlNodesToFormattedStringConverter}}" IsVisible="{Binding Item.LegendaryActions, Converter={StaticResource NullToFalseConverter}}" />--> |             <!--<Label FormattedText="{Binding Item.LegendaryActions, Converter={StaticResource HtmlNodesToFormattedStringConverter}}" IsVisible="{Binding Item.LegendaryActions, Converter={StaticResource NullToFalseConverter}}" />--> | ||||||
|             <mdview:MarkdownView x:Name="mdLegendaryActions" Theme="{StaticResource MonsterMarkdownTheme}" Markdown="{Binding Item.LegendaryActions, Converter={StaticResource HtmlNodesToFormattedStringConverter}}" IsVisible="{Binding Item.LegendaryActions, Converter={StaticResource NullToFalseConverter}}" /> |             <mdview:MarkdownView x:Name="mdLegendaryActions" Theme="{StaticResource MonsterMarkdownTheme}" Markdown="{Binding Item.LegendaryActions, Converter={StaticResource HtmlNodesToFormattedStringConverter}}" IsVisible="{Binding Item.LegendaryActions, Converter={StaticResource NullToFalseConverter}}" /> | ||||||
| 
 | 
 | ||||||
|             <!--<ListView ItemsSource="{Binding Item.SpecialFeaturesNodes}"> |  | ||||||
|                 <ListView.ItemTemplate> |  | ||||||
|                     <DataTemplate> |  | ||||||
|                         <Label BindingContext="{Binding}" FormattedText="{Binding Converter={StaticResource HtmlNodeToFormattedStringConverter}}" /> |  | ||||||
|                     </DataTemplate> |  | ||||||
|                 </ListView.ItemTemplate> |  | ||||||
|             </ListView>--> |  | ||||||
|             <skia:SKCanvasView PaintSurface="PaintHeaderBar" HorizontalOptions="FillAndExpand" HeightRequest="8" /> |             <skia:SKCanvasView PaintSurface="PaintHeaderBar" HorizontalOptions="FillAndExpand" HeightRequest="8" /> | ||||||
| 
 | 
 | ||||||
|             <Label Text="{Binding Item.Description}" Style="{StaticResource Key=content}" /> |             <Label Text="{Binding Item.Description}" Style="{StaticResource Key=content}" /> | ||||||
|  |  | ||||||
|  | @ -1,50 +0,0 @@ | ||||||
| using AideDeJeu.Tools; |  | ||||||
| using AideDeJeuLib.Monsters; |  | ||||||
| using AideDeJeuLib.Spells; |  | ||||||
| using Microsoft.EntityFrameworkCore; |  | ||||||
| using System; |  | ||||||
| using System.Collections.Generic; |  | ||||||
| using System.IO; |  | ||||||
| using System.Text; |  | ||||||
| using Xamarin.Forms; |  | ||||||
| 
 |  | ||||||
| namespace AideDeJeu.Services |  | ||||||
| { |  | ||||||
|     public class ItemDatabaseContext : DbContext |  | ||||||
|     { |  | ||||||
|         public ItemDatabaseContext(string databasePath) |  | ||||||
|         { |  | ||||||
|             DatabasePath = databasePath; |  | ||||||
|         } |  | ||||||
|         private string DatabasePath = null; |  | ||||||
|         private string DatabaseName = "database.db"; |  | ||||||
| 
 |  | ||||||
|         public DbSet<Spell> Spells { get; set; } |  | ||||||
| 
 |  | ||||||
|         public DbSet<Monster> Monsters { get; set; } |  | ||||||
| 
 |  | ||||||
|         protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) |  | ||||||
|         { |  | ||||||
|             //if (DatabasePath == null) |  | ||||||
|             //{ |  | ||||||
|             //    switch (Device.RuntimePlatform) |  | ||||||
|             //    { |  | ||||||
|             //        case Device.iOS: |  | ||||||
|             //            SQLitePCL.Batteries_V2.Init(); |  | ||||||
|             //            DatabasePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "..", "Library", DatabaseName); ; |  | ||||||
|             //            break; |  | ||||||
|             //        case Device.Android: |  | ||||||
|             //            DatabasePath = DependencyService.Get<INativeAPI>().GetDatabasePath(DatabaseName); |  | ||||||
|             //            break; |  | ||||||
|             //        case Device.UWP: |  | ||||||
|             //            DatabasePath = DependencyService.Get<INativeAPI>().GetDatabasePath(DatabaseName); |  | ||||||
|             //            break; |  | ||||||
|             //        default: |  | ||||||
|             //            throw new NotImplementedException("Platform not supported"); |  | ||||||
|             //    } |  | ||||||
|             //} |  | ||||||
|             // Specify that we will use sqlite and the path of the database here |  | ||||||
|             optionsBuilder.UseSqlite($"Filename={DatabasePath}"); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -1,93 +0,0 @@ | ||||||
| using AideDeJeu.Tools; |  | ||||||
| using AideDeJeuLib.Monsters; |  | ||||||
| using AideDeJeuLib.Spells; |  | ||||||
| using Microsoft.EntityFrameworkCore; |  | ||||||
| using System; |  | ||||||
| using System.Collections.Generic; |  | ||||||
| using System.Linq; |  | ||||||
| using System.Text; |  | ||||||
| using System.Threading.Tasks; |  | ||||||
| 
 |  | ||||||
| namespace AideDeJeu.Services |  | ||||||
| { |  | ||||||
|     public class ItemDatabaseHelper |  | ||||||
|     { |  | ||||||
|         private string DatabasePath = null; |  | ||||||
|         public ItemDatabaseHelper(string databasePath = null) |  | ||||||
|         { |  | ||||||
|             DatabasePath = databasePath; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         protected async Task<ItemDatabaseContext> CreateContextAsync() |  | ||||||
|         { |  | ||||||
|             ItemDatabaseContext postDatabaseContext = (ItemDatabaseContext)Activator.CreateInstance(typeof(ItemDatabaseContext), DatabasePath); |  | ||||||
|             await postDatabaseContext.Database.EnsureCreatedAsync().ConfigureAwait(false); |  | ||||||
|             await postDatabaseContext.Database.MigrateAsync().ConfigureAwait(false); |  | ||||||
|             return postDatabaseContext; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public async Task<IEnumerable<Spell>> GetSpellsAsync(string classe, string niveauMin, string niveauMax, string ecole, string rituel, string source) |  | ||||||
|         { |  | ||||||
|             using (var context = await CreateContextAsync().ConfigureAwait(false)) |  | ||||||
|             { |  | ||||||
|                 return await context.Spells |  | ||||||
|                                     .AsNoTracking() |  | ||||||
|                                     .Where(spell =>  |  | ||||||
|                                         (int.Parse(spell.Level) >= int.Parse(niveauMin)) &&  |  | ||||||
|                                         (int.Parse(spell.Level) <= int.Parse(niveauMax)) && |  | ||||||
|                                         spell.Type.Contains(ecole) && |  | ||||||
|                                         spell.Source.Contains(source) && |  | ||||||
|                                         spell.Source.Contains(classe) && |  | ||||||
|                                         spell.Type.Contains(rituel) |  | ||||||
|                                         ) |  | ||||||
|                                     .OrderBy(spell => spell.NamePHB) |  | ||||||
|                                     .ToListAsync().ConfigureAwait(false); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public async Task AddOrUpdateSpellsAsync(IEnumerable<Spell> spells) |  | ||||||
|         { |  | ||||||
|             using (var context = await CreateContextAsync().ConfigureAwait(false)) |  | ||||||
|             { |  | ||||||
|                 // add posts that do not exist in the database |  | ||||||
|                 var newSpells = spells.Where( |  | ||||||
|                     spell => context.Spells.Any(dbSpell => dbSpell.Id == spell.Id) == false |  | ||||||
|                 ); |  | ||||||
|                 await context.Spells.AddRangeAsync(newSpells).ConfigureAwait(false); |  | ||||||
|                 await context.SaveChangesAsync().ConfigureAwait(false); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public async Task<IEnumerable<Monster>> GetMonstersAsync(string category, string type, string minPower, string maxPower, string size, string legendary, string source) |  | ||||||
|         { |  | ||||||
|             using (var context = await CreateContextAsync().ConfigureAwait(false)) |  | ||||||
|             { |  | ||||||
|                 var powerComparer = new PowerComparer(); |  | ||||||
|                 return await context.Monsters |  | ||||||
|                                     .AsNoTracking() |  | ||||||
|                                     .Where(monster => |  | ||||||
|                                         monster.Type.Contains(type) && |  | ||||||
|                                         (string.IsNullOrEmpty(size) || monster.Size.Equals(size)) && |  | ||||||
|                                         monster.Source.Contains(source) && |  | ||||||
|                                         powerComparer.Compare(monster.Challenge, minPower) >= 0 && |  | ||||||
|                                         powerComparer.Compare(monster.Challenge, maxPower) <= 0 |  | ||||||
|                                         ) |  | ||||||
|                                     .OrderBy(monster => monster.NamePHB) |  | ||||||
|                                     .ToListAsync().ConfigureAwait(false); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public async Task AddOrUpdateMonstersAsync(IEnumerable<Monster> monsters) |  | ||||||
|         { |  | ||||||
|             using (var context = await CreateContextAsync().ConfigureAwait(false)) |  | ||||||
|             { |  | ||||||
|                 // add posts that do not exist in the database |  | ||||||
|                 var newMonsters = monsters.Where( |  | ||||||
|                     monster => context.Monsters.Any(dbMonster => dbMonster.Id == monster.Id) == false |  | ||||||
|                 ); |  | ||||||
|                 await context.Monsters.AddRangeAsync(newMonsters).ConfigureAwait(false); |  | ||||||
|                 await context.SaveChangesAsync().ConfigureAwait(false); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -1,5 +1,4 @@ | ||||||
| using AideDeJeu.Services; | using AideDeJeu.Tools; | ||||||
| using AideDeJeu.Tools; |  | ||||||
| using AideDeJeuLib.Monsters; | using AideDeJeuLib.Monsters; | ||||||
| using AideDeJeuLib.Spells; | using AideDeJeuLib.Spells; | ||||||
| using Markdig; | using Markdig; | ||||||
|  | @ -9,12 +8,10 @@ using System.Diagnostics; | ||||||
| using System.Globalization; | using System.Globalization; | ||||||
| using System.IO; | using System.IO; | ||||||
| using System.Linq; | using System.Linq; | ||||||
| using System.Net.Http; |  | ||||||
| using System.Runtime.Serialization.Json; | using System.Runtime.Serialization.Json; | ||||||
| using System.Text; | using System.Text; | ||||||
| using System.Text.RegularExpressions; | using System.Text.RegularExpressions; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| using Xamarin.Forms.Internals; |  | ||||||
| 
 | 
 | ||||||
| namespace AideDeJeuCmd | namespace AideDeJeuCmd | ||||||
| { | { | ||||||
|  | @ -145,320 +142,8 @@ namespace AideDeJeuCmd | ||||||
|             Console.WriteLine(mdVF); |             Console.WriteLine(mdVF); | ||||||
|             await SaveStringAsync(dataDir + "monsters_hd_tmp.md", mdVF); |             await SaveStringAsync(dataDir + "monsters_hd_tmp.md", mdVF); | ||||||
| 
 | 
 | ||||||
|             //var md = await LoadStringAsync(dataDir + "spells_vo.md"); |  | ||||||
|             //var items = AideDeJeu.Tools.MarkdownExtensions.MarkdownToSpells(md); |  | ||||||
| 
 |  | ||||||
|             //var mdOut = string.Empty; |  | ||||||
|             //foreach (var item in items) |  | ||||||
|             //{ |  | ||||||
|             //    mdOut += item.ToMarkdownString(); |  | ||||||
|             //} |  | ||||||
| 
 |  | ||||||
|             //Console.WriteLine(mdOut); |  | ||||||
| 
 |  | ||||||
|             //await CreateIndexes(); |  | ||||||
|             //var spellsVF = LoadJSon<IEnumerable<Spell>>(dataDir + "spells_vf_full.json"); |  | ||||||
|             //var spellsVO = LoadJSon<IEnumerable<Spell>>(dataDir + "spells_vo_full.json"); |  | ||||||
|             //var spellsHD = LoadJSon<IEnumerable<Spell>>(dataDir + "spells_hd_full.json"); |  | ||||||
|             //var monstersVF = LoadJSon<IEnumerable<Monster>>(dataDir + "monsters_vf_full.json"); |  | ||||||
|             //var monstersVO = LoadJSon<IEnumerable<Monster>>(dataDir + "monsters_vo_full.json"); |  | ||||||
| 
 |  | ||||||
|             //var result = string.Empty; |  | ||||||
|             //var md = await LoadStringAsync(dataDir + "spells_vo.md"); |  | ||||||
| 
 |  | ||||||
|             //var regex = new Regex("\\[(?<name>.*?)\\]\\: spells_hd\\.md\\#(?<id>.*?)\n"); |  | ||||||
|             //var matches = regex.Matches(md); |  | ||||||
|             //foreach(Match match in matches) |  | ||||||
|             //{ |  | ||||||
|             //    Debug.WriteLine(match.Value); |  | ||||||
|             //    var oldMatch = match.Value; |  | ||||||
|             //    var name = match.Groups["name"].Value; |  | ||||||
|             //    var newMatch = string.Format("[{0}]: spells_hd.md#{1}\n", name, Helpers.IdFromName(name)); |  | ||||||
| 
 |  | ||||||
|             //    md = md.Replace(oldMatch, newMatch); |  | ||||||
|             //} |  | ||||||
|             //await SaveStringAsync(dataDir + "spells_vo_tmp.md", md); |  | ||||||
|             //foreach(var spell in spellsVF) |  | ||||||
|             //{ |  | ||||||
|             //    var nameAideDD = spell.Name; |  | ||||||
|             //    var nameHD = spell.NamePHB; |  | ||||||
|             //    if(!string.IsNullOrWhiteSpace(nameAideDD) && !string.IsNullOrWhiteSpace(nameHD)) |  | ||||||
|             //    { |  | ||||||
|             //        if (nameAideDD != nameHD) |  | ||||||
|             //        { |  | ||||||
|             //            Debug.WriteLine(string.Format("{0} => {1}", nameAideDD, nameHD)); |  | ||||||
| 
 |  | ||||||
|             //            md = md.Replace( |  | ||||||
|             //                string.Format("- NameVO: [{0}]", nameAideDD), |  | ||||||
|             //                string.Format("- NameVO: [{0}]", nameHD)); |  | ||||||
| 
 |  | ||||||
|             //            var tmpmd = md.Replace( |  | ||||||
|             //                string.Format("[{0}]: spells_hd.md#{1}", nameAideDD, Helpers.OldIdFromName(nameAideDD)), |  | ||||||
|             //                string.Format("[{0}]: spells_hd.md#{1}", nameHD, Helpers.IdFromName(nameHD)) |  | ||||||
|             //                ); |  | ||||||
| 
 |  | ||||||
|             //            if(tmpmd == md) |  | ||||||
|             //            { |  | ||||||
|             //                Debug.WriteLine("ko"); |  | ||||||
|             //            } |  | ||||||
|             //            md = tmpmd; |  | ||||||
|             //        } |  | ||||||
|             //    } |  | ||||||
|             //} |  | ||||||
|             /*var regex = new Regex("- NameVO: (?<name>.*?)\n"); |  | ||||||
|             var matches = regex.Matches(md); |  | ||||||
|             foreach(Match match in matches) |  | ||||||
|             { |  | ||||||
|                 var name = match.Groups["name"].Value; |  | ||||||
|                 if (!string.IsNullOrWhiteSpace(name)) |  | ||||||
|                 { |  | ||||||
|                     Debug.WriteLine(name); |  | ||||||
|                     var oldNameVO = string.Format("- NameVO: {0}", name); |  | ||||||
|                     var newNameVO = string.Format("- NameVO: [{0}](spells_vo.md#{1})", name, Helpers.IdFromName(name)); |  | ||||||
|                     md = md.Replace(oldNameVO, newNameVO); |  | ||||||
|                 } |  | ||||||
|             }*/ |  | ||||||
| 
 |  | ||||||
|             //var items = AideDeJeu.Tools.MarkdownExtensions.MarkdownToSpells(md); |  | ||||||
| 
 |  | ||||||
|             //await SaveStringAsync(dataDir + "spells_vo_tmp.md", md); |  | ||||||
|             //var regex = new Regex("(\\[[a-z].*?\\])"); |  | ||||||
|             //var matches = regex.Matches(monstersVOmd); |  | ||||||
|             //var links = matches.OrderBy(m => m.Value).Select(m => m.Value + string.Format(": spells_vo.md#{0}", m.Value.Replace("[", "").Replace("]","").Replace(" ","-"))).Distinct().ToList().Aggregate((a, b) => a + "\n" + b); |  | ||||||
| 
 |  | ||||||
|             return; |             return; | ||||||
|             //var mdhd = spellsHD.ToMarkdownString(); |  | ||||||
|             //var spellsMDHD = spellsHD.ToMarkdownString(); |  | ||||||
|             //var spellsMDVO = spellsVO.ToMarkdownString(); |  | ||||||
|             //var monstersMDVO = monstersVO.ToMarkdownString(); |  | ||||||
|             //await SaveStringAsync(dataDir + "spells_vo.md", spellsMDVO); |  | ||||||
|             //await SaveStringAsync(dataDir + "monsters_vo.md", monstersMDVO); |  | ||||||
| 
 | 
 | ||||||
|             //using (var instream = new StreamReader(dataDir + "monsters_hd.md", Encoding.UTF8)) |  | ||||||
|             //{ |  | ||||||
|             //    using (var outstream = new StreamWriter(dataDir + "monsters_hd_modif.md", false, Encoding.UTF8)) |  | ||||||
|             //    { |  | ||||||
|             //        var line = await instream.ReadLineAsync(); |  | ||||||
|             //        while (line != null) |  | ||||||
|             //        { |  | ||||||
|             //            if (line.StartsWith("# ")) |  | ||||||
|             //            { |  | ||||||
|             //                await outstream.WriteLineAsync(line); |  | ||||||
|             //                line = await instream.ReadLineAsync(); |  | ||||||
|             //                await outstream.WriteLineAsync("- " + line); |  | ||||||
|             //            } |  | ||||||
|             //            else if(line.StartsWith("| ---   | ---   | ---   | ---   | ---   | ---   |")) |  | ||||||
|             //            { |  | ||||||
|             //                await outstream.WriteLineAsync(line); |  | ||||||
|             //                line = await instream.ReadLineAsync(); |  | ||||||
|             //                var caracs = line.Substring(1).Split(' '); |  | ||||||
|             //                //var rx = new Regex("|(?<for>.*?) (?<bfor>\\(.*?)\\) (?<dex>.*?) (?<bdex>\\(.*?)\\) (?<con>.*?) (?<bcon>\\(.*?)\\) (?<int>.*?) (?<bint>\\(.*?)\\) (?<sag>.*?) (?<bsag>\\(.*?)\\) (?<cha>.*?) (?<bcha>\\(.*?)\\)"); |  | ||||||
|             //                //var match = rx.Match(line); |  | ||||||
|             //                var outline = string.Format("|{0,2} {1,4}|{2,2} {3,4}|{4,2} {5,4}|{6,2} {7,4}|{8,2} {9,4}|{10,2} {11,4}|", |  | ||||||
|             //                    caracs |  | ||||||
|             //                    ); |  | ||||||
|             //                await outstream.WriteLineAsync(outline); |  | ||||||
|             //                await outstream.WriteLineAsync(string.Empty); |  | ||||||
|             //            } |  | ||||||
|             //            else |  | ||||||
|             //            { |  | ||||||
|             //                await outstream.WriteLineAsync(line); |  | ||||||
|             //            } |  | ||||||
|             //            line = await instream.ReadLineAsync(); |  | ||||||
|             //        } |  | ||||||
|             //    } |  | ||||||
|             //} |  | ||||||
|             return; |  | ||||||
|             //var spellss = await TestMarkdown(@"..\..\..\..\..\Data\spells_hd.md"); |  | ||||||
|             //var monsterss = await TestMarkdownMonsters(@"..\..\..\..\..\Data\monsters_hd.md"); |  | ||||||
|             //return; |  | ||||||
|             //string ignoreDir = @"..\..\..\..\..\Ignore\"; |  | ||||||
|             //var documentsDirectoryPath = @"database.db"; // Windows.Storage.ApplicationData.Current.LocalFolder.Path; |  | ||||||
|             //ItemDatabaseHelper helper = new ItemDatabaseHelper(documentsDirectoryPath); |  | ||||||
|             //var spells = await helper.GetSpellsAsync(classe: "", niveauMin: "0", niveauMax: "9", ecole: "", rituel: "", source: "(SRD)"); |  | ||||||
|             //var monsters = await helper.GetMonstersAsync(category: "", type: "", minPower: " 0 (0 PX)", maxPower: " 30 (155000 PX)", size: "", legendary: "", source: "(SRD)"); |  | ||||||
| 
 |  | ||||||
|             /* |  | ||||||
|             var pack = new HtmlDocument(); |  | ||||||
|             var client = new HttpClient(); |  | ||||||
| 
 |  | ||||||
|             var spells = LoadJSon<IEnumerable<Spell>>(dataDir + "spells.json"); |  | ||||||
|             var spellsVO = new List<Spell>(); |  | ||||||
|             foreach (var spell in spells) |  | ||||||
|             { |  | ||||||
|                 spell.ParseHtml(); |  | ||||||
|                 var htmlVO = await client.GetStringAsync(string.Format("https://www.aidedd.org/dnd/sorts.php?vo={0}", spell.IdVO)); |  | ||||||
|                 pack.LoadHtml(htmlVO); |  | ||||||
|                 var spellVO = Spell.FromHtml(pack.DocumentNode.SelectSingleNode("//div[contains(@class,'bloc')]")); |  | ||||||
|                 spellVO.IdVO = spell.IdVO; |  | ||||||
|                 spell.IdVF = spellVO.IdVF; |  | ||||||
|                 spellsVO.Add(spellVO); |  | ||||||
| 
 |  | ||||||
|                 Console.WriteLine(string.Format("{0} : {1} / {2} : {3}", spell.IdVF, spell.NamePHB, spellVO.IdVO, spellVO.NamePHB)); |  | ||||||
|             } |  | ||||||
|             SaveJSon<IEnumerable<Spell>>(dataDir + "spells_vf.json", spells); |  | ||||||
|             SaveJSon<IEnumerable<Spell>>(dataDir + "spells_vo.json", spellsVO); |  | ||||||
| 
 |  | ||||||
|             var monsters = LoadJSon<IEnumerable<Monster>>(dataDir + "monsters.json"); |  | ||||||
|             var monstersVO = new List<Monster>(); |  | ||||||
|             foreach (var monster in monsters) |  | ||||||
|             { |  | ||||||
|                 monster.ParseHtml(); |  | ||||||
|                 var htmlVO = await client.GetStringAsync(string.Format("https://www.aidedd.org/dnd/monstres.php?vo={0}", monster.IdVO)); |  | ||||||
|                 pack.LoadHtml(htmlVO); |  | ||||||
|                 var monsterVO = Monster.FromHtml(pack.DocumentNode.SelectSingleNode("//div[contains(@class,'bloc')]")); |  | ||||||
|                 monsterVO.IdVO = monster.IdVO; |  | ||||||
|                 monster.IdVF = monsterVO.IdVF; |  | ||||||
|                 monstersVO.Add(monsterVO); |  | ||||||
| 
 |  | ||||||
|                 Console.WriteLine(string.Format("{0} : {1} / {2} : {3}", monster.IdVF, monster.NamePHB, monsterVO.IdVO, monsterVO.NamePHB)); |  | ||||||
|             } |  | ||||||
|             SaveJSon<IEnumerable<Monster>>(dataDir + "monsters_vf.json", monsters); |  | ||||||
|             SaveJSon<IEnumerable<Monster>>(dataDir + "monsters_vo.json", monstersVO); |  | ||||||
|             */ |  | ||||||
|             //var spellsVF = LoadJSon<IEnumerable<Spell>>(dataDir + "spells_vf_full.json"); |  | ||||||
|             //var spellsVO = LoadJSon<IEnumerable<Spell>>(dataDir + "spells_vo_full.json"); |  | ||||||
|             //var spellsHD = LoadJSon<IEnumerable<Spell>>(dataDir + "spells_hd_full.json"); |  | ||||||
|             //var monstersVF = LoadJSon<IEnumerable<Monster>>(dataDir + "monsters_vf_full.json"); |  | ||||||
|             //var monstersVO = LoadJSon<IEnumerable<Monster>>(dataDir + "monsters_vo_full.json"); |  | ||||||
| 
 |  | ||||||
|             //var mdhd = spellsHD.ToMarkdownString(); |  | ||||||
|             //await SaveStringAsync(dataDir + "spells_hd.md", mdhd); |  | ||||||
| 
 |  | ||||||
|             //spellsVF.ForEach(sp => sp.Html = null); |  | ||||||
|             //spellsVO.ForEach(sp => sp.Html = null); |  | ||||||
|             //spellsVF.ForEach(sp => sp.DescriptionDiv = sp.DescriptionDiv); |  | ||||||
|             //spellsVO.ForEach(sp => sp.DescriptionDiv = sp.DescriptionDiv); |  | ||||||
|             //monstersVF.ForEach(it => it.Html = null); |  | ||||||
|             //monstersVO.ForEach(it => it.Html = null); |  | ||||||
| 
 |  | ||||||
|             //SaveJSon<IEnumerable<Spell>>(dataDir + "spells_vf.json", spellsVF); |  | ||||||
|             //SaveJSon<IEnumerable<Spell>>(dataDir + "spells_vo.json", spellsVO); |  | ||||||
|             //SaveJSon<IEnumerable<Spell>>(dataDir + "spells_hd.json", spellsHD); |  | ||||||
|             //SaveJSon<IEnumerable<Monster>>(dataDir + "monsters_vf.json", monstersVF); |  | ||||||
|             //SaveJSon<IEnumerable<Monster>>(dataDir + "monsters_vo.json", monstersVO); |  | ||||||
|             //return; |  | ||||||
| 
 |  | ||||||
|             /* |  | ||||||
|             var spellLists = new Dictionary<string, IEnumerable<string>>() |  | ||||||
|             { |  | ||||||
|                 { "Barde", await LoadList(dataDir + "spell_barde.txt") }, |  | ||||||
|                 { "Clerc", await LoadList(dataDir + "spell_clerc.txt") }, |  | ||||||
|                 { "Druide", await LoadList(dataDir + "spell_druide.txt") }, |  | ||||||
|                 { "Ensorceleur", await LoadList(dataDir + "spell_ensorceleur.txt") }, |  | ||||||
|                 { "Magicien", await LoadList(dataDir + "spell_magicien.txt") }, |  | ||||||
|                 { "Ombrelame", await LoadList(dataDir + "spell_ombrelame.txt") }, |  | ||||||
|                 { "Paladin", await LoadList(dataDir + "spell_paladin.txt") }, |  | ||||||
|                 { "Rôdeur", await LoadList(dataDir + "spell_rodeur.txt") }, |  | ||||||
|                 { "Sorcier", await LoadList(dataDir + "spell_sorcier.txt") }, |  | ||||||
|             }; |  | ||||||
| 
 |  | ||||||
|             var spellsHD = new List<Spell>(); |  | ||||||
|             var spell = new Spell(); |  | ||||||
|             using (var reader = new StreamReader(dataDir + "spells_hd.txt")) |  | ||||||
|             { |  | ||||||
|                 var line = await reader.ReadLineAsync(); |  | ||||||
|                 while (line != null) |  | ||||||
|                 { |  | ||||||
|                     if (line.Length == 0) |  | ||||||
|                     { |  | ||||||
|                         Console.WriteLine(spell.NamePHB); |  | ||||||
| 
 |  | ||||||
|                         spell.DescriptionHtml = await FormatDescriptionAsync(spell.DescriptionHtml); |  | ||||||
|                         spell.Source = "(HD)"; |  | ||||||
|                         spell.Id = spell.IdVF = IdFromName(spell.NamePHB); |  | ||||||
|                         var spVF = spellsVF.SingleOrDefault(sp => IdFromName(sp.NamePHB) == spell.Id); |  | ||||||
|                         if(spVF != null) |  | ||||||
|                         { |  | ||||||
|                             if(spVF.Source.Contains("(SRD)")) |  | ||||||
|                             { |  | ||||||
|                                 spell.Source += "(SRD)"; |  | ||||||
|                                 var spVO = spellsVO.SingleOrDefault(sp => sp.IdVO == spVF.IdVO); |  | ||||||
|                                 if (spVO != null) |  | ||||||
|                                 { |  | ||||||
|                                     spell.NameVO = spVO.Name; |  | ||||||
|                                     spell.IdVO = spVO.IdVO; |  | ||||||
|                                 } |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|                         foreach (var spellList in spellLists) |  | ||||||
|                         { |  | ||||||
|                             if(spellList.Value.Contains(spell.NamePHB.ToLower())) |  | ||||||
|                             { |  | ||||||
|                                 spell.Source += " " + spellList.Key + " ;"; |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|                         spellsHD.Add(spell); |  | ||||||
|                         spell = new Spell(); |  | ||||||
|                     } |  | ||||||
|                     else |  | ||||||
|                     { |  | ||||||
|                         if (spell.NamePHB == null) |  | ||||||
|                         { |  | ||||||
|                             spell.NamePHB = Capitalize(line); |  | ||||||
|                         } |  | ||||||
|                         else if (spell.LevelType == null) |  | ||||||
|                         { |  | ||||||
|                             spell.LevelType = line; |  | ||||||
|                             var re = new Regex("(?<type>.*) de niveau (?<level>\\d*).?(?<rituel>\\(rituel\\))?"); |  | ||||||
|                             var match = re.Match(line); |  | ||||||
|                             spell.Type = match.Groups["type"].Value; |  | ||||||
|                             spell.Level = match.Groups["level"].Value; |  | ||||||
|                             spell.Rituel = match.Groups["rituel"].Value; |  | ||||||
|                             if (string.IsNullOrEmpty(spell.Type)) |  | ||||||
|                             { |  | ||||||
|                                 re = new Regex("(?<type>.*), (?<level>tour de magie)"); |  | ||||||
|                                 match = re.Match(line); |  | ||||||
|                                 spell.Type = match.Groups["type"].Value; |  | ||||||
|                                 spell.Level = "0"; // match.Groups["level"].Value; |  | ||||||
|                                 spell.Rituel = match.Groups["rituel"].Value; |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|                         else |  | ||||||
|                         { |  | ||||||
|                             if (line.StartsWith("Temps d’incantation : ")) |  | ||||||
|                             { |  | ||||||
|                                 spell.CastingTime = line.Substring(22); |  | ||||||
|                             } |  | ||||||
|                             else if (line.StartsWith("Portée : ")) |  | ||||||
|                             { |  | ||||||
|                                 spell.Range = line.Substring(9); |  | ||||||
|                             } |  | ||||||
|                             else if (line.StartsWith("Composantes : ")) |  | ||||||
|                             { |  | ||||||
|                                 spell.Components = line.Substring(14); |  | ||||||
|                             } |  | ||||||
|                             else if (line.StartsWith("Durée : ")) |  | ||||||
|                             { |  | ||||||
|                                 spell.Duration = line.Substring(8); |  | ||||||
|                             } |  | ||||||
|                             else |  | ||||||
|                             { |  | ||||||
|                                 spell.DescriptionHtml += line + "\n"; |  | ||||||
|                                 //if (line.EndsWith(".")) |  | ||||||
|                                 //{ |  | ||||||
|                                 //    spell.DescriptionHtml += line + "\n"; |  | ||||||
|                                 //} |  | ||||||
|                                 //else if (line.EndsWith("-")) |  | ||||||
|                                 //{ |  | ||||||
|                                 //    spell.DescriptionHtml += line.Substring(0, line.Length - 1); |  | ||||||
|                                 //} |  | ||||||
|                                 //else |  | ||||||
|                                 //{ |  | ||||||
|                                 //    spell.DescriptionHtml += line + " "; |  | ||||||
|                                 //} |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                     line = await reader.ReadLineAsync(); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             SaveJSon<IEnumerable<Spell>>(dataDir + "spells_hd.json", spellsHD); |  | ||||||
| 
 |  | ||||||
|             Console.WriteLine("Hello World!"); |  | ||||||
|             */ |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public static string Capitalize(string text) |         public static string Capitalize(string text) | ||||||
|  | @ -481,165 +166,6 @@ namespace AideDeJeuCmd | ||||||
|             return RemoveDiacritics(name.ToLower().Replace(" ", "-")); |             return RemoveDiacritics(name.ToLower().Replace(" ", "-")); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         static async Task<string> FormatDescriptionAsync(string description) |  | ||||||
|         { |  | ||||||
|             string formattedDescription = ""; |  | ||||||
|             using (var reader = new StringReader(description)) |  | ||||||
|             { |  | ||||||
|                 var line = await reader.ReadLineAsync(); |  | ||||||
|                 var li = false; |  | ||||||
|                 while (line != null) |  | ||||||
|                 { |  | ||||||
|                     if (line.StartsWith("»» ")) |  | ||||||
|                     { |  | ||||||
|                         li = true; |  | ||||||
|                         formattedDescription += "<li>" + line.Substring(3); |  | ||||||
|                     } |  | ||||||
|                     else |  | ||||||
|                     { |  | ||||||
|                         var titles = new List<string>() |  | ||||||
|                         { |  | ||||||
|                             "À plus haut niveau.", |  | ||||||
|                             "Agrandir.", |  | ||||||
|                             "Rétrécir.", |  | ||||||
|                             "Endurance de l’ours.", |  | ||||||
|                             "Force du taureau.", |  | ||||||
|                             "Grâce du chat.", |  | ||||||
|                             "Splendeur de l’aigle.", |  | ||||||
|                             "Ruse du renard.", |  | ||||||
|                             "Sagesse du hibou.", |  | ||||||
|                             "Aura factice.", |  | ||||||
|                             "Masque.", |  | ||||||
|                             "Effets visant une cible.", |  | ||||||
|                             "Zones de magie.", |  | ||||||
|                             "Sorts.", |  | ||||||
|                             "Objets magiques.", |  | ||||||
|                             "Déplacement magique.", |  | ||||||
|                             "Créatures et objets.", |  | ||||||
|                             "Dissipation de la magie.", |  | ||||||
|                             "Bouille-crâne.", |  | ||||||
|                             "Convulsions.", |  | ||||||
|                             "Fièvre répugnante.", |  | ||||||
|                             "Mal aveuglant.", |  | ||||||
|                             "Mort poisseuse.", |  | ||||||
|                             "Pourriture.", |  | ||||||
|                             "Écarter les eaux.", |  | ||||||
|                             "Inondation.", |  | ||||||
|                             "Modifier le cours de l’eau.", |  | ||||||
|                             "Tourbillon.", |  | ||||||
|                             "Création d’eau.", |  | ||||||
|                             "Destruction d’eau.", |  | ||||||
|                             "Si vous lancez ce sort en une action, choisissez un point à portée.", |  | ||||||
|                             "Si vous lancez le sort sur une période de huit heures, vous enrichissez la terre.", |  | ||||||
|                             "Annulation d’enchantement.", |  | ||||||
|                             "Renvoi.", |  | ||||||
|                             "Confinement minimal.", |  | ||||||
|                             "Enchaîné.", |  | ||||||
|                             "Enseveli.", |  | ||||||
|                             "Prison isolée.", |  | ||||||
|                             "Sommeil.", |  | ||||||
|                             "Mettre fin au sort.", |  | ||||||
|                             "Glyphe à sort.", |  | ||||||
|                             "Runes explosives.", |  | ||||||
|                             "Approche.", |  | ||||||
|                             "Arrête.", |  | ||||||
|                             "Fuis.", |  | ||||||
|                             "Lâche.", |  | ||||||
|                             "Rampe.", |  | ||||||
|                             "Main agrippeuse.", |  | ||||||
|                             "Main interposée.", |  | ||||||
|                             "Main percutante.", |  | ||||||
|                             "Poing serré.", |  | ||||||
|                             "Nauséeux.", |  | ||||||
|                             "Endormi.", |  | ||||||
|                             "Paniqué.", |  | ||||||
|                             "Créature en créature.", |  | ||||||
|                             "Objet en créature.", |  | ||||||
|                             "Créature en objet.", |  | ||||||
|                             "Adaptation aquatique.", |  | ||||||
|                             "Armes naturelles.", |  | ||||||
|                             "Changer d’apparence.", |  | ||||||
|                             "1. Rouge.", |  | ||||||
|                             "2. Orange.", |  | ||||||
|                             "3. Jaune.", |  | ||||||
|                             "4. Vert.", |  | ||||||
|                             "5. Bleu.", |  | ||||||
|                             "6. Indigo.", |  | ||||||
|                             "7. Violet.", |  | ||||||
|                             "Couloirs.", |  | ||||||
|                             "Escaliers.", |  | ||||||
|                             "Portes.", |  | ||||||
|                             "Autres effets de sort.", |  | ||||||
|                             "Attirance.", |  | ||||||
|                             "Répulsion.", |  | ||||||
|                             "Mettre un terme à l’effet.", |  | ||||||
|                             "Courage.", |  | ||||||
|                             "Interférence extradimensionnelle.", |  | ||||||
|                             "Langues.", |  | ||||||
|                             "Lumière du jour.", |  | ||||||
|                             "Protection contres les énergies.", |  | ||||||
|                             "Repos éternel.", |  | ||||||
|                             "Ténèbres.", |  | ||||||
|                             "Vulnérabilité à l’énergie.", |  | ||||||
|                             "Silence.", |  | ||||||
|                             "Terreur.", |  | ||||||
|                             "Démence.", |  | ||||||
|                             "Désespoir.", |  | ||||||
|                             "Discorde.", |  | ||||||
|                             "Douleur.", |  | ||||||
|                             "Étourdissement.", |  | ||||||
|                             "Frayeur.", |  | ||||||
|                             "Mort.", |  | ||||||
|                             "Sommeil.", |  | ||||||
|                             "Créatures.", |  | ||||||
|                             "Objets.", |  | ||||||
|                             "Familiarité.", |  | ||||||
|                             "Sur place.", |  | ||||||
|                             "À proximité.", |  | ||||||
|                             "Zone similaire.", |  | ||||||
|                             "Incident.", |  | ||||||
|                             "Round 2.", |  | ||||||
|                             "Round 3.", |  | ||||||
|                             "Round 4.", |  | ||||||
|                             "Rounds 5 à 10.", |  | ||||||
|                             "Fissures.", |  | ||||||
|                             "Structures.", |  | ||||||
|                         }; |  | ||||||
|                         foreach (var title in titles) |  | ||||||
|                         { |  | ||||||
|                             if (line.StartsWith(title)) |  | ||||||
|                             { |  | ||||||
|                                 line = "<strong><em>" + title + "</em></strong>" + line.Substring(title.Length); |  | ||||||
|                                 break; |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                     if (line.EndsWith(".")) |  | ||||||
|                     { |  | ||||||
|                         formattedDescription += line; |  | ||||||
|                         if (li) |  | ||||||
|                         { |  | ||||||
|                             formattedDescription += "</li>"; |  | ||||||
|                             li = false; |  | ||||||
|                         } |  | ||||||
|                         formattedDescription += "\n"; |  | ||||||
|                     } |  | ||||||
|                     else |  | ||||||
|                     { |  | ||||||
|                         formattedDescription += line + " "; |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                     line = await reader.ReadLineAsync(); |  | ||||||
|                 } |  | ||||||
|                 if (li) |  | ||||||
|                 { |  | ||||||
|                     formattedDescription += "</li>"; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             return formattedDescription; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         private static T LoadJSon<T>(string filename) where T : class |         private static T LoadJSon<T>(string filename) where T : class | ||||||
|         { |         { | ||||||
|             var serializer = new DataContractJsonSerializer(typeof(T)); |             var serializer = new DataContractJsonSerializer(typeof(T)); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Yan Maniez
						Yan Maniez