diff --git a/public/scripts/stats.js b/public/scripts/stats.js index 6844ec77e..3d058fbba 100644 --- a/public/scripts/stats.js +++ b/public/scripts/stats.js @@ -67,11 +67,19 @@ function calculateTotalStats() { * @param {Object} stats - The stats data. */ function createHtml(statsType, stats) { + console.log(stats); // Get time string let timeStirng = humanizeGenTime(stats.total_gen_time); + let chatAge = "Never"; + console.log(stats.date_first_chat, Date.now()); + if(stats.date_first_chat < Date.now()) { + console.log(moment.duration(stats.date_last_chat - stats.date_first_chat).humanize()); + chatAge = moment.duration(stats.date_last_chat - stats.date_first_chat).humanize(); + } // Create popup HTML with stats let html = `

${statsType} Stats

`; + html += createStatBlock("Chat Age", chatAge); html += createStatBlock("Chat Time", timeStirng); html += createStatBlock("Total User Messages", stats.user_msg_count); html += createStatBlock( @@ -111,10 +119,23 @@ async function userStatsHandler() { async function characterStatsHandler(characters, this_chid) { // Get stats from server await getStats(); - + console.log(charStats); // Get character stats let myStats = charStats[characters[this_chid].avatar]; - + if (myStats === undefined) { + myStats = { + total_gen_time: 0, + user_msg_count: 0, + non_user_msg_count: 0, + user_word_count: 0, + non_user_word_count: countWords(characters[this_chid].first_mes), + total_swipe_count: 0, + date_last_chat: 0, + date_first_chat: new Date('9999-12-31T23:59:59.999Z').getTime(), + }; + charStats[characters[this_chid].avatar] = myStats; + updateStats(); + } // Create HTML with stats createHtml("Character", myStats); } @@ -240,6 +261,7 @@ async function statMesProcess( stat.total_swipe_count++; } stat.date_last_chat = Date.now(); + stat.first_chat_time = Math.min(stat.date_first_chat ?? new Date('9999-12-31T23:59:59.999Z').getTime(), Date.now()); console.log(stat); updateStats(); } diff --git a/statsHelpers.js b/statsHelpers.js index 8195f4bd3..ee8d17fa9 100644 --- a/statsHelpers.js +++ b/statsHelpers.js @@ -22,6 +22,40 @@ let lastSaveTimestamp = 0; const statsFilePath = 'public/stats.json'; +function timestampToMoment(timestamp) { + if (!timestamp) { + return null; + } + + if (typeof timestamp === 'number') { + return timestamp; + } + + const pattern1 = /(\d{4})-(\d{1,2})-(\d{1,2}) @(\d{1,2})h (\d{1,2})m (\d{1,2})s (\d{1,3})ms/; + const replacement1 = (match, year, month, day, hour, minute, second, millisecond) => { + return `${year}-${month.padStart(2, "0")}-${day.padStart(2, "0")}T${hour.padStart(2, "0")}:${minute.padStart(2, "0")}:${second.padStart(2, "0")}.${millisecond.padStart(3, "0")}Z`; + }; + const isoTimestamp1 = timestamp.replace(pattern1, replacement1); + if (!isNaN(new Date(isoTimestamp1))) { + return new Date(isoTimestamp1).getTime(); + } + + const pattern2 = /(\w+)\s(\d{1,2}),\s(\d{4})\s(\d{1,2}):(\d{1,2})(am|pm)/i; + const replacement2 = (match, month, day, year, hour, minute, meridiem) => { + const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; + const monthNum = monthNames.indexOf(month) + 1; + const hour24 = meridiem.toLowerCase() === 'pm' ? (parseInt(hour, 10) % 12) + 12 : parseInt(hour, 10) % 12; + return `${year}-${monthNum.toString().padStart(2, "0")}-${day.padStart(2, "0")}T${hour24.toString().padStart(2, "0")}:${minute.padStart(2, "0")}:00Z`; + }; + const isoTimestamp2 = timestamp.replace(pattern2, replacement2); + if (!isNaN(new Date(isoTimestamp2))) { + return new Date(isoTimestamp2).getTime(); + } + + return null; +} + + async function collectAndCreateStats(chatsPath, charactersPath) { console.log('Collecting and creating stats...'); const files = await readdir(charactersPath); @@ -120,7 +154,8 @@ function calculateGenTime(gen_started, gen_finished) { * @returns {number} - The number of words in the string. */ function countWordsInString(str) { - return str.split(" ").length; + const match = str.match(/\b\w+\b/g); + return match ? match.length : 0; } @@ -143,7 +178,8 @@ const calculateStats = (chatsPath, item, index) => { non_user_msg_count: 0, total_swipe_count: 0, chat_size: 0, - date_last_chat: 0 + date_last_chat: 0, + date_first_chat: new Date('9999-12-31T23:59:59.999Z').getTime(), }; let uniqueGenStartTimes = new Set(); @@ -161,7 +197,8 @@ const calculateStats = (chatsPath, item, index) => { const chatStat = fs.statSync(path.join(char_dir, chat)); stats.chat_size += chatStat.size; - stats.date_last_chat = Math.max(stats.date_last_chat, chatStat.mtimeMs); + stats.date_last_chat = Math.max(stats.date_last_chat, Math.floor(chatStat.mtimeMs)); + stats.date_first_chat = Math.min(stats.date_first_chat, result.firstChatTime); } } } @@ -198,7 +235,7 @@ function calculateTotalGenTimeAndWordCount(char_dir, chat, uniqueGenStartTimes) let nonUserMsgCount = 0; let userMsgCount = 0; let totalSwipeCount = 0; - let firstNonUserMsgSkipped = false; + let firstChatTime = new Date('9999-12-31T23:59:59.999Z').getTime(); for (let [index, line] of lines.entries()) { if (line.length) { @@ -250,12 +287,19 @@ function calculateTotalGenTimeAndWordCount(char_dir, chat, uniqueGenStartTimes) } } } + + // If this is the first user message, set the first chat time + if (json.is_user && firstChatTime > Date.now()) { + firstChatTime = timestampToMoment(json.send_date); + } + + } catch (error) { console.error(`Error parsing line ${line}: ${error}`); } } } - return { totalGenTime, userWordCount, nonUserWordCount, userMsgCount, nonUserMsgCount, totalSwipeCount }; + return { totalGenTime, userWordCount, nonUserWordCount, userMsgCount, nonUserMsgCount, totalSwipeCount, firstChatTime }; } module.exports = {