yeref 0.24.71__py3-none-any.whl → 0.24.73__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
@@ -16405,6 +16405,70 @@ async def return_retention_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16405
16405
  sql = 'SELECT USER_TID, USER_VARS, USER_LSTS FROM "USER"'
16406
16406
  data_users = await db_select_pg(sql, (), BASE_P)
16407
16407
 
16408
+ months = ["2025-06", "2025-07", "2025-08", "2025-09"]
16409
+ data_users = []
16410
+ for _ in range(30):
16411
+ # дата входа
16412
+ entry_month = random.choice(months)
16413
+ entry_day = random.randint(1, 28)
16414
+ entry_date = f"{entry_month}-{entry_day:02}"
16415
+ entry_dt_obj = datetime.strptime(entry_date, '%Y-%m-%d')
16416
+ entry_dt = f"{entry_dt_obj.strftime('%d-%m-%Y')}_{datetime.now().strftime('%H-%M-%S')}"
16417
+ utm = random.choice(["/start", "/startapp"])
16418
+
16419
+ # месяцы от входа и дальше
16420
+ valid_months = [m for m in months if datetime.strptime(m + "-01", "%Y-%m-%d") >= entry_dt_obj.replace(day=1)]
16421
+ if not valid_months:
16422
+ valid_months = [entry_month]
16423
+
16424
+ user_mau = sorted(random.sample(valid_months, k=random.randint(1, len(valid_months))))
16425
+ user_dau_dates = set()
16426
+ txs, payments = [], []
16427
+
16428
+ # платеж
16429
+ if user_mau:
16430
+ pay_month = random.choice(user_mau)
16431
+ pay_day = random.randint(1, 28)
16432
+ pay_date = f"{pay_month}-{pay_day:02}"
16433
+ dt_pay = datetime.strptime(pay_date, "%Y-%m-%d")
16434
+ # if dt_pay >= entry_dt_obj:
16435
+ payments = [{
16436
+ "TYPE": random.choice(["don", "sub", "pst"]),
16437
+ "DT_START": f"{dt_pay.strftime('%d-%m-%Y')}_14-00-00",
16438
+ "DT_END": "0",
16439
+ "AMOUNT": str(random.randint(1, 10))
16440
+ }]
16441
+ user_dau_dates.add(pay_date)
16442
+
16443
+ # вход в приложение
16444
+ user_dau_dates.add(entry_date)
16445
+ for m in user_mau:
16446
+ day = random.randint(1, 28)
16447
+ visit = f"{m}-{day:02}"
16448
+ dt_visit = datetime.strptime(visit, "%Y-%m-%d")
16449
+ if dt_visit >= entry_dt_obj and random.random() < 0.7:
16450
+ user_dau_dates.add(visit)
16451
+
16452
+ # статусы (отток) с низкой вероятностью
16453
+ USER_STATUSES = []
16454
+ if random.random() < 0.2: # 10% шанс оттока
16455
+ churn_month = random.choice(valid_months)
16456
+ churn_day = random.randint(1, 28)
16457
+ churn_date = f"{churn_month}-{churn_day:02}"
16458
+ churn_ts = datetime.strptime(churn_date, "%Y-%m-%d").strftime("%d-%m-%Y") + "_23-59-59"
16459
+ USER_STATUSES = [{random.choice(["left", "kicked"]): churn_ts}]
16460
+
16461
+ user_dau = sorted(user_dau_dates)
16462
+ wallet = f"wallet{random.randint(1, 100)}" if txs else random.choice([f"wallet{random.randint(1, 100)}", ""])
16463
+
16464
+ data_users.append((
16465
+ random.randint(100000, 999999),
16466
+ json.dumps({"USER_WALLET": wallet, "USER_UTM": utm, "USER_DT": entry_dt}),
16467
+ json.dumps({"USER_DAU": user_dau, "USER_MAU": user_mau, "USER_TXS": txs,
16468
+ "USER_PAYMENTS": payments, "USER_STATUSES": USER_STATUSES})
16469
+ ))
16470
+ print(f"gen {data_users=}")
16471
+
16408
16472
  rev_by_cohort = defaultdict(lambda: defaultdict(float))
16409
16473
  cohort_users = defaultdict(set)
16410
16474
 
@@ -16432,35 +16496,39 @@ async def return_retention_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16432
16496
  if not cohort_months:
16433
16497
  return
