公式解析类

This commit is contained in:
wuaho 2021-08-02 11:25:09 +08:00
parent 6e36de0889
commit c92be39e49
3 changed files with 67 additions and 42 deletions

View File

@ -74,7 +74,8 @@ async def event_model(
df = await ckdb.query_dataframe(sql) df = await ckdb.query_dataframe(sql)
df.fillna(0,inplace=True) df.fillna(0,inplace=True)
if df.shape[0] == 0: if df.shape[0] == 0:
return schemas.Msg(code=0, msg='ok', data=[q]) continue
# return schemas.Msg(code=0, msg='ok', data=[q])
if groupby: if groupby:
# 有分组 # 有分组

View File

@ -247,7 +247,7 @@ class Settings(BaseSettings):
ARITHMETIC = { ARITHMETIC = {
'+': lambda x, y: x + y, '+': lambda x, y: x + y,
'-': lambda x, y: x - y, '-': lambda x, y: x - y,
'x': lambda x, y: x * y, '*': lambda x, y: x * y,
'/': lambda x, y: x / y, '/': lambda x, y: x / y,
} }

View File

@ -1,3 +1,4 @@
import re
from typing import Tuple from typing import Tuple
import arrow import arrow
@ -18,6 +19,68 @@ from db import get_database
from db.redisdb import get_redis_pool, RedisDrive from db.redisdb import get_redis_pool, RedisDrive
class CustomEvent:
def __init__(self, tbl, string, format):
self.tbl = tbl
self.string = string
self.pattern = re.compile('[+\-*/]')
self.format = format
self.events_name = []
def _parse(self, s):
m = s.split('.')
if len(m) == 3:
event_name, attr, comp = m
self.events_name.append(event_name)
return getattr(func, comp)(getattr(func, 'if')(getattr(self.tbl.c, '#event_name') == event_name,
getattr(self.tbl.c, attr), 0))
elif len(m) == 2:
event_name, comp = m
self.events_name.append(event_name)
# 总次数
if comp == 'total_count':
return func.sum(getattr(func, 'if')(getattr(self.tbl.c, '#event_name') == event_name, 1, 0))
elif comp == 'touch_user_count':
return func.uniqCombined(getattr(func, 'if')(getattr(self.tbl.c, '#event_name') == event_name,
getattr(self.tbl.c, '#account_id'), None))
elif comp == 'touch_user_avg':
return func.divide(
func.sum(getattr(func, 'if')(getattr(self.tbl.c, '#event_name') == event_name, 1, 0)),
func.uniqCombined(getattr(func, 'if')(getattr(self.tbl.c, '#event_name') == event_name,
getattr(self.tbl.c, '#account_id'), None)))
elif len(m) == 1:
n = int(m[0])
return n
def str2obj(self, factors, opts):
sel = None
for i, factor in enumerate(factors):
if i == 0:
sel = self._parse(factor)
else:
tmp = self._parse(factor)
sel = settings.ARITHMETIC[opts[i - 1]](sel, tmp)
return sel
def parse(self):
factors = self.pattern.split(self.string)
opts = self.pattern.findall(self.string)
sel = self.str2obj(factors, opts)
decimal = 2
if self.format == 'percent':
sel = sel * 100
elif format == 'integer':
decimal = 0
elif format == 'float':
decimal = 2
sel = func.round(sel, decimal).label('values')
res = {
'event_name': self.events_name,
'select': sel
}
return res
class BehaviorAnalysis: class BehaviorAnalysis:
def __init__(self, game: str, data_in: schemas.CkQuery, rdb: RedisDrive = Depends(get_redis_pool)): def __init__(self, game: str, data_in: schemas.CkQuery, rdb: RedisDrive = Depends(get_redis_pool)):
self.game = game self.game = game
@ -198,45 +261,6 @@ class BehaviorAnalysis:
'unit_num': self.unit_num 'unit_num': self.unit_num
} }
def custom_event(self, s, format='float'):
def f(m):
if len(m) == 3:
event_name, attr, comp = m
return getattr(func, comp)(getattr(func, 'if')(getattr(self.event_tbl.c, '#event_name') == event_name,
getattr(self.event_tbl.c, attr), 0))
elif len(m) == 2:
event_name, comp = m
# 总次数
if comp == 'total_count':
return func.sum(getattr(func, 'if')(getattr(self.event_tbl.c, '#event_name') == event_name, 1, 0))
elif comp == 'touch_user_count':
return func.uniqCombined(getattr(func, 'if')(getattr(self.event_tbl.c, '#event_name') == event_name,
getattr(self.event_tbl.c, '#account_id'), None))
elif comp == 'touch_user_avg':
return func.divide(
func.sum(getattr(func, 'if')(getattr(self.event_tbl.c, '#event_name') == event_name, 1, 0)),
func.uniqCombined(getattr(func, 'if')(getattr(self.event_tbl.c, '#event_name') == event_name,
getattr(self.event_tbl.c, '#account_id'), None)))
opt = ({'+', '-', '*', '/'} & set(s)).pop()
a, b = s.split(opt)
r1 = a.split('.')
n = 1
decimal = 2
if format == 'percent':
n = 100
elif format == 'integer':
decimal = 0
if '.' in b:
r2 = b.split('.')
return {'event_name': [r1[0], r2[0]],
'select': func.round(settings.ARITHMETIC[opt](f(r1) * n, f(r2)), decimal).label('values')
}
elif b.isdigit():
return {'event_name': [r1[0]],
'select': func.round(settings.ARITHMETIC[opt](f(r1) * n, int(b)), decimal).label('values')
}
def event_model_sql(self): def event_model_sql(self):
sqls = [] sqls = []
event_time_col = getattr(self.event_tbl.c, '#event_time') event_time_col = getattr(self.event_tbl.c, '#event_time')
@ -255,7 +279,7 @@ class BehaviorAnalysis:
if event.get('customEvent'): if event.get('customEvent'):
formula = event.get('customEvent') formula = event.get('customEvent')
custom = self.custom_event(formula, format) custom = CustomEvent(self.event_tbl, formula, format).parse()
event_name = custom['event_name'] event_name = custom['event_name']
where = [event_name_col.in_(event_name)] where = [event_name_col.in_(event_name)]
event_filter, _ = self.handler_filts(*event['filts']) event_filter, _ = self.handler_filts(*event['filts'])