Example #1
0
        public WikiBuildingInfoPresets FetchBuildingDetails(WikiBuildingInfoPresets wikiBuildingInfoList)
        {
            //download complete wikitext for each building
            SaveCompleteInfos(wikiBuildingInfoList);

            //extract infobox for each found wikitext
            ExtractAllInfoboxes();

            //parse infoboxes
            return(GetUpdatedWikiBuildingInfoList(wikiBuildingInfoList));
        }
        public WikiBuildingInfoPresets GetWikiBuildingInfos(WikiTextTableContainer list)
        {
            var wikibuildingList = new WikiBuildingInfoPresets();

            foreach (var curentry in list.Entries)
            {
                wikibuildingList.Infos.Add(ParseWikiBuildingInfo(curentry));
            }

            //order buildings by name
            wikibuildingList.Infos = wikibuildingList.Infos.OrderBy(x => x.Name).ToList();

            return(wikibuildingList);
        }
        public WikiBuildingInfoPresets Load(string pathToPresetsFile)
        {
            WikiBuildingInfoPresets result = null;

            try
            {
                result = SerializationHelper.LoadFromFile <WikiBuildingInfoPresets>(pathToPresetsFile);
            }
            catch (Exception ex)
            {
                Trace.WriteLine($"Error loading the buildings.{Environment.NewLine}{ex}");
                throw;
            }

            return(result);
        }
        private async Task GenerateTemplate(object param)
        {
            try
            {
                IsBusy        = true;
                StatusMessage = string.Empty;

                var buildingPresetsTask = Task.Run(() =>
                {
                    //load building presets
                    BuildingPresets localBuildingPresets = null;
                    try
                    {
                        var loader           = new BuildingPresetsLoader();
                        localBuildingPresets = loader.Load(PresetsVM.SelectedFile);
                        if (localBuildingPresets == null || localBuildingPresets.Buildings == null)
                        {
                            throw new ArgumentException();
                        }
                    }
                    catch (Exception ex)
                    {
                        var message = $"Error parsing {nameof(BuildingPresets)}.";
                        logger.Error(ex, message);
                        MessageBox.Show(message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);

                        StatusMessage = $"{message} -> Maybe wrong selected file?";
                        return(null);
                    }

                    PresetsVersion = localBuildingPresets.Version;

                    return(localBuildingPresets);
                });

                var wikiBuildingInfoPresetsTask = Task.Run(() =>
                {
                    //load wiki buildng info
                    WikiBuildingInfoPresets localWikiBuildingInfoPresets = null;
                    try
                    {
                        var loader = new WikiBuildingInfoPresetsLoader();
                        localWikiBuildingInfoPresets = loader.Load(WikiBuildingsInfoVM.SelectedFile);
                    }
                    catch (Exception ex)
                    {
                        var message = $"Error parsing {nameof(WikiBuildingInfoPresets)}.";
                        logger.Error(ex, message);
                        MessageBox.Show(message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);

                        StatusMessage = $"{message} -> Maybe wrong selected file?";
                        return(null);
                    }

                    WikiBuildingInfoPresetsVersion = localWikiBuildingInfoPresets.Version.ToString();

                    return(localWikiBuildingInfoPresets);
                });

                var layoutTask = Task.Run(() =>
                {
                    //load layout
                    List <AnnoObject> localLayout = null;
                    try
                    {
                        ILayoutLoader loader = new LayoutLoader();
                        localLayout          = loader.LoadLayout(LayoutVM.SelectedFile);
                    }
                    catch (Exception ex)
                    {
                        var message = "Error parsing layout file.";
                        logger.Error(ex, message);
                        MessageBox.Show(message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);

                        StatusMessage = $"{message} -> Maybe wrong selected file?";
                        return(null);
                    }

                    LayoutName = Path.GetFileName(LayoutVM.SelectedFile);

                    return(localLayout);
                });

                await Task.WhenAll(buildingPresetsTask, wikiBuildingInfoPresetsTask, layoutTask);

                var buildingPresets         = buildingPresetsTask.Result;
                var wikiBuildingInfoPresets = wikiBuildingInfoPresetsTask.Result;
                var layout = layoutTask.Result;

                if (buildingPresets == null || wikiBuildingInfoPresets == null || layout == null)
                {
                    return;
                }

                var layoutNameForTemplate = Path.GetFileNameWithoutExtension(LayoutVM.SelectedFile).Replace("_", " ");

                await Task.Run(() =>
                {
                    var exporter = new FandomExporter();
                    Template     = exporter.StartExport(layoutNameForTemplate, layout, buildingPresets, wikiBuildingInfoPresets, true);
                });

                StatusMessage = "Template successfully generated.";
            }
            catch (Exception ex)
            {
                var message = "Error generating template.";
                logger.Error(ex, message);
                MessageBox.Show(message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);

                StatusMessage = $"{message} -> Details in log file.";
            }
            finally
            {
                IsBusy = false;
            }
        }
        public string StartExport(string layoutName, LayoutFile layout, BuildingPresets buildingPresets, WikiBuildingInfoPresets wikiBuildingInfoPresets, bool exportUnsupportedTags)
        {
            //https://anno1800.fandom.com/wiki/Template:Production_layout
            //https://anno1800.fandom.com/wiki/Template:Production_layout/doc
            //https://anno1800.fandom.com/wiki/Category:Template_documentation

            //https://anno1800.fandom.com/wiki/Testing_page

            //TODO warn user when layout contains more than 15 building types because template only supports 1-15
            //template only supports 1-8 for "Production x Type" and "Production x per minute"
            //TODO warn user (or exit) when layout contains buildings other than Anno 1800

            var calculatedStatistics = _statisticsCalculationHelper.CalculateStatistics(layout.Objects);

            var exportString = new StringBuilder(900);//best guess on minimal layout

            exportString.Append(TEMPLATE_START)
            .AppendLine(HEADER_PRODUCTION_LAYOUT)
            .Append(TEMPLATE_LINE_START).Append(HEADER_ICON).AppendLine(TEMPLATE_ENTRY_DELIMITER)
            .Append(TEMPLATE_LINE_START).Append(HEADER_LAYOUT_NAME).Append(TEMPLATE_ENTRY_DELIMITER).AppendLine(layoutName)
            .Append(TEMPLATE_LINE_START).Append(HEADER_LAYOUT_IMAGE).AppendLine(TEMPLATE_ENTRY_DELIMITER);

            //add buildings
            exportString = addBuildingInfo(exportString, layout.Objects, buildingPresets, wikiBuildingInfoPresets);

            exportString.Append(TEMPLATE_LINE_START).Append(HEADER_LAYOUT_DESCRIPTION).AppendLine(TEMPLATE_ENTRY_DELIMITER)
            .Append(TEMPLATE_LINE_START).Append(HEADER_SIZE).Append(TEMPLATE_ENTRY_DELIMITER).Append(calculatedStatistics.UsedAreaWidth.ToString()).Append(TEMPLATE_SIZE_ENTRY_DELIMITER).AppendLine(calculatedStatistics.UsedAreaHeight.ToString())
            .Append(TEMPLATE_LINE_START).Append(HEADER_TILES).Append(TEMPLATE_ENTRY_DELIMITER).AppendLine(calculatedStatistics.UsedTiles.ToString())
            .Append(TEMPLATE_LINE_START).Append(HEADER_AUTHOR).AppendLine(TEMPLATE_ENTRY_DELIMITER)
            .Append(TEMPLATE_LINE_START).Append(HEADER_SOURCE).AppendLine(TEMPLATE_ENTRY_DELIMITER);

            exportString = addProductionInfo(exportString, layout.Objects, buildingPresets, wikiBuildingInfoPresets);
            exportString = addConstructionInfo(exportString, layout.Objects, buildingPresets, wikiBuildingInfoPresets);
            exportString = addBalance(exportString, layout.Objects, buildingPresets, wikiBuildingInfoPresets);
            exportString = addWorkforceInfo(exportString, layout.Objects, buildingPresets, wikiBuildingInfoPresets);
            exportString = addInfluence(exportString, layout.Objects, buildingPresets, wikiBuildingInfoPresets);
            exportString = addAttractiveness(exportString, layout.Objects, buildingPresets, wikiBuildingInfoPresets);

            if (exportUnsupportedTags)
            {
                exportString = addUnsupportedEntries(exportString);
            }

            exportString.Append(TEMPLATE_END);

            return(exportString.ToString());
        }
        private WikiBuildingInfo getWikiBuildingInfo(string buildingIdentifier, BuildingPresets buildingPresets, WikiBuildingInfoPresets wikiBuildingInfoPresets)
        {
            WikiBuildingInfo result = null;

            var foundPresetBuilding = buildingPresets.Buildings.FirstOrDefault(x => x.Identifier.Equals(buildingIdentifier, StringComparison.OrdinalIgnoreCase));
            var buildingName        = foundPresetBuilding?.Localization["eng"];
            var buildingFaction     = foundPresetBuilding?.Faction;
            var buildingRegion      = WorldRegion.OldWorld;

            if (buildingFaction?.Contains("Obreros") == true || buildingFaction?.Contains("Jornaleros") == true)
            {
                buildingRegion = WorldRegion.NewWorld;
            }

            if (string.IsNullOrWhiteSpace(buildingName))
            {
                //TODO error?
                logger.Warn($"found no building name for identifier: {buildingIdentifier}");
                return(result);
            }

            //try to find by name
            result = wikiBuildingInfoPresets.Infos.FirstOrDefault(x => x.Name.Equals(buildingName, StringComparison.OrdinalIgnoreCase) && x.Region == buildingRegion);
            if (result == null)
            {
                //Is it a farm with field info? (e.g. "Potato Farm - (72)")
                var matchFieldCount = regexFieldCount.Match(buildingName);
                if (matchFieldCount.Success)
                {
                    //strip field info and search again
                    var strippedBuildingName = buildingName.Replace(matchFieldCount.Value, string.Empty).Trim();
                    result = wikiBuildingInfoPresets.Infos.FirstOrDefault(x => x.Name.Equals(strippedBuildingName, StringComparison.OrdinalIgnoreCase) && x.Region == buildingRegion);
                }
            }

            return(result);
        }
        private StringBuilder addAttractiveness(StringBuilder exportString, List <AnnoObject> placedObjects, BuildingPresets buildingPresets, WikiBuildingInfoPresets wikiBuildingInfoPresets)
        {
            double attractiveness = 0;

            var groupedBuildings = placedObjects.Where(x => !x.Road && !string.IsNullOrWhiteSpace(x.Identifier) && !x.Identifier.Equals("Unknown Object", StringComparison.OrdinalIgnoreCase)).GroupBy(x => x.Identifier);

            foreach (var curGroup in groupedBuildings)
            {
                var buildingIdentifier = curGroup.Key;
                var buildingCount      = curGroup.Count();

                var foundWikiBuildingInfo = getWikiBuildingInfo(buildingIdentifier, buildingPresets, wikiBuildingInfoPresets);
                if (foundWikiBuildingInfo == null || foundWikiBuildingInfo.MaintenanceInfos.Count == 0)
                {
                    //no info found -> skip
                    logger.Trace($"found no wiki info for identifier: {buildingIdentifier}");
                    continue;
                }

                //get attractiveness
                var foundAttractivenessEntry = foundWikiBuildingInfo.MaintenanceInfos.FirstOrDefault(x => x.Unit.Name.StartsWith("Attractiveness", StringComparison.OrdinalIgnoreCase));
                if (foundAttractivenessEntry != null)
                {
                    attractiveness = attractiveness + (foundAttractivenessEntry.Value * buildingCount);
                }
            }

            exportString.Append(TEMPLATE_LINE_START).Append(HEADER_ATTRACTIVENESS).Append(TEMPLATE_ENTRY_DELIMITER).AppendLine(attractiveness != 0 ? attractiveness.ToString("0") : string.Empty);

            return(exportString);
        }
        private StringBuilder addWorkforceInfo(StringBuilder exportString, List <AnnoObject> placedObjects, BuildingPresets buildingPresets, WikiBuildingInfoPresets wikiBuildingInfoPresets)
        {
            double farmers     = 0;
            double workers     = 0;
            double artisans    = 0;
            double engineers   = 0;
            double jornaleros  = 0;
            double obreros     = 0;
            double explorers   = 0;
            double technicians = 0;

            var groupedBuildings = placedObjects.Where(x => !x.Road && !string.IsNullOrWhiteSpace(x.Identifier) && !x.Identifier.Equals("Unknown Object", StringComparison.OrdinalIgnoreCase)).GroupBy(x => x.Identifier);

            foreach (var curGroup in groupedBuildings)
            {
                var buildingIdentifier = curGroup.Key;
                var buildingCount      = curGroup.Count();

                var foundWikiBuildingInfo = getWikiBuildingInfo(buildingIdentifier, buildingPresets, wikiBuildingInfoPresets);
                if (foundWikiBuildingInfo == null || foundWikiBuildingInfo.MaintenanceInfos.Count == 0)
                {
                    //no info found -> skip
                    logger.Trace($"found no wiki info for identifier: {buildingIdentifier}");
                    continue;
                }

                //get farmers
                var foundFarmersEntry = foundWikiBuildingInfo.MaintenanceInfos.FirstOrDefault(x => x.Unit.Name.Equals("Workforce Farmers", StringComparison.OrdinalIgnoreCase));
                if (foundFarmersEntry != null)
                {
                    farmers += (foundFarmersEntry.Value * buildingCount);
                }

                //get workers
                var foundWorkersEntry = foundWikiBuildingInfo.MaintenanceInfos.FirstOrDefault(x => x.Unit.Name.Equals("Workforce Workers", StringComparison.OrdinalIgnoreCase));
                if (foundWorkersEntry != null)
                {
                    workers += (foundWorkersEntry.Value * buildingCount);
                }

                //get artisans
                var foundArtisansEntry = foundWikiBuildingInfo.MaintenanceInfos.FirstOrDefault(x => x.Unit.Name.Equals("Workforce Artisans", StringComparison.OrdinalIgnoreCase));
                if (foundArtisansEntry != null)
                {
                    artisans += (foundArtisansEntry.Value * buildingCount);
                }

                //get engineers
                var foundEngineersEntry = foundWikiBuildingInfo.MaintenanceInfos.FirstOrDefault(x => x.Unit.Name.Equals("Workforce Engineers", StringComparison.OrdinalIgnoreCase));
                if (foundEngineersEntry != null)
                {
                    engineers += (foundEngineersEntry.Value * buildingCount);
                }

                //get jornaleros
                var foundJornalerosEntry = foundWikiBuildingInfo.MaintenanceInfos.FirstOrDefault(x => x.Unit.Name.Equals("Workforce Jornaleros", StringComparison.OrdinalIgnoreCase));
                if (foundJornalerosEntry != null)
                {
                    jornaleros += (foundJornalerosEntry.Value * buildingCount);
                }

                //get obreros
                var foundObrerosEntry = foundWikiBuildingInfo.MaintenanceInfos.FirstOrDefault(x => x.Unit.Name.Equals("Workforce Obreros", StringComparison.OrdinalIgnoreCase));
                if (foundObrerosEntry != null)
                {
                    obreros += (foundObrerosEntry.Value * buildingCount);
                }

                //get explorers
                var foundExplorersEntry = foundWikiBuildingInfo.MaintenanceInfos.FirstOrDefault(x => x.Unit.Name.Equals("Workforce Explorers", StringComparison.OrdinalIgnoreCase));
                if (foundExplorersEntry != null)
                {
                    explorers += (foundExplorersEntry.Value * buildingCount);
                }

                //get technicians
                var foundTechniciansEntry = foundWikiBuildingInfo.MaintenanceInfos.FirstOrDefault(x => x.Unit.Name.Equals("Workforce Technicians", StringComparison.OrdinalIgnoreCase));
                if (foundTechniciansEntry != null)
                {
                    technicians += (foundTechniciansEntry.Value * buildingCount);
                }
            }

            //add info to template
            exportString.Append(TEMPLATE_LINE_START).Append(HEADER_FARMERS_WORKFORCE).Append(TEMPLATE_ENTRY_DELIMITER).AppendLine(farmers != 0 ? farmers.ToString("0") : string.Empty)
            .Append(TEMPLATE_LINE_START).Append(HEADER_WORKERS_WORKFORCE).Append(TEMPLATE_ENTRY_DELIMITER).AppendLine(workers != 0 ? workers.ToString("0") : string.Empty)
            .Append(TEMPLATE_LINE_START).Append(HEADER_ARTISANS_WORKFORCE).Append(TEMPLATE_ENTRY_DELIMITER).AppendLine(artisans != 0 ? artisans.ToString("0") : string.Empty)
            .Append(TEMPLATE_LINE_START).Append(HEADER_ENGINEERS_WORKFORCE).Append(TEMPLATE_ENTRY_DELIMITER).AppendLine(engineers != 0 ? engineers.ToString("0") : string.Empty)
            .Append(TEMPLATE_LINE_START).Append(HEADER_JORNALEROS_WORKFORCE).Append(TEMPLATE_ENTRY_DELIMITER).AppendLine(jornaleros != 0 ? jornaleros.ToString("0") : string.Empty)
            .Append(TEMPLATE_LINE_START).Append(HEADER_OBREROS_WORKFORCE).Append(TEMPLATE_ENTRY_DELIMITER).AppendLine(obreros != 0 ? obreros.ToString("0") : string.Empty)
            .Append(TEMPLATE_LINE_START).Append(HEADER_OBREROS_WORKFORCE).Append(TEMPLATE_ENTRY_DELIMITER).AppendLine(obreros != 0 ? obreros.ToString("0") : string.Empty)
            .Append(TEMPLATE_LINE_START).Append(HEADER_EXPLORERS_WORKFORCE).Append(TEMPLATE_ENTRY_DELIMITER).AppendLine(explorers != 0 ? explorers.ToString("0") : string.Empty)
            .Append(TEMPLATE_LINE_START).Append(HEADER_TECHNICIANS_WORKFORCE).Append(TEMPLATE_ENTRY_DELIMITER).AppendLine(technicians != 0 ? technicians.ToString("0") : string.Empty);

            return(exportString);
        }
        private StringBuilder addConstructionInfo(StringBuilder exportString, List <AnnoObject> placedObjects, BuildingPresets buildingPresets, WikiBuildingInfoPresets wikiBuildingInfoPresets)
        {
            double credits            = 0;
            double timber             = 0;
            double bricks             = 0;
            double steelBeams         = 0;
            double windows            = 0;
            double reinforcedConcrete = 0;

            var groupedBuildings = placedObjects.Where(x => !x.Road && !string.IsNullOrWhiteSpace(x.Identifier) && !x.Identifier.Equals("Unknown Object", StringComparison.OrdinalIgnoreCase)).GroupBy(x => x.Identifier);

            foreach (var curGroup in groupedBuildings)
            {
                var buildingIdentifier = curGroup.Key;
                var buildingCount      = curGroup.Count();

                var foundWikiBuildingInfo = getWikiBuildingInfo(buildingIdentifier, buildingPresets, wikiBuildingInfoPresets);
                if (foundWikiBuildingInfo == null || foundWikiBuildingInfo.ConstructionInfos.Count == 0)
                {
                    //no info found -> skip
                    logger.Trace($"found no wiki info for identifier: {buildingIdentifier}");
                    continue;
                }

                //get credits
                var foundCreditsEntry = foundWikiBuildingInfo.ConstructionInfos.FirstOrDefault(x => x.Unit.Name.Equals("Credits", StringComparison.OrdinalIgnoreCase));
                if (foundCreditsEntry != null)
                {
                    credits += (foundCreditsEntry.Value * buildingCount);
                }

                //get timber
                var foundTimberEntry = foundWikiBuildingInfo.ConstructionInfos.FirstOrDefault(x => x.Unit.Name.Equals("Timber", StringComparison.OrdinalIgnoreCase));
                if (foundTimberEntry != null)
                {
                    timber += (foundTimberEntry.Value * buildingCount);
                }

                //get bricks
                var foundBricksEntry = foundWikiBuildingInfo.ConstructionInfos.FirstOrDefault(x => x.Unit.Name.Equals("Bricks", StringComparison.OrdinalIgnoreCase));
                if (foundBricksEntry != null)
                {
                    bricks += (foundBricksEntry.Value * buildingCount);
                }

                //get steel beams
                var foundSteelBeamsEntry = foundWikiBuildingInfo.ConstructionInfos.FirstOrDefault(x => x.Unit.Name.Equals("Steel Beams", StringComparison.OrdinalIgnoreCase));
                if (foundSteelBeamsEntry != null)
                {
                    steelBeams += (foundSteelBeamsEntry.Value * buildingCount);
                }

                //get windows
                var foundWindowsEntry = foundWikiBuildingInfo.ConstructionInfos.FirstOrDefault(x => x.Unit.Name.Equals("Windows", StringComparison.OrdinalIgnoreCase));
                if (foundWindowsEntry != null)
                {
                    windows += (foundWindowsEntry.Value * buildingCount);
                }

                //get reinforced concrete
                var foundReinforcedConcreteEntry = foundWikiBuildingInfo.ConstructionInfos.FirstOrDefault(x => x.Unit.Name.Equals("Reinforced Concrete", StringComparison.OrdinalIgnoreCase));
                if (foundReinforcedConcreteEntry != null)
                {
                    reinforcedConcrete += (foundReinforcedConcreteEntry.Value * buildingCount);
                }
            }

            //add info to template
            exportString.Append(TEMPLATE_LINE_START).Append(HEADER_CREDITS).Append(TEMPLATE_ENTRY_DELIMITER).AppendLine(credits > 0 ? credits.ToString("0") : string.Empty)
            .Append(TEMPLATE_LINE_START).Append(HEADER_TIMBER).Append(TEMPLATE_ENTRY_DELIMITER).AppendLine(timber > 0 ? timber.ToString("0") : string.Empty)
            .Append(TEMPLATE_LINE_START).Append(HEADER_BRICKS).Append(TEMPLATE_ENTRY_DELIMITER).AppendLine(bricks > 0 ? bricks.ToString("0") : string.Empty)
            .Append(TEMPLATE_LINE_START).Append(HEADER_STEEL_BEAMS).Append(TEMPLATE_ENTRY_DELIMITER).AppendLine(steelBeams > 0 ? steelBeams.ToString("0") : string.Empty)
            .Append(TEMPLATE_LINE_START).Append(HEADER_WINDOWS).Append(TEMPLATE_ENTRY_DELIMITER).AppendLine(windows > 0 ? windows.ToString("0") : string.Empty)
            .Append(TEMPLATE_LINE_START).Append(HEADER_REINFORCED_CONCRETE).Append(TEMPLATE_ENTRY_DELIMITER).AppendLine(reinforcedConcrete > 0 ? reinforcedConcrete.ToString("0") : string.Empty);

            return(exportString);
        }
        private StringBuilder addBalance(StringBuilder exportString, List <AnnoObject> placedObjects, BuildingPresets buildingPresets, WikiBuildingInfoPresets wikiBuildingInfoPresets)
        {
            double balance = 0;

            var groupedBuildings = placedObjects.Where(x => !x.Road && !string.IsNullOrWhiteSpace(x.Identifier) && !x.Identifier.Equals("Unknown Object", StringComparison.OrdinalIgnoreCase)).GroupBy(x => x.Identifier);

            foreach (var curGroup in groupedBuildings)
            {
                var buildingIdentifier = curGroup.Key;
                var buildingCount      = curGroup.Count();

                var foundWikiBuildingInfo = getWikiBuildingInfo(buildingIdentifier, buildingPresets, wikiBuildingInfoPresets);
                if (foundWikiBuildingInfo == null || foundWikiBuildingInfo.MaintenanceInfos.Count == 0)
                {
                    //no info found -> skip
                    continue;
                }

                //get balance
                var foundBalanceEntry = foundWikiBuildingInfo.MaintenanceInfos.FirstOrDefault(x => x.Unit.Name.Equals("Balance", StringComparison.OrdinalIgnoreCase));
                if (foundBalanceEntry != null)
                {
                    balance = balance + (foundBalanceEntry.Value * buildingCount);
                }
            }

            exportString.Append(TEMPLATE_LINE_START).Append(HEADER_BALANCE).Append(TEMPLATE_ENTRY_DELIMITER).AppendLine(balance != 0 ? balance.ToString("0") : string.Empty);

            return(exportString);
        }
        private StringBuilder addProductionInfo(StringBuilder exportString, List <AnnoObject> placedObjects, BuildingPresets buildingPresets, WikiBuildingInfoPresets wikiBuildingInfoPresets)
        {
            var buildingCounter = 0;

            var supportedBuildings = placedObjects.Where(x => !x.Road && !string.IsNullOrWhiteSpace(x.Identifier) && !x.Identifier.Equals("Unknown Object", StringComparison.OrdinalIgnoreCase)).ToList();

            //1. get all buildings that need input
            //2. gat all buildings that have an endproduct
            //3. foreach building with input -> remove it from list of buildings with an endproduct
            //4. foreach building with an endproduct -> add it to the template

            //1. get all buildings that need input
            var buildingsWithInputProduct = new Dictionary <AnnoObject, List <InputProduct> >();

            foreach (var curBuilding in supportedBuildings)
            {
                var foundWikiBuildingInfo = getWikiBuildingInfo(curBuilding.Identifier, buildingPresets, wikiBuildingInfoPresets);
                if (foundWikiBuildingInfo == null ||
                    foundWikiBuildingInfo.ProductionInfos == null ||
                    foundWikiBuildingInfo.ProductionInfos.InputProducts.Count == 0)
                {
                    //no Production building or no info found -> skip
                    continue;
                }

                foreach (var curInput in foundWikiBuildingInfo.ProductionInfos.InputProducts)
                {
                    if (!buildingsWithInputProduct.ContainsKey(curBuilding))
                    {
                        buildingsWithInputProduct.Add(curBuilding, new List <InputProduct> {
                            curInput
                        });
                    }
                    else
                    {
                        buildingsWithInputProduct[curBuilding].Add(curInput);
                    }
                }
            }

            //2. gat all buildings that have an endproduct
            var buildingsWithEndProduct = new Dictionary <AnnoObject, EndProduct>();

            foreach (var curBuilding in supportedBuildings)
            {
                var foundWikiBuildingInfo = getWikiBuildingInfo(curBuilding.Identifier, buildingPresets, wikiBuildingInfoPresets);
                if (foundWikiBuildingInfo == null ||
                    foundWikiBuildingInfo.ProductionInfos == null ||
                    foundWikiBuildingInfo.ProductionInfos.EndProduct == null)
                {
                    //no Production building or no info found -> skip
                    continue;
                }

                buildingsWithEndProduct.Add(curBuilding, foundWikiBuildingInfo.ProductionInfos.EndProduct);
            }

            //3. foreach building with input -> remove it from list of buildings with an endproduct
            foreach (var curBuildingWithInputProduct in buildingsWithInputProduct)
            {
                foreach (var curInputProduct in curBuildingWithInputProduct.Value)
                {
                    var foundBuildingWithSameEndProduct = buildingsWithEndProduct.FirstOrDefault(x => string.Equals(x.Value.Icon, curInputProduct.Icon, StringComparison.OrdinalIgnoreCase)).Key;
                    if (foundBuildingWithSameEndProduct != null)
                    {
                        buildingsWithEndProduct.Remove(foundBuildingWithSameEndProduct);
                    }
                }
            }

            //4. foreach building with an endproduct -> add it to the template
            var groupedBuildingsWithEndProduct = buildingsWithEndProduct.GroupBy(x => x.Key.Identifier).ToList();

            foreach (var curGroup in groupedBuildingsWithEndProduct)
            {
                var buildingIdentifier = curGroup.Key;
                var buildingCount      = curGroup.Count();

                var foundWikiBuildingInfo = getWikiBuildingInfo(buildingIdentifier, buildingPresets, wikiBuildingInfoPresets);
                if (foundWikiBuildingInfo == null)
                {
                    //no Production building or no info found -> skip
                    continue;
                }

                if (buildingCount == 1 && foundWikiBuildingInfo.ProductionInfos.EndProduct.Amount <= 1)
                {
                    continue;
                }

                //add info about end product
                ++buildingCounter;

                var productionAmount = foundWikiBuildingInfo.ProductionInfos.EndProduct.Amount * buildingCount;
                var endProductIcon   = Path.GetFileNameWithoutExtension(foundWikiBuildingInfo.ProductionInfos.EndProduct.Icon);

                exportString.Append(TEMPLATE_LINE_START)
                .Append(HEADER_PRODUCTION)
                .Append(buildingCounter)
                .Append(HEADER_PRODUCTION_TYPE)
                .Append(TEMPLATE_ENTRY_DELIMITER)
                .AppendLine(endProductIcon);

                exportString.Append(TEMPLATE_LINE_START)
                .Append(HEADER_PRODUCTION)
                .Append(buildingCounter)
                .Append(HEADER_PRODUCTION_PER_MINUTE)
                .Append(TEMPLATE_ENTRY_DELIMITER)
                .AppendLine(productionAmount.ToString("0.##"));
            }

            return(exportString);
        }
        private string getBuildingName(string buildingIdentifier, BuildingPresets buildingPresets, WikiBuildingInfoPresets wikiBuildingInfoPresets)
        {
            var result = MAPPING_NOT_FOUND + buildingIdentifier;

            var foundFandomNameMapping = FandomeNamePresets.Names.FirstOrDefault(x => x.Identifiers.Contains(buildingIdentifier));

            if (foundFandomNameMapping != null)
            {
                result = foundFandomNameMapping.FandomName;
            }
            else
            {
                //try to get by wiki info
                var foundWikiBuildingInfo = getWikiBuildingInfo(buildingIdentifier, buildingPresets, wikiBuildingInfoPresets);
                if (!string.IsNullOrWhiteSpace(foundWikiBuildingInfo?.Icon))
                {
                    result = Path.GetFileNameWithoutExtension(foundWikiBuildingInfo.Icon);
                }
            }

            return(result);
        }
        private StringBuilder addBuildingInfo(StringBuilder exportString, List <AnnoObject> placedObjects, BuildingPresets buildingPresets, WikiBuildingInfoPresets wikiBuildingInfoPresets)
        {
            var buildingCounter = 0;

            var groupedBuildings = placedObjects.Where(x => !x.Road && !string.IsNullOrWhiteSpace(x.Identifier) && !x.Identifier.Equals("Unknown Object", StringComparison.OrdinalIgnoreCase))
                                   .GroupBy(x => x.Identifier)
                                   .OrderBy(x => x.Count());

            foreach (var curGroup in groupedBuildings)
            {
                ++buildingCounter;

                exportString.Append(TEMPLATE_LINE_START)
                .Append(HEADER_BUILDING)
                .Append(buildingCounter)
                .Append(HEADER_BUILDING_TYPE)
                .Append(TEMPLATE_ENTRY_DELIMITER)
                .AppendLine(getBuildingName(curGroup.Key, buildingPresets, wikiBuildingInfoPresets));

                exportString.Append(TEMPLATE_LINE_START)
                .Append(HEADER_BUILDING)
                .Append(buildingCounter)
                .Append(HEADER_BUILDING_AMOUNT)
                .Append(TEMPLATE_ENTRY_DELIMITER)
                .AppendLine(curGroup.Count().ToString());
            }

            return(exportString);
        }
