/*********************************************************************************************** * Build / 2014-08-01 / Wethospu * * * * Generates the content. * * * ***********************************************************************************************/ static bool Build() { Console.WriteLine("Press enter to start."); Console.WriteLine("Press 1 to validate urls and update ValidatedUrls.txt."); Console.WriteLine("Press 2 to download used images/videos and update MediaSizes.txt."); Console.WriteLine("Press 3 to do both."); Console.WriteLine("Press 4 for optimized release generation."); Console.WriteLine("Press esc to quit."); var row = Console.CursorTop; var key = Console.ReadKey(); Helper.ClearConsoleLine(row); if (key.Key == ConsoleKey.Escape) return false; Console.WriteLine(""); Constants.ValidateUrls = key.Key == ConsoleKey.D1 || key.Key == ConsoleKey.D3; Constants.DownloadData = key.Key == ConsoleKey.D2 || key.Key == ConsoleKey.D3; Constants.Initialize(key.Key == ConsoleKey.D4); CheckInternetSettings(); LoadSettings(); Dictionary<string, EnemyAttributes> enemyAttributes = new Dictionary<string, EnemyAttributes>(); if (File.Exists(Constants.DataRaw + "data.json")) { using (StreamReader r = new StreamReader(Constants.DataRaw + "data.json")) { string json = r.ReadToEnd(); enemyAttributes = JsonConvert.DeserializeObject<Dictionary<string, EnemyAttributes>>(json); } } else Helper.ShowWarningMessage("File " + Constants.DataRaw + "data.json" + " doesn't exist. No enemy data loaded."); Constants.UniqueIndexCounter = 0; string[] toGenerate = { "ac", "cm", "ta", "se", "cof", "hotw", "coe", "arah", "fotm" }; // File containing all enemies and encounters for searching. // Name|Rank|Category|Dungeon|Path // Some special values must also be translated. GeneratePage("General"); var indexFile = new StringBuilder(); indexFile.Append(Constants.InitialdataHtml); indexFile.Append(Constants.InitialDataIndex); // Generate enemies with help of datamined information. / 2015-10-05 / Wethospu var enemyData = EnemyGenerator.GenerateEnemies(enemyAttributes); var dungeonData = new DataCollector(); foreach (var dungeon in toGenerate) GenerateDungeon(dungeon, indexFile, dungeonData, enemyData); EnemyGenerator.GenerateFile(enemyData, indexFile, dungeonData); var fileName = Constants.DataOutput + Constants.DataEnemyResult + "indexfile.htm"; if (!Directory.Exists(Constants.DataOutput + Constants.DataEnemyResult)) { Helper.ShowWarning("Directory " + Constants.DataOutput + Constants.DataEnemyResult + " doesn't exist."); return true; } File.WriteAllText(fileName, indexFile.ToString()); OtherGenerator.GenerateOthers(dungeonData); Console.WriteLine(""); return true; }
/// <summary> /// Main function to generate everything. /// </summary> public static void GenerateOthers(DataCollector dungeonData) { Console.WriteLine("Generating pages"); MergeFiles(); // Generate main page to dynamically create the dungeon listing. GenerateMainPage(dungeonData.GenerateInstanceData()); // Generate about page to dynamically update date of the last update. ApplyDate(Constants.DataOtherRaw + "pages\\about.htm"); // Generate search page filters based on actual enemies. ApplyData(Constants.DataOtherRaw + "pages\\search.htm", dungeonData); // Generate includes based on release mode. ApplyIncludes(Constants.DataOtherRaw + "index.php"); }
/*********************************************************************************************** * ApplyData / 2015-08-14 / Wethospu * * * * Replaces ID_CATEGORIES, ID_PATHS, ID_TAGS and ID_RACES with relevant html. * * * ***********************************************************************************************/ private static void ApplyData(string file, DataCollector dungeonData) { var fileName = Constants.DataOutput + file.Replace(Constants.DataOtherRaw, ""); var dirName = Path.GetDirectoryName(fileName); if (dirName != null) Directory.CreateDirectory(dirName); var lines = File.ReadAllLines(file, Constants.Encoding); Helper.CurrentFile = file; var toSave = new StringBuilder(); toSave.Append(Constants.InitialdataHtml); for (var row = 0; row < lines.Length; row++) { var line = lines[row]; if (Constants.IsRelease) line = line.Trim(new char[] { '\t', ' ' }); // Ignore comments on release mode. / 2015-10-10 / Wethospu if (Constants.IsRelease && line.StartsWith("//")) continue; // Ignore empty lines. if (line == "") continue; Helper.InitializeWarningSystem(row + 1, line); // Ignore whitespace. if (string.IsNullOrWhiteSpace(line)) continue; if (line.Contains("ID_PATHS")) line = line.Replace("ID_PATHS", dungeonData.GenerateDungeonHtml()); if (line.Contains("ID_RACES")) line = line.Replace("ID_RACES", dungeonData.GenerateRaceHtml()); if (line.Contains("ID_RANKS")) line = line.Replace("ID_RANKS", dungeonData.GenerateRankHtml()); if (line.Contains("ID_TAGS")) line = line.Replace("ID_TAGS", dungeonData.GenerateTagHtml()); if (line.Contains("ID_EFFECT_TAGS")) line = line.Replace("ID_EFFECT_TAGS", dungeonData.GenerateEffectTagHtml()); toSave.Append(line).Append(Constants.ForcedLineEnding); } // Save file. File.WriteAllText(fileName, toSave.ToString()); }
/// <summary> /// Replaces strings ID_CATEGORIES, ID_PATHS, ID_TAGS and ID_RACES with relevant html. /// </summary> private static void ApplyData(string file, DataCollector dungeonData) { var fileName = Constants.DataOutput + file.Replace(Constants.DataOtherRaw, ""); var dirName = Path.GetDirectoryName(fileName); if (dirName != null) Directory.CreateDirectory(dirName); var lines = File.ReadAllLines(file, Constants.Encoding); ErrorHandler.CurrentFile = file; var toSave = new StringBuilder(); toSave.Append(Constants.InitialdataHtml); for (var row = 0; row < lines.Length; row++) { var line = lines[row]; if (Constants.IsRelease) line = line.Trim(new char[] { '\t', ' ' }); // Ignore comments on release mode to reduce file size. if (Constants.IsRelease && line.StartsWith("//")) continue; // Ignore empty lines to reduce file size. if (line == "") continue; ErrorHandler.InitializeWarningSystem(row + 1, line); // Ignore whitespace to reduce file size. if (string.IsNullOrWhiteSpace(line)) continue; line = line.Replace("ID_PATHS", dungeonData.GenerateInstanceHtml()); line = line.Replace("ID_RACES", dungeonData.GenerateRaceHtml()); line = line.Replace("ID_RANKS", dungeonData.GenerateRankHtml()); line = line.Replace("ID_TAGS", dungeonData.GenerateTagHtml()); line = line.Replace("ID_EFFECT_TAGS", dungeonData.GenerateEffectTagHtml()); line = line.Replace("PATH_ICON", Constants.WebsiteIconLocation); line = line.Replace("PATH_MEDIA", Constants.WebsiteMediaLocation); line = line.Replace("PATH_THUMB_BIG", Constants.WebsiteThumbBigLocation); line = line.Replace("PATH_THUMB_SMALL", Constants.WebsiteThumbSmallLocation); toSave.Append(line).Append(Constants.ForcedLineEnding); } // Save file. File.WriteAllText(fileName, toSave.ToString()); }
/// <summary> /// Generates html files for the enemies. /// </summary> public static void CreateFiles(List<Enemy> enemies, DataCollector dungeonData) { enemies = CreateLinks(enemies); // Separate enemies (100 enemies per file) to reduce the initial loading time on the website. var enemyFile = new StringBuilder(); enemyFile.Append(Constants.InitialdataHtml).Append(Constants.LineEnding); for (var i = 0; i < enemies.Count; i++) { enemyFile.Append(enemies[i].ToHtml()); if ((i + 1) % 100 == 0 || i == enemies.Count - 1) { var fileName = Constants.DataOutput + Constants.DataEnemyResult + "enemies" + (i/100) + ".htm"; var dirName = Path.GetDirectoryName(fileName); if (dirName != null) Directory.CreateDirectory(dirName); try { File.WriteAllText(fileName, enemyFile.ToString()); } catch (UnauthorizedAccessException) { ErrorHandler.ShowWarningMessage("File " + fileName + " in use."); } enemyFile = new StringBuilder(); enemyFile.Append(Constants.InitialdataHtml).Append(Constants.LineEnding); } } for (var i = 0; i < enemies.Count; i++) { // Add enemy info to the data collector for an advanced search capablities. if (dungeonData != null) { dungeonData.AddRace(enemies[i].Attributes.Family.GetDisplay()); dungeonData.AddRank(enemies[i].Rank); foreach (var tag in enemies[i].Tags) dungeonData.AddTag(tag); } } }
/*********************************************************************************************** * HandleIndexFile / 2014-08-01 / Wethospu * * * * Adds generated enemies to the index file. * * * * enemies: Generated enemies. * * dungeon: Current dungeon. * * indexFile: Output. * * * ***********************************************************************************************/ private static void HandleIndexFile(IReadOnlyList<Enemy> enemies, StringBuilder indexFile, DataCollector dungeonData) { if (indexFile == null) return; foreach (var enemy in enemies) { indexFile.Append(enemy.Name).Append("|").Append(Helper.Simplify(enemy.Name)).Append("|").Append(enemy.Rank); indexFile.Append("|").Append(enemy.Attributes.Family.GetInternal()).Append("|").Append(string.Join(":", enemy.Paths)); // Store index so that the enemy can be found faster when searching. indexFile.Append("|").Append(enemy.Index); // Generate tag string. / 2015-07-18 / Wethospu var builder = new StringBuilder(); foreach (var tag in enemy.Tags) builder.Append(dungeonData.ConvertTag(tag)); indexFile.Append("|").Append(builder.ToString()); indexFile.Append(Constants.ForcedLineEnding); } }
// With over thousand enemies the website's search performance is an issue. /// <summary> /// Make the search faster by using a small indexfile which contains search data for every enemy. /// </summary> private static void GenerateSearchIndex(DataCollector dungeonData, List<Enemy> enemies) { var indexFile = new StringBuilder(); indexFile.Append(Constants.InitialdataHtml); indexFile.Append(Constants.InitialDataIndex); foreach (var enemy in enemies) { // TODO: Previous enemy name was used to find the enemy info. Now Index seems to be used so remove the name. indexFile.Append(enemy.Name).Append("|").Append(Helper.Simplify(enemy.Name)).Append("|").Append(enemy.Rank); indexFile.Append("|").Append(enemy.Attributes.Family.GetInternal()).Append("|").Append(string.Join(":", enemy.Paths)); indexFile.Append("|").Append(enemy.Index); // Compact tags take less space (especially important for search URLs). var builder = new StringBuilder(); foreach (var tag in enemy.Tags) builder.Append(dungeonData.GetShortTag(tag)); indexFile.Append("|").Append(builder.ToString()); indexFile.Append(Constants.ForcedLineEnding); } var directory = Constants.DataOutput + Constants.DataEnemyResult; if (Directory.Exists(directory)) File.WriteAllText(directory + "indexfile.htm", indexFile.ToString()); else ErrorHandler.ShowWarning("Directory " + directory + " doesn't exist."); }
/// <summary> /// Generates a single instance. /// </summary> private static InstanceData GenerateInstance(InstanceType type, string file, DataCollector dungeonData, List<Enemy> enemyData) { Console.WriteLine("File " + file); LinkGenerator.CurrentDungeon = file; var location = Constants.DataGuidesRaw; if (type == InstanceType.fractal) location = Constants.DataFractalsRaw; if (type == InstanceType.dungeon) location = Constants.DataDungeonsRaw; if (type == InstanceType.raid) location = Constants.DataRaidsRaw; var encounterData = EncounterGenerator.ReadInstance(location, file, enemyData); if (encounterData == null) return null; if (encounterData.Paths == null) return encounterData; if (type == InstanceType.dungeon) dungeonData.AddDungeon(file, encounterData.Paths); if (type == InstanceType.fractal) dungeonData.AddFractal(encounterData.Paths); if (type == InstanceType.raid) dungeonData.AddRaid(file, encounterData.Paths); return encounterData; }
/// <summary> /// Main generating function. Generates all data. /// </summary> private static void Build() { var enemyData = ReadEnemyDataminedData(); Constants.UniqueIndexCounter = 0; GeneratePage("General"); LinkGenerator.CurrentDungeon = Constants.EnemyMediaFolder; var enemies = EnemyGenerator.GenerateEnemies(enemyData); foreach (var scale in Constants.Instabilities) { foreach (var instability in scale) { instability.GenerateHtml(enemies); } } var instanceData = new DataCollector(); foreach (var dungeon in Directory.EnumerateFiles(Constants.DataDungeonsRaw).Select(Path.GetFileNameWithoutExtension)) { var encounterData = GenerateInstance(InstanceType.dungeon, dungeon, instanceData, enemies); if (encounterData != null) EncounterGenerator.CreateFiles(encounterData, enemies, encounterData.Paths); } // Gather fractals to merge their path information. var fractals = new List<InstanceData>(); foreach (var fractal in Directory.EnumerateFiles(Constants.DataFractalsRaw).Select(Path.GetFileNameWithoutExtension)) { var encounterData = GenerateInstance(InstanceType.fractal, fractal, instanceData, enemies); if (encounterData != null) fractals.Add(encounterData); } foreach (var fractal in fractals) { LinkGenerator.CurrentDungeon = fractal.Paths[0].Tag; EncounterGenerator.CreateFiles(fractal, enemies, instanceData.FractalPaths); } foreach (var raid in Directory.EnumerateFiles(Constants.DataRaidsRaw).Select(Path.GetFileNameWithoutExtension)) { var encounterData = GenerateInstance(InstanceType.raid, raid, instanceData, enemies); if (encounterData != null) EncounterGenerator.CreateFiles(encounterData, enemies, encounterData.Paths); } ErrorHandler.InitializeWarningSystem(-1, ""); EnemyGenerator.CreateFiles(enemies, instanceData); GenerateSearchIndex(instanceData, enemies); OtherGenerator.GenerateOthers(instanceData); Console.WriteLine(""); }
/*********************************************************************************************** * GenerateDungeon / 2014-08-01 / Wethospu * * * * Generates one dungeon. * * * * enemyAttributes: Datamined enemy attributes and other information. * * * ***********************************************************************************************/ static void GenerateDungeon(string dungeon, StringBuilder indexFile, DataCollector dungeonData, List<Enemy> enemyData) { Console.WriteLine("Dungeon " + dungeon.ToUpper()); LinkGenerator.CurrentDungeon = dungeon; // Read and generate data. / 2015-08-09 / Wethospu var encounterData = EncounterGenerator.GeneratePaths(dungeon, enemyData); if (encounterData == null) return; EncounterGenerator.GenerateFiles(encounterData.Paths, encounterData.Encounters, enemyData); if (encounterData.Paths == null) return; dungeonData.AddDungeon(dungeon, encounterData.Paths); }