Compare commits

..

11 Commits

Author SHA1 Message Date
zyphlar
5aaf5aa378 VIBECODED: idea for marking which roads have Panoramax imagery
Signed-off-by: zyphlar <zyphlar@gmail.com>
2025-12-14 10:55:33 -08:00
zyphlar
c8bfeb8e96 Don't error when a temp file doesn't exist
Signed-off-by: zyphlar <zyphlar@gmail.com>
2025-11-11 19:46:22 -08:00
zyphlar
7fc5ed494b [tools] Handle not-yet-generated drules files
Signed-off-by: zyphlar <zyphlar@gmail.com>
2025-11-12 02:26:27 +01:00
zyphlar
d9850f506a [docs] Add CDN_SETUP_INSTRUCTIONS.md
Signed-off-by: zyphlar <zyphlar@gmail.com>
2025-11-12 02:26:27 +01:00
zyphlar
f16d14e07f [generator] Automate maps generation with Docker and CI/CD
Co-authored-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
Signed-off-by: zyphlar <zyphlar@gmail.com>
2025-11-12 02:26:27 +01:00
Codeberg Translate
7852cdb5a5 [strings] Update from Codeberg Translate
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: JanezPavelZebovec <janezpavelzebovec@noreply.codeberg.org>
Co-authored-by: Linus_W_Frische <linus_w_frische@noreply.codeberg.org>
Co-authored-by: Prefill add-on <noreply-addon-prefill@weblate.org>
Co-authored-by: Weblate <noreply-mt-weblate@weblate.org>
Co-authored-by: dobridabar <dobridabar@noreply.codeberg.org>
Co-authored-by: javnik <javnik@noreply.codeberg.org>
Co-authored-by: ovl-005 <ovl-005@noreply.codeberg.org>
Translation: CoMaps/Android - Map Feature Types
Translation: CoMaps/Android UI Strings
Translation: CoMaps/iOS - Map Feature Types
Translation: CoMaps/iOS UI Strings
2025-11-12 00:09:38 +00:00
x7z4w
9a96096066 [android] Remove routing options item divider
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-11-11 19:18:25 +01:00
Wojciech Sipak
f72c4a28d9 fix openlr helpers build
See the commit e0f8e043bb
apparently the code was never tested

Signed-off-by: Wojciech Sipak <wsipak@protonmail.com>
2025-11-11 18:46:49 +01:00
Wojciech Sipak
68bb78b00d fix levenshtein dfa test build
The constuctor argument type was modified without
any adjustments to the callers.

See the commit
a0a5459b15

Signed-off-by: Wojciech Sipak <wsipak@protonmail.com>
2025-11-11 18:46:49 +01:00
Jean-Baptiste
b9d4f082de [android] Rework clear and close icon on Android
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-11-11 17:55:28 +01:00
Jean-Baptiste
7e40a0e642 [android] Fix drawable used in floating marker view
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-11-11 17:51:53 +01:00
47 changed files with 1327 additions and 352 deletions

View File

