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 '';
+ }
+
+ 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.
+