mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-22 12:57: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):
|
def parse(self, ids_dict):
|
||||||
self.name = ids_dict.get("@name", "")
|
self.name = ids_dict.get("@name", "")
|
||||||
|
self.description = ids_dict.get("@description", "")
|
||||||
|
self.instructions = ids_dict.get("@instructions", "")
|
||||||
self.minOccurs = ids_dict["@minOccurs"]
|
self.minOccurs = ids_dict["@minOccurs"]
|
||||||
self.maxOccurs = ids_dict["@maxOccurs"]
|
self.maxOccurs = ids_dict["@maxOccurs"]
|
||||||
self.ifcVersion = ids_dict["@ifcVersion"]
|
self.ifcVersion = ids_dict["@ifcVersion"]
|
||||||
|
|||||||
@@ -159,31 +159,85 @@ class Json(Reporter):
|
|||||||
|
|
||||||
def report(self):
|
def report(self):
|
||||||
self.results["title"] = self.ids.info.get("title", "Untitled IDS")
|
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"] = []
|
self.results["specifications"] = []
|
||||||
for specification in self.ids.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
|
return self.results
|
||||||
|
|
||||||
def report_specification(self, specification):
|
def report_specification(self, specification):
|
||||||
applicability = [a.to_string("applicability") for a in specification.applicability]
|
applicability = [a.to_string("applicability") for a in specification.applicability]
|
||||||
|
total_applicable = len(specification.applicable_entities)
|
||||||
|
total_checks = 0
|
||||||
|
total_checks_pass = 0
|
||||||
requirements = []
|
requirements = []
|
||||||
for requirement in specification.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(
|
requirements.append(
|
||||||
{
|
{
|
||||||
"description": requirement.to_string("requirement"),
|
"description": requirement.to_string("requirement"),
|
||||||
"status": requirement.status,
|
"status": requirement.status,
|
||||||
"failed_entities": self.report_failed_entities(requirement),
|
"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_applicable_pass = total_applicable - len(specification.failed_entities)
|
||||||
total_successes = total - len(specification.failed_entities)
|
percent_applicable_pass = (
|
||||||
percentage = math.floor((total_successes / total) * 100) if total else "N/A"
|
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 {
|
return {
|
||||||
"name": specification.name,
|
"name": specification.name,
|
||||||
|
"description": specification.description,
|
||||||
|
"instructions": specification.instructions,
|
||||||
"status": specification.status,
|
"status": specification.status,
|
||||||
"total_successes": total_successes,
|
"total_applicable": total_applicable,
|
||||||
"total": total,
|
"total_applicable_pass": total_applicable_pass,
|
||||||
"percentage": percentage,
|
"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,
|
"required": specification.minOccurs != 0,
|
||||||
"applicability": applicability,
|
"applicability": applicability,
|
||||||
"requirements": requirements,
|
"requirements": requirements,
|
||||||
@@ -223,12 +277,15 @@ class Html(Json):
|
|||||||
self.results = {}
|
self.results = {}
|
||||||
|
|
||||||
def report(self):
|
def report(self):
|
||||||
self.results["title"] = self.ids.info.get("title", "Untitled IDS")
|
super().report()
|
||||||
self.results["time"] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
entity_limit = 100
|
||||||
self.results["specifications"] = []
|
for spec in self.results["specifications"]:
|
||||||
for specification in self.ids.specifications:
|
for requirement in spec["requirements"]:
|
||||||
self.results["specifications"].append(self.report_specification(specification))
|
total = len(requirement["failed_entities"])
|
||||||
return self.results
|
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):
|
def to_string(self):
|
||||||
import pystache
|
import pystache
|
||||||
@@ -272,7 +329,7 @@ class Ods(Json):
|
|||||||
|
|
||||||
table = Table(name=self.results["title"])
|
table = Table(name=self.results["title"])
|
||||||
tr = TableRow()
|
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 = TableCell(valuetype="string", stylename="h")
|
||||||
tc.addElement(P(text=header))
|
tc.addElement(P(text=header))
|
||||||
tr.addElement(tc)
|
tr.addElement(tc)
|
||||||
@@ -284,9 +341,9 @@ class Ods(Json):
|
|||||||
[
|
[
|
||||||
specification["name"],
|
specification["name"],
|
||||||
"Pass" if specification["status"] else "Fail",
|
"Pass" if specification["status"] else "Fail",
|
||||||
str(specification["total_successes"]),
|
str(specification["total_checks_pass"]),
|
||||||
str(specification["total"]),
|
str(specification["total_checks"]),
|
||||||
str(specification["percentage"]),
|
str(specification["percent_checks_pass"]),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -309,7 +366,7 @@ class Ods(Json):
|
|||||||
continue
|
continue
|
||||||
table = Table(name=specification["name"])
|
table = Table(name=specification["name"])
|
||||||
tr = TableRow()
|
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 = TableCell(valuetype="string", stylename="h")
|
||||||
tc.addElement(P(text=header))
|
tc.addElement(P(text=header))
|
||||||
tr.addElement(tc)
|
tr.addElement(tc)
|
||||||
@@ -321,6 +378,12 @@ class Ods(Json):
|
|||||||
row = [
|
row = [
|
||||||
requirement["description"],
|
requirement["description"],
|
||||||
failure.get("reason", "No reason provided"),
|
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")),
|
str(failure.get("element", "No element found")),
|
||||||
]
|
]
|
||||||
tr = TableRow()
|
tr = TableRow()
|
||||||
|
|||||||
@@ -26,173 +26,153 @@
|
|||||||
<title>{{name}}</title>
|
<title>{{name}}</title>
|
||||||
<link href="https://fonts.googleapis.com/css?family=Comfortaa|Inconsolata|Open+Sans&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css?family=Comfortaa|Inconsolata|Open+Sans&display=swap" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
|
:root {
|
||||||
|
--green: #97cc64;
|
||||||
|
--light-green: #b6cca1;
|
||||||
|
--red: #fb5a3e;
|
||||||
|
--light-red: #fbb4a8;
|
||||||
|
}
|
||||||
body { font-family: 'Arial', sans-serif; padding: 10px 40px; }
|
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.time { color: #999; font-style: italic; float: right; }
|
||||||
span.step-time { float: right; color: #555; font-size: 0.8em; font-style: italic; }
|
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.item { padding: 5px; border-radius: 5px; margin-right: 5px; border: 1px solid #eee; }
|
||||||
span.failure { background-color: #fb5a3e; padding: 5px; border-radius: 5px; color: #FFF; font-weight: bold; }
|
span.item.pass, span.item.fail { color: #FFF; font-weight: bold; border: 0px; }
|
||||||
p.failure { background-color: #fb5a3e; padding: 5px; border-radius: 5px; color: #fff; }
|
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.unspecified { background-color: #994f00; padding: 5px; border-radius: 5px; color: #fff; }
|
||||||
p.skipped { background-color: #8b8d8f; 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;}
|
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 { padding: 10px; font-family: monospace; }
|
||||||
li.success { background-color: #b6cca1; color: #333; }
|
li.pass { background-color: var(--light-green); color: #333; }
|
||||||
li.failure { background-color: #fbb4a8; color: #900; }
|
li.fail { background-color: var(--light-red); color: #900; }
|
||||||
li.unspecified { background-color: #ffd37f; color: #a30; }
|
li.unspecified { background-color: #ffd37f; color: #a30; }
|
||||||
li.skipped { background-color: #f5f5f5; color: #333; }
|
li.skipped { background-color: #f5f5f5; color: #333; }
|
||||||
li p { margin-bottom: 0px; }
|
li p { margin-bottom: 0px; }
|
||||||
footer { color: #999; font-size: 0.8em; }
|
footer { color: #999; font-size: 0.8em; }
|
||||||
header { text-align: center; }
|
header { text-align: center; }
|
||||||
hr { margin: 20px; margin-left: 0px; margin-right: 0px; border: none; border-top: 1px solid #ccc; }
|
hr { margin: 20px; margin-left: 0px; margin-right: 0px; border: none; border-top: 1px solid #ccc; }
|
||||||
details { user-select: none; }
|
summary { display: flex; cursor: pointer; }
|
||||||
details>summary span.icon { width: 24px; height: 24px; transition: all 0.3s; margin-left: auto; }
|
summary::-webkit-details-marker { display: none; }
|
||||||
summary { display: flex; cursor: pointer; }
|
* {box-sizing:border-box}
|
||||||
summary::-webkit-details-marker { display: none; }
|
.container { width: 100%; background-color: #ddd; border-radius: 5px}
|
||||||
* {box-sizing:border-box}
|
.percent { text-align: left; padding-top: 5px; padding-left: 5px; padding-bottom: 5px; color: white; border-radius: 5px; white-space: nowrap; }
|
||||||
.container { width: 100%; background-color: #ddd; border-radius: 5px}
|
.pass { background-color: var(--green); }
|
||||||
.completion { text-align: left; padding-top: 5px; padding-left: 5px; padding-bottom: 5px; color: white; }
|
.fail { background-color: var(--red); }
|
||||||
.percent0 {width: 0%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
table { width: 100%; border-bottom: 2px solid var(--red); border-spacing: 0; border-radius: 5px; margin-top: 10px; }
|
||||||
.percent1 {width: 1%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
th, td { padding: 5px; }
|
||||||
.percent2 {width: 2%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
thead>tr { background-color: var(--red); font-weight: bold; color: #fff; }
|
||||||
.percent3 {width: 3%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
tbody tr { border-bottom: 1px solid var(--red); }
|
||||||
.percent4 {width: 4%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
tbody tr:nth-child(odd) { background-color: rgba(1, 1, 1, 0.05); }
|
||||||
.percent5 {width: 5%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
tbody tr:nth-child(even) { background-color: rgba(1, 1, 1, 0.1); }
|
||||||
.percent6 {width: 6%; background-color: #97cc64; border-radius: 5px; font-weight: bold}
|
tbody tr:hover { background-color: rgba(0, 0, 0, 0); }
|
||||||
.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}
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<h1>{{title}}</h1>
|
<h1>{{title}}</h1>
|
||||||
<p><strong>{{time}}</strong></p>
|
<p><strong>{{date}}</strong></p>
|
||||||
</header>
|
</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}}
|
{{#specifications}}
|
||||||
<section>
|
<section>
|
||||||
<h2>{{name}}</h2>
|
<h2>{{name}}</h2>
|
||||||
|
{{#description}}
|
||||||
|
<p>{{description}}</p>
|
||||||
|
{{/description}}
|
||||||
|
{{#instructions}}
|
||||||
|
<p><em>{{instructions}}</em></p>
|
||||||
|
{{/instructions}}
|
||||||
|
|
||||||
<div class="container">
|
<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>
|
</div>
|
||||||
<details>
|
<p>
|
||||||
<summary>
|
<span class="item {{#status}}pass{{/status}}{{^status}}fail{{/status}}">{{#status}}Pass{{/status}}{{^status}}Fail{{/status}}</span>
|
||||||
<p>
|
<span class="item">
|
||||||
<span class="{{#status}}success{{/status}}{{^status}}failure{{/status}}">{{#status}}Pass{{/status}}{{^status}}Fail{{/status}}</span>
|
Checks passed: <strong>{{total_checks_pass}}</strong> / <strong>{{total_checks}}</strong>
|
||||||
Passed: <strong>{{total_successes}} / {{total}}</strong> ({{percentage}}%) - click here to see details
|
</span>
|
||||||
</p>
|
<span class="item">
|
||||||
</summary>
|
Elements passed: <strong>{{total_applicable_pass}}</strong> / <strong>{{total_applicable}}</strong>
|
||||||
<ol>
|
</span>
|
||||||
{{#requirements}}
|
</p>
|
||||||
<li class="{{#status}}success{{/status}}{{^status}}failure{{/status}}">
|
<p>
|
||||||
{{description}}
|
<strong>Applicability</strong>
|
||||||
{{^status}}{{#total}}
|
</p>
|
||||||
<p class="failure{{#is_unspecified}} unspecified{{/is_unspecified}}{{#is_skipped}} skipped{{/is_skipped}}">
|
<ul>
|
||||||
{{#failed_entities}}
|
{{#applicability}}
|
||||||
{{reason}} <em style="color: #fbb4a8;">{{element}}</em><br />
|
<li>{{.}}</li>
|
||||||
{{/failed_entities}}
|
{{/applicability}}
|
||||||
</p>
|
</ul>
|
||||||
{{/total}}{{/status}}
|
<p>
|
||||||
</li>
|
<strong>Requirements</strong>
|
||||||
{{/requirements}}
|
</p>
|
||||||
</ol>
|
<ol>
|
||||||
</details>
|
{{#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>
|
</section>
|
||||||
{{/specifications}}
|
{{/specifications}}
|
||||||
<hr>
|
<hr>
|
||||||
<footer>
|
<footer>
|
||||||
<p>
|
<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>
|
</p>
|
||||||
</footer>
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
Reference in New Issue
Block a user