@@ -5,10 +5,10 @@ on:
jobs: jobs:
description: 'Which job(s) to run right now?' description: 'Which job(s) to run right now?'
required: true required: true
default: 'all' default: 'all-except-upload'
type: choice type: choice
options: options:
- all - all-except-upload
- copy-coasts - copy-coasts
- planet - planet
- wiki - wiki
@@ -16,30 +16,82 @@ on:
- subways - subways
- tiger - tiger
- maps - maps
- upload
map-generator-continue:
description: 'Continue previous map generation?'
required: false
default: false
type: boolean
map-generator-countries:
description: 'Generate specific MWMs? (i.e. "US_New York_*, foo")'
required: false
type: string
reset:
description: 'Reset part of the system?'
required: false
default: 'no'
type: choice
options:
- 'no'
- wiki-ratelimit
## RCLONE_CONF is multi-line text containing keys and credentials for us2,ru1,fi1,de1 servers
env: env:
RCLONE_CONF: ${{ secrets.RCLONE_CONF }}
WIKIMEDIA_USERNAME: ${{ secrets.WIKIMEDIA_USERNAME }} WIKIMEDIA_USERNAME: ${{ secrets.WIKIMEDIA_USERNAME }}
WIKIMEDIA_PASSWORD: ${{ secrets.WIKIMEDIA_PASSWORD }} WIKIMEDIA_PASSWORD: ${{ secrets.WIKIMEDIA_PASSWORD }}
S3_KEY_ID: ${{ secrets.S3_KEY_ID }} ZULIP_BOT_EMAIL: ${{ secrets.ZULIP_BOT_EMAIL }}
S3_SECRET_KEY: ${{ secrets.S3_SECRET_KEY }} ZULIP_API_KEY: ${{ secrets.ZULIP_API_KEY }}
S3_ENDPOINT: ${{ secrets.S3_ENDPOINT }} MWMCONTINUE: ${{ inputs.map-generator-continue }}
S3_BUCKET: ${{ secrets.S3_BUCKET }} MWMCOUNTRIES: ${{ inputs.map-generator-countries }}
SFTP_USER: ${{ secrets.SFTP_USER }}
SFTP_PASSWORD: ${{ secrets.SFTP_PASSWORD }}
SFTP_HOST: ${{ secrets.SFTP_HOST }}
SFTP_PATH: ${{ secrets.SFTP_PATH }}
DEBIAN_FRONTEND: noninteractive DEBIAN_FRONTEND: noninteractive
TZ: Etc/UTC TZ: Etc/UTC
jobs: jobs:
copy-coasts: clone-repos:
if: inputs.jobs == 'copy-coasts' || inputs.jobs == 'all' name: Clone Git Repos
name: Copy Previously Generated Coasts
runs-on: mapfilemaker runs-on: mapfilemaker
container: container:
image: ubuntu:latest image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes: volumes:
- /media/4tbexternal:/media/4tbexternal - /mnt/4tbexternal:/mnt/4tbexternal
concurrency:
group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
steps:
- uses: actions/cache@v4
with:
path: "~"
key: cache-${{ github.run_id }}-${{ github.run_attempt }}
- name: Checkout main repo
shell: bash
run: |
echo "Cloning $FORGEJO_SERVER_URL/$FORGEJO_REPOSITORY branch $FORGEJO_REF_NAME"
cd ~
git clone --recurse-submodules --shallow-submodules -b $FORGEJO_REF_NAME --single-branch $FORGEJO_SERVER_URL/$FORGEJO_REPOSITORY.git comaps
- name: Checkout wikiparser repo
shell: bash
run: |
cd ~
git clone https://codeberg.org/comaps/wikiparser.git
- name: Checkout subways repo
shell: bash
run: |
cd ~
git clone https://codeberg.org/comaps/subways.git
copy-coasts:
if: inputs.jobs == 'copy-coasts' || inputs.jobs == 'all-except-upload'
name: Copy Previously Generated Coasts
runs-on: mapfilemaker
needs:
- clone-repos
container:
image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes:
- /mnt/4tbexternal/:/mnt/4tbexternal/
- /mnt/4tbexternal/osm-planet:/home/planet
concurrency: concurrency:
group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }} group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true cancel-in-progress: true
@@ -47,336 +99,403 @@ jobs:
- name: Copy Coasts - name: Copy Coasts
shell: bash shell: bash
run: | run: |
if [ -f /media/4tbexternal/osm-maps/*/intermediate_data/WorldCoasts.geom ]; then echo "WorldCoasts available:"
cp /media/4tbexternal/osm-maps/*/intermediate_data/WorldCoasts.geom /media/4tbexternal/osm-planet/latest_coasts.geom ls -al /mnt/4tbexternal/osm-maps/*/intermediate_data/WorldCoasts.*
cp /media/4tbexternal/osm-maps/*/intermediate_data/WorldCoasts.rawgeom /media/4tbexternal/osm-planet/latest_coasts.rawgeom
if [ -f /mnt/4tbexternal/osm-maps/*/intermediate_data/WorldCoasts.geom ]; then
echo "Before:"
ls -al /home/planet/latest_coasts*
cp -p /mnt/4tbexternal/osm-maps/*/intermediate_data/WorldCoasts.geom /home/planet/latest_coasts.geom
cp -p /mnt/4tbexternal/osm-maps/*/intermediate_data/WorldCoasts.rawgeom /home/planet/latest_coasts.rawgeom
echo "After:"
ls -al /home/planet/latest_coasts*
else
echo "No WorldCoasts found."
fi fi
update-planet: update-planet:
if: inputs.jobs == 'planet' || inputs.jobs == 'all' if: inputs.jobs == 'planet' || inputs.jobs == 'all-except-upload'
name: Update Planet name: Update Planet
runs-on: mapfilemaker runs-on: mapfilemaker
needs:
- clone-repos
container: container:
image: ubuntu:latest image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes: volumes:
- /media/4tbexternal:/media/4tbexternal - /mnt/4tbexternal/:/mnt/4tbexternal/
- /mnt/4tbexternal/osm-planet:/home/planet
concurrency: concurrency:
group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }} group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true cancel-in-progress: true
steps: steps:
- name: Install dependencies
shell: bash
run: |
apt-get update -y
apt-get install -y pyosmium osmium-tool python3-venv python3-pip wget2
rm -f /usr/lib/python*/EXTERNALLY-MANAGED
pip3 install "protobuf<4"
- name: Download Planet File if Absent - name: Download Planet File if Absent
shell: bash shell: bash
# TODO: replace wget2 with curl -Z
run: | run: |
if [ ! -d /media/4tbexternal/osm-planet/planet/ ]; then if [ ! -d /home/planet/planet/ ]; then
mkdir -p /media/4tbexternal/osm-planet/planet/ mkdir -p /home/planet/planet/
fi fi
if [ ! -f /media/4tbexternal/osm-planet/planet/planet-latest.osm.pbf ]; then if [ ! -f /home/planet/planet/planet-latest.osm.pbf ]; then
cd /media/4tbexternal/osm-planet/planet/ cd /home/planet/planet/
wget2 --verbose --progress=bar --continue --debug https://ftpmirror.your.org/pub/openstreetmap/pbf/planet-latest.osm.pbf wget2 --verbose --progress=bar --continue https://ftpmirror.your.org/pub/openstreetmap/pbf/planet-latest.osm.pbf
else
echo "planet-latest.osm.pbf was found, raw download not required."
fi fi
- name: Update Planet - name: Update Planet
shell: bash shell: bash
run: | run: |
cd /media/4tbexternal/osm-planet/planet/ cd /home/planet/planet/
pyosmium-up-to-date planet-latest.osm.pbf -o planet-latest-new.osm.pbf -vv --size 16384 rm -f planet-latest-new.osm.pbf
pyosmium-up-to-date planet-latest.osm.pbf -o planet-latest-new.osm.pbf -v --size 16384
mv planet-latest-new.osm.pbf planet-latest.osm.pbf mv planet-latest-new.osm.pbf planet-latest.osm.pbf
- name: Converting planet-latest.osm.pbf to planet.o5m - name: Converting planet-latest.osm.pbf to planet.o5m
run: /root/OM/osmctools/osmconvert planet-latest.osm.pbf -o=planet.o5m # TODO: better to run osmupdate (not convert) just before starting the maps jobs - for max fresh data.
run: |
echo "Starting..."
cd /home/planet/planet/
osmconvert -v --drop-author --drop-version --hash-memory=4000 planet-latest.osm.pbf -o=planet.o5m
echo "Done."
- name: Notify Zulip
run: |
curl -X POST https://comaps.zulipchat.com/api/v1/messages \
-u $ZULIP_BOT_EMAIL:$ZULIP_API_KEY \
--data-urlencode type=stream \
--data-urlencode 'to="DevOps"' \
--data-urlencode topic=codeberg-bot \
--data-urlencode 'content=Planet update is done!'
wiki-update: wiki-update:
if: inputs.jobs == 'wiki' || inputs.jobs == 'all' if: inputs.jobs == 'wiki' || inputs.jobs == 'all-except-upload'
name: Update Wikipedia name: Update Wikipedia
runs-on: mapfilemaker runs-on: mapfilemaker
needs:
- clone-repos
container: container:
image: ubuntu:latest image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes: volumes:
- /media/4tbexternal:/media/4tbexternal - /mnt/4tbexternal/:/mnt/4tbexternal/
- /mnt/4tbexternal/osm-planet:/home/planet
concurrency: concurrency:
group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }} group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true cancel-in-progress: true
steps: steps:
- name: Install dependencies - uses: actions/cache@v4
shell: bash with:
run: | path: "~"
apt-get update -y key: cache-${{ github.run_id }}-${{ github.run_attempt }}
apt-get install -y jq curl wget2 rustc cargo git ca-certificates
- name: Clone wikiparser if necessary
shell: bash
run: |
if [ ! -d /media/4tbexternal/wikiparser ]; then
cd /media/4tbexternal
git clone https://codeberg.org/comaps/wikiparser.git
fi
- name: Check for planet file - name: Check for planet file
shell: bash shell: bash
# TODO: remove debug output
run: | run: |
if [ ! -f /media/4tbexternal/osm-planet/planet/planet-latest.osm.pbf ]; then if [ ! -f /home/planet/planet/planet-latest.osm.pbf ]; then
echo "ERROR: No file at /media/4tbexternal/osm-planet/planet/planet-latest.osm.pbf" echo "ERROR: No file at /home/planet/planet/planet-latest.osm.pbf"
ls -al /media/4tbexternal/ ls -al /home/planet/
ls -al /media/4tbexternal/osm-planet/ ls -al /home/planet/planet/
ls -al /media/4tbexternal/osm-planet/planet/ exit 1
fi
- name: Only get new dumps once per 30 days
shell: bash
run: |
if [[ '${{ inputs.reset }}' == 'wiki-ratelimit' ]]; then
echo "Bypassing wiki rate limit upon request."
exit 0
fi
datediff() {
d1=$(date -d "$1" +%s)
d2=$(date -d "$2" +%s)
echo $(( (d1 - d2) / 86400 ))
}
RECENTDUMPDATE=$(find /home/planet/wikipedia/dumps/ -mindepth 1 -maxdepth 1 -iname "2*" -type d | sort -n -r | head -1 | cut -d/ -f6)
TODAY=$(date +%Y%m%d)
DATEDIFF=$(datediff $TODAY $RECENTDUMPDATE)
if [ $DATEDIFF -lt 30 ]; then
echo "ERROR: The most recent wiki dump is from $RECENTDUMPDATE, $DATEDIFF days ago. Wikimedia limits users to 15 snapshot requests per month."
echo "Set the 'reset' option to 'wiki-ratelimit' to bypass this."
ls -al /home/planet/wikipedia/dumps/
exit 1 exit 1
fi fi
- name: Update Wikipedia from Enterprise API - name: Update Wikipedia from Enterprise API
shell: bash shell: bash
run: | run: |
mkdir -p /media/4tbexternal/osm-planet/wikipedia/dumps #todo: curl in download.sh can fail when rate limited and even save error messages to the output. need to validate.
mkdir -p /media/4tbexternal/osm-planet/wikipedia/build #downloading all languages can also trigger rate limits or fail as well. needs work.
cd /media/4tbexternal/wikiparser #also: a failure to download means a failure to build, and could result in no wiki descriptions etc.
#also-also: do we want to remove old wiki data in planet between builds? pastk: no need, its being updated / augmented
mkdir -p /home/planet/wikipedia/dumps
mkdir -p /home/planet/wikipedia/build
cd ~/wikiparser
ls -al ls -al
echo "Downloading ..." echo "Downloading ..."
./download.sh /media/4tbexternal/osm-planet/wikipedia/dumps ./download.sh /home/planet/wikipedia/dumps
ls -al /home/planet/wikipedia/dumps/*
echo "Running ..." echo "Running ..."
./run.sh /media/4tbexternal/osm-planet/wikipedia/build \ ./run.sh /home/planet/wikipedia/build \
/media/4tbexternal/osm-planet/planet/planet-latest.osm.pbf \ /home/planet/planet/planet-latest.osm.pbf \
/media/4tbexternal/osm-planet/wikipedia/dumps/latest/*.tar.gz /home/planet/wikipedia/dumps/latest/*.tar.gz
echo "DONE" echo "DONE"
- name: Check that the latest dumps are present, recent, and not super tiny
shell: bash
run: |
FAILCHECK=0
# Check all .tar.gz files in /home/planet/wikipedia/dumps/latest/
for file in /home/planet/wikipedia/dumps/latest/*.tar.gz; do
# Check if file exists (handles case where glob doesn't match)
[ -e "$file" ] || continue
# Get file size in MB and modification time in days
size_mb=$(stat -f%z "$file" 2>/dev/null | awk '{print int($1/1024/1024)}' || stat -c%s "$file" | awk
'{print int($1/1024/1024)}')
days_old=$(find "$file" -mtime -7 | wc -l)
# Verify conditions
if [ "$size_mb" -lt 100 ]; then
echo "FAIL: $file is only ${size_mb}MB (< 100MB)"
FAILCHECK=1
elif [ "$days_old" -eq 0 ]; then
echo "FAIL: $file is older than 7 days"
ls -al $file
FAILCHECK=1
else
echo "PASS: $file (${size_mb}MB, modified within 7 days)"
fi
done
exit $FAILCHECK
- name: Notify Zulip
run: |
curl -X POST https://comaps.zulipchat.com/api/v1/messages \
-u $ZULIP_BOT_EMAIL:$ZULIP_API_KEY \
--data-urlencode type=stream \
--data-urlencode 'to="DevOps"' \
--data-urlencode topic=codeberg-bot \
--data-urlencode 'content=Wiki update is done!'
update-isolines: update-isolines:
if: inputs.jobs == 'isolines' || inputs.jobs == 'all' if: inputs.jobs == 'isolines' || inputs.jobs == 'all-except-upload'
name: Update Isolines name: Update Isolines
runs-on: mapfilemaker runs-on: mapfilemaker
needs:
- clone-repos
container: container:
image: ubuntu:latest image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes: volumes:
- /media/4tbexternal:/media/4tbexternal - /mnt/4tbexternal/:/mnt/4tbexternal/
- /mnt/4tbexternal/osm-planet:/home/planet
concurrency: concurrency:
group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }} group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true cancel-in-progress: true
steps: steps:
- name: Install dependencies - uses: actions/cache@v4
shell: bash with:
run: | path: "~"
apt-get update -qq \ key: cache-${{ github.run_id }}-${{ github.run_attempt }}
&& apt-get install -y --no-install-recommends \ # TODO: we only need to update these if our SRTM or countries change
curl \ # TODO: after update, verify that sizable files exist: /home/planet/isolines/*.isolines
osmctools \
rclone \
git \
ca-certificates \
openssh-client \
sshpass \
vim \
wget \
build-essential \
clang \
cmake \
python3 \
python3-pip \
python3.12-venv \
qt6-base-dev \
qt6-positioning-dev \
libc++-dev \
libfreetype-dev \
libglvnd-dev \
libgl1-mesa-dev \
libharfbuzz-dev \
libicu-dev \
libqt6svg6-dev \
libqt6positioning6-plugins \
libqt6positioning6 \
libsqlite3-dev \
libxrandr-dev \
libxinerama-dev \
libxcursor-dev \
libxi-dev \
zlib1g-dev
rm -f /usr/lib/python*/EXTERNALLY-MANAGED
pip3 install "protobuf<4"
- name: Clone main repo if necessary
shell: bash
run: |
if [ ! -d /media/4tbexternal/comaps-init ]; then
apt-get update -qq && apt-get install -y --no-install-recommends git
cd /media/4tbexternal
git clone --recurse-submodules --shallow-submodules -b rebase-generator-pastk-wb251014 --single-branch https://codeberg.org/comaps/comaps.git comaps-init
fi
- name: Update Isolines - name: Update Isolines
shell: bash shell: bash
# TODO: preserve previous isolines version?
# TODO: cleanup the tmp-tiles dir after completion
run: | run: |
cd /media/4tbexternal/comaps-init/ cd ~/comaps/
./tools/unix/build_omim.sh -R topography_generator_tool ./tools/unix/build_omim.sh -p ~ -R topography_generator_tool
rm -rf ../osm-planet/isolines/ rm -rf /home/planet/isolines/
mkdir ../osm-planet/isolines/ mkdir /home/planet/isolines/
../omim-build-relwithdebinfo/topography_generator_tool \ ~/omim-build-relwithdebinfo/topography_generator_tool \
--profiles_path=./data/conf/isolines/isolines-profiles.json \ --profiles_path=./data/conf/isolines/isolines-profiles.json \
--countries_to_generate_path=./data/conf/isolines/countries-to-generate.json \ --countries_to_generate_path=./data/conf/isolines/countries-to-generate.json \
--tiles_isolines_out_dir=../osm-planet/isolines/tmp-tiles/ \ --tiles_isolines_out_dir=/home/planet/isolines/tmp-tiles/ \
--countries_isolines_out_dir=../osm-planet/isolines/ \ --countries_isolines_out_dir=/home/planet/isolines/ \
--data_dir=./data/ \ --data_dir=./data/ \
--srtm_path=../osm-planet/SRTM-patched-europe/ \ --srtm_path=/home/planet/SRTM-patched-europe/ \
--threads=22 --threads=96
- name: Check isolines
shell: bash
run: |
NUMISO=$(ls -al /home/planet/isolines/*.isolines | wc -l)
echo "Found $NUMISO isolines"
if [ $NUMISO -lt 10 ]; then
echo "ERROR: Did generation fail?"
exit 1
fi
- name: Notify Zulip
run: |
curl -X POST https://comaps.zulipchat.com/api/v1/messages \
-u $ZULIP_BOT_EMAIL:$ZULIP_API_KEY \
--data-urlencode type=stream \
--data-urlencode 'to="DevOps"' \
--data-urlencode topic=codeberg-bot \
--data-urlencode 'content=Isolines are done!'
update-subways: update-subways:
if: inputs.jobs == 'subways' || inputs.jobs == 'all' if: inputs.jobs == 'subways' || inputs.jobs == 'all-except-upload'
name: Update Subways name: Update Subways
runs-on: mapfilemaker runs-on: mapfilemaker
needs:
- clone-repos
container: container:
image: ubuntu:latest image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes: volumes:
- /media/4tbexternal:/media/4tbexternal - /mnt/4tbexternal/:/mnt/4tbexternal/
- /mnt/4tbexternal/osm-planet:/home/planet
concurrency: concurrency:
group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }} group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true cancel-in-progress: true
steps: steps:
- name: Install dependencies - uses: actions/cache@v4
shell: bash with:
run: | path: "~"
apt-get update -qq && apt-get install -y --no-install-recommends curl osmctools osmium-tool python3-venv ca-certificates git python3-pip key: cache-${{ github.run_id }}-${{ github.run_attempt }}
rm -f /usr/lib/python*/EXTERNALLY-MANAGED
pip3 install "protobuf<4"
- name: Clone subways if necessary
shell: bash
run: |
if [ ! -d /media/4tbexternal/subways ]; then
cd /media/4tbexternal
git clone https://codeberg.org/comaps/subways.git
fi
- name: Clone main repo if necessary
shell: bash
run: |
if [ ! -d /media/4tbexternal/comaps-init ]; then
cd /media/4tbexternal
git clone --recurse-submodules --shallow-submodules -b rebase-generator-pastk-wb251014 --single-branch https://codeberg.org/comaps/comaps.git comaps-init
fi
- name: Update Subways - name: Update Subways
shell: bash shell: bash
run: | run: |
cd /media/4tbexternal/comaps-init/ cd ~/comaps/
cp tools/unix/maps/settings.sh.prod tools/unix/maps/settings.sh cp tools/unix/maps/settings.sh.prod tools/unix/maps/settings.sh
./tools/unix/maps/generate_subways.sh ./tools/unix/maps/generate_subways.sh
- name: Notify Zulip
run: |
curl -X POST https://comaps.zulipchat.com/api/v1/messages \
-u $ZULIP_BOT_EMAIL:$ZULIP_API_KEY \
--data-urlencode type=stream \
--data-urlencode 'to="DevOps"' \
--data-urlencode topic=codeberg-bot \
--data-urlencode 'content=Subways are done!'
update-tiger: update-tiger:
if: inputs.jobs == 'tiger' || inputs.jobs == 'all' if: inputs.jobs == 'tiger' || inputs.jobs == 'all-except-upload'
name: Update TIGER name: Update TIGER
runs-on: mapfilemaker runs-on: mapfilemaker
needs:
- clone-repos
container: container:
image: ubuntu:latest image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes: volumes:
- /media/4tbexternal:/media/4tbexternal - /mnt/4tbexternal/:/mnt/4tbexternal/
- /mnt/4tbexternal/osm-planet:/home/planet
concurrency: concurrency:
group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }} group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true cancel-in-progress: true
steps: steps:
- name: Install dependencies - uses: actions/cache@v4
shell: bash with:
run: | path: "~"
apt-get update -qq && apt-get install -y --no-install-recommends \ key: cache-${{ github.run_id }}-${{ github.run_attempt }}
build-essential \
clang \
cmake \
ninja-build \
ca-certificates \
git \
wget2
- name: Clone main repo if necessary
shell: bash
run: |
if [ ! -d /media/4tbexternal/comaps-init ]; then
cd /media/4tbexternal
git clone --recurse-submodules --shallow-submodules -b rebase-generator-pastk-wb251014 --single-branch https://codeberg.org/comaps/comaps.git comaps-init
fi
- name: Build address_parser - name: Build address_parser
shell: bash shell: bash
run: | run: |
cd /media/4tbexternal/comaps-init cd ~/comaps
rm -rf ../omim-build-relwithdebinfo/CMakeCache.txt #rm -rf ~/omim-build-relwithdebinfo/CMakeCache.txt
rm -rf ../omim-build-relwithdebinfo/CMakeFiles #rm -rf ~/omim-build-relwithdebinfo/CMakeFiles
./tools/unix/build_omim.sh -R address_parser_tool ./tools/unix/build_omim.sh -p ~ -R address_parser_tool
- name: Update TIGER from Nominatim - name: Update TIGER from Nominatim
shell: bash shell: bash
# TODO: use curl instead of wget2
run: | run: |
cd /media/4tbexternal/osm-planet/ # TODO: maybe remove old osm-planet/tiger first?
cd /home/planet/
mkdir -p tiger
wget2 https://nominatim.org/data/tiger-nominatim-preprocessed-latest.csv.tar.gz wget2 https://nominatim.org/data/tiger-nominatim-preprocessed-latest.csv.tar.gz
tar -xOzf tiger-nominatim-preprocessed-latest.csv.tar.gz | /media/4tbexternal/omim-build-relwithdebinfo/address_parser_tool --output_path=./tiger cd ~/comaps
tar -xOzf /home/planet/tiger-nominatim-preprocessed-latest.csv.tar.gz | ~/omim-build-relwithdebinfo/address_parser_tool --output_path=/home/planet/tiger
generate-maps: generate-maps:
if: inputs.jobs == 'maps' || inputs.jobs == 'all' if: inputs.jobs == 'maps' || inputs.jobs == 'all-except-upload'
name: Generate Maps name: Generate Maps
runs-on: mapfilemaker runs-on: mapfilemaker
needs:
- clone-repos
timeout-minutes: 40320
container: container:
image: ubuntu:latest image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes: volumes:
- /media/4tbexternal:/media/4tbexternal - /mnt/4tbexternal/:/mnt/4tbexternal/
- /mnt/4tbexternal/osm-planet:/home/planet
options: --ulimit nofile=262144:262144 options: --ulimit nofile=262144:262144
concurrency: concurrency:
group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }} group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true cancel-in-progress: true
steps: steps:
- name: Install dependencies - uses: actions/cache@v4
shell: bash with:
run: | path: "~"
apt-get update -qq \ key: cache-${{ github.run_id }}-${{ github.run_attempt }}
&& apt-get install -y --no-install-recommends \
curl \
osmctools \
rclone \
git \
ca-certificates \
openssh-client \
sshpass \
vim \
wget \
build-essential \
clang \
cmake \
ninja-build \
python3 \
python3-pip \
python3.12-venv \
qt6-base-dev \
qt6-positioning-dev \
libc++-dev \
libfreetype-dev \
libglvnd-dev \
libgl1-mesa-dev \
libharfbuzz-dev \
libicu-dev \
libqt6svg6-dev \
libqt6positioning6-plugins \
libqt6positioning6 \
libsqlite3-dev \
libxrandr-dev \
libxinerama-dev \
libxcursor-dev \
libxi-dev \
zlib1g-dev
- name: Clone repo if necessary
shell: bash
run: |
if [ ! -d /media/4tbexternal/comaps-init ]; then
cd /media/4tbexternal
git clone --recurse-submodules --shallow-submodules -b rebase-generator-pastk-wb251014 --single-branch https://codeberg.org/comaps/comaps.git comaps-init
fi
- name: Make output folders if necessary - name: Make output folders if necessary
shell: bash shell: bash
run: | run: |
if [ ! -d /media/4tbexternal/osm-maps ]; then if [ ! -d /mnt/4tbexternal/osm-maps ]; then
mkdir -p /media/4tbexternal/osm-maps mkdir -p /mnt/4tbexternal/osm-maps
fi fi
- name: Get SRTM if necessary - name: Get SRTM if necessary
# TODO: it should be a separate step like Wiki or isolines
shell: bash shell: bash
run: | run: |
if [ ! -d /media/4tbexternal/osm-planet/SRTM-patched-europe/ ]; then if [ ! -d /home/planet/SRTM-patched-europe/ ]; then
echo "ERROR: NO SRTM" echo "ERROR: NO SRTM"
exit 1 exit 1
fi fi
- name: Symlink paths for repo scripts
shell: bash
run: |
mkdir -p /root/OM
ln -s /media/4tbexternal/comaps-init /root/OM/organicmaps
ln -s /media/4tbexternal/osm-planet /home/planet
ln -s /media/4tbexternal/osm-maps /root/OM/maps_build
- name: Run docker_maps_generator.sh - name: Run docker_maps_generator.sh
shell: bash shell: bash
run: | run: |
cd /root/OM/organicmaps cd ~/comaps
./tools/unix/docker_maps_generator.sh bash ./tools/unix/maps/docker_maps_generator.sh
- name: Notify Zulip
run: |
curl -X POST https://comaps.zulipchat.com/api/v1/messages \
-u $ZULIP_BOT_EMAIL:$ZULIP_API_KEY \
--data-urlencode type=stream \
--data-urlencode 'to="DevOps"' \
--data-urlencode topic=codeberg-bot \
--data-urlencode 'content=Generator is done!'
upload-maps:
if: inputs.jobs == 'upload'
name: Upload Maps
runs-on: mapfilemaker
container:
image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes:
- /mnt/4tbexternal/:/mnt/4tbexternal/
- /mnt/4tbexternal/osm-planet:/home/planet
concurrency:
group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
steps:
- name: Write config file
run: |
mkdir -p ~/.config/rclone/
echo "${{ secrets.RCLONE_CONF }}" > ~/.config/rclone/rclone.conf
- name: Upload map files to CDNs
shell: bash
run: |
shopt -s nullglob
buildfolder=$(find /mnt/4tbexternal/osm-maps/ -mindepth 1 -maxdepth 1 -iname "2*" -type d | sort -n -r | head -1 | cut -d/ -f5)
builddate=$(find /mnt/4tbexternal/osm-maps/*/ -mindepth 1 -maxdepth 1 -iname "2*" -type d | sort -n -r | head -1 | cut -d/ -f6)
mwmfiles=( /mnt/4tbexternal/osm-maps/$buildfolder/$builddate/*.mwm )
if (( ${#mwmfiles[@]} )); then
echo "<$(date +%T)> Uploading maps from $buildfolder/$builddate..."
cd ~/comaps/tools/unix/maps
./upload_to_cdn.sh /mnt/4tbexternal/osm-maps/$buildfolder/$builddate
echo "<$(date +%T)> Finished uploading maps from $buildfolder/$builddate."
else
echo "<$(date +%T)> No MWM files in /mnt/4tbexternal/osm-maps/$buildfolder/$builddate/*.mwm, not uploading maps."
echo "<$(date +%T)> Found top level: $(ls -alt /mnt/4tbexternal/osm-maps/*)"
echo "<$(date +%T)> Found second level: $(ls -alt /mnt/4tbexternal/osm-maps/$buildfolder/*)"
fi
- name: Notify Zulip
run: |
curl -X POST https://comaps.zulipchat.com/api/v1/messages \
-u $ZULIP_BOT_EMAIL:$ZULIP_API_KEY \
--data-urlencode type=stream \
--data-urlencode 'to="DevOps"' \
--data-urlencode topic=codeberg-bot \
--data-urlencode 'content=Upload is done!'

1
.gitignore vendored
View File

@@ -9,6 +9,7 @@ Makefile.Release
object_script.*.Debug object_script.*.Debug
object_script.*.Release object_script.*.Release
compile_commands.json compile_commands.json
*.local.*
stxxl.errlog stxxl.errlog
stxxl.log stxxl.log

View File

@@ -357,7 +357,7 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
private MenuBottomSheetItem getCancelMenuItem() private MenuBottomSheetItem getCancelMenuItem()
{ {
return new MenuBottomSheetItem(R.string.cancel, R.drawable.ic_cancel, () -> onCancelActionSelected(mSelectedItem)); return new MenuBottomSheetItem(R.string.cancel, R.drawable.ic_close, () -> onCancelActionSelected(mSelectedItem));
} }
private class ItemViewHolder extends BaseInnerViewHolder<CountryItem> private class ItemViewHolder extends BaseInnerViewHolder<CountryItem>

View File

@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="@android:color/white"
android:pathData="M480,536L284,732Q273,743 256,743Q239,743 228,732Q217,721 217,704Q217,687 228,676L424,480L228,284Q217,273 217,256Q217,239 228,228Q239,217 256,217Q273,217 284,228L480,424L676,228Q687,217 704,217Q721,217 732,228Q743,239 743,256Q743,273 732,284L536,480L732,676Q743,687 743,704Q743,721 732,732Q721,743 704,743Q687,743 676,732L480,536Z"/>
</vector>

View File

@@ -1,5 +1,10 @@
<vector android:height="24dp" android:tint="#FFFFFF" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:viewportHeight="24" android:viewportWidth="24" android:width="24dp"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:height="24dp"
<path android:fillColor="@android:color/white" android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/> android:tint="#FFFFFF"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="@android:color/white"
android:pathData="M480,536L284,732Q273,743 256,743Q239,743 228,732Q217,721 217,704Q217,687 228,676L424,480L228,284Q217,273 217,256Q217,239 228,228Q239,217 256,217Q273,217 284,228L480,424L676,228Q687,217 704,217Q721,217 732,228Q743,239 743,256Q743,273 732,284L536,480L732,676Q743,687 743,704Q743,721 732,732Q721,743 704,743Q687,743 676,732L480,536Z"/>
</vector> </vector>

View File

@@ -3,7 +3,13 @@
android:height="20dp" android:height="20dp"
android:viewportWidth="960" android:viewportWidth="960"
android:viewportHeight="960"> android:viewportHeight="960">
<group
android:pivotX="370"
android:pivotY="480"
android:scaleX="2.2"
android:scaleY="1.7">
<path <path
android:pathData="M420,652q-8,0 -14,-5.5t-6,-14.5v-304q0,-9 6,-14.5t14,-5.5q2,0 14,6l145,145q5,5 7,10t2,11q0,6 -2,11t-7,10L434,646q-3,3 -6.5,4.5T420,652Z" android:pathData="M640,760 L200,480l440,-280v560Z"
android:fillColor="#1f1f1f"/> android:fillColor="#FFFFFF"/>
</group>
</vector> </vector>

View File

@@ -22,8 +22,8 @@
android:clipChildren="false"> android:clipChildren="false">
<com.google.android.material.imageview.ShapeableImageView <com.google.android.material.imageview.ShapeableImageView
android:id="@+id/floating_triangle" android:id="@+id/floating_triangle"
android:layout_width="wrap_content" android:layout_width="@dimen/margin_half"
android:layout_height="wrap_content" android:layout_height="@dimen/margin_half"
android:elevation="@dimen/margin_eighth" android:elevation="@dimen/margin_eighth"
android:layout_centerVertical="true" android:layout_centerVertical="true"
app:tint="@android:color/white" app:tint="@android:color/white"

View File

@@ -36,7 +36,6 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:padding="@dimen/margin_half_double_plus"/> android:padding="@dimen/margin_half_double_plus"/>
</LinearLayout> </LinearLayout>
<include layout="@layout/item_divider"/>
<LinearLayout <LinearLayout
android:orientation="horizontal" android:orientation="horizontal"
android:minHeight="@dimen/height_block_base" android:minHeight="@dimen/height_block_base"
@@ -58,7 +57,6 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:padding="@dimen/margin_half_double_plus"/> android:padding="@dimen/margin_half_double_plus"/>
</LinearLayout> </LinearLayout>
<include layout="@layout/item_divider"/>
<LinearLayout <LinearLayout
android:orientation="horizontal" android:orientation="horizontal"
android:minHeight="@dimen/height_block_base" android:minHeight="@dimen/height_block_base"
@@ -80,7 +78,6 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:padding="@dimen/margin_half_double_plus"/> android:padding="@dimen/margin_half_double_plus"/>
</LinearLayout> </LinearLayout>
<include layout="@layout/item_divider"/>
<LinearLayout <LinearLayout
android:orientation="horizontal" android:orientation="horizontal"
android:minHeight="@dimen/height_block_base" android:minHeight="@dimen/height_block_base"
@@ -102,7 +99,6 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:padding="@dimen/margin_half_double_plus"/> android:padding="@dimen/margin_half_double_plus"/>
</LinearLayout> </LinearLayout>
<include layout="@layout/item_divider"/>
<LinearLayout <LinearLayout
android:orientation="horizontal" android:orientation="horizontal"
android:minHeight="@dimen/height_block_base" android:minHeight="@dimen/height_block_base"
@@ -124,7 +120,6 @@
android:padding="@dimen/margin_half_double_plus" android:padding="@dimen/margin_half_double_plus"
android:layout_height="match_parent"/> android:layout_height="match_parent"/>
</LinearLayout> </LinearLayout>
<include layout="@layout/item_divider"/>
<LinearLayout <LinearLayout
android:orientation="horizontal" android:orientation="horizontal"
android:minHeight="@dimen/height_block_base" android:minHeight="@dimen/height_block_base"

View File

@@ -3,4 +3,4 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
style="@style/MwmWidget.TextView.Search" style="@style/MwmWidget.TextView.Search"
android:text="@string/clear_search" android:text="@string/clear_search"
app:drawableStartCompat="@drawable/ic_cancel"/> app:drawableStartCompat="@drawable/ic_close"/>

View File

@@ -54,7 +54,7 @@
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/clear_the_search" android:contentDescription="@string/clear_the_search"
android:scaleType="center" android:scaleType="center"
app:srcCompat="@drawable/ic_cancel"/> app:srcCompat="@drawable/ic_close"/>
<com.google.android.material.imageview.ShapeableImageView <com.google.android.material.imageview.ShapeableImageView
android:id="@+id/voice_input" android:id="@+id/voice_input"

View File

@@ -885,4 +885,5 @@
<string name="editor_socket">Rediger kontakt</string> <string name="editor_socket">Rediger kontakt</string>
<string name="charge_socket_type1">Type 1</string> <string name="charge_socket_type1">Type 1</string>
<string name="edit_socket_info_tooltip">Opprett nye kontakter eller rediger eksisterende.</string> <string name="edit_socket_info_tooltip">Opprett nye kontakter eller rediger eksisterende.</string>
<string name="avoid_paved">Unngå asfalterte veier</string>
</resources> </resources>

View File

@@ -372,7 +372,7 @@
<!-- The message when user did not find anything in the search. --> <!-- The message when user did not find anything in the search. -->
<string name="search_not_found_query">Pobierz region, w którym szukasz lub spróbuj dodać nazwę pobliskiego miasta/wsi.</string> <string name="search_not_found_query">Pobierz region, w którym szukasz lub spróbuj dodać nazwę pobliskiego miasta/wsi.</string>
<string name="search_history_title">Historia wyszukiwania</string> <string name="search_history_title">Historia wyszukiwania</string>
<string name="search_history_text">Uzyskaj szybki dostęp do ostatniego hasła wyszukiwania.</string> <string name="search_history_text">Zobacz swoje ostatnie wyszukiwania</string>
<string name="clear_search">Wyczyść historię wyszukiwania</string> <string name="clear_search">Wyczyść historię wyszukiwania</string>
<!-- Place Page link to Wikipedia article (if map object has it). --> <!-- Place Page link to Wikipedia article (if map object has it). -->
<string name="read_in_wikipedia">Wikipedia</string> <string name="read_in_wikipedia">Wikipedia</string>

View File

@@ -28,9 +28,9 @@
<string name="type.amenity.gambling">Gambling</string> <string name="type.amenity.gambling">Gambling</string>
<string name="type.leisure.adult_gaming_centre">Spillehal for voksne</string> <string name="type.leisure.adult_gaming_centre">Spillehal for voksne</string>
<string name="type.leisure.amusement_arcade">Arkadespil</string> <string name="type.leisure.amusement_arcade">Arkadespil</string>
<string name="type.amenity.charging_station">Ladestander</string> <string name="type.amenity.charging_station">Ladestation</string>
<string name="type.amenity.charging_station.bicycle">Cykelladestander</string> <string name="type.amenity.charging_station.bicycle">Ladestation til elcykler</string>
<string name="type.amenity.charging_station.motorcar">Billadestander</string> <string name="type.amenity.charging_station.motorcar">Ladestation til elbiler</string>
<string name="type.amenity.childcare">Vuggestue</string> <string name="type.amenity.childcare">Vuggestue</string>
<string name="type.amenity.cinema">Biograf</string> <string name="type.amenity.cinema">Biograf</string>
<string name="type.leisure.bowling_alley">Bowlinghal</string> <string name="type.leisure.bowling_alley">Bowlinghal</string>
@@ -83,17 +83,17 @@
<string name="type.amenity.parking.street_side">Parkeringslomme</string> <string name="type.amenity.parking.street_side">Parkeringslomme</string>
<string name="type.amenity.parking.street_side.fee">Parkeringslomme</string> <string name="type.amenity.parking.street_side.fee">Parkeringslomme</string>
<string name="type.amenity.parking.street_side.private">Privat parkeringslomme</string> <string name="type.amenity.parking.street_side.private">Privat parkeringslomme</string>
<string name="type.amenity.parking.lane">Parkering i vejside</string> <string name="type.amenity.parking.lane">Gadeparkering</string>
<string name="type.amenity.parking.lane.fee">Parkering i vejside</string> <string name="type.amenity.parking.lane.fee">Gadeparkering</string>
<string name="type.amenity.parking.lane.private">Privat parkering i vejside</string> <string name="type.amenity.parking.lane.private">Privat gadeparkering</string>
<string name="type.amenity.parking_entrance">Parkeringsindkørsel</string> <string name="type.amenity.parking_entrance">Indkørsel til parkeringshus</string>
<string name="type.amenity.parking_entrance.private">Privat parkeringsindkørsel</string> <string name="type.amenity.parking_entrance.private">Indkørsel til privat parkeringshus</string>
<string name="type.amenity.parking_entrance.permissive">Parkeringsindkørsel</string> <string name="type.amenity.parking_entrance.permissive">Indkørsel til parkeringshus</string>
<string name="type.amenity.parking_space">Parkeringsplads</string> <string name="type.amenity.parking_space">Parkeringss</string>
<string name="type.amenity.parking_space.permissive">Parkeringsplads</string> <string name="type.amenity.parking_space.permissive">Parkeringss</string>
<string name="type.amenity.parking_space.private">Parkeringsplads</string> <string name="type.amenity.parking_space.private">Parkeringss</string>
<string name="type.amenity.parking_space.underground">Parkeringsplads</string> <string name="type.amenity.parking_space.underground">Parkeringss</string>
<string name="type.amenity.parking_space.disabled">Handicapparkeringsplads</string> <string name="type.amenity.parking_space.disabled">Handicapparkeringss</string>
<string name="type.amenity.payment_terminal">Betalingsautomat</string> <string name="type.amenity.payment_terminal">Betalingsautomat</string>
<string name="type.amenity.pharmacy">Apotek</string> <string name="type.amenity.pharmacy">Apotek</string>
<string name="type.amenity.place_of_worship">Tilbedelsessted</string> <string name="type.amenity.place_of_worship">Tilbedelsessted</string>
@@ -393,7 +393,7 @@
<string name="type.man_made.bridge">Bro</string> <string name="type.man_made.bridge">Bro</string>
<!-- These translations are used for all type.highway.*.tunnel. --> <!-- These translations are used for all type.highway.*.tunnel. -->
<string name="type.highway.road.tunnel">Tunnel</string> <string name="type.highway.road.tunnel">Tunnel</string>
<string name="type.highway.secondary">Sækunder hovedvej</string> <string name="type.highway.secondary">Sekundær hovedvej</string>
<!-- These translations are used for all type.highway.*.bridge. --> <!-- These translations are used for all type.highway.*.bridge. -->
<string name="type.highway.secondary.bridge">Bro</string> <string name="type.highway.secondary.bridge">Bro</string>
<!-- These translations are used for all type.highway.*.tunnel. --> <!-- These translations are used for all type.highway.*.tunnel. -->
@@ -964,7 +964,7 @@
<string name="type.shop.curtain">Gardinhandel</string> <string name="type.shop.curtain">Gardinhandel</string>
<string name="type.shop.deli">Delikatessebutik</string> <string name="type.shop.deli">Delikatessebutik</string>
<string name="type.shop.department_store">Stormagasin</string> <string name="type.shop.department_store">Stormagasin</string>
<string name="type.shop.doityourself">Isenkræmmer</string> <string name="type.shop.doityourself">Byggemarked</string>
<string name="type.shop.dry_cleaning">Renseri</string> <string name="type.shop.dry_cleaning">Renseri</string>
<string name="type.shop.electronics">Elektronikbutik</string> <string name="type.shop.electronics">Elektronikbutik</string>
<string name="type.shop.erotic">Erotikbutik</string> <string name="type.shop.erotic">Erotikbutik</string>
@@ -984,7 +984,7 @@
<string name="type.shop.hearing_aids">Høreapparatbutik</string> <string name="type.shop.hearing_aids">Høreapparatbutik</string>
<string name="type.shop.herbalist">Urtebutik</string> <string name="type.shop.herbalist">Urtebutik</string>
<string name="type.shop.hifi">HiFi lyd</string> <string name="type.shop.hifi">HiFi lyd</string>
<string name="type.shop.houseware">Husholdningsartikler butik</string> <string name="type.shop.houseware">Isenkræmmer</string>
<string name="type.shop.jewelry">Smykkebutik</string> <string name="type.shop.jewelry">Smykkebutik</string>
<string name="type.shop.kitchen">Køkkenforretning</string> <string name="type.shop.kitchen">Køkkenforretning</string>
<string name="type.shop.laundry">Vaskeri</string> <string name="type.shop.laundry">Vaskeri</string>
@@ -993,21 +993,21 @@
<string name="type.shop.mobile_phone">Mobiltelefonbutik</string> <string name="type.shop.mobile_phone">Mobiltelefonbutik</string>
<string name="type.shop.money_lender">Pengeudlåner</string> <string name="type.shop.money_lender">Pengeudlåner</string>
<string name="type.shop.motorcycle">Motorcykelforhandler</string> <string name="type.shop.motorcycle">Motorcykelforhandler</string>
<string name="type.shop.motorcycle_repair">Motorcykel reparation</string> <string name="type.shop.motorcycle_repair">Motorcykelværksted</string>
<string name="type.shop.music">Pladebutik</string> <string name="type.shop.music">Pladebutik</string>
<string name="type.shop.musical_instrument">Butik med musikinstrumenter</string> <string name="type.shop.musical_instrument">Instrumentbutik</string>
<string name="type.shop.newsagent">Avis-kiosk</string> <string name="type.shop.newsagent">Avis-kiosk</string>
<string name="type.shop.optician">Optiker</string> <string name="type.shop.optician">Optiker</string>
<string name="type.shop.outdoor">Fritidsudstyr</string> <string name="type.shop.outdoor">Friluftsbutik</string>
<string name="type.shop.outpost">Afhentningssted</string> <string name="type.shop.outpost">Afhentningssted</string>
<string name="type.shop.pasta">Pasta butik</string> <string name="type.shop.pasta">Pastabutik</string>
<string name="type.shop.pastry">Bagværk</string> <string name="type.shop.pastry">Bagværk</string>
<string name="type.shop.pawnbroker">Pantelåner</string> <string name="type.shop.pawnbroker">Pantelåner</string>
<string name="type.shop.pet">Dyrehandel</string> <string name="type.shop.pet">Dyrehandel</string>
<string name="type.shop.pet_grooming">Kæledyrspleje</string> <string name="type.shop.pet_grooming">Kæledyrspleje</string>
<string name="type.shop.photo">Fotobutik</string> <string name="type.shop.photo">Fotobutik</string>
<string name="type.shop.rental">Udlejningsbutik</string> <string name="type.shop.rental">Udlejningsbutik</string>
<string name="type.shop.rental.bicycle">Cykeludlejningsbutik</string> <string name="type.shop.rental.bicycle">Cykeludlejning</string>
<string name="type.shop.seafood">Fiskehandler</string> <string name="type.shop.seafood">Fiskehandler</string>
<string name="type.shop.second_hand">Genbrugsbutik</string> <string name="type.shop.second_hand">Genbrugsbutik</string>
<string name="type.shop.shoes">Skobutik</string> <string name="type.shop.shoes">Skobutik</string>
@@ -1015,7 +1015,7 @@
<string name="type.shop.stationery">Kontorartikler</string> <string name="type.shop.stationery">Kontorartikler</string>
<string name="type.shop.supermarket">Supermarked</string> <string name="type.shop.supermarket">Supermarked</string>
<string name="type.shop.tattoo">Tatovør</string> <string name="type.shop.tattoo">Tatovør</string>
<string name="type.shop.tea">Tebutik</string> <string name="type.shop.tea">Tehandel</string>
<string name="type.shop.ticket">Billetkontor</string> <string name="type.shop.ticket">Billetkontor</string>
<string name="type.shop.toys">Legetøjsbutik</string> <string name="type.shop.toys">Legetøjsbutik</string>
<string name="type.shop.travel_agency">Rejsebureau</string> <string name="type.shop.travel_agency">Rejsebureau</string>
@@ -1026,7 +1026,7 @@
<string name="type.shop.wine">Vinhandel</string> <string name="type.shop.wine">Vinhandel</string>
<string name="type.shop.agrarian">Landbrugsbutik</string> <string name="type.shop.agrarian">Landbrugsbutik</string>
<string name="type.shop.antiques">Antikvitetsbutik</string> <string name="type.shop.antiques">Antikvitetsbutik</string>
<string name="type.shop.appliance">Hvidevarer butik</string> <string name="type.shop.appliance">Hvidevareforretning</string>
<!-- maybe change to Art Gallery for en-US when supported --> <!-- maybe change to Art Gallery for en-US when supported -->
<string name="type.shop.art">Kunstbutik</string> <string name="type.shop.art">Kunstbutik</string>
<string name="type.shop.baby_goods">Børnebutik</string> <string name="type.shop.baby_goods">Børnebutik</string>
@@ -1036,8 +1036,8 @@
<string name="type.shop.charity">Velgørenhedsbutik</string> <string name="type.shop.charity">Velgørenhedsbutik</string>
<string name="type.shop.cheese">Ostebutik</string> <string name="type.shop.cheese">Ostebutik</string>
<string name="type.shop.craft">Kunst og kunsthåndværk</string> <string name="type.shop.craft">Kunst og kunsthåndværk</string>
<string name="type.shop.dairy">Mejeriprodukter</string> <string name="type.shop.dairy">Mejeributik</string>
<string name="type.shop.electrical">El-butik</string> <string name="type.shop.electrical">Elektrikerbutik</string>
<string name="type.shop.fishing">Fiskeributik</string> <string name="type.shop.fishing">Fiskeributik</string>
<string name="type.shop.interior_decoration">Brugskunsthandel</string> <string name="type.shop.interior_decoration">Brugskunsthandel</string>
<string name="type.shop.lottery">Lottobutik</string> <string name="type.shop.lottery">Lottobutik</string>
@@ -1058,7 +1058,7 @@
<string name="type.sport.australian_football">Australsk fodbold</string> <string name="type.sport.australian_football">Australsk fodbold</string>
<string name="type.sport.baseball">Baseball</string> <string name="type.sport.baseball">Baseball</string>
<string name="type.sport.basketball">Basketball</string> <string name="type.sport.basketball">Basketball</string>
<string name="type.sport.beachvolleyball">Beachvolley</string> <string name="type.sport.beachvolleyball">Strandvolley</string>
<string name="type.sport.chess">Skak</string> <string name="type.sport.chess">Skak</string>
<string name="type.sport.curling">Curling</string> <string name="type.sport.curling">Curling</string>
<string name="type.sport.equestrian">Ridesport</string> <string name="type.sport.equestrian">Ridesport</string>
@@ -1163,7 +1163,7 @@
<string name="type.highway.bridleway">Ridesti</string> <string name="type.highway.bridleway">Ridesti</string>
<string name="type.highway.elevator">Elevator</string> <string name="type.highway.elevator">Elevator</string>
<string name="type.highway.bridleway.permissive">Ridesti</string> <string name="type.highway.bridleway.permissive">Ridesti</string>
<string name="type.amenity.biergarten">Traktørsted</string> <string name="type.amenity.biergarten">Biergarten</string>
<string name="type.aerialway">Svævebane</string> <string name="type.aerialway">Svævebane</string>
<string name="type.aerialway.cable_car">Kabinelift</string> <string name="type.aerialway.cable_car">Kabinelift</string>
<string name="type.aerialway.drag_lift">Træklift</string> <string name="type.aerialway.drag_lift">Træklift</string>
@@ -1220,7 +1220,7 @@
<string name="type.cuisine.bubble_tea">Boblete</string> <string name="type.cuisine.bubble_tea">Boblete</string>
<string name="type.barrier.wall">Mur</string> <string name="type.barrier.wall">Mur</string>
<string name="type.cuisine.fish_and_chips">Fish and Chips</string> <string name="type.cuisine.fish_and_chips">Fish and Chips</string>
<string name="type.highway">Hovedvej</string> <string name="type.highway">Vej</string>
<string name="type.highway.services">Rasteplads</string> <string name="type.highway.services">Rasteplads</string>
<string name="type.internet_access">Internet</string> <string name="type.internet_access">Internet</string>
<string name="type.internet_access.wlan">Trådløst internet</string> <string name="type.internet_access.wlan">Trådløst internet</string>
@@ -1305,7 +1305,7 @@
<string name="type.railway.subway">Metrolinje</string> <string name="type.railway.subway">Metrolinje</string>
<string name="type.public_transport.platform">Stoppested</string> <string name="type.public_transport.platform">Stoppested</string>
<string name="type.railway.subway.tunnel">Metrolinjetunnel</string> <string name="type.railway.subway.tunnel">Metrolinjetunnel</string>
<string name="type.shop.hardware">Byggemarked</string> <string name="type.shop.hardware">Isenkræmmer</string>
<string name="type.aerialway.t.bar">Ankerlift</string> <string name="type.aerialway.t.bar">Ankerlift</string>
<string name="type.traffic_calming.bump">Vejbump</string> <string name="type.traffic_calming.bump">Vejbump</string>
<string name="type.route.ferry">Færgerute</string> <string name="type.route.ferry">Færgerute</string>
@@ -1389,8 +1389,32 @@
<string name="type.barrier.wicket_gate">Portlåge</string> <string name="type.barrier.wicket_gate">Portlåge</string>
<string name="type.natural.wetland.reedbed">Rørskov</string> <string name="type.natural.wetland.reedbed">Rørskov</string>
<string name="type.shop.lighting">Lysbutik</string> <string name="type.shop.lighting">Lysbutik</string>
<string name="type.amenity.bench.backless">Rygløs bænk</string> <string name="type.amenity.bench.backless">Bænk</string>
<string name="type.amenity.charging_station.motorcar.small">Opladningspunkt til biler</string> <string name="type.amenity.charging_station.motorcar.small">Ladestander til biler</string>
<string name="type.leisure.sports_centre.sport.multi">Sportscenter</string> <string name="type.leisure.sports_centre.sport.multi">Idrætscenter</string>
<string name="type.leisure.sports_centre.sport.american_football">Sportscenter</string> <string name="type.leisure.sports_centre.sport.american_football">Idrætscenter</string>
<string name="type.amenity.car_pooling">Samkørsel</string>
<string name="type.shop.telecommunication">Telefonibutik</string>
<string name="type.disusedbusiness">Ledig forretning</string>
<string name="type.amenity.boat_rental">Bådudlejning</string>
<string name="type.man_made.observatory">Observatorium</string>
<string name="type.amenity.lounger">Solseng</string>
<string name="type.leisure.bandstand">Scenepavillon</string>
<string name="type.leisure.indoor_play">Legeland</string>
<string name="type.leisure.sports_centre.sport.archery">Bueskydningscenter</string>
<string name="type.leisure.sports_centre.sport.athletics">Atletikcenter</string>
<string name="type.leisure.sports_centre.sport.baseball">Baseballcenter</string>
<string name="type.leisure.sports_centre.sport.badminton">Badmintoncenter</string>
<string name="type.leisure.sports_centre.sport.basketball">Basketballcenter</string>
<string name="type.leisure.sports_centre.sport.golf">Golfcenter</string>
<string name="type.leisure.sports_centre.sport.gymnastics">Gymnastikcenter</string>
<string name="type.man_made.telescope">Teleskop</string>
<string name="type.man_made.telescope.optical">Teleskop (Optisk)</string>
<string name="type.man_made.telescope.radio">Teleskop (Radio)</string>
<string name="type.man_made.telescope.gamma">Teleskop (Gamma)</string>
<string name="type.leisure.sports_centre.sport.swimming">Svømmehal</string>
<string name="type.amenity.food_bank">Fødevarebank</string>
<string name="type.amenity.soup_kitchen">Suppekøkken</string>
<string name="type.amenity.food_sharing">Fødevarerdeling</string>
<string name="type.amenity.give_box">Donationsbøsse</string>
</resources> </resources>

View File

@@ -1363,4 +1363,13 @@
<string name="type.railway.funicular.tunnel">Kabelbanetunnel</string> <string name="type.railway.funicular.tunnel">Kabelbanetunnel</string>
<string name="type.military">Militært</string> <string name="type.military">Militært</string>
<string name="type.landuse.education">Utdanningsinstitusjon</string> <string name="type.landuse.education">Utdanningsinstitusjon</string>
<string name="type.man_made.telescope">Teleskop</string>
<string name="type.amenity.food_bank">Matsentral</string>
<string name="type.man_made.telescope.gamma">Teleskop (Gamma)</string>
<string name="type.man_made.telescope.radio">Teleskop (Radio)</string>
<string name="type.amenity.soup_kitchen">Suppekjøkken</string>
<string name="type.amenity.car_pooling">Samkjøring</string>
<string name="type.shop.telecommunication">Telekommunikasjonsbutikk</string>
<string name="type.amenity.boat_rental">Båtutleie</string>
<string name="type.man_made.observatory">Observatorium</string>
</resources> </resources>

View File

@@ -1435,4 +1435,15 @@
<string name="type.leisure.sports_centre.sport.yoga">Centrum sportowe</string> <string name="type.leisure.sports_centre.sport.yoga">Centrum sportowe</string>
<string name="type.leisure.fitness_centre.sport.yoga">Studio Jogi</string> <string name="type.leisure.fitness_centre.sport.yoga">Studio Jogi</string>
<string name="type.disusedbusiness">Pusty lokal</string> <string name="type.disusedbusiness">Pusty lokal</string>
<string name="type.amenity.boat_rental">Wypożyczalnia łodzi</string>
<string name="type.man_made.telescope">Teleskop</string>
<string name="type.man_made.telescope.optical">Teleskop optyczny</string>
<string name="type.man_made.telescope.radio">Radioteleskop</string>
<string name="type.man_made.telescope.gamma">Teleskop (prom. gamma)</string>
<string name="type.man_made.observatory">Obserwatorium</string>
<string name="type.amenity.car_pooling">Car Pooling</string>
<string name="type.shop.telecommunication">Sklep dostawcy usług telekomunikacyjnych</string>
<string name="type.amenity.food_bank">Bank żywności</string>
<string name="type.amenity.soup_kitchen">Jadłodajnia</string>
<string name="type.amenity.food_sharing">Jadłodzielnia</string>
</resources> </resources>

View File

@@ -154,4 +154,10 @@
<string name="type.amenity.charging_station.motorcar.small">Polnilno mesto za avtomobile</string> <string name="type.amenity.charging_station.motorcar.small">Polnilno mesto za avtomobile</string>
<string name="type.amenity.childcare">Vrtec</string> <string name="type.amenity.childcare">Vrtec</string>
<string name="type.amenity.cinema">Kino</string> <string name="type.amenity.cinema">Kino</string>
<string name="type.amenity.boat_rental">Izposoja čolnov</string>
<string name="type.man_made.telescope">Teleskop</string>
<string name="type.man_made.telescope.optical">Teleskop (svetlobni)</string>
<string name="type.man_made.telescope.radio">Teleskop (radijski)</string>
<string name="type.man_made.telescope.gamma">Teleskop (gama žarki)</string>
<string name="type.man_made.observatory">Zvezdarna</string>
</resources> </resources>

View File

@@ -1230,7 +1230,7 @@
<string name="type.sport.soccer">Фудбал</string> <string name="type.sport.soccer">Фудбал</string>
<string name="type.sport.swimming">Пливање</string> <string name="type.sport.swimming">Пливање</string>
<string name="type.sport.table_tennis">Стони тенис</string> <string name="type.sport.table_tennis">Стони тенис</string>
<string name="type.sport.tennis">Тенис</string> <string name="type.sport.tennis">Тениски терен</string>
<string name="type.sport.volleyball">Одбојка</string> <string name="type.sport.volleyball">Одбојка</string>
<string name="type.sport.10pin">Куглање</string> <string name="type.sport.10pin">Куглање</string>
<string name="type.sport.9pin">Куглање</string> <string name="type.sport.9pin">Куглање</string>

View File

@@ -147,6 +147,8 @@ set(SRC
osm_o5m_source.hpp osm_o5m_source.hpp
osm_source.cpp osm_source.cpp
osm_xml_source.hpp osm_xml_source.hpp
panoramax_collector.cpp
panoramax_collector.hpp
place_processor.cpp place_processor.cpp
place_processor.hpp place_processor.hpp
platform_helpers.cpp platform_helpers.cpp

View File

@@ -10,6 +10,7 @@
#include "generator/mini_roundabout_transformer.hpp" #include "generator/mini_roundabout_transformer.hpp"
#include "generator/node_mixer.hpp" #include "generator/node_mixer.hpp"
#include "generator/osm2type.hpp" #include "generator/osm2type.hpp"
#include "generator/panoramax_collector.hpp"
#include "generator/region_meta.hpp" #include "generator/region_meta.hpp"
#include "routing/speed_camera_prohibition.hpp" #include "routing/speed_camera_prohibition.hpp"
@@ -68,6 +69,9 @@ void CountryFinalProcessor::Process()
if (!m_isolinesPath.empty()) if (!m_isolinesPath.empty())
AddIsolines(); AddIsolines();
LOG(LINFO, ("Enriching with Panoramax data..."));
EnrichPanoramax();
// DropProhibitedSpeedCameras(); // DropProhibitedSpeedCameras();
LOG(LINFO, ("Processing building parts...")); LOG(LINFO, ("Processing building parts..."));
ProcessBuildingParts(); ProcessBuildingParts();
@@ -293,6 +297,50 @@ void CountryFinalProcessor::AddAddresses()
LOG(LINFO, ("Total addresses:", totalStats)); LOG(LINFO, ("Total addresses:", totalStats));
} }
void CountryFinalProcessor::EnrichPanoramax()
{
if (m_panoramaxFilename.empty() || !Platform::IsFileExistsByFullPath(m_panoramaxFilename))
{
LOG(LINFO, ("Panoramax data not available, skipping enrichment"));
return;
}
LOG(LINFO, ("Enriching roads with Panoramax imagery data from:", m_panoramaxFilename));
// Load Panoramax imagery data
PanoramaxCollector collector;
if (!collector.LoadImageryData(m_panoramaxFilename, ""))
{
LOG(LWARNING, ("Failed to load Panoramax data"));
return;
}
// Enrich roads in each MWM
ForEachMwmTmp(m_temporaryMwmPath, [&](auto const & name, auto const & path)
{
if (!IsCountry(name))
return;
LOG(LINFO, ("Enriching Panoramax for:", name));
std::vector<FeatureBuilder> features;
ForEachFeatureRawFormat<serialization_policy::MaxAccuracy>(
path, [&](FeatureBuilder && fb, uint64_t) {
collector.EnrichRoad(fb);
features.emplace_back(std::move(fb));
});
// Rewrite the file with enriched features
FeatureBuilderWriter<serialization_policy::MaxAccuracy> writer(path, FileWriter::Op::OP_WRITE_TRUNCATE);
for (auto & fb : features)
writer.Write(fb);
LOG(LINFO, (name, "done"));
});
LOG(LINFO, ("Panoramax enrichment complete:", DebugPrint(collector.GetStats())));
}
void CountryFinalProcessor::ProcessCoastline() void CountryFinalProcessor::ProcessCoastline()
{ {
/// @todo We can remove MinSize at all. /// @todo We can remove MinSize at all.

View File

@@ -26,6 +26,7 @@ public:
void SetAddressesDir(std::string const & dir) { m_addressPath = dir; } void SetAddressesDir(std::string const & dir) { m_addressPath = dir; }
void SetCityBoundariesFiles(std::string const & collectorFile) { m_boundariesCollectorFile = collectorFile; } void SetCityBoundariesFiles(std::string const & collectorFile) { m_boundariesCollectorFile = collectorFile; }
void SetPanoramaxFile(std::string const & filename) { m_panoramaxFilename = filename; }
// FinalProcessorIntermediateMwmInterface overrides: // FinalProcessorIntermediateMwmInterface overrides:
void Process() override; void Process() override;
@@ -39,6 +40,7 @@ private:
void AddFakeNodes(); void AddFakeNodes();
void AddIsolines(); void AddIsolines();
void AddAddresses(); void AddAddresses();
void EnrichPanoramax();
void DropProhibitedSpeedCameras(); void DropProhibitedSpeedCameras();
// void Finish(); // void Finish();
@@ -54,6 +56,7 @@ private:
std::string m_fakeNodesFilename; std::string m_fakeNodesFilename;
std::string m_miniRoundaboutsFilename; std::string m_miniRoundaboutsFilename;
std::string m_addrInterpolFilename; std::string m_addrInterpolFilename;
std::string m_panoramaxFilename;
std::string m_hierarchySrcFilename; std::string m_hierarchySrcFilename;

View File

@@ -42,6 +42,9 @@ struct GenerateInfo
// External folders with additional preprocessed data (isolines, addresses). // External folders with additional preprocessed data (isolines, addresses).
std::string m_isolinesDir, m_addressesDir; std::string m_isolinesDir, m_addressesDir;
// Panoramax imagery data file
std::string m_panoramaxFilename;
// Current generated file name if --output option is defined. // Current generated file name if --output option is defined.
std::string m_fileName; std::string m_fileName;

View File

@@ -107,6 +107,7 @@ DEFINE_string(nodes_list_path, "",
DEFINE_bool(generate_isolines_info, false, "Generate the isolines info section"); DEFINE_bool(generate_isolines_info, false, "Generate the isolines info section");
DEFINE_string(isolines_path, "", "Path to isolines directory. If set, adds isolines linear features."); DEFINE_string(isolines_path, "", "Path to isolines directory. If set, adds isolines linear features.");
DEFINE_string(addresses_path, "", "Path to addresses directory. If set, adds addr:interpolation features."); DEFINE_string(addresses_path, "", "Path to addresses directory. If set, adds addr:interpolation features.");
DEFINE_string(panoramax_file, "", "Path to Panoramax imagery coords file. If set, enriches roads with street-level imagery availability.");
// Routing. // Routing.
DEFINE_bool(make_routing_index, false, "Make sections with the routing information."); DEFINE_bool(make_routing_index, false, "Make sections with the routing information.");
@@ -243,6 +244,7 @@ MAIN_WITH_ERROR_HANDLING([](int argc, char ** argv)
genInfo.m_complexHierarchyFilename = FLAGS_complex_hierarchy_data; genInfo.m_complexHierarchyFilename = FLAGS_complex_hierarchy_data;
genInfo.m_isolinesDir = FLAGS_isolines_path; genInfo.m_isolinesDir = FLAGS_isolines_path;
genInfo.m_addressesDir = FLAGS_addresses_path; genInfo.m_addressesDir = FLAGS_addresses_path;
genInfo.m_panoramaxFilename = FLAGS_panoramax_file;
// Use merged style. // Use merged style.
GetStyleReader().SetCurrentStyle(MapStyleMerged); GetStyleReader().SetCurrentStyle(MapStyleMerged);

View File

@@ -0,0 +1,157 @@
#include "generator/panoramax_collector.hpp"
#include "indexer/feature_meta.hpp"
#include "indexer/ftypes_matcher.hpp"
#include "geometry/mercator.hpp"
#include "base/assert.hpp"
#include "base/logging.hpp"
#include <cstdint>
#include <fstream>
#include <sstream>
namespace generator
{
PanoramaxCollector::PanoramaxCollector() = default;
bool PanoramaxCollector::LoadImageryData(std::string const & coordsFilePath, std::string const & /* tilesDir */)
{
LOG(LINFO, ("Loading Panoramax imagery from:", coordsFilePath));
std::ifstream file(coordsFilePath, std::ios::binary);
if (!file.is_open())
{
LOG(LWARNING, ("Failed to open Panoramax coords file:", coordsFilePath));
return false;
}
// Read header
uint32_t version;
uint64_t count;
file.read(reinterpret_cast<char*>(&version), sizeof(version));
file.read(reinterpret_cast<char*>(&count), sizeof(count));
if (version != 1)
{
LOG(LWARNING, ("Unsupported Panoramax coords file version:", version));
return false;
}
LOG(LINFO, ("Loading", count, "Panoramax imagery points..."));
// Read coordinates and build spatial index
std::vector<ImageryPoint> points;
points.reserve(count);
for (uint64_t i = 0; i < count; ++i)
{
double lat, lon;
file.read(reinterpret_cast<char*>(&lat), sizeof(lat));
file.read(reinterpret_cast<char*>(&lon), sizeof(lon));
// Convert to Mercator coordinates
m2::PointD mercPt = mercator::FromLatLon(lat, lon);
points.emplace_back(mercPt);
if ((i + 1) % 500000 == 0)
LOG(LINFO, ("Loaded", i + 1, "/", count, "points"));
}
if (!file)
{
LOG(LWARNING, ("Error reading Panoramax coords file"));
return false;
}
file.close();
LOG(LINFO, ("Building spatial index for", points.size(), "points..."));
// Build spatial index
for (auto const & pt : points)
m_imageryTree.Add(pt);
m_stats.m_totalImageryPoints = static_cast<uint32_t>(points.size());
LOG(LINFO, ("Panoramax data loaded:", m_stats.m_totalImageryPoints, "imagery points"));
return true;
}
bool PanoramaxCollector::EnrichRoad(feature::FeatureBuilder & fb)
{
// Only process roads
static auto const & isRoad = ftypes::IsWayChecker::Instance();
if (!isRoad(fb.GetTypes()))
return false;
m_stats.m_totalRoads++;
// Check if road already has Panoramax flag
if (fb.GetMetadata().Has(feature::Metadata::FMD_PANORAMAX))
return false;
// Get road geometry
std::vector<m2::PointD> roadPoints;
fb.ForEachPoint([&roadPoints](m2::PointD const & pt) {
roadPoints.push_back(pt);
});
if (roadPoints.empty())
return false;
// Calculate road bounding box
m2::RectD roadBBox;
for (auto const & pt : roadPoints)
roadBBox.Add(pt);
// Expand bounding box by threshold distance in Mercator units
auto const center = roadBBox.Center();
auto const inflateRect = mercator::RectByCenterXYAndSizeInMeters(center, kDistanceThresholdM);
roadBBox.Inflate(inflateRect.SizeX() / 2.0, inflateRect.SizeY() / 2.0);
// Query imagery tree for nearby points
bool hasImagery = false;
m_imageryTree.ForEachInRect(roadBBox, [&](ImageryPoint const & imgPt) {
if (hasImagery)
return; // Already found, early exit
// Check distance to each road point
for (auto const & roadPt : roadPoints)
{
double const distM = mercator::DistanceOnEarth(roadPt, imgPt.m_point);
if (distM <= kDistanceThresholdM)
{
hasImagery = true;
return;
}
}
});
if (hasImagery)
{
fb.GetMetadata().Set(feature::Metadata::FMD_PANORAMAX, "yes");
m_stats.m_roadsWithImagery++;
return true;
}
return false;
}
std::string DebugPrint(PanoramaxCollector::Stats const & s)
{
std::ostringstream out;
out << "PanoramaxCollector::Stats {"
<< " totalRoads: " << s.m_totalRoads
<< ", roadsWithImagery: " << s.m_roadsWithImagery
<< " (" << (s.m_totalRoads > 0 ? (s.m_roadsWithImagery * 100.0 / s.m_totalRoads) : 0) << "%)"
<< ", totalImageryPoints: " << s.m_totalImageryPoints
<< " }";
return out.str();
}
} // namespace generator

