From 1a53a3f5f66f416e3d37e651646bd9428d853a5c Mon Sep 17 00:00:00 2001 From: arsam Date: Fri, 18 Sep 2026 23:19:28 +0330 Subject: [PATCH] Import source: app/backend/src/lib/persian Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality. --- app/backend/src/lib/persian.ts | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 app/backend/src/lib/persian.ts diff --git a/app/backend/src/lib/persian.ts b/app/backend/src/lib/persian.ts new file mode 100644 index 0000000..d79d4f7 --- /dev/null +++ b/app/backend/src/lib/persian.ts @@ -0,0 +1,34 @@ +export function normalizeFa(input: string) { + return input + .replace(/[\u200c\u0640]/g, '') + .replace(/[\u064b-\u0652]/g, '') + .replace(/[يى]/g, 'ی') + .replace(/ك/g, 'ک') + .replace(/[أإآٱ]/g, 'ا') + .replace(/\s+/g, ' ') + .trim() + .toLowerCase(); +} + +export function computeStreak(streakCount: number, lastReadAt: Date | null, now: Date): number { + if (!lastReadAt) return 1; + const lastDate = new Date(lastReadAt); + lastDate.setHours(0, 0, 0, 0); + const today = new Date(now); + today.setHours(0, 0, 0, 0); + const diffDays = Math.floor((today.getTime() - lastDate.getTime()) / (1000 * 60 * 60 * 24)); + if (diffDays === 1) return streakCount + 1; + if (diffDays > 1) return 1; + return streakCount; +} + +export function currentStreakIfAlive(streakCount: number, lastReadAt: Date | null, now: Date): number { + if (!lastReadAt) return 0; + const lastDate = new Date(lastReadAt); + lastDate.setHours(0, 0, 0, 0); + const today = new Date(now); + today.setHours(0, 0, 0, 0); + const diffDays = Math.floor((today.getTime() - lastDate.getTime()) / (1000 * 60 * 60 * 24)); + if (diffDays > 1) return 0; + return streakCount; +}