Example #14
0
        private void SaveCompleteInfos(WikiBuildingInfoPresets wikiBuildingInfoList)
        {
            Console.WriteLine("start fetching building details");

            if (!Directory.Exists(PathToDetailsFolder))
            {
                Directory.CreateDirectory(PathToDetailsFolder);
            }

            var existingMissingInfos = new List <string>();

            if (File.Exists(Path.Combine(PathToDetailsFolder, FILENAME_MISSING_INFOS)))
            {
                existingMissingInfos.AddRange(File.ReadAllLines(Path.Combine(PathToDetailsFolder, FILENAME_MISSING_INFOS), Encoding.UTF8));
            }

            var missingInfos = new List <string>();

            Stopwatch sw = new Stopwatch();

            sw.Start();

            Parallel.ForEach(wikiBuildingInfoList.Infos,
                             new ParallelOptions {
                MaxDegreeOfParallelism = Environment.ProcessorCount
            },
                             curBuilding =>
            {
                var pageName = curBuilding.Name.Replace(" ", "_");

                //only download when not present and not forced to download
                var fileName            = GetCleanedFilename(pageName);
                var destinationFilePath = Path.Combine(PathToDetailsFolder, $"{fileName}{FILE_ENDING_WIKITEXT}");
                if (!Program.ForceDownload && (File.Exists(destinationFilePath) || existingMissingInfos.Contains(curBuilding.Name)))
                {
                    return;
                }

                var provider       = new WikiTextProvider();
                var providerResult = provider.GetWikiTextAsync(pageName).GetAwaiter().GetResult();

                if (!string.IsNullOrWhiteSpace(providerResult.WikiText))
                {
                    providerResult.WikiText = GetLineBreakAlignedWikiText(providerResult.WikiText);
                    //align infobox name
                    providerResult.WikiText = providerResult.WikiText.Replace("{{Infobox_Buildings", "{{Infobox Buildings");
                    File.WriteAllText(destinationFilePath, providerResult.WikiText, Encoding.UTF8);
                    File.AppendAllLines(destinationFilePath, new List <string>
                    {
                        Environment.NewLine,
                        $"{REVISION_HEADER_ID}{REVISION_SEPARATOR}{providerResult.RevisionId}",
                        $"{REVISION_HEADER_DATE}{REVISION_SEPARATOR}{providerResult.EditDate.ToString("o")}"
                    }, Encoding.UTF8);
                }
                else
                {
                    missingInfos.Add(curBuilding.Name);
                }
            });

            if (missingInfos.Count > 0)
            {
                File.WriteAllLines(Path.Combine(PathToDetailsFolder, FILENAME_MISSING_INFOS), missingInfos.Distinct().OrderBy(x => x), Encoding.UTF8);
            }

            sw.Stop();
            var message = $"finished fetching building details (took {sw.ElapsedMilliseconds} ms)";

            logger.Trace(message);
            Console.WriteLine(message);
        }
