2021-02-17 16:59:17 +01:00
|
|
|
from datetime import datetime, timedelta
|
2020-11-28 21:11:21 +01:00
|
|
|
from pathlib import Path
|
|
|
|
from typing import List
|
2020-12-07 17:31:25 +01:00
|
|
|
import logging
|
2020-12-05 13:56:12 +01:00
|
|
|
|
|
|
|
import matplotlib.pyplot as plt
|
|
|
|
import matplotlib.dates as mdates
|
2020-11-28 21:11:21 +01:00
|
|
|
|
|
|
|
from langfingaz import loadData
|
|
|
|
from langfingaz import parseMeetings
|
|
|
|
from langfingaz.parseMeetings import BbbStatus, Meeting
|
|
|
|
from langfingaz.util import fileUtil
|
2020-12-05 13:56:12 +01:00
|
|
|
from langfingaz.util import util
|
2020-11-28 21:11:21 +01:00
|
|
|
|
|
|
|
|
2020-11-29 15:39:11 +01:00
|
|
|
def getDefaultPlotFolder() -> Path:
|
|
|
|
return fileUtil.getProjectBaseDir().joinpath("plot")
|
|
|
|
|
|
|
|
|
|
|
|
def plotMeetings(dataDir: Path = fileUtil.getProjectBaseDir().joinpath("data")):
|
2020-11-28 21:11:21 +01:00
|
|
|
bbbStati: List[BbbStatus] = []
|
|
|
|
|
2020-11-29 15:39:11 +01:00
|
|
|
for file in dataDir.iterdir():
|
2020-11-28 21:11:21 +01:00
|
|
|
if file.name.endswith(".xml"):
|
2020-12-07 17:31:25 +01:00
|
|
|
logging.debug("Reading from file " + str(file))
|
2020-11-28 21:11:21 +01:00
|
|
|
dataStr, t = loadData.loadData(file)
|
|
|
|
meetings: List[Meeting] = parseMeetings.parseMeetingsData(dataStr)
|
|
|
|
bbbStati.append(parseMeetings.BbbStatus(meetings, t))
|
2021-02-17 16:59:17 +01:00
|
|
|
if (len(bbbStati) < 1):
|
|
|
|
print("No bbbStatus objects could be read from data directory: " + str(dataDir))
|
|
|
|
return
|
2020-12-03 17:20:31 +01:00
|
|
|
|
|
|
|
# sort by date (x-axis)
|
|
|
|
bbbStati = sorted(bbbStati, key=BbbStatus.getKey)
|
2020-11-28 21:11:21 +01:00
|
|
|
|
2021-02-17 16:59:17 +01:00
|
|
|
# filter: take only bbbStatus objects of the last month (4 weeks)
|
|
|
|
#
|
|
|
|
# start: datetime = bbbStati[0].pointOfTime
|
|
|
|
# end: datetime = bbbStati[-1].pointOfTime
|
|
|
|
# delta: timedelta = end-start
|
|
|
|
end: datetime = bbbStati[-1].pointOfTime
|
|
|
|
monthBeforeEnd: datetime = end - timedelta(days=28)
|
|
|
|
bbbStati = [bbbStatus for bbbStatus in bbbStati if bbbStatus.pointOfTime >= monthBeforeEnd]
|
|
|
|
|
2020-11-29 15:39:11 +01:00
|
|
|
image: Path = doPlotMeetings(bbbStati)
|
|
|
|
print("saved image at " + str(image))
|
2020-11-28 21:11:21 +01:00
|
|
|
|
|
|
|
|
2020-11-29 15:39:11 +01:00
|
|
|
def doPlotMeetings(bbbStati: List[BbbStatus]) -> Path:
|
2021-02-17 16:59:17 +01:00
|
|
|
'''
|
|
|
|
:param bbbStati: List of bbbStatus objects sorted by date
|
|
|
|
'''
|
|
|
|
|
2020-11-29 15:39:11 +01:00
|
|
|
time = [] # x-axis: time
|
|
|
|
participants = [] # yAxis (1)
|
|
|
|
videos = [] # yAxis (2)
|
|
|
|
voices = [] # yAxis (3)
|
2020-11-28 21:11:21 +01:00
|
|
|
|
|
|
|
for bbbStatus in bbbStati:
|
|
|
|
time.append(bbbStatus.pointOfTime)
|
|
|
|
participants.append(bbbStatus.participantCount)
|
|
|
|
videos.append(bbbStatus.videoCount)
|
|
|
|
voices.append(bbbStatus.voiceParticipantCount)
|
|
|
|
|
2020-12-05 13:56:12 +01:00
|
|
|
_a, _b = plt.subplots() # Create a figure and an axes.
|
|
|
|
fig: plt.Figure = _a
|
2020-12-03 16:30:29 +01:00
|
|
|
ax = _b # of type plt.axes.Axes ??
|
2020-12-05 13:56:12 +01:00
|
|
|
if not (issubclass(type(fig), plt.Figure)):
|
2020-12-03 16:30:29 +01:00
|
|
|
raise ValueError("expected Figure")
|
|
|
|
|
2020-12-05 13:56:12 +01:00
|
|
|
ax.plot(time, participants, label='participants')
|
|
|
|
ax.plot(time, videos, label='video')
|
|
|
|
ax.plot(time, voices, label='voice')
|
|
|
|
|
|
|
|
# format the ticks (on x-axis)
|
2021-02-17 16:59:17 +01:00
|
|
|
days = mdates.DayLocator(interval=2) # every second days
|
|
|
|
hours = mdates.HourLocator(interval=12) # every 12 hours one minor tick
|
2020-12-05 13:56:12 +01:00
|
|
|
dateFmt = mdates.DateFormatter('%Y-%m-%d')
|
|
|
|
|
|
|
|
ax.xaxis.set_major_locator(days)
|
|
|
|
ax.xaxis.set_major_formatter(dateFmt)
|
|
|
|
ax.xaxis.set_minor_locator(hours)
|
|
|
|
|
|
|
|
# round to nearest day
|
|
|
|
dateMin = time[0].date() # round floor
|
|
|
|
dateMax = util.roundCeilingByDay(time[-1]) # round ceiling
|
|
|
|
ax.set_xlim(dateMin, dateMax)
|
|
|
|
|
2020-11-28 21:11:21 +01:00
|
|
|
ax.set_xlabel('time') # Add an x-label to the axes.
|
|
|
|
ax.set_ylabel('numbers') # Add a y-label to the axes.
|
|
|
|
ax.set_title("BigBlueButton Statistics") # Add a title to the axes.
|
|
|
|
ax.legend() # Add a legend.
|
|
|
|
|
2020-12-05 13:56:12 +01:00
|
|
|
# rotates and right aligns the x labels (dates), and moves the bottom of the
|
|
|
|
# axes up to make room for them
|
|
|
|
# https://matplotlib.org/api/_as_gen/matplotlib.figure.Figure.html#matplotlib.figure.Figure.autofmt_xdate
|
|
|
|
fig.autofmt_xdate()
|
|
|
|
|
|
|
|
imgFormat = 'png'
|
2020-11-29 15:39:11 +01:00
|
|
|
image: Path = getDefaultPlotFolder().joinpath(
|
2020-12-05 13:56:12 +01:00
|
|
|
"{}_until_{}.{}".format(
|
|
|
|
fileUtil.asString(time[0]),
|
|
|
|
fileUtil.asString(time[-1]),
|
|
|
|
imgFormat
|
|
|
|
)
|
2020-11-29 15:39:11 +01:00
|
|
|
)
|
2020-12-05 14:00:18 +01:00
|
|
|
fig.savefig(image, format=imgFormat, dpi=400)
|
2020-11-29 15:39:11 +01:00
|
|
|
# plt.show()
|
|
|
|
|
|
|
|
return image
|
2020-11-28 21:11:21 +01:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2020-11-29 15:39:11 +01:00
|
|
|
plotMeetings()
|