علاقه مند به نوآوری و استارتاپ، فعال در زمینه پرداخت الکترونیک، لندتک، تجارت الکترونیک، بازارسرمایه، دیجیتال مارکتینگ و همچنین بلاکچین و هوش مصنوعی
چارچوب بلوغ ـ ارزش محصول
تحلیل و تصمیمگیری استراتژیک برای پرتفولیوی محصولات فینتک
1. چارچوب «بلوغ ـ ارزش» محصول (Product Maturity-Value Framework)
هسته اصلی این چارچوب دو محور است که هر محصول را در یک ماتریس ۲×۲ قرار میدهد:
محور عمودی: ارزش استراتژیک و پتانسیل آینده (ترکیبی از اندازه بازار، رشد، مزیت رقابتی، تناسب با استراتژی کلان شرکت)
محور افقی: بلوغ کلی محصول (ترکیبی از ابعاد پنجگانه فناوری، بازار، درآمد، عملیات و تطبیقپذیری)
بر اساس جایگاه هر محصول، یکی از چهار استراتژی زیر اتخاذ میشود:

2. ابعاد پنجگانه ارزیابی بلوغ محصول
برای تعیین عدد بلوغ هر محصول (از ۱ تا ۵)، پنج بُعد زیر به صورت مستقل نمرهدهی میشوند. وزنها میتوانند بر اساس استراتژی شرکت تنظیم شوند (پیشنهاد اولیه در پرانتز).
الف) بلوغ فناوری (وزن ۲۵٪)
ثبات و پایداری: میزان خطاها، قطعیها، متوسط زمان بین خرابیها (MTBF)
مقیاسپذیری: توانایی پاسخگویی به رشد ۵ برابری تراکنش بدون تغییر معماری
امنیت و انطباق: سطح گواهیهای امنیتی (ISO 27001، PCI-DSS) و مقاومت در برابر نفوذ
وابستگی به زیرساخت: میزان وابستگی به سختافزار یا پلتفرم خاص
نوآوری فنی: استفاده از معماریهای نوین (میکروسرویس، ابری، پردازش رویدادی) و قابلیت توسعه سریع
راهنمای نمرهدهی (۱ تا ۵):
۱: محصول در حد MVP ناپایدار، باگهای بحرانی مکرر
۲: نمونه اولیه نسبتاً پایدار اما غیرمقیاسپذیر
۳: پایدار در بار عادی، مقیاسپذیری محدود، پوشش امنیتی نسبی
۴: مقیاسپذیر، پایدار با SLA مشخص، امنیت بالا
۵: کاملاً بالغ، ابری-بومی، با قابلیت خودترمیمی و Scale-out خودکار
ب) بلوغ بازار (وزن ۲۰٪)
سهم بازار نسبی: مقایسه با بزرگترین رقیب
نرخ رشد بازار: میانگین رشد سالانه تقاضا برای آن دسته محصول
شناخت برند و وفاداری مشتری: NPS، نرخ ریزش (Churn)، تعداد ارجاعات
شدت رقابت: تعداد رقبا و قدرت آنها، فشار قیمتگذاری
چرخه عمر بازار: آیا فناوری در حال ظهور، رشد، بلوغ یا افول است؟
نمرهدهی:
۱: محصول جدید در بازار آزموننشده، بدون مشتری پایدار
۲: مشتریان اولیه اما بازخورد ناپایدار، رقبای قوی
۳: سهم کوچک ولی وفادار، رشد بازار مثبت
۴: جایگاه تثبیتشده، برند قابل اتکا، رقابت متعادل
۵: رهبر بازار، برند غالب، جایگاه دفاعی قوی
ج) بلوغ درآمدی (وزن ۲۵٪)
سودآوری خالص: حاشیه سود پس از کسر هزینههای مستقیم و تخصیصیافته
پیشبینیپذیری جریان نقدی: درصد درآمد تکرارشونده، طول قراردادها
تنوع مشتریان: وابستگی به یک یا چند مشتری بزرگ (ریسک تمرکز)
ساختار هزینه: نسبت هزینه ثابت به متغیر، امکان کاهش هزینه در رکود
بازگشت سرمایه (ROI): مدتزمان تا بازگشت سرمایه اولیه و ارزش فعلی خالص (NPV)
نمرهدهی:
۱: زیانده، غیرقابل پیشبینی، وابسته به یک مشتری
۲: درآمد ناپایدار، حاشیه منفی، هزینه توسعه سنگین
۳: نزدیک به نقطه سر به سر، درآمدهای پراکنده
۴: سودآور با حاشیه ۲۰٪+، قراردادهای ۲-۳ ساله
۵: سودآور پایدار، جریان نقدی قابل پیشبینی، بازگشت سرمایه سریع
د) بلوغ عملیاتی (وزن ۲۰٪)
خودکارسازی پشتیبانی: درصد فرآیندهای تعمیر و نگهداری بدون دخالت انسان
هزینه پشتیبانی به ازای مشتری: روند زمانی این هزینه
کیفیت مستندات و آموزش: وجود ویدئوها، API docs، راهنماهای کاربری
مدیریت انتشار (Release): نرخ بهروزرسانی، زمان نصب نسخه جدید، توانایی Canary یا Blue-Green
سطح SLA تحققیافته: درصد تحقق تعهدات در ۱۲ ماه گذشته
نمرهدهی:
۱: ۱۰۰٪ پشتیبانی دستی، هر نصب جدید یک پروژه مجزا
۲: فرآیندهای تکراری نیمهخودکار
۳: اغلب فرآیندها مستند و قابل واگذاری، استقرار ساده
۴: عملیات عمدتاً خودکار، تیم پشتیبانی کوچک، SLA بالای ۹۹٪
۵: کاملاً خودکار، بدون نیاز به تیم اختصاصی عملیات، انتشار بدون توقف
ه) بلوغ تطبیقپذیری (وزن ۱۰٪)
انعطاف در برابر تغییرات رگولاتوری: سرعت پیادهسازی قوانین جدید (مثلاً PSD2، GDPR، مقررات بانک مرکزی)
قابلیت شخصیسازی: امکان اعمال تغییرات توسط مشتری بدون وابستگی به تیم اصلی
پلتفرمسازی: چقدر محصول میتواند به یک پلتفرم باز (Open API) تبدیل شود که دیگران روی آن سرویس بسازند؟
چابکی تیم توسعه: مدتزمان از ایده تا انتشار یک فیچر جدید
نمرهدهی:
۱: تغییرات ماهها طول میکشد، وابستگی کامل به تیم اصلی
۲: تغییرات کوچک با تأخیر زیاد، رابطهای بسته
۳: چرخههای انتشار منظم، APIهای محدود
۴: چرخه انتشار سریع، APIهای RESTful کامل، شخصیسازی مشتری
۵: چرخه انتشار چابک (هفتگی)، معماری پلاگینمحور، محصول به مثابه پلتفرم