Example #15
0
        private WikiBuildingInfoPresets GetUpdatedWikiBuildingInfoList(WikiBuildingInfoPresets wikiBuildingInfoList)
        {
            Console.WriteLine("start parsing infoboxes");

            Stopwatch sw = new Stopwatch();

            sw.Start();

            try
            {
                var infoboxParser = new InfoboxParser.InfoboxParser(_commons);

                foreach (var curFile in Directory.EnumerateFiles(PathToExtractedInfoboxesFolder, $"*{FILE_ENDING_INFOBOX}", SearchOption.TopDirectoryOnly))
                {
                    var fileContent = File.ReadAllText(curFile, Encoding.UTF8);
                    var infoboxes   = infoboxParser.GetInfobox(fileContent);

                    if (infoboxes.Count == 1)
                    {
                        var parsedInfobox = infoboxes[0];

                        WikiBuildingInfo foundWikiBuildingInfo;
                        if (parsedInfobox.Region == WorldRegion.Unknown)
                        {
                            foundWikiBuildingInfo = wikiBuildingInfoList.Infos.FirstOrDefault(x => x.Name.Equals(parsedInfobox.Name, StringComparison.OrdinalIgnoreCase));
                        }
                        else
                        {
                            throw new Exception("expected unknown region");
                        }

                        if (foundWikiBuildingInfo == null)
                        {
                            throw new Exception("no WikiBuildingInfo found!");
                        }

                        var buildingNameForUrl = foundWikiBuildingInfo.Name.Replace(" ", "_");

                        foundWikiBuildingInfo.Type            = parsedInfobox.Type;
                        foundWikiBuildingInfo.ProductionInfos = parsedInfobox.ProductionInfos;
                        foundWikiBuildingInfo.SupplyInfos     = parsedInfobox.SupplyInfos;
                        foundWikiBuildingInfo.UnlockInfos     = parsedInfobox.UnlockInfos;

                        //check Url for "World's Fair" | correct: https://anno1800.fandom.com/wiki/World%27s_Fair
                        if (buildingNameForUrl.Contains("World's_Fair"))
                        {
                            buildingNameForUrl = "World%27s_Fair";
                        }

                        //(maybe) TODO check Url for "Bombín Weaver" | correct: https://anno1800.fandom.com/wiki/Bomb%C2%AD%C3%ADn_Weaver
                        //contains unicode char (https://www.utf8-chartable.de/unicode-utf8-table.pl):  U+00AD	­	c2 ad	SOFT HYPHEN

                        foundWikiBuildingInfo.Url = new Uri("https://anno1800.fandom.com/wiki/" + buildingNameForUrl);

                        var revisionInfo = GetRevisionInfo(foundWikiBuildingInfo);
                        if (revisionInfo != null)
                        {
                            foundWikiBuildingInfo.RevisionId   = revisionInfo.Item1;
                            foundWikiBuildingInfo.RevisionDate = revisionInfo.Item2;
                        }
                    }
                    else if (infoboxes.Count > 1)
                    {
                        foreach (var curInfobox in infoboxes)
                        {
                            //multiple entries possible e.g. "Police Station" or "Museum"
                            var foundWikiBuildingInfo = wikiBuildingInfoList.Infos.FirstOrDefault(x => x.Name.Equals(curInfobox.Name, StringComparison.OrdinalIgnoreCase) && x.Region == curInfobox.Region);
                            if (foundWikiBuildingInfo == null)
                            {
                                throw new Exception("no WikiBuildingInfo found!");
                            }

                            var buildingNameForUrl = foundWikiBuildingInfo.Name.Replace(" ", "_");

                            foundWikiBuildingInfo.Type            = curInfobox.Type;
                            foundWikiBuildingInfo.ProductionInfos = curInfobox.ProductionInfos;
                            foundWikiBuildingInfo.SupplyInfos     = curInfobox.SupplyInfos;
                            foundWikiBuildingInfo.UnlockInfos     = curInfobox.UnlockInfos;
                            foundWikiBuildingInfo.Url             = new Uri("https://anno1800.fandom.com/wiki/" + buildingNameForUrl);

                            var revisionInfo = GetRevisionInfo(foundWikiBuildingInfo);
                            if (revisionInfo != null)
                            {
                                foundWikiBuildingInfo.RevisionId   = revisionInfo.Item1;
                                foundWikiBuildingInfo.RevisionDate = revisionInfo.Item2;
                            }
                        }
                    }
                    else
                    {
                        //got no infoboxes
                    }
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex, $"error parsing infoboxes");
                Console.WriteLine(ex);
            }

            sw.Stop();
            Console.WriteLine($"finished parsing infoboxes (took {sw.ElapsedMilliseconds} ms)");

            return(wikiBuildingInfoList);
        }
