yeref 0.24.68__tar.gz → 0.24.70__tar.gz
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-0.24.68 → yeref-0.24.70}/PKG-INFO +1 -1
- {yeref-0.24.68 → yeref-0.24.70}/setup.py +1 -1
- {yeref-0.24.68 → yeref-0.24.70}/yeref/yeref.py +70 -43
- {yeref-0.24.68 → yeref-0.24.70}/yeref.egg-info/PKG-INFO +1 -1
- {yeref-0.24.68 → yeref-0.24.70}/pyproject.toml +0 -0
- {yeref-0.24.68 → yeref-0.24.70}/setup.cfg +0 -0
- {yeref-0.24.68 → yeref-0.24.70}/yeref/__init__.py +0 -0
- {yeref-0.24.68 → yeref-0.24.70}/yeref/l_.py +0 -0
- {yeref-0.24.68 → yeref-0.24.70}/yeref/tonweb.js +0 -0
- {yeref-0.24.68 → yeref-0.24.70}/yeref.egg-info/SOURCES.txt +0 -0
- {yeref-0.24.68 → yeref-0.24.70}/yeref.egg-info/dependency_links.txt +0 -0
- {yeref-0.24.68 → yeref-0.24.70}/yeref.egg-info/top_level.txt +0 -0
@@ -16240,7 +16240,7 @@ async def return_cohort_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
|
|
16240
16240
|
|
16241
16241
|
months = ["2025-06", "2025-07", "2025-08", "2025-09"]
|
16242
16242
|
data_users = []
|
16243
|
-
for _ in range(
|
16243
|
+
for _ in range(30):
|
16244
16244
|
# дата входа
|
16245
16245
|
entry_month = random.choice(months)
|
16246
16246
|
entry_day = random.randint(1, 28)
|
@@ -16302,7 +16302,6 @@ async def return_cohort_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
|
|
16302
16302
|
))
|
16303
16303
|
print(f"gen {data_users=}")
|
16304
16304
|
|
16305
|
-
|
16306
16305
|
cohorts = defaultdict(set)
|
16307
16306
|
activity_months = defaultdict(set)
|
16308
16307
|
|
@@ -16312,9 +16311,6 @@ async def return_cohort_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
|
|
16312
16311
|
USER_DT = USER_VARS.get("USER_DT", "")
|
16313
16312
|
USER_DAU = USER_LSTS.get("USER_DAU", [])
|
16314
16313
|
|
16315
|
-
if not USER_DT:
|
16316
|
-
continue
|
16317
|
-
|
16318
16314
|
entry_mo = datetime.strptime(USER_DT, "%d-%m-%Y_%H-%M-%S").strftime("%Y-%m")
|
16319
16315
|
cohorts[entry_mo].add(USER_TID)
|
16320
16316
|
|
@@ -16368,7 +16364,7 @@ async def return_cohort_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
|
|
16368
16364
|
row.append(str(val))
|
16369
16365
|
row_sum += val
|
16370
16366
|
else:
|
16371
|
-
row.append("")
|
16367
|
+
row.append("0")
|
16372
16368
|
|
16373
16369
|
row.append(str(row_sum))
|
16374
16370
|
table.append(row)
|
@@ -16394,7 +16390,7 @@ async def return_cohort_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
|
|
16394
16390
|
for r in table:
|
16395
16391
|
writer.writerow(r)
|
16396
16392
|
writer.writerow([])
|
16397
|
-
writer.writerow([f"
|
16393
|
+
writer.writerow([f"Churn ~ ×{avg_churn:.0f} monthly"])
|
16398
16394
|
|
16399
16395
|
thumb = types.FSInputFile(os.path.join(EXTRA_D, "parse.jpg"))
|
16400
16396
|
await bot.send_document(chat_id=my_tid, document=types.FSInputFile(path), thumbnail=thumb)
|
@@ -16404,7 +16400,6 @@ async def return_cohort_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
|
|
16404
16400
|
await asyncio.sleep(round(random.uniform(0, 1), 2))
|
16405
16401
|
|
16406
16402
|
|
16407
|
-
|
16408
16403
|
async def return_retention_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
|
16409
16404
|
try:
|
16410
16405
|
sql = 'SELECT USER_TID, USER_VARS, USER_LSTS FROM "USER"'
|
@@ -16412,7 +16407,7 @@ async def return_retention_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
|
|
16412
16407
|
|
16413
16408
|
months = ["2025-06", "2025-07", "2025-08", "2025-09"]
|
16414
16409
|
data_users = []
|
16415
|
-
for _ in range(
|
16410
|
+
for _ in range(30):
|
16416
16411
|
# дата входа
|
16417
16412
|
entry_month = random.choice(months)
|
16418
16413
|
entry_day = random.randint(1, 28)
|
@@ -16474,57 +16469,89 @@ async def return_retention_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
|
|
16474
16469
|
))
|
16475
16470
|
print(f"gen {data_users=}")
|
16476
16471
|
|
16477
|
-
#
|
16478
|
-
|
16472
|
+
# Собираем платежи и дату входа для каждого пользователя
|
16473
|
+
rev_by_cohort = defaultdict(lambda: defaultdict(float))
|
16474
|
+
cohort_users = defaultdict(set)
|
16475
|
+
|
16479
16476
|
for USER_TID, USER_VARS, USER_LSTS in data_users:
|
16477
|
+
USER_VARS = json.loads(USER_VARS or "{}")
|
16480
16478
|
USER_LSTS = json.loads(USER_LSTS or "{}")
|
16479
|
+
dt_entry_raw = USER_VARS.get("USER_DT", "").split("_")[0]
|
16480
|
+
if not dt_entry_raw:
|
16481
|
+
continue
|
16482
|
+
cohort_mo = datetime.strptime(dt_entry_raw, "%d-%m-%Y").strftime("%Y-%m")
|
16483
|
+
cohort_users[cohort_mo].add(USER_TID)
|
16484
|
+
|
16481
16485
|
for pay in USER_LSTS.get("USER_PAYMENTS", []):
|
16482
|
-
|
16483
|
-
|
16486
|
+
dt_pay = datetime.strptime(pay.get("DT_START", ""), "%d-%m-%Y_%H-%M-%S")
|
16487
|
+
pay_mo = dt_pay.strftime("%Y-%m")
|
16488
|
+
# вычисляем разницу в месяцах
|
16489
|
+
y0, m0 = map(int, cohort_mo.split("-"))
|
16490
|
+
y1, m1 = map(int, pay_mo.split("-"))
|
16491
|
+
offset = (y1 - y0) * 12 + (m1 - m0)
|
16492
|
+
if offset < 0:
|
16493
|
+
continue
|
16484
16494
|
amt = float(pay.get("AMOUNT", 0)) * 0.013
|
16485
|
-
|
16486
|
-
|
16487
|
-
# список всех месяцев с выручкой, отсортированный
|
16488
|
-
all_months = sorted({mo for revs in user_month_rev.values() for mo in revs.keys()})
|
16495
|
+
rev_by_cohort[cohort_mo][offset] += amt
|
16489
16496
|
|
16490
|
-
|
16491
|
-
|
16492
|
-
|
16493
|
-
|
16494
|
-
|
16495
|
-
|
16496
|
-
# общая выручка в prev_mo
|
16497
|
-
prev_total = sum(user_month_rev[u][prev_mo] for u in user_month_rev if prev_mo in user_month_rev[u])
|
16498
|
-
if prev_total == 0:
|
16499
|
-
results.append({"MO": mo, "NRR": ""})
|
16500
|
-
continue
|
16501
|
-
# выручка текущего месяца от тех же пользователей
|
16502
|
-
curr_existing = sum(
|
16503
|
-
user_month_rev[u][mo]
|
16504
|
-
for u in user_month_rev
|
16505
|
-
if prev_mo in user_month_rev[u] and mo in user_month_rev[u]
|
16506
|
-
)
|
16507
|
-
nrr = curr_existing / prev_total
|
16508
|
-
results.append({"MO": mo, "NRR": f"{nrr * 100:.2f}"})
|
16497
|
+
cohort_months = sorted(cohort_users.keys())
|
16498
|
+
# Определяем максимальный период
|
16499
|
+
max_offset = 0
|
16500
|
+
for c in cohort_months:
|
16501
|
+
if rev_by_cohort[c]:
|
16502
|
+
max_offset = max(max_offset, max(rev_by_cohort[c].keys()))
|
16509
16503
|
|
16510
|
-
#
|
16511
|
-
|
16512
|
-
avg_nrr = f"{(sum(vals) / len(vals)):.2f}" if vals else ""
|
16504
|
+
# Сумма выручки M1 для каждой когорты
|
16505
|
+
base_rev = {c: rev_by_cohort[c].get(0, 0.0) for c in cohort_months}
|
16513
16506
|
|
16507
|
+
# Формируем CSV-таблицу
|
16514
16508
|
path = os.path.join(EXTRA_D, "4_retention_metrics.csv")
|
16515
16509
|
with open(path, "w", newline="", encoding="utf-8") as f:
|
16516
16510
|
writer = csv.writer(f)
|
16517
|
-
|
16518
|
-
|
16519
|
-
|
16511
|
+
# Заголовок
|
16512
|
+
header = ["Месяц / Когорта"]
|
16513
|
+
for c in cohort_months:
|
16514
|
+
header.append(f"{c} ({len(cohort_users[c])})")
|
16515
|
+
header.append("∑")
|
16516
|
+
writer.writerow(header)
|
16517
|
+
|
16518
|
+
# Строки M1..M{max_offset+1}
|
16519
|
+
for i in range(max_offset + 1):
|
16520
|
+
row_label = f"M{i+1} ({i} мес)"
|
16521
|
+
row = [row_label]
|
16522
|
+
row_sum = 0.0
|
16523
|
+
for c in cohort_months:
|
16524
|
+
rev = rev_by_cohort[c].get(i, 0.0)
|
16525
|
+
if rev > 0 and base_rev[c] > 0:
|
16526
|
+
pct = rev / base_rev[c] * 100
|
16527
|
+
cell = f"{rev:.1f} ({pct:.0f}%)"
|
16528
|
+
row.append(cell)
|
16529
|
+
row_sum += rev
|
16530
|
+
else:
|
16531
|
+
row.append("")
|
16532
|
+
row.append(f"{row_sum:.1f}")
|
16533
|
+
writer.writerow(row)
|
16534
|
+
|
16535
|
+
# Средний рост NRR
|
16536
|
+
growths = []
|
16537
|
+
for c in cohort_months:
|
16538
|
+
for i in range(1, max_offset + 1):
|
16539
|
+
prev = rev_by_cohort[c].get(i - 1, 0.0)
|
16540
|
+
curr = rev_by_cohort[c].get(i, 0.0)
|
16541
|
+
if prev > 0:
|
16542
|
+
growths.append((curr - prev) / prev)
|
16543
|
+
avg_growth = (sum(growths) / len(growths) * 100) if growths else 0.0
|
16544
|
+
|
16520
16545
|
writer.writerow([])
|
16521
|
-
writer.writerow([f"Avg NRR
|
16546
|
+
writer.writerow([f"Avg monthly NRR growth:", f"{avg_growth:.2f}%"])
|
16522
16547
|
|
16523
16548
|
thumb = types.FSInputFile(os.path.join(EXTRA_D, "parse.jpg"))
|
16524
16549
|
await bot.send_document(chat_id=my_tid, document=types.FSInputFile(path), thumbnail=thumb)
|
16550
|
+
|
16525
16551
|
except Exception as e:
|
16526
16552
|
logger.info(log_ % str(e))
|
16527
16553
|
await asyncio.sleep(round(random.uniform(0, 1), 2))
|
16554
|
+
|
16528
16555
|
# endregion
|
16529
16556
|
|
16530
16557
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|