Достало искать, где есть бензин и я сделал народную карту заправок
Последние недели с бензином стало туго. На одной заправке пусто, на другой очередь на полчаса, на третьей лимит по 20 литров в руки.
И главное заранее не угадаешь. Едешь наугад, а там либо закрыто, либо хвост из машин до соседнего квартала.
В какой-то момент я понял, что весь день переписываюсь со знакомыми по одной схеме: «ты где заправлялся? а там ещё есть? а очередь большая?». И они меня о том же спрашивают. Десятки сообщений, и всё равно картина устаревает через час.
И я подумал, это же типичная задача для карты. Где люди сами отмечают, что видят. Как с пробками, только про бензин.
За пару вечеров собрал простую штуку. Заходишь на сайт, видишь карту заправок. У каждой отметки от других водителей: есть топливо или нет, какое (92, 95, дизель), какая сейчас очередь, есть ли лимит налива, иногда цену пишут. Заправил бак, отметил сам, потратил пять секунд, помог следующему.
Несколько решений, которые принял по дороге:
Никаких регистраций и СМС. Меня самого бесит, когда ради одной кнопки заставляют заводить аккаунт. Тут просто заходишь и пользуешься, отметки анонимные.
Ничего не нужно устанавливать. Это обычный сайт, но сделан так, что можно добавить иконку на рабочий стол телефона и открывать как приложение. Никаких установок.
Главная головная боль достоверность данных. Любой может отметить неправду, случайно или специально, и подставить заправку. Поэтому отметки показываются свежие, у каждой видно, сколько человек подтвердило «есть» и сколько «нет», и старые данные обесцениваются. То, что было три часа назад, уже не показатель. Идеально не сделать, но чем больше людей отмечает, тем самоочищаемее картина.
Выложил для своих, особо не рассчитывал. За первые сутки:
— больше 8000 человек зашли посмотреть
— 370+ водителей что-то отметили
— 130+ заправок на карте
— полторы тысячи отметок про наличие, очередь и лимиты
Честно, не ожидал, что так быстро подхватят. Видимо, наболело не только у меня.
Сейчас данных больше всего по тем районам, откуда первые пользователи, в других местах карта пока пустая, но это вопрос того, сколько людей подключится. Чем больше отмечаем, тем оно полезнее для всех.
Ссылку оставлю в комментариях, чтобы пост не сочли рекламой, просто хотел поделиться, вдруг кому пригодится в той же ситуации.
P.S. Больше всего надеюсь, что бензин скоро появится везде и эта карта станет вообще никому не нужна.
Телефонный навигатор для Forza Horizon 6. Как это было сделано - часть 4, пока финал
Приборка, ретро-киберпанк и мемный штурман: когда навигатор стал companion app
После карты, маршрутов и борьбы с развязками я мог бы остановиться. Навигатор работает, телефон показывает позицию, маршрут строится, HUD в игре можно выключить. Казалось бы, все.
Но телефон уже лежит рядом с рулем. Он уже стал частью кокпита. И тут в голове появляется абсолютно нездоровая, но очень логичная мысль: а почему он должен быть только картой? Пусть будет приборкой. А если есть телеметрия, пусть еще и реагирует на события. Потому что если машина влетела в стену на 180 км/ч, программа имеет моральное право сказать что-нибудь мемное.
Dashboard: не дублировать игру, а сделать отдельное устройство
В некоторых машинах Forza внутренняя приборка работает нормально. Поэтому экранный спидометр я выключил почти сразу. Но внешний HUD на телефоне дает другое ощущение: не “еще один интерфейс поверх игры”, а отдельный прибор рядом с рулем.
Я хотел не стерильную табличку speed/gear/rpm, а что-то ближе к электронным приборкам авто их 80х в смеси с современными технологиями: скорость, передача, TRIP A, RPM bar, мини-карта, маршрут, темный фон, цифры как на старой электронике. Такое, чтобы выглядело не как админка роутера, а как штука, которую кто-то прикрутил к машине в гараже в 2003 году и почему-то она работает.
Семисегментные цифры прямо в DOM
Можно было взять шрифт. Но я захотел нормальные семисегментные цифры из отдельных сегментов. В браузере это делается довольно приятно: у каждой цифры есть набор включенных сегментов, а дальше DOM собирает маленький индикатор.
Это не самая сложная часть проекта, зато она очень влияет на настроение. Обычный текст говорит “это веб-страница”. Семисегментный индикатор говорит “добро пожаловать в странный автомобильный прибор”.
Семисегментные цифры приборки
const DASH_SEGMENTS = {
"0":"abcdef", "1":"bc", "2":"abged", "3":"abgcd",
"4":"fgbc", "5":"afgcd", "6":"afgecd", "7":"abc",
"8":"abcdefg", "9":"abfgcd", "-":"g", "N":"ceg", "R":"efgab"
};
function renderDashboardDigits(el, value, small=false){
const text = String(value ?? '0').toUpperCase().slice(0, 4);
el.innerHTML = '';
for(const ch of text){
const on = DASH_SEGMENTS[ch] || DASH_SEGMENTS[' '];
const digit = document.createElement('span');
digit.className = 'dashboardDigit' + (small ? ' small' : '');
for(const seg of ['a','b','c','d','e','f','g']){
const part = document.createElement('span');
part.className = 'dashboardDigitSeg s-' + seg + (on.includes(seg) ? ' on' : '');
digit.appendChild(part);
}
el.appendChild(digit);
}
}
RPM bar: маленькая полоска, много удовольствия
Обороты приходят из телеметрии. Максимальные обороты тоже могут прийти, но на всякий случай интерфейс умеет подстроиться под увиденный максимум. Полоса RPM собрана из 88 сегментов, последние сегменты помечены как red zone.
Здесь я окончательно понял, что приборка - это не про “показать число”. Это про ощущение. Когда шкала оборотов бежит рядом с рулем, мозг почему-то верит ей сильнее, чем сухому тексту.
RPM bar из 88 сегментов
function ensureDashboardRpmSegments(){
const track = document.getElementById('dashboardRpmTrack');
if(!track || dashboardRpmBuilt) return;
track.innerHTML = '';
dashboardRpmSegs = [];
for(let i = 0; i < 88; i++){
const seg = document.createElement('span');
seg.className = 'dashboardRpmSeg' + (i >= 76 ? ' red' : '');
track.appendChild(seg);
dashboardRpmSegs.push(seg);
}
dashboardRpmBuilt = true;
}
const ratio = clamp(rpm / Math.max(1000, dashboardLearnedMaxRpm), 0, 1);
const activeCount = Math.round(ratio * dashboardRpmSegs.length);
TRIP A: маленькая цифра, которая тоже пыталась сломаться
TRIP A выглядит как декоративная мелочь. Но именно такие мелочи делают приборку живой. И, конечно, даже она не могла просто работать без вопросов.
Если DistanceTraveled из телеметрии приходит нормально - используем его. Если он не двигается или приходит как бесполезный ноль - считаем расстояние сами, интегрируя скорость по времени. Это типичный момент разработки: хотел маленькую цифру, получил fallback-логику.
TRIP A с fallback-расчетом
function updateDashboardTrip(){
const rawDistance = Number(telemetry && telemetry.distance_traveled_m);
const rawValid = Number.isFinite(rawDistance) && rawDistance > 1;
if(rawValid){
if(dashboardTripRawBaseM === null || rawDistance + 5 < dashboardTripRawLastM){
dashboardTripRawBaseM = rawDistance;
}
dashboardTripRawLastM = rawDistance;
dashboardTripKm = Math.max(0, (rawDistance - dashboardTripRawBaseM) / 1000);
} else {
const dtMs = Math.max(0, Math.min(2500, now - dashboardTripLastAt));
const speedKmh = Math.max(0, Number(telemetry.speed_kmh) || 0);
dashboardTripKm += (speedKmh * dtMs) / 3600000;
}
}
Мини-карта в HUD: красиво, но телефон не надо жарить
В приборке есть мини-карта. Но ее нельзя было просто нарисовать как полноценную большую карту еще раз. Телефон должен держать нормальный FPS, не греться как кирпич и не превращать езду в презентацию PowerPoint.
Поэтому мини-карта живет на canvas, использует кэш тайлов и подбирает zoom по скорости. Чем быстрее едет машина, тем дальше навигатор должен смотреть вперед. На медленной скорости можно приблизить, на высокой - отодвинуть камеру, чтобы не ехать носом в край экрана.
Автоzoom мини-карты по скорости
function dashboardMiniDesiredZoom(mode, vw, vh, anchor, deg){
const kmh = Math.max(0, Number(telemetry.speed_kmh) || 0);
const lookSeconds = 4.5;
const lookMeters = Math.max(35, (kmh / 3.6) * lookSeconds);
const lookPx = mapPxFromMeters(lookMeters);
const ahead = dashboardForwardLookPoint(lookPx);
for(let z = MAX_ZOOM; z >= MIN_ZOOM; z--){
const v = viewFor(z);
const raw = {x: ahead.map_x * v.s - v.px, y: ahead.map_y * v.s - v.py};
const screen = rotatePointAround(raw.x, raw.y, anchor.x, anchor.y, deg);
if(screen.x >= sideMargin && screen.x <= vw - sideMargin &&
screen.y >= topMargin && screen.y <= vh - bottomMargin){
return z;
}
}
return MIN_ZOOM;
}
Мемный слой: когда телеметрия начинает шутить
Дальше случилось неизбежное. Если программа знает скорость, тормоз, вертикальную скорость и высоту, она может понимать игровые события. А если понимает события, может реагировать звуком.
Так появился мемный слой. Сэмплы лежат в папках samples/collision, samples/mega_fail_crash и samples/jump_takeoff. Сервер отдает список доступных звуков, телефон проигрывает случайный сэмпл при событии. Никакого облака, никакого сервиса, просто свои локальные файлы и браузер.
Настройки событий мемного слоя
MEME_EVENT_DEFAULTS = {
"mega_fail_crash": {
"window_sec": 0.15,
"min_previous_speed_kmh": 120.0,
"max_current_speed_kmh": 15.0,
"min_speed_drop_kmh": 100.0,
},
"collision": {
"window_sec": 0.5,
"min_speed_drop_kmh": 40.0,
"min_previous_speed_kmh": 60.0,
"max_brake_pct": 5.0,
},
"jump_takeoff": {
"detection_mode": "fast_freefall_confirmed",
"min_speed_kmh": 75.0,
"freefall_window_sec": 0.15,
"min_takeoff_vertical_speed_mps": 1.0,
"max_freefall_vertical_speed_mps": -0.25,
},
}
Столкновение - это не просто “скорость упала”
Самое важное для collision - не срабатывать на обычное торможение. Если игрок нажал тормоз, скорость упала, это не авария. Это водитель. Поэтому событие смотрит на падение скорости и одновременно проверяет, что тормоз почти не нажат.
Столкновение как резкое падение скорости без тормоза
if(collisionPast){
const drop = collisionPast.speed - speed;
const maxBrake = Number(collisionCfg.max_brake_pct ?? 5);
const noBrake = (brake <= maxBrake) && (Number(collisionPast.brake || 0) <= maxBrake);
if(noBrake &&
collisionPast.speed >= Number(collisionCfg.min_previous_speed_kmh || 60) &&
drop >= Number(collisionCfg.min_speed_drop_kmh || 40)){
playMemeEvent('collision');
return;
}
}
Прыжок - это не каждый холм
С прыжком было веселее. Нельзя просто сказать: машина поднялась вверх, значит прыжок. В игре есть холмы, эстакады, подъемы. Поэтому логика ждет не только рост высоты, но и признаки полета: вертикальную скорость, апекс, начало падения, небольшой drop from apex. По сути, нужно поймать момент “машина реально оторвалась”, а не “дорога пошла вверх”.
Прыжок как подтвержденный полет, а не просто подъем
const takeoffOk =
(recentMaxVy >= minTakeoffVy) ||
(verticalSpeedGain >= minVyGain) ||
(recentRise >= minRise && recentMaxVy >= minTakeoffVy * .55);
const fallingOk =
(fallingSamples.length >= minFallSamples || Number(vy) <= fallingLimit) &&
(fallDuration >= minFallDuration || confirmDrop >= minApexDrop * .55) &&
accelOk;
if(takeoffOk && fallingOk && notRoadSlope && dropFromApex >= minApexDrop){
playMemeEvent('jump_takeoff');
}
Что получилось в итоге
На этом этапе проект перестал быть “просто картой на телефоне”. Он стал companion app:
- основной слой - позиция машины и карта;
- навигационный слой - route, distance, heading-up, reroute;
- приборный слой - speed, gear, rpm, TRIP A, мини-карта;
- event layer - столкновения, прыжки, mega fail и звуковые реакции;
- будущий слой - Z-логгер для развязок и уточнение 3D-логики маршрутов.
И самое смешное: все это началось с очень простой мысли “хочу убрать мини-карту из игры и не потеряться”.
Я надеюсь, что вдохновение ко мне вернётся, и я сделаю что-то подобное для другой игры (напишите, кстати, какую игру еще можно было попробовать также снабдить навигатором?), или ещё что нибудь. Спасибо, что читали и ставили плюсы, всем добра!
Сделал карту, где водители отмечают наличие бензина на АЗС
Уже несколько недель наблюдаю за баталиями в комментариях по поводу наличия бензина. И вот вчера вечером пришла мысль: а почему бы не сделать простой сервис с картой заправок.
В итоге за пол ночи и сегодняшний день набросал вот это: https://azsstatus.ru
Это простой браузерный сайт с народной картой АЗС, адаптированный под мобильные устройства. Все отметки оставляют сами водители, регистрация не требуется.
Что есть:
карта с заправками (в базе ~26к записей);
поиск по городам;
4 типа меток, разделённые по цветам:
есть топливо;
нет;
очередь;
мало (продажа с ограничениями);
история изменения меток;
фильтры по меткам (заправки без меток отображаются всегда)
светлая и тёмная темы.
Вот так выглядит добавление меток:
Чего не хватает:
не все заправки
разделение статусов по маркам топлива (92 - есть, 98 - нет)
дизайн
Пока это скорее MVP — просто хотел проверить, будет ли вообще такая идея кому-то полезна.
Буду рад фидбеку. Если найдёте ошибки пишите - постараюсь исправить.
- А на трубе сыграть бы смог?
Считать Пушкин не умел. Появление денег связывалось у него с представлением неиссякаемого Пактола, и быстро пропустив их сквозь пальцы, он с детской наивностью недоумевал перед совершившимся исчезновением. Карты неудержимо влекли его. Он зачастую давал себе зарок больше не играть, подкрепляя это торжественным обещанием жене, но при первом подвернувшемся случае благие намерения разлетались в прах, и до самой зари он не мог оторваться от зеленого поля. Часто вспоминала Наталья Николаевна крайности, испытанные ею с первых шагов супружеской жизни. Бывали дни, после редкого выигрыша или крупной литературной получки, когда мгновенно являлось в доме изобилие во всем, деньги тратились без удержа и расчета, точно всякий стремился наверстать скорее испытанное лишение. Муж старался не только исполнить, но предугадать ее желания. Минуты эти были скоротечны и быстро сменялись полным безденежьем, когда не только речи быть не могло о какой-нибудь прихоти, но требовалось все напряжение ума, чтобы извернуться и достать самое необходимое для ежедневного существования. Некоторые из друзей Пушкина, посвященные в его денежные затруднения, ставили в упрек Наталии Николаевне ее увлечение светскою жизнью и изысканность нарядов. Первое она не отрицала. Но всегда упорно отвергала обвинение в личных тратах. Все ее выездные туалеты, все, что у нее было роскошного и ценного, оказывалось подарками Екатерины Ивановны ( Загряжской, фрейлины, тетки . Ник-ны ) . Она гордилась красотою племянницы; ее придворное положение способствовало той благосклонности, которой удостоивала Наталью Николаевну царская чета, а старушку тешило, при ее значительных средствах, что ее племянница могла поспорить изяществом с первыми щеголихами. А. П. Арапова. Воспоминания. – Новое Время, 1907, № 11413, ил. прил., с. 5.
Карта ЧМ-2026 показывает турнир не по странам, а по местам рождения игроков
На Reddit пользователь PiggySVW из r/MapPorn сделал интерактивную карту чемпионата мира 2026 года. На ней отмечены места рождения игроков, тренеров и судей, а также сборные и стадионы турнира.
Обычно чемпионат мира воспринимается как соревнование стран: флаги, гимны, группы, таблицы и матчи. Но если смотреть не на эмблемы сборных, а на места рождения участников, картина получается гораздо интереснее.
Карта показывает, что современный футбол — это не только про национальные команды, но и про города, миграцию, футбольные академии и личные маршруты игроков.
Например, в обсуждении сразу обратили внимание на Францию. По подсчётам пользователей, на турнире много участников, родившихся во Франции, а особенно выделяются Париж и его пригороды. На такой карте Париж выглядит не просто как столица страны, а как один из главных футбольных центров мира.
Ещё одна интересная деталь — Кабо-Верде. У этой сборной есть игроки, родившиеся в Роттердаме. В обсуждении это связывают с большой кабо-вердианской общиной в Нидерландах: многие выходцы с островов переезжали туда ещё во второй половине XX века.
На карте можно найти и совсем неожиданные точки: игроков, которые выступают за одну страну, но родились в другой части мира.
В итоге получается не просто футбольная карта, а наглядная история о том, как глобально устроен современный спорт: семьи, переезды, академии, двойное гражданство и города, которые дают миру десятки игроков.
Карту можно открыть здесь
P.S. Больше таких коротких историй собираю в Telegram-канале Симулятория








