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

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

    מתוזמן נעוץ נעול הועבר נפתר בקשות לפיתוח
    26 פוסטים 5 כותבים 47 צפיות 3 עוקבים
    טוען פוסטים נוספים
    • מהישן לחדש
    • מהחדש לישן
    • הכי הרבה הצבעות
    תגובה
    • תגובה כנושא
    התחברו כדי לפרסם תגובה
    נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
    • ק מנותק
      קו המוסיקה
      נערך לאחרונה על ידי

      אני זוכר שכתבתי על הנושא הזה כבר לפני כמה חודשים, אבל לא הייתה היענות מספקת 😕 ולכן אני מעלה את זה שוב.
      לדעתי, לכל מי שמפעיל קו שמכיל תוכן 📞🎧 – זה דבר חשוב מאוד.

      הכוונה היא לאפשר גישה לנתונים מלאים ומפורטים 📊, כמו למשל:

      אילו קבצים מקבלים את אחוזי ההאזנה הגבוהים ביותר 🔝
      כמות ההאזנות לכל קובץ 🎶 (שאת זה אפשר לבדוק חלקית כבר היום)
      אילו שלוחות הכי מואזנות בקו 📂
      לאילו שלוחות נכנסים הכי הרבה 👥

      בקיצור – מערכת שמרכזת נתונים סטטיסטיים מלאים וברורים על פעילות המשתמשים בקו 📈

      אני אישית מאוד הייתי רוצה לפתח משהו כזה 💻, אבל אין לי מספיק ידע בתחום הפיתוח 😅
      אולי אם כמה אנשים כאן ישתפו פעולה וירימו את זה יחד 🤝 – זה יכול להועיל מאוד לכולנו, במיוחד למי שמנהל קווי תוכן 🙌

      אם כבר קיים פתרון כזה – אשמח מאוד לשמוע עליו 🔍
      ובכל מקרה, אשמח לכל תגובה או מחשבה בנושא 💬
      לדעתי זה נושא חשוב מאוד! 🚀

      א ק 2 תגובות תגובה אחרונה תגובה ציטוט 1
      • ק קו המוסיקה סימן נושא זה כשאלה
      • B מנותק
        BEN ZION @565906
        נערך לאחרונה על ידי

        @קו-המוסיקה @אa @565906
        מצורף קוד HTML בסיסי ניתן לשדרג עוד
        אין לי במערכת לוג האזנה אז אני לא יודע איך עובד נראה טוב
        יש לו באג שאין לי כוח כרגע לתקן שבציון דקות שהם מעל רף של דקות נתין לבחור כמה דקות הוא מציין בשיחות מתחת לרף כל מעבר בשלוחה שלא התעכבו בה את הרף
        עוד לא מצאתי איך לחשב לפי שיחה אולי בהמשך אני אשדרג

        <!DOCTYPE html>
        <html lang="he" dir="rtl">
        <head>
          <meta charset="UTF-8" />
          <meta name="viewport" content="width=device-width, initial-scale=1.0" />
          <title>מערכת סיכום דקות מתקדמת - ימות המשיח</title>
          <style>
            body { font-family: Arial, sans-serif; background: #f0f2f5; margin: 0; padding: 20px; color: #333; }
            .container { max-width: 1200px; margin: auto; background: #fff; padding: 25px; border-radius: 15px; box-shadow: 0 8px 30px rgba(0,0,0,0.1); }
            h1 { margin-top: 0; color: #1a4388; text-align: center; border-bottom: 2px solid #eee; padding-bottom: 15px; }
            
            .setup-panel { background: #f8fafc; padding: 20px; border-radius: 12px; border: 1px solid #e2e8f0; margin-bottom: 20px; display: flex; flex-wrap: wrap; gap: 15px; align-items: flex-end; }
            .input-group { display: flex; flex-direction: column; gap: 5px; }
            label { font-weight: bold; font-size: 14px; }
            input, select { padding: 10px; border: 1px solid #cbd5e1; border-radius: 8px; font-size: 14px; }
            
            button { border: none; background: #1a4388; color: #fff; padding: 10px 20px; border-radius: 8px; cursor: pointer; font-weight: bold; transition: background 0.2s; }
            button:hover { background: #133266; }
            button.secondary { background: #10b981; }
            button.secondary:hover { background: #059669; }
        
            .summary-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 15px; margin-bottom: 20px; }
            .card { background: #fff; padding: 15px; border-radius: 10px; border: 1px solid #e2e8f0; box-shadow: 0 2px 4px rgba(0,0,0,0.02); text-align: center; }
            .card .val { font-size: 22px; font-weight: bold; color: #1a4388; display: block; margin-bottom: 5px; }
            .card .lbl { font-size: 13px; color: #64748b; font-weight: bold; }
        
            .tabs { display: flex; gap: 10px; margin-bottom: 15px; border-bottom: 2px solid #e2e8f0; padding-bottom: 10px; display: none; }
            .tab-btn { background: #e2e8f0; color: #333; padding: 10px 15px; border-radius: 8px; cursor: pointer; font-weight: bold; border: none; }
            .tab-btn.active { background: #1a4388; color: #fff; }
            
            .tab-content { display: none; }
            .tab-content.active { display: block; }
        
            .grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
            @media (max-width: 768px) { .grid-2 { grid-template-columns: 1fr; } }
        
            .table-container { overflow-x: auto; max-height: 400px; border: 1px solid #e2e8f0; border-radius: 10px; margin-bottom: 20px; background: #fff;}
            table { width: 100%; border-collapse: collapse; text-align: right; }
            th { position: sticky; top: 0; background: #1a4388; color: white; padding: 10px; font-size: 14px; }
            td { padding: 10px; border-bottom: 1px solid #f1f5f9; font-size: 14px; }
            tr:hover { background: #f8fafc; }
        
            .error { color: #991b1b; background: #fef2f2; padding: 12px; border-radius: 8px; border: 1px solid #fee2e2; margin: 10px 0; }
            .success { color: #065f46; background: #ecfdf5; padding: 12px; border-radius: 8px; border: 1px solid #d1fae5; margin: 10px 0; }
            .warning { color: #854d0e; background: #fefce8; padding: 12px; border-radius: 8px; border: 1px solid #fef08a; margin: 10px 0; }
            
            h3 { color: #1a4388; margin-bottom: 10px; border-bottom: 1px solid #e2e8f0; padding-bottom: 5px; }
          </style>
        </head>
        <body>
          
        <div class="container">
          <h1>ניהול נתוני שיחות מתקדם - ימות המשיח</h1>
          
          <div class="setup-panel">
            <div class="input-group">
              <label>טוקן API:</label>
              <input type="password" id="token" placeholder="הכנס טוקן..." />
            </div>
            <div class="input-group">
              <label>שנה:</label>
              <input type="number" id="year" value="2026" style="width: 80px;" />
            </div>
            <div class="input-group">
              <label>חודש:</label>
              <select id="month">
                <option value="01">01</option><option value="02">02</option>
                <option value="03">03</option><option value="04" selected>04</option>
                <option value="05">05</option><option value="06">06</option>
                <option value="07">07</option><option value="08">08</option>
                <option value="09">09</option><option value="10">10</option>
                <option value="11">11</option><option value="12">12</option>
              </select>
            </div>
            <div class="input-group">
              <label>רף דקות להגדרת שיחה (מעל/מתחת):</label>
              <input type="number" id="minLimit" value="15" style="width: 100px;" />
            </div>
            <button onclick="fetchData()">משוך נתונים</button>
          </div>
          
          <div id="statusMessage"></div>
          
          <div id="summaryCards" class="summary-cards" style="display:none;">
            <div class="card"><span class="val" id="totalCalls">0</span><span class="lbl">סה"כ כניסות למערכת</span></div>
            <div class="card"><span class="val" id="totalListeners">0</span><span class="lbl">מאזינים יוניקיים</span></div>
            <div class="card"><span class="val" id="avgListenerTime">0:00</span><span class="lbl">ממוצע למאזין</span></div>
            <div class="card"><span class="val" id="callsOverLimit">0</span><span class="lbl">שיחות מעל הרף</span></div>
            <div class="card"><span class="val" id="callsUnderLimit">0</span><span class="lbl">שיחות מתחת לרף</span></div>
          </div>
        
          <div class="tabs" id="tabsMenu">
            <button class="tab-btn active" onclick="switchTab('tab-extensions')">נתוני שלוחות</button>
            <button class="tab-btn" onclick="switchTab('tab-files')">נתוני קבצים והאזנות</button>
            <button class="tab-btn" onclick="switchTab('tab-daily')">סטטיסטיקה יומית ושעות</button>
          </div>
        
          <div id="tab-extensions" class="tab-content active">
            <div class="grid-2">
              <div>
                <h3>השלוחות המובילות בזמן האזנה (טופ 10)</h3>
                <div class="table-container">
                  <table>
                    <thead><tr><th>מקום</th><th>שלוחה</th><th>שם</th><th>זמן כולל</th></tr></thead>
                    <tbody id="topTimeExtensions"></tbody>
                  </table>
                </div>
              </div>
              <div>
                <h3>השלוחות עם הכי הרבה כניסות</h3>
                <div class="table-container">
                  <table>
                    <thead><tr><th>מקום</th><th>שלוחה</th><th>שם</th><th>כמות כניסות</th></tr></thead>
                    <tbody id="topCallsExtensions"></tbody>
                  </table>
                </div>
              </div>
            </div>
          </div>
        
          <div id="tab-files" class="tab-content">
            <div class="grid-2">
              <div>
                <h3>הקבצים המושמעים ביותר</h3>
                <div class="table-container">
                  <table>
                    <thead><tr><th>שלוחה</th><th>קובץ</th><th>כמות השמעות</th><th>זמן השמעה מצטבר</th></tr></thead>
                    <tbody id="topFiles"></tbody>
                  </table>
                </div>
              </div>
              <div>
                <h3>קבצים עם הכי הרבה עזיבות (האזנה חלקית)</h3>
                <div class="table-container">
                  <table>
                    <thead><tr><th>שלוחה</th><th>קובץ</th><th>מספר עזיבות באמצע</th></tr></thead>
                    <tbody id="dropoffFiles"></tbody>
                  </table>
                </div>
              </div>
            </div>
          </div>
        
          <div id="tab-daily" class="tab-content">
            <div class="grid-2">
              <div>
                <h3>מאזינים לפי ימים</h3>
                <div class="table-container">
                  <table>
                    <thead><tr><th>תאריך</th><th>סה"כ כניסות</th><th>מאזינים יוניקיים</th></tr></thead>
                    <tbody id="dailyStats"></tbody>
                  </table>
                </div>
              </div>
              <div>
                <h3>השעות הפעילות ביותר (לפי כניסות)</h3>
                <div class="table-container">
                  <table>
                    <thead><tr><th>שעה</th><th>כמות כניסות</th></tr></thead>
                    <tbody id="hourlyStats"></tbody>
                  </table>
                </div>
              </div>
            </div>
          </div>
        
        </div>
          
        <script>
          function showMsg(text, type) {
            const el = document.getElementById("statusMessage");
            el.innerHTML = `<div class="${type}">${text}</div>`;
          }
        
          function switchTab(tabId) {
            document.querySelectorAll('.tab-content').forEach(el => el.classList.remove('active'));
            document.querySelectorAll('.tab-btn').forEach(el => el.classList.remove('active'));
            document.getElementById(tabId).classList.add('active');
            event.currentTarget.classList.add('active');
          }
        
          function formatHMS(s) {
            if (isNaN(s) || s < 0) return "0:00";
            const h = Math.floor(s / 3600);
            const m = Math.floor((s % 3600) / 60);
            const sec = Math.floor(s % 60);
            return h > 0 ? `${h}:${String(m).padStart(2,'0')}:${String(sec).padStart(2,'0')}` : `${m}:${String(sec).padStart(2,'0')}`;
          }
        
          async function fetchData() {
            const token = document.getElementById("token").value;
            const year = document.getElementById("year").value;
            const month = document.getElementById("month").value;
            
            if (!token) { showMsg("אנא הזן טוקן תקני", "error"); return; }
            
            const pathEnterExit = `ivr2:Log/LogFolderEnterExit-${year}-${month}.ymgr`;
            const pathPlayback = `ivr2:Log/LogPlaybackPlayStop/LogPlaybackPlayStop.${year}-${month}.ymgr`;
        
            const urlEnterExit = `https://private.call2all.co.il/ym/api/RenderYMGRFile?token=${token}&wath=${pathEnterExit}&convertType=json&notLoadLang=1`;
            const urlPlayback = `https://private.call2all.co.il/ym/api/RenderYMGRFile?token=${token}&wath=${pathPlayback}&convertType=json&notLoadLang=1`;
        
            showMsg("מתחבר לשרת ימות המשיח, מושך נתונים...", "success");
        
            try {
              const [resEnterExit, resPlayback] = await Promise.all([
                fetch(urlEnterExit).then(r => r.json()).catch(() => ({ responseStatus: "ERROR" })),
                fetch(urlPlayback).then(r => r.json()).catch(() => ({ responseStatus: "ERROR" }))
              ]);
        
              if (resEnterExit.responseStatus !== "OK" && resPlayback.responseStatus !== "OK") {
                showMsg("שגיאה מהשרת: לא נמצאו קבצי לוג לחודש זה.", "error");
                return;
              }
        
              let warning = "";
              if (resEnterExit.responseStatus !== "OK") warning += " לא נמצא לוג כניסות (EnterExit).";
              if (resPlayback.responseStatus !== "OK") warning += " לא נמצא לוג השמעות קבצים (PlaybackPlayStop).";
              if (warning) showMsg("הערה: " + warning, "warning");
              else showMsg("הנתונים נמשכו ועובדו בהצלחה!", "success");
        
              processData(resEnterExit.data || [], resPlayback.data || []);
              
            } catch (err) {
              showMsg("שגיאת תקשורת עם השרת.", "error");
            }
          }
        
          function processData(folderData, playbackData) {
            const limitMinutes = parseFloat(document.getElementById("minLimit").value) || 15;
            const limitSeconds = limitMinutes * 60;
        
            // ----- עיבוד נתוני כניסה/יציאה (FolderEnterExit) -----
            const extensions = {};
            const daily = {};
            const hourly = {};
            const phones = {};
            
            let gCalls = 0;
            let gSeconds = 0;
            let callsOverLimit = 0;
            let callsUnderLimit = 0;
        
            folderData.forEach(row => {
              const ext = row["Folder"];
              const seconds = parseFloat(row["TimeTotal"]) || 0;
              const title = row["PathTitle"] || row["ValName"] || "";
              const phone = row["Phone"];
              const date = row["EnterDate"];
              const time = row["EnterTime"];
        
              if (!ext) return;
        
              // שלוחות
              if (!extensions[ext]) extensions[ext] = { ext, title, calls: 0, seconds: 0 };
              extensions[ext].calls++;
              extensions[ext].seconds += seconds;
        
              // מאזינים (Phone)
              if (phone) {
                if (!phones[phone]) phones[phone] = { count: 0, totalSeconds: 0 };
                phones[phone].count++;
                phones[phone].totalSeconds += seconds;
              }
        
              // חתך זמן (רף)
              if (seconds >= limitSeconds) callsOverLimit++;
              else callsUnderLimit++;
        
              // נתונים יומיים
              if (date) {
                if (!daily[date]) daily[date] = { calls: 0, uniquePhones: new Set() };
                daily[date].calls++;
                if (phone) daily[date].uniquePhones.add(phone);
              }
        
              // שעות פעילות
              if (time) {
                const hour = time.split(":")[0];
                if (!hourly[hour]) hourly[hour] = 0;
                hourly[hour]++;
              }
        
              gCalls++;
              gSeconds += seconds;
            });
        
            // ----- עיבוד נתוני קבצים (PlaybackPlayStop) -----
            const files = {};
            
            playbackData.forEach(row => {
              const ext = row["Folder"] || "";
              const fileName = row["FileName"] || row["ValName"] || "";
              const playSeconds = parseFloat(row["TimeTotal"] || row["PlayTotalTime"]) || 0;
              const fileKey = ext + "/" + fileName;
        
              if (!fileName) return;
        
              if (!files[fileKey]) files[fileKey] = { ext, fileName, plays: 0, totalSeconds: 0, dropoffs: 0 };
              
              files[fileKey].plays++;
              files[fileKey].totalSeconds += playSeconds;
        
              // חישוב עזיבות אמצע: נניח שעזיבה היא אם הושמע פחות מ-80% מהקובץ או אם סטאטוס/סיבה היא לא רגילה
              // מכיוון שהמפתחות משתנים, הדרך הפשוטה לזהות "נטישה" מהירה היא שיחה שנותקה פחות מ-15 שניות לסיום (אם יש אורך) או חיתוך.
              // נשתמש בהגיון בסיסי: אם המאזין שמע פחות מ-10 שניות או פחות מהאורך (במידה וקיים).
              const fileLength = parseFloat(row["FileLength"]);
              if (fileLength && playSeconds < fileLength - 5) {
                 files[fileKey].dropoffs++;
              } else if (!fileLength && playSeconds < 30) {
                 // גיבוי למקרה שאין אורך קובץ מדויק
                 files[fileKey].dropoffs++;
              }
            });
        
            renderUI(extensions, daily, hourly, phones, files, gCalls, callsOverLimit, callsUnderLimit);
          }
        
          function renderUI(extensions, daily, hourly, phones, files, gCalls, callsOverLimit, callsUnderLimit) {
            document.getElementById("summaryCards").style.display = "grid";
            document.getElementById("tabsMenu").style.display = "flex";
        
            const uniqueListenersCount = Object.keys(phones).length;
            let avgTime = 0;
            if (uniqueListenersCount > 0) {
              const totalSystemTime = Object.values(phones).reduce((sum, p) => sum + p.totalSeconds, 0);
              avgTime = totalSystemTime / uniqueListenersCount;
            }
        
            // כרטיסיות למעלה
            document.getElementById("totalCalls").innerText = gCalls;
            document.getElementById("totalListeners").innerText = uniqueListenersCount;
            document.getElementById("avgListenerTime").innerText = formatHMS(avgTime);
            document.getElementById("callsOverLimit").innerText = callsOverLimit;
            document.getElementById("callsUnderLimit").innerText = callsUnderLimit;
        
            const extArr = Object.values(extensions);
            const filesArr = Object.values(files);
        
            // 1. שלוחות טופ זמן
            const topTimeExt = [...extArr].sort((a, b) => b.seconds - a.seconds).slice(0, 10);
            document.getElementById("topTimeExtensions").innerHTML = topTimeExt.map((e, i) => 
              `<tr><td>${i+1}</td><td><strong>${e.ext}</strong></td><td>${e.title}</td><td>${formatHMS(e.seconds)}</td></tr>`
            ).join("");
        
            // 2. שלוחות טופ כניסות
            const topCallsExt = [...extArr].sort((a, b) => b.calls - a.calls);
            document.getElementById("topCallsExtensions").innerHTML = topCallsExt.map((e, i) => 
              `<tr><td>${i+1}</td><td><strong>${e.ext}</strong></td><td>${e.title}</td><td>${e.calls}</td></tr>`
            ).join("");
        
            // 3. קבצים מושמעים ביותר
            const topFiles = [...filesArr].sort((a, b) => b.plays - a.plays).slice(0, 30); // מציג עד 30
            document.getElementById("topFiles").innerHTML = topFiles.map(f => 
              `<tr><td>${f.ext}</td><td>${f.fileName}</td><td>${f.plays}</td><td>${formatHMS(f.totalSeconds)}</td></tr>`
            ).join("");
        
            // 4. עזיבות באמצע
            const dropoffFiles = [...filesArr].sort((a, b) => b.dropoffs - a.dropoffs).filter(f => f.dropoffs > 0).slice(0, 20);
            document.getElementById("dropoffFiles").innerHTML = dropoffFiles.map(f => 
              `<tr><td>${f.ext}</td><td>${f.fileName}</td><td style="color:red; font-weight:bold;">${f.dropoffs}</td></tr>`
            ).join("");
        
            // 5. יומי
            const dailyHtml = Object.keys(daily).sort().map(date => 
              `<tr><td>${date}</td><td>${daily[date].calls}</td><td>${daily[date].uniquePhones.size}</td></tr>`
            ).join("");
            document.getElementById("dailyStats").innerHTML = dailyHtml;
        
            // 6. שעות
            const hourlyHtml = Object.keys(hourly).sort((a, b) => hourly[b] - hourly[a]).map(hour => 
              `<tr><td>${hour}:00</td><td>${hourly[hour]}</td></tr>`
            ).join("");
            document.getElementById("hourlyStats").innerHTML = hourlyHtml;
          }
        </script>
          
        </body>
        </html>
        כמובן שכל אחד יכול לשדרג אם בינה
        
        ק תגובה 1 תגובה אחרונה תגובה ציטוט 1
        • א מנותק
          אA @קו המוסיקה
          נערך לאחרונה על ידי אA

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

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

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

            אילו קבצים מקבלים את אחוזי ההאזנה הגבוהים ביותר
            כמות ההאזנות לכל קובץ (שאת זה אפשר לבדוק חלקית כבר היום)
            אילו שלוחות הכי מואזנות בקו
            לאילו שלוחות נכנסים הכי הרבה

            זה לדעתי הבסיס,
            אם יש לשהו אחר עוד משהו שלא חשבתי על שיכתוב

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

              @אa יש פה קוד שהכנתי למישהו הוא עובד על שלוחות לא על קבצים זה הרעיון
              @קו-המוסיקה אם תפרט יותר מה צריך אני יכול גם לשדרג את הקוד הזה

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

                @BEN-ZION נראה לי שהסברתי מה שאני צריך,
                אממ...
                תן לי לחשוב אם יש לי עוד רעיונות לנתונים

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

                  @BEN-ZION @אa
                  אוקיי הנה עוד כמה דברים
                  כמה מאזינים נכנסו היום / השבוע / החודש
                  זמן האזנה ממוצע לכל מאזין
                  הקבצים הכי מושמעים (Top 10)
                  איפה אנשים נוטשים (באיזה קטע הם יוצאים)
                  כמה פעמים כל קובץ הושמע
                  כמה שיחות נכנסו לעומת כמה נותקו
                  השעות הכי פעילות
                  אולי גם משהו שאומר לך איזה קבצים קיבלו הכי הרבה קבצים השבוע

                  ואם הולכים חזק יותר עם כל הדבר הזה,
                  אפשר גם לעשות התראות כשיש האזנה נמוכה ביום מסוים בהשוואה ליום אחר,
                  (זה הייתי יותר ממליץ שזה יעבוד בבינה מלכותית)

                  קיצור זה אם באמת משהו פה רוצה מאוד להשקיע, אבל את הבסיס כבר הבאתי למעלה

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

                    @קו-המוסיקה
                    זה הנמסקנות שהגעתי האם יש ההארות ההערות?
                    דוח סטטיסטיקה למערכות
                    בכל שלוחה איזה נתונים מקבלים זמני האזנה הכי גבוהים מ1 - 10
                    אילו שלוחות הכי מואזנות בכל המערכת
                    לאלו שלוחות נכנסים הכי הרבה בכל המערכת
                    כמה מאזינים נכנסים כל יום למערכת /לכל שלוחה
                    זמן האזנה ממוצע לכל מאזין
                    הקבצים אם הכי הרבה עזיבות באמצע
                    כמה פעמים כל קובץ הושמע
                    כמה שיחות נכנסו ושהו מעל 15 דקות וכמה נותקו בפחות מכך(שיהיה ניתן לבחור את הדקות)
                    מה השעות הכי פעילות להאזנה

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

                      @BEN-ZION כן זה לדעתי הדברים שבאת חשובים

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

                        @BEN-ZION אשמח מאוד אם תצליח ליצור כזה דבר!
                        אני בטוח שכולם יודו לך על זה.
                        זה באמת אחד הדברים שהכי חסרים למהלי מערכות...
                        חשבתי שגם בכמות מאזינים גדאי לעשות (כמובן אם מתאפשר...) שאם מאזין מתקשר מממספרים שונים, אבל מזוהה לדוג' בקובץ listallinformation.ini שיזוהה כמאזין 1 ולא כשני מאזינים....

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

                          @קו-המוסיקה @אa @565906
                          מצורף קוד HTML בסיסי ניתן לשדרג עוד
                          אין לי במערכת לוג האזנה אז אני לא יודע איך עובד נראה טוב
                          יש לו באג שאין לי כוח כרגע לתקן שבציון דקות שהם מעל רף של דקות נתין לבחור כמה דקות הוא מציין בשיחות מתחת לרף כל מעבר בשלוחה שלא התעכבו בה את הרף
                          עוד לא מצאתי איך לחשב לפי שיחה אולי בהמשך אני אשדרג

                          <!DOCTYPE html>
                          <html lang="he" dir="rtl">
                          <head>
                            <meta charset="UTF-8" />
                            <meta name="viewport" content="width=device-width, initial-scale=1.0" />
                            <title>מערכת סיכום דקות מתקדמת - ימות המשיח</title>
                            <style>
                              body { font-family: Arial, sans-serif; background: #f0f2f5; margin: 0; padding: 20px; color: #333; }
                              .container { max-width: 1200px; margin: auto; background: #fff; padding: 25px; border-radius: 15px; box-shadow: 0 8px 30px rgba(0,0,0,0.1); }
                              h1 { margin-top: 0; color: #1a4388; text-align: center; border-bottom: 2px solid #eee; padding-bottom: 15px; }
                              
                              .setup-panel { background: #f8fafc; padding: 20px; border-radius: 12px; border: 1px solid #e2e8f0; margin-bottom: 20px; display: flex; flex-wrap: wrap; gap: 15px; align-items: flex-end; }
                              .input-group { display: flex; flex-direction: column; gap: 5px; }
                              label { font-weight: bold; font-size: 14px; }
                              input, select { padding: 10px; border: 1px solid #cbd5e1; border-radius: 8px; font-size: 14px; }
                              
                              button { border: none; background: #1a4388; color: #fff; padding: 10px 20px; border-radius: 8px; cursor: pointer; font-weight: bold; transition: background 0.2s; }
                              button:hover { background: #133266; }
                              button.secondary { background: #10b981; }
                              button.secondary:hover { background: #059669; }
                          
                              .summary-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 15px; margin-bottom: 20px; }
                              .card { background: #fff; padding: 15px; border-radius: 10px; border: 1px solid #e2e8f0; box-shadow: 0 2px 4px rgba(0,0,0,0.02); text-align: center; }
                              .card .val { font-size: 22px; font-weight: bold; color: #1a4388; display: block; margin-bottom: 5px; }
                              .card .lbl { font-size: 13px; color: #64748b; font-weight: bold; }
                          
                              .tabs { display: flex; gap: 10px; margin-bottom: 15px; border-bottom: 2px solid #e2e8f0; padding-bottom: 10px; display: none; }
                              .tab-btn { background: #e2e8f0; color: #333; padding: 10px 15px; border-radius: 8px; cursor: pointer; font-weight: bold; border: none; }
                              .tab-btn.active { background: #1a4388; color: #fff; }
                              
                              .tab-content { display: none; }
                              .tab-content.active { display: block; }
                          
                              .grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
                              @media (max-width: 768px) { .grid-2 { grid-template-columns: 1fr; } }
                          
                              .table-container { overflow-x: auto; max-height: 400px; border: 1px solid #e2e8f0; border-radius: 10px; margin-bottom: 20px; background: #fff;}
                              table { width: 100%; border-collapse: collapse; text-align: right; }
                              th { position: sticky; top: 0; background: #1a4388; color: white; padding: 10px; font-size: 14px; }
                              td { padding: 10px; border-bottom: 1px solid #f1f5f9; font-size: 14px; }
                              tr:hover { background: #f8fafc; }
                          
                              .error { color: #991b1b; background: #fef2f2; padding: 12px; border-radius: 8px; border: 1px solid #fee2e2; margin: 10px 0; }
                              .success { color: #065f46; background: #ecfdf5; padding: 12px; border-radius: 8px; border: 1px solid #d1fae5; margin: 10px 0; }
                              .warning { color: #854d0e; background: #fefce8; padding: 12px; border-radius: 8px; border: 1px solid #fef08a; margin: 10px 0; }
                              
                              h3 { color: #1a4388; margin-bottom: 10px; border-bottom: 1px solid #e2e8f0; padding-bottom: 5px; }
                            </style>
                          </head>
                          <body>
                            
                          <div class="container">
                            <h1>ניהול נתוני שיחות מתקדם - ימות המשיח</h1>
                            
                            <div class="setup-panel">
                              <div class="input-group">
                                <label>טוקן API:</label>
                                <input type="password" id="token" placeholder="הכנס טוקן..." />
                              </div>
                              <div class="input-group">
                                <label>שנה:</label>
                                <input type="number" id="year" value="2026" style="width: 80px;" />
                              </div>
                              <div class="input-group">
                                <label>חודש:</label>
                                <select id="month">
                                  <option value="01">01</option><option value="02">02</option>
                                  <option value="03">03</option><option value="04" selected>04</option>
                                  <option value="05">05</option><option value="06">06</option>
                                  <option value="07">07</option><option value="08">08</option>
                                  <option value="09">09</option><option value="10">10</option>
                                  <option value="11">11</option><option value="12">12</option>
                                </select>
                              </div>
                              <div class="input-group">
                                <label>רף דקות להגדרת שיחה (מעל/מתחת):</label>
                                <input type="number" id="minLimit" value="15" style="width: 100px;" />
                              </div>
                              <button onclick="fetchData()">משוך נתונים</button>
                            </div>
                            
                            <div id="statusMessage"></div>
                            
                            <div id="summaryCards" class="summary-cards" style="display:none;">
                              <div class="card"><span class="val" id="totalCalls">0</span><span class="lbl">סה"כ כניסות למערכת</span></div>
                              <div class="card"><span class="val" id="totalListeners">0</span><span class="lbl">מאזינים יוניקיים</span></div>
                              <div class="card"><span class="val" id="avgListenerTime">0:00</span><span class="lbl">ממוצע למאזין</span></div>
                              <div class="card"><span class="val" id="callsOverLimit">0</span><span class="lbl">שיחות מעל הרף</span></div>
                              <div class="card"><span class="val" id="callsUnderLimit">0</span><span class="lbl">שיחות מתחת לרף</span></div>
                            </div>
                          
                            <div class="tabs" id="tabsMenu">
                              <button class="tab-btn active" onclick="switchTab('tab-extensions')">נתוני שלוחות</button>
                              <button class="tab-btn" onclick="switchTab('tab-files')">נתוני קבצים והאזנות</button>
                              <button class="tab-btn" onclick="switchTab('tab-daily')">סטטיסטיקה יומית ושעות</button>
                            </div>
                          
                            <div id="tab-extensions" class="tab-content active">
                              <div class="grid-2">
                                <div>
                                  <h3>השלוחות המובילות בזמן האזנה (טופ 10)</h3>
                                  <div class="table-container">
                                    <table>
                                      <thead><tr><th>מקום</th><th>שלוחה</th><th>שם</th><th>זמן כולל</th></tr></thead>
                                      <tbody id="topTimeExtensions"></tbody>
                                    </table>
                                  </div>
                                </div>
                                <div>
                                  <h3>השלוחות עם הכי הרבה כניסות</h3>
                                  <div class="table-container">
                                    <table>
                                      <thead><tr><th>מקום</th><th>שלוחה</th><th>שם</th><th>כמות כניסות</th></tr></thead>
                                      <tbody id="topCallsExtensions"></tbody>
                                    </table>
                                  </div>
                                </div>
                              </div>
                            </div>
                          
                            <div id="tab-files" class="tab-content">
                              <div class="grid-2">
                                <div>
                                  <h3>הקבצים המושמעים ביותר</h3>
                                  <div class="table-container">
                                    <table>
                                      <thead><tr><th>שלוחה</th><th>קובץ</th><th>כמות השמעות</th><th>זמן השמעה מצטבר</th></tr></thead>
                                      <tbody id="topFiles"></tbody>
                                    </table>
                                  </div>
                                </div>
                                <div>
                                  <h3>קבצים עם הכי הרבה עזיבות (האזנה חלקית)</h3>
                                  <div class="table-container">
                                    <table>
                                      <thead><tr><th>שלוחה</th><th>קובץ</th><th>מספר עזיבות באמצע</th></tr></thead>
                                      <tbody id="dropoffFiles"></tbody>
                                    </table>
                                  </div>
                                </div>
                              </div>
                            </div>
                          
                            <div id="tab-daily" class="tab-content">
                              <div class="grid-2">
                                <div>
                                  <h3>מאזינים לפי ימים</h3>
                                  <div class="table-container">
                                    <table>
                                      <thead><tr><th>תאריך</th><th>סה"כ כניסות</th><th>מאזינים יוניקיים</th></tr></thead>
                                      <tbody id="dailyStats"></tbody>
                                    </table>
                                  </div>
                                </div>
                                <div>
                                  <h3>השעות הפעילות ביותר (לפי כניסות)</h3>
                                  <div class="table-container">
                                    <table>
                                      <thead><tr><th>שעה</th><th>כמות כניסות</th></tr></thead>
                                      <tbody id="hourlyStats"></tbody>
                                    </table>
                                  </div>
                                </div>
                              </div>
                            </div>
                          
                          </div>
                            
                          <script>
                            function showMsg(text, type) {
                              const el = document.getElementById("statusMessage");
                              el.innerHTML = `<div class="${type}">${text}</div>`;
                            }
                          
                            function switchTab(tabId) {
                              document.querySelectorAll('.tab-content').forEach(el => el.classList.remove('active'));
                              document.querySelectorAll('.tab-btn').forEach(el => el.classList.remove('active'));
                              document.getElementById(tabId).classList.add('active');
                              event.currentTarget.classList.add('active');
                            }
                          
                            function formatHMS(s) {
                              if (isNaN(s) || s < 0) return "0:00";
                              const h = Math.floor(s / 3600);
                              const m = Math.floor((s % 3600) / 60);
                              const sec = Math.floor(s % 60);
                              return h > 0 ? `${h}:${String(m).padStart(2,'0')}:${String(sec).padStart(2,'0')}` : `${m}:${String(sec).padStart(2,'0')}`;
                            }
                          
                            async function fetchData() {
                              const token = document.getElementById("token").value;
                              const year = document.getElementById("year").value;
                              const month = document.getElementById("month").value;
                              
                              if (!token) { showMsg("אנא הזן טוקן תקני", "error"); return; }
                              
                              const pathEnterExit = `ivr2:Log/LogFolderEnterExit-${year}-${month}.ymgr`;
                              const pathPlayback = `ivr2:Log/LogPlaybackPlayStop/LogPlaybackPlayStop.${year}-${month}.ymgr`;
                          
                              const urlEnterExit = `https://private.call2all.co.il/ym/api/RenderYMGRFile?token=${token}&wath=${pathEnterExit}&convertType=json&notLoadLang=1`;
                              const urlPlayback = `https://private.call2all.co.il/ym/api/RenderYMGRFile?token=${token}&wath=${pathPlayback}&convertType=json&notLoadLang=1`;
                          
                              showMsg("מתחבר לשרת ימות המשיח, מושך נתונים...", "success");
                          
                              try {
                                const [resEnterExit, resPlayback] = await Promise.all([
                                  fetch(urlEnterExit).then(r => r.json()).catch(() => ({ responseStatus: "ERROR" })),
                                  fetch(urlPlayback).then(r => r.json()).catch(() => ({ responseStatus: "ERROR" }))
                                ]);
                          
                                if (resEnterExit.responseStatus !== "OK" && resPlayback.responseStatus !== "OK") {
                                  showMsg("שגיאה מהשרת: לא נמצאו קבצי לוג לחודש זה.", "error");
                                  return;
                                }
                          
                                let warning = "";
                                if (resEnterExit.responseStatus !== "OK") warning += " לא נמצא לוג כניסות (EnterExit).";
                                if (resPlayback.responseStatus !== "OK") warning += " לא נמצא לוג השמעות קבצים (PlaybackPlayStop).";
                                if (warning) showMsg("הערה: " + warning, "warning");
                                else showMsg("הנתונים נמשכו ועובדו בהצלחה!", "success");
                          
                                processData(resEnterExit.data || [], resPlayback.data || []);
                                
                              } catch (err) {
                                showMsg("שגיאת תקשורת עם השרת.", "error");
                              }
                            }
                          
                            function processData(folderData, playbackData) {
                              const limitMinutes = parseFloat(document.getElementById("minLimit").value) || 15;
                              const limitSeconds = limitMinutes * 60;
                          
                              // ----- עיבוד נתוני כניסה/יציאה (FolderEnterExit) -----
                              const extensions = {};
                              const daily = {};
                              const hourly = {};
                              const phones = {};
                              
                              let gCalls = 0;
                              let gSeconds = 0;
                              let callsOverLimit = 0;
                              let callsUnderLimit = 0;
                          
                              folderData.forEach(row => {
                                const ext = row["Folder"];
                                const seconds = parseFloat(row["TimeTotal"]) || 0;
                                const title = row["PathTitle"] || row["ValName"] || "";
                                const phone = row["Phone"];
                                const date = row["EnterDate"];
                                const time = row["EnterTime"];
                          
                                if (!ext) return;
                          
                                // שלוחות
                                if (!extensions[ext]) extensions[ext] = { ext, title, calls: 0, seconds: 0 };
                                extensions[ext].calls++;
                                extensions[ext].seconds += seconds;
                          
                                // מאזינים (Phone)
                                if (phone) {
                                  if (!phones[phone]) phones[phone] = { count: 0, totalSeconds: 0 };
                                  phones[phone].count++;
                                  phones[phone].totalSeconds += seconds;
                                }
                          
                                // חתך זמן (רף)
                                if (seconds >= limitSeconds) callsOverLimit++;
                                else callsUnderLimit++;
                          
                                // נתונים יומיים
                                if (date) {
                                  if (!daily[date]) daily[date] = { calls: 0, uniquePhones: new Set() };
                                  daily[date].calls++;
                                  if (phone) daily[date].uniquePhones.add(phone);
                                }
                          
                                // שעות פעילות
                                if (time) {
                                  const hour = time.split(":")[0];
                                  if (!hourly[hour]) hourly[hour] = 0;
                                  hourly[hour]++;
                                }
                          
                                gCalls++;
                                gSeconds += seconds;
                              });
                          
                              // ----- עיבוד נתוני קבצים (PlaybackPlayStop) -----
                              const files = {};
                              
                              playbackData.forEach(row => {
                                const ext = row["Folder"] || "";
                                const fileName = row["FileName"] || row["ValName"] || "";
                                const playSeconds = parseFloat(row["TimeTotal"] || row["PlayTotalTime"]) || 0;
                                const fileKey = ext + "/" + fileName;
                          
                                if (!fileName) return;
                          
                                if (!files[fileKey]) files[fileKey] = { ext, fileName, plays: 0, totalSeconds: 0, dropoffs: 0 };
                                
                                files[fileKey].plays++;
                                files[fileKey].totalSeconds += playSeconds;
                          
                                // חישוב עזיבות אמצע: נניח שעזיבה היא אם הושמע פחות מ-80% מהקובץ או אם סטאטוס/סיבה היא לא רגילה
                                // מכיוון שהמפתחות משתנים, הדרך הפשוטה לזהות "נטישה" מהירה היא שיחה שנותקה פחות מ-15 שניות לסיום (אם יש אורך) או חיתוך.
                                // נשתמש בהגיון בסיסי: אם המאזין שמע פחות מ-10 שניות או פחות מהאורך (במידה וקיים).
                                const fileLength = parseFloat(row["FileLength"]);
                                if (fileLength && playSeconds < fileLength - 5) {
                                   files[fileKey].dropoffs++;
                                } else if (!fileLength && playSeconds < 30) {
                                   // גיבוי למקרה שאין אורך קובץ מדויק
                                   files[fileKey].dropoffs++;
                                }
                              });
                          
                              renderUI(extensions, daily, hourly, phones, files, gCalls, callsOverLimit, callsUnderLimit);
                            }
                          
                            function renderUI(extensions, daily, hourly, phones, files, gCalls, callsOverLimit, callsUnderLimit) {
                              document.getElementById("summaryCards").style.display = "grid";
                              document.getElementById("tabsMenu").style.display = "flex";
                          
                              const uniqueListenersCount = Object.keys(phones).length;
                              let avgTime = 0;
                              if (uniqueListenersCount > 0) {
                                const totalSystemTime = Object.values(phones).reduce((sum, p) => sum + p.totalSeconds, 0);
                                avgTime = totalSystemTime / uniqueListenersCount;
                              }
                          
                              // כרטיסיות למעלה
                              document.getElementById("totalCalls").innerText = gCalls;
                              document.getElementById("totalListeners").innerText = uniqueListenersCount;
                              document.getElementById("avgListenerTime").innerText = formatHMS(avgTime);
                              document.getElementById("callsOverLimit").innerText = callsOverLimit;
                              document.getElementById("callsUnderLimit").innerText = callsUnderLimit;
                          
                              const extArr = Object.values(extensions);
                              const filesArr = Object.values(files);
                          
                              // 1. שלוחות טופ זמן
                              const topTimeExt = [...extArr].sort((a, b) => b.seconds - a.seconds).slice(0, 10);
                              document.getElementById("topTimeExtensions").innerHTML = topTimeExt.map((e, i) => 
                                `<tr><td>${i+1}</td><td><strong>${e.ext}</strong></td><td>${e.title}</td><td>${formatHMS(e.seconds)}</td></tr>`
                              ).join("");
                          
                              // 2. שלוחות טופ כניסות
                              const topCallsExt = [...extArr].sort((a, b) => b.calls - a.calls);
                              document.getElementById("topCallsExtensions").innerHTML = topCallsExt.map((e, i) => 
                                `<tr><td>${i+1}</td><td><strong>${e.ext}</strong></td><td>${e.title}</td><td>${e.calls}</td></tr>`
                              ).join("");
                          
                              // 3. קבצים מושמעים ביותר
                              const topFiles = [...filesArr].sort((a, b) => b.plays - a.plays).slice(0, 30); // מציג עד 30
                              document.getElementById("topFiles").innerHTML = topFiles.map(f => 
                                `<tr><td>${f.ext}</td><td>${f.fileName}</td><td>${f.plays}</td><td>${formatHMS(f.totalSeconds)}</td></tr>`
                              ).join("");
                          
                              // 4. עזיבות באמצע
                              const dropoffFiles = [...filesArr].sort((a, b) => b.dropoffs - a.dropoffs).filter(f => f.dropoffs > 0).slice(0, 20);
                              document.getElementById("dropoffFiles").innerHTML = dropoffFiles.map(f => 
                                `<tr><td>${f.ext}</td><td>${f.fileName}</td><td style="color:red; font-weight:bold;">${f.dropoffs}</td></tr>`
                              ).join("");
                          
                              // 5. יומי
                              const dailyHtml = Object.keys(daily).sort().map(date => 
                                `<tr><td>${date}</td><td>${daily[date].calls}</td><td>${daily[date].uniquePhones.size}</td></tr>`
                              ).join("");
                              document.getElementById("dailyStats").innerHTML = dailyHtml;
                          
                              // 6. שעות
                              const hourlyHtml = Object.keys(hourly).sort((a, b) => hourly[b] - hourly[a]).map(hour => 
                                `<tr><td>${hour}:00</td><td>${hourly[hour]}</td></tr>`
                              ).join("");
                              document.getElementById("hourlyStats").innerHTML = hourlyHtml;
                            }
                          </script>
                            
                          </body>
                          </html>
                          כמובן שכל אחד יכול לשדרג אם בינה
                          
                          ק תגובה 1 תגובה אחרונה תגובה ציטוט 1
                          • ק מנותק
                            קו המוסיקה @BEN ZION
                            נערך לאחרונה על ידי קו המוסיקה

                            @BEN-ZION מה אני אמור להכניס פה?Screenshot 2026-04-04 at 23.40.32.png

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

                              @קו-המוסיקה
                              טוקן

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

                                @אA
                                סליחה על הבורות אבל מאיפה אני משיג טוקן?
                                (אני מרגיש שזה שאלה מצחיקה...)

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

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

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

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

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

                                      @אA כן אולי באמת הגיע הזמן...

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

                                        @CUBASE
                                        מספר מערכת:סיסמא, כבר לא עובד חלק בכל הפקודות.

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

                                          @אA מעניין מה שאתה אומר, לא שמעתי על כך, אילו פקודות?

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

                                            @CUBASE
                                            אני לא יודע להגיד לך בוודאות, אבל כשאני ניסיתי בכמה מהן לא עבד לי.

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

                                              @אA מוזר, אני עובד הרבה עם פקודות מהירות מהדפדפן באמצעות מספר וסיסמה ולא נתקלתי בשגיאה.. 🤔

                                              (ובמיוחד שלא פורסם משהו על כך, רשמית זה עדיין אמור להיות פעיל)

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