3 # This is the open-adventure dungeon text coverage report generator. It
4 # consumes a YAML description of the dungeon and determines whether the
5 # various strings contained are present within the test check files.
7 # Currently, only the location descriptions, arbitrary messages, object
8 # descriptions, hints, classes and turn thrusholds are supported. This will
9 # be expanded in the future.
17 yaml_name = "../adventure.yaml"
18 html_template_path = "coverage_dungeon.html.tpl"
19 html_output_path = "../coverage/adventure.yaml.html"
23 <td class="coverFile">{}</td>
24 <td class="{}"> </td>
25 <td class="{}"> </td>
31 <td class="coverFile">{}</td>
32 <td class="{}"> </td>
38 <td class="coverFile">{}</td>
39 <td class="{}"> </td>
43 def search(needle, haystack):
44 # Search for needle in haystack, first escaping needle for regex, then
45 # replacing %s, %d, etc. with regex wildcards, so the variable messages
46 # within the dungeon definition will actually match
47 needle = re.escape(needle) \
48 .replace("\%S", ".*") \
49 .replace("\%s", ".*") \
50 .replace("\%d", ".*") \
53 return re.search(needle, haystack)
55 def loc_coverage(locations, text):
56 for locname, loc in locations:
57 if loc["description"]["long"] == None or loc["description"]["long"] == '':
58 loc["description"]["long"] = True
59 if loc["description"]["long"] != True:
60 if search(loc["description"]["long"], text):
61 loc["description"]["long"] = True
62 if loc["description"]["short"] == None or loc["description"]["short"] == '':
63 loc["description"]["short"] = True
64 if loc["description"]["short"] != True:
65 if search(loc["description"]["short"], text):
66 loc["description"]["short"] = True
68 def arb_coverage(arb_msgs, text):
69 for i, msg in enumerate(arb_msgs):
70 (msg_name, msg_text) = msg
71 if msg_text == None or msg_text == '':
72 arb_msgs[i] = (msg_name, True)
73 elif msg_text != True:
74 if search(msg_text, text):
75 arb_msgs[i] = (msg_name, True)
77 def obj_coverage(objects, text):
78 for i, objouter in enumerate(objects):
79 (obj_name, obj) = objouter
80 if obj["descriptions"]:
81 for j, desc in enumerate(obj["descriptions"]):
82 if desc == None or desc == '':
83 obj["descriptions"][j] = True
84 objects[i] = (obj_name, obj)
86 if search(desc, text):
87 obj["descriptions"][j] = True
88 objects[i] = (obj_name, obj)
91 def hint_coverage(hints, text):
92 for name, hint in hints:
93 if hint["question"] != True:
94 if search(hint["question"], text):
95 hint["question"] = True
96 if hint["hint"] != True:
97 if search(hint["hint"], text):
101 def threshold_coverage(classes, text):
102 for i, msg in enumerate(classes):
103 if msg["message"] == None:
104 msg["message"] = True
105 elif msg["message"] != True:
106 if search(msg["message"], text):
107 msg["message"] = True
110 if __name__ == "__main__":
111 with open(yaml_name, "r") as f:
114 with open(html_template_path, "r") as f:
115 html_template = f.read()
117 locations = db["locations"]
118 arb_msgs = db["arbitrary_messages"]
119 objects = db["objects"]
120 hintsraw = db["hints"]
121 classes = db["classes"]
122 turn_thresholds = db["turn_thresholds"]
125 for hint in hintsraw:
126 hints.append((hint["hint"]["name"], {"question" : hint["hint"]["question"],"hint" : hint["hint"]["hint"]}))
129 for filename in os.listdir(test_dir):
130 if filename.endswith(".chk"):
131 with open(filename, "r") as chk:
133 loc_coverage(locations, text)
134 arb_coverage(arb_msgs, text)
135 obj_coverage(objects, text)
136 hint_coverage(hints, text)
137 threshold_coverage(classes, text)
138 threshold_coverage(turn_thresholds, text)
141 location_total = len(locations) * 2
144 for locouter in locations:
145 locname = locouter[0]
147 if loc["description"]["long"] != True:
148 long_success = "uncovered"
150 long_success = "covered"
151 location_covered += 1
153 if loc["description"]["short"] != True:
154 short_success = "uncovered"
156 short_success = "covered"
157 location_covered += 1
159 location_html += location_row.format(locname, long_success, short_success)
160 location_percent = round((location_covered / float(location_total)) * 100, 1)
164 arb_total = len(arb_msgs)
166 for name, msg in arb_msgs:
168 success = "uncovered"
172 arb_msg_html += arb_msg_row.format(name, success)
173 arb_percent = round((arb_covered / float(arb_total)) * 100, 1)
179 for (obj_name, obj) in objects:
180 if obj["descriptions"]:
181 for j, desc in enumerate(obj["descriptions"]):
184 success = "uncovered"
188 object_html += object_row.format("%s[%d]" % (obj_name, j), success)
189 objects_percent = round((objects_covered / float(objects_total)) * 100, 1)
193 hints_total = len(hints) * 2
195 for name, hint in hints:
196 if hint["question"] != True:
197 question_success = "uncovered"
199 question_success = "covered"
201 if hint["hint"] != True:
202 hint_success = "uncovered"
204 hint_success = "covered"
206 hints_html += location_row.format(name, question_success, hint_success)
207 hints_percent = round((hints_covered / float(hints_total)) * 100, 1)
210 class_total = len(classes)
212 for name, msg in enumerate(classes):
213 if msg["message"] != True:
214 success = "uncovered"
218 class_html += arb_msg_row.format(msg["threshold"], success)
219 class_percent = round((class_covered / float(class_total)) * 100, 1)
222 turn_total = len(turn_thresholds)
224 for name, msg in enumerate(turn_thresholds):
225 if msg["message"] != True:
226 success = "uncovered"
230 turn_html += arb_msg_row.format(msg["threshold"], success)
231 turn_percent = round((turn_covered / float(turn_total)) * 100, 1)
233 # output some quick report stats
234 print("\nadventure.yaml coverage rate:")
235 print(" locations..........: {}% covered ({} of {})".format(location_percent, location_covered, location_total))
236 print(" arbitrary_messages.: {}% covered ({} of {})".format(arb_percent, arb_covered, arb_total))
237 print(" objects............: {}% covered ({} of {})".format(objects_percent, objects_covered, objects_total))
238 print(" hints..............: {}% covered ({} of {})".format(hints_percent, hints_covered, hints_total))
239 print(" classes............: {}% covered ({} of {})".format(class_percent, class_covered, class_total))
240 print(" turn_thresholds....: {}% covered ({} of {})".format(turn_percent, turn_covered, turn_total))
243 with open(html_output_path, "w") as f:
244 f.write(html_template.format(
245 location_total, location_covered, location_percent,
246 arb_total, arb_covered, arb_percent,
247 objects_total, objects_covered, objects_percent,
248 hints_total, hints_covered, hints_percent,
249 class_total, class_covered, class_percent,
250 turn_total, turn_covered, turn_percent,
251 location_html, arb_msg_html, object_html, hints_html, class_html, turn_html