Mercurial > repos > IBBoard.WarFoundry.API
view API/Exporters/WarFoundryHtmlExporter.cs @ 472:e6c93ceba119
Re #359: Add "only contained" attribute to unit types
* Make sure we add and remove from the parent unit appropriately
* Make sure that setting the unit's parent to null removes it from the parent
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Mon, 16 Apr 2012 20:14:23 +0100 |
parents | 6da9db4a9c23 |
children | 81f32062c9fa |
line wrap: on
line source
// This file (WarFoundryHtmlExporter.cs) is a part of the IBBoard.WarFoundry.API project and is copyright 2009 IBBoard // // The file and the library/program it is in are licensed and distributed, without warranty, under the GNU Affero GPL license, either version 3 of the License or (at your option) any later version. Please see COPYING for more information and the full license. using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Xml; using System.Xml.Schema; using IBBoard.Lang; using IBBoard.Xml; using IBBoard.WarFoundry.API.Objects; using IBBoard.WarFoundry.API.Util; namespace IBBoard.WarFoundry.API.Exporters { /// <summary> /// Custom exporter that exports an army as a basic HTML file /// </summary> public class WarFoundryHtmlExporter : IWarFoundryExporter { private static WarFoundryHtmlExporter exporter; private delegate string GetStatCellTextDelegate(Stat stat); public static WarFoundryHtmlExporter GetDefault() { if (exporter == null) { exporter = new WarFoundryHtmlExporter(); } return exporter; } private WarFoundryHtmlExporter() { //Hide constructor } public void ExportArmy(Army army, string path) { XmlDocument doc = new XmlDocument(); CustomXmlResolver resolver = new CustomXmlResolver(); Uri localUri = new Uri("file://" + IBBoard.Constants.ExecutablePath + "/schemas/xhtml1-strict.dtd"); resolver.AddMapping("-//W3C//DTD XHTML 1.0 Strict//EN", localUri); resolver.AddMapping("http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd", localUri); doc.XmlResolver = resolver; doc.AppendChild(doc.CreateDocumentType("html", "-//W3C//DTD XHTML 1.0 Strict//EN", "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd", null)); XmlElement html = doc.CreateElement("html"); doc.AppendChild(html); XmlElement head = doc.CreateElement("head"); html.AppendChild(head); XmlElement title = doc.CreateElement("title"); title.InnerXml = army.Name; head.AppendChild(title); XmlElement metaCharset = doc.CreateElement("meta"); metaCharset.SetAttribute("http-equiv", "Content-Type"); metaCharset.SetAttribute("content", "text/html;charset=UTF-8"); head.AppendChild(metaCharset); XmlElement style = doc.CreateElement("style"); style.InnerText = "table, th, td { border: 1px solid #000; border-spacing: 0; border-collapse: collapse; margin: 0 }\n" +"table table { width: 100%; border-width: 0; margin: -2px }\n" +"table table td { border-width:0 1px }"; head.AppendChild(style); XmlElement body = doc.CreateElement("body"); html.AppendChild(body); XmlElement header = doc.CreateElement("h1"); header.InnerText = Translation.GetTranslation("armyHtmlOutputBodyHeader", "{0} - {1}pts", army.Name, army.Points); body.AppendChild(header); foreach (XmlElement table in CreateTables(army, doc)) { if (!IsTableOnlyHeader(table)) { body.AppendChild(table); } } File.WriteAllText(path, doc.OuterXml); } private bool IsTableOnlyHeader(XmlElement table) { return table.ChildNodes.Count == 1; } private XmlElement[] CreateTables(Army army, XmlDocument doc) { Dictionary<string, XmlElement> tables = new Dictionary<string, XmlElement>(); foreach (SystemStats statSets in army.GameSystem.SystemStats) { tables[statSets.ID] = CreateTable(statSets, doc); } foreach (Unit unit in army.GetUnits()) { CreateUnitRow(unit, tables[GetFirstStatType(unit)]); } return DictionaryUtils.ToArray(tables); } private static string GetFirstStatType(Unit unit) { string[] unitStatIDs = unit.UnitStatsArrayIDs; return GetFirstStatType(unitStatIDs); } public static string GetFirstStatType(string[] unitStatIDs) { return unitStatIDs[0]; } private XmlElement CreateTable(SystemStats stats, XmlDocument doc) { XmlElement table = doc.CreateElement("table"); XmlElement headerRow = doc.CreateElement("tr"); table.AppendChild(headerRow); XmlElement name = doc.CreateElement("th"); name.InnerText = Translation.GetTranslation("armyHtmlOutputTableHeaderUnitName", "name"); headerRow.AppendChild(name); XmlElement unitTypeName = doc.CreateElement("th"); unitTypeName.InnerText = Translation.GetTranslation("armyHtmlOutputTableHeaderUnitTypeName", "type name"); headerRow.AppendChild(unitTypeName); foreach (StatSlot stat in stats.StatSlots) { XmlElement statHeader = doc.CreateElement("th"); statHeader.InnerText = stat.Name; headerRow.AppendChild(statHeader); } XmlElement notes = doc.CreateElement("th"); notes.InnerText = Translation.GetTranslation("armyHtmlOutputTableHeaderUnitNotes", "name");; headerRow.AppendChild(notes); XmlElement points = doc.CreateElement("th"); points.InnerText = Translation.GetTranslation("armyHtmlOutputTableHeaderUnitPoints", "name");; headerRow.AppendChild(points); return table; } private XmlElement CreateUnitRow(Unit unit, XmlElement tableElem) { XmlDocument doc = tableElem.OwnerDocument; XmlElement row = doc.CreateElement("tr"); tableElem.AppendChild(row); Stat[][] memberStats = unit.UnitStatsArraysWithName; string[] statTypeIDs = unit.UnitStatsArrayIDs; string defaultStatType = GetFirstStatType(statTypeIDs); int statRowCount = 0; bool hasOther = false; foreach (string statTypeID in statTypeIDs) { if (statTypeID.Equals(defaultStatType)) { statRowCount++; } else if (!hasOther) { statRowCount++; hasOther = true; } } XmlElement name = doc.CreateElement("td"); name.InnerText = unit.Name; SetRowSpan(name, statRowCount); row.AppendChild(name); CreateStatsBlock(row, memberStats, statTypeIDs); StringBuilder sb = new StringBuilder(); UnitEquipmentItem[] unitEquipment = unit.GetEquipment(); if (unitEquipment.Length > 0) { bool addSeparator = false; foreach (UnitEquipmentItem equip in unitEquipment) { if (!addSeparator) { addSeparator = true; } else { sb.Append(", "); } string amountString; double amount = UnitEquipmentUtil.GetEquipmentAmount(unit, equip); if (UnitEquipmentUtil.GetEquipmentAmountIsRatio(unit, equip)) { if (amount == 100) { amountString = GetEquipmentAmountAllTranslation(unit); } else { int number = UnitEquipmentUtil.GetEquipmentAmountTaken(unit, equip); amountString = GetEquipmentAmountRatioTranslation(amount, number); } } else { if (amount == -1) { amountString = GetEquipmentAmountAllTranslation(unit); } else { amountString = GetEquipmentAmountNumberTranslation((int)amount); } } sb.Append(Translation.GetTranslation("armyHtmlExportEquipAmountRatio", "{0} for {1}", equip.Name, amountString)); } sb.Append(". "); } ICollection<Ability> abilities = unit.Abilities; if (abilities.Count > 0) { bool addSeparator = false; foreach (Ability ability in abilities) { if (!addSeparator) { addSeparator = true; } else { sb.Append(", "); } sb.Append(ability.Name); } sb.Append(". "); } XmlElement notes = doc.CreateElement("td"); notes.InnerText = sb.ToString(); SetRowSpan(notes, statRowCount); row.AppendChild(notes); XmlElement points = doc.CreateElement("td"); points.InnerText = unit.Points.ToString(); SetRowSpan(points, statRowCount); row.AppendChild(points); return row; } private static void SetRowSpan(XmlElement xmlElement, int statRowCount) { if (statRowCount > 1) { xmlElement.SetAttribute("rowspan", statRowCount.ToString()); } } private void CreateStatsBlock(XmlElement unitRow, Stat[][] memberStats, string[] statTypeIDs) { XmlDocument doc = unitRow.OwnerDocument; string defaultStatType = GetFirstStatType(statTypeIDs); Stat[] defaultStatLine = memberStats[0]; int defaultStatLineCount = defaultStatLine.Length; AddStatCell(defaultStatLine[0].SlotValueString, unitRow); for (int i = 1; i < defaultStatLineCount; i++) { string statText = GetDefaultStatCellText(defaultStatLine[i]); AddStatCell(statText, unitRow); } int statCount = statTypeIDs.Length; if (statCount > 1) { XmlElement unitTable = (XmlElement)unitRow.ParentNode; Dictionary<string, XmlElement> statParents = CreateStatsParentElements(statTypeIDs, unitTable); for (int i = 1; i < statCount; i++) { Stat[] statLine = memberStats[i]; string statTypeID = statTypeIDs[i]; XmlElement tableElement = DictionaryUtils.GetValue(statParents, statTypeID); int statLineCount = statLine.Length; XmlElement statRow = doc.CreateElement("tr"); tableElement.AppendChild(statRow); GetStatCellTextDelegate statCellTextDelegate = (statTypeID.Equals(defaultStatType) ? new GetStatCellTextDelegate(GetDefaultStatCellText) : new GetStatCellTextDelegate(GetOtherStatCellText)); AddStatCell(statLine[0].SlotValueString, statRow); for (int j = 1; j < statLineCount; j++) { string statText = statCellTextDelegate(statLine[j]); AddStatCell(statText, statRow); } } if (statParents.Count > 1) { AddOtherUnitStatTables(statParents, unitTable, defaultStatLineCount); } } } private static void AddOtherUnitStatTables(Dictionary<string, XmlElement> statParents, XmlElement unitTable, int defaultStatLineCount) { XmlDocument doc = unitTable.OwnerDocument; XmlElement otherStatsRow = doc.CreateElement("tr"); unitTable.AppendChild(otherStatsRow); XmlElement otherStatsCell = doc.CreateElement("td"); otherStatsCell.SetAttribute("colspan", defaultStatLineCount.ToString()); otherStatsRow.AppendChild(otherStatsCell); foreach (XmlElement tableElem in statParents.Values) { if (tableElem != unitTable) { otherStatsCell.AppendChild(tableElem); } } } private Dictionary<string, XmlElement> CreateStatsParentElements(string[] statTypeIDs, XmlElement parentTable) { Dictionary<string, XmlElement> statParents = new Dictionary<string, XmlElement>(); XmlDocument doc = parentTable.OwnerDocument; string defaultStatTypeID = GetFirstStatType(statTypeIDs); statParents[defaultStatTypeID] = parentTable; foreach (string statTypeID in statTypeIDs) { if (!statParents.ContainsKey(statTypeID)) { XmlElement tableElement = doc.CreateElement("table"); statParents[statTypeID] = tableElement; } } return statParents; } private string GetDefaultStatCellText(Stat stat) { return Translation.GetTranslation("armyHtmlExportDefaultStatCellText", "{0}", stat.SlotValueString, stat.ParentSlotName); } private string GetOtherStatCellText(Stat stat) { return Translation.GetTranslation("armyHtmlExportOtherStatCellText", "{1}: {0}", stat.SlotValueString, stat.ParentSlotName); } private static void AddStatCell(string statValue, XmlElement row) { XmlElement statCell = row.OwnerDocument.CreateElement("td"); statCell.InnerText = statValue; row.AppendChild(statCell); } private string GetEquipmentAmountRatioTranslation (double amount, int number) { return Translation.GetTranslation ("armyHtmlExportEquipAmountPercentage", "{0}% ({1})", amount, number); } private string GetEquipmentAmountNumberTranslation(int amount) { return Translation.GetTranslation("armyHtmlExportEquipAmountNumber", "{0}", amount); } private string GetEquipmentAmountAllTranslation(Unit unit) { return Translation.GetTranslation("armyHtmlExportEquipAmountAll", "all ({1})", 100, unit.Size); } } }