yeref 0.24.67__tar.gz → 0.24.69__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: yeref
3
- Version: 0.24.67
3
+ Version: 0.24.69
4
4
  Summary: desc-f
5
5
  Author: john smith
6
6
  Dynamic: author
@@ -2,7 +2,7 @@ from setuptools import setup
2
2
 
3
3
  setup(
4
4
  name='yeref',
5
- version='0.24.67',
5
+ version='0.24.69',
6
6
  description='desc-f',
7
7
  author='john smith',
8
8
  packages=['yeref'],
@@ -16238,9 +16238,6 @@ async def return_cohort_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16238
16238
  sql = 'SELECT USER_TID, USER_VARS, USER_LSTS FROM "USER"'
16239
16239
  data_users = await db_select_pg(sql, (), BASE_P)
16240
16240
 
16241
- cohorts = defaultdict(set)
16242
- activity_months = defaultdict(set)
16243
-
16244
16241
  months = ["2025-06", "2025-07", "2025-08", "2025-09"]
16245
16242
  data_users = []
16246
16243
  for _ in range(20):
@@ -16305,15 +16302,16 @@ async def return_cohort_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16305
16302
  ))
16306
16303
  print(f"gen {data_users=}")
16307
16304
 
16305
+
16306
+ cohorts = defaultdict(set)
16307
+ activity_months = defaultdict(set)
16308
+
16308
16309
  for USER_TID, USER_VARS, USER_LSTS in data_users:
16309
16310
  USER_VARS = json.loads(USER_VARS or "{}")
16310
16311
  USER_LSTS = json.loads(USER_LSTS or "{}")
16311
16312
  USER_DT = USER_VARS.get("USER_DT", "")
16312
16313
  USER_DAU = USER_LSTS.get("USER_DAU", [])
16313
16314
 
16314
- if not USER_DT:
16315
- continue
16316
-
16317
16315
  entry_mo = datetime.strptime(USER_DT, "%d-%m-%Y_%H-%M-%S").strftime("%Y-%m")
16318
16316
  cohorts[entry_mo].add(USER_TID)
16319
16317
 
@@ -16325,6 +16323,7 @@ async def return_cohort_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16325
16323
  pass
16326
16324
 
16327
16325
  cohort_months = sorted(cohorts.keys())
16326
+ num_months = len(cohort_months)
16328
16327
 
16329
16328
  def add_months(mo_str, n):
16330
16329
  y, m = map(int, mo_str.split("-"))
@@ -16333,7 +16332,7 @@ async def return_cohort_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16333
16332
  new_m = (total - 1) % 12 + 1
16334
16333
  return f"{new_y:04d}-{new_m:02d}"
16335
16334
 
16336
- num_cohorts = len(cohort_months)
16335
+ # Собираем таблицу посменно по календарным месяцам
16337
16336
  table = []
16338
16337
  header = ["Месяц/Когорта"]
16339
16338
  for mo in cohort_months:
@@ -16341,40 +16340,44 @@ async def return_cohort_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16341
16340
  header.append("∑")
16342
16341
  table.append(header)
16343
16342
 
16344
- # Собираем саму таблицу
16345
- for i in range(num_cohorts):
16343
+ # Матрица для подсчёта retention (counts[i][j] = активных из когорты j в календарном месяце i)
16344
+ counts = [[0] * num_months for _ in range(num_months)]
16345
+ for i in range(num_months):
16346
+ calendar_mo = cohort_months[i]
16346
16347
  row = [f"M{i+1}"]
16347
16348
  row_sum = 0
16348
- for cohort_mo in cohort_months:
16349
- target_mo = add_months(cohort_mo, i)
16350
- if i == 0:
16349
+
16350
+ for j in range(num_months):
16351
+ if j > i:
16352
+ row.append("")
16353
+ continue
16354
+
16355
+ cohort_mo = cohort_months[j]
16356
+ if i == j:
16357
+ # первый месяц когорты
16351
16358
  val = len(cohorts[cohort_mo])
16352
16359
  else:
16353
- cnt = sum(1 for uid in cohorts[cohort_mo] if target_mo in activity_months.get(uid, set()))
16354
- val = cnt
16360
+ # считаем, сколько из когорты j активны в календарном месяце i
16361
+ val = sum(1 for uid in cohorts[cohort_mo] if calendar_mo in activity_months.get(uid, set()))
16362
+
16363
+ counts[i][j] = val
16355
16364
  if val:
16356
16365
  row.append(str(val))
16357
16366
  row_sum += val
16358
16367
  else:
16359
16368
  row.append("")
16369
+
16360
16370
  row.append(str(row_sum))
16361
16371
  table.append(row)
16362
16372
 
16363
- # Считаем общий отток по всем когортам
16373
+ # Считаем средний ежемесячный churn
16364
16374
  total_lost = 0
16365
16375
  total_start = 0
16366
- for cohort_mo in cohort_months:
16367
- counts = []
16368
- for i in range(num_cohorts):
16369
- target_mo = add_months(cohort_mo, i)
16370
- if i == 0:
16371
- count = len(cohorts[cohort_mo])
16372
- else:
16373
- count = sum(1 for uid in cohorts[cohort_mo] if target_mo in activity_months.get(uid, set()))
16374
- counts.append(count)
16375
- for k in range(len(counts) - 1):
16376
- start_cnt = counts[k]
16377
- next_cnt = counts[k + 1]
16376
+ for j in range(num_months):
16377
+ # для каждой когорты собираем по календарным месяцам
16378
+ for i in range(j, num_months - 1):
16379
+ start_cnt = counts[i][j]
16380
+ next_cnt = counts[i + 1][j]
16378
16381
  if start_cnt > 0:
16379
16382
  lost = start_cnt - next_cnt
16380
16383
  total_lost += lost
@@ -16388,7 +16391,7 @@ async def return_cohort_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16388
16391
  for r in table:
16389
16392
  writer.writerow(r)
16390
16393
  writer.writerow([])
16391
- writer.writerow([f"Avg monthly cohort churn: {avg_churn:.2f}%"])
16394
+ writer.writerow([f"Churn ~ ×{avg_churn:.1f} monthly"])
16392
16395
 
16393
16396
  thumb = types.FSInputFile(os.path.join(EXTRA_D, "parse.jpg"))
16394
16397
  await bot.send_document(chat_id=my_tid, document=types.FSInputFile(path), thumbnail=thumb)
@@ -16398,6 +16401,7 @@ async def return_cohort_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16398
16401
  await asyncio.sleep(round(random.uniform(0, 1), 2))
16399
16402
 
16400
16403
 
16404
+
16401
16405
  async def return_retention_metrics(bot, PROJECT_USERNAME, EXTRA_D, BASE_P):
16402
16406
  try:
16403
16407
  sql = 'SELECT USER_TID, USER_VARS, USER_LSTS FROM "USER"'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: yeref
3
- Version: 0.24.67
3
+ Version: 0.24.69
4
4
  Summary: desc-f
5
5
  Author: john smith
6
6
  Dynamic: author
File without changes
File without changes
File without changes
File without changes
File without changes