Каким по счету вы родились в семье
Страница свободного номера
Вообразите грандиозную очередь, в которой выстроились все когда-либо жившие на Земле люди — от первобытного предка до младенца, появившегося на свет секунду назад. Эта бесконечная цепь насчитывает около ста семнадцати миллиардов человек. Где-то в ней занимаете свое место и вы. Персональный порядковый номер принадлежит вам с самого рождения, его невозможно аннулировать или передать кому-то другому. До недавнего времени его просто никто не озвучивал.
Я обнаружил это совершенно случайно, изучая материалы демографов из Population Reference Bureau: к 2022 году совокупное число рожденных за всю историю людей достигло примерно 117 миллиардов. Сейчас здравствует около восьми с небольшим миллиардов, а оставшиеся почти сто девять миллиардов и составляют летопись человечества.
Раз каждого можно учесть, значит, у каждого есть свой порядковый номер. Его нужно лишь корректно вычислить.
Как рассчитывается номер
Значение определяется исключительно датой рождения. Конкретный день неизменно выдает идентичный результат — независимо от того, где происходят вычисления, на сервере или на бумаге. Никакого ручного распределения нет: цифру можно узнать для любой даты, даже для той, которой еще предстоит наступить. У человека, который появится на свет через год, уже есть свой номер, пока еще не названный вслух.
В основе лежит массив из пятидесяти опорных точек, отражающих динамику прироста населения к определенным годам. Исторический срез (38 точек) взят из публикации демографов за 2022 год. Еще дюжина точек устремлена в будущее вплоть до 3400 года — это уже не статистика, а математическая проекция с учетом прогнозируемого спада рождаемости, о чем честно предупреждает исходный код. Точки распределены неравномерно: на период с 1950 по 2022 год приходится двадцать девять из них, тогда как на предшествующие двести тысячелетий — всего девять. О современниках нам известно несравненно больше, чем о далеких предках.