16434
16498
 
16435
- max_offset = 0
16436
- for c in cohort_months:
16437
- if rev_by_cohort[c]:
16438
- max_offset = max(max_offset, max(rev_by_cohort[c].keys()))
16499
+ # Функция прибавления месяцев
16500
+ def add_months(mo_str, n):
16501
+ y, m = map(int, mo_str.split("-"))
16502
+ total = m + n
16503
+ new_y = y + (total - 1) // 12
16504
+ new_m = (total - 1) % 12 + 1
16505
+ return f"{new_y:04d}-{new_m:02d}"
16439
16506
 
16440
- base_rev = {c: rev_by_cohort[c].get(0, 0.0) for c in cohort_months}
16507
+ num_cohorts = len(cohort_months)
16508
+ first_cohort = cohort_months[0]
16441
16509
 
16442
16510
  path = os.path.join(EXTRA_D, "4_retention_metrics.csv")
16443
16511
  with open(path, "w", newline="", encoding="utf-8") as f:
16444
16512
  writer = csv.writer(f)
16445
- header = ["Месяц / Когорта"] + [
16513
+ header = ["Месяц/Когорта"] + [
16446
16514
  f"{c} ({len(cohort_users[c])})" for c in cohort_months
16447
16515
  ] + ["∑"]
16448
16516
  writer.writerow(header)
16449
16517
 
16450
- for i in range(max_offset + 1):
16451
- row = [f"M{i+1} ({i} мес)"]
16518
+ for i in range(num_cohorts):
16519
+ calendar_mo = add_months(first_cohort, i)
16520
+ row = [f"M{i+1}"]
16452
16521
  row_sum = 0.0
16453
16522
  for c in cohort_months:
16454
- rev = rev_by_cohort[c].get(i, 0.0)
16455
- if i == 0:
16456
- pct = 100
16457
- cell = f"{rev:.1f} ({pct}%)"
16458
- row.append(cell)
16459
- row_sum += rev
16523
+ y0, m0 = map(int, c.split("-"))
16524
+ y1, m1 = map(int, calendar_mo.split("-"))
16525
+ offset = (y1 - y0) * 12 + (m1 - m0)
16526
+ if offset < 0:
16527
+ row.append("")
16460
16528
  else:
16461
- if base_rev[c] > 0 and rev > 0:
16462
- pct = rev / base_rev[c] * 100
16463
- cell = f"{rev:.1f} ({pct:.0f}%)"
16529
+ rev = rev_by_cohort[c].get(offset, 0.0)
16530
+ if rev > 0:
16531
+ cell = f"{rev:.1f}"
16464
16532
  row.append(cell)
16465
16533
  row_sum += rev
16466
16534
  else:
@@ -16475,6 +16543,7 @@ async def return_retention_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16475
16543
  logger.info(log_ % str(e))
16476
16544
  await asyncio.sleep(round(random.uniform(0, 1), 2))
16477
16545
 
16546
+
16478
16547
  # endregion
16479
16548
 
16480
16549
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: yeref
3
- Version: 0.24.71
3
+ Version: 0.24.73
4
4
  Summary: desc-f
5
5
  Author: john smith
6
6
  Dynamic: author
@@ -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=MwzWQTSqgeehsMOK_9lsWv6BwiTcmt3vIaOggbD04lk,1053721
5
+ yeref-0.24.73.dist-info/METADATA,sha256=VukAmV-sflraUOmoDqfbN94BUREeH_TMfdieUYeyq3I,119
6
+ yeref-0.24.73.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
7
+ yeref-0.24.73.dist-info/top_level.txt,sha256=yCQKchWHbfV-3OuQPYRdi2loypD-nmbDJbtt3OuKKkY,6
8
+ yeref-0.24.73.dist-info/RECORD,,
@@ -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=mrSmu7Lp9EB_o7Xh47tbZJxZamujZfBXlLtTrAEKUsU,1050482
5
- yeref-0.24.71.dist-info/METADATA,sha256=nqpY31UqBjgapTkhgjx3PBXVkF5ApMcWmugeYGUSYVI,119
6
- yeref-0.24.71.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
7
- yeref-0.24.71.dist-info/top_level.txt,sha256=yCQKchWHbfV-3OuQPYRdi2loypD-nmbDJbtt3OuKKkY,6
8
- yeref-0.24.71.dist-info/RECORD,,