Mercurial > repos > IBDev-IBBoard.WarFoundry.API
comparison API/Exporters/WarFoundryHtmlExporter.cs @ 337:3c4a6403a88c
* Fix capitalisation so that new files are in the namespace
no-open-ticket
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Sun, 03 Apr 2011 18:50:32 +0000 |
parents | |
children | 6da9db4a9c23 |
comparison
equal
deleted
inserted
replaced
336:3631c1493c7f | 337:3c4a6403a88c |
---|---|
1 // This file (WarFoundryHtmlExporter.cs) is a part of the IBBoard.WarFoundry.API project and is copyright 2009 IBBoard | |
2 // | |
3 // 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. | |
4 | |
5 using System; | |
6 using System.Collections.Generic; | |
7 using System.IO; | |
8 using System.Text; | |
9 using System.Xml; | |
10 using System.Xml.Schema; | |
11 using IBBoard.Lang; | |
12 using IBBoard.Xml; | |
13 using IBBoard.WarFoundry.API.Objects; | |
14 using IBBoard.WarFoundry.API.Util; | |
15 | |
16 namespace IBBoard.WarFoundry.API.Exporters | |
17 { | |
18 /// <summary> | |
19 /// Custom exporter that exports an army as a basic HTML file | |
20 /// </summary> | |
21 public class WarFoundryHtmlExporter : IWarFoundryExporter | |
22 { | |
23 private static WarFoundryHtmlExporter exporter; | |
24 private delegate string GetStatCellTextDelegate(Stat stat); | |
25 | |
26 public static WarFoundryHtmlExporter GetDefault() | |
27 { | |
28 if (exporter == null) | |
29 { | |
30 exporter = new WarFoundryHtmlExporter(); | |
31 } | |
32 | |
33 return exporter; | |
34 } | |
35 | |
36 private WarFoundryHtmlExporter() | |
37 { | |
38 //Hide constructor | |
39 } | |
40 | |
41 public void ExportArmy(Army army, string path) | |
42 { | |
43 XmlDocument doc = new XmlDocument(); | |
44 CustomXmlResolver resolver = new CustomXmlResolver(); | |
45 resolver.AddMapping("-//W3C//DTD XHTML 1.0 Strict//EN", new Uri("file://" + IBBoard.Constants.ExecutablePath + "/schemas/xhtml1-strict.dtd")); | |
46 doc.XmlResolver = resolver; | |
47 doc.AppendChild(doc.CreateDocumentType("html", "-//W3C//DTD XHTML 1.0 Strict//EN", "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd", null)); | |
48 XmlElement html = doc.CreateElement("html"); | |
49 doc.AppendChild(html); | |
50 XmlElement head = doc.CreateElement("head"); | |
51 html.AppendChild(head); | |
52 XmlElement title = doc.CreateElement("title"); | |
53 title.InnerXml = army.Name; | |
54 head.AppendChild(title); | |
55 XmlElement metaCharset = doc.CreateElement("meta"); | |
56 metaCharset.SetAttribute("http-equiv", "Content-Type"); | |
57 metaCharset.SetAttribute("content", "text/html;charset=UTF-8"); | |
58 head.AppendChild(metaCharset); | |
59 XmlElement style = doc.CreateElement("style"); | |
60 style.InnerText = "table, th, td { border: 1px solid #000; border-spacing: 0; border-collapse: collapse; margin: 0 }\n" | |
61 +"table table { width: 100%; border-width: 0; margin: -2px }\n" | |
62 +"table table td { border-width:0 1px }"; | |
63 head.AppendChild(style); | |
64 XmlElement body = doc.CreateElement("body"); | |
65 html.AppendChild(body); | |
66 XmlElement header = doc.CreateElement("h1"); | |
67 header.InnerText = Translation.GetTranslation("armyHtmlOutputBodyHeader", "{0} - {1}pts", army.Name, army.Points); | |
68 body.AppendChild(header); | |
69 | |
70 foreach (XmlElement table in CreateTables(army, doc)) | |
71 { | |
72 if (!IsTableOnlyHeader(table)) | |
73 { | |
74 body.AppendChild(table); | |
75 } | |
76 } | |
77 | |
78 StreamWriter writer = new StreamWriter(path, false); | |
79 | |
80 try | |
81 { | |
82 writer.Write(doc.OuterXml); | |
83 } | |
84 finally | |
85 { | |
86 writer.Close(); | |
87 } | |
88 } | |
89 | |
90 private bool IsTableOnlyHeader(XmlElement table) | |
91 { | |
92 return table.ChildNodes.Count == 1; | |
93 } | |
94 | |
95 private XmlElement[] CreateTables(Army army, XmlDocument doc) | |
96 { | |
97 Dictionary<string, XmlElement> tables = new Dictionary<string, XmlElement>(); | |
98 | |
99 foreach (SystemStats statSets in army.GameSystem.SystemStats) | |
100 { | |
101 tables[statSets.ID] = CreateTable(statSets, doc); | |
102 } | |
103 | |
104 foreach (Unit unit in army.GetUnits()) | |
105 { | |
106 CreateUnitRow(unit, tables[GetFirstStatType(unit)]); | |
107 } | |
108 | |
109 return DictionaryUtils.ToArray(tables); | |
110 } | |
111 | |
112 private static string GetFirstStatType(Unit unit) | |
113 { | |
114 string[] unitStatIDs = unit.UnitStatsArrayIDs; | |
115 return GetFirstStatType(unitStatIDs); | |
116 } | |
117 | |
118 public static string GetFirstStatType(string[] unitStatIDs) | |
119 { | |
120 return unitStatIDs[0]; | |
121 } | |
122 | |
123 private XmlElement CreateTable(SystemStats stats, XmlDocument doc) | |
124 { | |
125 XmlElement table = doc.CreateElement("table"); | |
126 XmlElement headerRow = doc.CreateElement("tr"); | |
127 table.AppendChild(headerRow); | |
128 XmlElement name = doc.CreateElement("th"); | |
129 name.InnerText = Translation.GetTranslation("armyHtmlOutputTableHeaderUnitName", "name"); | |
130 headerRow.AppendChild(name); | |
131 | |
132 XmlElement unitTypeName = doc.CreateElement("th"); | |
133 unitTypeName.InnerText = Translation.GetTranslation("armyHtmlOutputTableHeaderUnitTypeName", "type name"); | |
134 headerRow.AppendChild(unitTypeName); | |
135 | |
136 foreach (StatSlot stat in stats.StatSlots) | |
137 { | |
138 XmlElement statHeader = doc.CreateElement("th"); | |
139 statHeader.InnerText = stat.Name; | |
140 headerRow.AppendChild(statHeader); | |
141 } | |
142 | |
143 XmlElement notes = doc.CreateElement("th"); | |
144 notes.InnerText = Translation.GetTranslation("armyHtmlOutputTableHeaderUnitNotes", "name");; | |
145 headerRow.AppendChild(notes); | |
146 | |
147 XmlElement points = doc.CreateElement("th"); | |
148 points.InnerText = Translation.GetTranslation("armyHtmlOutputTableHeaderUnitPoints", "name");; | |
149 headerRow.AppendChild(points); | |
150 | |
151 return table; | |
152 } | |
153 | |
154 private XmlElement CreateUnitRow(Unit unit, XmlElement tableElem) | |
155 { | |
156 XmlDocument doc = tableElem.OwnerDocument; | |
157 XmlElement row = doc.CreateElement("tr"); | |
158 tableElem.AppendChild(row); | |
159 Stat[][] memberStats = unit.UnitStatsArraysWithName; | |
160 string[] statTypeIDs = unit.UnitStatsArrayIDs; | |
161 string defaultStatType = GetFirstStatType(statTypeIDs); | |
162 int statRowCount = 0; | |
163 bool hasOther = false; | |
164 | |
165 foreach (string statTypeID in statTypeIDs) | |
166 { | |
167 if (statTypeID.Equals(defaultStatType)) | |
168 { | |
169 statRowCount++; | |
170 } | |
171 else if (!hasOther) | |
172 { | |
173 statRowCount++; | |
174 hasOther = true; | |
175 } | |
176 } | |
177 | |
178 XmlElement name = doc.CreateElement("td"); | |
179 name.InnerText = unit.Name; | |
180 SetRowSpan(name, statRowCount); | |
181 row.AppendChild(name); | |
182 CreateStatsBlock(row, memberStats, statTypeIDs); | |
183 | |
184 StringBuilder sb = new StringBuilder(); | |
185 UnitEquipmentItem[] unitEquipment = unit.GetEquipment(); | |
186 | |
187 if (unitEquipment.Length > 0) | |
188 { | |
189 bool addSeparator = false; | |
190 | |
191 foreach (UnitEquipmentItem equip in unitEquipment) | |
192 { | |
193 if (!addSeparator) | |
194 { | |
195 addSeparator = true; | |
196 } | |
197 else | |
198 { | |
199 sb.Append(", "); | |
200 } | |
201 | |
202 string amountString; | |
203 double amount = UnitEquipmentUtil.GetEquipmentAmount(unit, equip); | |
204 | |
205 if (UnitEquipmentUtil.GetEquipmentAmountIsRatio(unit, equip)) | |
206 { | |
207 | |
208 if (amount == 100) | |
209 { | |
210 amountString = GetEquipmentAmountAllTranslation(unit); | |
211 } | |
212 else | |
213 { | |
214 int number = UnitEquipmentUtil.GetEquipmentAmountTaken(unit, equip); | |
215 amountString = GetEquipmentAmountRatioTranslation(amount, number); | |
216 } | |
217 } | |
218 else | |
219 { | |
220 if (amount == -1) | |
221 { | |
222 amountString = GetEquipmentAmountAllTranslation(unit); | |
223 } | |
224 else | |
225 { | |
226 amountString = GetEquipmentAmountNumberTranslation((int)amount); | |
227 } | |
228 } | |
229 | |
230 sb.Append(Translation.GetTranslation("armyHtmlExportEquipAmountRatio", "{0} for {1}", equip.Name, amountString)); | |
231 } | |
232 | |
233 sb.Append(". "); | |
234 } | |
235 | |
236 ICollection<Ability> abilities = unit.Abilities; | |
237 | |
238 if (abilities.Count > 0) | |
239 { | |
240 bool addSeparator = false; | |
241 | |
242 foreach (Ability ability in abilities) | |
243 { | |
244 if (!addSeparator) | |
245 { | |
246 addSeparator = true; | |
247 } | |
248 else | |
249 { | |
250 sb.Append(", "); | |
251 } | |
252 | |
253 sb.Append(ability.Name); | |
254 } | |
255 | |
256 sb.Append(". "); | |
257 } | |
258 | |
259 XmlElement notes = doc.CreateElement("td"); | |
260 notes.InnerText = sb.ToString(); | |
261 SetRowSpan(notes, statRowCount); | |
262 row.AppendChild(notes); | |
263 | |
264 XmlElement points = doc.CreateElement("td"); | |
265 points.InnerText = unit.Points.ToString(); | |
266 SetRowSpan(points, statRowCount); | |
267 row.AppendChild(points); | |
268 | |
269 return row; | |
270 } | |
271 | |
272 private static void SetRowSpan(XmlElement xmlElement, int statRowCount) | |
273 { | |
274 if (statRowCount > 1) | |
275 { | |
276 xmlElement.SetAttribute("rowspan", statRowCount.ToString()); | |
277 } | |
278 } | |
279 | |
280 private void CreateStatsBlock(XmlElement unitRow, Stat[][] memberStats, string[] statTypeIDs) | |
281 { | |
282 XmlDocument doc = unitRow.OwnerDocument; | |
283 string defaultStatType = GetFirstStatType(statTypeIDs); | |
284 | |
285 Stat[] defaultStatLine = memberStats[0]; | |
286 int defaultStatLineCount = defaultStatLine.Length; | |
287 AddStatCell(defaultStatLine[0].SlotValueString, unitRow); | |
288 | |
289 for (int i = 1; i < defaultStatLineCount; i++) | |
290 { | |
291 string statText = GetDefaultStatCellText(defaultStatLine[i]); | |
292 AddStatCell(statText, unitRow); | |
293 } | |
294 | |
295 int statCount = statTypeIDs.Length; | |
296 | |
297 if (statCount > 1) | |
298 { | |
299 XmlElement unitTable = (XmlElement)unitRow.ParentNode; | |
300 Dictionary<string, XmlElement> statParents = CreateStatsParentElements(statTypeIDs, unitTable); | |
301 | |
302 for (int i = 1; i < statCount; i++) | |
303 { | |
304 Stat[] statLine = memberStats[i]; | |
305 string statTypeID = statTypeIDs[i]; | |
306 XmlElement tableElement = DictionaryUtils.GetValue(statParents, statTypeID); | |
307 int statLineCount = statLine.Length; | |
308 XmlElement statRow = doc.CreateElement("tr"); | |
309 tableElement.AppendChild(statRow); | |
310 GetStatCellTextDelegate statCellTextDelegate = (statTypeID.Equals(defaultStatType) ? new GetStatCellTextDelegate(GetDefaultStatCellText) : new GetStatCellTextDelegate(GetOtherStatCellText)); | |
311 AddStatCell(statLine[0].SlotValueString, statRow); | |
312 | |
313 for (int j = 1; j < statLineCount; j++) | |
314 { | |
315 string statText = statCellTextDelegate(statLine[j]); | |
316 AddStatCell(statText, statRow); | |
317 } | |
318 } | |
319 | |
320 if (statParents.Count > 1) | |
321 { | |
322 AddOtherUnitStatTables(statParents, unitTable, defaultStatLineCount); | |
323 } | |
324 } | |
325 } | |
326 | |
327 private static void AddOtherUnitStatTables(Dictionary<string, XmlElement> statParents, XmlElement unitTable, int defaultStatLineCount) | |
328 { | |
329 XmlDocument doc = unitTable.OwnerDocument; | |
330 XmlElement otherStatsRow = doc.CreateElement("tr"); | |
331 unitTable.AppendChild(otherStatsRow); | |
332 XmlElement otherStatsCell = doc.CreateElement("td"); | |
333 otherStatsCell.SetAttribute("colspan", defaultStatLineCount.ToString()); | |
334 otherStatsRow.AppendChild(otherStatsCell); | |
335 | |
336 foreach (XmlElement tableElem in statParents.Values) | |
337 { | |
338 if (tableElem != unitTable) | |
339 { | |
340 otherStatsCell.AppendChild(tableElem); | |
341 } | |
342 } | |
343 } | |
344 | |
345 private Dictionary<string, XmlElement> CreateStatsParentElements(string[] statTypeIDs, XmlElement parentTable) | |
346 { | |
347 Dictionary<string, XmlElement> statParents = new Dictionary<string, XmlElement>(); | |
348 XmlDocument doc = parentTable.OwnerDocument; | |
349 string defaultStatTypeID = GetFirstStatType(statTypeIDs); | |
350 statParents[defaultStatTypeID] = parentTable; | |
351 | |
352 foreach (string statTypeID in statTypeIDs) | |
353 { | |
354 if (!statParents.ContainsKey(statTypeID)) | |
355 { | |
356 XmlElement tableElement = doc.CreateElement("table"); | |
357 statParents[statTypeID] = tableElement; | |
358 } | |
359 } | |
360 | |
361 return statParents; | |
362 } | |
363 | |
364 private string GetDefaultStatCellText(Stat stat) | |
365 { | |
366 return Translation.GetTranslation("armyHtmlExportDefaultStatCellText", "{0}", stat.SlotValueString, stat.ParentSlotName); | |
367 } | |
368 | |
369 private string GetOtherStatCellText(Stat stat) | |
370 { | |
371 return Translation.GetTranslation("armyHtmlExportOtherStatCellText", "{1}: {0}", stat.SlotValueString, stat.ParentSlotName); | |
372 } | |
373 | |
374 private static void AddStatCell(string statValue, XmlElement row) | |
375 { | |
376 XmlElement statCell = row.OwnerDocument.CreateElement("td"); | |
377 statCell.InnerText = statValue; | |
378 row.AppendChild(statCell); | |
379 } | |
380 | |
381 private string GetEquipmentAmountRatioTranslation (double amount, int number) | |
382 { | |
383 return Translation.GetTranslation ("armyHtmlExportEquipAmountPercentage", "{0}% ({1})", amount, number); | |
384 } | |
385 | |
386 private string GetEquipmentAmountNumberTranslation(int amount) | |
387 { | |
388 return Translation.GetTranslation("armyHtmlExportEquipAmountNumber", "{0}", amount); | |
389 } | |
390 | |
391 private string GetEquipmentAmountAllTranslation(Unit unit) | |
392 { | |
393 return Translation.GetTranslation("armyHtmlExportEquipAmountAll", "all ({1})", 100, unit.Size); | |
394 } | |
395 } | |
396 } |