Интерполяция между соседними точками выполняется по прямой линии:
function interpolate(year: number): number {
for (let i = 0; i < ANCHORS.length - 1; i++) {
const a = ANCHORS[i]!, b = ANCHORS[i + 1]!;
if (year >= a.year && year <= b.year) {
const t = (year - a.year) / (b.year - a.year);
return a.cumulative + t * (b.cumulative - a.cumulative);
}
}
return 0;
}
Можно было бы выстроить сглаженную кривую, но я намеренно отказался от этой идеи. Между плотно расположенными современными данными разница минимальна, а в глубокой древности кривая породила бы вымышленные изгибы. Прямая линия честно транслирует сухие цифры из таблиц.
Внутри календарного года позиция вычисляется исходя из доли прошедших дней:
const fraction = dayOfYear / daysInYear(year);
const number = Math.round(yearStart + fraction * (yearEnd - yearStart));
Чем дальше выбранная эпоха отстоит от двадцатого столетия, тем выше уровень неопределенности, о чем сервис предупреждает пользователя:
после 1900 → разброс в тысячу
раньше 1900 → разброс в 50 миллионов
раньше 1500 → разброс в 500 миллионов
до нашей эры → разброс в 2 миллиарда
Две разрозненные таблицы, объединенные в единый массив. Изначально данные по древним эпохам брались из старого демографического исследования, а итоговые показатели — из нового. Суть цифр была идентичной, однако десять миллиардов древних рождений, отсутствовавших в старой версии, растворились среди ближайших интервалов, пришедшихся на 1990–2026 годы. В результате получалось, что в наши дни ежегодно рождается до 550 миллионов человек при реальной цифре в сто тридцать два миллиона.
Пришлось пересобрать всю таблицу заново, опираясь на единственный авторитетный источник. При этом общий счетчик единожды уменьшился на четверть миллиарда.
Двузначное обозначение «50» превратилось в 1950-й год. В JavaScript заложен стандартный механизм формирования даты из года, месяца и дня. Если передать ему значение 50, система трактует его как 1950 год, а не как пятидесятый год нашей эры — таково архитектурное решение из девяностых годов прошлого века, закрепившееся в языке.
// НЕ Date.UTC(year, 0, 1): для годов 0–99 Date.UTC маппит их в 1900–1999
const yearStart0 = new Date(0);
yearStart0.setUTCFullYear(year, 0, 1);
Конфиденциальность
Сам по себе порядковый номер — лишь элегантная абстракция. Чтобы она обрела подлинный вес, необходимо комьюнити, объединенное общим опытом. Участники могут голосовать по грядущим событиям, система агрегирует мнения, а по завершении ситуации становится очевидно, как мыслило большинство.
Для реализации этого механизма конфиденциальность должна быть не декларативной, а технической. Заявления вроде «мы не передаем ваши личные сведения третьим лицам» — это элемент политики конфиденциальности, которую можно изменить в любой момент. Мне требовалось, чтобы анонимность гарантировалась самой архитектурой базы данных.
CREATE TABLE votes ( -- ответы
poll_id UUID NOT NULL, -- на какой вопрос
option_id UUID NOT NULL, -- какой вариант выбран
country_code CHAR(2) NOT NULL,
voted_at TIMESTAMPTZ NOT NULL
);
CREATE TABLE poll_participations ( -- кто уже отвечал
user_id UUID NOT NULL,
poll_id UUID NOT NULL,
PRIMARY KEY (user_id, poll_id)
);
В таблице голосов напрочь отсутствует привязка к конкретной личности — эта колонка не просто пуста, ее физически не существует. Вторая таблица содержит идентификатор пользователя, но лишена информации о сделанном выборе; она служит исключительно для предотвращения повторного голосования. Она фиксирует факт участия, но не раскрывает позицию. Сопоставить записи из этих двух таблиц напрямую невозможно, за исключением одной скрытой нити, о которой пойдет речь ниже. В таблице ответов фиксируется лишь код континента, не содержащий никаких персональных маркеров.
Дополнительно временные метки голосований искусственно сдвигаются на случайный интервал в пределах тридцати секунд. Без этого одновременные ответы пользователей совпали бы по времени с записями об участии, что позволило бы деанонимизировать их методом корреляции. Аналогичным образом дата участия округляется до суток.
Таблицы изолированы от стандартных ролей базы данных. Наружу выведены исключительно специализированные функции и представления, выдающие агрегированный результат, но исключающие прямой доступ к строкам.
Иллюзия безопасности через порог. Изначально статистика по конкретной стране открывалась только в том случае, если в опросе приняли участие не менее пятидесяти человек. Однако в противном случае возникала уязвимость: «в малонаселенной стране проголосовало трое, и один из них — вы».
Эта математическая брешь очевидна в пропорции сорок девять к одному. Формальный порог пройден, но единственный пользователь полностью деанонимизирован. Пришлось ввести дополнительное условие: минимум по пять голосов за каждый из вариантов ответа.
WHERE ct.total >= 50 AND ct.min_bucket >= 5;
Общий количественный порог не защищает интересы меньшинства. Это кажется очевидным при детальном разборе, но легко ускользает, когда заложено в единое условие фильтрации.
Граница доверия, установленная разработчиком
Я намеренно не утверждаю, что связь между пользователем и его ответом «необратима». Подобные заявления избыточны для любого веб-ресурса, обладающего собственной серверной инфраструктурой.
Единственная связующая нить внутри базы все же существует, и я честно говорю о ней. Запись об участии и сам голос порождаются в рамках единой транзакции, и реляционная СУБД Postgres помечает обе строки общим идентификатором. Пока эта служебная информация не затерта в ходе технического обслуживания таблиц, администратор с правами суперпользователя теоретически способен их объединить. На внешнем уровне остаются стандартные лог-файлы веб-сервера. Я не использую их для подобного анализа, но и заявлять о «криптографической абсолютной анонимности» не имею права. Такова реальная граница приватности.
Подобный подход гораздо честнее громких маркетинговых лозунгов в надежде, что пользователи не станут задавать неудобные вопросы.
Прогнозирование без денежных ставок
Свои баллы можно ставить на исходы прогнозов (в спортивных событиях разрешено участвовать и без прогнозов). В обычных опросах коэффициенты формируются на базе распределения мнений участников, начинаясь с равных шансов, а после набора первых пятидесяти ответов — зависят от коллективного выбора. В спортивных событиях коэффициенты транслируются с открытого рынка (автоматизированный модуль уже написан, хотя пока ожидает активации), очищаясь от маржи букмекеров. Любая букмекерская контора закладывает в котировки маржу, из-за чего сумма вероятностей превышает сто процентов. Я нормализую показатель до ста процентов, чтобы цифра объективно отражала общественное мнение, а не чужую прибыль. Никакой монетизации здесь нет: баллы невозможно перевести другому участнику или обменять на материальные призы.
Кроме того, формулировки вопросов и критерии исходов фиксируются намертво после поступления самого первого ответа. Пользователь принимал решение в условиях конкретного регламента, и менять их задним числом означало бы нарушить негласный договор с ним. Условия исходов защищены триггером базы данных, а формулировка доступна для изменения лишь через строго регламентированную системную функцию, минуя любые интерфейсные ухищрения.
Послания тем, кто еще не родился
Функция отправки писем в будущее реализована на многих платформах. Однако адресовать послание конкретному человеку, который еще не появился на свет, ранее было невозможно ввиду неопределенности адресата. Теперь у будущего землянина есть уникальный цифровой адрес — его порядковый номер.
Письмо привязывается к номеру, а не к электронному ящику или имени, и ожидает своего часа. Если по истечении года с момента расчетной даты номер так и остается незанятым, послание аннулируется — вечного хранения писем я не гарантирую. Это единственный сценарий на ресурсе, где персональный номер предназначен не для вас, а для нового участника очереди.

О концепции персональных номеров
Мне неоднократно доводилось слышать мнение, будто присвоение людям номеров — сомнительная затея. Я придерживаюсь противоположной позиции. Порядковый номер никоим образом не отменяет и не заменяет имя, индивидуальность или внешность. Он просто фиксирует эксклюзивное место в истории, принадлежащее вам с самого первого дня. Человечество привыкло измерять годы, летоисчисления и демографические показатели. Было бы странно исключить из этого списка самих людей.
Узнать собственный номер по дате рождения можно на ресурсе: papanumbers.com. Из российских сетей сайт доступен через VPN, так как сервер заблокирован, а зеркало пока не развернуто.
Электричество: от уравнений Максвелла до лилового свечения в пяти шагах
Пять способов сымитировать аргументацию в диалоге с языковой моделью
Биологические логические элементы и рибосомная память
Правило 0,7%: секрет выдающегося успеха и карьеры
Почему ChatGPT отлично рассуждает о покере, но ужасно в него играет
Как разгадать загадку университетского квеста
Обязаны ли мы использовать квантовые компьютеры для познания химии?