126 lines
3.7 KiB
Python
126 lines
3.7 KiB
Python
"""
|
||
novelWriter – Project Session Log Class
|
||
=======================================
|
||
|
||
File History:
|
||
Created: 2023-06-11 [2.1b1]
|
||
|
||
This file is a part of novelWriter
|
||
Copyright 2018–2023, Veronica Berglyd Olsen
|
||
|
||
This program is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation, either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
This program is distributed in the hope that it will be useful, but
|
||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import json
|
||
import logging
|
||
|
||
from time import time
|
||
from typing import TYPE_CHECKING
|
||
from pathlib import Path
|
||
|
||
from novelwriter.error import logException
|
||
from novelwriter.common import formatTimeStamp
|
||
from novelwriter.constants import nwFiles
|
||
|
||
if TYPE_CHECKING:
|
||
from novelwriter.core.project import NWProject
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
class NWSessionLog:
|
||
"""Core: Session JSON Lines Log File
|
||
|
||
The class that wraps the session log file, which is in JSON Lines
|
||
format. That is, one JSON object per line.
|
||
"""
|
||
|
||
def __init__(self, project: NWProject):
|
||
self._project = project
|
||
self._start = 0.0
|
||
return
|
||
|
||
##
|
||
# Properties
|
||
##
|
||
|
||
@property
|
||
def start(self) -> float:
|
||
"""The session start time."""
|
||
return self._start
|
||
|
||
##
|
||
# Methods
|
||
##
|
||
|
||
def startSession(self):
|
||
"""Start the writng session."""
|
||
self._start = time()
|
||
return
|
||
|
||
def appendSession(self, idleTime: float) -> bool:
|
||
"""Append session statistics to the sessions log file."""
|
||
sessFile = self._project.storage.getMetaFile(nwFiles.SESS_FILE)
|
||
if not isinstance(sessFile, Path):
|
||
return False
|
||
|
||
now = time()
|
||
iNovel, iNotes = self._project.data.initCounts
|
||
cNovel, cNotes = self._project.data.currCounts
|
||
iTotal = iNovel + iNotes
|
||
wDiff = cNovel + cNotes - iTotal
|
||
sTime = now - self._start
|
||
|
||
logger.info("The session lasted %d sec and added %d words", int(sTime), wDiff)
|
||
if sTime < 300 and wDiff == 0:
|
||
logger.info("Session too short, skipping log entry")
|
||
return False
|
||
|
||
try:
|
||
if not sessFile.exists():
|
||
with open(sessFile, mode="w", encoding="utf-8") as fObj:
|
||
fObj.write(self.createInitial(iTotal))
|
||
|
||
with open(sessFile, mode="a+", encoding="utf-8") as fObj:
|
||
fObj.write(self.createRecord(
|
||
start=formatTimeStamp(self._start),
|
||
end=formatTimeStamp(now),
|
||
novel=cNovel,
|
||
notes=cNotes,
|
||
idle=round(idleTime)
|
||
))
|
||
|
||
except Exception:
|
||
logger.error("Failed to write to session stats file")
|
||
logException()
|
||
return False
|
||
|
||
return True
|
||
|
||
def createInitial(self, total: int) -> str:
|
||
"""Low level function to create the initial log file record."""
|
||
data = json.dumps({"type": "initial", "offset": total})
|
||
return f"{data}\n"
|
||
|
||
def createRecord(self, start: str, end: str, novel: int, notes: int, idle: int) -> str:
|
||
"""Low level function to create a log record."""
|
||
data = json.dumps({
|
||
"type": "record", "start": start, "end": end,
|
||
"novel": novel, "notes": notes, "idle": idle,
|
||
})
|
||
return f"{data}\n"
|
||
|
||
# END Class NWSessionLog
|