Added support for colored header in presence graph

parent 2e2e6d9d
......@@ -2,35 +2,56 @@ from typing import List
from colour import Color
from svgwrite import Drawing
from svgwrite.container import Group
from svgwrite.container import Group, Style
from svgwrite.gradients import LinearGradient
from svgwrite.shapes import Line
from svgwrite.shapes import Line, Rect
from svgwrite.text import Text
from bitsd.server.presence_graph.parameters import START_TIME, END_TIME
HEIGHT = 1000
WIDTH = 1000
HEADER_SIZE = 70
COLOR_OPEN = Color("green")
COLOR_CLOSE = Color("red")
GRADIENT_NUMBER_COLORS = 11
class PresenceGraph(Drawing):
def __init__(self, data: List[List[float]], *args, **kwargs):
def __init__(self, data: List[List[float]], data_header: List[float] = None, *args, **kwargs):
super().__init__(profile='full', debug=True, *args, **kwargs)
self.viewbox(width=100, height=100)
self.viewbox(width=WIDTH, height=HEIGHT)
self._data = data
self._data_header = data_header
# Calculate the discrete gradient
self._gradient = list(COLOR_CLOSE.range_to(COLOR_OPEN, GRADIENT_NUMBER_COLORS))
def generate(self) -> None:
self._mk_gradients()
self._mk_header_style()
self._add_header()
self._add_rect()
self._add_hours()
self._add_grid()
def _mk_gradients(self) -> None:
COLOR_OPEN = Color("green")
COLOR_CLOSE = Color("red")
NUMBER_COLORS = 11
def _mk_header_style(self) -> None:
# Set default background for the header
self.defs.add(Style("#header {fill: black;}"))
# Calculate the discrete gradient
gradient = list(COLOR_CLOSE.range_to(COLOR_OPEN, NUMBER_COLORS))
if self._data_header is not None or True:
for i in range(5):
value = int(round(self._data_header[i] * (GRADIENT_NUMBER_COLORS - 1)))
self.defs.add(Style("#day_{} {{fill: {};}}".format(i, self._gradient[value].hex)))
def _mk_gradients(self) -> None:
# For each day of the week
for i in range(0, 5):
# Make a vertical linear gradient
......@@ -45,10 +66,10 @@ class PresenceGraph(Drawing):
position = j / len(self._data[i])
# Calculate the rescaled value on the number of the colors in the gradient
value = int(round(self._data[i][j] * (NUMBER_COLORS - 1)))
value = int(round(self._data[i][j] * (GRADIENT_NUMBER_COLORS - 1)))
# Get the hex value of the computed color
color = gradient[value].hex
color = self._gradient[value].hex
# Add the color in the right position of the gradient
lg.add_stop_color(position, color)
......@@ -57,13 +78,44 @@ class PresenceGraph(Drawing):
g = self.add(Group(id="rects"))
for i in range(0, 5):
g.add(self.rect((i * 100 / 5, 0), (100 / 5, 100), fill="url(#grad_{})".format(i)))
g.add(Rect((i * WIDTH / 5, HEADER_SIZE), (WIDTH / 5, HEIGHT), fill="url(#grad_{})".format(i)))
def _add_grid(self) -> None:
g = self.add(Group(id="grid", stroke="black"))
g = self.add(Group(id="grid",
stroke="black",
stroke_width="5"
))
# Vertical lines
for i in range(1, 5):
g.add(Line((i * 100 / 5, 0), (i * 100 / 5, 100)))
g.add(Line((i * WIDTH / 5, 0), (i * WIDTH / 5, HEIGHT)))
# Header line
g.add(Line((0, HEADER_SIZE), (WIDTH, HEADER_SIZE)))
def _add_hours(self) -> None:
pass
g = self.add(Group(id="hours",
text_anchor="middle",
font_size="30",
font_family="Sans",
font_weight="bold"
))
g.add(Text(START_TIME.strftime("%H:%M"), x=[WIDTH / 2], y=[HEADER_SIZE], dy=[40]))
g.add(Text(END_TIME.strftime("%H:%M"), x=[WIDTH / 2], y=[HEIGHT], dy=[-15]))
def _add_header(self) -> None:
g = self.add(Group(id="header"))
for i in range(5):
g.add(Rect((i * WIDTH / 5, 0), (WIDTH / 5, HEADER_SIZE), id="day_{}".format(i)))
g = self.add(Group(id="days",
text_anchor="middle",
font_size="30",
font_family="Sans",
font_weight="bold"
))
for i, day in enumerate(["Mon.", "Tue.", "Wed.", "Thu.", "Thu."]):
g.add(Text(day, x=[(i * 2 + 1) * WIDTH / 10], y=[HEADER_SIZE / 2], dy=[13]))
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment