mirror of
https://github.com/RaidMax/IW4M-Admin.git
synced 2025-06-27 07:30:08 -05:00
Add server version to master api
Add IsEvadedOffense to EFPenalty Fix remote log reading in not Windows
This commit is contained in:
146
Master/env_master/Lib/site-packages/pygal/graph/stackedbar.py
Normal file
146
Master/env_master/Lib/site-packages/pygal/graph/stackedbar.py
Normal file
@ -0,0 +1,146 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# This file is part of pygal
|
||||
#
|
||||
# A python svg graph plotting library
|
||||
# Copyright © 2012-2016 Kozea
|
||||
#
|
||||
# This library is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Lesser General Public License as published by the Free
|
||||
# Software Foundation, either version 3 of the License, or (at your option) any
|
||||
# later version.
|
||||
#
|
||||
# This library 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 Lesser General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with pygal. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
Stacked Bar chart: Like a bar chart but with all series stacking
|
||||
on top of the others instead of being displayed side by side.
|
||||
"""
|
||||
|
||||
from __future__ import division
|
||||
|
||||
from pygal.adapters import none_to_zero
|
||||
from pygal.graph.bar import Bar
|
||||
|
||||
|
||||
class StackedBar(Bar):
|
||||
|
||||
"""Stacked Bar graph class"""
|
||||
|
||||
_adapters = [none_to_zero]
|
||||
|
||||
def _get_separated_values(self, secondary=False):
|
||||
"""Separate values between positives and negatives stacked"""
|
||||
series = self.secondary_series if secondary else self.series
|
||||
transposed = list(zip(*[serie.values for serie in series]))
|
||||
positive_vals = [sum([
|
||||
val for val in vals
|
||||
if val is not None and val >= self.zero])
|
||||
for vals in transposed]
|
||||
negative_vals = [sum([
|
||||
val
|
||||
for val in vals
|
||||
if val is not None and val < self.zero])
|
||||
for vals in transposed]
|
||||
return positive_vals, negative_vals
|
||||
|
||||
def _compute_box(self, positive_vals, negative_vals):
|
||||
"""Compute Y min and max"""
|
||||
if self.range and self.range[0] is not None:
|
||||
self._box.ymin = self.range[0]
|
||||
else:
|
||||
self._box.ymin = negative_vals and min(
|
||||
min(negative_vals), self.zero) or self.zero
|
||||
if self.range and self.range[1] is not None:
|
||||
self._box.ymax = self.range[1]
|
||||
else:
|
||||
self._box.ymax = positive_vals and max(
|
||||
max(positive_vals), self.zero) or self.zero
|
||||
|
||||
def _compute(self):
|
||||
"""Compute y min and max and y scale and set labels"""
|
||||
positive_vals, negative_vals = self._get_separated_values()
|
||||
|
||||
if self.logarithmic:
|
||||
positive_vals = list(filter(
|
||||
lambda x: x > self.zero, positive_vals))
|
||||
negative_vals = list(filter(
|
||||
lambda x: x > self.zero, negative_vals))
|
||||
|
||||
self._compute_box(positive_vals, negative_vals)
|
||||
positive_vals = positive_vals or [self.zero]
|
||||
negative_vals = negative_vals or [self.zero]
|
||||
|
||||
self._x_pos = [
|
||||
x / self._len for x in range(self._len + 1)
|
||||
] if self._len > 1 else [0, 1] # Center if only one value
|
||||
|
||||
self._points(self._x_pos)
|
||||
|
||||
self.negative_cumulation = [0] * self._len
|
||||
self.positive_cumulation = [0] * self._len
|
||||
|
||||
if self.secondary_series:
|
||||
positive_vals, negative_vals = self._get_separated_values(True)
|
||||
positive_vals = positive_vals or [self.zero]
|
||||
negative_vals = negative_vals or [self.zero]
|
||||
self.secondary_negative_cumulation = [0] * self._len
|
||||
self.secondary_positive_cumulation = [0] * self._len
|
||||
self._pre_compute_secondary(positive_vals, negative_vals)
|
||||
|
||||
self._x_pos = [(i + .5) / self._len for i in range(self._len)]
|
||||
|
||||
def _pre_compute_secondary(self, positive_vals, negative_vals):
|
||||
"""Compute secondary y min and max"""
|
||||
self._secondary_min = (negative_vals and min(
|
||||
min(negative_vals), self.zero)) or self.zero
|
||||
self._secondary_max = (positive_vals and max(
|
||||
max(positive_vals), self.zero)) or self.zero
|
||||
|
||||
def _bar(self, serie, parent, x, y, i, zero, secondary=False):
|
||||
"""Internal stacking bar drawing function"""
|
||||
if secondary:
|
||||
cumulation = (self.secondary_negative_cumulation
|
||||
if y < self.zero else
|
||||
self.secondary_positive_cumulation)
|
||||
else:
|
||||
cumulation = (self.negative_cumulation
|
||||
if y < self.zero else
|
||||
self.positive_cumulation)
|
||||
zero = cumulation[i]
|
||||
cumulation[i] = zero + y
|
||||
if zero == 0:
|
||||
zero = self.zero
|
||||
y -= self.zero
|
||||
y += zero
|
||||
|
||||
width = (self.view.x(1) - self.view.x(0)) / self._len
|
||||
x, y = self.view((x, y))
|
||||
y = y or 0
|
||||
series_margin = width * self._series_margin
|
||||
x += series_margin
|
||||
width -= 2 * series_margin
|
||||
if self.secondary_series:
|
||||
width /= 2
|
||||
x += int(secondary) * width
|
||||
serie_margin = width * self._serie_margin
|
||||
x += serie_margin
|
||||
width -= 2 * serie_margin
|
||||
height = self.view.y(zero) - y
|
||||
r = serie.rounded_bars * 1 if serie.rounded_bars else 0
|
||||
self.svg.transposable_node(
|
||||
parent, 'rect',
|
||||
x=x, y=y, rx=r, ry=r, width=width, height=height,
|
||||
class_='rect reactive tooltip-trigger')
|
||||
return x, y, width, height
|
||||
|
||||
def _plot(self):
|
||||
"""Draw bars for series and secondary series"""
|
||||
for serie in self.series[::-1 if self.stack_from_top else 1]:
|
||||
self.bar(serie)
|
||||
for serie in self.secondary_series[::-1 if self.stack_from_top else 1]:
|
||||
self.bar(serie, True)
|
Reference in New Issue
Block a user