View File

@@ -0,0 +1,72 @@
#pragma once
#include "generator/feature_builder.hpp"
#include "geometry/point2d.hpp"
#include "geometry/tree4d.hpp"
#include "base/geo_object_id.hpp"
#include <string>
#include <vector>
namespace generator
{
/// Enriches road features with Panoramax street-level imagery availability flag.
/// Loads Panoramax imagery coordinates from tile index and marks roads within threshold distance.
class PanoramaxCollector
{
public:
// Distance threshold for matching roads to imagery (meters)
static double constexpr kDistanceThresholdM = 20.0;
/// ImageryPoint represents a single point where street-level imagery exists
struct ImageryPoint
{
m2::PointD m_point; // Mercator coordinates
ImageryPoint() = default;
explicit ImageryPoint(m2::PointD const & pt) : m_point(pt) {}
m2::RectD GetLimitRect() const { return m2::RectD(m_point, m_point); }
};
/// Statistics for debugging/logging
struct Stats
{
uint32_t m_totalRoads = 0;
uint32_t m_roadsWithImagery = 0;
uint32_t m_totalImageryPoints = 0;
uint32_t m_tilesProcessed = 0;
friend std::string DebugPrint(Stats const & s);
};
PanoramaxCollector();
/// Load Panoramax imagery data from tile directory
/// @param tileIndexPath Path to tile_index.json
/// @param tilesDir Directory containing .mvt tiles
/// @return true if data loaded successfully
bool LoadImageryData(std::string const & tileIndexPath, std::string const & tilesDir);
/// Check if a road has nearby imagery and enrich it
/// @param fb FeatureBuilder for a road segment
/// @return true if imagery was found within threshold
bool EnrichRoad(feature::FeatureBuilder & fb);
Stats const & GetStats() const { return m_stats; }
private:
/// Spatial index of imagery points
m4::Tree<ImageryPoint> m_imageryTree;
/// Statistics
Stats m_stats;
/// Decode an MVT tile and extract imagery coordinates
std::vector<m2::PointD> DecodeMVTTile(std::string const & tilePath,
int tileX, int tileY, int zoom);
};
} // namespace generator

