summaryrefslogtreecommitdiff
path: root/content/posts/2024-12-12-guessr.md
diff options
context:
space:
mode:
author2026-02-02 00:35:54 +0300
committer2026-02-02 00:35:54 +0300
commitbfdd73d7324a4f66a16f55d4fb064b0ff08d40e9 (patch)
tree27fff9c802dcdd22960bb2e776e58278000d0364 /content/posts/2024-12-12-guessr.md
parentПоправил шаблон (diff)
downloadblog-bfdd73d7324a4f66a16f55d4fb064b0ff08d40e9.tar.gz
blog-bfdd73d7324a4f66a16f55d4fb064b0ff08d40e9.tar.bz2
blog-bfdd73d7324a4f66a16f55d4fb064b0ff08d40e9.tar.xz
blog-bfdd73d7324a4f66a16f55d4fb064b0ff08d40e9.zip
Большая чистка блога
Diffstat (limited to 'content/posts/2024-12-12-guessr.md')
-rw-r--r--content/posts/2024-12-12-guessr.md130
1 files changed, 0 insertions, 130 deletions
diff --git a/content/posts/2024-12-12-guessr.md b/content/posts/2024-12-12-guessr.md
deleted file mode 100644
index 235901c..0000000
--- a/content/posts/2024-12-12-guessr.md
+++ /dev/null
@@ -1,130 +0,0 @@
----
-categories:
-- Мои проекты
-date: '2024-12-12T22:27:49+03:00'
-description: ''
-image: files/2024-12-12-guessr_logo.webp
-location: Казань
-tags:
-- IT
-- Проект выходного дня
-title: Guessr
----
-
-На недавних выходных я запилил очередной «проект выходного дня». На этот раз —
-аналог известного сервиса GeoGuessr, но в отличие от него, все точки
-сконцентрированы в моей родной Казани. Ну и я не использую панорамы, а
-фотографии мест.
-
-Я обещал выложить исходники, и в общем, вот они:
-https://git.neonxp.ru/guessr.git/
-
-## Немного про разработку
-
-Первым встал вопрос, откуда брать данные, а именно фотографии и координаты
-точек. Пару лет назад нашу страну покинул такой проект, как Ingress,
-представлявший собой гео игру в дополненной реальности. В свою очередь, я
-посчитал, что раз проект решил отказаться от нас, как игроков, я посчитал
-морально оправданным ~~спиз~~экспропреировать кусочек их данных, а именно
-спарсил с их карты intel.ingress.com т.н. «порталы», которые, по сути и есть эти
-самые геоточки с фотографиями.
-
-Дамп я загнал в Postgresql с подключенным расширением
-[Postgis](https://postgis.net/).
-
-Ну а далее написал достаточно простой API на Golang, который реализует следующие
-методы:
-
-- Создание новой игровой сессии, в ответ ставится кука внутри которой
- зашифровано текущее состояние — ник, количество очков, ID текущего
- угадываемого объекта (в начале пустое).
- ```http
- POST /api/state
- Content-Type: application/json
-
- {
- "username": "NeonXP"
- }
- ```
-
-- Получение состояния. Просто возвращает вышеуказанные параметры
- ```http
- GET /api/state
- ```
-
-- Выдача нового объекта для угадывания. При этом возвращается ссылка на фото и
- обновляется состояние, тем что в него вписывается ID объекта
- ```http
- POST /api/next
- ```
-
-- Угадывание. Собственно, на вход передаются координаты куда на карте указал
- игрок. А в ответ возвращается:
- - Название объекта
- - Расстояние от переданной точки до реального размещения объекта
- - Geojson строка в которой зашифрована линия соединяющая точку и объект (нужна
- для отрисовки красной линии на карте)
-
- При этом высчитываются очки которые получает игрок за попытку по формуле
- max(1000-d, 0), где d - расстояние между выбранной точкой и объектом в метрах.
- То есть, если разница меньше 1000м, то чем ближе - тем больше очков (максимум
- 1000 очков за 1 очень точное угадывание).
- ```http
- POST /api/guess
- Content-Type: application/json
-
- {
- "lat": 55.123,
- "lon": 49.123
- }
- ```
-
-Вот в общем-то и всё API!
-
-Из интересностей, при выборе очередной точки у неё в БД увеличивается счетчик, а
-сам select выбирает случайную точку только среди тех точек, где этот счетчик
-минимальный. То есть, пока не будут выданы игрокам все точки, уже выбранные
-заново не будут выданы. Вот это место в коде:
-https://git.neonxp.ru/guessr.git/tree/pkg/service/places.go#n26 (стр. 26-32)
-
-```go
-err = btx.NewSelect().
- ColumnExpr(`p.guid, p.img`).
- Model(r).
- Where(`p.count = (SELECT MIN(pl.count) FROM places pl WHERE pl.deleted_at IS NULL)`).
- OrderExpr(`RANDOM()`).
- Limit(1).
- Scan(ctx, r)
-```
-
-Ещё я бы отметил то, что я решил по максимуму логику вынести в БД, и, например,
-при угадывании расстояние до точки, а также вышеупомянутый geojson формируются
-так же на стороне БД:
-https://git.neonxp.ru/guessr.git/tree/pkg/service/places.go#n50 (стр. 50-59)
-
-```go
-err := p.db.NewSelect().
- Model(&model.Place{GUID: guid}).
- WherePK("guid").
- ColumnExpr(`p.name, p.guid, p.img,
- ST_Distance(ST_MakePoint(?, ?)::geography, p.position::geography)::int AS distance,
- ST_AsGeoJSON(ST_MakeLine(
- ST_SetSRID(ST_MakePoint(?, ?), 4326),
- ST_SetSRID(p.position, 4326)
- )) AS geojson`, lon, lat, lon, lat).
- Scan(ctx, r)
-```
-
-## Дальнейшие планы
-
-В комментах к анонсу ребята накидали достаточно много хороших идей, синтезировав
-которые, и добавив свои хотелки я составил примерно такой чеклист:
-
-- [ ] Авторизация и общая доска лидерства
-- [ ] После угадывания спрашивать у игрока «сложность», чтобы потом можно было,
- например, настраивать чтобы попадались только простые объекты. И, например,
- разное количество очков за простые и сложные объекты
-- [ ] Подумать как вынести игру в оффлайн, по типу того же ингресса. Это сложно
- и предстоит хорошо это обдумать
-
-Как-то так :) А впереди новые выходные и новые «проекты выходного дня»! \ No newline at end of file