UNPKG

pddl-gantt

Version:

Plan visualization for AI-Planning plans. The package includes HTML components for Gantt, swimlane and line plot visualization of plan originating from AI Planning solvers.

136 lines 6.13 kB
"use strict"; /* -------------------------------------------------------------------------------------------- * Copyright (c) Jan Dolejsi 2020. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. * ------------------------------------------------------------------------------------------ */ Object.defineProperty(exports, "__esModule", { value: true }); exports.createPlansView = exports.PlansView = void 0; const PlanView_1 = require("./PlanView"); const PLAN_SELECTORS = "planSelectors"; const PLAN_SELECTOR = "planSelector"; const PLAN_SELECTOR_SELECTED = PLAN_SELECTOR + "-selected"; const PLAN_VIEWS = "planViews"; /** Multiple-plan view. */ class PlansView extends PlanView_1.View { constructor(hostElement, options) { super(hostElement, options); this.selectedPlan = -1; this.plans = []; this.planViews = []; this.onPlanSelected = options.onPlanSelected; this.clear(); } clear() { this.showPlans([], -1); } /** * Get `PlanView` for the plan at given `planIndex` * @param planIndex plan index * @throws when planIndex is out of range */ getView(planIndex) { return this.planViews[planIndex]; } showPlans(plans, planId = -1, configuration) { this.selectedPlan = planId < 0 ? plans.length - 1 : planId; this.plans = plans; this.planViews = []; this.createPlanSelectors(); this.createPlanViews(configuration); } addPlan(plan, configuration) { const planIndex = this.plans.push(plan) - 1; this.createPlanSelectors(); this.planViewsEl && this.addPlanView(plan, planIndex, this.planViewsEl, configuration); } setSelectedPlan(newSelectedPlan) { var _a; if (this.selectedPlan != newSelectedPlan) { // remember the index of the plan that is being shown for later manipulation this.selectedPlan = newSelectedPlan; (_a = this.onPlanSelected) === null || _a === void 0 ? void 0 : _a.call(this, this.selectedPlan); } } createPlanSelectors() { const planSelectorsEl = this.getOrCreateBlankChildElement(PLAN_SELECTORS); planSelectorsEl.style.display = this.plans.length > 1 ? "flex" : "none"; const maxMetric = Math.max(...this.plans.map(plan => { var _a; return (_a = plan.metric) !== null && _a !== void 0 ? _a : 0; })); this.plans.forEach((plan, planIndex) => this.createPlanSelector(plan, planIndex, this.selectedPlan, maxMetric, planSelectorsEl)); this.scrollPlanSelectorIntoView(this.selectedPlan); } createPlanSelector(plan, planIndex, selectedPlan, maxMetric, parentEl) { var _a; const normalizedMetric = ((_a = plan.metric) !== null && _a !== void 0 ? _a : 0) / maxMetric * 100; const costRounded = plan.metric !== undefined ? plan.metric.toFixed(PlanView_1.DIGITS) : NaN.toString(); const tooltip = `Plan #${planIndex} Metric value / cost: ${plan.metric} Makespan: ${plan.makespan} States evaluated: ${plan.statesEvaluated}`; const planSelectorEl = document.createElement('div'); planSelectorEl.className = PLAN_SELECTOR; if (planIndex === selectedPlan) { planSelectorEl.classList.add(PLAN_SELECTOR_SELECTED); } planSelectorEl.setAttribute(PlanView_1.ATTR_PLAN, planIndex.toString()); planSelectorEl.onclick = () => this.showSelectedPlan(planIndex); const label = document.createElement("span"); label.innerText = costRounded; planSelectorEl.appendChild(label); const bar = document.createElement("div"); bar.className = "planMetricBar"; bar.style.height = (0, PlanView_1.px)(normalizedMetric); bar.title = tooltip; planSelectorEl.appendChild(bar); parentEl.appendChild(planSelectorEl); } createPlanViews(configuration) { const planViesEl = this.planViewsEl = this.getOrCreateBlankChildElement(PLAN_VIEWS); this.plans.forEach((plan, planIndex) => this.addPlanView(plan, planIndex, planViesEl, configuration)); } addPlanView(plan, planIndex, parent, configuration) { const newPlanView = (0, PlanView_1.appendPlanView)(parent, planIndex, this.options); newPlanView.showPlan(plan, configuration); this.showSelectedPlan(planIndex); this.planViews[planIndex] = newPlanView; } showSelectedPlan(selectedPlanIndex) { this.setSelectedPlan(selectedPlanIndex); this.planViews.forEach(planView => { planView.setVisible(planView.planIndex === selectedPlanIndex); }); document.querySelectorAll("div." + PLAN_SELECTOR).forEach(div => { const planIdAsStr = div.getAttribute(PlanView_1.ATTR_PLAN); if (planIdAsStr !== null) { const planId = parseInt(planIdAsStr); if (selectedPlanIndex === planId) { div.classList.add(PLAN_SELECTOR_SELECTED); } else { div.classList.remove(PLAN_SELECTOR_SELECTED); } } else { console.warn(`planSelector element does not have the 'plan' attribute`); } }); } /** * Ensures the plan selector with the given index is visible by scrolling the plan selectors div. * @param planIndex plan selector to scroll to */ scrollPlanSelectorIntoView(planIndex) { document.querySelectorAll('div.' + PLAN_SELECTOR).forEach(div => { var _a; if (parseInt((_a = div.getAttribute(PlanView_1.ATTR_PLAN)) !== null && _a !== void 0 ? _a : "-1") === planIndex) { div.scrollIntoView(); } }); } } exports.PlansView = PlansView; function createPlansView(hostElementId, options) { const hostElement = (0, PlanView_1.getHostElement)(hostElementId); return new PlansView(hostElement, options); } exports.createPlansView = createPlansView; //# sourceMappingURL=PlansView.js.map