View File

@@ -182,6 +182,7 @@ RawGenerator::FinalProcessorPtr RawGenerator::CreateCountryFinalProcessor(Affili
auto finalProcessor = std::make_shared<CountryFinalProcessor>(affiliations, m_genInfo.m_tmpDir, m_threadsCount); auto finalProcessor = std::make_shared<CountryFinalProcessor>(affiliations, m_genInfo.m_tmpDir, m_threadsCount);
finalProcessor->SetIsolinesDir(m_genInfo.m_isolinesDir); finalProcessor->SetIsolinesDir(m_genInfo.m_isolinesDir);
finalProcessor->SetAddressesDir(m_genInfo.m_addressesDir); finalProcessor->SetAddressesDir(m_genInfo.m_addressesDir);
finalProcessor->SetPanoramaxFile(m_genInfo.m_panoramaxFilename);
finalProcessor->SetMiniRoundabouts(m_genInfo.GetIntermediateFileName(MINI_ROUNDABOUTS_FILENAME)); finalProcessor->SetMiniRoundabouts(m_genInfo.GetIntermediateFileName(MINI_ROUNDABOUTS_FILENAME));
finalProcessor->SetAddrInterpolation(m_genInfo.GetIntermediateFileName(ADDR_INTERPOL_FILENAME)); finalProcessor->SetAddrInterpolation(m_genInfo.GetIntermediateFileName(ADDR_INTERPOL_FILENAME));
if (addAds) if (addAds)

View File

@@ -27,7 +27,7 @@
"type.amenity.bicycle_parking" = "Cykelparkering"; "type.amenity.bicycle_parking" = "Cykelparkering";
"type.amenity.bicycle_rental" = "Cykeludlejning"; "type.amenity.bicycle_rental" = "Cykeludlejning";
"type.amenity.bicycle_repair_station" = "Cykelreparationsstation"; "type.amenity.bicycle_repair_station" = "Cykelreparationsstation";
"type.amenity.biergarten" = "Traktørsted"; "type.amenity.biergarten" = "Biergarten";
"type.amenity.brothel" = "Bordel"; "type.amenity.brothel" = "Bordel";
"type.amenity.bureau_de_change" = "Valutaveksling"; "type.amenity.bureau_de_change" = "Valutaveksling";
"type.amenity.bus_station" = "Rutebilstation"; "type.amenity.bus_station" = "Rutebilstation";
@@ -40,9 +40,9 @@
"type.amenity.gambling" = "Gambling"; "type.amenity.gambling" = "Gambling";
"type.leisure.adult_gaming_centre" = "Spillehal for voksne"; "type.leisure.adult_gaming_centre" = "Spillehal for voksne";
"type.leisure.amusement_arcade" = "Arkadespil"; "type.leisure.amusement_arcade" = "Arkadespil";
"type.amenity.charging_station" = "Ladestander"; "type.amenity.charging_station" = "Ladestation";
"type.amenity.charging_station.bicycle" = "Cykelladestander"; "type.amenity.charging_station.bicycle" = "Ladestation til elcykler";
"type.amenity.charging_station.motorcar" = "Billadestander"; "type.amenity.charging_station.motorcar" = "Ladestation til elbiler";
"type.amenity.childcare" = "Vuggestue"; "type.amenity.childcare" = "Vuggestue";
"type.amenity.cinema" = "Biograf"; "type.amenity.cinema" = "Biograf";
"type.leisure.bowling_alley" = "Bowlinghal"; "type.leisure.bowling_alley" = "Bowlinghal";
@@ -99,17 +99,17 @@
"type.amenity.parking.street_side" = "Parkeringslomme"; "type.amenity.parking.street_side" = "Parkeringslomme";
"type.amenity.parking.street_side.fee" = "Parkeringslomme"; "type.amenity.parking.street_side.fee" = "Parkeringslomme";
"type.amenity.parking.street_side.private" = "Privat parkeringslomme"; "type.amenity.parking.street_side.private" = "Privat parkeringslomme";
"type.amenity.parking.lane" = "Parkering i vejside"; "type.amenity.parking.lane" = "Gadeparkering";
"type.amenity.parking.lane.fee" = "Parkering i vejside"; "type.amenity.parking.lane.fee" = "Gadeparkering";
"type.amenity.parking.lane.private" = "Privat parkering i vejside"; "type.amenity.parking.lane.private" = "Privat gadeparkering";
"type.amenity.parking_entrance" = "Parkeringsindkørsel"; "type.amenity.parking_entrance" = "Indkørsel til parkeringshus";
"type.amenity.parking_entrance.private" = "Privat parkeringsindkørsel"; "type.amenity.parking_entrance.private" = "Indkørsel til privat parkeringshus";
"type.amenity.parking_entrance.permissive" = "Parkeringsindkørsel"; "type.amenity.parking_entrance.permissive" = "Indkørsel til parkeringshus";
"type.amenity.parking_space" = "Parkeringsplads"; "type.amenity.parking_space" = "Parkeringss";
"type.amenity.parking_space.permissive" = "Parkeringsplads"; "type.amenity.parking_space.permissive" = "Parkeringss";
"type.amenity.parking_space.private" = "Parkeringsplads"; "type.amenity.parking_space.private" = "Parkeringss";
"type.amenity.parking_space.underground" = "Parkeringsplads"; "type.amenity.parking_space.underground" = "Parkeringss";
"type.amenity.parking_space.disabled" = "Handicapparkeringsplads"; "type.amenity.parking_space.disabled" = "Handicapparkeringss";
"type.amenity.payment_terminal" = "Betalingsautomat"; "type.amenity.payment_terminal" = "Betalingsautomat";
"type.amenity.pharmacy" = "Apotek"; "type.amenity.pharmacy" = "Apotek";
"type.amenity.place_of_worship" = "Tilbedelsessted"; "type.amenity.place_of_worship" = "Tilbedelsessted";
@@ -384,7 +384,7 @@
"type.healthcare.psychotherapist" = "Psykoterapi"; "type.healthcare.psychotherapist" = "Psykoterapi";
"type.healthcare.sample_collection" = "Prøvetagning"; "type.healthcare.sample_collection" = "Prøvetagning";
"type.healthcare.speech_therapist" = "Tale terapi"; "type.healthcare.speech_therapist" = "Tale terapi";
"type.highway" = "Hovedvej"; "type.highway" = "Vej";
"type.highway.bridleway" = "Ridesti"; "type.highway.bridleway" = "Ridesti";
/* These translations are used for all type.highway.*.bridge. */ /* These translations are used for all type.highway.*.bridge. */
@@ -503,7 +503,7 @@
/* These translations are used for all type.highway.*.tunnel. */ /* These translations are used for all type.highway.*.tunnel. */
"type.highway.road.tunnel" = "Tunnel"; "type.highway.road.tunnel" = "Tunnel";
"type.highway.secondary" = "Sækunder hovedvej"; "type.highway.secondary" = "Sekundær hovedvej";
/* These translations are used for all type.highway.*.bridge. */ /* These translations are used for all type.highway.*.bridge. */
"type.highway.secondary.bridge" = "Bro"; "type.highway.secondary.bridge" = "Bro";
@@ -1216,7 +1216,7 @@
"type.shop.curtain" = "Gardinhandel"; "type.shop.curtain" = "Gardinhandel";
"type.shop.deli" = "Delikatessebutik"; "type.shop.deli" = "Delikatessebutik";
"type.shop.department_store" = "Stormagasin"; "type.shop.department_store" = "Stormagasin";
"type.shop.doityourself" = "Isenkræmmer"; "type.shop.doityourself" = "Byggemarked";
"type.shop.dry_cleaning" = "Renseri"; "type.shop.dry_cleaning" = "Renseri";
"type.shop.electronics" = "Elektronikbutik"; "type.shop.electronics" = "Elektronikbutik";
"type.shop.erotic" = "Erotikbutik"; "type.shop.erotic" = "Erotikbutik";
@@ -1232,12 +1232,12 @@
"type.shop.greengrocer" = "Grønthandler"; "type.shop.greengrocer" = "Grønthandler";
"type.shop.grocery" = "Købmand"; "type.shop.grocery" = "Købmand";
"type.shop.hairdresser" = "Frisør"; "type.shop.hairdresser" = "Frisør";
"type.shop.hardware" = "Byggemarked"; "type.shop.hardware" = "Isenkræmmer";
"type.shop.health_food" = "Helsekostbutik"; "type.shop.health_food" = "Helsekostbutik";
"type.shop.hearing_aids" = "Høreapparatbutik"; "type.shop.hearing_aids" = "Høreapparatbutik";
"type.shop.herbalist" = "Urtebutik"; "type.shop.herbalist" = "Urtebutik";
"type.shop.hifi" = "HiFi lyd"; "type.shop.hifi" = "HiFi lyd";
"type.shop.houseware" = "Husholdningsartikler butik"; "type.shop.houseware" = "Isenkræmmer";
"type.shop.jewelry" = "Smykkebutik"; "type.shop.jewelry" = "Smykkebutik";
"type.shop.kiosk" = "Kiosk"; "type.shop.kiosk" = "Kiosk";
"type.shop.kitchen" = "Køkkenforretning"; "type.shop.kitchen" = "Køkkenforretning";
@@ -1247,21 +1247,21 @@
"type.shop.mobile_phone" = "Mobiltelefonbutik"; "type.shop.mobile_phone" = "Mobiltelefonbutik";
"type.shop.money_lender" = "Pengeudlåner"; "type.shop.money_lender" = "Pengeudlåner";
"type.shop.motorcycle" = "Motorcykelforhandler"; "type.shop.motorcycle" = "Motorcykelforhandler";
"type.shop.motorcycle_repair" = "Motorcykel reparation"; "type.shop.motorcycle_repair" = "Motorcykelværksted";
"type.shop.music" = "Pladebutik"; "type.shop.music" = "Pladebutik";
"type.shop.musical_instrument" = "Butik med musikinstrumenter"; "type.shop.musical_instrument" = "Instrumentbutik";
"type.shop.newsagent" = "Avis-kiosk"; "type.shop.newsagent" = "Avis-kiosk";
"type.shop.optician" = "Optiker"; "type.shop.optician" = "Optiker";
"type.shop.outdoor" = "Fritidsudstyr"; "type.shop.outdoor" = "Friluftsbutik";
"type.shop.outpost" = "Afhentningssted"; "type.shop.outpost" = "Afhentningssted";
"type.shop.pasta" = "Pasta butik"; "type.shop.pasta" = "Pastabutik";
"type.shop.pastry" = "Bagværk"; "type.shop.pastry" = "Bagværk";
"type.shop.pawnbroker" = "Pantelåner"; "type.shop.pawnbroker" = "Pantelåner";
"type.shop.pet" = "Dyrehandel"; "type.shop.pet" = "Dyrehandel";
"type.shop.pet_grooming" = "Kæledyrspleje"; "type.shop.pet_grooming" = "Kæledyrspleje";
"type.shop.photo" = "Fotobutik"; "type.shop.photo" = "Fotobutik";
"type.shop.rental" = "Udlejningsbutik"; "type.shop.rental" = "Udlejningsbutik";
"type.shop.rental.bicycle" = "Cykeludlejningsbutik"; "type.shop.rental.bicycle" = "Cykeludlejning";
"type.shop.seafood" = "Fiskehandler"; "type.shop.seafood" = "Fiskehandler";
"type.shop.second_hand" = "Genbrugsbutik"; "type.shop.second_hand" = "Genbrugsbutik";
"type.shop.shoes" = "Skobutik"; "type.shop.shoes" = "Skobutik";
@@ -1269,7 +1269,7 @@
"type.shop.stationery" = "Kontorartikler"; "type.shop.stationery" = "Kontorartikler";
"type.shop.supermarket" = "Supermarked"; "type.shop.supermarket" = "Supermarked";
"type.shop.tattoo" = "Tatovør"; "type.shop.tattoo" = "Tatovør";
"type.shop.tea" = "Tebutik"; "type.shop.tea" = "Tehandel";
"type.shop.ticket" = "Billetkontor"; "type.shop.ticket" = "Billetkontor";
"type.shop.toys" = "Legetøjsbutik"; "type.shop.toys" = "Legetøjsbutik";
"type.shop.travel_agency" = "Rejsebureau"; "type.shop.travel_agency" = "Rejsebureau";
@@ -1280,7 +1280,7 @@
"type.shop.wine" = "Vinhandel"; "type.shop.wine" = "Vinhandel";
"type.shop.agrarian" = "Landbrugsbutik"; "type.shop.agrarian" = "Landbrugsbutik";
"type.shop.antiques" = "Antikvitetsbutik"; "type.shop.antiques" = "Antikvitetsbutik";
"type.shop.appliance" = "Hvidevarer butik"; "type.shop.appliance" = "Hvidevareforretning";
/* maybe change to Art Gallery for en-US when supported */ /* maybe change to Art Gallery for en-US when supported */
"type.shop.art" = "Kunstbutik"; "type.shop.art" = "Kunstbutik";
@@ -1291,8 +1291,8 @@
"type.shop.charity" = "Velgørenhedsbutik"; "type.shop.charity" = "Velgørenhedsbutik";
"type.shop.cheese" = "Ostebutik"; "type.shop.cheese" = "Ostebutik";
"type.shop.craft" = "Kunst og kunsthåndværk"; "type.shop.craft" = "Kunst og kunsthåndværk";
"type.shop.dairy" = "Mejeriprodukter"; "type.shop.dairy" = "Mejeributik";
"type.shop.electrical" = "El-butik"; "type.shop.electrical" = "Elektrikerbutik";
"type.shop.fishing" = "Fiskeributik"; "type.shop.fishing" = "Fiskeributik";
"type.shop.interior_decoration" = "Brugskunsthandel"; "type.shop.interior_decoration" = "Brugskunsthandel";
"type.shop.lottery" = "Lottobutik"; "type.shop.lottery" = "Lottobutik";
@@ -1313,7 +1313,7 @@
"type.sport.australian_football" = "Australsk fodbold"; "type.sport.australian_football" = "Australsk fodbold";
"type.sport.baseball" = "Baseball"; "type.sport.baseball" = "Baseball";
"type.sport.basketball" = "Basketball"; "type.sport.basketball" = "Basketball";
"type.sport.beachvolleyball" = "Beachvolley"; "type.sport.beachvolleyball" = "Strandvolley";
"type.sport.bowls" = "Bowls"; "type.sport.bowls" = "Bowls";
"type.sport.chess" = "Skak"; "type.sport.chess" = "Skak";
"type.sport.cricket" = "Cricket"; "type.sport.cricket" = "Cricket";
@@ -1489,7 +1489,31 @@
"type.power.portal" = "Power Portal"; "type.power.portal" = "Power Portal";
"type.building.guardhouse" = "Sikkerhedsbås"; "type.building.guardhouse" = "Sikkerhedsbås";
"type.shop.lighting" = "Lysbutik"; "type.shop.lighting" = "Lysbutik";
"type.amenity.charging_station.motorcar.small" = "Opladningspunkt til biler"; "type.amenity.charging_station.motorcar.small" = "Ladestander til biler";
"type.leisure.sports_centre.sport.american_football" = "Sportscenter"; "type.leisure.sports_centre.sport.american_football" = "Idrætscenter";
"type.leisure.sports_centre.sport.multi" = "Sportscenter"; "type.leisure.sports_centre.sport.multi" = "Idrætscenter";
"type.amenity.bench.backless" = "Rygløs bænk"; "type.amenity.bench.backless" = "Bænk";
"type.man_made.observatory" = "Observatorium";
"type.man_made.telescope.optical" = "Teleskop (Optisk)";
"type.man_made.telescope.radio" = "Teleskop (Radio)";
"type.amenity.food_sharing" = "Fødevarerdeling";
"type.amenity.food_bank" = "Fødevarebank";
"type.amenity.soup_kitchen" = "Suppekøkken";
"type.man_made.telescope" = "Teleskop";
"type.amenity.give_box" = "Donationsbøsse";
"type.man_made.telescope.gamma" = "Teleskop (Gamma)";
"type.amenity.car_pooling" = "Samkørsel";
"type.shop.telecommunication" = "Telefonibutik";
"type.disusedbusiness" = "Ledig forretning";
"type.amenity.boat_rental" = "Bådudlejning";
"type.amenity.lounger" = "Solseng";
"type.leisure.bandstand" = "Scenepavillon";
"type.leisure.indoor_play" = "Legeland";
"type.leisure.sports_centre.sport.archery" = "Bueskydningscenter";
"type.leisure.sports_centre.sport.athletics" = "Atletikcenter";
"type.leisure.sports_centre.sport.baseball" = "Baseballcenter";
"type.leisure.sports_centre.sport.badminton" = "Badmintoncenter";
"type.leisure.sports_centre.sport.basketball" = "Basketballcenter";
"type.leisure.sports_centre.sport.golf" = "Golfcenter";
"type.leisure.sports_centre.sport.gymnastics" = "Gymnastikcenter";
"type.leisure.sports_centre.sport.swimming" = "Svømmehal";

View File

@@ -1099,3 +1099,4 @@
"offline_explanation_title" = "Offline-kart"; "offline_explanation_title" = "Offline-kart";
"avoid_steps" = "Unngå trapper"; "avoid_steps" = "Unngå trapper";
"editor_place_doesnt_exist_description" = "Beskriv hvordan stedet ser ut nå for å sende en feilmelding til OpenStreetMap-fellesskapet"; "editor_place_doesnt_exist_description" = "Beskriv hvordan stedet ser ut nå for å sende en feilmelding til OpenStreetMap-fellesskapet";
"avoid_paved" = "Unngå asfalterte veier";

View File

@@ -1525,3 +1525,12 @@
"type.shop.lighting" = "Lampebutikk"; "type.shop.lighting" = "Lampebutikk";
"type.leisure.sports_centre.sport.swimming" = "Svømmesenter"; "type.leisure.sports_centre.sport.swimming" = "Svømmesenter";
"type.amenity.bench.backless" = "Benk uten rygg"; "type.amenity.bench.backless" = "Benk uten rygg";
"type.man_made.telescope.radio" = "Teleskop (Radio)";
"type.amenity.food_bank" = "Matsentral";
"type.amenity.soup_kitchen" = "Suppekjøkken";
"type.man_made.telescope" = "Teleskop";
"type.man_made.telescope.gamma" = "Teleskop (Gamma)";
"type.amenity.car_pooling" = "Samkjøring";
"type.man_made.observatory" = "Observatorium";
"type.shop.telecommunication" = "Telekommunikasjonsbutikk";
"type.amenity.boat_rental" = "Båtutleie";

View File

@@ -487,7 +487,7 @@
/* The message when user did not find anything in the search. */ /* The message when user did not find anything in the search. */
"search_not_found_query" = "Pobierz region, w którym szukasz lub spróbuj dodać nazwę pobliskiego miasta/wsi."; "search_not_found_query" = "Pobierz region, w którym szukasz lub spróbuj dodać nazwę pobliskiego miasta/wsi.";
"search_history_title" = "Historia wyszukiwania"; "search_history_title" = "Historia wyszukiwania";
"search_history_text" = "Uzyskaj szybki dostęp do ostatniego hasła wyszukiwania."; "search_history_text" = "Zobacz swoje ostatnie wyszukiwania.";
"clear_search" = "Wyczyść historię wyszukiwania"; "clear_search" = "Wyczyść historię wyszukiwania";
/* Place Page link to Wikipedia article (if map object has it). */ /* Place Page link to Wikipedia article (if map object has it). */

View File

@@ -1527,3 +1527,14 @@
"type.leisure.bandstand" = "Muszla koncertowa"; "type.leisure.bandstand" = "Muszla koncertowa";
"type.disusedbusiness" = "Pusty lokal"; "type.disusedbusiness" = "Pusty lokal";
"type.amenity.lounger" = "Leżak"; "type.amenity.lounger" = "Leżak";
"type.man_made.observatory" = "Obserwatorium";
"type.man_made.telescope.optical" = "Teleskop optyczny";
"type.man_made.telescope.radio" = "Radioteleskop";
"type.man_made.telescope" = "Teleskop";
"type.man_made.telescope.gamma" = "Teleskop (prom. gamma)";
"type.amenity.boat_rental" = "Wypożyczalnia łodzi";
"type.amenity.food_sharing" = "Jadłodzielnia";
"type.amenity.food_bank" = "Bank żywności";
"type.amenity.soup_kitchen" = "Jadłodajnia";
"type.amenity.car_pooling" = "Car Pooling";
"type.shop.telecommunication" = "Sklep dostawcy usług telekomunikacyjnych";

View File

@@ -153,3 +153,9 @@
"type.amenity.love_hotel" = "Hotel za zaljubljence"; "type.amenity.love_hotel" = "Hotel za zaljubljence";
"type.amenity.charging_station.motorcar.small" = "Polnilno mesto za avtomobile"; "type.amenity.charging_station.motorcar.small" = "Polnilno mesto za avtomobile";
"type.amenity.cinema" = "Kino"; "type.amenity.cinema" = "Kino";
"type.man_made.observatory" = "Zvezdarna";
"type.man_made.telescope.optical" = "Teleskop (svetlobni)";
"type.man_made.telescope.radio" = "Teleskop (radijski)";
"type.man_made.telescope" = "Teleskop";
"type.man_made.telescope.gamma" = "Teleskop (gama žarki)";
"type.amenity.boat_rental" = "Izposoja čolnov";

View File

@@ -190,7 +190,7 @@ UNIT_TEST(LevenshteinDFA_ErrorsMade)
} }
{ {
vector<UniString> const allowedMisprints = {MakeUniString("yj")}; array<UniString, 11> const allowedMisprints = {MakeUniString("yj")};
size_t const prefixSize = 1; size_t const prefixSize = 1;
size_t const maxErrors = 1; size_t const maxErrors = 1;
string const str = "yekaterinburg"; string const str = "yekaterinburg";

View File

@@ -52,7 +52,7 @@ optional<Score> GetFrcScore(Graph::Edge const & e, FunctionalRoadClass functiona
return hwClass == HighwayClass::Motorway || hwClass == HighwayClass::Trunk ? optional<Score>(kMaxScoreForFrc) : nullopt; return hwClass == HighwayClass::Motorway || hwClass == HighwayClass::Trunk ? optional<Score>(kMaxScoreForFrc) : nullopt;
case FunctionalRoadClass::FRC1: case FunctionalRoadClass::FRC1:
return (HighwayClass::Motorway || hwClass == HighwayClass::Trunk || hwClass == HighwayClass::Primary) ? optional<Score>(kMaxScoreForFrc) return (hwClass == HighwayClass::Motorway || hwClass == HighwayClass::Trunk || hwClass == HighwayClass::Primary) ? optional<Score>(kMaxScoreForFrc)
: nullopt; : nullopt;
case FunctionalRoadClass::FRC2: case FunctionalRoadClass::FRC2:

View File

@@ -0,0 +1,68 @@
Edit the rclone conf secret for Codeberg Actions, to deliver maps to i.e. /var/www/html/maps/251231 via a limited user.
apt update
apt install nginx vim
### set hostname for ssh sanity (will show in console upon next bash launch):
vim /etc/hostname
hostname cdn-XX-1
### for SSL:
sudo snap install --classic certbot
sudo certbot --nginx
### remove IPs from logging on line ~36:
vim /etc/nginx/nginx.conf
```
##
# Logging Settings
##
log_format comaps '0.0.0.0 - - [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"';
access_log /var/log/nginx/access.log comaps;
```
### set up monitoring:
apt install goaccess
edit /etc/goaccess/goaccess.conf and uncomment time-format %H:%M:%S, date-format %Y-%m-%d, log-format COMBINED
vim /etc/crontab
`*/5 * * * * root /usr/bin/goaccess /var/log/nginx/access.log -o /var/www/html/monitor.html`
### set up basic http pages/responses:
cd /var/www/html/
mkdir maps
rm index.nginx-debian.html
wget https://www.comaps.app/favicon.ico
vim robots.txt
```
User-agent: *
Disallow: /
```
vim index.html
```
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>CoMaps CDN</title>
</head>
<body>
<h1>This is a CDN for <a href="https://comaps.app">CoMaps</a></h1>
<h2>Resources:</h2>
<ol>
<li>CoMaps <a href="https://cdn.comaps.app/subway/">subway validator</a></li>
<li>CoMaps <a href="https://comaps.app/news/">News</a></li>
<li><a href="https://comaps.app/donate/">Donate</a></li>
</ol>
</body>
</html>
```

View File

@@ -1,5 +1,5 @@
import os import os
import subprocess
class MapsGeneratorError(Exception): class MapsGeneratorError(Exception):
pass pass
@@ -35,9 +35,24 @@ class FailedTest(MapsGeneratorError):
def wait_and_raise_if_fail(p): def wait_and_raise_if_fail(p):
if p.wait() != os.EX_OK: if p.wait() != os.EX_OK:
args = p.args if type(p) is subprocess.Popen:
logs = p.output.name args = p.args
if p.error.name != logs: stdout = p.stdout
logs += " and " + p.error.name stderr = p.stderr
msg = f"The launch of {args.pop(0)} failed.\nArguments used: {' '.join(args)}\nSee details in {logs}" logs = None
raise BadExitStatusError(msg) errors = None
if type(stdout) is not type(None):
logs = stdout.read(256).decode()
if type(stderr) is not type(None):
errors = stderr.read(256).decode()
if errors != logs:
logs += " and " + errors
msg = f"The launch of {args.pop(0)} failed.\nArguments used: {' '.join(args)}\nSee details in {logs}"
raise BadExitStatusError(msg)
else:
args = p.args
logs = p.output.name
if p.error.name != logs:
logs += " and " + p.error.name
msg = f"The launch of {args.pop(0)} failed.\nArguments used: {' '.join(args)}\nSee details in {logs}"
raise BadExitStatusError(msg)

View File

@@ -11,6 +11,7 @@ import multiprocessing
import os import os
import shutil import shutil
import tarfile import tarfile
import errno
from collections import defaultdict from collections import defaultdict
from concurrent.futures import ThreadPoolExecutor, as_completed from concurrent.futures import ThreadPoolExecutor, as_completed
from typing import AnyStr from typing import AnyStr
@@ -168,8 +169,18 @@ class StageDownloadDescriptions(Stage):
) )
""" """
src = "/home/planet/descriptions" # The src folder is hardcoded here and must be implemented on the map building machine
src = "/home/planet/wikipedia/descriptions"
# The dest folder will generally become build/*/intermediate_data/descriptions
dest = env.paths.descriptions_path dest = env.paths.descriptions_path
# An empty source folder is a big problem
try:
if os.path.isdir(src):
print("Found %s" % (src))
else:
raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), src)
except OSError as e:
print("rmtree error: %s - %s" % (e.filename, e.strerror))
# Empty folder "descriptions" can be already created. # Empty folder "descriptions" can be already created.
try: try:
if os.path.isdir(dest): if os.path.isdir(dest):

