diff --git a/poster/assets/app.js b/poster/assets/app.js new file mode 100644 index 0000000..8131d40 --- /dev/null +++ b/poster/assets/app.js @@ -0,0 +1,772 @@ +(() => { + const THEME_KEY = 'simpm-poster-theme'; + const LANG_KEY = 'simpm-poster-lang'; + const rootEl = document.documentElement; + + const translations = { + en: { + 'doc.title': 'SimPM — Simulation Tool in Project Management (Interactive Poster)', + 'doc.description': 'Interactive research poster for SimPM: a process-based discrete-event simulation library for project and construction management in Python.', + + 'header.exhibition': 'Research Exhibition Poster', + 'header.university': 'K. N. Toosi University of Technology', + 'header.title': 'SimPM — Simulation Tool in Project Management', + 'header.subtitle': + 'SimPM is a process-based discrete-event simulation library for modeling projects and\n construction operations in Python—with built-in logging, schedule-friendly\n probability distributions, and optional Dash dashboards.', + + 'badge.python': 'Python', + 'badge.des': 'Process-based DES', + 'badge.dist': 'Schedule distributions', + 'badge.logs': 'Tabular logging', + 'badge.dashboard': 'Optional dashboards', + + 'nav.overview': 'Overview', + 'nav.blocks': 'Building Blocks', + 'nav.workflow': 'Workflow', + 'nav.modeling': 'Modeling', + 'nav.engine': 'Engine', + 'nav.outputs': 'Outputs', + 'nav.examples': 'Examples', + + 'overview.title': 'Overview', + 'overview.subtitle': 'A project-focused discrete-event simulation toolkit for studying duration risk, bottlenecks, and resource plans.', + 'overview.what.title': 'What it does', + 'overview.what.li1': 'Model activities as processes (generator functions) that request resources and do work.', + 'overview.what.li2': 'Represent crews/equipment as resources with capacity, priorities, and (optionally) preemption.', + 'overview.what.li3': 'Use distributions (triangular, beta, empirical, …) for realistic task durations.', + 'overview.what.li4': 'Produce tables for schedules, queues, waiting times, and utilization—plus optional dashboards.', + 'overview.poster.title': 'Interactive poster', + 'overview.poster.li1': 'Click any figure (diagram/code) to zoom and read the caption.', + 'overview.poster.li2': 'Use the sticky navigation to jump between panels.', + 'overview.poster.li3': 'All figures are generated (Mermaid) to stay lightweight.', + + 'blocks.title': 'Building blocks', + 'blocks.subtitle': 'SimPM maps core DES ideas to practical project-management objects.', + 'blocks.list.title': 'Core objects', + 'blocks.list.li1': 'Environment: simulation clock + event scheduler (e.g., env.now).', + 'blocks.list.li2': 'Entity: a work item (task, truck, activity) with attributes and a schedule.', + 'blocks.list.li3': 'Resource: crew/equipment/workspace capacity with queueing and logging.', + 'blocks.list.li4': 'Distributions: duration uncertainty passed directly to Entity.do.', + 'blocks.figures.title': 'Figures', + + 'workflow.title': 'Workflow', + 'workflow.subtitle': 'Write a model in Python → run the environment → analyze logs → (optionally) open a dashboard.', + 'workflow.tip': 'Tip: switch themes to see the Mermaid figures re-render.', + + 'modeling.title': 'Modeling: activities, resources, distributions', + 'modeling.subtitle': 'Model logic using get/do/put; add priority or preemption when needed.', + 'modeling.patterns.title': 'Common patterns', + 'modeling.patterns.li1': 'Resource contention: entities queue when capacity is unavailable.', + 'modeling.patterns.li2': 'Priorities: urgent tasks jump ahead in the queue.', + 'modeling.patterns.li3': 'Preemption: high-priority work can interrupt lower-priority usage.', + 'modeling.figures.title': 'Figures', + + 'engine.title': 'Engine: process-based DES', + 'engine.subtitle': 'Processes yield actions; the environment advances time from event to event.', + 'engine.why.title': 'Why DES', + 'engine.why.li1': 'Efficiently represents queues and limited crews without stepping through every second.', + 'engine.why.li2': 'Supports stochastic durations for schedule risk and Monte Carlo experiments.', + 'engine.why.li3': 'Produces explicit waiting/working intervals, enabling bottleneck analysis.', + 'engine.figures.title': 'Figures', + + 'outputs.title': 'Outputs: logs and dashboards', + 'outputs.subtitle': 'SimPM produces pandas-friendly tables for schedules and resource performance; dashboards are optional.', + + 'examples.title': 'Examples', + 'examples.subtitle': 'Minimal activity, distributions, and dashboard mode.', + 'examples.install.title': 'Install', + 'examples.install.tip': 'Use the extra to enable Plotly Dash dashboards.', + 'examples.figures.title': 'Code figures', + + 'footer.built': 'Built for offline exhibition display. Use the sticky navigation for fast jumps.', + + 'lightbox.title': 'Figure', + 'lightbox.close': 'Close (Esc)', + + 'theme.light': 'Light', + 'theme.dark': 'Dark', + 'theme.toLight': 'Switch to light theme', + 'theme.toDark': 'Switch to dark theme', + + 'lang.en': 'EN', + 'lang.fa': 'FA', + 'lang.toEnglish': 'Switch to English', + 'lang.toPersian': 'Switch to Persian' + }, + fa: { + 'doc.title': 'SimPM — ابزار شبیه\u000cسازی در مدیریت پروژه (پوستر تعاملی)'.replaceAll('\u000c', '\u200c'), + 'doc.description': 'پوستر پژوهشی تعاملی برای SimPM: یک کتابخانهٔ شبیه\u000cسازی گسسته\u000cرویداد مبتنی بر فرایند برای مدیریت پروژه و ساخت در پایتون.'.replaceAll('\u000c', '\u200c'), + + 'header.exhibition': 'پوستر نمایشگاه پژوهشی', + 'header.university': 'دانشگاه صنعتی خواجه نصیرالدین طوسی', + 'header.title': 'SimPM — ابزار شبیه\u000cسازی در مدیریت پروژه'.replaceAll('\u000c', '\u200c'), + 'header.subtitle': + 'SimPM یک کتابخانهٔ شبیه\u000cسازی گسسته\u000cرویداد مبتنی بر فرایند برای مدل\u000cسازی پروژه\u000cها و عملیات ساخت در Python است؛\n با ثبت رخدادها، توزیع\u000cهای احتمالی مناسب برنامه\u000cزمان\u000cبندی و داشبوردهای Dash (اختیاری).'.replaceAll('\u000c', '\u200c'), + + 'badge.python': 'Python', + 'badge.des': 'DES مبتنی بر فرایند'.replaceAll('\u000c', '\u200c'), + 'badge.dist': 'توزیع\u000cهای زمانی'.replaceAll('\u000c', '\u200c'), + 'badge.logs': 'ثبت جدولی'.replaceAll('\u000c', '\u200c'), + 'badge.dashboard': 'داشبورد (اختیاری)'.replaceAll('\u000c', '\u200c'), + + 'nav.overview': 'مرور', + 'nav.blocks': 'اجزای اصلی', + 'nav.workflow': 'گردش\u000cکار'.replaceAll('\u000c', '\u200c'), + 'nav.modeling': 'مدل\u000cسازی'.replaceAll('\u000c', '\u200c'), + 'nav.engine': 'موتور', + 'nav.outputs': 'خروجی\u000cها'.replaceAll('\u000c', '\u200c'), + 'nav.examples': 'مثال\u000cها'.replaceAll('\u000c', '\u200c'), + + 'overview.title': 'مرور', + 'overview.subtitle': 'یک ابزار شبیه\u000cسازی گسسته\u000cرویداد با تمرکز بر پروژه برای مطالعه ریسک زمان\u000cبندی، گلوگاه\u000cها و برنامه منابع.'.replaceAll('\u000c', '\u200c'), + 'overview.what.title': 'چه کاری انجام می\u000cدهد'.replaceAll('\u000c', '\u200c'), + 'overview.what.li1': 'فعالیت\u000cها را به\u000cصورت فرایند (تابع\u000cهای مولد) مدل می\u000cکند که منابع را درخواست کرده و کار انجام می\u000cدهند.'.replaceAll('\u000c', '\u200c'), + 'overview.what.li2': 'اکیپ\u000cها/تجهیزات را به\u000cصورت منبع با ظرفیت، اولویت و (در صورت نیاز) پیش\u000cدستی مدل می\u000cکند.'.replaceAll('\u000c', '\u200c'), + 'overview.what.li3': 'برای مدت\u000cزمان فعالیت\u000cها از توزیع\u000cهای احتمالی (مثلثی، بتا، تجربی و …) استفاده می\u000cکند.'.replaceAll('\u000c', '\u200c'), + 'overview.what.li4': 'برای برنامه، صف، زمان انتظار و بهره\u000cبرداری جدول\u000cهای تحلیلی تولید می\u000cکند؛ به\u000cهمراه داشبورد اختیاری.'.replaceAll('\u000c', '\u200c'), + 'overview.poster.title': 'پوستر تعاملی'.replaceAll('\u000c', '\u200c'), + 'overview.poster.li1': 'روی هر شکل (نمودار/کد) کلیک کنید تا بزرگ\u000cنمایی شود و توضیح آن را بخوانید.'.replaceAll('\u000c', '\u200c'), + 'overview.poster.li2': 'از ناوبری چسبان برای جابه\u000cجایی سریع بین بخش\u000cها استفاده کنید.'.replaceAll('\u000c', '\u200c'), + 'overview.poster.li3': 'برای سبک بودن، شکل\u000cها با Mermaid تولید می\u000cشوند.'.replaceAll('\u000c', '\u200c'), + + 'blocks.title': 'اجزای اصلی', + 'blocks.subtitle': 'SimPM مفاهیم DES را به اشیای عملی در مدیریت پروژه تبدیل می\u000cکند.'.replaceAll('\u000c', '\u200c'), + 'blocks.list.title': 'اشیای کلیدی', + 'blocks.list.li1': 'Environment: ساعت شبیه\u000cسازی و زمان\u000cبند رخدادها (مثل env.now).'.replaceAll('\u000c', '\u200c'), + 'blocks.list.li2': 'Entity: یک قلم کار (فعالیت، کامیون، بسته کاری) با ویژگی\u000cها و برنامه.'.replaceAll('\u000c', '\u200c'), + 'blocks.list.li3': 'Resource: ظرفیت اکیپ/تجهیزات/فضا با صف و ثبت رخداد.'.replaceAll('\u000c', '\u200c'), + 'blocks.list.li4': 'Distributions: عدم قطعیت مدت\u000cزمان که مستقیم به Entity.do داده می\u000cشود.'.replaceAll('\u000c', '\u200c'), + 'blocks.figures.title': 'شکل\u000cها'.replaceAll('\u000c', '\u200c'), + + 'workflow.title': 'گردش\u000cکار'.replaceAll('\u000c', '\u200c'), + 'workflow.subtitle': 'مدل\u000cسازی در پایتون → اجرای محیط → تحلیل لاگ\u000cها → (اختیاری) داشبورد.'.replaceAll('\u000c', '\u200c'), + 'workflow.tip': 'نکته: با تغییر تم، شکل\u000cهای Mermaid دوباره رندر می\u000cشوند.'.replaceAll('\u000c', '\u200c'), + + 'modeling.title': 'مدل\u000cسازی: فعالیت\u000cها، منابع، توزیع\u000cها'.replaceAll('\u000c', '\u200c'), + 'modeling.subtitle': 'منطق را با get/do/put بنویسید؛ در صورت نیاز اولویت/پیش\u000cدستی اضافه کنید.'.replaceAll('\u000c', '\u200c'), + 'modeling.patterns.title': 'الگوهای رایج', + 'modeling.patterns.li1': 'رقابت منابع: وقتی ظرفیت آزاد نیست، موجودیت\u000cها در صف می\u000cمانند.'.replaceAll('\u000c', '\u200c'), + 'modeling.patterns.li2': 'اولویت: کارهای فوری در صف جلوتر قرار می\u000cگیرند.'.replaceAll('\u000c', '\u200c'), + 'modeling.patterns.li3': 'پیش\u000cدستی: کار با اولویت بالا می\u000cتواند استفادهٔ با اولویت پایین را قطع کند.'.replaceAll('\u000c', '\u200c'), + 'modeling.figures.title': 'شکل\u000cها'.replaceAll('\u000c', '\u200c'), + + 'engine.title': 'موتور: DES مبتنی بر فرایند'.replaceAll('\u000c', '\u200c'), + 'engine.subtitle': 'فرایندها عمل\u000cها را yield می\u000cکنند و محیط زمان را از رخداد به رخداد جلو می\u000cبرد.'.replaceAll('\u000c', '\u200c'), + 'engine.why.title': 'چرا DES'.replaceAll('\u000c', '\u200c'), + 'engine.why.li1': 'صف\u000cها و اکیپ\u000cهای محدود را بدون شبیه\u000cسازی هر ثانیه مدل می\u000cکند.'.replaceAll('\u000c', '\u200c'), + 'engine.why.li2': 'برای تحلیل ریسک و مونت\u000cکارلو از مدت\u000cزمان\u000cهای تصادفی پشتیبانی می\u000cکند.'.replaceAll('\u000c', '\u200c'), + 'engine.why.li3': 'بازه\u000cهای انتظار/کار را صریح تولید می\u000cکند و تحلیل گلوگاه را ممکن می\u000cسازد.'.replaceAll('\u000c', '\u200c'), + 'engine.figures.title': 'شکل\u000cها'.replaceAll('\u000c', '\u200c'), + + 'outputs.title': 'خروجی\u000cها: لاگ\u000cها و داشبورد'.replaceAll('\u000c', '\u200c'), + 'outputs.subtitle': 'SimPM جدول\u000cهای سازگار با pandas برای برنامه و عملکرد منابع تولید می\u000cکند؛ داشبورد اختیاری است.'.replaceAll('\u000c', '\u200c'), + + 'examples.title': 'مثال\u000cها'.replaceAll('\u000c', '\u200c'), + 'examples.subtitle': 'فعالیت حداقلی، توزیع\u000cها و حالت داشبورد.'.replaceAll('\u000c', '\u200c'), + 'examples.install.title': 'نصب', + 'examples.install.tip': 'برای فعال شدن داشبورد، افزونهٔ dash را نصب کنید.'.replaceAll('\u000c', '\u200c'), + 'examples.figures.title': 'شکل\u000cهای کد'.replaceAll('\u000c', '\u200c'), + + 'footer.built': 'برای نمایش آفلاین ساخته شده است. از ناوبری چسبان برای پرش سریع استفاده کنید.'.replaceAll('\u000c', '\u200c'), + + 'lightbox.title': 'شکل', + 'lightbox.close': 'بستن (Esc)', + + 'theme.light': 'روشن'.replaceAll('\u000c', '\u200c'), + 'theme.dark': 'تیره'.replaceAll('\u000c', '\u200c'), + 'theme.toLight': 'تغییر به حالت روشن'.replaceAll('\u000c', '\u200c'), + 'theme.toDark': 'تغییر به حالت تیره'.replaceAll('\u000c', '\u200c'), + + 'lang.en': 'EN', + 'lang.fa': 'FA', + 'lang.toEnglish': 'تغییر به انگلیسی'.replaceAll('\u000c', '\u200c'), + 'lang.toPersian': 'تغییر به فارسی'.replaceAll('\u000c', '\u200c') + } + }; + + function getCurrentLang() { + const lang = rootEl.dataset.lang; + return (lang === 'fa' || lang === 'en') ? lang : 'en'; + } + + function normalizeHalfSpaces(text) { + return String(text).replaceAll('\u000c', '\u200c'); + } + + function t(key) { + const lang = getCurrentLang(); + const value = translations[lang]?.[key] ?? translations.en[key] ?? ''; + return normalizeHalfSpaces(value); + } + + function getStoredTheme() { + try { + const value = localStorage.getItem(THEME_KEY); + return (value === 'light' || value === 'dark') ? value : null; + } catch { + return null; + } + } + + function getSystemTheme() { + try { + return (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) ? 'dark' : 'light'; + } catch { + return 'dark'; + } + } + + function setStoredTheme(theme) { + try { + localStorage.setItem(THEME_KEY, theme); + } catch { + // ignore + } + } + + function applyHighlightTheme(theme) { + const isDark = theme === 'dark'; + const darkLink = document.getElementById('hljs-dark'); + const lightLink = document.getElementById('hljs-light'); + if (darkLink) darkLink.disabled = !isDark; + if (lightLink) lightLink.disabled = isDark; + } + + function applyTheme(theme) { + rootEl.dataset.theme = theme; + applyHighlightTheme(theme); + + const btn = document.getElementById('themeToggle'); + if (btn) { + const isDark = theme === 'dark'; + btn.setAttribute('aria-pressed', isDark ? 'true' : 'false'); + btn.textContent = isDark ? t('theme.dark') : t('theme.light'); + btn.title = isDark ? t('theme.toLight') : t('theme.toDark'); + } + } + + function getStoredLang() { + try { + const value = localStorage.getItem(LANG_KEY); + return (value === 'en' || value === 'fa') ? value : null; + } catch { + return null; + } + } + + function setStoredLang(lang) { + try { + localStorage.setItem(LANG_KEY, lang); + } catch { + // ignore + } + } + + function updateDocumentStrings() { + document.title = t('doc.title'); + const meta = document.querySelector('meta[name="description"]'); + if (meta) meta.setAttribute('content', t('doc.description')); + } + + function applyI18nToDom() { + for (const el of document.querySelectorAll('[data-i18n]')) { + const key = el.getAttribute('data-i18n'); + if (!key) continue; + el.textContent = t(key); + } + for (const el of document.querySelectorAll('[data-i18n-html]')) { + const key = el.getAttribute('data-i18n-html'); + if (!key) continue; + el.innerHTML = t(key); + } + } + + function updateLangButton() { + const btn = document.getElementById('langToggle'); + if (!btn) return; + const lang = getCurrentLang(); + btn.setAttribute('aria-pressed', lang === 'fa' ? 'true' : 'false'); + btn.textContent = lang === 'fa' ? t('lang.fa') : t('lang.en'); + btn.title = lang === 'fa' ? t('lang.toEnglish') : t('lang.toPersian'); + } + + function applyLanguage(lang) { + const safe = (lang === 'fa' || lang === 'en') ? lang : 'en'; + rootEl.dataset.lang = safe; + rootEl.lang = safe; + rootEl.dir = safe === 'fa' ? 'rtl' : 'ltr'; + updateDocumentStrings(); + applyI18nToDom(); + updateLangButton(); + applyTheme((rootEl.dataset.theme === 'light' || rootEl.dataset.theme === 'dark') ? rootEl.dataset.theme : 'dark'); + } + + // Mermaid helpers + function getMermaidTheme() { + const theme = (rootEl.dataset.theme === 'light') ? 'light' : 'dark'; + // Mermaid themes: 'default'|'dark'|'neutral'|'forest'|'base' + return theme === 'dark' ? 'dark' : 'default'; + } + + function initMermaid() { + if (!window.mermaid) return; + try { + window.mermaid.initialize({ + startOnLoad: false, + securityLevel: 'loose', + theme: getMermaidTheme() + }); + } catch { + // ignore + } + } + + let mermaidCounter = 0; + + async function renderMermaidToSvg(diagramText) { + if (!window.mermaid) { + return 'Mermaid failed to load.'; + } + + mermaidCounter += 1; + const id = `m-${Date.now()}-${mermaidCounter}`; + + // Ensure theme tracks current UI + try { + window.mermaid.initialize({ startOnLoad: false, securityLevel: 'loose', theme: getMermaidTheme() }); + } catch { + // ignore + } + + const { svg } = await window.mermaid.render(id, diagramText); + return svg; + } + + function svgToElement(svgString) { + const parser = new DOMParser(); + const doc = parser.parseFromString(svgString, 'image/svg+xml'); + return doc.documentElement; + } + + function safeSerializeSvg(svgEl) { + // Drop potentially problematic + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +
+
Research Exhibition Poster
+
K. N. Toosi University of Technology
+
+
+ +
+ +
+

SimPM — Simulation Tool in Project Management

+

+ SimPM is a process-based discrete-event simulation library for modeling projects and + construction operations in Python—with built-in logging, schedule-friendly + probability distributions, and optional Dash dashboards. +

+
+ Python + Process-based DES + Schedule distributions + Tabular logging + Optional dashboards +
+
+
+
+ + + +
+
+ +
+
+
+

Overview

+

A project-focused discrete-event simulation toolkit for studying duration risk, bottlenecks, and resource plans.

+
+
+
+
+
+

What it does

+
    +
  • Model activities as processes (generator functions) that request resources and do work.
  • +
  • Represent crews/equipment as resources with capacity, priorities, and (optionally) preemption.
  • +
  • Use distributions (triangular, beta, empirical, …) for realistic task durations.
  • +
  • Produce tables for schedules, queues, waiting times, and utilization—plus optional dashboards.
  • +
+
+
+

Interactive poster

+
    +
  • Click any figure (diagram/code) to zoom and read the caption.
  • +
  • Use the sticky navigation to jump between panels.
  • +
  • All figures are generated (Mermaid) to stay lightweight.
  • +
+
+
+
+
+ +
+
+
+

Building blocks

+

SimPM maps core DES ideas to practical project-management objects.

+
+
+
+
+
+

Core objects

+
    +
  • Environment: simulation clock + event scheduler (e.g., env.now).
  • +
  • Entity: a work item (task, truck, activity) with attributes and a schedule.
  • +
  • Resource: crew/equipment/workspace capacity with queueing and logging.
  • +
  • Distributions: duration uncertainty passed directly to Entity.do.
  • +
+
+
+

Figures

+
+
+
+
+
+ +
+
+
+

Workflow

+

Write a model in Python → run the environment → analyze logs → (optionally) open a dashboard.

+
+
+
+
+ +
+
+ +
+
+
+

Modeling: activities, resources, distributions

+

Model logic using get/do/put; add priority or preemption when needed.

+
+
+
+
+
+

Common patterns

+
    +
  • Resource contention: entities queue when capacity is unavailable.
  • +
  • Priorities: urgent tasks jump ahead in the queue.
  • +
  • Preemption: high-priority work can interrupt lower-priority usage.
  • +
+
+
+

Figures

+
+
+
+
+
+ +
+
+
+

Engine: process-based DES

+

Processes yield actions; the environment advances time from event to event.

+
+
+
+
+
+

Why DES

+
    +
  • Efficiently represents queues and limited crews without stepping through every second.
  • +
  • Supports stochastic durations for schedule risk and Monte Carlo experiments.
  • +
  • Produces explicit waiting/working intervals, enabling bottleneck analysis.
  • +
+
+
+

Figures

+
+
+
+
+
+ +
+
+
+

Outputs: logs and dashboards

+

SimPM produces pandas-friendly tables for schedules and resource performance; dashboards are optional.

+
+
+
+
+
+
+ +
+
+
+

Examples

+

Minimal activity, distributions, and dashboard mode.

+
+
+
+
+
+

Install

+
pip install simpm
+pip install simpm[dash]
+ +
+
+

Code figures

+
+
+
+
+
+ + + +
+
+ + + + + + +