yeref 0.24.63__py3-none-any.whl → 0.24.65__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
yeref/yeref.py
CHANGED
@@ -16372,7 +16372,6 @@ async def return_cohort_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
|
|
16372
16372
|
row.append(str(row_sum))
|
16373
16373
|
table.append(row)
|
16374
16374
|
|
16375
|
-
# Записываем CSV
|
16376
16375
|
path = os.path.join(EXTRA_D, "3_cohort_metrics.csv")
|
16377
16376
|
with open(path, "w", newline="", encoding="utf-8") as f:
|
16378
16377
|
writer = csv.writer(f)
|
@@ -16384,6 +16383,128 @@ async def return_cohort_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
|
|
16384
16383
|
except Exception as e:
|
16385
16384
|
logger.info(log_ % str(e))
|
16386
16385
|
await asyncio.sleep(round(random.uniform(0, 1), 2))
|
16386
|
+
|
16387
|
+
|
16388
|
+
async def return_retention_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
|
16389
|
+
try:
|
16390
|
+
sql = 'SELECT USER_TID, USER_VARS, USER_LSTS FROM "USER"'
|
16391
|
+
data_users = await db_select_pg(sql, (), BASE_P)
|
16392
|
+
|
16393
|
+
months = ["2025-06", "2025-07", "2025-08", "2025-09"]
|
16394
|
+
data_users = []
|
16395
|
+
for _ in range(20):
|
16396
|
+
# дата входа
|
16397
|
+
entry_month = random.choice(months)
|
16398
|
+
entry_day = random.randint(1, 28)
|
16399
|
+
entry_date = f"{entry_month}-{entry_day:02}"
|
16400
|
+
entry_dt_obj = datetime.strptime(entry_date, '%Y-%m-%d')
|
16401
|
+
entry_dt = f"{entry_dt_obj.strftime('%d-%m-%Y')}_{datetime.now().strftime('%H-%M-%S')}"
|
16402
|
+
utm = random.choice(["/start", "/startapp"])
|
16403
|
+
|
16404
|
+
# месяцы от входа и дальше
|
16405
|
+
valid_months = [m for m in months if datetime.strptime(m + "-01", "%Y-%m-%d") >= entry_dt_obj.replace(day=1)]
|
16406
|
+
if not valid_months:
|
16407
|
+
valid_months = [entry_month]
|
16408
|
+
|
16409
|
+
user_mau = sorted(random.sample(valid_months, k=random.randint(1, len(valid_months))))
|
16410
|
+
user_dau_dates = set()
|
16411
|
+
txs, payments = [], []
|
16412
|
+
|
16413
|
+
# платеж
|
16414
|
+
if user_mau:
|
16415
|
+
pay_month = random.choice(user_mau)
|
16416
|
+
pay_day = random.randint(1, 28)
|
16417
|
+
pay_date = f"{pay_month}-{pay_day:02}"
|
16418
|
+
dt_pay = datetime.strptime(pay_date, "%Y-%m-%d")
|
16419
|
+
# if dt_pay >= entry_dt_obj:
|
16420
|
+
payments = [{
|
16421
|
+
"TYPE": random.choice(["don", "sub", "pst"]),
|
16422
|
+
"DT_START": f"{dt_pay.strftime('%d-%m-%Y')}_14-00-00",
|
16423
|
+
"DT_END": "0",
|
16424
|
+
"AMOUNT": str(random.randint(1, 10))
|
16425
|
+
}]
|
16426
|
+
user_dau_dates.add(pay_date)
|
16427
|
+
|
16428
|
+
# вход в приложение
|
16429
|
+
user_dau_dates.add(entry_date)
|
16430
|
+
for m in user_mau:
|
16431
|
+
day = random.randint(1, 28)
|
16432
|
+
visit = f"{m}-{day:02}"
|
16433
|
+
dt_visit = datetime.strptime(visit, "%Y-%m-%d")
|
16434
|
+
if dt_visit >= entry_dt_obj and random.random() < 0.7:
|
16435
|
+
user_dau_dates.add(visit)
|
16436
|
+
|
16437
|
+
# статусы (отток) с низкой вероятностью
|
16438
|
+
USER_STATUSES = []
|
16439
|
+
if random.random() < 0.2: # 10% шанс оттока
|
16440
|
+
churn_month = random.choice(valid_months)
|
16441
|
+
churn_day = random.randint(1, 28)
|
16442
|
+
churn_date = f"{churn_month}-{churn_day:02}"
|
16443
|
+
churn_ts = datetime.strptime(churn_date, "%Y-%m-%d").strftime("%d-%m-%Y") + "_23-59-59"
|
16444
|
+
USER_STATUSES = [{random.choice(["left", "kicked"]): churn_ts}]
|
16445
|
+
|
16446
|
+
user_dau = sorted(user_dau_dates)
|
16447
|
+
wallet = f"wallet{random.randint(1, 100)}" if txs else random.choice([f"wallet{random.randint(1, 100)}", ""])
|
16448
|
+
|
16449
|
+
data_users.append((
|
16450
|
+
random.randint(100000, 999999),
|
16451
|
+
json.dumps({"USER_WALLET": wallet, "USER_UTM": utm, "USER_DT": entry_dt}),
|
16452
|
+
json.dumps({"USER_DAU": user_dau, "USER_MAU": user_mau, "USER_TXS": txs,
|
16453
|
+
"USER_PAYMENTS": payments, "USER_STATUSES": USER_STATUSES})
|
16454
|
+
))
|
16455
|
+
print(f"gen {data_users=}")
|
16456
|
+
|
16457
|
+
# собираем выручку по пользователю и месяцу
|
16458
|
+
user_month_rev = defaultdict(lambda: defaultdict(float))
|
16459
|
+
for USER_TID, USER_VARS, USER_LSTS in data_users:
|
16460
|
+
USER_LSTS = json.loads(USER_LSTS or "{}")
|
16461
|
+
for pay in USER_LSTS.get("USER_PAYMENTS", []):
|
16462
|
+
dt_p = datetime.strptime(pay.get("DT_START", ""), "%d-%m-%Y_%H-%M-%S")
|
16463
|
+
mo = dt_p.strftime("%Y-%m")
|
16464
|
+
amt = float(pay.get("AMOUNT", 0)) * 0.013
|
16465
|
+
user_month_rev[USER_TID][mo] += amt
|
16466
|
+
|
16467
|
+
# список всех месяцев с выручкой, отсортированный
|
16468
|
+
all_months = sorted({mo for revs in user_month_rev.values() for mo in revs.keys()})
|
16469
|
+
|
16470
|
+
results = []
|
16471
|
+
for idx, mo in enumerate(all_months):
|
16472
|
+
if idx == 0:
|
16473
|
+
results.append({"MO": mo, "NRR": ""})
|
16474
|
+
continue
|
16475
|
+
prev_mo = all_months[idx - 1]
|
16476
|
+
# общая выручка в prev_mo
|
16477
|
+
prev_total = sum(user_month_rev[u][prev_mo] for u in user_month_rev if prev_mo in user_month_rev[u])
|
16478
|
+
if prev_total == 0:
|
16479
|
+
results.append({"MO": mo, "NRR": ""})
|
16480
|
+
continue
|
16481
|
+
# выручка текущего месяца от тех же пользователей
|
16482
|
+
curr_existing = sum(
|
16483
|
+
user_month_rev[u][mo]
|
16484
|
+
for u in user_month_rev
|
16485
|
+
if prev_mo in user_month_rev[u] and mo in user_month_rev[u]
|
16486
|
+
)
|
16487
|
+
nrr = curr_existing / prev_total
|
16488
|
+
results.append({"MO": mo, "NRR": f"{nrr * 100:.2f}"})
|
16489
|
+
|
16490
|
+
# средний NRR (арифметическое по ненулевым)
|
16491
|
+
vals = [float(r["NRR"]) for r in results if r["NRR"]]
|
16492
|
+
avg_nrr = f"{(sum(vals) / len(vals)):.2f}" if vals else ""
|
16493
|
+
|
16494
|
+
path = os.path.join(EXTRA_D, "4_retention_metrics.csv")
|
16495
|
+
with open(path, "w", newline="", encoding="utf-8") as f:
|
16496
|
+
writer = csv.writer(f)
|
16497
|
+
writer.writerow(["MO", "NRR (%)"])
|
16498
|
+
for r in results:
|
16499
|
+
writer.writerow([r["MO"], r["NRR"]])
|
16500
|
+
writer.writerow([])
|
16501
|
+
writer.writerow([f"Avg NRR (%)", avg_nrr])
|
16502
|
+
|
16503
|
+
thumb = types.FSInputFile(os.path.join(EXTRA_D, "parse.jpg"))
|
16504
|
+
await bot.send_document(chat_id=my_tid, document=types.FSInputFile(path), thumbnail=thumb)
|
16505
|
+
except Exception as e:
|
16506
|
+
logger.info(log_ % str(e))
|
16507
|
+
await asyncio.sleep(round(random.uniform(0, 1), 2))
|
16387
16508
|
# endregion
|
16388
16509
|
|
16389
16510
|
|
@@ -0,0 +1,8 @@
|
|
1
|
+
yeref/__init__.py,sha256=Qpv3o6Xa78VdLcsSRmctGtpnYE9btpAkCekgGhgJyXM,49
|
2
|
+
yeref/l_.py,sha256=LMX_olmJwq-tgoALJCnhV_fGrL_i_43yBLkLIcEVqGo,1176743
|
3
|
+
yeref/tonweb.js,sha256=Jf6aFOQ1OIY4q7fINYz-m5LsI3seMus124M5SYYZmtE,443659
|
4
|
+
yeref/yeref.py,sha256=fze5I1x5ZD0D4OgYpK1sv-bDgu2RXtMGPhDwjiwBa64,1053049
|
5
|
+
yeref-0.24.65.dist-info/METADATA,sha256=Q5AZlJwo8T2kw62j1kSn8eFMPG3O6DBs7KoKHmLDWYo,119
|
6
|
+
yeref-0.24.65.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
7
|
+
yeref-0.24.65.dist-info/top_level.txt,sha256=yCQKchWHbfV-3OuQPYRdi2loypD-nmbDJbtt3OuKKkY,6
|
8
|
+
yeref-0.24.65.dist-info/RECORD,,
|
yeref-0.24.63.dist-info/RECORD
DELETED
@@ -1,8 +0,0 @@
|
|
1
|
-
yeref/__init__.py,sha256=Qpv3o6Xa78VdLcsSRmctGtpnYE9btpAkCekgGhgJyXM,49
|
2
|
-
yeref/l_.py,sha256=LMX_olmJwq-tgoALJCnhV_fGrL_i_43yBLkLIcEVqGo,1176743
|
3
|
-
yeref/tonweb.js,sha256=Jf6aFOQ1OIY4q7fINYz-m5LsI3seMus124M5SYYZmtE,443659
|
4
|
-
yeref/yeref.py,sha256=rAoPHlZIPtypeSgPOOh0OTBFFxTwHk22mfPgHUGAip8,1047232
|
5
|
-
yeref-0.24.63.dist-info/METADATA,sha256=Vx9UiXw9chj2HewsdxkCOVgZU5LuPKp_9htAWA0tU_0,119
|
6
|
-
yeref-0.24.63.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
7
|
-
yeref-0.24.63.dist-info/top_level.txt,sha256=yCQKchWHbfV-3OuQPYRdi2loypD-nmbDJbtt3OuKKkY,6
|
8
|
-
yeref-0.24.63.dist-info/RECORD,,
|
File without changes
|
File without changes
|