View File

@@ -9,6 +9,8 @@ from maps_generator.utils.file import download_file
def make_test_booking_data(max_days): def make_test_booking_data(max_days):
def test_booking_data(env: Env, logger, *args, **kwargs): def test_booking_data(env: Env, logger, *args, **kwargs):
if not settings.HOTELS_URL:
return None
base_url, _ = settings.HOTELS_URL.rsplit("/", maxsplit=1) base_url, _ = settings.HOTELS_URL.rsplit("/", maxsplit=1)
url = f"{base_url}/meta.json" url = f"{base_url}/meta.json"
meta_path = os.path.join(env.paths.tmp_dir(), "hotels-meta.json") meta_path = os.path.join(env.paths.tmp_dir(), "hotels-meta.json")

View File

@@ -0,0 +1,107 @@
[Developer]
# Path to the `comaps` source code repository:
OMIM_PATH: ~/comaps
# A path with the generator_tool binary:
BUILD_PATH: ~/omim-build-relwithdebinfo
[Main]
# A special small planet file will be downloaded if DEBUG is set to 1.
DEBUG: 0
# A main working directory. There is a subdirectory created for each generator run
# which contains the planet and other downloads, temporary build files, logs and completed MWMs.
MAIN_OUT_PATH: /mnt/4tbexternal/osm-maps
# Path for storing caches for nodes, ways, relations.
# If it's not set then caches are stored inside the directory of the current build.
# CACHE_PATH: ${Main:MAIN_OUT_PATH}/cache
[Generator tool]
# Path to the data/ folder in the repository:
USER_RESOURCE_PATH: ${Developer:OMIM_PATH}/data
# Features stage only parallelism level. Set to 0 for auto detection.
THREADS_COUNT_FEATURES_STAGE: 0
# Do not change it. This is determined automatically.
NODE_STORAGE: mem
[Osm tools]
# Path to osmctools binaries:
OSM_TOOLS_PATH: /usr/bin/
# If the binaries are not found neither in the configured path nor system-wide,
# then the tools are built from the sources:
OSM_TOOLS_SRC_PATH: ${Developer:OMIM_PATH}/tools/osmctools
[Logging]
# maps_generator's general (python output only) log file path and name.
# More detailed logs that include output of the `generator_tool` binary
# are located in the `logs/` subdir of a particular build directory,
# e.g. `maps_build/2023_06_04__20_05_07/logs/`.
LOG_FILE_PATH: ${Main:MAIN_OUT_PATH}/generation.log
[External]
# Planet file location. It should be a dump of OSM data in osm.pbf format.
# By default its an entire planet from "planet.openstreetmap.org".
# Or set it to a particular country/region extract from e.g. [Geofabrik](http://download.geofabrik.de/index.html).
# Note that an entire planet generation takes 40+ hours on a 256GB RAM server (and 1TB+ disk space).
# Stick to smaller extracts unless you have a machine this large.
# Here and further, its possible to specify either an URL (to be downloaded automatically)
# or a local file path like file:///path/to/file.
# A sample URL to download a latest OSM dump for North Macedonia:
PLANET_URL: file:///home/planet/planet/planet.o5m
# Location of the md5 checksum of the planet file:
PLANET_MD5_URL: ${External:PLANET_URL}.md5
# A base url to the latest_coasts.geom and latest_coasts.rawgeom files.
# For example, if PLANET_COASTS_URL = https://somesite.com/download/
# then the https://somesite.com/download/latest_coasts.geom url will be used to download latest_coasts.geom and
# the https://somesite.com/download/latest_coasts.rawgeom url will be used to download latest_coasts.rawgeom.
# Comment to skip getting the coastlines files.
PLANET_COASTS_URL: file:///home/planet/
# Should be 'true' for an entire planet build to make a special routing section in World.mwm
# for alerting about absent regions without which the route can't be built.
# NEED_BUILD_WORLD_ROADS: true
# Subway file location, see docs/SUBWAY_GENERATION.md if you want to generate your own file.
# Comment to disable subway layer generation.
SUBWAY_URL: file:///home/planet/subway/subways.transit.json
# Location of the EXPERIMENTAL GTFS-extracted public transport transit files:
# TRANSIT_URL:
# Urls for production maps generation.
# UGC_URL:
# HOTELS_URL:
# PROMO_CATALOG_CITIES:
# POPULARITY_URL:
# FOOD_URL:
# FOOD_TRANSLATIONS_URL:
SRTM_PATH: /home/planet/SRTM-patched-europe/
ISOLINES_PATH: /home/planet/isolines/
ADDRESSES_PATH: /home/planet/tiger/
# Local path (not url!) to .csv files.
UK_POSTCODES_URL: /home/planet/postcodes/gb-postcode-data/gb_postcodes.csv
US_POSTCODES_URL: /home/planet/postcodes/us-postcodes/uszips.csv
[Stages]
# Set to 1 to update the entire OSM planet file (as taken from "planet.openstreetmap.org")
# via an osmupdate tool before the generation. Not for use with partial planet extracts.
NEED_PLANET_UPDATE: 0
# If you want to calculate diffs you need to specify where the old maps are,
# e.g. ${Main:MAIN_OUT_PATH}/2021_03_16__09_00_00/
DATA_ARCHIVE_DIR: ${Generator tool:USER_RESOURCE_PATH}
# How many versions in the archive to use for diff calculation:
DIFF_VERSION_DEPTH: 2
[Common]
# Default parallelism level for the most of jobs. Set to 0 for auto detection.
THREADS_COUNT: 0
[Stats]
# Path to rules for calculating statistics by type:
STATS_TYPES_CONFIG: ${Developer:OMIM_PATH}/tools/python/maps_generator/var/etc/stats_types_config.txt

