• דף הבית
    • אינדקס קישורים
    • פוסטים אחרונים
    • משתמשים
    • חיפוש בהגדרות המתקדמות
    • חיפוש גוגל בפורום
    • ניהול המערכת
    • ניהול המערכת - שרת private
    • הרשמה
    • התחברות

    למה אין נתונים לקווים? 🤔

    מתוזמן נעוץ נעול הועבר נפתר בקשות לפיתוח
    38 פוסטים 6 כותבים 128 צפיות 4 עוקבים
    טוען פוסטים נוספים
    • מהישן לחדש
    • מהחדש לישן
    • הכי הרבה הצבעות
    תגובה
    • תגובה כנושא
    התחברו כדי לפרסם תגובה
    נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
    • ק מנותק
      קו המוסיקה @BEN ZION
      נערך לאחרונה על ידי

      @BEN-ZION סמתי את זה בקובץ ivr
      האם זה בסדר?

      B תגובה 1 תגובה אחרונה תגובה ציטוט 0
      • B מנותק
        BEN ZION @קו המוסיקה
        נערך לאחרונה על ידי

        @קו-המוסיקה נראה לי שלא אבל אני לא יודע

        תגובה 1 תגובה אחרונה תגובה ציטוט 0
        • א מחובר
          אA @BEN ZION
          נערך לאחרונה על ידי אA

          @BEN-ZION
          בטעות תייגתי אותך
          @קו-המוסיקה

          יצרתי לך קובץ html לניתוח הנתונים.
          אשמח שתיתן עליו הערות והארות לשידרוג

          <!DOCTYPE html>
          <html lang="he" dir="rtl">
          <head>
              <meta charset="UTF-8">
              <title>ניתוח נתוני מערכות | v23</title>
              <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
              <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
              <style>
                  :root { --bg: #0f172a; --card: #1e293b; --primary: #38bdf8; --accent: #22c55e; --text: #f1f5f9; --border: #334155; --danger: #ef4444; --warning: #f59e0b; }
                  body { font-family: 'Segoe UI', sans-serif; background: var(--bg); color: var(--text); margin: 0; display: flex; flex-direction: column; height: 100vh; }
                  
                  header { background: #1e293b; padding: 1rem 2rem; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--border); box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1); }
                  .logo-box { display: flex; align-items: center; gap: 12px; }
                  .logo-icon { background: linear-gradient(135deg, var(--primary), #0ea5e9); color: #0f172a; width: 40px; height: 40px; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 1.2rem; box-shadow: 0 0 15px rgba(56, 189, 248, 0.4); }
                  .logo-text { font-size: 1.4rem; font-weight: 800; color: var(--text); letter-spacing: -0.5px; }
          
                  .config-box { display: flex; gap: 12px; align-items: center; }
                  input[type="date"]::-webkit-calendar-picker-indicator { filter: invert(1); cursor: pointer; }
                  input, select { background: #0f172a; border: 1px solid var(--border); color: white; padding: 10px; border-radius: 8px; outline: none; transition: 0.2s; }
                  .btn-run { background: var(--primary); color: #0f172a; border: none; padding: 10px 25px; border-radius: 8px; font-weight: bold; cursor: pointer; transition: 0.3s; }
                  
                  .nav-tabs { background: #1e293b; display: flex; padding: 0 20px; border-bottom: 1px solid var(--border); }
                  .tab { padding: 15px 25px; cursor: pointer; color: #94a3b8; border-bottom: 3px solid transparent; transition: 0.3s; font-weight: 500; }
                  .tab.active { color: var(--primary); border-bottom-color: var(--primary); background: rgba(56, 189, 248, 0.07); }
          
                  .main-content { flex: 1; padding: 25px; overflow-y: auto; background: #0f172a; }
                  .card { background: var(--card); padding: 25px; border-radius: 16px; border: 1px solid var(--border); margin-bottom: 25px; box-shadow: 0 10px 15px -3px rgba(0,0,0,0.1); }
                  .stat-num { font-size: 2.5rem; font-weight: 800; color: var(--primary); }
                  
                  .control-bar { display: flex; gap: 20px; align-items: center; background: #334155; padding: 15px 25px; border-radius: 12px 12px 0 0; border: 1px solid var(--border); border-bottom: none; }
                  .search-input { background: #0f172a; border: 1px solid var(--border); color: white; padding: 8px 15px; border-radius: 8px; width: 250px; outline: none; }
          
                  table { width: 100%; border-collapse: collapse; background: var(--card); border-radius: 0 0 12px 12px; overflow: hidden; border: 1px solid var(--border); }
                  th { text-align: right; padding: 15px; background: #475569; color: white; font-weight: 600; font-size: 0.85rem; }
                  td { padding: 15px; border-bottom: 1px solid var(--border); font-size: 0.95rem; }
                  tr:hover { background: rgba(255,255,255,0.02); }
          
                  .bar-container { width: 100px; background: #0f172a; height: 10px; border-radius: 10px; display: inline-block; overflow: hidden; vertical-align: middle; border: 1px solid var(--border); margin-left: 8px; }
                  .bar-fill { height: 100%; background: var(--accent); border-radius: 10px; }
                  
                  #debug-console { background: #000; color: #22c55e; font-family: 'Courier New', monospace; padding: 20px; height: 350px; overflow-y: auto; border-radius: 12px; border: 1px solid #22c55e; line-height: 1.6; }
                  .progress-container { width: 100%; background: #1e293b; height: 6px; display: none; }
                  #progress-fill { height: 100%; background: var(--primary); width: 0%; transition: 0.4s; box-shadow: 0 0 10px var(--primary); }
                  
                  .live-status { display: flex; align-items: center; gap: 6px; font-size: 0.75rem; font-weight: bold; padding: 4px 10px; border-radius: 20px; background: #334155; }
                  .dot { width: 8px; height: 8px; border-radius: 50%; background: #666; }
                  .dot.active { background: var(--accent); box-shadow: 0 0 8px var(--accent); animation: pulse 2s infinite; }
                  @keyframes pulse { 0% { opacity: 1; } 50% { opacity: 0.4; } 100% { opacity: 1; } }
                  .hidden { display: none; }
              </style>
          </head>
          <body>
          
          <header>
              <div class="logo-box">
                  <div class="logo-icon"><i class="fas fa-chart-bar"></i></div>
                  <div class="logo-text">ניתוח נתוני מערכות</div>
                  <div class="live-status"><div id="live-dot" class="dot"></div> <span id="live-text">OFFLINE</span></div>
              </div>
              <div class="config-box">
                  <input type="password" id="apiToken" placeholder="טוקן API">
                  <input type="date" id="startDate">
                  <input type="date" id="endDate">
                  <button class="btn-run" onclick="manualStart()">הפעל ניתוח</button>
              </div>
          </header>
          
          <div class="progress-container" id="progBar"><div id="progress-fill"></div></div>
          
          <div class="nav-tabs">
              <div class="tab active" onclick="switchTab(event, 'dash-tab')"><i class="fas fa-th-large"></i> דאשבורד</div>
              <div class="tab" onclick="switchTab(event, 'ext-tab')"><i class="fas fa-folder-tree"></i> שלוחות</div>
              <div class="tab" onclick="switchTab(event, 'play-tab')"><i class="fas fa-play-circle"></i> השמעות</div>
              <div class="tab" onclick="switchTab(event, 'users-tab')"><i class="fas fa-users"></i> מאזינים</div>
              <div class="tab" style="color: var(--warning)" onclick="switchTab(event, 'debug-tab')"><i class="fas fa-terminal"></i> לוג</div>
          </div>
          
          <div class="main-content">
              <div id="dash-tab" class="tab-content">
                  <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 25px; margin-bottom: 25px;">
                      <div class="card"><span style="color: #94a3b8">מאזינים ייחודיים</span><br><span id="stat-users" class="stat-num">0</span></div>
                      <div class="card"><span style="color: #94a3b8">סה"כ דקות האזנה</span><br><span id="stat-min" class="stat-num">0</span></div>
                      <div class="card"><span style="color: #94a3b8">שיחות שהושלמו</span><br><span id="stat-comp" class="stat-num">0</span></div>
                  </div>
                  <div class="card"><h3>גרף פעילות יומי</h3><canvas id="dailyChart" height="100"></canvas></div>
              </div>
          
              <div id="ext-tab" class="tab-content hidden">
                  <div class="control-bar">
                      <label>מיון:</label>
                      <select id="extSort" onchange="renderExts()"><option value="count">כמות כניסות</option><option value="sec">זמן שהייה</option></select>
                      <input type="text" id="extSearch" class="search-input" placeholder="חפש שלוחה..." onkeyup="renderExts()">
                  </div>
                  <table id="extTable"><thead><tr><th>שם השלוחה</th><th>כניסות</th><th>דקות שהייה</th><th>ממוצע לשהייה</th></tr></thead><tbody></tbody></table>
              </div>
          
              <div id="play-tab" class="tab-content hidden">
                  <div class="control-bar">
                      <label>מיון:</label>
                      <select id="playSort" onchange="renderPlays()"><option value="count">פופולריות</option><option value="pct">אחוז השלמה</option></select>
                      <input type="text" id="playSearch" class="search-input" placeholder="חפש קובץ / שלוחה..." onkeyup="renderPlays()">
                  </div>
                  <table id="playTable"><thead><tr><th>שם קובץ / שלוחה</th><th>השמעות</th><th>סה"כ דקות</th><th>אחוז השלמה ממוצע</th><th>שיעור נטישה</th></tr></thead><tbody></tbody></table>
              </div>
          
              <div id="users-tab" class="tab-content hidden">
                  <div class="control-bar">
                      <label>מיון:</label>
                      <select id="userSort" onchange="renderUsers()"><option value="sec">זמן האזנה כולל</option><option value="calls">מספר שיחות גבוה</option></select>
                      <input type="text" id="userSearch" class="search-input" placeholder="חפש טלפון..." onkeyup="renderUsers()">
                  </div>
                  <table id="usersTable"><thead><tr><th>מספר טלפון</th><th>דקות האזנה</th><th>מספר שיחות</th><th>סטטוס</th></tr></thead><tbody></tbody></table>
              </div>
          
              <div id="debug-tab" class="tab-content hidden"><div class="card"><div id="debug-console"></div></div></div>
          </div>
          
          <script>
              const API = "https://www.call2all.co.il/ym/api/";
              let dataStore = { exts: {}, plays: {}, users: {}, daily: {}, totalSec: 0, completed: 0 };
              let dailyChart = null;
              let autoRefreshTimer = null;
          
              function addLog(msg, color = '#22c55e') {
                  const console = document.getElementById('debug-console');
                  const div = document.createElement('div');
                  div.style.color = color;
                  div.innerHTML = `<span style="color:#555">[${new Date().toLocaleTimeString()}]</span> ${msg}`;
                  console.appendChild(div);
                  console.scrollTop = console.scrollHeight;
              }
          
              function cleanExt(val) {
                  if (!val) return "ראשית";
                  let s = val.toString().trim().replace(/^\ufeff/, "");
                  if (s === "" || s === "/" || s === "." || s.toLowerCase() === "root" || s.toLowerCase() === "main") return "ראשית";
                  return s;
              }
          
              function parseSec(t) {
                  if (!t) return 0;
                  if (t.toString().includes(':')) {
                      const p = t.split(':').map(Number);
                      return p.length === 3 ? (p[0]*3600)+(p[1]*60)+p[2] : (p[0]*60)+p[1];
                  }
                  return parseInt(t) || 0;
              }
          
              async function manualStart() {
                  if(autoRefreshTimer) clearInterval(autoRefreshTimer);
                  await startFullAnalysis();
                  document.getElementById('live-dot').classList.add('active');
                  document.getElementById('live-text').innerText = "LIVE (עדכון כל דקה)";
                  autoRefreshTimer = setInterval(startFullAnalysis, 60000); 
              }
          
              async function startFullAnalysis() {
                  const token = document.getElementById('apiToken').value;
                  const start = document.getElementById('startDate').value;
                  const end = document.getElementById('endDate').value;
                  if (!token) return alert("הזן טוקן API");
          
                  addLog("מרענן נתונים...", "#38bdf8");
                  dataStore = { exts: {}, plays: {}, users: {}, daily: {}, totalSec: 0, completed: 0 };
                  document.getElementById('progBar').style.display = 'block';
          
                  const month = start.substring(0, 7);
                  try {
                      const res = await fetch(`${API}RenderYMGRFile?token=${token}&wath=ivr2:/Log/LogFolderEnterExit-${month}.ymgr&convertType=json`);
                      const json = await res.json();
                      if (json.data) {
                          json.data.forEach(row => {
                              const ext = cleanExt(row["שלוחה"]);
                              const sec = parseSec(row["זמן כולל בשלוחה"]);
                              if (!dataStore.exts[ext]) dataStore.exts[ext] = { count: 0, sec: 0 };
                              dataStore.exts[ext].count++;
                              dataStore.exts[ext].sec += sec;
                          });
                      }
                  } catch(e) { addLog("שגיאה בטעינת שלוחות", "red"); }
          
                  let dates = [];
                  for(let d=new Date(start); d<=new Date(end); d.setDate(d.getDate()+1)) dates.push(new Date(d).toISOString().split('T')[0]);
          
                  for (let day of dates) {
                      updateProgress(dates.indexOf(day)+1, dates.length);
                      try {
                          const res = await fetch(`${API}RenderYMGRFile?token=${token}&wath=ivr2:/Log/LogPlaybackPlayStop/LogPlaybackPlayStop.${day}.ymgr&convertType=json`);
                          const json = await res.json();
                          if (json.data) {
                              if (!dataStore.daily[day]) dataStore.daily[day] = 0;
                              json.data.forEach(row => {
                                  const file = row["השמעה"] || "לא ידוע";
                                  const phone = row["טלפון"] || "חסוי";
                                  const sec = parseInt(row["סה\"כ שניות"]) || 0;
                                  const len = parseSec(row["אורך הקובץ"]);
                                  const isEnd = row["נקודת יציאה"] === "סוף";
                                  
                                  dataStore.daily[day]++;
                                  dataStore.totalSec += sec;
                                  if (isEnd) dataStore.completed++;
          
                                  if (!dataStore.users[phone]) dataStore.users[phone] = { sec: 0, calls: 0 };
                                  dataStore.users[phone].sec += sec;
                                  dataStore.users[phone].calls++;
          
                                  if (!dataStore.plays[file]) dataStore.plays[file] = { count: 0, sec: 0, drops: 0, pcts: [] };
                                  dataStore.plays[file].count++;
                                  dataStore.plays[file].sec += sec;
                                  dataStore.plays[file].pcts.push(len > 0 ? Math.min(100, Math.round((sec/len)*100)) : 0);
                                  if (!isEnd) dataStore.plays[file].drops++;
                              });
                          }
                      } catch(e) {}
                  }
                  renderUI();
              }
          
              function renderUI() {
                  document.getElementById('progBar').style.display = 'none';
                  document.getElementById('stat-users').innerText = Object.keys(dataStore.users).length.toLocaleString();
                  document.getElementById('stat-min').innerText = Math.floor(dataStore.totalSec / 60).toLocaleString();
                  document.getElementById('stat-comp').innerText = dataStore.completed.toLocaleString();
                  renderExts();
                  renderPlays();
                  renderUsers();
                  updateChart();
              }
          
              function renderExts() {
                  const sort = document.getElementById('extSort').value;
                  const q = document.getElementById('extSearch').value.toLowerCase();
                  let items = Object.entries(dataStore.exts).map(([name, d]) => ({name, ...d}))
                      .filter(i => i.name.toLowerCase().includes(q));
                  items.sort((a,b) => b[sort] - a[sort]);
                  document.querySelector('#extTable tbody').innerHTML = items.map(i => `
                      <tr><td style="color:var(--primary); font-weight:600">${i.name}</td><td>${i.count.toLocaleString()}</td><td>${(i.sec/60).toFixed(1)}</td><td>${i.count ? Math.round(i.sec/i.count) : 0} ש'</td></tr>
                  `).join('');
              }
          
              function renderPlays() {
                  const sort = document.getElementById('playSort').value;
                  const q = document.getElementById('playSearch').value.toLowerCase();
                  let items = Object.entries(dataStore.plays).map(([name, d]) => {
                      const avg = d.pcts.length ? Math.round(d.pcts.reduce((a,b)=>a+b,0)/d.pcts.length) : 0;
                      const dropRate = Math.round((d.drops/d.count)*100);
                      return {name, avg, dropRate, ...d};
                  }).filter(i => i.name.toLowerCase().includes(q));
                  items.sort((a,b) => sort === 'count' ? b.count - a.count : b.avg - a.avg);
                  document.querySelector('#playTable tbody').innerHTML = items.map(i => `
                      <tr><td>${i.name}</td><td>${i.count}</td><td>${(i.sec/60).toFixed(1)}</td>
                      <td><div class="bar-container"><div class="bar-fill" style="width:${i.avg}%"></div></div> <b>${i.avg}%</b></td>
                      <td style="color:${i.dropRate > 50 ? 'var(--danger)' : 'var(--accent)'}; font-weight:bold">${i.dropRate}%</td></tr>
                  `).join('');
              }
          
              function renderUsers() {
                  const sortKey = document.getElementById('userSort').value;
                  const q = document.getElementById('userSearch').value;
                  let items = Object.entries(dataStore.users).map(([phone, d]) => ({phone, ...d}))
                      .filter(i => i.phone.includes(q));
                  items.sort((a,b) => b[sortKey] - a[sortKey]);
                  document.querySelector('#usersTable tbody').innerHTML = items.map((i, idx) => `
                      <tr><td style="font-weight:bold">${i.phone}</td><td style="color:var(--primary); font-weight:bold">${(i.sec/60).toFixed(1)}</td><td>${i.calls}</td><td>${idx < 3 ? '🏆 מוביל' : 'מאזין'}</td></tr>
                  `).join('');
              }
          
              function updateChart() {
                  if (dailyChart) dailyChart.destroy();
                  const ctx = document.getElementById('dailyChart').getContext('2d');
                  dailyChart = new Chart(ctx, {
                      type: 'line',
                      data: { labels: Object.keys(dataStore.daily), datasets: [{ label: 'שיחות', data: Object.values(dataStore.daily), borderColor: '#38bdf8', tension: 0.4, fill: true, backgroundColor: 'rgba(56, 189, 248, 0.1)' }] },
                      options: { plugins: { legend: { display: false } }, scales: { y: { beginAtZero: true } } }
                  });
              }
          
              function updateProgress(c, t) { document.getElementById('progress-fill').style.width = (c/t*100) + '%'; }
              function switchTab(e, id) {
                  document.querySelectorAll('.tab-content').forEach(c => c.classList.add('hidden'));
                  document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
                  document.getElementById(id).classList.remove('hidden');
                  e.currentTarget.classList.add('active');
              }
              document.getElementById('startDate').value = document.getElementById('endDate').value = new Date().toISOString().split('T')[0];
          </script>
          </body>
          </html>
          
          ק תגובה 1 תגובה אחרונה תגובה ציטוט 0
          • ק מנותק
            קו המוסיקה @אA
            נערך לאחרונה על ידי

            @אA
            אין שום נתונים, או שהבעיה אצלי ששמרתי את הזה ששומר את הlog ב ivr...
            Screenshot 2026-04-05 at 19.37.13.png

            C תגובה 1 תגובה אחרונה תגובה ציטוט 0
            • C מנותק
              CUBASE @קו המוסיקה
              נערך לאחרונה על ידי

              @קו-המוסיקה לא אמורה להיות בעיה בהגדרת השלוחה ב-ivr.ini

              ק תגובה 1 תגובה אחרונה תגובה ציטוט 0
              • ק מנותק
                קו המוסיקה @CUBASE
                נערך לאחרונה על ידי

                @CUBASE ככה חשבתי,
                גם בגלל שראיתי בשלוחה את הנתונים האלה,
                אז @אa זה לא עובד...

                א תגובה 1 תגובה אחרונה תגובה ציטוט 0
                • א מחובר
                  אA @קו המוסיקה
                  נערך לאחרונה על ידי

                  @קו-המוסיקה
                  זה מוגדר שלוקח את הנתונים מהקבצים שבתקיית הלוג.
                  אצלי זה עבד מצויין.
                  וההגדרה עצמה לא קשרוה לקבצי הלוג.

                  תגובה 1 תגובה אחרונה תגובה ציטוט 0
                  • L מנותק
                    lavitoren הטי"ל @קו המוסיקה
                    נערך לאחרונה על ידי lavitoren הטי"ל

                    פוסט זה נמחק!
                    א תגובה 1 תגובה אחרונה תגובה ציטוט 0
                    • א מחובר
                      אA @lavitoren הטי"ל
                      נערך לאחרונה על ידי

                      @lavitoren-הטי-ל
                      מאיפה הבאת את זה?

                      L תגובה 1 תגובה אחרונה תגובה ציטוט 0
                      • L מנותק
                        lavitoren הטי"ל @אA
                        נערך לאחרונה על ידי

                        @אA ארגון מסוים אני עובד שם נראה לי שזה של שניאור אבל הוא לא אמר לא לפרסם או שזה פרטי ואגב אתה זריז
                        אבל מאוד(??)🤔

                        א תגובה 1 תגובה אחרונה תגובה ציטוט 1
                        • א מחובר
                          אA @lavitoren הטי"ל
                          נערך לאחרונה על ידי

                          @lavitoren-הטי-ל
                          תודה על המחמאה, אבל מה זה ה? בסוף?🤔
                          בכל מקרה בדיוק הייתי על השירשור וכתבתי תגובה...

                          ק תגובה 1 תגובה אחרונה תגובה ציטוט 0
                          • ק מנותק
                            קו המוסיקה @אA
                            נערך לאחרונה על ידי

                            @אA @lavitoren-הטי-ל
                            לא יודע מה בדיוק פיספסתי,
                            אבל אממ... יש למשהו הסבר למה זה לא עובד לי עכשיו,
                            אולי זה לא צבר מספיק נתונים יש כזה דבר?
                            כי אני מנסה לחשוב על משהו שיכול להיות בעיייתי ולא מוצא...

                            א תגובה 1 תגובה אחרונה תגובה ציטוט 0
                            • א מחובר
                              אA @קו המוסיקה
                              נערך לאחרונה על ידי

                              @קו-המוסיקה
                              יש קבצי לוג בתקיית הלוג?
                              הכנסת מספר מערכת:סיסמא תקינים?

                              תגובה 1 תגובה אחרונה תגובה ציטוט 0
                              • פוסט ראשון
                                פוסט אחרון