Example #16
0
        private WikiBuildingInfoPresets GetUpdatedWikiBuildingInfoList(WikiBuildingInfoPresets wikiBuildingInfoList)
        {
            Console.WriteLine("start parsing infoboxes");

            Stopwatch sw = new Stopwatch();

            sw.Start();

            try
            {
                foreach (var curFile in Directory.EnumerateFiles(PathToExtractedInfoboxesFolder, $"*{FILE_ENDING_INFOBOX}", SearchOption.TopDirectoryOnly))
                {
                    var fileContent = File.ReadAllText(curFile, Encoding.UTF8);
                    var infoboxes   = _infoboxParser.GetInfobox(fileContent);

                    if (infoboxes.Count == 1)
                    {
                        var parsedInfobox = infoboxes[0];

                        WikiBuildingInfo foundWikiBuildingInfo;
                        if (parsedInfobox.Region == WorldRegion.Unknown)
                        {
                            foundWikiBuildingInfo = wikiBuildingInfoList.Infos.FirstOrDefault(x => x.Name.Equals(parsedInfobox.Name, StringComparison.OrdinalIgnoreCase));
                        }
                        else
                        {
                            throw new Exception("expected unknown region");
                        }

                        if (foundWikiBuildingInfo is null)
                        {
                            //if (parsedInfobox?.Name.Contains("Road") == true)
                            //{
                            foundWikiBuildingInfo = wikiBuildingInfoList.Infos.FirstOrDefault(x => x.Name.EndsWith(parsedInfobox.Name));
                            if (foundWikiBuildingInfo is null)
                            {
                                var wikiBuildingInfo = CreateNewBuildingInfo(parsedInfobox);
                                wikiBuildingInfoList.Infos.Add(wikiBuildingInfo);
                                continue;

                                //var exception = new Exception("No WikiBuildingInfo found!");
                                //exception.Data.Add(nameof(curFile), curFile);
                                //exception.Data.Add($"{nameof(parsedInfobox)}.{nameof(parsedInfobox.Name)}", parsedInfobox.Name);

                                //logger.Error(exception);
                                //continue;

                                //throw exception;
                                //is page with multiple infoboxes -> not supported yet
                                //continue;
                            }
                            //}
                            else
                            {
                            }
                        }

                        foundWikiBuildingInfo = CopyInfoboxToBuildingInfo(parsedInfobox, foundWikiBuildingInfo);
                    }
                    else if (infoboxes.Count > 1)
                    {
                        foreach (var curInfobox in infoboxes)
                        {
                            //multiple entries possible e.g. "Police Station" or "Museum"
                            var foundWikiBuildingInfo = wikiBuildingInfoList.Infos.FirstOrDefault(x => x.Name.Equals(curInfobox.Name, StringComparison.OrdinalIgnoreCase) && x.Region == curInfobox.Region);
                            if (foundWikiBuildingInfo is null)
                            {
                                //if (curInfobox?.Name.Contains("Road") == true)
                                //{
                                foundWikiBuildingInfo = wikiBuildingInfoList.Infos.FirstOrDefault(x => x.Name.EndsWith(curInfobox.Name));
                                if (foundWikiBuildingInfo is null)
                                {
                                    var exception = new Exception("No WikiBuildingInfo found!");
                                    exception.Data.Add(nameof(curFile), curFile);
                                    exception.Data.Add($"{nameof(curInfobox)}.{nameof(curInfobox.Name)}", curInfobox.Name);

                                    logger.Error(exception);
                                    continue;

                                    //throw exception;

                                    //is page with multiple infoboxes -> not supported yet
                                    //continue;
                                }
                                //}
                                else
                                {
                                }
                            }

                            foundWikiBuildingInfo = CopyInfoboxToBuildingInfo(curInfobox, foundWikiBuildingInfo);
                        }
                    }
                    else
                    {
                        //got no infoboxes
                    }
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex, $"error parsing infoboxes");
                Console.WriteLine(ex);
            }

            sw.Stop();
            Console.WriteLine($"finished parsing infoboxes (took {sw.ElapsedMilliseconds} ms)");

            return(wikiBuildingInfoList);
        }