public void Analyze(List <FFXIVAetheryte> iAetherytes, List <FFXIVGatheringNode> iNodes, ref Dictionary <string, double> dictionaryClosestAetherytes) { Status = "Unknown"; IsValid = false; try { string contentGrid = File.ReadAllText(GridFile.FullName); if (contentGrid == "") { Status = "Empty Grid"; return; } ParseFromLine(contentGrid); //Finding item gathering nodes bool noGatheringNodeMode = false; List <FFXIVGatheringNode> correspondingNodes = new List <FFXIVGatheringNode>(); foreach (FFXIVGatheringNode node in iNodes) { if (null == node) { continue; } string foundItemName = node.NodeItems.Find(x => x != null && x.ToLower().Trim() == ItemName.ToLower().Trim()); if (foundItemName != null && foundItemName != "") { correspondingNodes.Add(node); } } if (correspondingNodes.Count <= 0 && ItemName != "") { List <FFXIVSearchItem> resultGarlandTools = GarlandTool.Search(ItemName, null, FFXIVItem.TypeItem.Gathered); if (resultGarlandTools.Count > 0) { List <FFXIVGatheringNode> correspondingNodesFromGarland = GarlandTool.GetGatheringNodesFromItem(resultGarlandTools[0].ID); foreach (FFXIVGatheringNode garlandNode in correspondingNodesFromGarland) { string foundItemName = garlandNode.NodeItems.Find(x => x != null && x.ToLower().Trim() == ItemName.ToLower().Trim()); if (foundItemName != null && foundItemName != "") { correspondingNodes.Add(garlandNode); } /* * FFXIVGatheringNode bestNode = null; * double maxCorrespondance = -1; * foreach (FFXIVGatheringNode node in iNodes) * { * if(node.Zone.ToLower().Trim() != garlandNode.Zone.ToLower().Trim()) * { * continue; * } * * double nbSameItem = 0; * double nbTotalItem = node.NodeItems.Count; * * foreach(string itemName in node.NodeItems) * { * if (null != garlandNode.NodeItems.Find(x => x != null && x.ToLower().Trim() == itemName.ToLower().Trim())) * { * nbSameItem += 1.0; * } * } * double correspondance = 100.0 * nbSameItem / nbTotalItem; * if(maxCorrespondance < correspondance) * { * maxCorrespondance = correspondance; * bestNode = node; * } * } * if (maxCorrespondance < 0) continue; * if (null == bestNode) continue; * correspondingNodes.Add(bestNode); */ } } noGatheringNodeMode = correspondingNodes.Count > 0; } AllNodes = correspondingNodes; //Finding closest node double minDistance = -1; if (!noGatheringNodeMode) { foreach (FFXIVGatheringNode node in correspondingNodes) { if (null == node) { continue; } double nodeDistance = -1; foreach (FFXIVPosition point in Points) { double distance = node.Position.PlanarDistanceTo(point); if (minDistance < 0 || distance < minDistance) { minDistance = distance; ClosestNode = node; ClosestNodeDistance = minDistance; } if (nodeDistance < 0 || distance < nodeDistance) { nodeDistance = distance; } } AllNodesDistance.Add(nodeDistance); } if (minDistance > 50) { Status = "Too far from closest gathering node."; return; } if (null == ClosestNode) { Status = "No gathering node."; return; } } else { if (AllNodes.Count == 1) { ClosestNode = AllNodes[0]; } foreach (FFXIVGatheringNode node in correspondingNodes) { AllNodesDistance.Add(-1); } } string statusPrefix = ""; if (noGatheringNodeMode) { statusPrefix = "[No-Node] "; } //Finding zone aetherytes List <FFXIVAetheryte> listZoneAetherytes = new List <FFXIVAetheryte>(); foreach (FFXIVAetheryte aetherythe in iAetherytes) { if (noGatheringNodeMode) { foreach (FFXIVGatheringNode node in correspondingNodes) { if (aetherythe.Zone == node.Zone) { listZoneAetherytes.Add(aetherythe); } } } else { if (aetherythe.Zone == ClosestNode.Zone) { listZoneAetherytes.Add(aetherythe); } } } //Finding closest aetheryte double minDistanceAetheryte = -1; List <FFXIVPosition> listAetheryteClosePoints = new List <FFXIVPosition>(); foreach (FFXIVAetheryte aetherythe in listZoneAetherytes) { if (null == aetherythe) { continue; } double distanceAetheryte = -1; foreach (FFXIVPosition point in Points) { double distance = aetherythe.Position.PlanarDistanceTo(point); if (minDistanceAetheryte < 0 || distance < minDistanceAetheryte) { minDistanceAetheryte = distance; ClosestAetheryte = aetherythe; ClosestAetheryteDistance = minDistanceAetheryte; } if (distanceAetheryte < 0 || distance < distanceAetheryte) { distanceAetheryte = distance; } if (distance < 50) { listAetheryteClosePoints.Add(point); } } ZoneAetherytes.Add(aetherythe); ZoneAetherytesDistance.Add(distanceAetheryte); } if (minDistanceAetheryte > 40) { Status = statusPrefix + "Too far from closest aetheryte."; return; } if (null == ClosestAetheryte) { Status = statusPrefix + "No Aetheryte."; return; } if (listAetheryteClosePoints.Count < 1) { Status = statusPrefix + "Not enough close points."; return; } ListAetheryteClosePoints = listAetheryteClosePoints; if (dictionaryClosestAetherytes.ContainsKey(ItemName)) { double distance = dictionaryClosestAetherytes[ItemName]; if (distance < minDistanceAetheryte) { Status = statusPrefix + "Other grid is closer to grid points."; return; } } dictionaryClosestAetherytes[ItemName] = minDistanceAetheryte; Status = statusPrefix + "OK"; IsValid = true; } catch (Exception e) { Status = e.Message; } }
public void BuildPicture(List <FFXIVAetheryte> listAetheryteToDraw = null) { //if (null != Picture) return; double minX = 0, minY = 0, maxX = 0, maxY = 0; int index = 0; if (null == listAetheryteToDraw || listAetheryteToDraw.Count <= 0) { foreach (FFXIVPosition point in Points) { if (point.X < minX || index == 0) { minX = point.X; } if (point.X > maxX || index == 0) { maxX = point.X; } if (point.Y < minY || index == 0) { minY = point.Y; } if (point.Y > maxY || index == 0) { maxY = point.Y; } index++; } foreach (FFXIVGatheringNode node in AllNodes) { if (null == node) { continue; } if (null == node.Position) { continue; } if (node.Position.X < minX) { minX = node.Position.X; } if (node.Position.X > maxX) { maxX = node.Position.X; } if (node.Position.Y < minY) { minY = node.Position.Y; } if (node.Position.Y > maxY) { maxY = node.Position.Y; } } foreach (FFXIVAetheryte aetherythe in ZoneAetherytes) { if (null == aetherythe) { continue; } if (aetherythe.Position.X < minX) { minX = aetherythe.Position.X; } if (aetherythe.Position.X > maxX) { maxX = aetherythe.Position.X; } if (aetherythe.Position.Y < minY) { minY = aetherythe.Position.Y; } if (aetherythe.Position.Y > maxY) { maxY = aetherythe.Position.Y; } } } else { foreach (FFXIVAetheryte aetherythe in listAetheryteToDraw) { if (null == aetherythe) { continue; } { minX = -aetherythe.OffsetX * 50; minY = -aetherythe.OffsetY * 50; maxX = aetherythe.OffsetX * 50; maxY = aetherythe.OffsetY * 50; } } //Find Closest Aetheryte double minDistanceAetheryte = -1; List <FFXIVPosition> listAetheryteClosePoints = new List <FFXIVPosition>(); foreach (FFXIVAetheryte aetherythe in listAetheryteToDraw) { if (null == aetherythe) { continue; } double distanceAetheryte = -1; foreach (FFXIVPosition point in Points) { double distance = aetherythe.Position.PlanarDistanceTo(point); if (minDistanceAetheryte < 0 || distance < minDistanceAetheryte) { minDistanceAetheryte = distance; ClosestAetheryte = aetherythe; ClosestAetheryteDistance = minDistanceAetheryte; } if (distanceAetheryte < 0 || distance < distanceAetheryte) { distanceAetheryte = distance; } if (distance < 50) { listAetheryteClosePoints.Add(point); } } } } //Drawing Bitmap minX -= 10; maxX += 10; minY -= 10; maxY += 10; int width = (int)(maxX - minX + 0.5); int height = (int)(maxY - minY + 0.5); int thicknessW = width / 100; int thicknessH = height / 100; int thickness = thicknessH; if (thicknessW > thickness) { thickness = thicknessW; } if (thickness < 2) { thickness = 2; } if (width > 0 && height > 0) { Bitmap bm = new Bitmap(width, height); using (Graphics gr = Graphics.FromImage(bm)) { gr.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = new Rectangle(0, 0, width, height); gr.FillRectangle(Brushes.White, rect); try { if (listAetheryteToDraw.Count > 0 && null != listAetheryteToDraw[0]) { gr.DrawImage(Image.FromFile(listAetheryteToDraw[0].BackgroundPicture.FullName), rect); } } catch { } foreach (FFXIVPosition point in Points) { int coordX = (int)point.X + (int)(-minX) - thickness / 2; int coordY = (int)point.Y + (int)(-minY) - thickness / 2; Rectangle rectPoint = new Rectangle(coordX, coordY, thickness, thickness); gr.FillEllipse(Brushes.Black, rectPoint); } foreach (FFXIVPosition point in ListAetheryteClosePoints) { int coordX = (int)point.X + (int)(-minX) - thickness / 2; int coordY = (int)point.Y + (int)(-minY) - thickness / 2; Rectangle rectPoint = new Rectangle(coordX, coordY, thickness, thickness); gr.FillEllipse(Brushes.Brown, rectPoint); } foreach (FFXIVGatheringNode node in AllNodes) { if (null == node.Position) { continue; } int coordX = (int)node.Position.X + (int)(-minX) - thickness / 2; int coordY = (int)node.Position.Y + (int)(-minY) - thickness / 2; Rectangle rectPoint = new Rectangle(coordX, coordY, thickness, thickness); gr.FillEllipse(Brushes.GreenYellow, rectPoint); } foreach (FFXIVAetheryte aetheryte in ZoneAetherytes) { int coordX = (int)aetheryte.Position.X + (int)(-minX) - thickness / 2; int coordY = (int)aetheryte.Position.Y + (int)(-minY) - thickness / 2; Rectangle rectPoint = new Rectangle(coordX, coordY, thickness, thickness); gr.FillEllipse(Brushes.Blue, rectPoint); } foreach (FFXIVAetheryte aetheryte in listAetheryteToDraw) { int coordX = (int)aetheryte.Position.X + (int)(-minX) - thickness / 2; int coordY = (int)aetheryte.Position.Y + (int)(-minY) - thickness / 2; Rectangle rectPoint = new Rectangle(coordX - thickness / 2, coordY - thickness / 2, thickness * 2, thickness * 2); gr.FillEllipse(Brushes.Red, rectPoint); rectPoint = new Rectangle(coordX, coordY, thickness * 1, thickness * 1); gr.FillEllipse(Brushes.White, rectPoint); } if (null != ClosestNode && null != ClosestNode.Position) { int coordX = (int)ClosestNode.Position.X + (int)(-minX) - thickness / 2; int coordY = (int)ClosestNode.Position.Y + (int)(-minY) - thickness / 2; Rectangle rectPoint = new Rectangle(coordX, coordY, thickness, thickness); gr.FillEllipse(Brushes.Green, rectPoint); } if (null != ClosestAetheryte) { int coordX = (int)ClosestAetheryte.Position.X + (int)(-minX) - thickness / 2; int coordY = (int)ClosestAetheryte.Position.Y + (int)(-minY) - thickness / 2; Rectangle rectPoint = new Rectangle(coordX - thickness / 2, coordY - thickness / 2, thickness * 2, thickness * 2); gr.FillEllipse(Brushes.Violet, rectPoint); rectPoint = new Rectangle(coordX, coordY, thickness * 1, thickness * 1); gr.FillEllipse(Brushes.White, rectPoint); } } Picture = bm; } }
/// <summary> /// Retrieves all aetheryte names and positions from https://ffxiv.consolegameswiki.com/wiki/Zone /// </summary> /// <returns></returns> public static List <FFXIVAetheryte> GetAetherytesFromRegion(string iRegion, string iZoneName, string iPageLink) { List <FFXIVAetheryte> result = new List <FFXIVAetheryte>(); DirectoryInfo exeDirectory = new DirectoryInfo(Service_Misc.GetExecutionPath()); DirectoryInfo metadataDirectory = new DirectoryInfo(Path.Combine(exeDirectory.FullName, "Metadata")); //Main zone page CookieCollection oCookies = new CookieCollection(); HttpStatusCode oCode = HttpStatusCode.NotFound; HtmlDocument answer = Service_Misc.GetWebPageFromRequest("GET https://ffxiv.consolegameswiki.com" + iPageLink + " HTTP/1.1|Host: ffxiv.consolegameswiki.com|Connection: keep-alive|Pragma: no-cache|Cache-Control: no-cache|Upgrade-Insecure-Requests: 1|User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36|Sec-Fetch-User: ?1|Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9|Sec-Fetch-Site: same-origin|Sec-Fetch-Mode: navigate|Referer: https://ffxiv.consolegameswiki.com/wiki/FF14_Wiki|Accept-Encoding: gzip, deflate|Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7|Cookie: __cfduid=d64998d831d683525635413f445baf9671577745615; _ga=GA1.2.147161069.1577745617; _gid=GA1.2.132489683.1577745617; trc_cookie_storage=taboola%2520global%253Auser-id%3D8ee6f8c7-39f8-4db7-b620-5868e971d900-tuct4ec3105||", oCookies, ref oCookies, ref oCode); if (null == answer) { return(result); } HtmlNode nodeInfobox = Service_Misc.GetFirstChildNode(answer.DocumentNode, "div", "infobox-n area"); if (null == nodeInfobox) { return(result); } List <HtmlNode> dlNodes = nodeInfobox.Descendants("dl").ToList(); if (dlNodes.Count != 1) { return(result); } foreach (HtmlNode aNode in dlNodes[0].ChildNodes) { if (aNode.Name != "dd") { continue; } string text = aNode.InnerText; List <string> listAetherytes = text.Split(')').ToList(); foreach (string aetheryteText in listAetherytes) { if (aetheryteText.Contains("(X:") && aetheryteText.Contains("Y:")) { string xText = aetheryteText.Split(new string[] { "(X:" }, StringSplitOptions.None)[1].Split(',')[0].Trim(); string yText = aetheryteText.Split(new string[] { "Y:" }, StringSplitOptions.None)[1].Split(')')[0].Split(',')[0].Trim(); string nameText = aetheryteText.Split(new string[] { "(X:" }, StringSplitOptions.None)[0]; double x = 0, y = 0; double.TryParse(xText, System.Globalization.NumberStyles.Any, CultureInfo.InvariantCulture, out x); double.TryParse(yText, System.Globalization.NumberStyles.Any, CultureInfo.InvariantCulture, out y); FFXIVAetheryte aetheryte = new FFXIVAetheryte(); aetheryte.Region = iRegion; aetheryte.Zone = iZoneName; aetheryte.Name = nameText; //Conversion aetheryte position to map position double offsetX = 0; double offsetY = 0; FileInfo metadataFile = new FileInfo(Path.Combine(metadataDirectory.FullName, aetheryte.Zone + ".txt")); if (!metadataFile.Exists) { offsetX = 0; offsetY = 0; File.WriteAllText(metadataFile.FullName, "21.4;21.4"); } else { string metadata = File.ReadAllText(metadataFile.FullName); List <string> coordinatesMetadata = metadata.Replace(",", ".").Split(';').ToList(); double.TryParse(coordinatesMetadata[0], System.Globalization.NumberStyles.Any, CultureInfo.InvariantCulture, out offsetX); double.TryParse(coordinatesMetadata[1], System.Globalization.NumberStyles.Any, CultureInfo.InvariantCulture, out offsetY); } aetheryte.Position = new FFXIVPosition((x - offsetX) * 50, (y - offsetY) * 50); result.Add(aetheryte); } } } return(result); }