aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorParker Berberian <pberberian@iol.unh.edu>2020-03-16 18:52:03 +0000
committerGerrit Code Review <gerrit@opnfv.org>2020-03-16 18:52:03 +0000
commitd5b4f4c77534824430fd8e2d3f15e5f7ed6303f5 (patch)
tree8bd6fffb858840d6307631aefdd5cf4c721c6c65
parent0db3a84d9d9ed213983a517efd35c339537ef472 (diff)
parentaaff0c1a5abc850db49dc72a79abb581be8cfcfc (diff)
Merge "Fixed a few bugs for the stats functions and created a few tests."
-rw-r--r--src/booking/stats.py70
-rw-r--r--src/booking/tests/test_stats.py59
-rw-r--r--src/templates/base/booking/stats.html15
3 files changed, 104 insertions, 40 deletions
diff --git a/src/booking/stats.py b/src/booking/stats.py
index 47de80b..bdb478a 100644
--- a/src/booking/stats.py
+++ b/src/booking/stats.py
@@ -1,5 +1,5 @@
##############################################################################
-# Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, and others.
+# Copyright (c) 2020 Parker Berberian, Sawyer Bergeron, Sean Smith and others.
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Apache License, Version 2.0
@@ -7,7 +7,7 @@
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
from booking.models import Booking
-import datetime
+from datetime import datetime, timedelta
import pytz
@@ -18,43 +18,41 @@ class StatisticsManager(object):
"""
Calculate Booking usage data points.
- Will return a dictionary of names and 2-D array of x and y data points.
- e.g. {"plot1": [["x1", "x2", "x3"],["y1", "y2", "y3]]}
- x values will be dates in string
- every change (booking start / end) will be reflected,
- instead of one data point per day
- y values are the integer number of bookings/users active at
- some point in the given date span is the number of days to plot.
- The last x value will always be the current time
+ Gathers all active bookings that fall in interval [(now - span), (now + 1 week)].
+ x data points are every 12 hours
+ y values are the integer number of bookings/users active at time
"""
- data = []
+
x = []
y = []
users = []
- now = datetime.datetime.now(pytz.utc)
- delta = datetime.timedelta(days=span)
- end = now - delta
- bookings = Booking.objects.filter(start__lte=now, end__gte=end).prefetch_related("collaborators")
- for booking in bookings: # collect data from each booking
- user_list = [u.pk for u in booking.collaborators.all()]
- user_list.append(booking.owner.pk)
- data.append((booking.start, 1, user_list))
- data.append((booking.end, -1, user_list))
-
- # sort based on time
- data.sort(key=lambda i: i[0])
-
- # collect data
- count = 0
- active_users = {}
- for datum in data:
- x.append(str(datum[0])) # time
- count += datum[1] # booking count
- y.append(count)
- for pk in datum[2]: # maintain count of each user's active bookings
- active_users[pk] = active_users.setdefault(pk, 0) + datum[1]
- if active_users[pk] == 0:
- del active_users[pk]
- users.append(len([x for x in active_users.values() if x > 0]))
+
+ now = datetime.now(pytz.utc)
+ delta = timedelta(days=span)
+ start = now - delta
+ end = now + timedelta(weeks=1)
+
+ bookings = Booking.objects.filter(
+ start__lte=end,
+ end__gte=start
+ ).prefetch_related("collaborators")
+
+ # get data
+ while start <= end:
+ active_users = 0
+
+ books = bookings.filter(
+ start__lte=start,
+ end__gte=start
+ ).prefetch_related("collaborators")
+
+ for booking in books:
+ active_users += booking.collaborators.all().count() + 1
+
+ x.append(str(start))
+ y.append(books.count())
+ users.append(active_users)
+
+ start += timedelta(hours=12)
return {"booking": [x, y], "user": [x, users]}
diff --git a/src/booking/tests/test_stats.py b/src/booking/tests/test_stats.py
new file mode 100644
index 0000000..5501355
--- /dev/null
+++ b/src/booking/tests/test_stats.py
@@ -0,0 +1,59 @@
+#############################################################################
+# Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, Sean Smith, and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+import pytz
+from datetime import timedelta, datetime
+
+from django.test import TestCase
+
+from booking.models import Booking
+from booking.stats import StatisticsManager as sm
+from dashboard.testing_utils import make_user
+
+
+class StatsTestCases(TestCase):
+
+ def test_no_booking_outside_span(self):
+ now = datetime.now(pytz.utc)
+
+ bad_date = now + timedelta(days=1200)
+ Booking.objects.create(start=now, end=bad_date, owner=make_user(username='jj'))
+
+ actual = sm.getContinuousBookingTimeSeries()
+ dates = actual['booking'][0]
+
+ for date in dates:
+ self.assertNotEqual(date, bad_date)
+
+ def check_booking_and_user_counts(self):
+ now = datetime.now(pytz.utc)
+
+ for i in range(20):
+ Booking.objects.create(
+ start=now,
+ end=now + timedelta(weeks=3),
+ owner=make_user(username='a'))
+
+ for i in range(30):
+ Booking.objects.create(
+ start=now + timedelta(days=5),
+ end=now + timedelta(weeks=3, days=5),
+ owner=make_user(username='a'))
+
+ for i in range(120):
+ Booking.objects.create(
+ start=now + timedelta(weeks=1),
+ end=now + timedelta(weeks=4),
+ owner=make_user(username='a'))
+
+ dates = [[now, 20], [now + timedelta(days=5), 30], [now + timedelta(weeks=1), 120]]
+ actual = sm.getContinuousBookingTimeSeries()
+
+ for date in dates:
+ self.assertEqual(date[1], actual['booking'][date[0]])
+ self.assertEqual(date[1], actual['booking'][date[1]])
diff --git a/src/templates/base/booking/stats.html b/src/templates/base/booking/stats.html
index a78f793..4c06b71 100644
--- a/src/templates/base/booking/stats.html
+++ b/src/templates/base/booking/stats.html
@@ -5,20 +5,26 @@
{{ block.super }}
<script src="{% static "node_modules/plotly.js-dist/plotly.js" %}"></script>
<script>
+
function drawGraph(data, graph_id, graph_title){
var container = document.getElementById(graph_id);
var plot_data = { x: data[0],
y: data[1],
- fill: "tonexty",
+ line: {shape: "hv"},
type: "scatter",
- mode: "none",
+ mode: "lines+makers",
};
var layout = {
- title: graph_title
+ title: graph_title,
+ yaxis: {
+ rangemode: 'tozero',
+ autorange: true
+ }
};
Plotly.newPlot(container, [plot_data], layout);
}
-function getData(){
+
+function getData() {
var req = new XMLHttpRequest();
var url = "/booking/stats/json";
var day_input = document.getElementById("number_days");
@@ -37,6 +43,7 @@ function getData(){
req.open("GET", url, true);
req.send();
}
+
</script>
{% endblock %}