mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +00:00
IfcTester now supports much more granular statistic reports and more detailed / beautiful HTML reports.
This commit is contained in:
@@ -168,6 +168,8 @@ class Specification:
|
||||
|
||||
def parse(self, ids_dict):
|
||||
self.name = ids_dict.get("@name", "")
|
||||
self.description = ids_dict.get("@description", "")
|
||||
self.instructions = ids_dict.get("@instructions", "")
|
||||
self.minOccurs = ids_dict["@minOccurs"]
|
||||
self.maxOccurs = ids_dict["@maxOccurs"]
|
||||
self.ifcVersion = ids_dict["@ifcVersion"]
|
||||
|
||||
@@ -159,31 +159,85 @@ class Json(Reporter):
|
||||
|
||||
def report(self):
|
||||
self.results["title"] = self.ids.info.get("title", "Untitled IDS")
|
||||
self.results["date"] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
total_specifications = 0
|
||||
total_specifications_pass = 0
|
||||
total_requirements = 0
|
||||
total_requirements_pass = 0
|
||||
total_checks = 0
|
||||
total_checks_pass = 0
|
||||
status = True
|
||||
self.results["specifications"] = []
|
||||
for specification in self.ids.specifications:
|
||||
self.results["specifications"].append(self.report_specification(specification))
|
||||
specification_report = self.report_specification(specification)
|
||||
self.results["specifications"].append(specification_report)
|
||||
total_specifications += 1
|
||||
total_specifications_pass += 1 if specification_report["status"] else 0
|
||||
total_requirements += len(specification_report["requirements"])
|
||||
total_requirements_pass += len([r for r in specification_report["requirements"] if r["status"]])
|
||||
total_checks += specification_report["total_checks"]
|
||||
total_checks_pass += specification_report["total_checks_pass"]
|
||||
if not specification_report["status"]:
|
||||
status = False
|
||||
self.results["status"] = status
|
||||
self.results["total_specifications"] = total_specifications
|
||||
self.results["total_specifications_pass"] = total_specifications_pass
|
||||
self.results["total_specifications_fail"] = total_specifications - total_specifications_pass
|
||||
self.results["percent_specifications_pass"] = (
|
||||
math.floor((total_specifications_pass / total_specifications) * 100) if total_specifications else "N/A"
|
||||
)
|
||||
self.results["total_requirements"] = total_requirements
|
||||
self.results["total_requirements_pass"] = total_requirements_pass
|
||||
self.results["total_requirements_fail"] = total_requirements - total_requirements_pass
|
||||
self.results["percent_requirements_pass"] = (
|
||||
math.floor((total_requirements_pass / total_requirements) * 100) if total_requirements else "N/A"
|
||||
)
|
||||
self.results["total_checks"] = total_checks
|
||||
self.results["total_checks_pass"] = total_checks_pass
|
||||
self.results["total_checks_fail"] = total_checks - total_checks_pass
|
||||
self.results["percent_checks_pass"] = (
|
||||
math.floor((total_checks_pass / total_checks) * 100) if total_checks else "N/A"
|
||||
)
|
||||
return self.results
|
||||
|
||||
def report_specification(self, specification):
|
||||
applicability = [a.to_string("applicability") for a in specification.applicability]
|
||||
total_applicable = len(specification.applicable_entities)
|
||||
total_checks = 0
|
||||
total_checks_pass = 0
|
||||
requirements = []
|
||||
for requirement in specification.requirements:
|
||||
total_fail = len(requirement.failed_entities)
|
||||
total_checks += total_applicable
|
||||
total_checks_pass += total_applicable - total_fail
|
||||
requirements.append(
|
||||
{
|
||||
"description": requirement.to_string("requirement"),
|
||||
"status": requirement.status,
|
||||
"failed_entities": self.report_failed_entities(requirement),
|
||||
"total_applicable": total_applicable,
|
||||
"total_pass": total_applicable - total_fail,
|
||||
"total_fail": total_fail,
|
||||
}
|
||||
)
|
||||
total = len(specification.applicable_entities)
|
||||
total_successes = total - len(specification.failed_entities)
|
||||
percentage = math.floor((total_successes / total) * 100) if total else "N/A"
|
||||
total_applicable_pass = total_applicable - len(specification.failed_entities)
|
||||
percent_applicable_pass = (
|
||||
math.floor((total_applicable_pass / total_applicable) * 100) if total_applicable else "N/A"
|
||||
)
|
||||
percent_checks_pass = math.floor((total_checks_pass / total_checks) * 100) if total_checks else "N/A"
|
||||
return {
|
||||
"name": specification.name,
|
||||
"description": specification.description,
|
||||
"instructions": specification.instructions,
|
||||
"status": specification.status,
|
||||
"total_successes": total_successes,
|
||||
"total": total,
|
||||
"percentage": percentage,
|
||||
"total_applicable": total_applicable,
|
||||
"total_applicable_pass": total_applicable_pass,
|
||||
"total_applicable_fail": total_applicable - total_applicable_pass,
|
||||
"percent_applicable_pass": percent_applicable_pass,
|
||||
"total_checks": total_checks,
|
||||
"total_checks_pass": total_checks_pass,
|
||||
"total_checks_fail": total_checks - total_checks_pass,
|
||||
"percent_checks_pass": percent_checks_pass,
|
||||
"required": specification.minOccurs != 0,
|
||||
"applicability": applicability,
|
||||
"requirements": requirements,
|
||||
@@ -223,12 +277,15 @@ class Html(Json):
|
||||
self.results = {}
|
||||
|
||||
def report(self):
|
||||
self.results["title"] = self.ids.info.get("title", "Untitled IDS")
|
||||
self.results["time"] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
self.results["specifications"] = []
|
||||
for specification in self.ids.specifications:
|
||||
self.results["specifications"].append(self.report_specification(specification))
|
||||
return self.results
|
||||
super().report()
|
||||
entity_limit = 100
|
||||
for spec in self.results["specifications"]:
|
||||
for requirement in spec["requirements"]:
|
||||
total = len(requirement["failed_entities"])
|
||||
requirement["failed_entities"] = requirement["failed_entities"][0:entity_limit]
|
||||
requirement["has_omitted"] = total > entity_limit
|
||||
requirement["total_entities"] = total
|
||||
requirement["total_omitted"] = total - entity_limit
|
||||
|
||||
def to_string(self):
|
||||
import pystache
|
||||
@@ -272,7 +329,7 @@ class Ods(Json):
|
||||
|
||||
table = Table(name=self.results["title"])
|
||||
tr = TableRow()
|
||||
for header in ["Specification", "Status", "Total Compliant", "Total Applicable", "Percentage Compliant"]:
|
||||
for header in ["Specification", "Status", "Total Pass", "Total Checks", "Percentage Pass"]:
|
||||
tc = TableCell(valuetype="string", stylename="h")
|
||||
tc.addElement(P(text=header))
|
||||
tr.addElement(tc)
|
||||
@@ -284,9 +341,9 @@ class Ods(Json):
|
||||
[
|
||||
specification["name"],
|
||||
"Pass" if specification["status"] else "Fail",
|
||||
str(specification["total_successes"]),
|
||||
str(specification["total"]),
|
||||
str(specification["percentage"]),
|
||||
str(specification["total_checks_pass"]),
|
||||
str(specification["total_checks"]),
|
||||
str(specification["percent_checks_pass"]),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -309,7 +366,7 @@ class Ods(Json):
|
||||
continue
|
||||
table = Table(name=specification["name"])
|
||||
tr = TableRow()
|
||||
for header in ["Requirement", "Problem", "Element"]:
|
||||
for header in ["Requirement", "Problem", "Class", "PredefinedType", "Name", "Description", "GlobalId", "Tag", "Element"]:
|
||||
tc = TableCell(valuetype="string", stylename="h")
|
||||
tc.addElement(P(text=header))
|
||||
tr.addElement(tc)
|
||||
@@ -321,6 +378,12 @@ class Ods(Json):
|
||||
row = [
|
||||
requirement["description"],
|
||||
failure.get("reason", "No reason provided"),
|
||||
failure["class"],
|
||||
failure["predefined_type"],
|
||||
failure["name"],
|
||||
failure["description"],
|
||||
failure["global_id"],
|
||||
failure["tag"],
|
||||
str(failure.get("element", "No element found")),
|
||||
]
|
||||
tr = TableRow()
|
||||
|
||||
@@ -26,173 +26,153 @@
|
||||
<title>{{name}}</title>
|
||||
<link href="https://fonts.googleapis.com/css?family=Comfortaa|Inconsolata|Open+Sans&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--green: #97cc64;
|
||||
--light-green: #b6cca1;
|
||||
--red: #fb5a3e;
|
||||
--light-red: #fbb4a8;
|
||||
}
|
||||
body { font-family: 'Arial', sans-serif; padding: 10px 40px; }
|
||||
section { padding: 15px; border-radius: 5px; border: 1px solid #eee; margin-bottom: 15px; }
|
||||
section>h2 { margin-top: 0px; }
|
||||
span.time { color: #999; font-style: italic; float: right; }
|
||||
span.step-time { float: right; color: #555; font-size: 0.8em; font-style: italic; }
|
||||
span.success { background-color: #97cc64; padding: 5px; border-radius: 5px; color: #FFF; font-weight: bold; }
|
||||
span.failure { background-color: #fb5a3e; padding: 5px; border-radius: 5px; color: #FFF; font-weight: bold; }
|
||||
p.failure { background-color: #fb5a3e; padding: 5px; border-radius: 5px; color: #fff; }
|
||||
span.item { padding: 5px; border-radius: 5px; margin-right: 5px; border: 1px solid #eee; }
|
||||
span.item.pass, span.item.fail { color: #FFF; font-weight: bold; border: 0px; }
|
||||
p.fail { background-color: #fb5a3e; padding: 5px; border-radius: 5px; color: #fff; }
|
||||
p.unspecified { background-color: #994f00; padding: 5px; border-radius: 5px; color: #fff; }
|
||||
p.skipped { background-color: #8b8d8f; padding: 5px; border-radius: 5px; color: #fff; }
|
||||
p.description { background-color: #eee; border-radius: 5px; padding: 20px; margin-left: auto; margin-right: auto; display: inline-block; font-weight: bold;}
|
||||
li { padding: 10px; font-family: monospace; }
|
||||
li.success { background-color: #b6cca1; color: #333; }
|
||||
li.failure { background-color: #fbb4a8; color: #900; }
|
||||
li.pass { background-color: var(--light-green); color: #333; }
|
||||
li.fail { background-color: var(--light-red); color: #900; }
|
||||
li.unspecified { background-color: #ffd37f; color: #a30; }
|
||||
li.skipped { background-color: #f5f5f5; color: #333; }
|
||||
li p { margin-bottom: 0px; }
|
||||
footer { color: #999; font-size: 0.8em; }
|
||||
header { text-align: center; }
|
||||
hr { margin: 20px; margin-left: 0px; margin-right: 0px; border: none; border-top: 1px solid #ccc; }
|
||||
details { user-select: none; }
|
||||
details>summary span.icon { width: 24px; height: 24px; transition: all 0.3s; margin-left: auto; }
|
||||
summary { display: flex; cursor: pointer; }
|
||||
summary::-webkit-details-marker { display: none; }
|
||||
* {box-sizing:border-box}
|
||||
.container { width: 100%; background-color: #ddd; border-radius: 5px}
|
||||
.completion { text-align: left; padding-top: 5px; padding-left: 5px; padding-bottom: 5px; color: white; }
|
||||
.percent0 {width: 0%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent1 {width: 1%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent2 {width: 2%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent3 {width: 3%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent4 {width: 4%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent5 {width: 5%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent6 {width: 6%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent7 {width: 7%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent8 {width: 8%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent9 {width: 9%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent10 {width: 10%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent11 {width: 11%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent12 {width: 12%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent13 {width: 13%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent14 {width: 14%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent15 {width: 15%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent16 {width: 16%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent17 {width: 17%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent18 {width: 18%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent19 {width: 19%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent20 {width: 20%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent21 {width: 21%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent22 {width: 22%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent23 {width: 23%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent24 {width: 24%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent25 {width: 25%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent26 {width: 26%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent27 {width: 27%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent28 {width: 28%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent29 {width: 29%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent30 {width: 30%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent31 {width: 31%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent32 {width: 32%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent33 {width: 33%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent34 {width: 34%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent35 {width: 35%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent36 {width: 36%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent37 {width: 37%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent38 {width: 38%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent39 {width: 39%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent40 {width: 40%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent41 {width: 41%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent42 {width: 42%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent43 {width: 43%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent44 {width: 44%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent45 {width: 45%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent46 {width: 46%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent47 {width: 47%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent48 {width: 48%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent49 {width: 49%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent50 {width: 50%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent51 {width: 51%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent52 {width: 52%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent53 {width: 53%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent54 {width: 54%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent55 {width: 55%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent56 {width: 56%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent57 {width: 57%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent58 {width: 58%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent59 {width: 59%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent60 {width: 60%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent61 {width: 61%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent62 {width: 62%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent63 {width: 63%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent64 {width: 64%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent65 {width: 65%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent66 {width: 66%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent67 {width: 67%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent68 {width: 68%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent69 {width: 69%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent70 {width: 70%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent71 {width: 71%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent72 {width: 72%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent73 {width: 73%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent74 {width: 74%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent75 {width: 75%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent76 {width: 76%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent77 {width: 77%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent78 {width: 78%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent79 {width: 79%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent80 {width: 80%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent81 {width: 81%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent82 {width: 82%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent83 {width: 83%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent84 {width: 84%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent85 {width: 85%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent86 {width: 86%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent87 {width: 87%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent88 {width: 88%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent89 {width: 89%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent90 {width: 90%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent91 {width: 91%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent92 {width: 92%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent93 {width: 93%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent94 {width: 94%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent95 {width: 95%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent96 {width: 96%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent97 {width: 97%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent98 {width: 98%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent99 {width: 99%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
.percent100 {width: 100%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
||||
summary { display: flex; cursor: pointer; }
|
||||
summary::-webkit-details-marker { display: none; }
|
||||
* {box-sizing:border-box}
|
||||
.container { width: 100%; background-color: #ddd; border-radius: 5px}
|
||||
.percent { text-align: left; padding-top: 5px; padding-left: 5px; padding-bottom: 5px; color: white; border-radius: 5px; white-space: nowrap; }
|
||||
.pass { background-color: var(--green); }
|
||||
.fail { background-color: var(--red); }
|
||||
table { width: 100%; border-bottom: 2px solid var(--red); border-spacing: 0; border-radius: 5px; margin-top: 10px; }
|
||||
th, td { padding: 5px; }
|
||||
thead>tr { background-color: var(--red); font-weight: bold; color: #fff; }
|
||||
tbody tr { border-bottom: 1px solid var(--red); }
|
||||
tbody tr:nth-child(odd) { background-color: rgba(1, 1, 1, 0.05); }
|
||||
tbody tr:nth-child(even) { background-color: rgba(1, 1, 1, 0.1); }
|
||||
tbody tr:hover { background-color: rgba(0, 0, 0, 0); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>{{title}}</h1>
|
||||
<p><strong>{{time}}</strong></p>
|
||||
<p><strong>{{date}}</strong></p>
|
||||
</header>
|
||||
<h2>Summary</h2>
|
||||
<div class="container">
|
||||
<div class="{{#status}}pass{{/status}}{{^status}}fail{{/status}} percent" style="width: {{percent_checks_pass}}%;">{{percent_checks_pass}}%</div>
|
||||
</div>
|
||||
<p>
|
||||
<span class="item {{#status}}pass{{/status}}{{^status}}fail{{/status}}">{{#status}}Pass{{/status}}{{^status}}Fail{{/status}}</span>
|
||||
<span class="item">
|
||||
Specifications passed: <strong>{{total_specifications_pass}}</strong> / <strong>{{total_specifications}}</strong>
|
||||
</span>
|
||||
<span class="item">
|
||||
Requirements passed: <strong>{{total_requirements_pass}}</strong> / <strong>{{total_requirements}}</strong>
|
||||
</span>
|
||||
<span class="item">
|
||||
Checks passed: <strong>{{total_checks_pass}}</strong> / <strong>{{total_checks}}</strong>
|
||||
</span>
|
||||
</p>
|
||||
<hr>
|
||||
{{#specifications}}
|
||||
<section>
|
||||
<h2>{{name}}</h2>
|
||||
{{#description}}
|
||||
<p>{{description}}</p>
|
||||
{{/description}}
|
||||
{{#instructions}}
|
||||
<p><em>{{instructions}}</em></p>
|
||||
{{/instructions}}
|
||||
|
||||
<div class="container">
|
||||
<div class="completion percent{{percentage}}">{{percentage}}%</div>
|
||||
<div class="{{#status}}pass{{/status}}{{^status}}fail{{/status}} percent" style="width: {{percent_checks_pass}}%;">{{percent_checks_pass}}%</div>
|
||||
</div>
|
||||
<details>
|
||||
<summary>
|
||||
<p>
|
||||
<span class="{{#status}}success{{/status}}{{^status}}failure{{/status}}">{{#status}}Pass{{/status}}{{^status}}Fail{{/status}}</span>
|
||||
Passed: <strong>{{total_successes}} / {{total}}</strong> ({{percentage}}%) - click here to see details
|
||||
</p>
|
||||
</summary>
|
||||
<ol>
|
||||
{{#requirements}}
|
||||
<li class="{{#status}}success{{/status}}{{^status}}failure{{/status}}">
|
||||
{{description}}
|
||||
{{^status}}{{#total}}
|
||||
<p class="failure{{#is_unspecified}} unspecified{{/is_unspecified}}{{#is_skipped}} skipped{{/is_skipped}}">
|
||||
{{#failed_entities}}
|
||||
{{reason}} <em style="color: #fbb4a8;">{{element}}</em><br />
|
||||
{{/failed_entities}}
|
||||
</p>
|
||||
{{/total}}{{/status}}
|
||||
</li>
|
||||
{{/requirements}}
|
||||
</ol>
|
||||
</details>
|
||||
<p>
|
||||
<span class="item {{#status}}pass{{/status}}{{^status}}fail{{/status}}">{{#status}}Pass{{/status}}{{^status}}Fail{{/status}}</span>
|
||||
<span class="item">
|
||||
Checks passed: <strong>{{total_checks_pass}}</strong> / <strong>{{total_checks}}</strong>
|
||||
</span>
|
||||
<span class="item">
|
||||
Elements passed: <strong>{{total_applicable_pass}}</strong> / <strong>{{total_applicable}}</strong>
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
<strong>Applicability</strong>
|
||||
</p>
|
||||
<ul>
|
||||
{{#applicability}}
|
||||
<li>{{.}}</li>
|
||||
{{/applicability}}
|
||||
</ul>
|
||||
<p>
|
||||
<strong>Requirements</strong>
|
||||
</p>
|
||||
<ol>
|
||||
{{#requirements}}
|
||||
<li class="{{#status}}pass{{/status}}{{^status}}fail{{/status}}">
|
||||
<details>
|
||||
<summary>
|
||||
{{description}}
|
||||
</summary>
|
||||
{{#total_fail}}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Class</th>
|
||||
<th>PredefinedType</th>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>Warning</th>
|
||||
<th>GlobalId</th>
|
||||
<th>Tag</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#failed_entities}}
|
||||
<tr>
|
||||
<td>{{class}}</td>
|
||||
<td>{{predefined_type}}</td>
|
||||
<td>{{name}}</td>
|
||||
<td>{{description}}</td>
|
||||
<td>{{reason}}</td>
|
||||
<td>{{global_id}}</td>
|
||||
<td>{{tag}}</td>
|
||||
</tr>
|
||||
{{/failed_entities}}
|
||||
{{#has_omitted}}
|
||||
<tr>
|
||||
<td colspan="7"> ... {{total_omitted}} more elements not shown out of {{total_entities}} total ...</td>
|
||||
</tr>
|
||||
{{/has_omitted}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{/total_fail}}
|
||||
</details>
|
||||
</li>
|
||||
{{/requirements}}
|
||||
</ol>
|
||||
</section>
|
||||
{{/specifications}}
|
||||
<hr>
|
||||
<footer>
|
||||
<p>
|
||||
Report by <a href="https://blenderbim.org/">BlenderBIM</a> and <a href="http://ifcopenshell.org/">IfcOpenShell</a>.
|
||||
Report by the <a href="https://blenderbim.org/">BlenderBIM Add-on</a> and <a href="http://ifcopenshell.org/">IfcOpenShell</a>.
|
||||
</p>
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user