View File

@@ -22,14 +22,18 @@ function BuildDrawingRules() {
-o "$DATA_PATH/drules_proto$suffix" \ -o "$DATA_PATH/drules_proto$suffix" \
-p "$DATA_PATH/styles/$styleType/include/" -p "$DATA_PATH/styles/$styleType/include/"
# Output diff and store to a file # Output diff and store to a file
diff -u "$DATA_PATH"/drules_proto$suffix.txt{.prev,} | tee "$DATA_PATH"/drules_proto$suffix.txt.diff if [ -f "$DATA_PATH/drules_proto$suffix.txt.prev" ]; then
diff -u "$DATA_PATH/drules_proto$suffix.txt.prev" "$DATA_PATH/drules_proto$suffix.txt" | tee "$DATA_PATH/drules_proto$suffix.txt.diff" || true
fi
} }
outputs=(classificator.txt types.txt visibility.txt colors.txt patterns.txt drules_proto.txt) outputs=(classificator.txt types.txt visibility.txt colors.txt patterns.txt drules_proto.txt)
# Store old versions for diffs # Store old versions for diffs
for item in ${outputs[*]} for item in ${outputs[*]}
do do
mv $DATA_PATH/$item{,.prev} || true if [ -f "$DATA_PATH/$item" ]; then
mv -f "$DATA_PATH/$item" "$DATA_PATH/$item.prev"
fi
done done
# Building drawing rules # Building drawing rules
@@ -63,7 +67,11 @@ python3 "$OMIM_PATH/tools/python/stylesheet/drules_merge.py" \
# Output diffs and store to files # Output diffs and store to files
for item in ${outputs[*]} for item in ${outputs[*]}
do do
diff -u "$DATA_PATH"/$item{.prev,} | tee "$DATA_PATH"/$item.diff if [ -f "$DATA_PATH/$item.prev" ] && [ -f "$DATA_PATH/$item" ]; then
diff -u "$DATA_PATH/$item.prev" "$DATA_PATH/$item" | tee "$DATA_PATH/$item.diff" || true
else
echo "Skipping diff for $item (first run or file missing)"
fi
done done
echo "Diffs for all changes are stored in $DATA_PATH/*.txt.diff" echo "Diffs for all changes are stored in $DATA_PATH/*.txt.diff"

