|
@@ -1,4 +1,5 @@
|
|
|
from .DataStream import EMchPosmap as pos_map, span_days, time_border, calc_interval
|
|
|
+from .PainterBase import PainterBase
|
|
|
from .MerchantReader import MerchantReader
|
|
|
from matplotlib.figure import Figure
|
|
|
from matplotlib import ticker
|
|
@@ -59,43 +60,7 @@ def allpathes(reader: MerchantReader, tuple_pathes: dict, days: list, spec=None)
|
|
|
yield 'all', None, None, all_datas
|
|
|
|
|
|
|
|
|
-class MerchantPainter(object):
|
|
|
- def __init__(self, start_time: int, end_time: int, mchids: set = None, card_types: set = None, spec: int = None, filter_wave: int = None):
|
|
|
- self._reader = MerchantReader()
|
|
|
- _start_time, _end_time, self._mchids, self._card_types, self._spec, self._filter_wave = start_time, end_time, mchids, card_types, spec, filter_wave
|
|
|
-
|
|
|
- if _end_time is None:
|
|
|
- _end_time = int(time.time())
|
|
|
- end_time = self._reader.near_stamp(_end_time, False)
|
|
|
- if end_time is None:
|
|
|
- raise Exception('data is empty')
|
|
|
-
|
|
|
- if _start_time is None or start_time > end_time:
|
|
|
- _start_time = end_time - 7200
|
|
|
-
|
|
|
- start_time = self._reader.near_stamp(_start_time, True)
|
|
|
- if start_time is None:
|
|
|
- raise Exception('data is empty')
|
|
|
-
|
|
|
- stime = lambda t: time.strftime('%d-%H:%M:%S', time.localtime(t))
|
|
|
- logger.debug("near_stamp start_time %d , %s end_time=%s", start_time, stime(start_time), stime(end_time))
|
|
|
-
|
|
|
- interval = calc_interval(start_time, end_time)
|
|
|
- start_time = time_border(interval, start_time, True)
|
|
|
- end_time = time_border(interval, end_time, False)
|
|
|
- logger.debug("time_border start_time %d , %s end_time=%s", start_time, stime(start_time), stime(end_time))
|
|
|
-
|
|
|
- self._days = span_days(start_time, end_time)
|
|
|
-
|
|
|
- stime = lambda t: time.strftime('%d-%H:%M:%S', time.localtime(t))
|
|
|
- sdays = [stime(day) for day in self._days]
|
|
|
- logger.debug(sdays)
|
|
|
-
|
|
|
- self._start_time = start_time
|
|
|
- self._end_time = end_time
|
|
|
- self._interval = interval
|
|
|
- pass
|
|
|
-
|
|
|
+class MerchantPainter(PainterBase):
|
|
|
def _fig_funs(self):
|
|
|
def create():
|
|
|
fig = Figure(figsize=(19, 8))
|
|
@@ -127,43 +92,6 @@ class MerchantPainter(object):
|
|
|
|
|
|
return create, flush
|
|
|
|
|
|
- def paint_ratios(self):
|
|
|
- tuple_pathes = self._reader.many_tuple_path(self._days, self._mchids, self._card_types, self._spec)
|
|
|
- gen = allpathes(self._reader, tuple_pathes, self._days, self._spec)
|
|
|
- if len(self._days) == 0:
|
|
|
- return BytesIO()
|
|
|
-
|
|
|
- day_stamp = self._days[0]
|
|
|
- fig_create, fig_flush = self._fig_funs()
|
|
|
- ax, fig = fig_create()
|
|
|
- x = np.array([d - self._start_time for d in range(self._start_time, self._end_time)])
|
|
|
-
|
|
|
- if self._filter_wave is not None and self._filter_wave > 1:
|
|
|
- window = np.ones(self._filter_wave) / self._filter_wave
|
|
|
- else:
|
|
|
- window = None
|
|
|
-
|
|
|
- mchid_ratios = []
|
|
|
- for _mchid, _card_type, _spec, _data in gen:
|
|
|
- succ, count, y = calc_mchratios(_data, pos_map, self._start_time - day_stamp, self._end_time - day_stamp)
|
|
|
- y = np.convolve(y, window, 'same') if window is not None else y
|
|
|
- label, ratio = self._label(chname=_mchid, succ=succ, count=count, card_type=_card_type, spec=_spec)
|
|
|
- ax.plot(x, y, ls='-', label=label)
|
|
|
- if _card_type is None and _spec is None and type(_mchid) is int:
|
|
|
- mchid_ratios.append((_mchid, ratio))
|
|
|
-
|
|
|
- xticks = [d - self._start_time for d in range(self._start_time, self._end_time + 1, self._interval)]
|
|
|
- xlables = [time.strftime('%d-%H:%M:%S', time.localtime(d + self._start_time)) for d in xticks]
|
|
|
-
|
|
|
- buf = fig_flush(ax, fig, xticks=xticks, xlables=xlables)
|
|
|
-
|
|
|
- mchid_ratios = sorted(mchid_ratios, key=lambda x: (x[1], x[0]), reverse=True)
|
|
|
- result = []
|
|
|
- for mchid,ratio in mchid_ratios:
|
|
|
- result.append(f'{mchid}:{ratio}')
|
|
|
-
|
|
|
- return buf, result
|
|
|
-
|
|
|
def _label(self, chname, succ, count, card_type=None, spec=None):
|
|
|
_card_type = None
|
|
|
if card_type == 1:
|
|
@@ -192,105 +120,4 @@ class MerchantPainter(object):
|
|
|
ratio = 0.00
|
|
|
lable += f":{succ}/{count}={ratio}%"
|
|
|
|
|
|
- return lable,ratio
|
|
|
-
|
|
|
- ##################################################################################################################################################
|
|
|
- def _fig_bar_funs(self):
|
|
|
- def create():
|
|
|
- fig = Figure(figsize=(19, 16))
|
|
|
- ax_count, ax_amount = fig.subplots(2, 1)
|
|
|
- ax_count.set_title('sending order count monitor')
|
|
|
- ax_count.set(xlabel='merchant id', ylabel='count')
|
|
|
-
|
|
|
- ax_amount.set_title('sending order amount monitor')
|
|
|
- ax_amount.set(xlabel='merchant id', ylabel='amount')
|
|
|
- return ax_count, ax_amount, fig
|
|
|
-
|
|
|
- def end(ax, xticks=None, xlables=None, yticks=None, ylables=None):
|
|
|
- if xticks is not None:
|
|
|
- ax.set_xticks(ticks=xticks)
|
|
|
- if xlables is not None:
|
|
|
- ax.set_xticklabels(xlables)
|
|
|
-
|
|
|
- if yticks is not None:
|
|
|
- ax.set_yticks(ticks=yticks)
|
|
|
- if ylables is not None:
|
|
|
- ax.set_yticklabels(ylables)
|
|
|
-
|
|
|
- ax.legend()
|
|
|
- ax.grid()
|
|
|
-
|
|
|
- def flush(fig):
|
|
|
- fig.autofmt_xdate()
|
|
|
- buf = BytesIO()
|
|
|
- fig.savefig(buf, format="png")
|
|
|
- return buf
|
|
|
-
|
|
|
- return create, end,flush
|
|
|
-
|
|
|
- def paint_refilling(self):
|
|
|
- tuple_pathes = self._reader.many_tuple_path(self._days, self._mchids, self._card_types, self._spec)
|
|
|
- gen = allpathes(self._reader, tuple_pathes, self._days, self._spec)
|
|
|
- if len(self._days) == 0:
|
|
|
- return BytesIO()
|
|
|
-
|
|
|
- day_stamp = self._days[0]
|
|
|
- fig_create, fig_end, fig_flush = self._fig_bar_funs()
|
|
|
- ax_count, ax_amount, fig = fig_create()
|
|
|
-
|
|
|
- lables = list()
|
|
|
- datas = list()
|
|
|
- mchids = list()
|
|
|
- for _mchid, _card_type, _spec, _data in gen:
|
|
|
- lables.append(f"{_mchid}")
|
|
|
- logger.debug(_mchid)
|
|
|
- mchids.append(_mchid)
|
|
|
- ret = calc_morder_send(_data, pos_map, self._start_time - day_stamp, self._end_time - day_stamp)
|
|
|
- datas.append(ret)
|
|
|
- send_count, submit_count, succ_count, fail_count, submit_amount, succ_amount, fail_amount, send_amount, lack = ret
|
|
|
- logger.debug("send=%d submit=%d succ=%d fail=%d",send_count, submit_count, succ_count, fail_count)
|
|
|
- cratio = succ_count / (succ_count + fail_count + 0.0001)
|
|
|
- aratio = succ_amount / (succ_amount + fail_amount + 0.0001)
|
|
|
- logger.debug("cratio=%.2f aratio=%.2f", cratio, aratio)
|
|
|
-
|
|
|
- send_count, submit_count, succ_count, fail_count, submit_amount, succ_amount, fail_amount, send_amount, lack = zip(*datas)
|
|
|
- self.draw_count(ax_count, lables, send_count, submit_count, succ_count, fail_count, fig_end)
|
|
|
- self.draw_amount(ax_amount, lables, submit_amount, succ_amount, fail_amount, send_amount, lack, fig_end)
|
|
|
-
|
|
|
- return fig_flush(fig), mchids
|
|
|
-
|
|
|
- def draw_count(self, ax, lables, send_count, submit_count, succ_count, fail_count, fig_end):
|
|
|
- width = 0.24
|
|
|
- x_asix = np.arange(len(lables))
|
|
|
-
|
|
|
- rect_send = ax.bar(x_asix - width * 0.5, list(send_count), width, label='sending', align='center')
|
|
|
- rect_submit = ax.bar(x_asix - width * 1.5, list(submit_count), width, label='summit',align='center')
|
|
|
- rect_succ = ax.bar(x_asix + width * 0.5, list(succ_count), width, label='succ',align='center')
|
|
|
- rect_fail = ax.bar(x_asix + width * 1.5, list(fail_count), width, label='fail', align='center')
|
|
|
-
|
|
|
- ax.bar_label(rect_send, padding=0, rotation=270, fmt='%d')
|
|
|
- ax.bar_label(rect_submit, padding=0, rotation=270, fmt='%d')
|
|
|
- ax.bar_label(rect_succ, padding=0, rotation=270, fmt='%d')
|
|
|
- ax.bar_label(rect_fail, padding=0, rotation=270, fmt='%d')
|
|
|
-
|
|
|
- fig_end(ax, xticks=x_asix, xlables=lables)
|
|
|
- pass
|
|
|
-
|
|
|
- def draw_amount(self, ax, lables, submit_amount, succ_amount, fail_amount, send_amount, lack, fig_end):
|
|
|
- width = 0.18
|
|
|
- x_asix = np.arange(len(lables))
|
|
|
-
|
|
|
- rect_submit = ax.bar(x_asix - width * 2, list(submit_amount), width, label='summit',align='center')
|
|
|
- rect_send = ax.bar(x_asix - width, list(send_amount), width, label='sending', align='center')
|
|
|
- rect_msucc = ax.bar(x_asix, list(lack), width, label='may succ', align='center')
|
|
|
- rect_succ = ax.bar(x_asix + width, list(succ_amount), width, label='succ',align='center')
|
|
|
- rect_fail = ax.bar(x_asix + width * 2, list(fail_amount), width, label='fail', align='center')
|
|
|
-
|
|
|
- ax.bar_label(rect_submit, padding=0, rotation=270, fmt='%.2f')
|
|
|
- ax.bar_label(rect_send, padding=0, rotation=270, fmt='%.2f')
|
|
|
- ax.bar_label(rect_msucc, padding=0, rotation=270, fmt='%.2f')
|
|
|
- ax.bar_label(rect_succ, padding=0, rotation=270, fmt='%.2f')
|
|
|
- ax.bar_label(rect_fail, padding=0, rotation=270, fmt='%.2f')
|
|
|
-
|
|
|
- fig_end(ax, xticks=x_asix, xlables=lables)
|
|
|
- pass
|
|
|
+ return lable,ratio
|