Skip to content

Instantly share code, notes, and snippets.

@Vovanda
Last active April 9, 2025 01:53
Show Gist options
  • Save Vovanda/b47f75287542eb1f62704d5881b3d1d8 to your computer and use it in GitHub Desktop.
Save Vovanda/b47f75287542eb1f62704d5881b3d1d8 to your computer and use it in GitHub Desktop.
Отображение случайного сообщения в виджете VK приложения (VKScript)

📌 Виджет сообщества VK Friends2Rand: Генератор случайных текстов для сообщества

Использование социального графа как замены Math.random()

🎯 Особенность подхода

Решение проблемы невозможности использования стандартных источников случайности:

  • 🚫 Нет доступа к генераторам случайных чисел
  • 🚫 Блокировка внешних API-запросов
  • ✅ Используем API.friends.get и социальный граф

🔍 Как это работает?

1. [Донорский профиль] → API.friends.get → 10К друзей (эталонный порядок)
2. [Случайная выборка] → order:random → 2 случайных ID
3. [Конвертация] → Позиция в списке / Общее количество → [0.0, 1.0]
4. [Логика весов] → Распределение по диапазонам

⚖️ Весовая модель

         0.0─┐          
          10% → Редкие
         0.1─┤          
          20% → Средние
         0.3─┤          
          60% → Частые
         0.9─┘          

🔥 Риски для виджета

Риск Вероятность Влияние
🔄 Изменение списка друзей донора ████▌ 70% Нарушение детерминизма
❌ Бан донора ██ 15% Отказ получения friend list
⚙️ Изменение API VK █ 5% Ломается логика выборки

👀 Демонстрация

Виджет доступен в группе VK: Питомник Омская Дружина

// VKScript rand implementation
// VK API random in widget
// ## Генератор псевдослучайных чисел через Friends API ##
// Получаем полный список друзей (для эталонного порядка)
// Используем стабильный аккаунт с большим количеством друзей
var friends_ids = API.friends.get({ user_id: 3972090, count: 10000 }); // user_id можно заменить на другой
// Количество случайных значений (для выбора категории и элемента)
var count_of_randoms = 2;
// Запрашиваем случайные ID из друзей (через order:random)
var rnd_ids = API.friends.get({ user_id: 3972090, order:"random", count: count_of_randoms }).items;
// Нормализованные значения [0..1]
var rnd_values = [];
var i = 0;
// Преобразуем позиции в случайные числа
while(i < count_of_randoms) {
// Нормализация: позиция в списке / общее количество
rnd_values.push(friends_ids.items.indexOf(rnd_ids[i]) / friends_ids.count);
i=i+1;
}
// ## Логика выбора текстов ##
var items = [];
// Весовое распределение:
if (rnd_values[0] <= 0.1) { // 10%
items = [{ "text": "Случайный очень редкий текст" }];
}
if (rnd_values[0] > 0.1 && rnd_values[0] <= 0.3) { // 20%
items = [
{ "text": "Случайный редкий текст №1" },
{ "text": "Случайный редкий текст №2" }
];
}
if (rnd_values[0] > 0.3 && rnd_values[0] <= 0.9) { // 60%
items = [
{ "text": "Случайный частый текст №1" },
{ "text": "Случайный частый текст №2" },
{ "text": "Случайный частый текст №3" }
];
}
// 10% случаев - виджет не отображается
if (rnd_values[0] > 0.9) return null;
// Выбираем конкретный текст из категории
var item_id = parseInt(rnd_values[1] * items.length + 0.5); // Округление через +0.5
return {
"title": "Ты удевишься, но!",
"text": items[item_id].text
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment