// ৯. দৈনিক ও ধারাবাহিক লগইন অ্যাক্টিভিটি রিওয়ার্ড ইঞ্জিন (Daily, Weekly & Monthly Streak) if (!function_exists('process_user_daily_login_rewards')) { function process_user_daily_login_rewards($pdo, $user_id) { $user_id = intval($user_id); if ($user_id <= 0) return; $today = date('Y-m-d'); // সেশন মেমোরি: আজকের দিনে ইতিমধ্যে চেক হয়ে থাকলে প্রতি পেজে রিপিট কুয়েরি বন্ধ রাখা if (isset($_SESSION['tr_login_streak_checked']) && $_SESSION['tr_login_streak_checked'] === $today) { return; } try { $stmt = $pdo->prepare("SELECT last_login_date, streak_days, total_login_days FROM user_login_streaks WHERE user_id = ? LIMIT 1"); $stmt->execute([$user_id]); $row = $stmt->fetch(); if (!$row) { // নতুন ইউজার: আজ থেকে ১ম স্ট্রিক শুরু (+১ পয়েন্ট দৈনিক বোনাস) $pdo->prepare("INSERT INTO user_login_streaks (user_id, last_login_date, streak_days, total_login_days) VALUES (?, ?, 1, 1)")->execute([$user_id, $today]); $pdo->prepare("UPDATE users SET points = points + 1 WHERE id = ?")->execute([$user_id]); $pdo->prepare("INSERT INTO points_log (user_id, points_earned, action_type, remarks) VALUES (?, 1, 'daily_login_bonus', 'দৈনিক প্রথম লগইন বোনাস')")->execute([$user_id]); add_notification($pdo, $user_id, 'points', "🌟 দৈনিক লগইন বোনাস!", "আজ সাইটে প্রথম লগইন করায় আপনার একাউন্টে +১ পয়েন্ট যুক্ত হয়েছে!", "/profile.php"); } else { $last_date = $row['last_login_date']; if ($last_date === $today) { $_SESSION['tr_login_streak_checked'] = $today; return; } $yesterday = date('Y-m-d', strtotime('-1 day')); $new_streak = 1; if ($last_date === $yesterday) { // টানা ধারাবাহিক লগইন! $new_streak = intval($row['streak_days']) + 1; } $new_total = intval($row['total_login_days']) + 1; $pdo->prepare("UPDATE user_login_streaks SET last_login_date = ?, streak_days = ?, total_login_days = ? WHERE user_id = ?")->execute([$today, $new_streak, $new_total, $user_id]); // ক. দৈনিক লগইন পয়েন্ট প্রদান (+১ pt) $pdo->prepare("UPDATE users SET points = points + 1 WHERE id = ?")->execute([$user_id]); $pdo->prepare("INSERT INTO points_log (user_id, points_earned, action_type, remarks) VALUES (?, 1, 'daily_login_bonus', 'দৈনিক প্রথম লগইন বোনাস')")->execute([$user_id]); add_notification($pdo, $user_id, 'points', "🌟 দৈনিক লগইন বোনাস!", "আজকের দৈনিক প্রথম লগইনের জন্য +১ পয়েন্ট অর্জন করেছেন (স্ট্রিক: {$new_streak} দিন)!", "/profile.php"); // খ. ৭ দিনের সাপ্তাহিক ধারাবাহিকতা বোনাস (+৫ pts) if ($new_streak % 7 === 0) { $pdo->prepare("UPDATE users SET points = points + 5 WHERE id = ?")->execute([$user_id]); $pdo->prepare("INSERT INTO points_log (user_id, points_earned, action_type, remarks) VALUES (?, 5, 'weekly_login_streak', 'টানা ৭ দিন লগইন স্ট্রিক বোনাস')")->execute([$user_id]); add_notification($pdo, $user_id, 'points', "🔥 ৭ দিনের স্ট্রিক বোনাস!", "অভিনন্দন! টানা ৭ দিন সাইটে সক্রিয় থাকায় স্পেশাল সাপ্তাহিক স্ট্রিক বোনাস +৫ পয়েন্ট পেয়েছেন!", "/profile.php"); } // গ. ৩০ দিনের মাসিক সুপার লয়ালটি বোনাস (+২০ pts) if ($new_streak % 30 === 0) { $pdo->prepare("UPDATE users SET points = points + 20 WHERE id = ?")->execute([$user_id]); $pdo->prepare("INSERT INTO points_log (user_id, points_earned, action_type, remarks) VALUES (?, 20, 'monthly_login_streak', 'টানা ৩০ দিন মাসিক লগইন বোনাস')")->execute([$user_id]); add_notification($pdo, $user_id, 'points', "👑 ৩০ দিনের মাসিক সুপার বোনাস!", "অসাধারণ! টানা ৩০ দিন সাইটে সক্রিয় থাকার জন্য মেগা লয়ালটি রিওয়ার্ড +২০ পয়েন্ট পেয়েছেন!", "/profile.php"); } } $_SESSION['tr_login_streak_checked'] = $today; } catch (Exception $e) {} } } // ১০. স্বয়ংক্রিয় ইমেজ কম্প্রেশন ইঞ্জিন (Auto-Compress to Under 100 KB WebP/JPEG) if (!function_exists('compress_image_under_max_kb')) { function compress_image_under_max_kb($source_file, $target_file, $max_kb = 100, $max_width = 1200) { $info = @getimagesize($source_file); if (!$info) return false; $mime = $info['mime']; $orig_width = $info[0]; $orig_height = $info[1]; // ক. ইমেজ রিসোর্স লোড করা switch ($mime) { case 'image/jpeg': case 'image/jpg': $image = @imagecreatefromjpeg($source_file); break; case 'image/png': $image = @imagecreatefrompng($source_file); break; case 'image/webp': $image = function_exists('imagecreatefromwebp') ? @imagecreatefromwebp($source_file) : false; break; case 'image/gif': $image = @imagecreatefromgif($source_file); break; default: $image = false; } if (!$image) return false; // খ. ডাইমেনশন অপ্টিমাইজেশন (সর্বোচ্চ ১২০০ পিক্সেল উইডথ) $new_width = $orig_width; $new_height = $orig_height; if ($orig_width > $max_width) { $new_width = $max_width; $new_height = intval(round(($orig_height / $orig_width) * $max_width)); } $canvas = imagecreatetruecolor($new_width, $new_height); // ট্রান্সপারেন্সি ও আলফা চ্যানেল সংরক্ষণ $use_webp = function_exists('imagewebp'); if ($mime === 'image/png' || $mime === 'image/webp') { imagealphablending($canvas, false); imagesavealpha($canvas, true); $transparent = imagecolorallocatealpha($canvas, 255, 255, 255, 127); imagefilledrectangle($canvas, 0, 0, $new_width, $new_height, $transparent); } else { $white = imagecolorallocate($canvas, 255, 255, 255); imagefilledrectangle($canvas, 0, 0, $new_width, $new_height, $white); } imagecopyresampled($canvas, $image, 0, 0, 0, 0, $new_width, $new_height, $orig_width, $orig_height); imagedestroy($image); // গ. কোয়ালিটি লুপ: স্বয়ংক্রিয়ভাবে ১০০ KB এর নিচে নামানো $max_bytes = $max_kb * 1024; $qualities = [82, 72, 60, 48, 38]; foreach ($qualities as $q) { if ($use_webp) { imagealphablending($canvas, true); imagesavealpha($canvas, true); imagewebp($canvas, $target_file, $q); } else { imagejpeg($canvas, $target_file, $q); } if (file_exists($target_file) && filesize($target_file) <= $max_bytes) { imagedestroy($canvas); return true; } } // ঘ. অতিরিক্ত বড় রেজোলিউশনের ক্ষেত্রে স্কেলিং করে ফাইনাল কম্প্রেশন $scaled_w = intval(round($new_width * 0.75)); $scaled_h = intval(round($new_height * 0.75)); $small_canvas = imagecreatetruecolor($scaled_w, $scaled_h); if ($use_webp) { imagealphablending($small_canvas, false); imagesavealpha($small_canvas, true); } else { $white = imagecolorallocate($small_canvas, 255, 255, 255); imagefilledrectangle($small_canvas, 0, 0, $scaled_w, $scaled_h, $white); } imagecopyresampled($small_canvas, $canvas, 0, 0, 0, 0, $scaled_w, $scaled_h, $new_width, $new_height); imagedestroy($canvas); if ($use_webp) { imagealphablending($small_canvas, true); imagesavealpha($small_canvas, true); imagewebp($small_canvas, $target_file, 55); } else { imagejpeg($small_canvas, $target_file, 55); } imagedestroy($small_canvas); return true; } } // ১১. ব্র্যান্ডেড ইমেল ভেরিফিকেশন ওটিপি প্রেরক ফাংশন (TipsRound.Com Email Verification) if (!function_exists('send_tipsround_verification_email')) { function send_tipsround_verification_email($to_email, $user_name, $otp_code) { $subject = "=?UTF-8?B?" . base64_encode("TipsRound.Com - ইমেল ভেরিফিকেশন কোড") . "?="; $from_email = "noreply@tipsround.com"; $from_header = "TipsRound.Com <" . $from_email . ">"; $headers = "MIME-Version: 1.0\r\n"; $headers .= "Content-Type: text/html; charset=UTF-8\r\n"; $headers .= "From: " . $from_header . "\r\n"; $headers .= "Reply-To: support@tipsround.com\r\n"; $headers .= "X-Mailer: PHP/" . phpversion() . "\r\n"; $current_year = date("Y"); $user_name_safe = htmlspecialchars($user_name, ENT_QUOTES, 'UTF-8'); $message = <<