MerchantAmountPainter.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. from .DataStream import EMchPosmap as pos_map, span_days, time_border, calc_interval
  2. from .MerchantReader import MerchantReader
  3. from .MerchantPainter import MerchantPainter, mch_paths
  4. from matplotlib.figure import Figure
  5. from matplotlib import ticker
  6. from io import BytesIO
  7. import numpy as np
  8. from .algorithm import calc_morder_send
  9. import time as time
  10. import logging
  11. logger = logging.getLogger('painter')
  12. class MerchantAmountPainter(MerchantPainter):
  13. def __init__(self, start_time: int, end_time: int, mchids: set = None, card_types: set = None, spec: int = None, filter_wave: int = None):
  14. self._reader = MerchantReader()
  15. self._mchids, self._card_types, self._spec, self._filter_wave = mchids, card_types, spec, filter_wave
  16. self._days, self._start_time, self._end_time, self._interval = self.calc_time(self._reader, start_time, end_time)
  17. pass
  18. def _fig_bar_funs(self):
  19. def create():
  20. fig = Figure(figsize=(19, 16))
  21. ax_count, ax_amount = fig.subplots(2, 1)
  22. ax_count.set_title('sending order count monitor')
  23. ax_count.set(xlabel='merchant id', ylabel='count')
  24. ax_amount.set_title('sending order amount monitor')
  25. ax_amount.set(xlabel='merchant id', ylabel='amount')
  26. return ax_count, ax_amount, fig
  27. def end(ax, xticks=None, xlables=None, yticks=None, ylables=None):
  28. if xticks is not None:
  29. ax.set_xticks(ticks=xticks)
  30. if xlables is not None:
  31. ax.set_xticklabels(xlables)
  32. if yticks is not None:
  33. ax.set_yticks(ticks=yticks)
  34. if ylables is not None:
  35. ax.set_yticklabels(ylables)
  36. ax.legend()
  37. ax.grid()
  38. def flush(fig):
  39. fig.tight_layout()
  40. buf = BytesIO()
  41. fig.savefig(buf, format="png")
  42. return buf
  43. return create, end,flush
  44. def paint(self):
  45. tuple_pathes = self._reader.many_tuple_path(self._days, self._mchids, self._card_types)
  46. gen = mch_paths(self._reader, tuple_pathes, self._days)
  47. if len(self._days) == 0:
  48. return BytesIO()
  49. day_stamp = self._days[0]
  50. fig_create, fig_end, fig_flush = self._fig_bar_funs()
  51. ax_count, ax_amount, fig = fig_create()
  52. lables = list()
  53. datas = list()
  54. mchids = list()
  55. for _mchid, _card_type, _spec, _data in gen:
  56. lables.append(f"{_mchid}")
  57. logger.debug(_mchid)
  58. mchids.append(_mchid)
  59. ret = calc_morder_send(_data, pos_map, self._start_time - day_stamp, self._end_time - day_stamp)
  60. datas.append(ret)
  61. send_count, submit_count, succ_count, fail_count, submit_amount, succ_amount, fail_amount, send_amount, lack = ret
  62. logger.debug("send=%d submit=%d succ=%d fail=%d",send_count, submit_count, succ_count, fail_count)
  63. cratio = succ_count / (succ_count + fail_count + 0.0001)
  64. aratio = succ_amount / (succ_amount + fail_amount + 0.0001)
  65. logger.debug("cratio=%.2f aratio=%.2f", cratio, aratio)
  66. send_count, submit_count, succ_count, fail_count, submit_amount, succ_amount, fail_amount, send_amount, lack = zip(*datas)
  67. self.draw_count(ax_count, lables, send_count, submit_count, succ_count, fail_count, fig_end)
  68. self.draw_amount(ax_amount, lables, submit_amount, succ_amount, fail_amount, send_amount, lack, fig_end)
  69. return fig_flush(fig), mchids
  70. def draw_count(self, ax, lables, send_count, submit_count, succ_count, fail_count, fig_end):
  71. width = 0.24
  72. x_asix = np.arange(len(lables))
  73. rect_send = ax.bar(x_asix - width * 0.5, list(send_count), width, label='sending', align='center')
  74. rect_submit = ax.bar(x_asix - width * 1.5, list(submit_count), width, label='summit',align='center')
  75. rect_succ = ax.bar(x_asix + width * 0.5, list(succ_count), width, label='succ',align='center')
  76. rect_fail = ax.bar(x_asix + width * 1.5, list(fail_count), width, label='fail', align='center')
  77. alpha = 45
  78. ax.bar_label(rect_send, padding=0, rotation=alpha, fmt='%d')
  79. ax.bar_label(rect_submit, padding=0, rotation=alpha, fmt='%d')
  80. ax.bar_label(rect_succ, padding=0, rotation=alpha, fmt='%d')
  81. ax.bar_label(rect_fail, padding=0, rotation=alpha, fmt='%d')
  82. fig_end(ax, xticks=x_asix, xlables=lables)
  83. pass
  84. def draw_amount(self, ax, lables, submit_amount, succ_amount, fail_amount, send_amount, lack, fig_end):
  85. width = 0.18
  86. x_asix = np.arange(len(lables))
  87. rect_submit = ax.bar(x_asix - width * 2, list(submit_amount), width, label='summit',align='center')
  88. rect_send = ax.bar(x_asix - width, list(send_amount), width, label='sending', align='center')
  89. rect_msucc = ax.bar(x_asix, list(lack), width, label='may succ', align='center')
  90. rect_succ = ax.bar(x_asix + width, list(succ_amount), width, label='succ',align='center')
  91. rect_fail = ax.bar(x_asix + width * 2, list(fail_amount), width, label='fail', align='center')
  92. alpha = 45
  93. ax.bar_label(rect_submit, padding=0, rotation=alpha, fmt='%.2f')
  94. ax.bar_label(rect_send, padding=0, rotation=alpha, fmt='%.2f')
  95. ax.bar_label(rect_msucc, padding=0, rotation=alpha, fmt='%.2f')
  96. ax.bar_label(rect_succ, padding=0, rotation=alpha, fmt='%.2f')
  97. ax.bar_label(rect_fail, padding=0, rotation=alpha, fmt='%.2f')
  98. fig_end(ax, xticks=x_asix, xlables=lables)
  99. pass