View File

@@ -0,0 +1,68 @@
# See run-docker.sh for cloning, building, and running the maps generator Docker routine
FROM debian:latest
ARG DEBIAN_FRONTEND=noninteractive
ENV TZ=Etc/UTC
RUN apt-get update -qq \
&& apt-get install -y --no-install-recommends \
build-essential \
ca-certificates \
cargo \
clang \
cmake \
curl \
git \
jq \
libc++-dev \
libfreetype-dev \
libgeos-dev \
libgl1-mesa-dev \
libglvnd-dev \
libharfbuzz-dev \
libicu-dev \
libqt6positioning6 \
libqt6positioning6-plugins \
libqt6svg6-dev \
libsqlite3-dev \
libxcursor-dev \
libxi-dev \
libxinerama-dev \
libxrandr-dev \
ninja-build \
nodejs \
openssh-client \
osmctools \
osmium-tool \
pyosmium \
python3 \
python3-pip \
python3-venv \
python-is-python3 \
python3-dev \
qt6-base-dev \
qt6-positioning-dev \
rclone \
rustc \
sshpass \
vim-tiny \
wget \
wget2 \
zlib1g-dev \
&& rm -rf /var/cache/apt/* /var/lib/apt/lists/*;
# Allow pip to install system-wide in the container
RUN pip3 install "protobuf<4" --break-system-packages
# Mount a volume to store the large input, output, and temp files here
RUN mkdir /mnt/4tbexternal
# And a volume to store >10gb files for the planet output here
RUN mkdir /home/planet
WORKDIR ~
# The actual map generation process will run something like this,
# but ~/comaps isn't mounted nor provided in the docker image.
#CMD ~/comaps/tools/unix/maps/docker_maps_generator.sh
CMD /bin/bash

View File

@@ -0,0 +1,56 @@
#!/usr/bin/env bash
set -e
echo "<$(date +%T)> Starting..."
# Prepare paths
# Most other paths in /mnt/4tbexternal or /home/planet are already created by Dockerfile or CI/CD.
#
mkdir -p /root/.config/CoMaps # Odd mkdir permission errors in generator_tool in Docker without these
chmod -R 777 /root/.config
mkdir -p /home/planet/postcodes/gb-postcode-data/
mkdir -p /home/planet/postcodes/us-postcodes/
mkdir -p /home/planet/SRTM-patched-europe/
mkdir -p /home/planet/subway
echo "<$(date +%T)> Running ./configure.sh ..."
cd ~/comaps
export SKIP_MAP_DOWNLOAD=1 SKIP_GENERATE_SYMBOLS=1
./configure.sh
echo "<$(date +%T)> Compiling tools..."
cd ~/comaps
./tools/unix/build_omim.sh -p ~ -R generator_tool
./tools/unix/build_omim.sh -p ~ -R world_roads_builder_tool
./tools/unix/build_omim.sh -p ~ -R mwm_diff_tool
cd tools/python/maps_generator
python3 -m venv /tmp/venv
/tmp/venv/bin/pip3 install -r requirements_dev.txt
echo "<$(date +%T)> Copying map generator INI..."
cp var/etc/map_generator.ini.prod var/etc/map_generator.ini
cd ~/comaps/tools/python
if [ $MWMCONTINUE -gt 0 ]; then
echo "<$(date +%T)> Continuing from preexisting generator run..."
/tmp/venv/bin/python -m maps_generator --skip="MwmDiffs" --continue
else
if [[ -n $MWMCOUNTRIES ]]; then
echo "<$(date +%T)> Generating only specific maps [$MWMCOUNTRIES]..."
/tmp/venv/bin/python -m maps_generator --countries=$MWMCOUNTRIES --skip="MwmDiffs"
else
echo "<$(date +%T)> Generating maps..."
/tmp/venv/bin/python -m maps_generator --skip="MwmDiffs"
fi
fi
echo "<$(date +%T)> DONE"

View File

@@ -20,9 +20,9 @@ export SKIP_PLANET_UPDATE="1"
# If unavailable then replace with a local file. # If unavailable then replace with a local file.
# TODO: keep the downloaded csv file from the latest run. # TODO: keep the downloaded csv file from the latest run.
#export CITIES_INFO_URL="" #export CITIES_INFO_URL=""
export TMPDIR="$BUILD_PATH/subways" export TMPDIR="$BUILD_PATH/subway"
# The output file, which needs post-processing by transit_graph_generator.py # The output file, which needs post-processing by transit_graph_generator.py
export MAPSME="$SUBWAYS_PATH/subways.json" export MAPSME="$SUBWAYS_PATH/subway.json"
# Produce additional files needed for https://cdn.organicmaps.app/subway/ # Produce additional files needed for https://cdn.organicmaps.app/subway/
export HTML_DIR="$SUBWAYS_VALIDATOR_PATH" export HTML_DIR="$SUBWAYS_VALIDATOR_PATH"
@@ -30,7 +30,12 @@ export DUMP="$SUBWAYS_VALIDATOR_PATH"
export GEOJSON="$SUBWAYS_VALIDATOR_PATH" export GEOJSON="$SUBWAYS_VALIDATOR_PATH"
export DUMP_CITY_LIST="$SUBWAYS_VALIDATOR_PATH/cities.txt" export DUMP_CITY_LIST="$SUBWAYS_VALIDATOR_PATH/cities.txt"
"$SUBWAYS_REPO_PATH/scripts/process_subways.sh" 2>&1 | tee "$SUBWAYS_LOG" # cd to subways repo so relative paths work in the script
PREVDIR=$(pwd)
cd "$SUBWAYS_REPO_PATH"
echo "Running process_subways.sh:"
./scripts/process_subways.sh 2>&1 | tee "$SUBWAYS_LOG"
cd "$PREVDIR"
# Make render.html available for map visualization on the web # Make render.html available for map visualization on the web
cp -r "$SUBWAYS_REPO_PATH"/render/* "$SUBWAYS_VALIDATOR_PATH/" cp -r "$SUBWAYS_REPO_PATH"/render/* "$SUBWAYS_VALIDATOR_PATH/"

View File

@@ -0,0 +1,34 @@
#!/usr/bin/env bash
# Run the maps generator via Docker manually without CI
# See .forgejo/workflows/map-generator.yml for steps to run before the main mapgen process,
# e.g. clone the repos, get/update planet file, generate isolines etc.
# To build the docker container:
# cd /mnt/4tbexternal/comaps/tools/unix/maps
# docker build . -t maps_generator
#
# To push for ci/cd, tag for codeberg:
# docker login codeberg.org
# docker tag maps_generator codeberg.org/comaps/maps_generator:latest
# docker push codeberg.org/comaps/maps_generator:latest
# You can also tag and push the image Id for posterity: codeberg.org/comaps/maps_generator:1234abcd
# If you get a Dockerfile not found error especially on an XFS partition, try copying Dockerfile to an ext4 partition first.
# Or use docker via apt instead of snap.
# We assume that the following will be cloned into the container itself at runtime:
# ~/comaps (comaps main app repo)
# ~/subways (repo for processing OSM subway/transit info)
# ~/wikiparser (repo for processing Wikipedia data)
# We also assume a number of files/folders/repos are pre-set-up before mounting via volumes below:
# /mnt/4tbexternal (base folder for directory traversal)
# /mnt/4tbexternal/osm-maps (folder for holding generated map data output)
# /home/planet (folder for holding required input dumps)
docker run \
--ulimit nofile=262144:262144 \
-v /mnt/4tbexternal/:/mnt/4tbexternal/ \
-v /mnt/4tbexternal/osm-planet:/home/planet \
-it codeberg.org/comaps/maps_generator:latest \
~/comaps/tools/unix/maps/docker_maps_generator.sh

View File

@@ -0,0 +1,26 @@
## NOTE: edit the settings.sh file to customize/override the defaults.
# Absolutize & normalize paths.
REPO_PATH="${REPO_PATH:-$(cd "$(dirname "$0")/../../.."; pwd -P)}"
#TODO: is base path used?
BASE_PATH="${BASE_PATH:-$REPO_PATH/..}"
# Source map data and processed outputs e.g. wiki articles
DATA_PATH="${DATA_PATH:-/home/planet}"
# Temporary files
BUILD_PATH="${BUILD_PATH:-$DATA_PATH/build}"
# Other code repositories, e.g. subways, wikiparser..
CODE_PATH="${CODE_PATH:-~}"
# OSM planet source files
PLANET_PATH="${PLANET_PATH:-$DATA_PATH/planet}"
PLANET_PBF="${PLANET_PBF:-$PLANET_PATH/planet-latest.osm.pbf}"
PLANET_O5M="${PLANET_O5M:-$PLANET_PATH/planet-latest.o5m}"
# Subways
SUBWAYS_REPO_PATH="${SUBWAYS_REPO_PATH:-/root/subways}"
SUBWAYS_PATH="${SUBWAYS_PATH:-$DATA_PATH/subway}"
SUBWAYS_LOG="${SUBWAYS_LOG:-$SUBWAYS_PATH/subway.log}"
SUBWAYS_VALIDATOR_PATH="${SUBWAYS_VALIDATOR_PATH:-$SUBWAYS_PATH/validator}"

View File

@@ -20,6 +20,6 @@ PLANET_O5M="${PLANET_O5M:-$PLANET_PATH/planet-latest.o5m}"
# Subways # Subways
SUBWAYS_REPO_PATH="${SUBWAYS_REPO_PATH:-$CODE_PATH/subways}" SUBWAYS_REPO_PATH="${SUBWAYS_REPO_PATH:-$CODE_PATH/subways}"
SUBWAYS_PATH="${SUBWAYS_PATH:-$DATA_PATH/subways}" SUBWAYS_PATH="${SUBWAYS_PATH:-$DATA_PATH/subway}"
SUBWAYS_LOG="${SUBWAYS_LOG:-$SUBWAYS_PATH/subways.log}" SUBWAYS_LOG="${SUBWAYS_LOG:-$SUBWAYS_PATH/subway.log}"
SUBWAYS_VALIDATOR_PATH="${SUBWAYS_VALIDATOR_PATH:-$SUBWAYS_PATH/validator}" SUBWAYS_VALIDATOR_PATH="${SUBWAYS_VALIDATOR_PATH:-$SUBWAYS_PATH/validator}"

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Upload new maps version to all CDN nodes (in parallel). # Upload new maps version to all CDN nodes (in parallel) and remove old versions.
# Use following commands for deleting older maps: # Use following commands for deleting older maps:
# #
@@ -8,15 +8,15 @@
# First list all maps versions on the server # First list all maps versions on the server
# sudo rclone lsd ru1:comaps-maps/maps # sudo rclone lsd ru1:comaps-maps/maps
# Delete the old version # Delete the old version
# sudo rclone purge -v ru1:comaps-maps/maps/250713 # sudo rclone purge -v ru1:comaps-maps/maps/250713/
# #
# fi1 - max 3 versions # fi1 - max 3 versions
# sudo rclone lsd fi1:/var/www/html/maps # sudo rclone lsd fi1:/var/www/html/maps
# sudo rclone purge -v fi1:/var/www/html/maps/250713 # sudo rclone purge -v fi1:/var/www/html/maps/250713/
# #
# de1 - max 6 versions # de1 - max 6 versions
# sudo rclone lsd de1:/var/www/html/comaps-cdn/maps # sudo rclone lsd de1:/var/www/html/comaps-cdn/maps
# sudo rclone purge -v de1:/var/www/html/comaps-cdn/maps/250713 # sudo rclone purge -v de1:/var/www/html/comaps-cdn/maps/250713/
# #
# us2 - all versions, don't delete # us2 - all versions, don't delete
# sudo rclone lsd us2:comaps-map-files/maps # sudo rclone lsd us2:comaps-map-files/maps
@@ -39,6 +39,54 @@ DIR=$(dirname $1)/$MAPS
echo "Uploading maps folder $DIR to $MAPS" echo "Uploading maps folder $DIR to $MAPS"
# Remove old versions before uploading new ones
echo "Checking for old versions to remove..."
# ru1 - keep max 3 versions
echo "Cleaning ru1 (keeping 3 newest versions)..."
OLD_VERSIONS_RU1=$(rclone lsd ru1:comaps-maps/maps --max-depth 1 | awk '{print $5}' | sort -r | tail -n +4)
for version in $OLD_VERSIONS_RU1; do
if [ $version -gt 250101 ]; then
echo " Deleting ru1:comaps-maps/maps/$version/"
rclone purge -v ru1:comaps-maps/maps/$version/
fi
done
# fi1 - keep max 3 versions
echo "Cleaning fi1 (keeping 3 newest versions)..."
OLD_VERSIONS_FI1=$(rclone lsd fi1:/var/www/html/maps --max-depth 1 | awk '{print $5}' | sort -r | tail -n +4)
for version in $OLD_VERSIONS_FI1; do
if [ $version -gt 250101 ]; then
echo " Deleting fi1:/var/www/html/maps/$version/"
rclone purge -v fi1:/var/www/html/maps/$version/
fi
done
# de1 - keep max 6 versions
echo "Cleaning de1 (keeping 6 newest versions)..."
OLD_VERSIONS_DE1=$(rclone lsd de1:/var/www/html/comaps-cdn/maps --max-depth 1 | awk '{print $5}' | sort -r | tail -n +7)
for version in $OLD_VERSIONS_DE1; do
if [ $version -gt 250101 ]; then
echo " Deleting de1:/var/www/html/comaps-cdn/maps/$version/"
rclone purge -v de1:/var/www/html/comaps-cdn/maps/$version/
fi
done
# fr1 - keep max 6 versions
echo "Cleaning fr1 (keeping 6 newest versions)..."
OLD_VERSIONS_FR1=$(rclone lsd fr1:/data/maps --max-depth 1 | awk '{print $5}' | sort -r | tail -n +7)
for version in $OLD_VERSIONS_FR1; do
if [ $version -gt 250101 ]; then
echo " Deleting fr1:/data/maps/$version/"
rclone purge -v fr1:/data/maps/$version/
fi
done
# us2 - keep all versions (no cleanup)
echo "Skipping us2 cleanup (keeping all versions)"
echo "Old version cleanup complete"
echo "Uploading to us2" echo "Uploading to us2"
# An explicit mwm/txt filter is used to skip temp files when run for an unfinished generation # An explicit mwm/txt filter is used to skip temp files when run for an unfinished generation
rclone copy -v --include "*.{mwm,txt}" $DIR us2:comaps-map-files/maps/$MAPS & rclone copy -v --include "*.{mwm,txt}" $DIR us2:comaps-map-files/maps/$MAPS &
@@ -52,9 +100,29 @@ rclone copy -v --include "*.{mwm,txt}" $DIR fi1:/var/www/html/maps/$MAPS &
echo "Uploading to de1" echo "Uploading to de1"
rclone copy -v --include "*.{mwm,txt}" $DIR de1:/var/www/html/comaps-cdn/maps/$MAPS & rclone copy -v --include "*.{mwm,txt}" $DIR de1:/var/www/html/comaps-cdn/maps/$MAPS &
echo "Uploading to fr1"
rclone copy -v --include "*.{mwm,txt}" $DIR fr1:/data/maps/$MAPS &
# us1 is not used for maps atm # us1 is not used for maps atm
# rclone lsd us1:/home/dh_zzxxrk/cdn-us-1.comaps.app/maps # rclone lsd us1:/home/dh_zzxxrk/cdn-us-1.comaps.app/maps
wait wait
echo "Running once more without parallelization to output status:"
echo "us2 status:"
rclone copy -v --include "*.{mwm,txt}" $DIR us2:comaps-map-files/maps/$MAPS
echo "ru1 status:"
rclone copy -v --include "*.{mwm,txt}" $DIR ru1:comaps-maps/maps/$MAPS
echo "fi1 status:"
rclone copy -v --include "*.{mwm,txt}" $DIR fi1:/var/www/html/maps/$MAPS
echo "de1 status:"
rclone copy -v --include "*.{mwm,txt}" $DIR de1:/var/www/html/comaps-cdn/maps/$MAPS
echo "fr1 status:"
rclone copy -v --include "*.{mwm,txt}" $DIR fr1:/data/maps/$MAPS
echo "Upload complete" echo "Upload complete"