۳. محور ارزش استراتژیک را چگونه محاسبه کنیم؟
برای اجتناب از ذهنیگرایی، ارزش استراتژیک را نیز میتوان با ترکیب چند شاخص کمّی و کیفی امتیازدهی کرد (۱ تا ۵):
تناسب با مأموریت و چشمانداز شرکت
اندازه بازار هدف (TAM) و نرخ رشد آن
مزیت رقابتی (موانع ورود، مالکیت فکری، انحصار فناورانه)
همافزایی با سایر محصولات (Cross-selling)
وابستگی اقتصاد کلان به آن (محصولات ضعیف در رکود یا غیرحساس)
به هر محصول یک عدد ارزش استراتژیک اختصاص دهید.
۴. ساختار گامبهگام جلسات تصمیمگیری
برای برگزاری یک جلسه اثربخش، این مسیر پیشنهاد میشود:
فهرستنویسی محصولات: تمام محصولات (اعم از در حال توسعه، عرضهشده، یا ایدههای جدید) را نام ببرید.
امتیازدهی سریع: هر عضو کمیته با استفاده از یک تمپلیت ساده (مثلاً یک فرم دیجیتال) به هر بُعد از ۱ تا ۵ نمره دهد.
میانگینگیری و بحث: امتیازها میانگین گرفته شود و موارد اختلاف بیش از ۱.۵ نمره بحث شوند تا به اجماع برسید.
رسم ماتریس: نقاط محصولات بر اساس (بلوغ کل، ارزش استراتژیک) روی ماتریس مشخص شوند.
تخصیص استراتژی: برای هر ربع، اقدامات از پیش تعریفشده را اعمال کنید.
تحلیل محدودیت منابع: یک گام اضافی: منابع در دسترس (بودجه، نیروی انسانی تخصصی، زیرساخت) را تخمین زده و سپس برای محصولات ستاره و علامت سؤال اولویتبندی کنید. از روش «وزندهی هزینه-فرصت» استفاده کنید – یعنی اگر منبعی را به محصول A بدهید، کدام محصول B بیشترین آسیب را میبیند؟ محصولی که با دریافت منبع، بیشترین جهش در ارزش استراتژیک یا بلوغ را ایجاد کند، در اولویت است.
۵. نمونه عملی در فضای فینتک
فرض کنید شرکت شما سه محصول دارد:
پرداختیار: یک سوئیچ پرداخت کارتخوان فروشگاهی (بلوغ فنی بالا، رشد بازار پایین، سودآور اما اشباعشده).
بلوغ کل: ۴.۵ | ارزش استراتژیک: ۲.۸ → گاو شیرده: هزینهها را بهینه کنید، نقدینگی حاصل را به محصولات دیگر تزریق کنید.
احراز هویت بیومتریک: سرویس جدید تشخیص چهره برای افتت حساب غیرحضوری (بازار در حال رشد، رقابت شدید، بلوغ عملیاتی پایین).
بلوغ کل: ۲.۳ | ارزش استراتژیک: ۴.۱ → علامت سؤال: منابع محدودی برای بلوغبخشی (استخدام DevOps، بهبود مستندات) اختصاص دهید تا آن را به ستاره تبدیل کنید.
سامانه بدهیهای کوچک (Micro-lending): نرمافزار جدید در حوزه وامهای خرد (بازار بسیار بزرگ، محصول در حد MVP، هیچ درآمدی).
بلوغ کل: ۱.۶ | ارزش استراتژیک: ۴.۷ → علامت سؤال با پتانسیل بالا: نیاز به سرمایهگذاری قابل توجه دارد؛ اما اگر منابع محدود است، میتوان آن را به فاز بعدی موکول کرد یا با شرکا توسعه داد.
سامانه قدیمی تسویه پایاپای: محصولی با معماری منسوخ، بازار رو به افول، چند مشتری محدود اما هزینه نگهداری بالا.
بلوغ کل: ۳ (فنی پایین ولی عملیاتی متوسط) | ارزش استراتژیک: ۱.۵ → خروج یا ادغام: برنامه مهاجرت مشتریان به محصول جدید و در نهایت از رده خارج کردن.
۶. لایه مکمل برای شرایط بحرانی و محدودیت شدید منابع
با توجه به وضعیت پرچالش اقتصادی، سه فیلتر را روی ماتریس نهایی اعمال کنید:
فیلتر بقا: آیا محصول جریان نقدی مثبت دارد یا ظرف ۶ ماه به آن میرسد؟ اگر خیر، قویاً حذف یا تعلیق شود، مگر آنکه ارزش استراتژیک آن بالای ۴.۵ باشد.
فیلتر چابکی: آیا محصول میتواند با ۵۰٪ کاهش منابع همچنان زنده بماند؟ محصولاتی که هزینههای ثابت سنگین دارند، در اولویت ادغام یا کوچکسازی هستند.
فیلتر تطبیق با رکود: در رکود اقتصادی، محصولاتی که به کاهش هزینه مشتریان یا افزایش بهرهوری آنها کمک میکنند، تابآورترند. به این دسته وزن بیشتری بدهید.
۷. یک الگوی سند مقایسه محصولات (بدون جدول)
برای مستندسازی خروجی جلسات، این ساختار متنی پیشنهاد میشود (برای هر محصول یک برگه مجزا):
نام محصول: …
خلاصه یک خطی: …
امتیاز بلوغ:
فناوری: ۳/۵ (دلیل: مقیاسپذیری متوسط، امنیت استاندارد)
بازار: ۲/۵ (دلیل: رشد ۱۵٪ اما رقابت وحشتناک)
درآمد: ۴/۵ (دلیل: حاشیه سود ۲۵٪ با قراردادهای ۳ ساله)
عملیاتی: ۳/۵ (دلیل: پشتیبانی نیمهخودکار، SLA حدود ۹۹.۵٪)
تطبیقپذیری: ۲/۵ (دلیل: API بسته، تغییرات زمانبر)
بلوغ کل (میانگین): ۲.۸
امتیاز ارزش استراتژیک: ۴.۱ (توضیح: بازار ۲۰۰ میلیون دلاری، مزیت رقابتی انحصاری در OCR فارسی)
موقعیت در ماتریس: علامت سؤال (ارزش بالا / بلوغ پایین)
اقدام پیشنهادی: سرمایهگذاری گزینشی به میزان ۵ میلیارد تومان در ۶ ماه آینده برای بهبود مقیاسپذیری و خودکارسازی پشتیبانی.
تحلیل ریسک منابع: اگر این سرمایهگذاری انجام نشود، محصول A (ستاره) با کمبود نقدینگی مواجه میشود؟ خیر، زیرا محصول B (گاو شیرده) مازاد نقدینگی دارد. بنابراین قابل تأمین است.
۸. جمعبندی و پیشنهاد نهایی
این چارچوب به شما امکان میدهد بهجای بحثهای پراکنده و سلیقهای، با یک منطق ساختاریافته و مبتنی بر داده، پرتفولیوی محصولات فینتکی خود را مدیریت کنید. پیشنهاد میشود:
یک تمپلیت گوگل شیت (بدون جدول بصری، بلکه با سلولهای ساده) طراحی کنید که فرمولهای میانگین و نمودار پراکندگی (Scatter Plot) خودکار داشته باشد.
هر فصل یکبار این ارزیابی را تکرار کنید، زیرا در اقتصاد پرنوسان، اعداد بلوغ و ارزش به سرعت تغییر میکنند.
ترکیب این مدل با تحلیل SWOT برای هر محصول، عمق تصمیمگیری را بیشتر میکند.
در اتنها درثورت تمایل می توانید از طریق کد HTML زیر نسبت به محاسبه و بررسی محصولات خود در یک چارچوب استاندارد اقدام نمایید.
برای این اقدام لازم است متن کد زیر را در نوت پد کپی کرده و فایل را با پسوند html ذخیره کرده و از طریق گوگل کروم یا مایکر.سافت یا هر اکسپلوره دیگری ملاحظه و مقادیر و امتیازدهی را در آن قرار دهید و در یک فضای جذاب و تعاملی به نتایج درست برای تصمیم گیری برسید.
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>چارچوب بلوغ ـ ارزش محصول</title>
<style>
:root {
--gold: #D0AF72;
--black: #1a1a1a;
--smoke: #2d2d2d;
--light-gray: #c0c0c0;
--white: #f4f4f4;
--bg: var(--black);
--card-bg: var(--smoke);
--text: var(--light-gray);
--accent: var(--gold);
--success: #4CAF50;
--warning: #FF9800;
--danger: #F44336;
--info: #2196F3;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background-color: var(--bg);
color: var(--text);
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
padding: 20px;
}
.container {
max-width: 1200px;
margin: auto;
}
header {
text-align: center;
margin-bottom: 30px;
padding: 20px;
border-bottom: 1px solid var(--accent);
}
h1 {
color: var(--accent);
font-size: 2.2rem;
margin-bottom: 10px;
}
h2, h3 {
color: var(--accent);
margin-bottom: 15px;
}
.card {
background-color: var(--card-bg);
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 4px 6px rgba(0,0,0,0.3);
}
.guide {
border-right: 4px solid var(--accent);
padding-right: 15px;
margin-bottom: 20px;
}
/* فرم افزودن محصول */
.form-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 15px;
margin-bottom: 20px;
}
.form-group {
display: flex;
flex-direction: column;
}
label {
margin-bottom: 5px;
font-weight: bold;
color: var(--accent);
}
input, select {
padding: 10px;
border: 1px solid var(--light-gray);
background-color: var(--black);
color: var(--white);
border-radius: 4px;
font-size: 1rem;
}
button {
background-color: var(--accent);
color: var(--black);
border: none;
padding: 10px 20px;
font-size: 1rem;
font-weight: bold;
border-radius: 4px;
cursor: pointer;
transition: 0.3s;
}
button:hover {
background-color: #b8943f;
}
.button-outline {
background: transparent;
border: 1px solid var(--accent);
color: var(--accent);
}
.button-outline:hover {
background: var(--accent);
color: var(--black);
}
.btn-danger {
background-color: var(--danger);
border-color: var(--danger);
}
.btn-danger:hover {
background-color: #d32f2f;
}
/* جدول محصولات */
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
font-size: 0.9rem;
}
th, td {
padding: 12px 8px;
border-bottom: 1px solid var(--accent);
text-align: center;
}
th {
background-color: var(--black);
color: var(--accent);
}
.product-actions button {
margin: 0 3px;
padding: 5px 10px;
font-size: 0.8rem;
}
/* بخش نمودار */
.chart-container {
width: 100%;
aspect-ratio: 16/9;
max-height: 500px;
position: relative;
}
svg {
width: 100%;
height: 100%;
}
.chart-tooltip {
position: absolute;
background: var(--card-bg);
border: 1px solid var(--accent);
padding: 10px;
border-radius: 5px;
pointer-events: none;
font-size: 0.9rem;
color: var(--white);
display: none;
z-index: 10;
}
/* بخش وزنها */
.weights-section {
display: flex;
flex-wrap: wrap;
gap: 15px;
align-items: center;
}
.weight-input {
width: 80px;
}
.error {
color: var(--danger);
font-size: 0.9rem;
margin-top: 5px;
}
.quadrant-legend {
display: flex;
justify-content: center;
gap: 15px;
margin: 10px 0;
flex-wrap: wrap;
}
.legend-item {
display: flex;
align-items: center;
gap: 5px;
}
.legend-color {
width: 15px;
height: 15px;
border-radius: 50%;
display: inline-block;
}
/* فوتر */
footer {
margin-top: 40px;
padding: 20px;
background-color: var(--smoke);
border-radius: 8px;
text-align: center;
color: var(--accent);
font-size: 0.9rem;
display: flex;
justify-content: center;
align-items: center;
gap: 15px;
flex-wrap: wrap;
box-shadow: 0 -2px 4px rgba(0,0,0,0.3);
}
footer a {
color: var(--gold);
text-decoration: none;
border-bottom: 1px dotted var(--gold);
transition: 0.3s;
}
footer a:hover {
color: #fff;
border-bottom-color: #fff;
}
@media (max-width: 700px) {
.form-grid {
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>چارچوب بلوغ ـ ارزش محصول</h1>
<p>تحلیل و تصمیمگیری استراتژیک برای پرتفولیوی محصولات فینتک</p>
</header>
<!-- راهنما -->
<div class="card guide">
<h2>راهنمای استفاده</h2>
<p>۱. وزنهای دلخواه برای هر بعد بلوغ را تنظیم کنید (پیشفرض منطبق بر مدل استاندارد است).</p>
<p>۲. برای هر محصول، امتیاز (۱ تا ۵) در پنج بُعد بلوغ و ارزش استراتژیک را وارد کنید.</p>
<p>۳. با کلیک روی «افزودن محصول»، محصول به لیست و نمودار اضافه میشود.</p>
<p>۴. محصولات بر اساس بلوغ کل (میانگین وزنی) و ارزش استراتژیک در ماتریس قرار میگیرند و توصیه مناسب صادر میشود.</p>
<p>۵. میتوانید محصولات را ویرایش یا حذف کنید.</p>
</div>
<!-- بخش وزنها -->
<div class="card">
<h2>وزنهای ابعاد بلوغ (مجموع باید ۱۰۰ باشد)</h2>
<div class="weights-section" id="weightsContainer">
<div class="form-group">
<label>فناوری (%): <input type="number" class="weight-input" id="weightTech" value="25" min="0" max="100" step="1"></label>
</div>
<div class="form-group">
<label>بازار (%): <input type="number" class="weight-input" id="weightMarket" value="20" min="0" max="100" step="1"></label>
</div>
<div class="form-group">
<label>درآمد (%): <input type="number" class="weight-input" id="weightRevenue" value="25" min="0" max="100" step="1"></label>
</div>
<div class="form-group">
<label>عملیات (%): <input type="number" class="weight-input" id="weightOps" value="20" min="0" max="100" step="1"></label>
</div>
<div class="form-group">
<label>تطبیقپذیری (%): <input type="number" class="weight-input" id="weightAdapt" value="10" min="0" max="100" step="1"></label>
</div>
<span id="weightError" class="error"></span>
</div>
</div>
<!-- فرم افزودن محصول -->
<div class="card">
<h2>افزودن / ویرایش محصول</h2>
<div class="form-grid">
<div class="form-group">
<label>نام محصول:</label>
<input type="text" id="productName" placeholder="مثال: پرداختیار">
</div>
<div class="form-group">
<label>بلوغ فناوری (1-5):</label>
<input type="number" id="techScore" min="1" max="5" step="0.1" value="3">
</div>
<div class="form-group">
<label>بلوغ بازار (1-5):</label>
<input type="number" id="marketScore" min="1" max="5" step="0.1" value="3">
</div>
<div class="form-group">
<label>بلوغ درآمد (1-5):</label>
<input type="number" id="revenueScore" min="1" max="5" step="0.1" value="3">
</div>
<div class="form-group">
<label>بلوغ عملیات (1-5):</label>
<input type="number" id="opsScore" min="1" max="5" step="0.1" value="3">
</div>
<div class="form-group">
<label>تطبیقپذیری (1-5):</label>
<input type="number" id="adaptScore" min="1" max="5" step="0.1" value="3">
</div>
<div class="form-group">
<label>ارزش استراتژیک (1-5):</label>
<input type="number" id="strategicValue" min="1" max="5" step="0.1" value="3">
</div>
<div style="display: flex; align-items: flex-end;">
<button id="addProductBtn" style="height: 40px; margin-right: 10px;">افزودن محصول</button>
<button id="updateProductBtn" class="button-outline" style="height: 40px; display: none;">بهروزرسانی</button>
<button id="cancelUpdateBtn" class="button-outline btn-danger" style="height: 40px; display: none;">لغو</button>
</div>
<input type="hidden" id="editingIndex" value="-1">
</div>
<div id="formError" class="error"></div>
</div>
<!-- جدول محصولات -->
<div class="card">
<h2>محصولات ثبتشده</h2>
<div id="productsTableContainer">
<p>هنوز محصولی ثبت نشده است.</p>
</div>
</div>
<!-- نمودار ماتریس -->
<div class="card">
<h2>نمودار ماتریس بلوغ ـ ارزش</h2>
<div class="quadrant-legend">
<div class="legend-item"><span class="legend-color" style="background: #2196F3;"></span> ستارهها (سرمایهگذاری تهاجمی)</div>
<div class="legend-item"><span class="legend-color" style="background: #FF9800;"></span> پتانسیل بالا (سرمایهگذاری گزینشی)</div>
<div class="legend-item"><span class="legend-color" style="background: #4CAF50;"></span> گاو شیرده (بهینهسازی و برداشت)</div>
<div class="legend-item"><span class="legend-color" style="background: #F44336;"></span> خروج/ادغام</div>
</div>
<div class="chart-container" id="chartContainer">
<svg id="chartSvg" viewBox="0 0 600 400"></svg>
<div class="chart-tooltip" id="chartTooltip"></div>
</div>
<p style="margin-top:10px; font-size:0.9rem;">* محور افقی: بلوغ کل (۱ تا ۵) | محور عمودی: ارزش استراتژیک (۱ تا ۵) | خطوط تقسیم در ۳.۰</p>
</div>
<!-- فوتر جدید -->
<footer>
<span>تهیهکننده: <strong>Hadi Behzadi</strong></span>
<span>|</span>
<a href="https://virgool.io/@hadibehzadi">مشاهدهی این مطلب در ویرگول</>">با احترام</a>
</footer>
</div>
(function() {
// ---------- دادهها ----------
let products = [];
const defaultWeights = { tech: 25, market: 20, revenue: 25, ops: 20, adapt: 10 };
let weights = { ...defaultWeights };
// ---------- المانهای DOM ----------
const weightTech = document.getElementById('weightTech');
const weightMarket = document.getElementById('weightMarket');
const weightRevenue = document.getElementById('weightRevenue');
const weightOps = document.getElementById('weightOps');
const weightAdapt = document.getElementById('weightAdapt');
const weightError = document.getElementById('weightError');
const productName = document.getElementById('productName');
const techScore = document.getElementById('techScore');
const marketScore = document.getElementById('marketScore');
const revenueScore = document.getElementById('revenueScore');
const opsScore = document.getElementById('opsScore');
const adaptScore = document.getElementById('adaptScore');
const strategicValue = document.getElementById('strategicValue');
const addProductBtn = document.getElementById('addProductBtn');
const updateProductBtn = document.getElementById('updateProductBtn');
const cancelUpdateBtn = document.getElementById('cancelUpdateBtn');
const editingIndex = document.getElementById('editingIndex');
const formError = document.getElementById('formError');
const productsTableContainer = document.getElementById('productsTableContainer');
const chartContainer = document.getElementById('chartContainer');
const chartSvg = document.getElementById('chartSvg');
const chartTooltip = document.getElementById('chartTooltip');
// ---------- توابع کمکی ----------
function validateWeights() {
const w = [
parseFloat(weightTech.value) || 0,
parseFloat(weightMarket.value) || 0,
parseFloat(weightRevenue.value) || 0,
parseFloat(weightOps.value) || 0,
parseFloat(weightAdapt.value) || 0
];
const sum = w.reduce((a, b) => a + b, 0);
if (Math.abs(sum - 100) > 0.01) {
weightError.textContent = 'مجموع وزنها باید دقیقاً ۱۰۰ باشد. (فعلی: ' + sum + ')';
return false;
} else {
weightError.textContent = '';
weights = { tech: w[0], market: w[1], revenue: w[2], ops: w[3], adapt: w[4] };
return true;
}
}
function getWeightsArray() {
return [weights.tech, weights.market, weights.revenue, weights.ops, weights.adapt];
}
function calculateMaturity(scores) {
const w = getWeightsArray();
let total = 0;
for (let i = 0; i < 5; i++) {
total += scores[i] * w[i];
}
return total / 100;
}
function getQuadrant(maturity, value) {
if (maturity >= 3.0 && value >= 3.0) return 'star';
if (maturity < 3.0 && value >= 3.0) return 'question';
if (maturity >= 3.0 && value < 3.0) return 'cashcow';
return 'dog';
}
function getRecommendation(quadrant) {
switch (quadrant) {
case 'star': return 'ستاره: سرمایهگذاری تهاجمی برای حفظ رهبری';
case 'question': return 'پتانسیل بالا: سرمایهگذاری گزینشی برای عبور از شکاف بلوغ';
case 'cashcow': return 'گاو شیرده: بهینهسازی هزینه و برداشت نقدینگی';
case 'dog': return 'خروج/ادغام: کاهش سرمایهگذاری یا خروج از بازار';
default: return '';
}
}
function getQuadrantColor(quadrant) {
switch (quadrant) {
case 'star': return '#2196F3';
case 'question': return '#FF9800';
case 'cashcow': return '#4CAF50';
case 'dog': return '#F44336';
default: return '#ffffff';
}
}
// ---------- بهروزرسانی نمایش ----------
function renderProductsTable() {
if (products.length === 0) {
productsTableContainer = '<p>هنوز محصولی ثبت نشده است.</p>';
return;
}
let html = `
<table>
<thead>
<tr>
<th>نام محصول</th>
<th>فناوری</th>
<th>بازار</th>
<th>درآمد</th>
<th>عملیات</th>
<th>تطبیقپذیری</th>
<th>بلوغ کل</th>
<th>ارزش استراتژیک</th>
<th>موقعیت</th>
<th>عملیات</th>
</tr>
</thead>
<tbody>`;
products.forEach((p, idx) => {
const maturity = calculateMaturity(p.scores);
const quadrant = getQuadrant(maturity, p.strategicValue);
const rec = getRecommendation(quadrant);
const color = getQuadrantColor(quadrant);
html += `
<tr>
<td>${escapeHtml(p.name)}</td>
<td>${p.scores[0].toFixed(1)}</td>
<td>${p.scores[1].toFixed(1)}</td>
<td>${p.scores[2].toFixed(1)}</td>
<td>${p.scores[3].toFixed(1)}</td>
<td>${p.scores[4].toFixed(1)}</td>
<td>${maturity.toFixed(2)}</td>
<td>${p.strategicValue.toFixed(1)}</td>
<td style="color: ${color}; font-weight: bold;">${rec}</td>
<td class="product-actions">
<button class="button-outline" ="window.editProduct(${idx})">ویرایش</button>
<button class="btn-danger" ="window.deleteProduct(${idx})">حذف</button>
</td>
</tr>`;
});
html += '</tbody></table>';
productsTableContainer = html;
}
function escapeHtml(text) {
const map = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
return text.replace(/[&<>"']/g, m => map[m]);
}
function drawChart() {
const svg = chartSvg;
svg = '';
const width = 600;
const height = 400;
const margin = { top: 20, right: 20, bottom: 40, left: 50 };
const plotWidth = width - margin.left - margin.right;
const plotHeight = height - margin.top - margin.bottom;
const xScale = d => margin.left + ((d - 1) / (5 - 1)) * plotWidth;
const yScale = d => margin.top + plotHeight - ((d - 1) / (5 - 1)) * plotHeight;
// خطوط محور
const xAxisLine = document.createElementNS("http://www.w3.org/2000/svg", "line");
xAxisLine.setAttribute("x1", margin.left);
xAxisLine.setAttribute("y1", yScale(1));
xAxisLine.setAttribute("x2", margin.left + plotWidth);
xAxisLine.setAttribute("y2", yScale(1));
xAxisLine.setAttribute("stroke", "#c0c0c0");
xAxisLine.setAttribute("stroke-width", "2");
svg(xAxisLine);
const yAxisLine = document.createElementNS("http://www.w3.org/2000/svg", "line");
yAxisLine.setAttribute("x1", margin.left);
yAxisLine.setAttribute("y1", yScale(5));
yAxisLine.setAttribute("x2", margin.left);
yAxisLine.setAttribute("y2", yScale(1));
yAxisLine.setAttribute("stroke", "#c0c0c0");
yAxisLine.setAttribute("stroke-width", "2");
svg(yAxisLine);
// برچسبها و شبکه
for (let i = 1; i <= 5; i++) {
const xLabel = document.createElementNS("http://www.w3.org/2000/svg", "text");
xLabel.setAttribute("x", xScale(i));
xLabel.setAttribute("y", yScale(1) + 20);
xLabel.setAttribute("fill", "#c0c0c0");
xLabel.setAttribute("text-anchor", "middle");
xLabel.setAttribute("font-size", "12");
xLabel.textContent = i;
svg(xLabel);
const yLabel = document.createElementNS("http://www.w3.org/2000/svg", "text");
yLabel.setAttribute("x", margin.left - 10);
yLabel.setAttribute("y", yScale(i) + 5);
yLabel.setAttribute("fill", "#c0c0c0");
yLabel.setAttribute("text-anchor", "end");
yLabel.setAttribute("font-size", "12");
yLabel.textContent = i;
svg(yLabel);
if (i > 1 && i < 5) {
const hLine = document.createElementNS("http://www.w3.org/2000/svg", "line");
hLine.setAttribute("x1", margin.left);
hLine.setAttribute("y1", yScale(i));
hLine.setAttribute("x2", margin.left + plotWidth);
hLine.setAttribute("y2", yScale(i));
hLine.setAttribute("stroke", "#4a4a4a");
hLine.setAttribute("stroke-width", "1");
hLine.setAttribute("stroke-dasharray", "4,4");
svg(hLine);
const vLine = document.createElementNS("http://www.w3.org/2000/svg", "line");
vLine.setAttribute("x1", xScale(i));
vLine.setAttribute("y1", yScale(5));
vLine.setAttribute("x2", xScale(i));
vLine.setAttribute("y2", yScale(1));
vLine.setAttribute("stroke", "#4a4a4a");
vLine.setAttribute("stroke-width", "1");
vLine.setAttribute("stroke-dasharray", "4,4");
svg(vLine);
}
}
// خطوط تقسیم ماتریس
const midX = xScale(3);
const midY = yScale(3);
const splitLineX = document.createElementNS("http://www.w3.org/2000/svg", "line");
splitLineX.setAttribute("x1", margin.left);
splitLineX.setAttribute("y1", midY);
splitLineX.setAttribute("x2", margin.left + plotWidth);
splitLineX.setAttribute("y2", midY);
splitLineX.setAttribute("stroke", "#D0AF72");
splitLineX.setAttribute("stroke-width", "1.5");
splitLineX.setAttribute("stroke-dasharray", "6,3");
svg(splitLineX);
const splitLineY = document.createElementNS("http://www.w3.org/2000/svg", "line");
splitLineY.setAttribute("x1", midX);
splitLineY.setAttribute("y1", yScale(5));
splitLineY.setAttribute("x2", midX);
splitLineY.setAttribute("y2", yScale(1));
splitLineY.setAttribute("stroke", "#D0AF72");
splitLineY.setAttribute("stroke-width", "1.5");
splitLineY.setAttribute("stroke-dasharray", "6,3");
svg(splitLineY);
// رسم نقاط محصولات
products.forEach((p, idx) => {
const maturity = calculateMaturity(p.scores);
const x = xScale(maturity);
const y = yScale(p.strategicValue);
const quadrant = getQuadrant(maturity, p.strategicValue);
const color = getQuadrantColor(quadrant);
const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
circle.setAttribute("cx", x);
circle.setAttribute("cy", y);
circle.setAttribute("r", "7");
circle.setAttribute("fill", color);
circle.setAttribute("stroke", "#fff");
circle.setAttribute("stroke-width", "1.5");
circle.setAttribute("data-index", idx);
circle.style.cursor = "pointer";
circle.addEventListener("mouseenter", showTooltip);
circle.addEventListener("mouseleave", hideTooltip);
circle.addEventListener("click", (e) => {
const i = parseInt(e.target.getAttribute("data-index"));
if (!isNaN(i)) editProduct(i);
});
svg(circle);
const text = document.createElementNS("http://www.w3.org/2000/svg", "text");
text.setAttribute("x", x + 10);
text.setAttribute("y", y - 5);
text.setAttribute("fill", "#fff");
text.setAttribute("font-size", "11");
text.style.pointerEvents = "none";
text.textContent = p.name.length > 8 ? p.name.substring(0,8)+'..' : p.name;
svg(text);
});
// عناوین محورها
const xAxisTitle = document.createElementNS("http://www.w3.org/2000/svg", "text");
xAxisTitle.setAttribute("x", margin.left + plotWidth / 2);
xAxisTitle.setAttribute("y", yScale(1) + 38);
xAxisTitle.setAttribute("fill", "#D0AF72");
xAxisTitle.setAttribute("text-anchor", "middle");
xAxisTitle.setAttribute("font-size", "13");
xAxisTitle.textContent = "بلوغ کل →";
svg(xAxisTitle);
const yAxisTitle = document.createElementNS("http://www.w3.org/2000/svg", "text");
yAxisTitle.setAttribute("x", margin.left - 40);
yAxisTitle.setAttribute("y", margin.top + plotHeight / 2);
yAxisTitle.setAttribute("fill", "#D0AF72");
yAxisTitle.setAttribute("text-anchor", "middle");
yAxisTitle.setAttribute("font-size", "13");
yAxisTitle.setAttribute("transform", rotate(-90, ${margin.left - 40}, ${margin.top + plotHeight / 2}));
yAxisTitle.textContent = "ارزش استراتژیک →";
svg(yAxisTitle);
}
function showTooltip(e) {
const idx = parseInt(e.target.getAttribute("data-index"));
if (isNaN(idx) || idx < 0 || idx >= products.length) return;
const p = products[idx];
const maturity = calculateMaturity(p.scores);
const quadrant = getQuadrant(maturity, p.strategicValue);
const rec = getRecommendation(quadrant);
const html = `
<strong>${escapeHtml(p.name)}</strong><br>
بلوغ: ${maturity.toFixed(2)}<br>
ارزش: ${p.strategicValue.toFixed(1)}<br>
<span style="color:${getQuadrantColor(quadrant)}">${rec}</span>
`;
chartTooltip = html;
chartTooltip.style.display = 'block';
positionTooltip(e);
}
function hideTooltip() {
chartTooltip.style.display = 'none';
}
function positionTooltip(e) {
const containerRect = chartContainer.getBoundingClientRect();
const x = e.clientX - containerRect.left + 15;
const y = e.clientY - containerRect.top - 60;
chartTooltip.style.left = Math.min(x, containerRect.width - 200) + 'px';
chartTooltip.style.top = Math.max(y, 10) + 'px';
}
chartContainer.addEventListener('mousemove', (e) => {
if (chartTooltip.style.display === 'block') {
positionTooltip(e);
}
});
// ---------- مدیریت فرم ----------
function clearForm() {
productName.value = '';
techScore.value = '3';
marketScore.value = '3';
revenueScore.value = '3';
opsScore.value = '3';
adaptScore.value = '3';
strategicValue.value = '3';
editingIndex.value = '-1';
addProductBtn.style.display = 'inline-block';
updateProductBtn.style.display = 'none';
cancelUpdateBtn.style.display = 'none';
formError.textContent = '';
}
function getScoresArray() {
return [
parseFloat(techScore.value),
parseFloat(marketScore.value),
parseFloat(revenueScore.value),
parseFloat(opsScore.value),
parseFloat(adaptScore.value)
];
}
function validateScores() {
const scores = getScoresArray();
for (let s of scores) {
if (isNaN(s) || s < 1 || s > 5) return false;
}
const val = parseFloat(strategicValue.value);
if (isNaN(val) || val < 1 || val > 5) return false;
if (productName.value.trim() === '') return false;
return true;
}
function addOrUpdateProduct() {
if (!validateWeights()) return;
if (!validateScores()) {
formError.textContent = 'لطفاً تمام امتیازها را بین ۱ تا ۵ وارد کنید و نام محصول را مشخص کنید.';
return;
}
formError.textContent = '';
const product = {
name: productName.value.trim(),
scores: getScoresArray(),
strategicValue: parseFloat(strategicValue.value)
};
const index = parseInt(editingIndex.value);
if (index >= 0 && index < products.length) {
products[index] = product;
} else {
products.push(product);
}
updateAll();
clearForm();
}
function editProduct(index) {
if (index < 0 || index >= products.length) return;
const p = products[index];
productName.value = p.name;
techScore.value = p.scores[0];
marketScore.value = p.scores[1];
revenueScore.value = p.scores[2];
opsScore.value = p.scores[3];
adaptScore.value = p.scores[4];
strategicValue.value = p.strategicValue;
editingIndex.value = index;
addProductBtn.style.display = 'none';
updateProductBtn.style.display = 'inline-block';
cancelUpdateBtn.style.display = 'inline-block';
formError.textContent = '';
validateWeights();
}
function deleteProduct(index) {
if (confirm('آیا از حذف این محصول اطمینان دارید؟')) {
products.splice(index, 1);
updateAll();
if (parseInt(editingIndex.value) === index) {
clearForm();
} else if (parseInt(editingIndex.value) > index) {
editingIndex.value = parseInt(editingIndex.value) - 1;
}
}
}
function cancelUpdate() {
clearForm();
}
function updateAll() {
renderProductsTable();
drawChart();
}
// اتصال رویدادها
addProductBtn.addEventListener('click', addOrUpdateProduct);
updateProductBtn.addEventListener('click', addOrUpdateProduct);
cancelUpdateBtn.addEventListener('click', cancelUpdate);
const weightInputs = [weightTech, weightMarket, weightRevenue, weightOps, weightAdapt];
weightInputs.forEach(inp => inp.addEventListener('input', () => {
validateWeights();
updateAll();
}));
window.editProduct = editProduct;
window.deleteProduct = deleteProduct;
validateWeights();
updateAll();
})();
</body>
</html>
مطلبی دیگر از این انتشارات
معماری ارزشآفرینی: چارچوب جامع مدیریت پروژههای فناوری از ایده تا توسعه مستمر در هلدینگهای پیچیده
مطلبی دیگر از این انتشارات
مدل ارزشآفرینی Bain & Company: نگاهی جامع
مطلبی دیگر از این انتشارات
معماری سازمانی فدرال (FEA) چیست؟