public ObservableCollection<CraftingMaterial> ReadSetFromDB(string url) { HtmlDocument document = null; try { document = htmlWeb.Load(url); } catch (WebException e) { MessageBox.Show(e.Message, "Something went wrong"); } string classToFind = "browsetb"; var set_table = document.DocumentNode.SelectNodes(string.Format("//*[contains(@class,'{0}')]", classToFind)).First(); var tbody = set_table.ChildNodes[3]; HtmlNode nodeWithSetItems = tbody; List<CraftingMaterial> tempMaterialList = new List<CraftingMaterial>(); // Here we go through each item to extract it's materials. Each row of the table is one item. foreach (HtmlNode nodeWithSingleItem in nodeWithSetItems.ChildNodes.Where(n => n.Name == "tr")) { classToFind = "td-rend"; var item_info = document.DocumentNode.SelectNodes(string.Format("//*[contains(@class,'{0}')]", classToFind)).First(); classToFind = "vitem_info_gold"; var info_gold = document.DocumentNode.SelectNodes(string.Format("//*[contains(@class,'{0}')]", classToFind)).First(); ItemRecipe setItem = new ItemRecipe(); // Info about the item itself, like name and the image HtmlNode nodeWithItemInfo = item_info.ChildNodes[0].ChildNodes[0]; string itemNameTemp = nodeWithItemInfo.Attributes[0].Value; string itemName = itemNameTemp.Substring(itemNameTemp.IndexOf("=") + 1).Replace("+", " ").Replace("%27", "'"); HtmlNode nodeWithItemImage = nodeWithItemInfo.ChildNodes[0].ChildNodes[0].ChildNodes[2]; string itemImageUrl = nodeWithItemImage.Attributes[0].Value; // Extract the gold info HtmlNode nodeWithGoldCost = info_gold.ChildNodes[0]; double gold = double.Parse(nodeWithGoldCost.InnerText.Replace(",", ".")); CraftingMaterial fee = new CraftingMaterial(FindResource("Icon_Gold").ToString(), "Fee", gold); fee.ShowAmount = false; fee.AllowAmountInput = false; fee.ShowFeeTextBlock = true; tempMaterialList.Add(fee); setItem.RecipeMaterials.Add(fee); // This node has all materials for a single item, so we can go through all materials in it HtmlNode nodeWithAllMaterialsForItem = nodeWithSingleItem.ChildNodes[7]; foreach (HtmlNode nodeWithOnlyOneMaterial in nodeWithAllMaterialsForItem.ChildNodes) { // The name of the material, e.g. "Superior Iron Ore" string materialNameTemp = nodeWithOnlyOneMaterial.ChildNodes[0].Attributes[0].Value; string materialName = materialNameTemp.Substring(materialNameTemp.IndexOf("=") + 1).Replace("+", " ").Replace("%27", "'"); ; // This node contains both how much of this material need aswell as the image belonging to it HtmlNode nodeWithAmountAndImage = nodeWithOnlyOneMaterial.ChildNodes[0].ChildNodes[0].ChildNodes[0]; double materialAmount; HtmlNode materialImageNode; /* If the amount is 1, it's not specified on the website, so we have to handle this case seperately * This also means that there are less nodes, so the node with the image is in a different position */ if (nodeWithAmountAndImage.ChildNodes.Count == 1) { materialAmount = 1; materialImageNode = nodeWithAmountAndImage.ChildNodes[0]; } else // If the amount is not 1, we can simply parse it { HtmlNode nodeWithMaterialAmount = nodeWithAmountAndImage.ChildNodes[1].ChildNodes[1]; ; materialAmount = double.Parse(nodeWithMaterialAmount.InnerText.Substring(1)); materialImageNode = nodeWithAmountAndImage.ChildNodes[2]; } // Finally we can set the image url string materialImageUrl = materialImageNode.Attributes[0].Value; // Create a new crafting material with all the info and add it to the list CraftingMaterial craftingMaterial = new CraftingMaterial(materialImageUrl, materialName, materialAmount); tempMaterialList.Add(craftingMaterial); setItem.RecipeMaterials.Add(craftingMaterial); } setItem.ImageUrl = itemImageUrl; setItem.ItemName = itemName; ItemRecipes.Add(setItem); } //Now we clean up a bit. Currently, if several items use the same materials, they are all listed individually. Here we add them up, so we get a nice little list instead for (int i = 0; i < tempMaterialList.Count; i++) { // We need to save how much of each material was needed double amount = 0; // This is the "reference" material, the others get compared to it CraftingMaterial outerMaterial = new CraftingMaterial(tempMaterialList[i].ImageUrl, tempMaterialList[i].MaterialName, tempMaterialList[i].Amount) { AllowAmountInput = tempMaterialList[i].AllowAmountInput, ShowAmount = tempMaterialList[i].ShowAmount, ShowFeeTextBlock = tempMaterialList[i].ShowFeeTextBlock }; for (int j = 0; j < tempMaterialList.Count; j++) { if (j == i) // same position means same material, we can ignore it continue; // The current material we want to compare to our reference. Same name means same material, so we can add it up CraftingMaterial innerMaterial = tempMaterialList[j]; if (innerMaterial.MaterialName == outerMaterial.MaterialName) { amount += innerMaterial.Amount; tempMaterialList.Remove(innerMaterial); } } // Add up the amount and add the material to the list outerMaterial.Amount += amount; Materials.Add(outerMaterial); } // Finally done. Return the list. Note that it's empty if the item was not found return Materials; }
/// <summary> /// Handler for the calculate button. Adds up the cost and adds the resulting crafting materials to the result list /// </summary> private void btCalculate_Click(object sender, RoutedEventArgs e) { Results.Clear(); double totalCost = 0; if (IsSet) { foreach (ItemRecipe recipe in ItemRecipes) { foreach (CraftingMaterial material in recipe.RecipeMaterials) { CraftingMaterial tempMaterial = Materials.FirstOrDefault(mat => mat.MaterialName == material.MaterialName); material.Cost = tempMaterial.Cost * material.Amount; if (material.MaterialName == "Fee") { material.Cost = material.Amount; material.Amount = 1; } recipe.Cost += material.Cost; } TotalCost += recipe.Cost; } ItemRecipes.ToList<ItemRecipe>().ForEach(item => Results.Add(item)); viewSingleItem.Visibility = Visibility.Collapsed; viewSet.Visibility = Visibility.Visible; } else { foreach (CraftingMaterial material in Materials) { if (material.MaterialName == "Fee") { material.Cost = material.Amount; material.Amount = 1; } totalCost += material.Cost * material.Amount; CraftingMaterial materialCost = new CraftingMaterial(material.ImageUrl, material.MaterialName, material.Amount, material.Amount * material.Cost); materialCost.ShowFeeTextBlock = true; Results.Add(materialCost); } CraftingMaterial materialTotalCost = new CraftingMaterial("Icons/Icon_Gold.png", "Total cost", 1, totalCost); materialTotalCost.ShowFeeTextBlock = true; Results.Add(materialTotalCost); viewSet.Visibility = Visibility.Collapsed; viewSingleItem.Visibility = Visibility.Visible; } e.Handled = true; }
/// <summary> /// Searches for an item on VindictusDB and returns all the materials needed to craft it /// </summary> public ObservableCollection<CraftingMaterial> ReadItemFromDB(string itemName, out bool item_found) { // clear the list to ensure now old materials interfere Materials.Clear(); // Well, we have to set it to something.. item_found = false; HtmlDocument document = null; try { document = htmlWeb.Load(baseURIDB + URIRecipe + itemName); } catch (WebException e) { // Actually, we don't know, but this surpressed the "item not found" message. item_found = true; MessageBox.Show(e.Message, "Something went wrong"); } if (document != null && !document.DocumentNode.InnerText.Contains("Invalid Entry")) { item_found = true; HtmlNode nodeWithGoldCost = document.DocumentNode.SelectSingleNode("/html[1]/body[1]/div[1]/div[4]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[1]/td[2]"); double gold = double.Parse(nodeWithGoldCost.InnerText.Replace(",", ".")); CraftingMaterial fee = new CraftingMaterial(FindResource("Icon_Gold").ToString(), "Fee", gold); fee.ShowAmount = false; fee.AllowAmountInput = false; fee.ShowFeeTextBlock = true; Materials.Add(fee); HtmlNode nodeWithAllMaterials = document.DocumentNode.SelectSingleNode("/html[1]/body[1]/div[1]/div[4]/div[1]/div[4]/div[2]/table[1]/tbody[1]/tr[1]/td[3]"); foreach (HtmlNode childNode in nodeWithAllMaterials.ChildNodes) { HtmlNode nodeWithSingleMaterial = childNode.ChildNodes[0]; HtmlAttribute materialNameAttribute = nodeWithSingleMaterial.Attributes[0]; string materialName = materialNameAttribute.Value.Substring(materialNameAttribute.Value.IndexOf("=") + 1).Replace("+", " ").Replace("%27", "'"); HtmlNode subNode = nodeWithSingleMaterial.ChildNodes[0].ChildNodes[0]; double materialAmount; HtmlNode materialImageNode; if (subNode.ChildNodes.Count == 1) { materialAmount = 1; materialImageNode = subNode.ChildNodes[0]; } else { HtmlNode nodeWithMaterialAmount = subNode.ChildNodes[1].ChildNodes[1]; materialAmount = double.Parse(nodeWithMaterialAmount.InnerText.Substring(1)); materialImageNode = subNode.ChildNodes[2]; } string materialImageUrl = materialImageNode.Attributes[0].Value; CraftingMaterial craftingMaterial = new CraftingMaterial(materialImageUrl, materialName, materialAmount); Materials.Add(craftingMaterial); } } return Materials; }