Compare commits
4 Commits
main
...
backend/mi
Author | SHA1 | Date | |
---|---|---|---|
54bc9028ad | |||
37926e68ec | |||
e2d3d29956 | |||
6921ab57f8 |
67
.gitea/workflows/frontend_build-android.yaml
Normal file
@ -0,0 +1,67 @@
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- frontend/**
|
||||
|
||||
|
||||
name: Build and release debug APK
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build APK
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- name: Install prerequisites
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get install -y jq
|
||||
|
||||
- uses: https://gitea.com/actions/checkout@v4
|
||||
|
||||
|
||||
- uses: https://github.com/actions/setup-java@v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'zulu'
|
||||
|
||||
- name: Fix flutter SDK folder permission
|
||||
run: git config --global --add safe.directory "*"
|
||||
|
||||
- uses: https://github.com/subosito/flutter-action@v2
|
||||
with:
|
||||
channel: stable
|
||||
flutter-version: 3.22.0
|
||||
cache: true
|
||||
|
||||
- name: Setup Android SDK
|
||||
uses: https://github.com/android-actions/setup-android@v3
|
||||
|
||||
- run: flutter pub get
|
||||
working-directory: ./frontend
|
||||
|
||||
- name: Add required secrets
|
||||
env:
|
||||
ANDROID_SECRETS_PROPERTIES: ${{ secrets.ANDROID_SECRETS_PROPERTIES }}
|
||||
run: |
|
||||
echo "$ANDROID_SECRETS_PROPERTIES" >> ./android/secrets.properties
|
||||
working-directory: ./frontend
|
||||
|
||||
- name: Sanity check
|
||||
run: |
|
||||
ls
|
||||
ls -lah android
|
||||
working-directory: ./frontend
|
||||
|
||||
- run: flutter build apk --debug --split-per-abi --build-number=${{ gitea.run_number }}
|
||||
working-directory: ./frontend
|
||||
|
||||
- name: Upload APKs to artifacts
|
||||
uses: https://gitea.com/actions/upload-artifact@v3
|
||||
with:
|
||||
name: app-release
|
||||
path: frontend/build/app/outputs/flutter-apk/
|
||||
if-no-files-found: error
|
||||
retention-days: 15
|
34
.gitea/workflows/frontend_build-web.yaml
Normal file
@ -0,0 +1,34 @@
|
||||
# on:
|
||||
# pull_request:
|
||||
# branches:
|
||||
# - main
|
||||
# paths:
|
||||
# - frontend/**
|
||||
|
||||
|
||||
# name: Build web
|
||||
|
||||
# jobs:
|
||||
# build:
|
||||
# name: Build Web
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
|
||||
# - name: Install prerequisites
|
||||
# run: |
|
||||
# sudo apt-get update
|
||||
# sudo apt-get install -y xz-utils
|
||||
|
||||
# - uses: actions/checkout@v4
|
||||
|
||||
# - uses: https://github.com/subosito/flutter-action@v2
|
||||
# with:
|
||||
# channel: stable
|
||||
# flutter-version: 3.19.6
|
||||
# cache: true
|
||||
|
||||
# - run: flutter pub get
|
||||
# working-directory: ./frontend
|
||||
|
||||
# - run: flutter build web
|
||||
# working-directory: ./frontend
|
@ -1,59 +0,0 @@
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- frontend/**
|
||||
|
||||
name: Build and release apps to beta track
|
||||
|
||||
jobs:
|
||||
get-version:
|
||||
name: Get version
|
||||
runs-on: macos
|
||||
steps:
|
||||
- uses: https://gitea.com/actions/checkout@v4
|
||||
|
||||
- name: Fetch tags from main branch
|
||||
# since this workflow is triggered by a pull request, we want to match the latest tag of the main branch
|
||||
id: version
|
||||
run: |
|
||||
git fetch origin main --tags
|
||||
LATEST_TAG=$(git describe --tags $(git rev-list --tags --max-count=1))
|
||||
# remove the 'v' prefix from the tag name
|
||||
echo "BUILD_NAME=${LATEST_TAG//v}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Output the version that is being used
|
||||
run: |
|
||||
echo "Building for version ${{ steps.version.outputs.BUILD_NAME }}"
|
||||
|
||||
outputs:
|
||||
build_name: ${{ steps.version.outputs.BUILD_NAME }}
|
||||
|
||||
build-android:
|
||||
name: Build and upload android app
|
||||
uses: ./.gitea/workflows/workflow_build-app-android.yaml
|
||||
with:
|
||||
build_type: beta
|
||||
build_name: ${{ needs.get-version.outputs.build_name }}
|
||||
secrets:
|
||||
ANDROID_SECRET_PROPERTIES_BASE64: ${{ secrets.ANDROID_SECRET_PROPERTIES_BASE64 }}
|
||||
ANDROID_GOOGLE_PLAY_JSON_BASE64: ${{ secrets.ANDROID_GOOGLE_PLAY_JSON_BASE64 }}
|
||||
ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
|
||||
ANDROID_GOOGLE_MAPS_API_KEY: ${{ secrets.ANDROID_GOOGLE_MAPS_API_KEY }}
|
||||
needs: get-version
|
||||
|
||||
build-ios:
|
||||
name: Build and upload ios app
|
||||
uses: ./.gitea/workflows/workflow_build-app-ios.yaml
|
||||
with:
|
||||
build_type: beta
|
||||
build_name: ${{ needs.get-version.outputs.build_name }}
|
||||
secrets:
|
||||
IOS_ASC_KEY_ID: ${{ secrets.IOS_ASC_KEY_ID }}
|
||||
IOS_ASC_ISSUER_ID: ${{ secrets.IOS_ASC_ISSUER_ID }}
|
||||
IOS_ASC_KEY: ${{ secrets.IOS_ASC_KEY }}
|
||||
IOS_MATCH_REPO_SSH_KEY_BASE64: ${{ secrets.IOS_MATCH_REPO_SSH_KEY_BASE64 }}
|
||||
IOS_MATCH_PASSWORD: ${{ secrets.IOS_MATCH_PASSWORD }}
|
||||
IOS_GOOGLE_MAPS_API_KEY: ${{ secrets.IOS_GOOGLE_MAPS_API_KEY }}
|
||||
needs: build-android # technically not needed, but this prevents the builds from running in parallel
|
@ -1,56 +0,0 @@
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- v*
|
||||
|
||||
name: Build and release apps to production track
|
||||
|
||||
jobs:
|
||||
get-version:
|
||||
name: Get version
|
||||
runs-on: macos
|
||||
steps:
|
||||
- uses: https://gitea.com/actions/checkout@v4
|
||||
|
||||
- name: Get version from git tag
|
||||
id: version
|
||||
env:
|
||||
REF_NAME: ${{ gitea.ref_name }}
|
||||
# remove the 'v' prefix from the tag name
|
||||
run: |
|
||||
echo "BUILD_NAME=${REF_NAME//v}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Output the version that is being used
|
||||
run: |
|
||||
echo "Building for version ${{ steps.version.outputs.BUILD_NAME }}"
|
||||
|
||||
outputs:
|
||||
build_name: ${{ steps.version.outputs.BUILD_NAME }}
|
||||
|
||||
build-android:
|
||||
name: Build and upload android app
|
||||
uses: ./.gitea/workflows/workflow_build-app-android.yaml
|
||||
with:
|
||||
build_type: release
|
||||
build_name: ${{ needs.get-version.outputs.build_name }}
|
||||
secrets:
|
||||
ANDROID_SECRET_PROPERTIES_BASE64: ${{ secrets.ANDROID_SECRET_PROPERTIES_BASE64 }}
|
||||
ANDROID_GOOGLE_PLAY_JSON_BASE64: ${{ secrets.ANDROID_GOOGLE_PLAY_JSON_BASE64 }}
|
||||
ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
|
||||
ANDROID_GOOGLE_MAPS_API_KEY: ${{ secrets.ANDROID_GOOGLE_MAPS_API_KEY }}
|
||||
needs: get-version
|
||||
|
||||
build-ios:
|
||||
name: Build and upload ios app
|
||||
uses: ./.gitea/workflows/workflow_build-app-ios.yaml
|
||||
with:
|
||||
build_type: release
|
||||
build_name: ${{ needs.get-version.outputs.build_name }}
|
||||
secrets:
|
||||
IOS_ASC_KEY_ID: ${{ secrets.IOS_ASC_KEY_ID }}
|
||||
IOS_ASC_ISSUER_ID: ${{ secrets.IOS_ASC_ISSUER_ID }}
|
||||
IOS_ASC_KEY: ${{ secrets.IOS_ASC_KEY }}
|
||||
IOS_MATCH_REPO_SSH_KEY_BASE64: ${{ secrets.IOS_MATCH_REPO_SSH_KEY_BASE64 }}
|
||||
IOS_MATCH_PASSWORD: ${{ secrets.IOS_MATCH_PASSWORD }}
|
||||
IOS_GOOGLE_MAPS_API_KEY: ${{ secrets.IOS_GOOGLE_MAPS_API_KEY }}
|
||||
needs: build-android # technically not needed, but this prevents the builds from running in parallel
|
39
.gitea/workflows/frontend_trigger_deployment.yaml
Normal file
@ -0,0 +1,39 @@
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- v*
|
||||
|
||||
jobs:
|
||||
push-to-remote:
|
||||
# We want to use the macos runner provided by github actions. This requires to push to a remote first.
|
||||
# After the push we can use the action under frontend/.github/actions/ to deploy properly using fastlane on macos.
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: 'src'
|
||||
|
||||
- name: Checkout remote repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: 'dest'
|
||||
ref: 'main'
|
||||
github-server-url: 'https://github.com'
|
||||
repository: 'moll-re/anyway-frontend-builder'
|
||||
token: ${{ secrets.PUSH_GITHUB_API_TOKEN }}
|
||||
fetch-depth: 0
|
||||
persist-credentials: true
|
||||
|
||||
- name: Copy files to remote repository
|
||||
run: cp -r src/frontend/. dest/
|
||||
|
||||
- name: Commit and push changes
|
||||
run: |
|
||||
cd dest
|
||||
git config --global user.email "me@moll.re"
|
||||
git config --global user.name "[bot]"
|
||||
git add .
|
||||
git commit -m "Automatic code update for tag"
|
||||
git tag -a ${{ github.ref_name }} -m "mirrored tag"
|
||||
git push origin main --tags
|
@ -1,78 +0,0 @@
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
build_type:
|
||||
description: 'Release type (release, beta)'
|
||||
required: true
|
||||
type: string
|
||||
build_name:
|
||||
description: 'Build name'
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
ANDROID_SECRET_PROPERTIES_BASE64:
|
||||
required: true
|
||||
ANDROID_GOOGLE_PLAY_JSON_BASE64:
|
||||
required: true
|
||||
ANDROID_KEYSTORE_BASE64:
|
||||
required: true
|
||||
ANDROID_GOOGLE_MAPS_API_KEY:
|
||||
required: true
|
||||
|
||||
name: Build and release android appbundle to specfied track
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontend/android
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macos-14
|
||||
env:
|
||||
# $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps
|
||||
BUNDLE_GEMFILE: ${{ gitea.workspace }}/frontend/android/Gemfile
|
||||
|
||||
steps:
|
||||
- uses: https://gitea.com/actions/checkout@v4
|
||||
|
||||
- uses: https://github.com/actions/setup-java@v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'zulu'
|
||||
|
||||
- name: Setup Android SDK
|
||||
uses: https://github.com/android-actions/setup-android@v3
|
||||
|
||||
- name: Fix flutter SDK folder permission
|
||||
run: git config --global --add safe.directory "*"
|
||||
|
||||
- uses: https://github.com/subosito/flutter-action@v2
|
||||
with:
|
||||
channel: stable
|
||||
flutter-version-file: ${{ gitea.workspace }}/frontend/pubspec.yaml
|
||||
architecture: x64
|
||||
cache: true
|
||||
|
||||
- name: Install dependencies and clean up
|
||||
run: |
|
||||
flutter pub get
|
||||
flutter clean
|
||||
|
||||
- name: Set up ruby env and install fastlane
|
||||
uses: https://github.com/ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: 3.3
|
||||
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
||||
|
||||
- name: Add required secret files
|
||||
run: |
|
||||
echo "${{ secrets.ANDROID_SECRET_PROPERTIES_BASE64 }}" | base64 -d > secrets.properties
|
||||
echo "${{ secrets.ANDROID_GOOGLE_PLAY_JSON_BASE64 }}" | base64 -d > google-key.json
|
||||
echo "${{ secrets.ANDROID_KEYSTORE_BASE64 }}" | base64 -d > release.keystore
|
||||
|
||||
- name: Run fastlane lane
|
||||
run: bundle exec fastlane deploy_${{ inputs.build_type }}
|
||||
env:
|
||||
BUILD_NUMBER: ${{ gitea.run_number }}
|
||||
BUILD_NAME: ${{ inputs.build_name }}
|
||||
ANDROID_GOOGLE_MAPS_API_KEY: ${{ secrets.ANDROID_GOOGLE_MAPS_API_KEY }}
|
@ -1,90 +0,0 @@
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
build_type:
|
||||
description: 'Release type (release, beta)'
|
||||
required: true
|
||||
type: string
|
||||
build_name:
|
||||
description: 'Build name'
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
IOS_ASC_KEY_ID:
|
||||
required: true
|
||||
IOS_ASC_ISSUER_ID:
|
||||
required: true
|
||||
IOS_ASC_KEY:
|
||||
required: true
|
||||
IOS_MATCH_REPO_SSH_KEY_BASE64:
|
||||
required: true
|
||||
IOS_MATCH_PASSWORD:
|
||||
required: true
|
||||
IOS_GOOGLE_MAPS_API_KEY:
|
||||
required: true
|
||||
|
||||
name: Build and release ipa to specified track
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontend/ios
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macos-14
|
||||
env:
|
||||
# $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps
|
||||
BUNDLE_GEMFILE: ${{ gitea.workspace }}/frontend/ios/Gemfile
|
||||
|
||||
steps:
|
||||
- uses: https://gitea.com/actions/checkout@v4
|
||||
|
||||
- name: Install Flutter
|
||||
uses: https://github.com/subosito/flutter-action@v2
|
||||
with:
|
||||
channel: stable
|
||||
flutter-version-file: ${{ gitea.workspace }}/frontend/pubspec.yaml
|
||||
architecture: x64
|
||||
cache: true
|
||||
|
||||
- name: Set up ruby env
|
||||
uses: https://github.com/ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: 3.3
|
||||
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
||||
|
||||
- uses: GuillaumeFalourd/setup-rsync@v1.2
|
||||
# rsync is required by the google maps ios tools
|
||||
|
||||
- name: Install dependencies and clean up
|
||||
run: |
|
||||
flutter pub get
|
||||
flutter precache --ios
|
||||
bundle exec pod install --allow-root
|
||||
flutter clean
|
||||
bundle exec pod cache clean --all --allow-root
|
||||
|
||||
- name: Setup SSH key for match git repo
|
||||
# and mark the host as known
|
||||
run: |
|
||||
echo $MATCH_REPO_SSH_KEY | base64 --decode > ~/.ssh/id_rsa
|
||||
chmod 600 ~/.ssh/id_rsa
|
||||
ssh-keyscan -p 2222 git.kluster.moll.re > ~/.ssh/known_hosts
|
||||
env:
|
||||
MATCH_REPO_SSH_KEY: ${{ secrets.IOS_MATCH_REPO_SSH_KEY_BASE64 }}
|
||||
|
||||
- name: Replace API Key from secret
|
||||
# on a macOS runner, sed requires a replacement suffix after the -i flag
|
||||
run: |
|
||||
sed -i '' -e "s/IOS_GOOGLE_MAPS_API_KEY/${{ secrets.IOS_GOOGLE_MAPS_API_KEY }}/g" Runner/AppDelegate.swift
|
||||
|
||||
- name: Run fastlane lane
|
||||
run: bundle exec fastlane deploy_${{ inputs.build_type }}
|
||||
env:
|
||||
BUILD_NUMBER: ${{ gitea.run_number }}
|
||||
BUILD_NAME: ${{ inputs.build_name }}
|
||||
IOS_ASC_KEY_ID: ${{ secrets.IOS_ASC_KEY_ID }}
|
||||
IOS_ASC_ISSUER_ID: ${{ secrets.IOS_ASC_ISSUER_ID }}
|
||||
IOS_ASC_KEY: ${{ secrets.IOS_ASC_KEY }}
|
||||
MATCH_PASSWORD: ${{ secrets.IOS_MATCH_PASSWORD }}
|
||||
IOS_GOOGLE_MAPS_API_KEY: ${{ secrets.IOS_GOOGLE_MAPS_API_KEY }}
|
5
.vscode/launch.json
vendored
@ -36,10 +36,7 @@
|
||||
"type": "dart",
|
||||
"request": "launch",
|
||||
"program": "lib/main.dart",
|
||||
"cwd": "${workspaceFolder}/frontend",
|
||||
"env": {
|
||||
"GOOGLE_MAPS_API_KEY": "testing"
|
||||
}
|
||||
"cwd": "${workspaceFolder}/frontend"
|
||||
},
|
||||
{
|
||||
"name": "Frontend - profile",
|
||||
|
3
backend/.gitignore
vendored
@ -12,6 +12,9 @@ __pycache__/
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Pytest reports
|
||||
report.html
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
|
@ -146,7 +146,7 @@ class ClusterManager:
|
||||
self.valid = False
|
||||
|
||||
else :
|
||||
self.logger.debug(f"Detected 0 {cluster_type} clusters.")
|
||||
self.logger.debug(f"Found 0 {cluster_type} clusters.")
|
||||
self.valid = False
|
||||
|
||||
|
||||
|
@ -55,7 +55,12 @@ class LandmarkManager:
|
||||
self.logger.info('LandmakManager successfully initialized.')
|
||||
|
||||
|
||||
def generate_landmarks_list(self, center_coordinates: tuple[float, float], preferences: Preferences) -> tuple[list[Landmark], list[Landmark]]:
|
||||
def generate_landmarks_list(
|
||||
self,
|
||||
center_coordinates: tuple[float, float],
|
||||
preferences: Preferences,
|
||||
allow_clusters: bool = True
|
||||
) -> tuple[list[Landmark], list[Landmark]]:
|
||||
"""
|
||||
Generate and prioritize a list of landmarks based on user preferences.
|
||||
|
||||
@ -63,16 +68,17 @@ class LandmarkManager:
|
||||
and current location. It scores and corrects these landmarks, removes duplicates, and then selects the most important
|
||||
landmarks based on a predefined criterion.
|
||||
|
||||
Args:
|
||||
Parameters :
|
||||
center_coordinates (tuple[float, float]): The latitude and longitude of the center location around which to search.
|
||||
preferences (Preferences): The user's preference settings that influence the landmark selection.
|
||||
allow_clusters (bool, optional) : If set to False, no clusters will be fetched. Mainly used for the option to fetch landmarks nearby.
|
||||
|
||||
Returns:
|
||||
tuple[list[Landmark], list[Landmark]]:
|
||||
- A list of all existing landmarks.
|
||||
- A list of the most important landmarks based on the user's preferences.
|
||||
"""
|
||||
self.logger.debug('Starting to fetch landmarks...')
|
||||
self.logger.info(f'Starting to fetch landmarks around {center_coordinates}...')
|
||||
max_walk_dist = int((preferences.max_time_minute/2)/60*self.walking_speed*1000/self.detour_factor)
|
||||
radius = min(max_walk_dist, int(self.max_bbox_side/2))
|
||||
|
||||
@ -89,6 +95,7 @@ class LandmarkManager:
|
||||
all_landmarks.update(current_landmarks)
|
||||
self.logger.info(f'Found {len(current_landmarks)} sightseeing landmarks')
|
||||
|
||||
if allow_clusters :
|
||||
# special pipeline for historic neighborhoods
|
||||
neighborhood_manager = ClusterManager(bbox, 'sightseeing')
|
||||
historic_clusters = neighborhood_manager.generate_clusters()
|
||||
@ -113,6 +120,7 @@ class LandmarkManager:
|
||||
landmark.duration = 30
|
||||
all_landmarks.update(current_landmarks)
|
||||
|
||||
if allow_clusters :
|
||||
# special pipeline for shopping malls
|
||||
shopping_manager = ClusterManager(bbox, 'shopping')
|
||||
shopping_clusters = shopping_manager.generate_clusters()
|
||||
@ -120,7 +128,10 @@ class LandmarkManager:
|
||||
|
||||
|
||||
landmarks_constrained = take_most_important(all_landmarks, self.n_important)
|
||||
|
||||
# DETAILS HERE
|
||||
# self.logger.info(f'All landmarks generated : {len(all_landmarks)} landmarks around {center_coordinates}, and constrained to {len(landmarks_constrained)} most important ones.')
|
||||
self.logger.info(f'Found {len(all_landmarks)} landmarks in total.')
|
||||
|
||||
return all_landmarks, landmarks_constrained
|
||||
|
||||
@ -236,6 +247,17 @@ class LandmarkManager:
|
||||
continue
|
||||
|
||||
tags = elem.get('tags')
|
||||
n_tags=len(tags)
|
||||
|
||||
# Skip this landmark if not suitable
|
||||
if tags.get('building:part') is not None :
|
||||
continue
|
||||
if tags.get('disused') is not None :
|
||||
continue
|
||||
if tags.get('boundary') is not None :
|
||||
continue
|
||||
if tags.get('shop') is not None and landmarktype != 'shopping' :
|
||||
continue
|
||||
|
||||
# Convert this to Landmark object
|
||||
landmark = Landmark(name=name,
|
||||
@ -244,180 +266,36 @@ class LandmarkManager:
|
||||
osm_id=id,
|
||||
osm_type=osm_type,
|
||||
attractiveness=0,
|
||||
n_tags=len(tags))
|
||||
n_tags=n_tags)
|
||||
|
||||
# Browse through tags to add information to landmark.
|
||||
for key, value in tags.items():
|
||||
# Extract useful information for score calculation later down the road.
|
||||
landmark.image_url = tags.get('image')
|
||||
landmark.website_url = tags.get('website')
|
||||
landmark.wiki_url = tags.get('wikipedia')
|
||||
landmark.name_en = tags.get('name:en')
|
||||
|
||||
# Skip this landmark if not suitable.
|
||||
if key == 'building:part' and value == 'yes' :
|
||||
break
|
||||
if 'disused:' in key :
|
||||
break
|
||||
if 'boundary:' in key :
|
||||
break
|
||||
if 'shop' in key and landmarktype != 'shopping' :
|
||||
break
|
||||
# if value == 'apartments' :
|
||||
# break
|
||||
|
||||
# Fill in the other attributes.
|
||||
if key == 'image' :
|
||||
landmark.image_url = value
|
||||
if key == 'website' :
|
||||
landmark.website_url = value
|
||||
if value == 'place_of_worship' :
|
||||
# Check for place of worship
|
||||
if tags.get('place_of_worship') is not None :
|
||||
landmark.is_place_of_worship = True
|
||||
if key == 'wikipedia' :
|
||||
landmark.wiki_url = value
|
||||
if key == 'name:en' :
|
||||
landmark.name_en = value
|
||||
if 'building:' in key or 'pay' in key :
|
||||
landmark.n_tags -= 1
|
||||
landmark.name_en = tags.get('place_of_worship')
|
||||
|
||||
|
||||
# Set the duration.
|
||||
if value in ['museum', 'aquarium', 'planetarium'] :
|
||||
# Set the duration. Needed for the optimization.
|
||||
if tags.get('amenity') in ['aquarium', 'planetarium'] or tags.get('tourism') in ['aquarium', 'museum', 'zoo']:
|
||||
landmark.duration = 60
|
||||
elif value == 'viewpoint' :
|
||||
elif tags.get('tourism') == 'viewpoint' :
|
||||
landmark.is_viewpoint = True
|
||||
landmark.duration = 10
|
||||
elif value == 'cathedral' :
|
||||
elif tags.get('building') == 'cathedral' :
|
||||
landmark.is_place_of_worship = False
|
||||
landmark.duration = 10
|
||||
|
||||
landmark.description, landmark.keywords = self.description_and_keywords(tags)
|
||||
# Compute the score and add landmark to the list.
|
||||
self.set_landmark_score(landmark, landmarktype, preference_level)
|
||||
landmarks.append(landmark)
|
||||
|
||||
continue
|
||||
|
||||
|
||||
return landmarks
|
||||
|
||||
|
||||
def description_and_keywords(self, tags: dict):
|
||||
"""
|
||||
Generates a description and a set of keywords for a given landmark based on its tags.
|
||||
|
||||
Params:
|
||||
tags (dict): A dictionary containing metadata about the landmark, including its name,
|
||||
importance, height, date of construction, and visitor information.
|
||||
|
||||
Returns:
|
||||
description (str): A string description of the landmark.
|
||||
keywords (dict): A dictionary of keywords with fields such as 'importance', 'height',
|
||||
'place_type', and 'date'.
|
||||
"""
|
||||
# Extract relevant fields
|
||||
name = tags.get('name')
|
||||
importance = tags.get('importance', None)
|
||||
n_visitors = tags.get('tourism:visitors', None)
|
||||
height = tags.get('height')
|
||||
place_type = self.get_place_type(tags)
|
||||
date = self.get_date(tags)
|
||||
|
||||
if place_type is None :
|
||||
return None, None
|
||||
|
||||
# Start the description.
|
||||
if importance is None :
|
||||
if len(tags.keys()) < 5 :
|
||||
return None, None
|
||||
if len(tags.keys()) < 10 :
|
||||
description = f"{name} is a well known {place_type}."
|
||||
elif len(tags.keys()) < 17 :
|
||||
importance = 'national'
|
||||
description = f"{name} is a {place_type} of national importance."
|
||||
else :
|
||||
importance = 'international'
|
||||
description = f"{name} is an internationally famous {place_type}."
|
||||
else :
|
||||
description = f"{name} is a {place_type} of {importance} importance."
|
||||
|
||||
if height is not None and date is not None :
|
||||
description += f" This {place_type} was constructed in {date} and is ca. {height} meters high."
|
||||
elif height is not None :
|
||||
description += f" This {place_type} stands ca. {height} meters tall."
|
||||
elif date is not None:
|
||||
description += f" It was constructed in {date}."
|
||||
|
||||
# Format the visitor number
|
||||
if n_visitors is not None :
|
||||
n_visitors = int(n_visitors)
|
||||
if n_visitors < 1000000 :
|
||||
description += f" It welcomes {int(n_visitors/1000)} thousand visitors every year."
|
||||
else :
|
||||
description += f" It welcomes {round(n_visitors/1000000, 1)} million visitors every year."
|
||||
|
||||
# Set the keywords.
|
||||
keywords = {"importance": importance,
|
||||
"height": height,
|
||||
"place_type": place_type,
|
||||
"date": date}
|
||||
|
||||
return description, keywords
|
||||
|
||||
|
||||
def get_place_type(self, data):
|
||||
"""
|
||||
Determines the type of the place based on available tags such as 'amenity', 'building',
|
||||
'historic', and 'leisure'. The priority order is: 'historic' > 'building' (if not generic) >
|
||||
'amenity' > 'leisure'.
|
||||
|
||||
Params:
|
||||
data (dict): A dictionary containing metadata about the place.
|
||||
|
||||
Returns:
|
||||
place_type (str): The determined type of the place, or None if no relevant type is found.
|
||||
"""
|
||||
amenity = data.get('amenity', None)
|
||||
building = data.get('building', None)
|
||||
historic = data.get('historic', None)
|
||||
leisure = data.get('leisure')
|
||||
|
||||
if historic and historic != "yes":
|
||||
return historic
|
||||
if building and building not in ["yes", "civic", "government", "apartments", "residential", "commericial", "industrial", "retail", "religious", "public", "service"]:
|
||||
return building
|
||||
if amenity:
|
||||
return amenity
|
||||
if leisure:
|
||||
return leisure
|
||||
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def get_date(self, data):
|
||||
"""
|
||||
Extracts the most relevant date from the available tags, prioritizing 'construction_date',
|
||||
'start_date', 'year_of_construction', and 'opening_date' in that order.
|
||||
|
||||
Params:
|
||||
data (dict): A dictionary containing metadata about the place.
|
||||
|
||||
Returns:
|
||||
date (str): The most relevant date found, or None if no date is available.
|
||||
"""
|
||||
construction_date = data.get('construction_date', None)
|
||||
opening_date = data.get('opening_date', None)
|
||||
start_date = data.get('start_date', None)
|
||||
year_of_construction = data.get('year_of_construction', None)
|
||||
|
||||
# Prioritize based on availability
|
||||
if construction_date:
|
||||
return construction_date
|
||||
if start_date:
|
||||
return start_date
|
||||
if year_of_construction:
|
||||
return year_of_construction
|
||||
if opening_date:
|
||||
return opening_date
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def dict_to_selector_list(d: dict) -> list:
|
||||
"""
|
||||
Convert a dictionary of key-value pairs to a list of Overpass query strings.
|
||||
|
117
backend/src/landmarks/landmarks_routes.py
Normal file
@ -0,0 +1,117 @@
|
||||
"""Main app for backend api"""
|
||||
import logging
|
||||
import time
|
||||
import random
|
||||
from fastapi import HTTPException, APIRouter
|
||||
|
||||
from ..structs.landmark import Landmark
|
||||
from ..structs.preferences import Preferences, Preference
|
||||
from ..landmarks.landmarks_manager import LandmarkManager
|
||||
|
||||
|
||||
# Setup the logger and the Landmarks Manager
|
||||
logger = logging.getLogger(__name__)
|
||||
manager = LandmarkManager()
|
||||
|
||||
|
||||
# Start the router
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.post("/get/landmarks")
|
||||
def get_landmarks(
|
||||
preferences: Preferences,
|
||||
start: tuple[float, float],
|
||||
) -> list[Landmark]:
|
||||
"""
|
||||
Function that returns all available landmarks given some preferences and a start position.
|
||||
|
||||
Args:
|
||||
preferences : the preferences specified by the user as the post body
|
||||
start : the coordinates of the starting point
|
||||
Returns:
|
||||
list[Landmark] : The full list of fetched landmarks
|
||||
"""
|
||||
if preferences is None:
|
||||
raise HTTPException(status_code=406, detail="Preferences not provided or incomplete.")
|
||||
if (preferences.shopping.score == 0 and
|
||||
preferences.sightseeing.score == 0 and
|
||||
preferences.nature.score == 0) :
|
||||
raise HTTPException(status_code=406, detail="All preferences are 0.")
|
||||
if start is None:
|
||||
raise HTTPException(status_code=406, detail="Start coordinates not provided")
|
||||
if not (-90 <= start[0] <= 90 or -180 <= start[1] <= 180):
|
||||
raise HTTPException(status_code=422, detail="Start coordinates not in range")
|
||||
|
||||
logger.info(f"Requested new trip generation. Details:\n\tCoordinates: {start}\n\tTime: {preferences.max_time_minute}\n\tSightseeing: {preferences.sightseeing.score}\n\tNature: {preferences.nature.score}\n\tShopping: {preferences.shopping.score}")
|
||||
|
||||
start_time = time.time()
|
||||
|
||||
# Generate the landmarks from the start location
|
||||
landmarks, _ = manager.generate_landmarks_list(
|
||||
center_coordinates = start,
|
||||
preferences = preferences
|
||||
)
|
||||
|
||||
if len(landmarks) == 0 :
|
||||
raise HTTPException(status_code=500, detail="No landmarks were found.")
|
||||
|
||||
t_generate_landmarks = time.time() - start_time
|
||||
logger.info(f'Fetched {len(landmarks)} landmarks in \t: {round(t_generate_landmarks,3)} seconds')
|
||||
|
||||
return landmarks
|
||||
|
||||
|
||||
@router.post("/landmarks/get-nearby/{lat}/{lon}")
|
||||
def get_landmarks_nearby(
|
||||
lat: float,
|
||||
lon: float
|
||||
) -> list[Landmark] :
|
||||
"""
|
||||
Suggests nearby landmarks based on a given latitude and longitude.
|
||||
|
||||
This endpoint returns a curated list of up to 5 landmarks around the given geographical coordinates. It uses fixed preferences for
|
||||
sightseeing, shopping, and nature, with a maximum time constraint of 30 minutes to limit the number of landmarks returned.
|
||||
|
||||
Args:
|
||||
lat (float): Latitude of the user's current location.
|
||||
lon (float): Longitude of the user's current location.
|
||||
|
||||
Returns:
|
||||
list[Landmark]: A list of selected nearby landmarks.
|
||||
"""
|
||||
logger.info(f'Fetching landmarks nearby ({lat}, {lon}).')
|
||||
# Define fixed preferences:
|
||||
prefs = Preferences(
|
||||
sightseeing = Preference(
|
||||
type='sightseeing',
|
||||
score=5
|
||||
),
|
||||
shopping = Preference(
|
||||
type='shopping',
|
||||
score=2
|
||||
),
|
||||
nature = Preference(
|
||||
type='nature',
|
||||
score=5
|
||||
),
|
||||
max_time_minute=30,
|
||||
detour_tolerance_minute=0,
|
||||
)
|
||||
|
||||
# Find the landmarks around the location
|
||||
_, landmarks_around = manager.generate_landmarks_list(
|
||||
center_coordinates = (lat, lon),
|
||||
preferences = prefs,
|
||||
allow_clusters=False,
|
||||
)
|
||||
if len(landmarks_around) == 0 :
|
||||
raise HTTPException(status_code=500, detail="No landmarks were found.")
|
||||
|
||||
# select 5 landmarks from there
|
||||
if len(landmarks_around) > 6 :
|
||||
landmarks_around = landmarks_around[:2] + random.sample(landmarks_around[3:], 2)
|
||||
|
||||
logger.info(f'Found {len(landmarks_around)} landmarks nearby ({lat}, {lon}).')
|
||||
logger.debug('Suggested landmarks :\n\t' + '\n\t'.join(f'{landmark}' for landmark in landmarks_around))
|
||||
return landmarks_around
|
@ -33,14 +33,14 @@ def configure_logging():
|
||||
# silence the chatty logs loki generates itself
|
||||
logging.getLogger('urllib3.connectionpool').setLevel(logging.WARNING)
|
||||
# no need for time since it's added by loki or can be shown in kube logs
|
||||
logging_format = '%(name)s - %(levelname)s - %(message)s'
|
||||
logging_format = '%(name)-55s - %(levelname)-7s - %(message)s'
|
||||
|
||||
else:
|
||||
# if we are in a debug (local) session, set verbose and rich logging
|
||||
from rich.logging import RichHandler
|
||||
logging_handlers = [RichHandler()]
|
||||
logging_level = logging.DEBUG if is_debug else logging.INFO
|
||||
logging_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
logging_format = '%(asctime)s - %(name)-55s - %(levelname)-7s - %(message)s'
|
||||
|
||||
|
||||
|
||||
|
@ -1,16 +1,19 @@
|
||||
"""Main app for backend api"""
|
||||
import logging
|
||||
import time
|
||||
import random
|
||||
from contextlib import asynccontextmanager
|
||||
from fastapi import FastAPI, HTTPException, BackgroundTasks
|
||||
|
||||
from .logging_config import configure_logging
|
||||
from .structs.landmark import Landmark
|
||||
from .structs.preferences import Preferences
|
||||
from .structs.preferences import Preferences, Preference
|
||||
from .structs.linked_landmarks import LinkedLandmarks
|
||||
from .structs.trip import Trip
|
||||
from .landmarks.landmarks_manager import LandmarkManager
|
||||
from .toilets.toilet_routes import router as toilets_router
|
||||
from .toilets.toilets_route import router as toilets_router
|
||||
from .optimization.optimization_routes import router as optimization_router
|
||||
from .landmarks.landmarks_routes import router as landmarks_router
|
||||
from .optimization.optimizer import Optimizer
|
||||
from .optimization.refiner import Refiner
|
||||
from .overpass.overpass import fill_cache
|
||||
@ -38,13 +41,17 @@ app = FastAPI(lifespan=lifespan)
|
||||
|
||||
|
||||
app.include_router(toilets_router)
|
||||
app.include_router(optimization_router)
|
||||
app.include_router(landmarks_router)
|
||||
|
||||
|
||||
@app.post("/trip/new")
|
||||
def new_trip(preferences: Preferences,
|
||||
def new_trip(
|
||||
preferences: Preferences,
|
||||
start: tuple[float, float],
|
||||
end: tuple[float, float] | None = None,
|
||||
background_tasks: BackgroundTasks = None) -> Trip:
|
||||
background_tasks: BackgroundTasks = None
|
||||
) -> Trip:
|
||||
"""
|
||||
Main function to call the optimizer.
|
||||
|
||||
@ -140,7 +147,7 @@ def new_trip(preferences: Preferences,
|
||||
# upon creation of the trip, persistence of both the trip and its landmarks is ensured.
|
||||
trip = Trip.from_linked_landmarks(linked_tour, cache_client)
|
||||
logger.info(f'Generated a trip of {trip.total_time} minutes with {len(refined_tour)} landmarks in {round(t_generate_landmarks + t_first_stage + t_second_stage,3)} seconds.')
|
||||
logger.debug('Detailed trip :\n\t' + '\n\t'.join(f'{landmark}' for landmark in refined_tour))
|
||||
logger.info('Detailed trip :\n\t' + '\n\t'.join(f'{landmark}' for landmark in refined_tour))
|
||||
|
||||
background_tasks.add_task(fill_cache)
|
||||
|
||||
@ -224,3 +231,4 @@ def update_trip_time(trip_uuid: str, removed_landmark_uuid: str) -> Trip:
|
||||
trip = Trip.from_linked_landmarks(linked_tour, cache_client)
|
||||
|
||||
return trip
|
||||
|
||||
|
135
backend/src/optimization/optimization_routes.py
Normal file
@ -0,0 +1,135 @@
|
||||
"""Main app for backend api"""
|
||||
import logging
|
||||
import time
|
||||
import yaml
|
||||
from fastapi import HTTPException, APIRouter, BackgroundTasks
|
||||
|
||||
from ..structs.landmark import Landmark
|
||||
from ..structs.preferences import Preferences
|
||||
from ..structs.linked_landmarks import LinkedLandmarks
|
||||
from ..utils.take_most_important import take_most_important
|
||||
from ..structs.trip import Trip
|
||||
from ..optimization.optimizer import Optimizer
|
||||
from ..optimization.refiner import Refiner
|
||||
from ..overpass.overpass import fill_cache
|
||||
from ..cache import client as cache_client
|
||||
from ..constants import LANDMARK_PARAMETERS_PATH
|
||||
|
||||
|
||||
# Setup the Logger, Optimizer and Refiner
|
||||
logger = logging.getLogger(__name__)
|
||||
optimizer = Optimizer()
|
||||
refiner = Refiner(optimizer=optimizer)
|
||||
|
||||
|
||||
# Start the router
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.post("/optimize/trip")
|
||||
def optimize_trip(
|
||||
preferences: Preferences,
|
||||
landmarks: list[Landmark],
|
||||
start: tuple[float, float],
|
||||
end: tuple[float, float] | None = None,
|
||||
background_tasks: BackgroundTasks = None
|
||||
) -> Trip:
|
||||
"""
|
||||
Main function to call the optimizer.
|
||||
|
||||
Args:
|
||||
preferences (Preferences) : the preferences specified by the user as the post body.
|
||||
start (tuple[float, float]) : the coordinates of the starting point.
|
||||
end tuple[float, float] : the coordinates of the finishing point.
|
||||
backgroud_tasks (BackgroundTasks) : necessary to fill the cache after the trip has been returned.
|
||||
Returns:
|
||||
(uuid) : The uuid of the first landmark in the optimized route
|
||||
"""
|
||||
if preferences is None:
|
||||
raise HTTPException(status_code=406, detail="Preferences not provided or incomplete.")
|
||||
if len(landmarks) == 0 :
|
||||
raise HTTPException(status_code=406, detail="No landmarks provided for computing the trip.")
|
||||
if (preferences.shopping.score == 0 and
|
||||
preferences.sightseeing.score == 0 and
|
||||
preferences.nature.score == 0) :
|
||||
raise HTTPException(status_code=406, detail="All preferences are 0.")
|
||||
if start is None:
|
||||
raise HTTPException(status_code=406, detail="Start coordinates not provided")
|
||||
if not (-90 <= start[0] <= 90 or -180 <= start[1] <= 180):
|
||||
raise HTTPException(status_code=422, detail="Start coordinates not in range")
|
||||
if end is None:
|
||||
end = start
|
||||
logger.info("No end coordinates provided. Using start=end.")
|
||||
|
||||
# Start the timer
|
||||
start_time = time.time()
|
||||
|
||||
logger.info(f"Requested new trip generation. Details:\n\tCoordinates: {start}\n\tTime: {preferences.max_time_minute}\n\tSightseeing: {preferences.sightseeing.score}\n\tNature: {preferences.nature.score}\n\tShopping: {preferences.shopping.score}")
|
||||
|
||||
start_landmark = Landmark(name='start',
|
||||
type='start',
|
||||
location=(start[0], start[1]),
|
||||
osm_type='start',
|
||||
osm_id=0,
|
||||
attractiveness=0,
|
||||
duration=0,
|
||||
must_do=True,
|
||||
n_tags = 0)
|
||||
|
||||
end_landmark = Landmark(name='finish',
|
||||
type='finish',
|
||||
location=(end[0], end[1]),
|
||||
osm_type='end',
|
||||
osm_id=0,
|
||||
attractiveness=0,
|
||||
duration=0,
|
||||
must_do=True,
|
||||
n_tags=0)
|
||||
|
||||
# From the parameters load the length at which to truncate the landmarks list.
|
||||
with LANDMARK_PARAMETERS_PATH.open('r') as f:
|
||||
parameters = yaml.safe_load(f)
|
||||
n_important = parameters['N_important']
|
||||
|
||||
# Truncate to the most important landmarks for a shorter list
|
||||
landmarks_short = take_most_important(landmarks, n_important)
|
||||
|
||||
# insert start and finish to the shorter landmarks list
|
||||
landmarks_short.insert(0, start_landmark)
|
||||
landmarks_short.append(end_landmark)
|
||||
|
||||
# First stage optimization
|
||||
try:
|
||||
base_tour = optimizer.solve_optimization(preferences.max_time_minute, landmarks_short)
|
||||
except Exception as exc:
|
||||
logger.error(f"Trip generation failed: {str(exc)}")
|
||||
raise HTTPException(status_code=500, detail=f"Optimization failed: {str(exc)}") from exc
|
||||
|
||||
t_first_stage = time.time() - start_time
|
||||
start_time = time.time()
|
||||
|
||||
# Second stage optimization
|
||||
try :
|
||||
refined_tour = refiner.refine_optimization(landmarks, base_tour,
|
||||
preferences.max_time_minute,
|
||||
preferences.detour_tolerance_minute)
|
||||
except Exception as exc :
|
||||
logger.warning(f"Refiner failed. Proceeding with base trip {str(exc)}")
|
||||
refined_tour = base_tour
|
||||
|
||||
t_second_stage = time.time() - start_time
|
||||
|
||||
logger.debug(f'First stage optimization\t: {round(t_first_stage,3)} seconds')
|
||||
logger.debug(f'Second stage optimization\t: {round(t_second_stage,3)} seconds')
|
||||
logger.info(f'Total computation time\t: {round(t_first_stage + t_second_stage,3)} seconds')
|
||||
linked_tour = LinkedLandmarks(refined_tour)
|
||||
|
||||
# upon creation of the trip, persistence of both the trip and its landmarks is ensured.
|
||||
trip = Trip.from_linked_landmarks(linked_tour, cache_client)
|
||||
logger.info(f'Optimized a trip of {trip.total_time} minutes with {len(refined_tour)} landmarks in {round(t_first_stage + t_second_stage,3)} seconds.')
|
||||
logger.info('Detailed trip :\n\t' + '\n\t'.join(f'{landmark}' for landmark in refined_tour))
|
||||
|
||||
background_tasks.add_task(fill_cache)
|
||||
|
||||
return trip
|
||||
|
@ -402,6 +402,8 @@ def fill_cache():
|
||||
n_files = 0
|
||||
total = 0
|
||||
|
||||
overpass.logger.info('Trip successfully returned, starting to fill cache.')
|
||||
|
||||
with os.scandir(OSM_CACHE_DIR) as it:
|
||||
for entry in it:
|
||||
if entry.is_file() and entry.name.startswith('hollow_'):
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
from .landmark import Landmark
|
||||
from ..utils.get_time_distance import get_time
|
||||
from ..utils.description import description_and_keywords
|
||||
|
||||
class LinkedLandmarks:
|
||||
"""
|
||||
@ -35,18 +36,23 @@ class LinkedLandmarks:
|
||||
Create the links between the landmarks in the list by setting their
|
||||
.next_uuid and the .time_to_next attributes.
|
||||
"""
|
||||
|
||||
# Mark secondary landmarks as such
|
||||
self.update_secondary_landmarks()
|
||||
|
||||
|
||||
for i, landmark in enumerate(self._landmarks[:-1]):
|
||||
# Set uuid of the next landmark
|
||||
landmark.next_uuid = self._landmarks[i + 1].uuid
|
||||
|
||||
# Adjust time to reach and total time
|
||||
time_to_next = get_time(landmark.location, self._landmarks[i + 1].location)
|
||||
landmark.time_to_reach_next = time_to_next
|
||||
self.total_time += time_to_next
|
||||
self.total_time += landmark.duration
|
||||
|
||||
# Fill in the keywords and description. GOOD IDEA, BAD EXECUTION, tags aren't available anymore at this stage
|
||||
# landmark.description, landmark.keywords = description_and_keywords(tags)
|
||||
|
||||
|
||||
self._landmarks[-1].next_uuid = None
|
||||
self._landmarks[-1].time_to_reach_next = 0
|
||||
|
||||
|
@ -19,10 +19,10 @@ def invalid_client():
|
||||
([48.8566, 2.3522], {}, 422),
|
||||
|
||||
# Invalid cases: incomplete preferences.
|
||||
([48.084588, 7.280405], {"sightseeing": {"type": "nature", "score": 5}, # no shopping
|
||||
([48.084588, 7.280405], {"sightseeing": {"type": "sightseeing", "score": 5}, # no shopping
|
||||
"nature": {"type": "nature", "score": 5},
|
||||
}, 422),
|
||||
([48.084588, 7.280405], {"sightseeing": {"type": "nature", "score": 5}, # no nature
|
||||
([48.084588, 7.280405], {"sightseeing": {"type": "sightseeing", "score": 5}, # no nature
|
||||
"shopping": {"type": "shopping", "score": 5},
|
||||
}, 422),
|
||||
([48.084588, 7.280405], {"nature": {"type": "nature", "score": 5}, # no sightseeing
|
||||
@ -30,19 +30,19 @@ def invalid_client():
|
||||
}, 422),
|
||||
|
||||
# Invalid cases: unexisting coords
|
||||
([91, 181], {"sightseeing": {"type": "nature", "score": 5},
|
||||
([91, 181], {"sightseeing": {"type": "sightseeing", "score": 5},
|
||||
"nature": {"type": "nature", "score": 5},
|
||||
"shopping": {"type": "shopping", "score": 5},
|
||||
}, 422),
|
||||
([-91, 181], {"sightseeing": {"type": "nature", "score": 5},
|
||||
([-91, 181], {"sightseeing": {"type": "sightseeing", "score": 5},
|
||||
"nature": {"type": "nature", "score": 5},
|
||||
"shopping": {"type": "shopping", "score": 5},
|
||||
}, 422),
|
||||
([91, -181], {"sightseeing": {"type": "nature", "score": 5},
|
||||
([91, -181], {"sightseeing": {"type": "sightseeing", "score": 5},
|
||||
"nature": {"type": "nature", "score": 5},
|
||||
"shopping": {"type": "shopping", "score": 5},
|
||||
}, 422),
|
||||
([-91, -181], {"sightseeing": {"type": "nature", "score": 5},
|
||||
([-91, -181], {"sightseeing": {"type": "sightseeing", "score": 5},
|
||||
"nature": {"type": "nature", "score": 5},
|
||||
"shopping": {"type": "shopping", "score": 5},
|
||||
}, 422),
|
||||
|
@ -1,343 +0,0 @@
|
||||
"""Collection of tests to ensure correct implementation and track progress. """
|
||||
import time
|
||||
from fastapi.testclient import TestClient
|
||||
import pytest
|
||||
|
||||
from .test_utils import load_trip_landmarks, log_trip_details
|
||||
from ..main import app
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def client():
|
||||
"""Client used to call the app."""
|
||||
return TestClient(app)
|
||||
|
||||
|
||||
def test_turckheim(client, request): # pylint: disable=redefined-outer-name
|
||||
"""
|
||||
Test n°1 : Custom test in Turckheim to ensure small villages are also supported.
|
||||
|
||||
Args:
|
||||
client:
|
||||
request:
|
||||
"""
|
||||
start_time = time.time() # Start timer
|
||||
duration_minutes = 20
|
||||
|
||||
response = client.post(
|
||||
"/trip/new",
|
||||
json={
|
||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 5},
|
||||
"nature": {"type": "nature", "score": 0},
|
||||
"shopping": {"type": "shopping", "score": 0},
|
||||
"max_time_minute": duration_minutes,
|
||||
"detour_tolerance_minute": 0},
|
||||
"start": [48.084588, 7.280405]
|
||||
# "start": [45.74445023349939, 4.8222687890538865]
|
||||
# "start": [45.75156398104873, 4.827154464827647]
|
||||
}
|
||||
)
|
||||
result = response.json()
|
||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
||||
|
||||
|
||||
# Get computation time
|
||||
comp_time = time.time() - start_time
|
||||
|
||||
# Add details to report
|
||||
log_trip_details(request, landmarks, result['total_time'], duration_minutes)
|
||||
|
||||
|
||||
# checks :
|
||||
assert response.status_code == 200 # check for successful planning
|
||||
assert isinstance(landmarks, list) # check that the return type is a list
|
||||
assert len(landmarks) > 2 # check that there is something to visit
|
||||
assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds"
|
||||
assert duration_minutes*0.8 < result['total_time'], f"Trip too short: {result['total_time']} instead of {duration_minutes}"
|
||||
assert duration_minutes*1.2 > result['total_time'], f"Trip too long: {result['total_time']} instead of {duration_minutes}"
|
||||
# assert 2!= 3
|
||||
|
||||
def test_bellecour(client, request) : # pylint: disable=redefined-outer-name
|
||||
"""
|
||||
Test n°2 : Custom test in Lyon centre to ensure proper decision making in crowded area.
|
||||
|
||||
Args:
|
||||
client:
|
||||
request:
|
||||
"""
|
||||
start_time = time.time() # Start timer
|
||||
duration_minutes = 120
|
||||
|
||||
|
||||
response = client.post(
|
||||
"/trip/new",
|
||||
json={
|
||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 5},
|
||||
"nature": {"type": "nature", "score": 5},
|
||||
"shopping": {"type": "shopping", "score": 5},
|
||||
"max_time_minute": duration_minutes,
|
||||
"detour_tolerance_minute": 0},
|
||||
"start": [45.7576485, 4.8330241]
|
||||
}
|
||||
)
|
||||
result = response.json()
|
||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
||||
|
||||
# Get computation time
|
||||
comp_time = time.time() - start_time
|
||||
|
||||
# Add details to report
|
||||
log_trip_details(request, landmarks, result['total_time'], duration_minutes)
|
||||
|
||||
# for elem in landmarks :
|
||||
# print(elem)
|
||||
|
||||
# checks :
|
||||
assert response.status_code == 200 # check for successful planning
|
||||
assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds"
|
||||
assert duration_minutes*0.8 < result['total_time'], f"Trip too short: {result['total_time']} instead of {duration_minutes}"
|
||||
assert duration_minutes*1.2 > result['total_time'], f"Trip too long: {result['total_time']} instead of {duration_minutes}"
|
||||
|
||||
def test_cologne(client, request) : # pylint: disable=redefined-outer-name
|
||||
"""
|
||||
Test n°3 : Custom test in Cologne to ensure proper decision making in crowded area.
|
||||
|
||||
Args:
|
||||
client:
|
||||
request:
|
||||
"""
|
||||
start_time = time.time() # Start timer
|
||||
duration_minutes = 240
|
||||
|
||||
response = client.post(
|
||||
"/trip/new",
|
||||
json={
|
||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 5},
|
||||
"nature": {"type": "nature", "score": 5},
|
||||
"shopping": {"type": "shopping", "score": 5},
|
||||
"max_time_minute": duration_minutes,
|
||||
"detour_tolerance_minute": 0},
|
||||
"start": [50.942352665, 6.957777972392]
|
||||
}
|
||||
)
|
||||
result = response.json()
|
||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
||||
|
||||
# Get computation time
|
||||
comp_time = time.time() - start_time
|
||||
|
||||
# Add details to report
|
||||
log_trip_details(request, landmarks, result['total_time'], duration_minutes)
|
||||
|
||||
# for elem in landmarks :
|
||||
# print(elem)
|
||||
|
||||
# checks :
|
||||
assert response.status_code == 200 # check for successful planning
|
||||
assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds"
|
||||
assert duration_minutes*0.8 < result['total_time'], f"Trip too short: {result['total_time']} instead of {duration_minutes}"
|
||||
assert duration_minutes*1.2 > result['total_time'], f"Trip too long: {result['total_time']} instead of {duration_minutes}"
|
||||
|
||||
|
||||
def test_strasbourg(client, request) : # pylint: disable=redefined-outer-name
|
||||
"""
|
||||
Test n°4 : Custom test in Strasbourg to ensure proper decision making in crowded area.
|
||||
|
||||
Args:
|
||||
client:
|
||||
request:
|
||||
"""
|
||||
start_time = time.time() # Start timer
|
||||
duration_minutes = 180
|
||||
|
||||
response = client.post(
|
||||
"/trip/new",
|
||||
json={
|
||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 5},
|
||||
"nature": {"type": "nature", "score": 5},
|
||||
"shopping": {"type": "shopping", "score": 5},
|
||||
"max_time_minute": duration_minutes,
|
||||
"detour_tolerance_minute": 0},
|
||||
"start": [48.5846589226, 7.74078715721]
|
||||
}
|
||||
)
|
||||
result = response.json()
|
||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
||||
|
||||
# Get computation time
|
||||
comp_time = time.time() - start_time
|
||||
|
||||
# Add details to report
|
||||
log_trip_details(request, landmarks, result['total_time'], duration_minutes)
|
||||
|
||||
# for elem in landmarks :
|
||||
# print(elem)
|
||||
|
||||
# checks :
|
||||
assert response.status_code == 200 # check for successful planning
|
||||
assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds"
|
||||
assert duration_minutes*0.8 < result['total_time'], f"Trip too short: {result['total_time']} instead of {duration_minutes}"
|
||||
assert duration_minutes*1.2 > result['total_time'], f"Trip too long: {result['total_time']} instead of {duration_minutes}"
|
||||
|
||||
|
||||
def test_zurich(client, request) : # pylint: disable=redefined-outer-name
|
||||
"""
|
||||
Test n°5 : Custom test in Zurich to ensure proper decision making in crowded area.
|
||||
|
||||
Args:
|
||||
client:
|
||||
request:
|
||||
"""
|
||||
start_time = time.time() # Start timer
|
||||
duration_minutes = 180
|
||||
|
||||
response = client.post(
|
||||
"/trip/new",
|
||||
json={
|
||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 5},
|
||||
"nature": {"type": "nature", "score": 5},
|
||||
"shopping": {"type": "shopping", "score": 5},
|
||||
"max_time_minute": duration_minutes,
|
||||
"detour_tolerance_minute": 0},
|
||||
"start": [47.377884227, 8.5395114066]
|
||||
}
|
||||
)
|
||||
result = response.json()
|
||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
||||
|
||||
# Get computation time
|
||||
comp_time = time.time() - start_time
|
||||
|
||||
# Add details to report
|
||||
log_trip_details(request, landmarks, result['total_time'], duration_minutes)
|
||||
|
||||
# for elem in landmarks :
|
||||
# print(elem)
|
||||
|
||||
# checks :
|
||||
assert response.status_code == 200 # check for successful planning
|
||||
assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds"
|
||||
assert duration_minutes*0.8 < result['total_time'], f"Trip too short: {result['total_time']} instead of {duration_minutes}"
|
||||
assert duration_minutes*1.2 > result['total_time'], f"Trip too long: {result['total_time']} instead of {duration_minutes}"
|
||||
|
||||
|
||||
def test_paris(client, request) : # pylint: disable=redefined-outer-name
|
||||
"""
|
||||
Test n°6 : Custom test in Paris (les Halles) centre to ensure proper decision making in crowded area.
|
||||
|
||||
Args:
|
||||
client:
|
||||
request:
|
||||
"""
|
||||
start_time = time.time() # Start timer
|
||||
duration_minutes = 200
|
||||
|
||||
response = client.post(
|
||||
"/trip/new",
|
||||
json={
|
||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 5},
|
||||
"nature": {"type": "nature", "score": 0},
|
||||
"shopping": {"type": "shopping", "score": 5},
|
||||
"max_time_minute": duration_minutes,
|
||||
"detour_tolerance_minute": 0},
|
||||
"start": [48.85468881798671, 2.3423925755998374]
|
||||
}
|
||||
)
|
||||
result = response.json()
|
||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
||||
|
||||
# Get computation time
|
||||
comp_time = time.time() - start_time
|
||||
|
||||
# Add details to report
|
||||
log_trip_details(request, landmarks, result['total_time'], duration_minutes)
|
||||
|
||||
# for elem in landmarks :
|
||||
# print(elem)
|
||||
|
||||
# checks :
|
||||
assert response.status_code == 200 # check for successful planning
|
||||
assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds"
|
||||
assert duration_minutes*0.8 < result['total_time'], f"Trip too short: {result['total_time']} instead of {duration_minutes}"
|
||||
assert duration_minutes*1.2 > result['total_time'], f"Trip too long: {result['total_time']} instead of {duration_minutes}"
|
||||
|
||||
|
||||
def test_new_york(client, request) : # pylint: disable=redefined-outer-name
|
||||
"""
|
||||
Test n°7 : Custom test in New York to ensure proper decision making in crowded area.
|
||||
|
||||
Args:
|
||||
client:
|
||||
request:
|
||||
"""
|
||||
start_time = time.time() # Start timer
|
||||
duration_minutes = 600
|
||||
|
||||
response = client.post(
|
||||
"/trip/new",
|
||||
json={
|
||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 5},
|
||||
"nature": {"type": "nature", "score": 5},
|
||||
"shopping": {"type": "shopping", "score": 5},
|
||||
"max_time_minute": duration_minutes,
|
||||
"detour_tolerance_minute": 0},
|
||||
"start": [40.72592726802, -73.9920434795]
|
||||
}
|
||||
)
|
||||
result = response.json()
|
||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
||||
|
||||
# Get computation time
|
||||
comp_time = time.time() - start_time
|
||||
|
||||
# Add details to report
|
||||
log_trip_details(request, landmarks, result['total_time'], duration_minutes)
|
||||
|
||||
# for elem in landmarks :
|
||||
# print(elem)
|
||||
|
||||
# checks :
|
||||
assert response.status_code == 200 # check for successful planning
|
||||
assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds"
|
||||
assert duration_minutes*0.8 < result['total_time'], f"Trip too short: {result['total_time']} instead of {duration_minutes}"
|
||||
assert duration_minutes*1.2 > result['total_time'], f"Trip too long: {result['total_time']} instead of {duration_minutes}"
|
||||
|
||||
|
||||
def test_shopping(client, request) : # pylint: disable=redefined-outer-name
|
||||
"""
|
||||
Test n°8 : Custom test in Lyon centre to ensure shopping clusters are found.
|
||||
|
||||
Args:
|
||||
client:
|
||||
request:
|
||||
"""
|
||||
start_time = time.time() # Start timer
|
||||
duration_minutes = 240
|
||||
|
||||
response = client.post(
|
||||
"/trip/new",
|
||||
json={
|
||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 0},
|
||||
"nature": {"type": "nature", "score": 0},
|
||||
"shopping": {"type": "shopping", "score": 5},
|
||||
"max_time_minute": duration_minutes,
|
||||
"detour_tolerance_minute": 0},
|
||||
"start": [45.7576485, 4.8330241]
|
||||
}
|
||||
)
|
||||
result = response.json()
|
||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
||||
|
||||
# Get computation time
|
||||
comp_time = time.time() - start_time
|
||||
|
||||
# Add details to report
|
||||
log_trip_details(request, landmarks, result['total_time'], duration_minutes)
|
||||
|
||||
# for elem in landmarks :
|
||||
# print(elem)
|
||||
|
||||
# checks :
|
||||
assert response.status_code == 200 # check for successful planning
|
||||
assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds"
|
||||
assert duration_minutes*0.8 < result['total_time'], f"Trip too short: {result['total_time']} instead of {duration_minutes}"
|
||||
assert duration_minutes*1.2 > result['total_time'], f"Trip too long: {result['total_time']} instead of {duration_minutes}"
|
38
backend/src/tests/test_nearby.py
Normal file
@ -0,0 +1,38 @@
|
||||
"""Collection of tests to ensure correct implementation and track progress of the get_landmarks_nearby feature. """
|
||||
from fastapi.testclient import TestClient
|
||||
import pytest
|
||||
|
||||
from ..main import app
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def client():
|
||||
"""Client used to call the app."""
|
||||
return TestClient(app)
|
||||
|
||||
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"location,status_code",
|
||||
[
|
||||
([45.7576485, 4.8330241], 2000), # Lyon, Bellecour.
|
||||
([41.4020572, 2.1818985], 2000), # Barcelona
|
||||
]
|
||||
)
|
||||
def test_nearby(client, location, status_code): # pylint: disable=redefined-outer-name
|
||||
"""
|
||||
Test n°1 : Verify handling of invalid input.
|
||||
|
||||
Args:
|
||||
client:
|
||||
request:
|
||||
"""
|
||||
response = client.post(f"/landmarks/get-nearby/{location[0]}/{location[1]}")
|
||||
print(response)
|
||||
print(response.json())
|
||||
suggestions = response.json()
|
||||
|
||||
# checks :
|
||||
assert response.status_code == status_code # check for successful planning
|
||||
assert isinstance(suggestions, list) # check that the return type is a list
|
||||
assert len(suggestions) > 0
|
81
backend/src/tests/test_trip_generation.py
Normal file
@ -0,0 +1,81 @@
|
||||
"""Collection of tests to ensure correct implementation and track progress."""
|
||||
import time
|
||||
from fastapi.testclient import TestClient
|
||||
import pytest
|
||||
|
||||
from .test_utils import load_trip_landmarks, log_trip_details
|
||||
from ..structs.preferences import Preferences, Preference
|
||||
from ..main import app
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def client():
|
||||
"""Client used to call the app."""
|
||||
return TestClient(app)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"sightseeing, shopping, nature, max_time_minute, start_coords, end_coords",
|
||||
[
|
||||
# Edge cases
|
||||
(0, 0, 5, 240, [45.7576485, 4.8330241], None), # Lyon, Bellecour - test shopping only
|
||||
|
||||
# Realistic
|
||||
(5, 0, 0, 20, [48.0845881, 7.2804050], None), # Turckheim
|
||||
(5, 5, 5, 120, [45.7576485, 4.8330241], None), # Lyon, Bellecour
|
||||
(5, 5, 5, 240, [50.9423526, 6.9577780], None), # Cologne, centre
|
||||
(5, 5, 5, 180, [48.5846589226, 7.74078715721], None), # Strasbourg, centre
|
||||
(5, 5, 5, 180, [47.377884227, 8.5395114066], None), # Zurich, centre
|
||||
(5, 0, 5, 200, [48.85468881798671, 2.3423925755998374], None), # Paris, centre
|
||||
(5, 5, 5, 600, [40.72592726802, -73.9920434795], None), # New York, Lower Manhattan
|
||||
]
|
||||
)
|
||||
def test_trip(client, request, sightseeing, shopping, nature, max_time_minute, start_coords, end_coords):
|
||||
|
||||
start_time = time.time() # Start timer
|
||||
|
||||
prefs = Preferences(
|
||||
sightseeing=Preference(type='sightseeing', score=sightseeing),
|
||||
shopping=Preference(type='shopping', score=shopping),
|
||||
nature=Preference(type='nature', score=nature),
|
||||
max_time_minute=max_time_minute,
|
||||
detour_tolerance_minute=0,
|
||||
)
|
||||
start = start_coords
|
||||
end = end_coords
|
||||
|
||||
# Step 1: request the list of landmarks in the vicinty of the starting point
|
||||
response = client.post(
|
||||
"/get/landmarks",
|
||||
json={
|
||||
"preferences": prefs.model_dump(),
|
||||
"start": start_coords,
|
||||
"end": end_coords,
|
||||
}
|
||||
)
|
||||
landmarks = response.json()
|
||||
|
||||
# Step 2: Feed the landmarks to the optimizer to compute the trip
|
||||
response = client.post(
|
||||
"/optimize/trip",
|
||||
json={
|
||||
"preferences": prefs.model_dump(),
|
||||
"landmarks": landmarks,
|
||||
"start": start,
|
||||
"end": end,
|
||||
}
|
||||
)
|
||||
result = response.json()
|
||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
||||
|
||||
# Get computation time
|
||||
comp_time = time.time() - start_time
|
||||
|
||||
# Add details to report
|
||||
log_trip_details(request, landmarks, result['total_time'], prefs.max_time_minute)
|
||||
|
||||
# checks :
|
||||
assert response.status_code == 200 # check for successful planning
|
||||
assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds"
|
||||
assert prefs.max_time_minute*0.8 < result['total_time'], f"Trip too short: {result['total_time']} instead of {prefs.max_time_minute}"
|
||||
assert prefs.max_time_minute*1.2 > result['total_time'], f"Trip too long: {result['total_time']} instead of {prefs.max_time_minute}"
|
@ -1,9 +1,12 @@
|
||||
"""Helper methods for testing."""
|
||||
import time
|
||||
import logging
|
||||
from functools import wraps
|
||||
from fastapi import HTTPException
|
||||
|
||||
from ..structs.landmark import Landmark
|
||||
from ..cache import client as cache_client
|
||||
from ..structs.landmark import Landmark
|
||||
from ..structs.preferences import Preferences, Preference
|
||||
|
||||
|
||||
def landmarks_to_osmid(landmarks: list[Landmark]) -> list[int] :
|
||||
@ -91,3 +94,34 @@ def log_trip_details(request, landmarks: list[Landmark], duration: int, target_d
|
||||
request.node.trip_details = trip_string
|
||||
request.node.trip_duration = str(duration) # result['total_time']
|
||||
request.node.target_duration = str(target_duration)
|
||||
|
||||
|
||||
|
||||
|
||||
def trip_params(
|
||||
sightseeing: int,
|
||||
shopping: int,
|
||||
nature: int,
|
||||
max_time_minute: int,
|
||||
start_coords: tuple[float, float] = None,
|
||||
end_coords: tuple[float, float] = None,
|
||||
):
|
||||
def decorator(test_func):
|
||||
@wraps(test_func)
|
||||
def wrapper(client, request):
|
||||
prefs = Preferences(
|
||||
sightseeing=Preference(type='sightseeing', score=sightseeing),
|
||||
shopping=Preference(type='shopping', score=shopping),
|
||||
nature=Preference(type='nature', score=nature),
|
||||
max_time_minute=max_time_minute,
|
||||
detour_tolerance_minute=0,
|
||||
)
|
||||
|
||||
start = start_coords
|
||||
end = end_coords
|
||||
|
||||
# Inject into test function
|
||||
return test_func(client, request, prefs, start, end)
|
||||
|
||||
return wrapper
|
||||
return decorator
|
123
backend/src/utils/description.py
Normal file
@ -0,0 +1,123 @@
|
||||
"""Add more information about the landmarks by writing a short description and keywords. """
|
||||
|
||||
|
||||
def description_and_keywords(tags: dict):
|
||||
"""
|
||||
Generates a description and a set of keywords for a given landmark based on its tags.
|
||||
|
||||
Params:
|
||||
tags (dict): A dictionary containing metadata about the landmark, including its name,
|
||||
importance, height, date of construction, and visitor information.
|
||||
|
||||
Returns:
|
||||
description (str): A string description of the landmark.
|
||||
keywords (dict): A dictionary of keywords with fields such as 'importance', 'height',
|
||||
'place_type', and 'date'.
|
||||
"""
|
||||
# Extract relevant fields
|
||||
name = tags.get('name')
|
||||
importance = tags.get('importance', None)
|
||||
n_visitors = tags.get('tourism:visitors', None)
|
||||
height = tags.get('height')
|
||||
place_type = get_place_type(tags)
|
||||
date = get_date(tags)
|
||||
|
||||
if place_type is None :
|
||||
return None, None
|
||||
|
||||
# Start the description.
|
||||
if importance is None :
|
||||
if len(tags.keys()) < 5 :
|
||||
return None, None
|
||||
if len(tags.keys()) < 10 :
|
||||
description = f"{name} is a well known {place_type}."
|
||||
elif len(tags.keys()) < 17 :
|
||||
importance = 'national'
|
||||
description = f"{name} is a {place_type} of national importance."
|
||||
else :
|
||||
importance = 'international'
|
||||
description = f"{name} is an internationally famous {place_type}."
|
||||
else :
|
||||
description = f"{name} is a {place_type} of {importance} importance."
|
||||
|
||||
if height is not None and date is not None :
|
||||
description += f" This {place_type} was constructed in {date} and is ca. {height} meters high."
|
||||
elif height is not None :
|
||||
description += f" This {place_type} stands ca. {height} meters tall."
|
||||
elif date is not None:
|
||||
description += f" It was constructed in {date}."
|
||||
|
||||
# Format the visitor number
|
||||
if n_visitors is not None :
|
||||
n_visitors = int(n_visitors)
|
||||
if n_visitors < 1000000 :
|
||||
description += f" It welcomes {int(n_visitors/1000)} thousand visitors every year."
|
||||
else :
|
||||
description += f" It welcomes {round(n_visitors/1000000, 1)} million visitors every year."
|
||||
|
||||
# Set the keywords.
|
||||
keywords = {"importance": importance,
|
||||
"height": height,
|
||||
"place_type": place_type,
|
||||
"date": date}
|
||||
|
||||
return description, keywords
|
||||
|
||||
|
||||
def get_place_type(tags):
|
||||
"""
|
||||
Determines the type of the place based on available tags such as 'amenity', 'building',
|
||||
'historic', and 'leisure'. The priority order is: 'historic' > 'building' (if not generic) >
|
||||
'amenity' > 'leisure'.
|
||||
|
||||
Params:
|
||||
tags (dict): A dictionary containing metadata about the place.
|
||||
|
||||
Returns:
|
||||
place_type (str): The determined type of the place, or None if no relevant type is found.
|
||||
"""
|
||||
amenity = tags.get('amenity', None)
|
||||
building = tags.get('building', None)
|
||||
historic = tags.get('historic', None)
|
||||
leisure = tags.get('leisure')
|
||||
|
||||
if historic and historic != "yes":
|
||||
return historic
|
||||
if building and building not in ["yes", "civic", "government", "apartments", "residential", "commericial", "industrial", "retail", "religious", "public", "service"]:
|
||||
return building
|
||||
if amenity:
|
||||
return amenity
|
||||
if leisure:
|
||||
return leisure
|
||||
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def get_date(tags):
|
||||
"""
|
||||
Extracts the most relevant date from the available tags, prioritizing 'construction_date',
|
||||
'start_date', 'year_of_construction', and 'opening_date' in that order.
|
||||
|
||||
Params:
|
||||
tags (dict): A dictionary containing metadata about the place.
|
||||
|
||||
Returns:
|
||||
date (str): The most relevant date found, or None if no date is available.
|
||||
"""
|
||||
construction_date = tags.get('construction_date', None)
|
||||
opening_date = tags.get('opening_date', None)
|
||||
start_date = tags.get('start_date', None)
|
||||
year_of_construction = tags.get('year_of_construction', None)
|
||||
|
||||
# Prioritize based on availability
|
||||
if construction_date:
|
||||
return construction_date
|
||||
if start_date:
|
||||
return start_date
|
||||
if year_of_construction:
|
||||
return year_of_construction
|
||||
if opening_date:
|
||||
return opening_date
|
||||
|
||||
return None
|
@ -1,15 +1,22 @@
|
||||
"""Helper function to return only the major landmarks from a large list."""
|
||||
from ..structs.landmark import Landmark
|
||||
|
||||
def take_most_important(landmarks: list[Landmark], n_important) -> list[Landmark]:
|
||||
def take_most_important(
|
||||
landmarks: list[Landmark],
|
||||
n_important: int
|
||||
) -> list[Landmark]:
|
||||
"""
|
||||
Given a list of landmarks, return the n_important most important landmarks
|
||||
Given a list of landmarks, return the most important landmarks based on their attractiveness.
|
||||
|
||||
Args:
|
||||
landmarks: list[Landmark] - list of landmarks
|
||||
n_important: int - number of most important landmarks to return
|
||||
landmarks (list[Landmark]): List of landmarks that needs to be truncated
|
||||
n_important (int): Number of most important landmarks to return
|
||||
|
||||
Returns:
|
||||
list[Landmark] - list of the n_important most important landmarks
|
||||
list[Landmark]: List of the n_important most important landmarks
|
||||
"""
|
||||
if n_important == 0 :
|
||||
raise ValueError('Number of landmarks to keep cannot be zero.')
|
||||
|
||||
# Sort landmarks by attractiveness (descending)
|
||||
sorted_landmarks = sorted(landmarks, key=lambda x: x.attractiveness, reverse=True)
|
||||
|
59
frontend/.github/workflows/build_app_android.yaml
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up ruby env
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: 3.2.1
|
||||
bundler-cache: true
|
||||
|
||||
- name: Setup java for android build
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'zulu'
|
||||
|
||||
- name: Setup android SDK
|
||||
uses: android-actions/setup-android@v3
|
||||
|
||||
- name: Install Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: stable
|
||||
flutter-version: 3.22.0
|
||||
cache: true
|
||||
|
||||
- name: Infer version number from git tag
|
||||
id: version
|
||||
env:
|
||||
REF_NAME: ${{ github.ref_name }}
|
||||
run:
|
||||
# remove the 'v' prefix from the tag name
|
||||
echo "BUILD_NAME=${REF_NAME//v}" >> $GITHUB_ENV
|
||||
|
||||
- name: Put selected secrets into files
|
||||
run: |
|
||||
echo "${{ secrets.ANDROID_SECRET_PROPERTIES_BASE64 }}" | base64 -d > secrets.properties
|
||||
echo "${{ secrets.ANDROID_GOOGLE_PLAY_JSON_BASE64 }}" | base64 -d > google-key.json
|
||||
echo "${{ secrets.ANDROID_KEYSTORE_BASE64 }}" | base64 -d > release.keystore
|
||||
working-directory: android
|
||||
|
||||
- name: Install fastlane
|
||||
run: bundle install
|
||||
working-directory: android
|
||||
|
||||
- name: Run fastlane lane
|
||||
run: bundle exec fastlane deploy_release
|
||||
working-directory: android
|
||||
env:
|
||||
BUILD_NUMBER: ${{ github.run_number }}
|
||||
# BUILD_NAME is implicitly available
|
||||
GOOGLE_MAPS_API_KEY: ${{ secrets.GOOGLE_MAPS_API_KEY }}
|
64
frontend/.github/workflows/build_app_ios.yaml
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macos-latest
|
||||
env:
|
||||
# $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps
|
||||
BUNDLE_GEMFILE: ${{ github.workspace }}/ios/Gemfile
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up ruby env
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: 3.3
|
||||
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
||||
|
||||
- name: Install Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: stable
|
||||
flutter-version: 3.22.0
|
||||
cache: true
|
||||
|
||||
- name: Infer version number from git tag
|
||||
id: version
|
||||
env:
|
||||
REF_NAME: ${{ github.ref_name }}
|
||||
run:
|
||||
# remove the 'v' prefix from the tag name
|
||||
echo "BUILD_NAME=${REF_NAME//v}" >> $GITHUB_ENV
|
||||
|
||||
- name: Setup SSH key for match git repo
|
||||
# and mark the host as known
|
||||
run: |
|
||||
echo $MATCH_REPO_SSH_KEY | base64 --decode > ~/.ssh/id_rsa
|
||||
chmod 600 ~/.ssh/id_rsa
|
||||
ssh-keyscan -p 2222 git.kluster.moll.re > ~/.ssh/known_hosts
|
||||
env:
|
||||
MATCH_REPO_SSH_KEY: ${{ secrets.IOS_MATCH_REPO_SSH_KEY_BASE64 }}
|
||||
|
||||
- name: Install dependencies and clean up
|
||||
run: |
|
||||
flutter pub get
|
||||
bundle exec pod install
|
||||
flutter clean
|
||||
bundle exec pod cache clean --all
|
||||
working-directory: ios
|
||||
|
||||
- name: Run fastlane lane
|
||||
run: bundle exec fastlane deploy_release --verbose
|
||||
working-directory: ios
|
||||
env:
|
||||
BUILD_NUMBER: ${{ github.run_number }}
|
||||
# BUILD_NAME is implicitly available
|
||||
GOOGLE_MAPS_API_KEY: ${{ secrets.GOOGLE_MAPS_API_KEY }}
|
||||
IOS_ASC_KEY_ID: ${{ secrets.IOS_ASC_KEY_ID }}
|
||||
IOS_ASC_ISSUER_ID: ${{ secrets.IOS_ASC_ISSUER_ID }}
|
||||
IOS_ASC_KEY: ${{ secrets.IOS_ASC_KEY }}
|
||||
MATCH_PASSWORD: ${{ secrets.IOS_MATCH_PASSWORD }}
|
||||
IOS_GOOGLE_MAPS_API_KEY: ${{ secrets.IOS_GOOGLE_MAPS_API_KEY }}
|
@ -4,7 +4,7 @@
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: "09de023485e95e6d1225c2baa44b8feb85e0d45f"
|
||||
revision: "54e66469a933b60ddf175f858f82eaeb97e48c8d"
|
||||
channel: "stable"
|
||||
|
||||
project_type: app
|
||||
@ -13,11 +13,26 @@ project_type: app
|
||||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: 09de023485e95e6d1225c2baa44b8feb85e0d45f
|
||||
base_revision: 09de023485e95e6d1225c2baa44b8feb85e0d45f
|
||||
create_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
|
||||
base_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
|
||||
- platform: android
|
||||
create_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
|
||||
base_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
|
||||
- platform: ios
|
||||
create_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
|
||||
base_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
|
||||
- platform: linux
|
||||
create_revision: 09de023485e95e6d1225c2baa44b8feb85e0d45f
|
||||
base_revision: 09de023485e95e6d1225c2baa44b8feb85e0d45f
|
||||
create_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
|
||||
base_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
|
||||
- platform: macos
|
||||
create_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
|
||||
base_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
|
||||
- platform: web
|
||||
create_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
|
||||
base_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
|
||||
- platform: windows
|
||||
create_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
|
||||
base_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
|
||||
|
||||
# User provided section
|
||||
|
||||
|
@ -17,17 +17,7 @@ flutter pub get
|
||||
```
|
||||
|
||||
## Development
|
||||
### TODO
|
||||
|
||||
## Deployment and metadata
|
||||
### Deploying a new version
|
||||
To truly deploy a new version of the application, i.e. to the official app stores, a special CI step is required. This listens for new tags. To create a new tag position yourself on the main branch and run
|
||||
```bash
|
||||
git tag -a v<name> -m "Release <name>"
|
||||
git push origin v<name>
|
||||
```
|
||||
We adhere to the [Semantic Versioning](https://semver.org/) standard, so the tag should be of the form `v0.1.8` for example.
|
||||
|
||||
### ...
|
||||
### Icons and logos
|
||||
The application uses a custom launcher icon and splash screen. These are managed platform-independently using the `flutter_launcher_icons` package.
|
||||
|
||||
@ -35,10 +25,14 @@ To update the icons, change the `flutter_launcher_icons.yaml` configuration file
|
||||
```bash
|
||||
dart run flutter_launcher_icons
|
||||
```
|
||||
### Other metadata
|
||||
Fastlane provides mechanisms to update the metadata of the application. This includes the name, description, screenshots, etc. The metadata is stored in the `fastlane/metadata` directory of both the `android`and the `ios` version of the application. Both versions have different structures but **they should be kept in sync**. For more information see the [fastlane documentation](https://docs.fastlane.tools/):
|
||||
- https://docs.fastlane.tools/actions/deliver/
|
||||
- https://docs.fastlane.tools/actions/supply/
|
||||
|
||||
### Deploying a new version
|
||||
To truly deploy a new version of the application, i.e. to the official app stores, a special CI step is required. This listens for new tags. To create a new tag position yourself on the main branch and run
|
||||
```bash
|
||||
git tag -a v<name> -m "Release <name>"
|
||||
git push origin v<name>
|
||||
```
|
||||
We adhere to the [Semantic Versioning](https://semver.org/) standard, so the tag should be of the form `v0.1.8` for example.
|
||||
|
||||
|
||||
## Fastlane - in depth
|
||||
@ -52,17 +46,16 @@ bundle exec fastlane <lane>
|
||||
```
|
||||
This is reused in the CI/CD pipeline to automate the deployment process.
|
||||
|
||||
Secrets used by fastlane are stored on hashicorp vault and are fetched by the CI/CD pipeline. See below.
|
||||
|
||||
## Secrets
|
||||
These are used by the CI/CD pipeline to deploy the application.
|
||||
These are mostly used by the CI/CD pipeline to deploy the application. The main usage for github actions is documented under [https://github.com/hashicorp/vault-action](https://github.com/hashicorp/vault-action).
|
||||
|
||||
**Platform-specific secrets** are used by the CI/CD pipeline to deploy to the respective app stores.
|
||||
- `ANDROID_GOOGLE_MAPS_API_KEY` is used to authenticate with the Google Maps API and is scoped to the android platform
|
||||
- `GOOGLE_MAPS_API_KEY` is used to authenticate with the Google Maps API and is scoped to the android platform
|
||||
- `ANDROID_KEYSTORE` is used to sign the android apk
|
||||
- `ANDROID_GOOGLE_KEY` is used to authenticate with the Google Play Store api
|
||||
- `IOS_GOOGLE_MAPS_API_KEY` is used to authenticate with the Google Maps API and is scoped to the ios platform
|
||||
- `IOS_ASC_ISSUER_ID` is used to authenticate with the App Store Connect API
|
||||
- `IOS_ASC_KEY` as well
|
||||
- `IOS_ASC_KEY_ID` as well
|
||||
- `IOS_MATCH_PASSWORD` is used by fastlane match to download the certificates
|
||||
- `IOS_MATCH_REPO_SSH_KEY_BASE64` is used to authenticate with the git repository where the certificates are stored
|
||||
- `IOS_GOOGLE_...`
|
||||
- `IOS_GOOGLE_...`
|
||||
- `IOS_GOOGLE_...`
|
220
frontend/android/Gemfile.lock
Normal file
@ -0,0 +1,220 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
CFPropertyList (3.0.7)
|
||||
base64
|
||||
nkf
|
||||
rexml
|
||||
addressable (2.8.7)
|
||||
public_suffix (>= 2.0.2, < 7.0)
|
||||
artifactory (3.0.17)
|
||||
atomos (0.1.3)
|
||||
aws-eventstream (1.3.0)
|
||||
aws-partitions (1.970.0)
|
||||
aws-sdk-core (3.202.2)
|
||||
aws-eventstream (~> 1, >= 1.3.0)
|
||||
aws-partitions (~> 1, >= 1.651.0)
|
||||
aws-sigv4 (~> 1.9)
|
||||
jmespath (~> 1, >= 1.6.1)
|
||||
aws-sdk-kms (1.88.0)
|
||||
aws-sdk-core (~> 3, >= 3.201.0)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sdk-s3 (1.159.0)
|
||||
aws-sdk-core (~> 3, >= 3.201.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sigv4 (1.9.1)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
babosa (1.0.4)
|
||||
base64 (0.2.0)
|
||||
claide (1.1.0)
|
||||
colored (1.2)
|
||||
colored2 (3.1.2)
|
||||
commander (4.6.0)
|
||||
highline (~> 2.0.0)
|
||||
declarative (0.0.20)
|
||||
digest-crc (0.6.5)
|
||||
rake (>= 12.0.0, < 14.0.0)
|
||||
domain_name (0.6.20240107)
|
||||
dotenv (2.8.1)
|
||||
emoji_regex (3.2.3)
|
||||
excon (0.111.0)
|
||||
faraday (1.10.3)
|
||||
faraday-em_http (~> 1.0)
|
||||
faraday-em_synchrony (~> 1.0)
|
||||
faraday-excon (~> 1.1)
|
||||
faraday-httpclient (~> 1.0)
|
||||
faraday-multipart (~> 1.0)
|
||||
faraday-net_http (~> 1.0)
|
||||
faraday-net_http_persistent (~> 1.0)
|
||||
faraday-patron (~> 1.0)
|
||||
faraday-rack (~> 1.0)
|
||||
faraday-retry (~> 1.0)
|
||||
ruby2_keywords (>= 0.0.4)
|
||||
faraday-cookie_jar (0.0.7)
|
||||
faraday (>= 0.8.0)
|
||||
http-cookie (~> 1.0.0)
|
||||
faraday-em_http (1.0.0)
|
||||
faraday-em_synchrony (1.0.0)
|
||||
faraday-excon (1.1.0)
|
||||
faraday-httpclient (1.0.1)
|
||||
faraday-multipart (1.0.4)
|
||||
multipart-post (~> 2)
|
||||
faraday-net_http (1.0.2)
|
||||
faraday-net_http_persistent (1.2.0)
|
||||
faraday-patron (1.0.0)
|
||||
faraday-rack (1.0.0)
|
||||
faraday-retry (1.0.3)
|
||||
faraday_middleware (1.2.0)
|
||||
faraday (~> 1.0)
|
||||
fastimage (2.3.1)
|
||||
fastlane (2.222.0)
|
||||
CFPropertyList (>= 2.3, < 4.0.0)
|
||||
addressable (>= 2.8, < 3.0.0)
|
||||
artifactory (~> 3.0)
|
||||
aws-sdk-s3 (~> 1.0)
|
||||
babosa (>= 1.0.3, < 2.0.0)
|
||||
bundler (>= 1.12.0, < 3.0.0)
|
||||
colored (~> 1.2)
|
||||
commander (~> 4.6)
|
||||
dotenv (>= 2.1.1, < 3.0.0)
|
||||
emoji_regex (>= 0.1, < 4.0)
|
||||
excon (>= 0.71.0, < 1.0.0)
|
||||
faraday (~> 1.0)
|
||||
faraday-cookie_jar (~> 0.0.6)
|
||||
faraday_middleware (~> 1.0)
|
||||
fastimage (>= 2.1.0, < 3.0.0)
|
||||
gh_inspector (>= 1.1.2, < 2.0.0)
|
||||
google-apis-androidpublisher_v3 (~> 0.3)
|
||||
google-apis-playcustomapp_v1 (~> 0.1)
|
||||
google-cloud-env (>= 1.6.0, < 2.0.0)
|
||||
google-cloud-storage (~> 1.31)
|
||||
highline (~> 2.0)
|
||||
http-cookie (~> 1.0.5)
|
||||
json (< 3.0.0)
|
||||
jwt (>= 2.1.0, < 3)
|
||||
mini_magick (>= 4.9.4, < 5.0.0)
|
||||
multipart-post (>= 2.0.0, < 3.0.0)
|
||||
naturally (~> 2.2)
|
||||
optparse (>= 0.1.1, < 1.0.0)
|
||||
plist (>= 3.1.0, < 4.0.0)
|
||||
rubyzip (>= 2.0.0, < 3.0.0)
|
||||
security (= 0.1.5)
|
||||
simctl (~> 1.6.3)
|
||||
terminal-notifier (>= 2.0.0, < 3.0.0)
|
||||
terminal-table (~> 3)
|
||||
tty-screen (>= 0.6.3, < 1.0.0)
|
||||
tty-spinner (>= 0.8.0, < 1.0.0)
|
||||
word_wrap (~> 1.0.0)
|
||||
xcodeproj (>= 1.13.0, < 2.0.0)
|
||||
xcpretty (~> 0.3.0)
|
||||
xcpretty-travis-formatter (>= 0.0.3, < 2.0.0)
|
||||
gh_inspector (1.1.3)
|
||||
google-apis-androidpublisher_v3 (0.54.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-apis-core (0.11.3)
|
||||
addressable (~> 2.5, >= 2.5.1)
|
||||
googleauth (>= 0.16.2, < 2.a)
|
||||
httpclient (>= 2.8.1, < 3.a)
|
||||
mini_mime (~> 1.0)
|
||||
representable (~> 3.0)
|
||||
retriable (>= 2.0, < 4.a)
|
||||
rexml
|
||||
google-apis-iamcredentials_v1 (0.17.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-apis-playcustomapp_v1 (0.13.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-apis-storage_v1 (0.31.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-cloud-core (1.7.1)
|
||||
google-cloud-env (>= 1.0, < 3.a)
|
||||
google-cloud-errors (~> 1.0)
|
||||
google-cloud-env (1.6.0)
|
||||
faraday (>= 0.17.3, < 3.0)
|
||||
google-cloud-errors (1.4.0)
|
||||
google-cloud-storage (1.47.0)
|
||||
addressable (~> 2.8)
|
||||
digest-crc (~> 0.4)
|
||||
google-apis-iamcredentials_v1 (~> 0.1)
|
||||
google-apis-storage_v1 (~> 0.31.0)
|
||||
google-cloud-core (~> 1.6)
|
||||
googleauth (>= 0.16.2, < 2.a)
|
||||
mini_mime (~> 1.0)
|
||||
googleauth (1.8.1)
|
||||
faraday (>= 0.17.3, < 3.a)
|
||||
jwt (>= 1.4, < 3.0)
|
||||
multi_json (~> 1.11)
|
||||
os (>= 0.9, < 2.0)
|
||||
signet (>= 0.16, < 2.a)
|
||||
highline (2.0.3)
|
||||
http-cookie (1.0.7)
|
||||
domain_name (~> 0.5)
|
||||
httpclient (2.8.3)
|
||||
jmespath (1.6.2)
|
||||
json (2.7.2)
|
||||
jwt (2.8.2)
|
||||
base64
|
||||
mini_magick (4.13.2)
|
||||
mini_mime (1.1.5)
|
||||
multi_json (1.15.0)
|
||||
multipart-post (2.4.1)
|
||||
nanaimo (0.3.0)
|
||||
naturally (2.2.1)
|
||||
nkf (0.2.0)
|
||||
optparse (0.5.0)
|
||||
os (1.1.4)
|
||||
plist (3.7.1)
|
||||
public_suffix (6.0.1)
|
||||
rake (13.2.1)
|
||||
representable (3.2.0)
|
||||
declarative (< 0.1.0)
|
||||
trailblazer-option (>= 0.1.1, < 0.2.0)
|
||||
uber (< 0.2.0)
|
||||
retriable (3.1.2)
|
||||
rexml (3.3.6)
|
||||
strscan
|
||||
rouge (2.0.7)
|
||||
ruby2_keywords (0.0.5)
|
||||
rubyzip (2.3.2)
|
||||
security (0.1.5)
|
||||
signet (0.19.0)
|
||||
addressable (~> 2.8)
|
||||
faraday (>= 0.17.5, < 3.a)
|
||||
jwt (>= 1.5, < 3.0)
|
||||
multi_json (~> 1.10)
|
||||
simctl (1.6.10)
|
||||
CFPropertyList
|
||||
naturally
|
||||
strscan (3.1.0)
|
||||
terminal-notifier (2.0.0)
|
||||
terminal-table (3.0.2)
|
||||
unicode-display_width (>= 1.1.1, < 3)
|
||||
trailblazer-option (0.1.2)
|
||||
tty-cursor (0.7.1)
|
||||
tty-screen (0.8.2)
|
||||
tty-spinner (0.9.3)
|
||||
tty-cursor (~> 0.7)
|
||||
uber (0.1.0)
|
||||
unicode-display_width (2.5.0)
|
||||
word_wrap (1.0.0)
|
||||
xcodeproj (1.25.0)
|
||||
CFPropertyList (>= 2.3.3, < 4.0)
|
||||
atomos (~> 0.1.3)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
nanaimo (~> 0.3.0)
|
||||
rexml (>= 3.3.2, < 4.0)
|
||||
xcpretty (0.3.0)
|
||||
rouge (~> 2.0.7)
|
||||
xcpretty-travis-formatter (1.0.1)
|
||||
xcpretty (~> 0.2, >= 0.0.7)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
x86_64-linux
|
||||
|
||||
DEPENDENCIES
|
||||
fastlane
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.18
|
@ -77,7 +77,7 @@ android {
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
// // Placeholders of keys that are replaced by the build system.
|
||||
manifestPlaceholders += ['MAPS_API_KEY': System.getenv('ANDROID_GOOGLE_MAPS_API_KEY')]
|
||||
manifestPlaceholders += ['MAPS_API_KEY': System.getenv('GOOGLE_MAPS_API_KEY')]
|
||||
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ default_platform(:android)
|
||||
platform :android do
|
||||
|
||||
desc "Deploy a new version to closed testing (play store)"
|
||||
lane :deploy_beta do
|
||||
lane :deploy_testing do
|
||||
build_name = ENV["BUILD_NAME"]
|
||||
build_number = ENV["BUILD_NUMBER"]
|
||||
|
||||
@ -17,8 +17,7 @@ platform :android do
|
||||
)
|
||||
|
||||
upload_to_play_store(
|
||||
track: 'beta',
|
||||
# upload aab files intstead
|
||||
track: 'alpha',
|
||||
skip_upload_apk: true,
|
||||
skip_upload_changelogs: true,
|
||||
aab: "../build/app/outputs/bundle/release/app-release.aab",
|
||||
@ -48,7 +47,6 @@ platform :android do
|
||||
skip_upload_apk: true,
|
||||
skip_upload_changelogs: true,
|
||||
aab: "../build/app/outputs/bundle/release/app-release.aab",
|
||||
metadata_path: "fastlane/metadata",
|
||||
)
|
||||
end
|
||||
end
|
||||
|
@ -0,0 +1,7 @@
|
||||
AnyWay - plan city trips your way
|
||||
|
||||
AnyWay is a mobile application that helps users plan city trips. The app allows users to specify their preferences and constraints, and then generates a personalized itinerary for them. The planning follows some guiding principles:
|
||||
- **Personalization**:The user's preferences should be reflected in the choice of destinations.
|
||||
- **Efficiency**:The itinerary should be optimized for the user's constraints.
|
||||
- **Flexibility**: We aknowledge that tourism is a dynamic activity, and that users may want to change their plans on the go.
|
||||
- **Discoverability**: Tourism is an inherently exploratory activity. Once a rough itinerary is generated, detours and spontaneous decisions should be encouraged.
|
After Width: | Height: | Size: 106 KiB |
After Width: | Height: | Size: 1.3 MiB |
After Width: | Height: | Size: 637 KiB |
After Width: | Height: | Size: 573 KiB |
After Width: | Height: | Size: 175 KiB |
After Width: | Height: | Size: 360 KiB |
@ -1,7 +0,0 @@
|
||||
AnyWay is an application that helps you plan truly unique city trips. When planning a new trip, you can specify your preferences and constraints and anyway generates a personalized itinerary just for you.
|
||||
|
||||
Anyway follows these core principles:
|
||||
- Personalization: Trips should be match your interests - not just the most popular destinations.
|
||||
- Efficiency: Don't just walk in circles! Anyway creates the most efficient route for you.
|
||||
- Flexibility: Vacations are the time to be spontaneous. Anyway lets you update your plans on the go.
|
||||
- Discoverability: Tourism means exploration. Anyway encourages you to take detours and make spontaneous decisions.
|
Before Width: | Height: | Size: 3.0 MiB |
Before Width: | Height: | Size: 4.1 MiB |
Before Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 1.1 MiB |
@ -19,7 +19,7 @@ pluginManagement {
|
||||
|
||||
plugins {
|
||||
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||
id "com.android.application" version "8.1.0" apply false
|
||||
id "com.android.application" version "7.3.0" apply false
|
||||
id "org.jetbrains.kotlin.android" version "2.0.20" apply false
|
||||
}
|
||||
|
||||
|
@ -1,2 +0,0 @@
|
||||
## Vector assets
|
||||
As per https://www.svgrepo.com/collection/pixellove-bordered-vectors/ these icons are licensed under CC0.
|
107
frontend/assets/cat.svg
Normal file
@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 27.5.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 500 500" style="enable-background:new 0 0 500 500;" xml:space="preserve">
|
||||
<g id="OBJECTS">
|
||||
<g>
|
||||
<path style="fill:#F2DBDE;" d="M381.005,363.01c-53.963,8.445-84.441,11.1-138.832,6.101
|
||||
c-54.388-4.998-109.48-25.844-144.743-67.555c-23.468-27.759-36.728-62.943-43.732-98.613c-3.745-19.07-5.754-39.21,0.433-57.635
|
||||
c7.513-22.378,26.565-39.569,48.136-49.156c21.572-9.589,45.552-12.365,69.151-12.944c47.753-1.172,95.706,6.26,140.863,21.831
|
||||
c35.603,12.277,69.954,29.937,96.972,56.171c27.019,26.233,46.213,61.723,47.963,99.341
|
||||
C458.967,298.17,438.434,354.022,381.005,363.01z"/>
|
||||
<g>
|
||||
<path style="fill:#F2BFC6;" d="M314.479,248.209c-22.398,36.41-29.246,81.831-19.597,123.401
|
||||
c27.302-0.242,52.026-3.263,86.124-8.6c57.429-8.989,77.961-64.84,76.211-102.458c-1.503-32.308-15.881-63.041-37.024-87.694
|
||||
C375.546,184.337,337.241,211.21,314.479,248.209z"/>
|
||||
<path style="fill:#F2BFC6;" d="M60.074,229.111c2.232,7.566,4.802,15.029,7.749,22.32c40.138-5.931,78.066-26.379,104.834-56.907
|
||||
c26.459-30.176,41.716-69.876,42.677-109.969c-14.6-1.246-29.267-1.705-43.916-1.345c-11.908,0.292-23.911,1.147-35.655,3.151
|
||||
C136.569,142.478,107.155,198.423,60.074,229.111z"/>
|
||||
<path style="fill:#F2BFC6;" d="M365.131,128.557c-16.748-9.529-34.631-17.233-52.85-23.516
|
||||
c-6.45-2.224-12.962-4.262-19.517-6.153c-1.712,23.304-4.543,46.555-11.914,68.659c-9.236,27.692-26.464,53.808-52.01,67.931
|
||||
c-22.973,12.7-50.376,14.689-74.443,25.169c-21.624,9.417-39.587,25.305-54.36,43.893c8.346,9.381,17.714,17.663,27.862,24.902
|
||||
c16.736-21.461,41.874-37.166,67.161-48.559c35.578-16.03,74.129-26.682,105.739-49.566
|
||||
C334.357,207.023,357.577,169.22,365.131,128.557z"/>
|
||||
</g>
|
||||
</g>
|
||||
<ellipse style="opacity:0.15;fill:#2D3038;" cx="250.223" cy="394.224" rx="109.236" ry="18.917"/>
|
||||
<g>
|
||||
<path style="fill:#2D3038;" d="M305.132,388.442c-0.168,1.158-0.626,2.243-1.458,3.061c-1.863,1.832-4.823,1.724-7.427,1.538
|
||||
c-17.939-1.285-36.017-0.625-53.815,1.965c-7.053,3.155-16.423,3.233-25.275,2.004c-8.853-1.231-17.514-3.684-26.397-4.661
|
||||
c-8.885-0.976-21.867-0.33-26.499,2.758c0,0-7.266,3.996-12.907,12.021c-3.367,4.789-4.105,11.306-2.377,16.899
|
||||
c2.452,7.945,10.312,13.334,18.475,14.912c8.163,1.579,16.603-0.053,24.6-2.327c22.82-6.49,43.805-18.134,66.018-26.468
|
||||
c22.213-8.334,47.017-13.282,69.546-5.844c3.96,1.306,7.879,3.033,10.941,5.866c3.062,2.832,5.173,6.927,4.813,11.081
|
||||
c-0.464,5.356-4.97,9.719-10.061,11.444c-5.092,1.726-10.658,1.275-15.953,0.346c-5.296-0.93-10.554-2.17-15.926-2.414
|
||||
c-20.08-0.909-38.455,4.247-56.124,10.857c-17.669,6.608-35.096,14.21-53.56,18.085c-18.463,3.874-35.807,8.106-51.682-4.186
|
||||
c-20.345-15.753-19.603-41.137-8.091-63.296c5.521-10.629,12.589-18.637,19.416-27.732c-1.72-12.542-6.898-24.945-9.467-37.525
|
||||
c-4.135-20.25-1.309-41.854,7.666-61.314c5.614-15.439,11.257-30.942,19.093-45.38c7.835-14.438,18.007-27.88,31.297-37.536
|
||||
c13.289-9.656,29.927-15.279,46.993-13.222c7.787-8.403,16.038-16.377,24.703-23.871c-1.319-7.29-1.183-14.637,0.584-20.961
|
||||
c-4.077-8.872-8.2-17.907-9.54-27.579c-0.835-6.027-0.441-12.408,1.577-17.991c1.878-5.198,8.452-6.799,12.542-3.08
|
||||
c6.673,6.07,12.683,12.869,17.891,20.235c18.398-4.802,38.164-4.231,56.264,1.583c6.473-8.017,14.398-14.861,23.286-20.075
|
||||
c2.366-1.388,5.533-2.613,7.657-0.875c1.683,1.377,1.736,3.89,1.592,6.059c-0.815,12.217-3.418,24.313-8.016,36.577
|
||||
c4.862,15.779,0.82,33.862-9.812,46.412c-2.168,11.956,1.193,24.438,2.504,36.665c2.294,21.385-1.98,43.411-12.271,62.744
|
||||
c-2.4,4.508-5.754,8.444-9.863,11.477c-1.71,1.263-3.38,2.581-5.006,3.951c-5.172,20.881-10.139,41.311-15.351,62.281
|
||||
c2.061,7.78,4.487,15.496,7.272,23.126c3.209-0.899,6.478-1.696,9.816-1.809c3.896-0.132,7.942,0.744,11.024,3.131
|
||||
c2.308,1.785,3.979,4.375,4.658,7.212c0.484,2.028,0.445,4.26-0.563,6.086c-0.663,1.203-1.81,2.171-3.102,2.583
|
||||
c0.454,1.78,0.565,3.616,0.106,5.385c-0.778,3.004-3.622,5.6-6.675,5.375c-0.047,0.112-0.097,0.223-0.151,0.333
|
||||
c-0.979,1.985-3.08,3.228-5.239,3.714c-2.063,0.464-4.207,0.333-6.319,0.174c-0.138,0.225-0.3,0.437-0.489,0.633
|
||||
c-1.556,1.603-4.16,1.338-6.346,0.87c-3.015-0.645-6.04-1.471-8.688-3.051c-2.647-1.583-4.906-4.013-5.707-6.991
|
||||
c-1.237-4.607,2.111-10.097,0.151-14.313c-3.538-7.609-7.733-14.893-12.004-22.126c-8.712,7.077-18.162,13.242-28.147,18.367
|
||||
c6.95-0.974,14.248-1.345,21.476-0.293c3.273,0.475,6.596,1.283,9.285,3.208c2.689,1.924,4.631,5.173,4.214,8.453
|
||||
c-0.34,2.664-2.596,5.054-5.156,5.449"/>
|
||||
<path style="fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" d="M151.465,379.089
|
||||
c0.578-3.877,0.614-7.729,0.28-11.566"/>
|
||||
<path style="fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" d="M296.431,98.602
|
||||
c1.739,2.591,3.381,5.247,4.918,7.962"/>
|
||||
<path style="fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" d="M273.736,153.553
|
||||
c-0.645-1.929-1.188-3.891-1.625-5.865"/>
|
||||
<path style="fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" d="M295.23,106.811
|
||||
c-4.87-7.904-10.55-15.309-16.923-22.061c-1.834-1.943-4.156-3.987-6.799-3.598c-2.928,0.431-4.574,3.626-5.147,6.53
|
||||
c-1.629,8.254,1.474,16.627,4.521,24.47"/>
|
||||
<path style="fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" d="M352.846,98.327
|
||||
c1.084,0.372,2.162,0.763,3.232,1.174"/>
|
||||
<path style="fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" d="M363.545,168.179
|
||||
c-1.077,1.107-2.211,2.161-3.399,3.155"/>
|
||||
<path style="fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" d="M295.583,130.136
|
||||
c3.86-4.907,10.772-7.181,16.791-5.521c6.019,1.659,10.791,7.151,11.446,13.054c-4.594,3.601-11.6,3.717-16.311,0.268
|
||||
c-3.162-2.315-5.105-6.101-5.423-9.993"/>
|
||||
<path style="fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" d="M363.109,126.785
|
||||
c-1.79-2.631-5.159-4.002-8.321-3.646c-3.162,0.356-6.042,2.317-7.787,4.979c-1.743,2.662-2.395,5.96-1.828,9.854
|
||||
c4.738,1.952,10.727,0.164,13.621-4.066c1.462-2.137,2.057-4.785,1.832-7.36"/>
|
||||
<path style="fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" d="M350.957,171.048
|
||||
c-4.278,4.378-10.749,6.497-16.787,5.499"/>
|
||||
<path style="fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" d="M338.68,282.717
|
||||
c-5.42,4.867-10.31,10.327-14.541,16.258"/>
|
||||
<path style="fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" d="M333.834,368.351
|
||||
c0.757,2.017,1.54,4.028,2.348,6.032c2.26-0.589,4.541-1.183,6.876-1.268c2.333-0.084,4.757,0.381,6.656,1.74
|
||||
c1.559,1.116,2.664,2.753,3.552,4.452c0.261,0.499,0.505,1.013,0.727,1.536"/>
|
||||
<path style="fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" d="M317.138,283.315
|
||||
c0.476,18.805,3.038,37.553,7.633,55.961"/>
|
||||
<path style="fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" d="M337.823,376.837
|
||||
c2.877-0.595,5.878,0.99,7.67,3.316c1.791,2.327,2.567,5.273,3.025,8.174c0.191,1.214,0.327,2.48,0.209,3.695"/>
|
||||
<path style="fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" d="M327.236,380.633
|
||||
c3.086-0.38,6.102,1.606,7.733,4.252c1.632,2.645,2.112,5.835,2.285,8.939c0.04,0.721,0.054,1.476-0.027,2.204"/>
|
||||
<path style="fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" d="M305.059,385.808
|
||||
c-0.036-0.193-0.079-0.385-0.128-0.573c-1.058-4.111-4.728-7.422-8.927-8.052"/>
|
||||
<g>
|
||||
<path style="fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" d="M250.442,264.812
|
||||
c-1.67-3.125-3.183-6.325-4.488-9.622c-5.098-12.883-6.92-27.047-5.248-40.801"/>
|
||||
<path style="fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" d="M302.266,351.248
|
||||
c-7.667-12.944-15.022-25.405-19.496-39.762"/>
|
||||
<path style="fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" d="M272.435,372.065
|
||||
c-3.368,0.554-6.637,1.226-9.757,1.918c10.852-22.715,21.971-46.794,19.913-71.883c-0.826-10.055-4.036-20.316-11.156-27.463
|
||||
c-8.522-8.553-21.576-11.406-33.547-9.827c-22.022,2.903-41.327,20.57-46.167,42.248"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" d="M328.579,152.076
|
||||
c1.379-0.341,2.796,0.501,3.736,1.565c0.942,1.065,1.588,2.366,2.551,3.41c0.963,1.044,2.43,1.826,3.784,1.398
|
||||
c1.002-0.317,1.702-1.217,2.207-2.139c0.504-0.921,0.888-1.923,1.572-2.721c1.237-1.447,3.432-1.978,5.192-1.258"/>
|
||||
<path style="fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" d="M360.735,158.173
|
||||
c-2.16,5.007-7.325,8.57-12.773,8.812c-1.946,0.086-3.967-0.245-5.593-1.317c-1.872-1.234-2.979-3.253-3.85-5.361
|
||||
c-0.089,1.146-0.496,2.29-1.133,3.25c-1.229,1.854-3.175,3.116-5.189,4.059c-3.3,1.546-7.007,2.373-10.616,1.879
|
||||
c-3.611-0.495-7.099-2.413-9.07-5.477"/>
|
||||
<path style="fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" d="M338.276,158.534
|
||||
c0,0,0.176,1.073,0.244,1.773"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 9.5 KiB |
@ -1,79 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
|
||||
<title>cel-snow-globe</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs>
|
||||
|
||||
</defs>
|
||||
<g id="General" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="SLICES-64px" transform="translate(-450.000000, 0.000000)">
|
||||
|
||||
</g>
|
||||
<g id="ICONS" transform="translate(-445.000000, 5.000000)">
|
||||
<g id="cel-snow-globe" transform="translate(450.000000, 2.000000)">
|
||||
<path d="M46,44 C48.209,44 50,45.791 50,48 L50,52 L2,52 L2,48 C2,45.791 3.791,44 6,44 L46,44 Z" id="Fill-1055" fill="#EEC261">
|
||||
|
||||
</path>
|
||||
<path d="M7.2402,44.002 C2.7562,39.33 0.0002,32.987 0.0002,26 C0.0002,11.641 11.6402,0 26.0002,0 C40.3592,0 52.0002,11.641 52.0002,26 C52.0002,32.986 49.2442,39.33 44.7602,44.001 L7.2402,44.002 Z" id="Fill-1056" fill="#B6E0F2">
|
||||
|
||||
</path>
|
||||
<path d="M38,37 C38,33.134 34.866,30 31,30 C27.134,30 24,33.134 24,37 C24,40.866 27.134,44 31,44 C34.866,44 38,40.866 38,37" id="Fill-1057" fill="#E9EFFA">
|
||||
|
||||
</path>
|
||||
<path d="M26,25 C26,22.238 28.239,20 31,20 C33.761,20 36,22.238 36,25 C36,27.762 33.761,30 31,30 C28.239,30 26,27.762 26,25" id="Fill-1058" fill="#E9EFFA">
|
||||
|
||||
</path>
|
||||
<path d="M38,37 C38,33.134 34.866,30 31,30 C27.134,30 24,33.134 24,37 C24,40.866 27.134,44 31,44 C34.866,44 38,40.866 38,37 Z" id="Stroke-1059" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M26,25 C26,22.238 28.239,20 31,20 C33.761,20 36,22.238 36,25 C36,27.762 33.761,30 31,30 C28.239,30 26,27.762 26,25 Z" id="Stroke-1060" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M46,44 C48.209,44 50,45.791 50,48 L50,52 L2,52 L2,48 C2,45.791 3.791,44 6,44 L46,44 Z" id="Stroke-1061" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M7.2402,44.002 C2.7562,39.33 0.0002,32.987 0.0002,26 C0.0002,11.641 11.6402,0 26.0002,0 C40.3592,0 52.0002,11.641 52.0002,26 C52.0002,32.986 49.2442,39.33 44.7602,44.001" id="Stroke-1062" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M8,24 C8,14.059 16.059,6 26,6" id="Stroke-1063" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M20,28 L26.061,32.04" id="Stroke-1064" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M42,28 L35.939,32.04" id="Stroke-1065" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M42,25 L42,28" id="Stroke-1066" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M45,28 L42,28" id="Stroke-1067" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M20,25 L20,28" id="Stroke-1068" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M17,28 L20,28" id="Stroke-1069" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M10.02,31.0098 C10.02,31.5688 9.568,32.0208 9.01,32.0208 C8.452,32.0208 8,31.5688 8,31.0098 C8,30.4518 8.452,29.9998 9.01,29.9998 C9.568,29.9998 10.02,30.4518 10.02,31.0098 Z" id="Stroke-1070" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M22.02,15.0098 C22.02,15.5688 21.568,16.0208 21.01,16.0208 C20.452,16.0208 20,15.5688 20,15.0098 C20,14.4518 20.452,13.9998 21.01,13.9998 C21.568,13.9998 22.02,14.4518 22.02,15.0098 Z" id="Stroke-1071" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M44.02,17.0098 C44.02,17.5688 43.568,18.0208 43.01,18.0208 C42.452,18.0208 42,17.5688 42,17.0098 C42,16.4518 42.452,15.9998 43.01,15.9998 C43.568,15.9998 44.02,16.4518 44.02,17.0098 Z" id="Stroke-1072" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M18.02,37.0098 C18.02,37.5688 17.568,38.0208 17.01,38.0208 C16.452,38.0208 16,37.5688 16,37.0098 C16,36.4518 16.452,35.9998 17.01,35.9998 C17.568,35.9998 18.02,36.4518 18.02,37.0098 Z" id="Stroke-1073" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M36.02,9.0098 C36.02,9.5688 35.568,10.0208 35.01,10.0208 C34.452,10.0208 34,9.5688 34,9.0098 C34,8.4518 34.452,7.9998 35.01,7.9998 C35.568,7.9998 36.02,8.4518 36.02,9.0098 Z" id="Stroke-1074" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 5.1 KiB |
273
frontend/assets/city.svg
Normal file
@ -0,0 +1,273 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 27.5.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 1000 700" style="enable-background:new 0 0 1000 700;" xml:space="preserve">
|
||||
<g id="Shadow">
|
||||
<g style="opacity:0.1;">
|
||||
<path style="fill:#38415C;" d="M186.919,556.734c0,0.331,0.541,0.599,1.208,0.599c0.667,0,1.208-0.268,1.208-0.599
|
||||
c0-0.331-0.541-0.599-1.208-0.599C187.46,556.135,186.919,556.403,186.919,556.734z"/>
|
||||
<path style="fill:#38415C;" d="M957.699,446.328h-12.196h-37.267h-8.131h-4.525h-22.106h-29.729h-8.01h-8.921h-7.462H777.69h-5.38
|
||||
h-8.517h-13.921h-24.898h-0.367h-35.201h-33.29h-13.405h-8.642h-18.387h-20.084H584.19h-2.542h-5.421h-37.944h-7.453h-2.757
|
||||
h-2.757h-1.428h-8.748h-5.514h-10.175h-0.905h-4.609h-10.175h-5.514h-10.175h-2.757h-2.757h-27.938h-8.05h-29.96h-6.713h-18.964
|
||||
h-11.234h-48.644h-12.099h-10.229h-20.764h-12.382h-3.512h-23.242h-5.943h-13.266h-10.795h-35.413h-16.467h-4.656h-8.696h-25.877
|
||||
H89.054h-4.763H72.026h-7.508H53.821H42.302v9.376h11.519v6.41h10.696v6.835h19.774v2.177h20.658v9.405h17.084v-5.919h11.557
|
||||
v10.475h3.789v11.69h11.18v9.823h-4.017v1.763h7.066v4.785h23.433v28.254h-1.845v1.897h4.028v2.429h4.636v0.913v2.777v2.41h5.594
|
||||
v4.306h0.673l0,0h0.673v-4.306h3.015l1.823-2.41h12.206v-3.69h31.948V543.3h4.028v-1.897h-1.845V484.37h15.302v40.617h1.509v3.023
|
||||
h2.811v10.012h1.016v-10.012h2.287v7.997h1.017v-7.997h4.828v-3.023h6.098v-10.569h11.445v-0.743h-1.492v-2.116h7.56v32.974
|
||||
h-1.078v0.849h7.678v5.101h-0.992v0.817h7.047v2.933h-1.099v0.627h3.502v2.77h3.348v5.513h0.402h0.398h0.314v-5.513h1.354v9.889
|
||||
h0.402h0.399h0.314v-9.889h0.451h2.897v-2.77h3.034v-0.627h-0.632v-2.933h7.047v-0.817h-0.992v-5.101h7.678v-0.849h-1.078v-43.096
|
||||
h23.505v-5.982h8.399v31.88h-4.954v0.806h4.954v1.443h6.279v2.37h30.344v27.318h7.165v21.803h13.871V593h1.952v-11.927h4.298
|
||||
v9.528h1.952v-9.528h21.941v-12.964h3.982v-8.839h11.148v-32.999h4.318v-7.629l6.342,0.769v1.742h5.514v-1.073l10.175,1.234v1.969
|
||||
h5.514v-1.3l9.332,1.131v9.523h2.491v16.539h11.982v6.297h6.46v5.29h2.267v9.068h0.586v-9.068h2.267v-5.29h6.46v-6.297h12.075
|
||||
v-16.539h2.399v-45.67l5.467,13.925h5.729v12.219h-2.645v0.527h31.278v6.75h-3.52v0.763h-1.791v2.08h8.284v2.313h-1.087v0.668
|
||||
h18.198v-0.668h-1.087v-2.313h23.966c0.802,1.935,2.023,3.811,3.668,5.596l-3.992,0.913c-0.688-0.732-2.184-1.239-3.92-1.239
|
||||
c-2.388,0-4.324,0.96-4.324,2.143c0,1.183,1.936,2.143,4.324,2.143c2.388,0,4.324-0.96,4.324-2.143
|
||||
c0-0.239-0.08-0.468-0.225-0.683l4.015-0.919c2.595,2.749,6.165,5.281,10.623,7.491c0.352,0.174,0.709,0.346,1.069,0.515
|
||||
l-3.154,1.668c-0.76-0.329-1.753-0.528-2.841-0.528c-2.388,0-4.324,0.959-4.324,2.143s1.936,2.143,4.324,2.143
|
||||
c2.388,0,4.324-0.959,4.324-2.143c0-0.559-0.432-1.068-1.139-1.449l3.16-1.671c5.36,2.471,11.576,4.337,18.308,5.527l-1.744,2.453
|
||||
c-0.378-0.054-0.777-0.083-1.19-0.083c-2.388,0-4.324,0.96-4.324,2.143c0,1.183,1.936,2.143,4.324,2.143
|
||||
c2.388,0,4.324-0.96,4.324-2.143c0-0.895-1.107-1.662-2.68-1.982l1.743-2.451c5.551,0.953,11.445,1.449,17.493,1.449
|
||||
c0.498,0,0.995-0.003,1.491-0.01l0.198,3.017c-2.096,0.148-3.707,1.041-3.707,2.121c0,1.183,1.936,2.143,4.324,2.143
|
||||
c2.388,0,4.324-0.96,4.324-2.143c0-1.184-1.936-2.143-4.324-2.143c-0.046,0-0.091,0.001-0.137,0.002l-0.197-3.004
|
||||
c2.456-0.044,4.881-0.173,7.265-0.378l-2.223,24.735l79.948-8.225v-43.336h13.883v22.309h24.985v8.902h1.355v-8.902h2.795v16.446
|
||||
h1.355v-16.446h3.219v11.855h1.355v-11.855h4.235v-54.059h12.874V506.6h2.033v3.715h2.033v2.582h14.483v-2.582h2.033V506.6h7.369
|
||||
v1.594h3.557V506.6h1.259v4.262h5.082V506.6h1.452l3.161-11.593h11.528v5.526h0.762v-5.526h4.32v6.746h0.762v-6.746h6.25v-1.567
|
||||
h-1.592v-17.317h12.874l1.507-4.997h10.931v-9.012h11.954v-6.86h12.196V446.328z M653.829,518.335l-11.117,0.179v-7.937h2.055
|
||||
v-0.76h-2.055v-0.593l13.295,2.426c-1.417,1.94-2.19,4.031-2.19,6.21C653.816,518.019,653.821,518.177,653.829,518.335z
|
||||
M689.289,499.58c-4.354,0.083-8.516,0.542-12.36,1.312l-5.314-6.414v-0.42h5.082v4.786h5.082v-4.786h7.148L689.289,499.58z
|
||||
M702.329,517.554l-8.713,0.14c-0.026-0.114-0.079-0.224-0.155-0.328l9.073-2.076L702.329,517.554z M666.025,494.058v0.401
|
||||
c-0.325,0.085-0.657,0.163-0.979,0.251l-0.713-0.651H666.025z M666.025,495.263v0.341l-0.291-0.266
|
||||
C665.83,495.311,665.929,495.289,666.025,495.263z M666.025,496.603v2.241h2.454l3.554,3.247c-2.98,0.871-5.693,1.943-8.062,3.179
|
||||
l-10.904-5.064c0.33-0.173,0.666-0.344,1.007-0.513c3.276-1.624,6.914-3.003,10.823-4.12L666.025,496.603z M672.377,502.405
|
||||
l15.07,13.768l-22.95-10.659C666.813,504.306,669.465,503.258,672.377,502.405z M669.572,498.844h2.043v-3.739l4.87,5.877
|
||||
c-1.242,0.259-2.449,0.55-3.618,0.872L669.572,498.844z M691.664,494.058v4.786h12.332l-1.224,1.721
|
||||
c-3.776-0.648-7.828-1.001-12.044-1.001c-0.32,0-0.64,0.002-0.959,0.006l-0.361-5.512H691.664z M703.939,499.641l-0.101,1.127
|
||||
c-0.206-0.039-0.404-0.087-0.612-0.124L703.939,499.641z M702.896,511.25l-8.307,4.394l8.619-7.874L702.896,511.25z
|
||||
M702.863,511.616l-0.306,3.407l-9.299,2.127c-0.053-0.046-0.11-0.09-0.172-0.133l0.598-0.547L702.863,511.616z M693.364,518.468
|
||||
l8.74,1.595l-0.252,2.801l-8.846-4.108C693.147,518.667,693.268,518.571,693.364,518.468z M693.53,518.245
|
||||
c0.056-0.1,0.091-0.205,0.102-0.312l8.676-0.14l-0.182,2.021L693.53,518.245z M656.116,486.551l-11.415-10.428h11.415V486.551z
|
||||
M656.116,487.55v4.746h-1.779v1.763h8.903l0.969,0.885c-4.029,1.15-7.778,2.571-11.154,4.243
|
||||
c-0.352,0.175-0.698,0.352-1.039,0.53l-3.311-1.538c0.63-0.372,1.01-0.852,1.01-1.376c0-1.184-1.936-2.143-4.324-2.143
|
||||
c-1.018,0-1.941,0.182-2.68,0.473v-5.035h2.055v-0.76h-2.055v-9.479h2.055v-0.76h-2.055v-2.977h0.897L656.116,487.55z
|
||||
M642.711,500.338h2.055v-0.76h-2.055v-1.104c0.739,0.292,1.662,0.473,2.68,0.473c1.158,0,2.209-0.226,2.985-0.593l3.31,1.537
|
||||
c-3.677,1.959-6.684,4.15-8.975,6.503V500.338z M642.711,508.163c2.337-2.844,5.703-5.479,10.027-7.784l10.906,5.065
|
||||
c-3.215,1.722-5.771,3.749-7.47,5.983l-13.463-2.457V508.163z M664.17,505.688l24.004,11.148l0.198,0.181
|
||||
c-0.107,0.074-0.2,0.152-0.279,0.235l-31.242-5.701C658.515,509.362,661.02,507.375,664.17,505.688z M673.21,502.168
|
||||
c1.146-0.316,2.33-0.602,3.548-0.855l12.647,15.264c-0.111,0.028-0.218,0.06-0.32,0.094L673.21,502.168z M677.203,501.222
|
||||
c3.766-0.755,7.844-1.204,12.11-1.286l1.082,16.492c-0.187,0.011-0.369,0.03-0.544,0.057L677.203,501.222z M689.793,499.928
|
||||
c0.311-0.004,0.623-0.006,0.935-0.006c4.131,0,8.103,0.346,11.804,0.981l-11.067,15.563c-0.19-0.025-0.388-0.04-0.591-0.045
|
||||
L689.793,499.928z M702.985,500.982c0.278,0.05,0.543,0.112,0.818,0.165l-0.497,5.535l-10.935,9.99
|
||||
c-0.142-0.048-0.294-0.09-0.453-0.126L702.985,500.982z M692.678,518.929l9.146,4.247l-0.629,7.002l-9.143-11.035
|
||||
C692.279,519.085,692.49,519.013,692.678,518.929z M656.683,511.774l31.244,5.702c-0.056,0.1-0.091,0.204-0.102,0.312
|
||||
l-33.276,0.536c-0.008-0.154-0.012-0.309-0.012-0.464C654.537,515.724,655.295,513.675,656.683,511.774z M687.841,518.026
|
||||
c0.026,0.114,0.079,0.224,0.155,0.328l-30.225,6.916c-1.892-2.059-3.018-4.325-3.204-6.708L687.841,518.026z M688.199,518.57
|
||||
c0.106,0.092,0.231,0.178,0.373,0.257l-22.753,12.035c-3.243-1.527-5.915-3.348-7.845-5.376L688.199,518.57z M688.923,518.989
|
||||
c0.188,0.074,0.394,0.137,0.616,0.186l-11.067,15.563c-4.604-0.824-8.776-2.098-12.301-3.714L688.923,518.989z M689.992,519.254
|
||||
c0.19,0.024,0.388,0.04,0.591,0.045l1.082,16.493c-0.311,0.004-0.623,0.006-0.936,0.006c-4.131,0-8.102-0.346-11.804-0.98
|
||||
L689.992,519.254z M691.063,519.291c0.187-0.011,0.369-0.03,0.544-0.057l9.537,11.51l-0.39,4.342
|
||||
c-2.753,0.394-5.632,0.641-8.61,0.697L691.063,519.291z M640.035,523.229h7.987v-2.08h-1.791v-0.763h-3.52v-1.635l11.136-0.179
|
||||
c0.189,2.432,1.339,4.745,3.27,6.846l-13.578,3.106C641.982,526.835,640.816,525.059,640.035,523.229z M654.074,536.027
|
||||
c-4.336-2.149-7.809-4.612-10.333-7.285l13.579-3.107c1.969,2.07,4.697,3.929,8.007,5.487l-10.218,5.404
|
||||
C654.761,536.362,654.415,536.196,654.074,536.027z M655.459,536.689l10.219-5.405c3.597,1.65,7.855,2.95,12.553,3.791
|
||||
l-4.97,6.989C666.716,540.907,660.672,539.092,655.459,536.689z M690.728,543.552c-5.882,0-11.614-0.483-17.013-1.409l4.97-6.989
|
||||
c3.776,0.648,7.828,1.001,12.043,1.001c0.321,0,0.64-0.002,0.959-0.006l0.485,7.393
|
||||
C691.692,543.549,691.211,543.552,690.728,543.552z M692.653,543.535l-0.485-7.395c2.956-0.057,5.813-0.299,8.553-0.681
|
||||
l-0.69,7.679C697.611,543.354,695.148,543.49,692.653,543.535z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Object">
|
||||
<g style="opacity:0.3;">
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="207.5072" y1="393.376" x2="207.5072" y2="229.7061">
|
||||
<stop offset="0" style="stop-color:#403E40"/>
|
||||
<stop offset="0.1275" style="stop-color:#4E4D4E"/>
|
||||
<stop offset="0.3124" style="stop-color:#5A5A5A"/>
|
||||
<stop offset="0.5479" style="stop-color:#626262"/>
|
||||
<stop offset="1" style="stop-color:#646464"/>
|
||||
</linearGradient>
|
||||
<polygon style="fill:url(#SVGID_1_);" points="175.04,393.376 239.974,393.376 239.974,259.43 241.819,259.43 241.819,255.601
|
||||
237.792,255.601 237.792,250.701 205.844,250.701 205.844,243.255 193.638,243.255 191.815,238.393 188.799,238.393
|
||||
188.799,229.706 188.126,229.706 187.454,229.706 187.454,238.393 181.859,238.393 181.859,243.255 181.859,248.859
|
||||
181.859,250.701 177.223,250.701 177.223,255.601 173.195,255.601 173.195,259.43 175.04,259.43 "/>
|
||||
|
||||
<linearGradient id="SVGID_00000000931258187104496080000017865145222397382034_" gradientUnits="userSpaceOnUse" x1="188.1266" y1="229.7061" x2="188.1266" y2="227.2891">
|
||||
<stop offset="0" style="stop-color:#403E40"/>
|
||||
<stop offset="0.1275" style="stop-color:#4E4D4E"/>
|
||||
<stop offset="0.3124" style="stop-color:#5A5A5A"/>
|
||||
<stop offset="0.5479" style="stop-color:#626262"/>
|
||||
<stop offset="1" style="stop-color:#646464"/>
|
||||
</linearGradient>
|
||||
<path style="fill:url(#SVGID_00000000931258187104496080000017865145222397382034_);" d="M189.335,228.498
|
||||
c0-0.668-0.541-1.209-1.209-1.209c-0.667,0-1.208,0.541-1.208,1.209c0,0.667,0.541,1.208,1.208,1.208
|
||||
C188.794,229.706,189.335,229.165,189.335,228.498z"/>
|
||||
|
||||
<linearGradient id="SVGID_00000036247364810958532620000001993945857249512106_" gradientUnits="userSpaceOnUse" x1="508.9194" y1="421.4165" x2="508.9194" y2="155.3276">
|
||||
<stop offset="0" style="stop-color:#403E40"/>
|
||||
<stop offset="0.1275" style="stop-color:#4E4D4E"/>
|
||||
<stop offset="0.3124" style="stop-color:#5A5A5A"/>
|
||||
<stop offset="0.5479" style="stop-color:#626262"/>
|
||||
<stop offset="1" style="stop-color:#646464"/>
|
||||
</linearGradient>
|
||||
<polygon style="fill:url(#SVGID_00000036247364810958532620000001993945857249512106_);" points="777.689,401.218 777.689,221.14
|
||||
697.741,204.545 706.501,401.218 471.904,401.218 471.904,289.958 467.586,289.958 467.586,223.38 456.438,223.38
|
||||
456.438,205.547 452.456,205.547 452.456,179.391 430.514,179.391 430.514,160.168 428.562,160.168 428.562,179.391
|
||||
424.264,179.391 424.264,155.328 422.311,155.328 422.311,179.391 408.44,179.391 408.44,223.38 401.275,223.38 401.275,289.958
|
||||
395.133,289.958 395.133,401.218 332.748,401.218 332.748,253.114 333.825,253.114 333.825,251.402 326.147,251.402
|
||||
326.147,241.111 327.14,241.111 327.14,239.463 320.092,239.463 320.092,233.547 320.725,233.547 320.725,232.282 317.69,232.282
|
||||
317.69,226.693 314.794,226.693 314.343,226.693 314.343,206.742 314.029,206.742 313.63,206.742 313.228,206.742
|
||||
313.228,226.693 311.874,226.693 311.874,215.571 311.56,215.571 311.161,215.571 310.759,215.571 310.759,226.693
|
||||
307.411,226.693 307.411,232.282 303.909,232.282 303.909,233.547 305.009,233.547 305.009,239.463 297.962,239.463
|
||||
297.962,241.111 298.954,241.111 298.954,251.402 291.276,251.402 291.276,253.114 292.354,253.114 292.354,401.218
|
||||
84.29,401.218 84.29,421.417 933.548,421.417 933.548,401.218 "/>
|
||||
</g>
|
||||
|
||||
<linearGradient id="SVGID_00000121963338060960119620000016097684000583641491_" gradientUnits="userSpaceOnUse" x1="499.6613" y1="451.2495" x2="499.6613" y2="202.0752">
|
||||
<stop offset="0.0815" style="stop-color:#403E40"/>
|
||||
<stop offset="0.4715" style="stop-color:#444244"/>
|
||||
<stop offset="0.8768" style="stop-color:#504F50"/>
|
||||
<stop offset="1" style="stop-color:#555455"/>
|
||||
</linearGradient>
|
||||
<path style="fill:url(#SVGID_00000121963338060960119620000016097684000583641491_);" d="M918.278,419.4v-18.183h-25.56
|
||||
l-9.674-71.571h-1.452v-8.598h-5.082v8.598h-1.259v-3.216h-3.557v3.216h-7.369v-7.496h-2.033v-5.209h-14.483v5.209h-2.033v7.496
|
||||
h-2.033v42.986h-12.874V263.564h-4.235v-23.92h-1.355v23.92h-3.219v-33.181h-1.355v33.181h-2.795v-17.961h-1.355v17.961h-24.985
|
||||
v77.418h-27.78v50.154h-25.944l-20.601-37.972c3.473-2,6.738-4.405,9.735-7.193l4.225,4.508c-0.907,0.793-1.481,1.957-1.481,3.256
|
||||
c0,2.388,1.936,4.324,4.324,4.324c2.388,0,4.324-1.936,4.324-4.324c0-2.388-1.936-4.324-4.324-4.324
|
||||
c-0.916,0-1.764,0.285-2.463,0.771l-4.255-4.54c0.36-0.341,0.717-0.687,1.069-1.039c4.458-4.459,8.028-9.568,10.623-15.114
|
||||
l4.705,2.172c-0.086,0.339-0.131,0.693-0.131,1.059c0,2.388,1.936,4.324,4.324,4.324c2.388,0,4.324-1.936,4.324-4.324
|
||||
c0-2.388-1.936-4.324-4.324-4.324c-1.852,0-3.432,1.165-4.048,2.803l-4.648-2.146c2.866-6.273,4.489-13.092,4.744-20.153
|
||||
l5.065,0.165c0.062,2.334,1.972,4.207,4.321,4.207c2.388,0,4.324-1.936,4.324-4.324c0-2.388-1.936-4.324-4.324-4.324
|
||||
c-2.266,0-4.123,1.743-4.308,3.961l-5.064-0.165c0.013-0.496,0.021-0.993,0.021-1.491c0-6.303-1.088-12.438-3.173-18.192
|
||||
l4.231-1.558c0.664,1.533,2.191,2.606,3.968,2.606c2.388,0,4.324-1.936,4.324-4.324c0-2.388-1.936-4.324-4.324-4.324
|
||||
c-2.388,0-4.324,1.936-4.324,4.324c0,0.44,0.066,0.866,0.189,1.267l-4.229,1.557c-2.41-6.464-6.085-12.437-10.898-17.611
|
||||
l3.31-3.102c0.776,0.741,1.827,1.197,2.985,1.197c2.388,0,4.324-1.935,4.324-4.324c0-2.388-1.936-4.324-4.324-4.324
|
||||
c-2.388,0-4.324,1.936-4.324,4.324c0,1.057,0.38,2.025,1.01,2.776l-3.31,3.102c-0.341-0.36-0.687-0.717-1.039-1.069
|
||||
c-5.012-5.013-10.848-8.903-17.201-11.546l1.821-4.434c0.413,0.131,0.853,0.203,1.309,0.203c2.388,0,4.324-1.936,4.324-4.324
|
||||
c0-2.388-1.936-4.324-4.324-4.324c-2.388,0-4.324,1.936-4.324,4.324c0,1.762,1.054,3.276,2.566,3.95l-1.816,4.423
|
||||
c-5.685-2.304-11.775-3.615-18.057-3.842l0.197-6.06c0.046,0.001,0.091,0.003,0.137,0.003c2.388,0,4.324-1.936,4.324-4.324
|
||||
c0-2.388-1.936-4.324-4.324-4.324c-2.388,0-4.324,1.936-4.324,4.324c0,2.179,1.611,3.98,3.707,4.279l-0.198,6.086
|
||||
c-0.496-0.014-0.993-0.021-1.491-0.021c-6.048,0-11.942,1.001-17.493,2.925l-1.743-4.946c1.573-0.647,2.68-2.193,2.68-4
|
||||
c0-2.388-1.936-4.324-4.324-4.324c-2.388,0-4.324,1.936-4.324,4.324c0,2.388,1.936,4.324,4.324,4.324
|
||||
c0.413,0,0.812-0.059,1.19-0.167l1.744,4.948c-6.732,2.401-12.948,6.166-18.308,11.152l-3.16-3.372
|
||||
c0.707-0.77,1.139-1.796,1.139-2.923c0-2.388-1.936-4.324-4.324-4.324c-2.388,0-4.324,1.935-4.324,4.324
|
||||
c0,2.388,1.936,4.324,4.324,4.324c1.088,0,2.081-0.402,2.841-1.065l3.154,3.366c-0.36,0.341-0.717,0.688-1.069,1.04
|
||||
c-4.458,4.458-8.028,9.568-10.623,15.114l-4.015-1.854c0.146-0.433,0.225-0.896,0.225-1.377c0-2.388-1.936-4.324-4.324-4.324
|
||||
c-2.388,0-4.324,1.936-4.324,4.324c0,2.388,1.936,4.324,4.324,4.324c1.736,0,3.232-1.023,3.92-2.5l3.992,1.843
|
||||
c-2.865,6.273-4.489,13.093-4.744,20.153l-5.154-0.167c-0.064-2.333-1.973-4.204-4.321-4.204c-2.388,0-4.324,1.936-4.324,4.324
|
||||
c0,2.388,1.936,4.324,4.324,4.324c2.267,0,4.125-1.744,4.308-3.963l5.153,0.167c-0.013,0.496-0.021,0.993-0.021,1.491
|
||||
c0,6.302,1.088,12.438,3.173,18.191l-4.231,1.558c-0.664-1.533-2.191-2.606-3.969-2.606c-2.388,0-4.324,1.936-4.324,4.324
|
||||
c0,2.388,1.936,4.324,4.324,4.324c2.388,0,4.324-1.936,4.324-4.324c0-0.44-0.066-0.866-0.189-1.266l4.229-1.557
|
||||
c2.409,6.464,6.084,12.436,10.898,17.611l-3.31,3.102c-0.776-0.741-1.827-1.197-2.985-1.197c-2.388,0-4.324,1.935-4.324,4.324
|
||||
c0,2.388,1.936,4.324,4.324,4.324c2.388,0,4.324-1.936,4.324-4.324c0-1.057-0.38-2.025-1.01-2.776l3.311-3.102
|
||||
c0.341,0.36,0.687,0.717,1.039,1.069c3.376,3.375,7.125,6.242,11.154,8.561l-20.601,37.972h-16.685v-25.743h-6.801v-48.882h2.645
|
||||
v-1.063H564.32v1.063h2.645v24.652h-5.729l-5.467,28.096v-92.143h-2.399v-33.37h-12.075v-12.705h-6.46V220.37h-2.267v-18.294
|
||||
h-0.586v18.294h-2.267v10.672h-6.46v12.705h-11.982v33.37h-2.491V337.7h-18.579v53.436h-61.639V287.814h4.954v-1.626h-4.954v-2.911
|
||||
h-6.279v-4.781h-51.354v4.781h-6.279v2.911h-4.954v1.626h4.954v64.319h-8.4v-12.069h-51.819v14.737h-11.298v27.442h-18.294V292.55
|
||||
h-6.098v-6.099h-4.828v-16.134h-1.017v16.134h-2.287v-20.2h-1.016v20.2h-2.811v6.099h-1.509v89.693h-37.859v-52.597h1.779v-3.557
|
||||
h-11.688v-9.655h-5.59v9.655h-5.082v-9.655h-5.082v9.655h-9.885v-9.655h-30.261v9.655h-7.066v3.557h4.017v19.819h-11.18v44.72
|
||||
h-15.346v-11.942h-17.084v26.044H84.29V419.4H53.82v31.849h891.682V419.4H918.278z M716.559,351.896l-7.135-13.152
|
||||
c2.287-1.349,4.417-2.938,6.354-4.731l10.219,10.906C723.091,347.622,719.925,349.955,716.559,351.896z M689.85,309.7
|
||||
c0.175,0.055,0.357,0.094,0.544,0.116l-1.082,33.274c-4.266-0.165-8.344-1.071-12.11-2.594L689.85,309.7z M676.758,340.314
|
||||
c-1.218-0.512-2.402-1.089-3.548-1.726l15.875-29.261c0.102,0.07,0.209,0.133,0.32,0.19L676.758,340.314z M690.874,309.832
|
||||
c0.203-0.01,0.401-0.041,0.591-0.091l11.067,31.4c-3.701,1.281-7.673,1.978-11.804,1.978c-0.313,0-0.625-0.004-0.936-0.012
|
||||
L690.874,309.832z M691.917,309.581c0.159-0.072,0.311-0.157,0.453-0.254l15.875,29.261c-1.677,0.932-3.435,1.734-5.261,2.394
|
||||
L691.917,309.581z M694.589,311.399l20.697,22.088c-1.893,1.751-3.973,3.303-6.206,4.623L694.589,311.399z M693.683,309.731
|
||||
l-0.598-1.103c0.062-0.086,0.119-0.176,0.172-0.268l30.224,13.952c-1.93,4.091-4.602,7.766-7.844,10.847L693.683,309.731z
|
||||
M693.46,307.925c0.077-0.21,0.129-0.432,0.156-0.662l33.274,1.082c-0.186,4.809-1.313,9.38-3.204,13.534L693.46,307.925z
|
||||
M693.631,306.783c-0.011-0.217-0.046-0.428-0.102-0.63l31.244-11.503c1.388,3.836,2.146,7.971,2.146,12.279
|
||||
c0,0.313-0.004,0.624-0.012,0.936L693.631,306.783z M693.364,305.702c-0.097-0.207-0.217-0.401-0.358-0.579l24.281-22.752
|
||||
c3.15,3.404,5.654,7.411,7.319,11.828L693.364,305.702z M692.678,304.772c-0.188-0.17-0.399-0.315-0.627-0.433l12.647-30.797
|
||||
c4.661,1.958,8.83,4.864,12.261,8.477L692.678,304.772z M691.606,304.157c-0.175-0.055-0.357-0.094-0.544-0.116l1.082-33.273
|
||||
c4.265,0.164,8.344,1.071,12.11,2.594L691.606,304.157z M690.582,304.025c-0.203,0.01-0.401,0.041-0.591,0.09l-11.067-31.4
|
||||
c3.701-1.281,7.672-1.978,11.804-1.978c0.313,0,0.625,0.004,0.936,0.012L690.582,304.025z M689.539,304.276
|
||||
c-0.221,0.099-0.428,0.226-0.616,0.375L666.17,280.37c3.525-3.261,7.697-5.832,12.301-7.494L689.539,304.276z M688.572,304.978
|
||||
c-0.143,0.158-0.268,0.332-0.373,0.518l-30.224-13.953c1.929-4.091,4.602-7.766,7.845-10.847L688.572,304.978z M687.996,305.932
|
||||
c-0.077,0.211-0.129,0.432-0.156,0.662l-33.274-1.082c0.186-4.809,1.313-9.38,3.204-13.534L687.996,305.932z M687.825,307.075
|
||||
c0.011,0.217,0.046,0.427,0.102,0.629l-31.244,11.503c-1.388-3.836-2.146-7.97-2.146-12.279c0-0.313,0.004-0.625,0.012-0.936
|
||||
L687.825,307.075z M688.092,308.155c0.078,0.168,0.171,0.326,0.279,0.474l-0.198,0.365l-24.004,22.492
|
||||
c-3.15-3.404-5.654-7.411-7.319-11.828L688.092,308.155z M687.446,310.332l-15.07,27.777c-2.912-1.72-5.564-3.835-7.88-6.272
|
||||
L687.446,310.332z M672.866,339.221c1.169,0.649,2.376,1.238,3.618,1.759l-5.681,13.833c-1.732-0.721-3.424-1.537-5.07-2.445
|
||||
L672.866,339.221z M676.929,341.163c3.843,1.555,8.006,2.479,12.36,2.647l-0.485,14.92c-6.107-0.221-12.028-1.496-17.555-3.735
|
||||
L676.929,341.163z M689.769,343.828c0.319,0.008,0.638,0.013,0.959,0.013c4.215,0,8.267-0.712,12.043-2.02l4.97,14.101
|
||||
c-5.399,1.87-11.131,2.844-17.013,2.844c-0.482,0-0.964-0.007-1.444-0.021L689.769,343.828z M703.225,341.661
|
||||
c1.862-0.672,3.655-1.49,5.365-2.44l7.133,13.148c-2.417,1.333-4.933,2.468-7.528,3.394L703.225,341.661z M727.382,343.582
|
||||
c-0.341,0.341-0.686,0.676-1.035,1.007l-10.217-10.904c3.31-3.144,6.038-6.895,8.007-11.07l13.579,6.269
|
||||
C735.191,334.277,731.718,339.247,727.382,343.582z M737.917,328.448l-13.578-6.268c1.931-4.239,3.081-8.904,3.27-13.813
|
||||
l14.921,0.485C742.281,315.718,740.702,322.349,737.917,328.448z M742.565,306.929c0,0.482-0.007,0.963-0.02,1.444l-14.917-0.485
|
||||
c0.008-0.319,0.012-0.639,0.012-0.959c0-4.397-0.774-8.615-2.19-12.528l14.03-5.165
|
||||
C741.507,294.832,742.565,300.799,742.565,306.929z M728.718,271.66c4.68,5.032,8.253,10.839,10.596,17.124l-14.032,5.167
|
||||
c-1.699-4.508-4.255-8.598-7.47-12.072L728.718,271.66z M727.382,270.274c0.341,0.341,0.676,0.686,1.007,1.035l-10.904,10.217
|
||||
c-3.502-3.687-7.756-6.653-12.513-8.65l5.681-13.833C716.831,261.615,722.507,265.399,727.382,270.274z M692.652,255.126
|
||||
c6.107,0.221,12.028,1.496,17.555,3.735l-5.681,13.833c-3.843-1.555-8.006-2.479-12.36-2.647L692.652,255.126z M690.728,255.092
|
||||
c0.482,0,0.964,0.007,1.444,0.02l-0.485,14.917c-0.319-0.008-0.638-0.012-0.959-0.012c-4.215,0-8.267,0.712-12.043,2.019
|
||||
l-4.97-14.101C679.114,256.065,684.846,255.092,690.728,255.092z M673.261,258.094l4.97,14.102
|
||||
c-4.698,1.696-8.956,4.319-12.553,7.648l-10.219-10.906C660.671,264.091,666.716,260.43,673.261,258.094z M654.074,270.274
|
||||
c0.341-0.341,0.687-0.676,1.035-1.007l10.218,10.904c-3.31,3.144-6.038,6.895-8.007,11.071l-13.579-6.269
|
||||
C646.265,279.58,649.738,274.61,654.074,270.274z M643.539,285.409l13.578,6.268c-1.931,4.239-3.081,8.905-3.27,13.813
|
||||
l-14.921-0.485C639.175,298.14,640.754,291.509,643.539,285.409z M638.891,306.929c0-0.482,0.007-0.964,0.02-1.444l14.917,0.485
|
||||
c-0.008,0.318-0.012,0.638-0.012,0.959c0,4.396,0.774,8.614,2.19,12.528l-14.03,5.166
|
||||
C639.949,319.025,638.891,313.058,638.891,306.929z M652.738,342.197c-4.68-5.032-8.253-10.839-10.597-17.124l14.032-5.167
|
||||
c1.699,4.508,4.255,8.598,7.47,12.072L652.738,342.197z M654.074,343.582c-0.341-0.341-0.676-0.686-1.007-1.035l10.904-10.217
|
||||
c2.368,2.494,5.082,4.656,8.062,6.414l-7.135,13.152C660.988,349.642,657.35,346.859,654.074,343.582z M665.046,353.636
|
||||
c1.692,0.934,3.431,1.771,5.21,2.512l-1.821,4.434c-0.413-0.131-0.853-0.202-1.309-0.202c-2.388,0-4.324,1.936-4.324,4.324
|
||||
c0,2.388,1.936,4.324,4.324,4.324c2.388,0,4.324-1.936,4.324-4.324c0-1.762-1.054-3.276-2.566-3.95l1.816-4.423
|
||||
c5.685,2.304,11.775,3.615,18.057,3.842l-0.148,4.534c-2.341,0.053-4.224,1.967-4.224,4.321c0,2.388,1.936,4.324,4.324,4.324
|
||||
c2.388,0,4.324-1.936,4.324-4.324c0-2.26-1.734-4.113-3.944-4.306l0.148-4.535c0.496,0.014,0.993,0.021,1.491,0.021
|
||||
c6.048,0,11.942-1.001,17.493-2.925l1.554,4.408c-1.471,0.69-2.491,2.184-2.491,3.916c0,2.388,1.936,4.324,4.324,4.324
|
||||
c2.388,0,4.324-1.936,4.324-4.324c0-2.388-1.936-4.324-4.324-4.324c-0.485,0-0.951,0.081-1.387,0.229l-1.547-4.388
|
||||
c2.667-0.952,5.252-2.117,7.736-3.487l20.345,37.5h-92.055L665.046,353.636z"/>
|
||||
<g>
|
||||
|
||||
<linearGradient id="SVGID_00000121273610027325662480000007068999652675512506_" gradientUnits="userSpaceOnUse" x1="815.83" y1="285.1626" x2="815.83" y2="287.5796">
|
||||
<stop offset="0" style="stop-color:#403E40"/>
|
||||
<stop offset="1" style="stop-color:#161F21"/>
|
||||
</linearGradient>
|
||||
<path style="fill:url(#SVGID_00000121273610027325662480000007068999652675512506_);" d="M816.844,286.371
|
||||
c0-0.667-0.454-1.208-1.014-1.208c-0.56,0-1.014,0.541-1.014,1.208c0,0.668,0.454,1.208,1.014,1.208
|
||||
C816.39,287.58,816.844,287.039,816.844,286.371z"/>
|
||||
|
||||
<linearGradient id="SVGID_00000011738580747612097720000010840228285618223286_" gradientUnits="userSpaceOnUse" x1="500" y1="287.5796" x2="500" y2="451.2495">
|
||||
<stop offset="0" style="stop-color:#403E40"/>
|
||||
<stop offset="1" style="stop-color:#161F21"/>
|
||||
</linearGradient>
|
||||
<polygon style="fill:url(#SVGID_00000011738580747612097720000010840228285618223286_);" points="927.404,433.241 921.11,391.136
|
||||
908.236,391.136 908.236,356.197 909.828,356.197 909.828,353.036 903.578,353.036 903.578,339.427 902.815,339.427
|
||||
902.815,353.036 898.496,353.036 898.496,341.887 897.734,341.887 897.734,353.036 871.695,353.036 871.695,356.197
|
||||
873.474,356.197 873.474,427.088 843.745,427.088 843.745,395.334 826.815,395.334 826.815,317.303 828.363,317.303
|
||||
828.363,313.475 824.982,313.475 824.982,308.574 821.091,308.574 821.091,306.732 821.091,301.129 821.091,296.267
|
||||
816.395,296.267 816.395,287.58 815.83,287.58 815.265,287.58 815.265,296.267 812.734,296.267 811.204,301.129 800.958,301.129
|
||||
800.958,308.574 774.141,308.574 774.141,313.475 770.76,313.475 770.76,317.303 772.309,317.303 772.309,368.073
|
||||
749.871,368.073 749.871,417.957 724.973,406.925 724.973,358.507 728.991,358.507 728.991,354.95 721.924,354.95
|
||||
721.924,345.294 691.664,345.294 691.664,354.95 681.778,354.95 681.778,345.294 676.696,345.294 676.696,354.95 671.615,354.95
|
||||
671.615,345.294 666.025,345.294 666.025,354.95 654.337,354.95 654.337,358.507 656.115,358.507 656.115,425.617
|
||||
644.765,425.617 644.765,424.913 642.711,424.913 642.711,405.789 644.765,405.789 644.765,404.255 642.711,404.255
|
||||
642.711,385.13 644.765,385.13 644.765,383.597 642.711,383.597 642.711,364.472 644.765,364.472 644.765,362.939
|
||||
642.711,362.939 642.711,343.814 644.765,343.814 644.765,342.28 642.711,342.28 642.711,323.156 644.765,323.156
|
||||
644.765,321.622 642.711,321.622 642.711,301.83 646.231,301.83 646.231,300.291 648.021,300.291 648.021,296.095
|
||||
614.595,296.095 614.595,291.429 615.682,291.429 615.682,290.081 597.484,290.081 597.484,291.429 598.571,291.429
|
||||
598.571,296.095 590.287,296.095 590.287,300.291 592.078,300.291 592.078,301.83 595.598,301.83 595.598,321.622
|
||||
593.543,321.622 593.543,323.156 595.598,323.156 595.598,342.28 593.543,342.28 593.543,343.814 595.598,343.814
|
||||
595.598,362.939 593.543,362.939 593.543,364.472 595.598,364.472 595.598,383.597 593.543,383.597 593.543,385.13
|
||||
595.598,385.13 595.598,404.255 593.543,404.255 593.543,405.789 595.598,405.789 595.598,424.913 593.543,424.913
|
||||
593.543,426.447 595.598,426.447 595.598,442.075 584.189,442.075 584.189,381.685 538.283,381.685 538.283,425.617
|
||||
530.83,425.617 530.83,288.763 525.315,288.763 525.315,292.286 515.14,294.775 515.14,292.487 509.625,292.487 509.625,296.124
|
||||
499.45,298.612 499.45,295.989 493.936,295.989 493.936,299.961 483.76,302.45 483.76,300.286 478.246,300.286 478.246,303.799
|
||||
468.071,306.288 468.071,304.423 462.557,304.423 462.557,438.816 454.799,438.816 454.799,367.168 426.065,367.168
|
||||
426.065,411.227 396.608,411.227 396.608,373.655 392.979,373.655 392.979,361.316 395.133,361.316 395.133,360.077
|
||||
385.601,360.077 385.601,356.197 384.584,356.197 384.584,360.077 381.535,360.077 381.535,340.162 380.773,340.162
|
||||
380.773,360.077 376.802,360.077 376.802,361.316 379.138,361.316 379.138,373.655 359.697,373.655 359.697,402.316
|
||||
340.771,402.316 330.886,438.816 311.053,438.816 311.053,319.642 284.794,319.642 284.794,315.373 286.286,315.373
|
||||
286.286,313.875 266.397,313.875 266.397,315.373 267.961,315.373 267.961,319.642 267.961,326.508 267.961,408.127
|
||||
255.579,408.127 255.579,377.289 259.98,377.289 259.98,374.497 228.825,374.497 228.825,355.867 222.882,355.867
|
||||
222.882,352.039 209.616,352.039 209.616,355.867 198.821,355.867 198.821,422.389 163.408,422.389 163.408,373.052
|
||||
133.589,373.052 133.589,412.021 107.712,412.021 107.712,436.954 89.054,436.954 89.054,405.609 64.517,405.609 64.517,432.333
|
||||
42.301,432.333 42.301,451.25 64.517,451.25 72.025,451.25 84.29,451.25 89.054,451.25 107.712,451.25 133.589,451.25
|
||||
142.285,451.25 146.941,451.25 163.408,451.25 198.821,451.25 209.616,451.25 222.882,451.25 228.825,451.25 252.067,451.25
|
||||
255.579,451.25 267.961,451.25 288.725,451.25 298.954,451.25 311.053,451.25 359.697,451.25 370.931,451.25 389.895,451.25
|
||||
396.608,451.25 426.568,451.25 434.618,451.25 462.557,451.25 465.314,451.25 468.071,451.25 478.246,451.25 483.76,451.25
|
||||
493.936,451.25 498.545,451.25 499.45,451.25 509.625,451.25 515.14,451.25 523.887,451.25 525.315,451.25 528.072,451.25
|
||||
530.83,451.25 538.283,451.25 576.227,451.25 581.647,451.25 584.189,451.25 595.598,451.25 615.682,451.25 634.069,451.25
|
||||
642.711,451.25 656.115,451.25 689.405,451.25 724.606,451.25 724.973,451.25 749.871,451.25 763.792,451.25 772.309,451.25
|
||||
777.689,451.25 819.353,451.25 826.815,451.25 835.736,451.25 843.745,451.25 873.474,451.25 895.58,451.25 900.105,451.25
|
||||
908.236,451.25 957.698,451.25 957.698,433.241 "/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 28 KiB |
@ -1,64 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
|
||||
<title>cld-server</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs>
|
||||
|
||||
</defs>
|
||||
<g id="General" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="SLICES-64px" transform="translate(-810.000000, -200.000000)">
|
||||
|
||||
</g>
|
||||
<g id="ICONS" transform="translate(-805.000000, -195.000000)">
|
||||
<g id="cld-server" transform="translate(810.000000, 204.000000)">
|
||||
<path d="M48,12 C51.313,12 54,9.313 54,6 C54,2.687 51.313,0 48,0 L6,0 C2.687,0 0,2.687 0,6 C0,9.313 2.687,12 6,12 L48,12 Z" id="Fill-424" fill="#969CE3">
|
||||
|
||||
</path>
|
||||
<path d="M10,6 C10,7.104 9.104,8 8,8 C6.896,8 6,7.104 6,6 C6,4.896 6.896,4 8,4 C9.104,4 10,4.896 10,6" id="Fill-425" fill="#7BBDEC">
|
||||
|
||||
</path>
|
||||
<path d="M48,30 C51.313,30 54,27.313 54,24 C54,20.687 51.313,18 48,18 L6,18 C2.687,18 0,20.687 0,24 C0,27.313 2.687,30 6,30 L48,30 Z" id="Fill-426" fill="#969CE3">
|
||||
|
||||
</path>
|
||||
<path d="M10,24 C10,25.104 9.104,26 8,26 C6.896,26 6,25.104 6,24 C6,22.896 6.896,22 8,22 C9.104,22 10,22.896 10,24" id="Fill-427" fill="#7BBDEC">
|
||||
|
||||
</path>
|
||||
<path d="M48,48 C51.313,48 54,45.313 54,42 C54,38.687 51.313,36 48,36 L6,36 C2.687,36 0,38.687 0,42 C0,45.313 2.687,48 6,48 L48,48 Z" id="Fill-428" fill="#969CE3">
|
||||
|
||||
</path>
|
||||
<path d="M10,42 C10,43.104 9.104,44 8,44 C6.896,44 6,43.104 6,42 C6,40.896 6.896,40 8,40 C9.104,40 10,40.896 10,42" id="Fill-429" fill="#7BBDEC">
|
||||
|
||||
</path>
|
||||
<path d="M48,12 C51.313,12 54,9.313 54,6 C54,2.687 51.313,0 48,0 L6,0 C2.687,0 0,2.687 0,6 C0,9.313 2.687,12 6,12 L48,12 Z" id="Stroke-430" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M10,6 C10,7.104 9.104,8 8,8 C6.896,8 6,7.104 6,6 C6,4.896 6.896,4 8,4 C9.104,4 10,4.896 10,6 Z" id="Stroke-431" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M48,6 L36,6" id="Stroke-432" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M48,30 C51.313,30 54,27.313 54,24 C54,20.687 51.313,18 48,18 L6,18 C2.687,18 0,20.687 0,24 C0,27.313 2.687,30 6,30 L48,30 Z" id="Stroke-433" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M10,24 C10,25.104 9.104,26 8,26 C6.896,26 6,25.104 6,24 C6,22.896 6.896,22 8,22 C9.104,22 10,22.896 10,24 Z" id="Stroke-434" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M48,24 L36,24" id="Stroke-435" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M48,48 C51.313,48 54,45.313 54,42 C54,38.687 51.313,36 48,36 L6,36 C2.687,36 0,38.687 0,42 C0,45.313 2.687,48 6,48 L48,48 Z" id="Stroke-436" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M10,42 C10,43.104 9.104,44 8,44 C6.896,44 6,43.104 6,42 C6,40.896 6.896,40 8,40 C9.104,40 10,40.896 10,42 Z" id="Stroke-437" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M48,42 L36,42" id="Stroke-438" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 3.7 KiB |
@ -1,64 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
|
||||
<title>con-drill</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs>
|
||||
|
||||
</defs>
|
||||
<g id="General" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="SLICES-64px" transform="translate(-450.000000, -300.000000)">
|
||||
|
||||
</g>
|
||||
<g id="ICONS" transform="translate(-445.000000, -295.000000)">
|
||||
<g id="con-drill" transform="translate(452.000000, 306.000000)">
|
||||
<path d="M4,46 L20,46 C21.104,46 22,45.104 22,44 L22,36 C22,34.896 21.104,34 20,34 L13.375,34 L2,34 L2,44 C2,45.104 2.896,46 4,46" id="Fill-680" fill="#99A5B7">
|
||||
|
||||
</path>
|
||||
<path d="M40,4 L34,4 L34,12 L40,12 C41.104,12 42,11.104 42,10 L42,6 C42,4.896 41.104,4 40,4" id="Fill-681" fill="#E9EFFA">
|
||||
|
||||
</path>
|
||||
<path d="M30,16 C32.209,16 34,14.209 34,12 L34,4 C34,1.791 32.209,0 30,0 L4,0 C1.791,0 0,1.791 0,4 L0,12 C0,14.209 1.791,16 4,16 L30,16 Z" id="Fill-682" fill="#D3D873">
|
||||
|
||||
</path>
|
||||
<path d="M12.71,22 L18,22 C16.354,20.354 17.87,17.918 19,16 L14,16 L12.71,22 Z" id="Fill-683" fill="#F16963">
|
||||
|
||||
</path>
|
||||
<path d="M13.375,34 C11.926,34 10.75,32.824 10.75,31.375 C10.75,31.12 10.786,30.874 10.854,30.641 L14,16 L6,16 L2,34 L13.375,34 Z" id="Fill-684" fill="#AEC14A">
|
||||
|
||||
</path>
|
||||
<path d="M12.71,22 L18,22 C16.354,20.354 17.87,17.918 19,16" id="Stroke-685" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M42,8 L54,8" id="Stroke-686" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M34,4 L40,4 C41.104,4 42,4.896 42,6 L42,10 C42,11.104 41.104,12 40,12 L34,12" id="Stroke-687" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M2,34 L6,16" id="Stroke-688" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M6,8 L14,8" id="Stroke-689" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M6,4 L14,4" id="Stroke-690" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M2,34 L2,44 C2,45.104 2.896,46 4,46 L20,46 C21.104,46 22,45.104 22,44 L22,36 C22,34.896 21.104,34 20,34 L13.375,34" id="Stroke-691" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M13.375,34 C11.926,34 10.75,32.824 10.75,31.375 C10.75,31.12 10.786,30.874 10.854,30.641 L14,16" id="Stroke-692" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M2,34 L14,34" id="Stroke-693" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M30,16 C32.209,16 34,14.209 34,12 L34,4 C34,1.791 32.209,0 30,0 L4,0 C1.791,0 0,1.791 0,4 L0,12 C0,14.209 1.791,16 4,16 L30,16 Z" id="Stroke-694" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 3.4 KiB |
@ -1,37 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
|
||||
<title>con-warning</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs>
|
||||
|
||||
</defs>
|
||||
<g id="General" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="SLICES-64px" transform="translate(-720.000000, -300.000000)">
|
||||
|
||||
</g>
|
||||
<g id="ICONS" transform="translate(-715.000000, -295.000000)">
|
||||
<g id="con-warning" transform="translate(718.000000, 302.000000)">
|
||||
<path d="M50,46 C53.313,46 56,43.313 56,40 C56,38.751 55.358,37.299 55.358,37.299 L32.878,2.51 L32.88,2.509 C31.791,0.99 30.011,1.13686838e-13 28,1.13686838e-13 C25.989,1.13686838e-13 24.209,0.99 23.12,2.509 L23.122,2.51 L0.642,37.299 C0.642,37.299 0,38.751 0,40 C0,43.313 2.687,46 6,46 L50,46 Z" id="Fill-390" fill="#F3E777">
|
||||
|
||||
</path>
|
||||
<path d="M26,36 C26,34.896 26.896,34 28,34 C29.104,34 30,34.896 30,36 C30,37.104 29.104,38 28,38 C26.896,38 26,37.104 26,36" id="Fill-391" fill="#F16963">
|
||||
|
||||
</path>
|
||||
<path d="M32,16 C32,13.791 30.209,12 28,12 C25.791,12 24,13.791 24,16 L26,28 C26,29.104 26.896,30 28,30 C29.104,30 30,29.104 30,28 L32,16 Z" id="Fill-392" fill="#F16963">
|
||||
|
||||
</path>
|
||||
<path d="M26,36 C26,34.896 26.896,34 28,34 C29.104,34 30,34.896 30,36 C30,37.104 29.104,38 28,38 C26.896,38 26,37.104 26,36 Z" id="Stroke-393" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M32,16 C32,13.791 30.209,12 28,12 C25.791,12 24,13.791 24,16 L26,28 C26,29.104 26.896,30 28,30 C29.104,30 30,29.104 30,28 L32,16 Z" id="Stroke-394" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M50,46 C53.313,46 56,43.313 56,40 C56,38.751 55.358,37.299 55.358,37.299 L32.878,2.51 L32.88,2.509 C31.791,0.99 30.011,1.13686838e-13 28,1.13686838e-13 C25.989,1.13686838e-13 24.209,0.99 23.12,2.509 L23.122,2.51 L0.642,37.299 C0.642,37.299 0,38.751 0,40 C0,43.313 2.687,46 6,46 L50,46 Z" id="Stroke-395" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 2.4 KiB |
427
frontend/assets/confused.svg
Normal file
After Width: | Height: | Size: 40 KiB |
@ -1,76 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
|
||||
<title>gen-lifebelt</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs>
|
||||
|
||||
</defs>
|
||||
<g id="General" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="SLICES-64px">
|
||||
|
||||
</g>
|
||||
<g id="ICONS" transform="translate(5.000000, 5.000000)">
|
||||
<g id="gen-lifebelt" transform="translate(0.000000, 2.000000)">
|
||||
<path d="M26.0001,40 C18.2681,40 12.0001,33.732 12.0001,26 C12.0001,18.267 18.2681,12 26.0001,12 C33.7321,12 40.0001,18.267 40.0001,26 C40.0001,33.732 33.7321,40 26.0001,40 M26.0001,0 C11.6411,0 0.0001,11.64 0.0001,26 C0.0001,40.359 11.6411,52 26.0001,52 C40.3591,52 52.0001,40.359 52.0001,26 C52.0001,11.64 40.3591,0 26.0001,0" id="Fill-464" fill="#F16963">
|
||||
|
||||
</path>
|
||||
<path d="M3.0025,13.8716 L13.6385,19.4216 L13.6485,19.4116 C14.9905,16.9016 17.0765,14.8566 19.6105,13.5526 L19.6385,13.5256 L13.8725,3.0026 C9.2455,5.4476 5.4475,9.2456 3.0025,13.8716" id="Fill-465" fill="#F1F0E2">
|
||||
|
||||
</path>
|
||||
<path d="M38.128,3.0022 L32.361,13.5252 L32.39,13.5532 C34.923,14.8562 37.01,16.9012 38.352,19.4122 L38.361,19.4212 L48.998,13.8712 C46.553,9.2452 42.754,5.4472 38.128,3.0022" id="Fill-466" fill="#F1F0E2">
|
||||
|
||||
</path>
|
||||
<path d="M13.648,32.5872 L13.639,32.5782 L3.002,38.1282 C5.447,42.7542 9.246,46.5532 13.872,48.9972 L19.639,38.4742 L19.611,38.4472 C17.077,37.1442 14.99,35.0982 13.648,32.5872" id="Fill-467" fill="#F1F0E2">
|
||||
|
||||
</path>
|
||||
<path d="M48.9976,38.1284 L38.3616,32.5774 L38.3516,32.5864 C37.0106,35.0974 34.9236,37.1434 32.3896,38.4474 L32.3616,38.4744 L38.1276,48.9974 C42.7546,46.5524 46.5526,42.7544 48.9976,38.1284" id="Fill-468" fill="#F1F0E2">
|
||||
|
||||
</path>
|
||||
<path d="M2.9971,13.8689 C2.3621,12.7229 2.0001,11.4029 2.0001,9.9999 C2.0001,5.5819 5.5821,1.9999 10.0001,1.9999 C11.4031,1.9999 12.7231,2.3619 13.8691,2.9969" id="Stroke-469" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M49.003,13.8689 C49.638,12.7229 50,11.4029 50,9.9999 C50,5.5819 46.418,1.9999 42,1.9999 C40.597,1.9999 39.277,2.3619 38.131,2.9969" id="Stroke-470" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M2.9971,38.1311 C2.3621,39.2771 2.0001,40.5961 2.0001,42.0001 C2.0001,46.4171 5.5821,50.0001 10.0001,50.0001 C11.4031,50.0001 12.7231,49.6381 13.8691,49.0031" id="Stroke-471" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M49.003,38.1311 C49.638,39.2771 50,40.5961 50,42.0001 C50,46.4171 46.418,50.0001 42,50.0001 C40.597,50.0001 39.277,49.6381 38.131,49.0031" id="Stroke-472" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M52.0001,26 C52.0001,11.64 40.3591,0 26.0001,0 C11.6411,0 0.0001,11.64 0.0001,26 C0.0001,40.359 11.6411,52 26.0001,52 C40.3591,52 52.0001,40.359 52.0001,26 Z" id="Stroke-473" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M40.0001,26 C40.0001,33.732 33.7321,40 26.0001,40 C18.2681,40 12.0001,33.732 12.0001,26 C12.0001,18.267 18.2681,12 26.0001,12 C33.7321,12 40.0001,18.267 40.0001,26 Z" id="Stroke-474" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M13.8692,2.9968 L19.6392,13.5248" id="Stroke-475" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M13.6387,19.4216 L2.9967,13.8686" id="Stroke-476" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M38.1309,2.9968 L32.3609,13.5248" id="Stroke-477" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M38.3614,19.4216 L49.0034,13.8686" id="Stroke-478" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M13.8692,49.0027 L19.6392,38.4747" id="Stroke-479" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M13.6387,32.5779 L2.9967,38.1309" id="Stroke-480" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M38.1309,49.0027 L32.3609,38.4747" id="Stroke-481" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
<path d="M38.3614,32.5779 L49.0034,38.1309" id="Stroke-482" stroke="#414547" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
||||
</path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 5.0 KiB |
161
frontend/assets/plan.svg
Normal file
@ -0,0 +1,161 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 27.5.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 2200 2200" style="enable-background:new 0 0 2200 2200;" xml:space="preserve">
|
||||
|
||||
<g id="Objects">
|
||||
<g>
|
||||
<path style="fill:#788D8E;" d="M1202.178,2002.073c-5.328,0-9.648-4.319-9.649-9.647c-0.001-5.328,4.319-9.649,9.647-9.649
|
||||
c9.63-0.001,19.271-0.006,28.918-0.014c0.003,0,0.006,0,0.009,0c5.325,0,9.643,4.314,9.647,9.639
|
||||
c0.005,5.328-4.311,9.651-9.639,9.656C1221.458,2002.068,1211.813,2002.072,1202.178,2002.073z M1144.298,2002.03
|
||||
c-0.006,0-0.01,0-0.016,0c-9.658-0.015-19.305-0.036-28.94-0.061c-5.328-0.014-9.636-4.345-9.622-9.673
|
||||
c0.014-5.319,4.331-9.622,9.648-9.622c0.008,0,0.017,0,0.025,0c9.628,0.025,19.269,0.046,28.919,0.061
|
||||
c5.328,0.009,9.641,4.335,9.632,9.663C1153.937,1997.721,1149.619,2002.03,1144.298,2002.03z M1288.979,2001.966
|
||||
c-5.317,0-9.634-4.306-9.647-9.626c-0.012-5.328,4.298-9.657,9.626-9.669c9.634-0.022,19.274-0.047,28.923-0.075
|
||||
c5.297,0.018,9.66,4.292,9.676,9.619c0.015,5.328-4.291,9.66-9.619,9.676c-9.652,0.028-19.299,0.054-28.936,0.075
|
||||
C1288.994,2001.966,1288.986,2001.966,1288.979,2001.966z M1057.498,2001.759c-0.015,0-0.03,0-0.045,0
|
||||
c-9.659-0.044-19.306-0.095-28.939-0.152c-5.328-0.031-9.622-4.376-9.591-9.704c0.031-5.309,4.344-9.591,9.646-9.591
|
||||
c0.02,0,0.04,0,0.058,0c9.625,0.057,19.263,0.107,28.914,0.152c5.328,0.025,9.628,4.364,9.603,9.692
|
||||
C1067.12,1997.468,1062.805,2001.759,1057.498,2001.759z M1375.787,2001.691c-5.31,0-9.625-4.293-9.647-9.609
|
||||
c-0.022-5.328,4.281-9.665,9.609-9.686c9.636-0.039,19.28-0.079,28.928-0.123c0.015,0,0.029,0,0.044,0
|
||||
c5.308,0,9.623,4.291,9.647,9.604c0.024,5.328-4.276,9.666-9.604,9.691c-9.651,0.043-19.297,0.084-28.937,0.122
|
||||
C1375.813,2001.691,1375.8,2001.691,1375.787,2001.691z M1462.601,2001.29c-5.305,0-9.619-4.287-9.647-9.598
|
||||
c-0.027-5.328,4.27-9.67,9.598-9.698c9.641-0.05,19.285-0.102,28.932-0.156c0.018,0,0.037,0,0.056,0
|
||||
c5.302,0,9.616,4.284,9.646,9.594c0.029,5.328-4.266,9.671-9.594,9.701c-9.649,0.054-19.297,0.105-28.94,0.156
|
||||
C1462.635,2001.29,1462.618,2001.29,1462.601,2001.29z M970.707,2001.198c-0.027,0-0.054,0-0.081,0
|
||||
c-9.662-0.079-19.308-0.166-28.939-0.259c-5.328-0.052-9.605-4.413-9.554-9.741c0.052-5.296,4.361-9.554,9.646-9.554
|
||||
c0.032,0,0.063,0,0.095,0.001c9.621,0.093,19.258,0.179,28.911,0.258c5.328,0.044,9.612,4.399,9.568,9.727
|
||||
C980.31,1996.93,975.998,2001.198,970.707,2001.198z M1549.42,2000.802c-5.301,0-9.614-4.281-9.646-9.59
|
||||
c-0.032-5.328,4.262-9.673,9.59-9.705l28.936-0.176c0.021,0,0.042,0,0.061,0c5.301,0,9.614,4.279,9.647,9.587
|
||||
c0.033,5.328-4.259,9.674-9.587,9.708l-28.942,0.176C1549.459,2000.802,1549.439,2000.802,1549.42,2000.802z M883.923,2000.297
|
||||
c-0.041,0-0.083,0-0.124-0.001c-9.663-0.122-19.308-0.25-28.935-0.385c-5.328-0.075-9.586-4.454-9.511-9.782
|
||||
c0.075-5.328,4.464-9.604,9.782-9.511c9.617,0.136,19.254,0.264,28.907,0.385c5.328,0.067,9.592,4.44,9.525,9.768
|
||||
C893.501,1996.057,889.195,2000.297,883.923,2000.297z M1636.244,2000.264c-5.3,0-9.612-4.279-9.646-9.586
|
||||
c-0.034-5.328,4.258-9.675,9.586-9.709l28.943-0.184c0.021,0,0.042,0,0.062,0c5.3,0,9.613,4.279,9.647,9.586
|
||||
c0.034,5.328-4.259,9.675-9.586,9.709l-28.943,0.184C1636.286,2000.264,1636.265,2000.264,1636.244,2000.264z M1723.075,1999.719
|
||||
c-5.3,0-9.614-4.28-9.647-9.588c-0.033-5.328,4.26-9.674,9.588-9.707l28.946-0.177c0.02,0,0.04,0,0.059,0
|
||||
c5.301,0,9.615,4.28,9.647,9.589c0.032,5.328-4.261,9.674-9.589,9.706l-28.945,0.177
|
||||
C1723.115,1999.719,1723.095,1999.719,1723.075,1999.719z M1809.912,1999.201c-5.303,0-9.616-4.283-9.647-9.593
|
||||
c-0.03-5.328,4.265-9.672,9.593-9.702l28.952-0.16c0.018,0,0.036,0,0.053,0c5.304,0,9.618,4.285,9.647,9.596
|
||||
c0.028,5.328-4.268,9.67-9.596,9.699l-28.947,0.16C1809.949,1999.201,1809.931,1999.201,1809.912,1999.201z M797.15,1998.997
|
||||
c-0.057,0-0.115-0.001-0.172-0.002c-9.665-0.169-19.31-0.346-28.935-0.531c-5.327-0.103-9.562-4.504-9.459-9.832
|
||||
c0.104-5.327,4.48-9.533,9.832-9.459c9.612,0.186,19.245,0.363,28.899,0.531c5.327,0.092,9.57,4.487,9.477,9.814
|
||||
C806.701,1994.788,802.399,1998.997,797.15,1998.997z M1896.756,1998.75c-5.307,0-9.621-4.29-9.647-9.602
|
||||
c-0.025-5.328,4.274-9.667,9.602-9.693c9.658-0.045,19.31-0.089,28.958-0.129c0.014,0,0.027,0,0.041,0
|
||||
c5.309,0,9.624,4.292,9.647,9.607c0.023,5.328-4.279,9.666-9.607,9.688c-9.644,0.041-19.294,0.084-28.948,0.129
|
||||
C1896.787,1998.75,1896.771,1998.75,1896.756,1998.75z M710.388,1997.237c-0.076,0-0.152-0.001-0.228-0.003
|
||||
c-9.667-0.223-19.311-0.457-28.932-0.7c-5.326-0.135-9.535-4.562-9.401-9.889c0.133-5.243,4.425-9.404,9.64-9.404
|
||||
c0.083,0,0.166,0.001,0.249,0.003c9.607,0.243,19.237,0.477,28.891,0.7c5.327,0.122,9.545,4.541,9.421,9.868
|
||||
C719.907,1993.064,715.612,1997.237,710.388,1997.237z M623.642,1994.948c-0.096,0-0.193-0.001-0.29-0.004
|
||||
c-9.67-0.287-19.314-0.585-28.929-0.894c-5.326-0.172-9.503-4.628-9.333-9.953c0.171-5.325,4.65-9.465,9.953-9.333
|
||||
c9.6,0.309,19.227,0.607,28.88,0.892c5.326,0.158,9.516,4.604,9.357,9.93C633.126,1990.815,628.838,1994.948,623.642,1994.948z
|
||||
M536.937,1991.683c-0.226,0-0.453-0.007-0.682-0.024c-10.955-0.765-20.624-1.8-29.559-3.167
|
||||
c-5.267-0.806-8.883-5.728-8.078-10.995c0.805-5.268,5.725-8.888,10.995-8.078c8.408,1.286,17.563,2.264,27.985,2.992
|
||||
c5.316,0.371,9.323,4.981,8.952,10.296C546.196,1987.794,541.959,1991.683,536.937,1991.683z M452.936,1972.044
|
||||
c-1.444,0-2.91-0.325-4.291-1.012c-5.129-2.553-10.134-5.398-14.875-8.458c-3.821-2.466-7.597-5.17-11.224-8.036
|
||||
c-4.179-3.305-4.889-9.372-1.585-13.552c3.305-4.18,9.371-4.889,13.552-1.585c3.144,2.486,6.415,4.828,9.719,6.961
|
||||
c4.142,2.673,8.519,5.162,13.01,7.397c4.77,2.373,6.713,8.165,4.34,12.935C459.893,1970.083,456.481,1972.044,452.936,1972.044z
|
||||
M390.843,1913.094c-3.257,0-6.436-1.65-8.252-4.636c-5.088-8.366-9.753-17.406-13.866-26.869
|
||||
c-2.125-4.886,0.115-10.57,5.002-12.693c4.884-2.125,10.569,0.114,12.694,5.002c3.765,8.661,8.023,16.915,12.657,24.534
|
||||
c2.768,4.552,1.323,10.487-3.23,13.256C394.28,1912.639,392.55,1913.094,390.843,1913.094z M360.798,1832.103
|
||||
c-4.545,0-8.593-3.227-9.469-7.857c-1.832-9.681-3.208-19.642-4.092-29.605c-0.471-5.307,3.45-9.991,8.757-10.463
|
||||
c5.305-0.466,9.991,3.449,10.462,8.757c0.828,9.335,2.117,18.663,3.831,27.724c0.99,5.236-2.451,10.282-7.686,11.272
|
||||
C361.996,1832.047,361.393,1832.103,360.798,1832.103z M357.3,1745.636c-0.337,0-0.677-0.018-1.02-0.054
|
||||
c-5.299-0.557-9.143-5.304-8.586-10.603c1.051-10.004,2.612-19.95,4.636-29.561c1.098-5.214,6.217-8.55,11.429-7.451
|
||||
c5.214,1.099,8.55,6.215,7.451,11.429c-1.889,8.965-3.345,18.252-4.327,27.6C366.362,1741.952,362.175,1745.636,357.3,1745.636z
|
||||
M379.592,1662.099c-1.292,0-2.604-0.261-3.863-0.812c-4.881-2.136-7.107-7.824-4.97-12.706
|
||||
c3.967-9.067,8.429-18.064,13.26-26.742c2.591-4.655,8.466-6.329,13.122-3.737c4.656,2.592,6.329,8.466,3.737,13.122
|
||||
c-4.533,8.143-8.72,16.585-12.442,25.091C386.85,1659.939,383.308,1662.099,379.592,1662.099z M425.149,1588.527
|
||||
c-2.174,0-4.36-0.73-6.162-2.228c-4.097-3.407-4.658-9.489-1.252-13.587c6.291-7.567,13.033-14.977,20.039-22.024
|
||||
c3.756-3.78,9.865-3.796,13.644-0.039c3.778,3.756,3.796,9.865,0.039,13.643c-6.604,6.642-12.958,13.624-18.884,20.754
|
||||
C430.666,1587.342,427.917,1588.527,425.149,1588.527z M488.757,1529.81c-3.021,0-5.994-1.414-7.875-4.063
|
||||
c-3.085-4.345-2.062-10.367,2.282-13.452c8.036-5.705,16.424-11.148,24.935-16.182c4.587-2.711,10.502-1.194,13.215,3.393
|
||||
c2.712,4.586,1.194,10.503-3.393,13.215c-8.051,4.762-15.987,9.912-23.588,15.308
|
||||
C492.639,1529.232,490.688,1529.81,488.757,1529.81z M565.026,1488.849c-3.858,0-7.5-2.33-8.989-6.14
|
||||
c-1.939-4.962,0.513-10.558,5.476-12.497c8.996-3.515,18.386-6.814,27.91-9.805c5.085-1.593,10.499,1.23,12.094,6.314
|
||||
c1.597,5.083-1.229,10.498-6.313,12.095c-9.107,2.86-18.081,6.012-26.67,9.368
|
||||
C567.381,1488.636,566.194,1488.849,565.026,1488.849z M648.419,1465.236c-4.529,0-8.569-3.204-9.462-7.816
|
||||
c-1.012-5.232,2.408-10.293,7.639-11.306c9.243-1.788,18.981-3.446,28.945-4.926c5.268-0.786,10.177,2.855,10.961,8.125
|
||||
c0.783,5.27-2.855,10.178-8.125,10.961c-9.686,1.439-19.145,3.049-28.114,4.784
|
||||
C649.644,1465.178,649.027,1465.236,648.419,1465.236z M734.448,1453.776c-4.949,0-9.161-3.786-9.599-8.809
|
||||
c-0.464-5.308,3.463-9.987,8.771-10.45c8.927-0.779,18.419-1.521,29.019-2.265c5.285-0.369,9.926,3.633,10.3,8.948
|
||||
c0.373,5.315-3.633,9.926-8.948,10.299c-10.489,0.737-19.875,1.469-28.691,2.239
|
||||
C735.013,1453.764,734.729,1453.776,734.448,1453.776z M821.074,1447.866c-5.059,0-9.308-3.941-9.621-9.059
|
||||
c-0.325-5.318,3.722-9.893,9.041-10.219l28.889-1.767c5.341-0.318,9.893,3.723,10.219,9.041c0.325,5.318-3.722,9.893-9.041,10.219
|
||||
l-28.889,1.766C821.471,1447.86,821.272,1447.866,821.074,1447.866z M907.74,1442.568c-5.059,0-9.308-3.941-9.621-9.059
|
||||
c-0.325-5.318,3.722-9.893,9.041-10.219l28.889-1.766c5.344-0.326,9.893,3.723,10.219,9.041c0.325,5.318-3.722,9.893-9.041,10.218
|
||||
l-28.889,1.767C908.137,1442.562,907.938,1442.568,907.74,1442.568z M994.406,1437.269c-5.059,0-9.307-3.941-9.62-9.059
|
||||
c-0.325-5.318,3.722-9.893,9.041-10.219l28.889-1.766c5.345-0.309,9.893,3.722,10.219,9.041c0.325,5.318-3.722,9.893-9.041,10.219
|
||||
l-28.889,1.767C994.805,1437.263,994.604,1437.269,994.406,1437.269z M1081.072,1431.969c-5.059,0-9.307-3.941-9.62-9.059
|
||||
c-0.325-5.318,3.722-9.893,9.041-10.219l28.889-1.766c5.322-0.318,9.894,3.723,10.219,9.041c0.325,5.318-3.722,9.893-9.041,10.219
|
||||
l-28.889,1.767C1081.47,1431.964,1081.27,1431.969,1081.072,1431.969z M1167.738,1426.671c-5.059,0-9.307-3.941-9.62-9.059
|
||||
c-0.325-5.318,3.722-9.893,9.041-10.219l28.889-1.767c5.349-0.326,9.894,3.723,10.219,9.041c0.325,5.318-3.722,9.893-9.041,10.219
|
||||
l-28.889,1.766C1168.135,1426.665,1167.936,1426.671,1167.738,1426.671z M1254.358,1420.693c-4.914,0-9.115-3.738-9.592-8.73
|
||||
c-0.508-5.304,3.38-10.015,8.685-10.523c10.205-0.975,19.481-2.043,28.357-3.264c5.276-0.72,10.146,2.966,10.872,8.244
|
||||
c0.725,5.279-2.966,10.146-8.244,10.872c-9.142,1.257-18.676,2.354-29.148,3.356
|
||||
C1254.976,1420.678,1254.665,1420.693,1254.358,1420.693z M1339.835,1406.05c-4.233,0-8.115-2.807-9.295-7.086
|
||||
c-1.416-5.136,1.6-10.448,6.735-11.864c9.242-2.549,18.223-5.456,26.694-8.639c4.994-1.875,10.551,0.65,12.425,5.636
|
||||
c1.875,4.988-0.649,10.55-5.636,12.425c-9.014,3.388-18.553,6.476-28.353,9.178
|
||||
C1341.548,1405.937,1340.684,1406.05,1339.835,1406.05z M1418.99,1371.212c-3.131,0-6.201-1.522-8.057-4.329
|
||||
c-2.938-4.445-1.716-10.43,2.729-13.368c7.542-4.985,14.948-10.622,22.014-16.754c4.022-3.493,10.115-3.063,13.609,0.962
|
||||
c3.493,4.024,3.062,10.117-0.962,13.609c-7.698,6.683-15.781,12.832-24.022,18.28
|
||||
C1422.663,1370.694,1420.817,1371.212,1418.99,1371.212z M1480.743,1310.868c-1.931,0-3.882-0.578-5.577-1.782
|
||||
c-4.344-3.086-5.366-9.108-2.281-13.452c5.366-7.558,10.318-15.487,14.721-23.567c2.549-4.679,8.41-6.406,13.087-3.856
|
||||
c4.679,2.549,6.406,8.409,3.856,13.087c-4.765,8.747-10.126,17.328-15.932,25.506
|
||||
C1486.737,1309.454,1483.762,1310.868,1480.743,1310.868z M1517.216,1232.602c-0.778,0-1.568-0.094-2.356-0.292
|
||||
c-5.169-1.297-8.306-6.538-7.009-11.707c2.256-8.984,3.898-18.121,4.878-27.155c0.575-5.299,5.342-9.13,10.632-8.55
|
||||
c5.298,0.575,9.126,5.335,8.55,10.633c-1.076,9.911-2.875,19.928-5.346,29.771
|
||||
C1525.467,1229.681,1521.535,1232.602,1517.216,1232.602z M1520.169,1146.498c-4.554,0-8.606-3.239-9.472-7.879
|
||||
c-1.672-8.957-4.032-17.905-7.015-26.593c-1.731-5.04,0.953-10.527,5.992-12.257c5.036-1.729,10.528,0.953,12.257,5.992
|
||||
c3.287,9.575,5.889,19.438,7.733,29.318c0.978,5.237-2.475,10.276-7.713,11.254
|
||||
C1521.352,1146.444,1520.757,1146.498,1520.169,1146.498z M1486.631,1067.128c-3.053,0-6.055-1.445-7.93-4.142
|
||||
c-5.223-7.514-11.025-14.791-17.243-21.63c-3.585-3.942-3.295-10.044,0.647-13.629c3.942-3.584,10.044-3.295,13.628,0.648
|
||||
c6.781,7.457,13.11,15.396,18.811,23.597c3.041,4.375,1.961,10.387-2.415,13.428
|
||||
C1490.452,1066.568,1488.532,1067.128,1486.631,1067.128z M1424.593,1007.152c-1.794,0-3.608-0.499-5.227-1.546
|
||||
c-7.728-4.995-15.75-9.441-23.845-13.217l-0.314-0.146c-4.827-2.257-6.911-7.999-4.653-12.826c2.257-4.826,8-6.91,12.825-4.653
|
||||
l0.276,0.129c8.915,4.158,17.716,9.036,26.183,14.508c4.475,2.892,5.758,8.864,2.866,13.339
|
||||
C1430.859,1005.596,1427.759,1007.152,1424.593,1007.152z M1344.533,974.803c-0.7,0-1.41-0.076-2.123-0.236
|
||||
c-8.759-1.966-18.077-3.643-27.693-4.985c-5.277-0.736-8.958-5.611-8.222-10.888c0.737-5.277,5.615-8.957,10.888-8.222
|
||||
c10.137,1.415,19.98,3.187,29.254,5.268c5.199,1.167,8.467,6.327,7.3,11.527C1352.93,971.754,1348.947,974.803,1344.533,974.803z
|
||||
M274.324,966.773c-5.318,0-9.634-4.305-9.647-9.625c-0.012-5.328,4.297-9.657,9.625-9.67l28.943-0.066c0.008,0,0.016,0,0.023,0
|
||||
c5.317,0,9.634,4.305,9.647,9.625c0.012,5.328-4.297,9.657-9.625,9.67l-28.943,0.066
|
||||
C274.339,966.773,274.331,966.773,274.324,966.773z M361.152,966.573c-5.318,0-9.635-4.305-9.647-9.625
|
||||
c-0.012-5.328,4.297-9.657,9.625-9.67l28.943-0.066c5.338-0.002,9.657,4.297,9.67,9.625s-4.297,9.657-9.625,9.67l-28.943,0.066
|
||||
C361.167,966.573,361.16,966.573,361.152,966.573z M447.979,966.373c-5.318,0-9.634-4.305-9.647-9.625
|
||||
c-0.012-5.328,4.297-9.657,9.625-9.67l28.942-0.066c0.008,0,0.015,0,0.023,0c5.318,0,9.635,4.305,9.648,9.625
|
||||
c0.012,5.328-4.297,9.657-9.626,9.67l-28.942,0.066C447.995,966.373,447.987,966.373,447.979,966.373z M534.808,966.174
|
||||
c-5.318,0-9.635-4.305-9.648-9.625c-0.012-5.328,4.297-9.657,9.625-9.67l28.943-0.066c0.008,0,0.015,0,0.023,0
|
||||
c5.318,0,9.635,4.305,9.648,9.625c0.012,5.328-4.297,9.657-9.626,9.67l-28.943,0.066
|
||||
C534.823,966.174,534.815,966.174,534.808,966.174z M621.636,965.973c-5.318,0-9.635-4.305-9.648-9.625
|
||||
c-0.012-5.328,4.297-9.657,9.625-9.67l28.943-0.066c0.008,0,0.015,0,0.023,0c5.318,0,9.635,4.305,9.648,9.625
|
||||
c0.012,5.328-4.297,9.657-9.626,9.67l-28.943,0.066C621.651,965.973,621.643,965.973,621.636,965.973z M708.463,965.774
|
||||
c-5.318,0-9.635-4.305-9.648-9.625c-0.012-5.328,4.297-9.657,9.625-9.67l28.943-0.066c0.008,0,0.015,0,0.023,0
|
||||
c5.318,0,9.635,4.305,9.648,9.625c0.012,5.328-4.297,9.657-9.626,9.67l-28.943,0.066
|
||||
C708.478,965.774,708.471,965.774,708.463,965.774z M795.291,965.574c-5.318,0-9.635-4.305-9.648-9.625
|
||||
c-0.012-5.328,4.297-9.657,9.625-9.67l28.943-0.066c5.292,0.018,9.658,4.297,9.67,9.625c0.012,5.328-4.297,9.657-9.626,9.67
|
||||
l-28.943,0.066C795.306,965.574,795.299,965.574,795.291,965.574z M882.12,965.374c-5.318,0-9.635-4.305-9.648-9.625
|
||||
c-0.012-5.328,4.297-9.657,9.625-9.67l28.943-0.066c0.008,0,0.016,0,0.024,0c5.317,0,9.634,4.305,9.647,9.625
|
||||
c0.012,5.328-4.297,9.657-9.626,9.67l-28.943,0.066C882.135,965.374,882.127,965.374,882.12,965.374z M968.947,965.174
|
||||
c-5.318,0-9.635-4.305-9.648-9.625c-0.012-5.328,4.297-9.657,9.625-9.67l28.943-0.066c0.008,0,0.015,0,0.023,0
|
||||
c5.318,0,9.635,4.305,9.648,9.625c0.012,5.328-4.297,9.657-9.626,9.67l-28.943,0.066
|
||||
C968.962,965.174,968.955,965.174,968.947,965.174z M1258.376,965.13c-0.103,0-0.204-0.001-0.307-0.005
|
||||
c-8.629-0.27-17.745-0.424-28.69-0.483c-5.328-0.029-9.623-4.372-9.595-9.7c0.029-5.31,4.342-9.595,9.647-9.595
|
||||
c0.018,0,0.036,0,0.054,0c11.114,0.06,20.389,0.216,29.188,0.492c5.326,0.167,9.508,4.619,9.341,9.945
|
||||
C1267.849,961.007,1263.564,965.13,1258.376,965.13z M1055.775,964.974c-5.318,0-9.635-4.305-9.648-9.625
|
||||
c-0.012-5.328,4.297-9.657,9.625-9.67l28.943-0.066c0.008,0,0.016,0,0.024,0c5.318,0,9.634,4.305,9.647,9.625
|
||||
c0.012,5.328-4.297,9.657-9.626,9.67l-28.943,0.066C1055.79,964.974,1055.783,964.974,1055.775,964.974z M1142.603,964.775
|
||||
c-5.318,0-9.635-4.305-9.648-9.625c-0.012-5.328,4.297-9.657,9.625-9.67l28.943-0.066c0.007,0,0.015,0,0.023,0
|
||||
c5.318,0,9.635,4.305,9.648,9.625c0.012,5.328-4.297,9.657-9.626,9.67l-28.943,0.066
|
||||
C1142.619,964.775,1142.611,964.775,1142.603,964.775z"/>
|
||||
<path style="fill:#D13737;" d="M462.452,197.927c-156.647,0-283.638,126.991-283.638,283.638
|
||||
c0,251.801,283.638,464.048,283.638,464.048S746.09,733.366,746.09,481.565C746.09,324.918,619.099,197.927,462.452,197.927z
|
||||
M462.316,679.485c-109.374,0-198.045-88.671-198.045-198.055c0-109.374,88.671-198.045,198.045-198.045
|
||||
c109.384,0,198.055,88.671,198.055,198.045C660.371,590.814,571.701,679.485,462.316,679.485z"/>
|
||||
<path style="fill:#18ACB7;" d="M1737.548,1228.212c-156.647,0-283.638,126.991-283.638,283.638
|
||||
c0,251.801,283.638,464.048,283.638,464.048s283.638-212.246,283.638-464.048
|
||||
C2021.187,1355.203,1894.196,1228.212,1737.548,1228.212z M1737.413,1709.77c-109.374,0-198.045-88.671-198.045-198.055
|
||||
c0-109.374,88.671-198.045,198.045-198.045c109.384,0,198.055,88.671,198.055,198.045
|
||||
C1935.468,1621.1,1846.797,1709.77,1737.413,1709.77z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 16 KiB |
@ -1,126 +0,0 @@
|
||||
# Terms and Conditions
|
||||
|
||||
> Last updated: January 09, 2025
|
||||
>
|
||||
> Also see: https://anydev.info/terms-and-conditions/
|
||||
|
||||
Please read these terms and conditions carefully before using our Service.
|
||||
|
||||
## Interpretation and Definitions
|
||||
### Interpretation
|
||||
|
||||
The words of which the initial letter is capitalized have meanings defined under the following conditions. The following definitions shall have the same meaning regardless of whether they appear in singular or in plural.
|
||||
|
||||
### Definitions
|
||||
|
||||
For the purposes of these Terms and Conditions:
|
||||
- **Application** means the software program provided by the Company downloaded by You on any electronic device, named AnyWay
|
||||
- **Application Store** means the digital distribution service operated and developed by Apple Inc. (Apple App Store) or Google Inc. (Google Play Store) in which the Application has been downloaded.
|
||||
- **Affiliate** means an entity that controls, is controlled by or is under common control with a party, where "control" means ownership of 50% or more of the shares, equity interest or other securities entitled to vote for election of directors or other managing authority.
|
||||
- **Country** refers to: Switzerland
|
||||
- **Company** (referred to as either "the Company", "We", "Us" or "Our" in this Agreement) refers to AnyDev.
|
||||
- **Device** means any device that can access the Service such as a computer, a cellphone or a digital tablet.
|
||||
- **Service** refers to the Application.
|
||||
- **Terms and Conditions** (also referred as "Terms") mean these Terms and Conditions that form the entire agreement between You and the Company regarding the use of the Service. This Terms and Conditions agreement has been created with the help of the Terms and Conditions Generator.
|
||||
- **Third-party Social Media Service** means any services or content (including data, information, products or services) provided by a third-party that may be displayed, included or made available by the Service.
|
||||
- **You** means the individual accessing or using the Service, or the company, or other legal entity on behalf of which such individual is accessing or using the Service, as applicable.
|
||||
|
||||
## Acknowledgment
|
||||
|
||||
These are the Terms and Conditions governing the use of this Service and the agreement that operates between You and the Company. These Terms and Conditions set out the rights and obligations of all users regarding the use of the Service.
|
||||
|
||||
Your access to and use of the Service is conditioned on Your acceptance of and compliance with these Terms and Conditions. These Terms and Conditions apply to all visitors, users and others who access or use the Service.
|
||||
|
||||
By accessing or using the Service You agree to be bound by these Terms and Conditions. If You disagree with any part of these Terms and Conditions then You may not access the Service.
|
||||
|
||||
You represent that you are over the age of 18. The Company does not permit those under 18 to use the Service.
|
||||
|
||||
Your access to and use of the Service is also conditioned on Your acceptance of and compliance with the Privacy Policy of the Company. Our Privacy Policy describes Our policies and procedures on the collection, use and disclosure of Your personal information when You use the Application or the Website and tells You about Your privacy rights and how the law protects You. Please read Our Privacy Policy carefully before using Our Service.
|
||||
|
||||
|
||||
## Links to Other Websites
|
||||
|
||||
Our Service may contain links to third-party web sites or services that are not owned or controlled by the Company.
|
||||
|
||||
The Company has no control over, and assumes no responsibility for, the content, privacy policies, or practices of any third party web sites or services. You further acknowledge and agree that the Company shall not be responsible or liable, directly or indirectly, for any damage or loss caused or alleged to be caused by or in connection with the use of or reliance on any such content, goods or services available on or through any such web sites or services.
|
||||
|
||||
We strongly advise You to read the terms and conditions and privacy policies of any third-party web sites or services that You visit.
|
||||
|
||||
|
||||
## Termination
|
||||
|
||||
We may terminate or suspend Your access immediately, without prior notice or liability, for any reason whatsoever, including without limitation if You breach these Terms and Conditions.
|
||||
|
||||
Upon termination, Your right to use the Service will cease immediately.
|
||||
|
||||
|
||||
## Limitation of Liability
|
||||
|
||||
Notwithstanding any damages that You might incur, the entire liability of the Company and any of its suppliers under any provision of this Terms and Your exclusive remedy for all of the foregoing shall be limited to the amount actually paid by You through the Service or 100 USD if You haven't purchased anything through the Service.
|
||||
|
||||
To the maximum extent permitted by applicable law, in no event shall the Company or its suppliers be liable for any special, incidental, indirect, punitive, or consequential damages whatsoever (including, but not limited to, damages for loss of profits, loss of data, loss of use, loss of goodwill, business interruption, personal injury, loss of privacy, or any other pecuniary or non-pecuniary loss or damage) arising out of or in any way related to the use of or inability to use the Service, third-party software and/or third-party hardware used with the Service, or otherwise in connection with any provision of this Terms, even if the Company or any supplier has been advised of the possibility of such damages and even if the remedy fails of its essential purpose.
|
||||
|
||||
In particular, the Company and its suppliers are not liable for any damages or losses that may arise from:
|
||||
- Your reliance on any content provided through the Service;
|
||||
- Errors, mistakes, or inaccuracies of content;
|
||||
- Any unauthorized access to or use of our servers and/or any personal information stored therein;
|
||||
- Any interruption or cessation of transmission to or from the Service;
|
||||
- Any bugs, viruses, trojan horses, or the like which may be transmitted to or through the Service by any third party;
|
||||
- Any errors or omissions in any content or for any loss or damage of any kind incurred as a result of Your use of any content posted, emailed, transmitted, or otherwise made available via the Service.
|
||||
|
||||
The Company shall not be liable for any loss or damage resulting from failure to meet any of Your expectations related to the use or performance of the Service, including but not limited to inaccuracies in GPS location services, suggested itineraries, or other location-based services.
|
||||
|
||||
Some jurisdictions do not allow the exclusion or limitation of certain types of liability, such as incidental or consequential damages or implied warranties. Therefore, the above limitations or exclusions may not apply to You. In such jurisdictions, each party's liability will be limited to the greatest extent permitted by law.
|
||||
|
||||
To the extent permitted by applicable law, the Company and its suppliers’ aggregate liability to You for any claims arising from or related to the use of the Service shall in no event exceed the greater of (a) the amount You paid, if any, for accessing the Service during the twelve (12) month period preceding the claim or (b) one hundred (100) USD.
|
||||
|
||||
You agree that the limitations of liability set forth in this section will survive any termination or expiration of these Terms and apply even if any limited remedy specified in these Terms is found to have failed its essential purpose.
|
||||
"AS IS" and "AS AVAILABLE" Disclaimer
|
||||
|
||||
The Service is provided to You "AS IS" and "AS AVAILABLE" and with all faults and defects without warranty of any kind. To the maximum extent permitted under applicable law, the Company, on its own behalf and on behalf of its Affiliates and its and their respective licensors and service providers, expressly disclaims all warranties, whether express, implied, statutory or otherwise, with respect to the Service, including all implied warranties of merchantability, fitness for a particular purpose, title and non-infringement, and warranties that may arise out of course of dealing, course of performance, usage or trade practice. Without limitation to the foregoing, the Company provides no warranty or undertaking, and makes no representation of any kind that the Service will meet Your requirements, achieve any intended results, be compatible or work with any other software, applications, systems or services, operate without interruption, meet any performance or reliability standards or be error free or that any errors or defects can or will be corrected.
|
||||
|
||||
Without limiting the foregoing, neither the Company nor any of the company's provider makes any representation or warranty of any kind, express or implied: (i) as to the operation or availability of the Service, or the information, content, and materials or products included thereon; (ii) that the Service will be uninterrupted or error-free; (iii) as to the accuracy, reliability, or currency of any information or content provided through the Service; or (iv) that the Service, its servers, the content, or e-mails sent from or on behalf of the Company are free of viruses, scripts, trojan horses, worms, malware, timebombs or other harmful components.
|
||||
|
||||
Some jurisdictions do not allow the exclusion of certain types of warranties or limitations on applicable statutory rights of a consumer, so some or all of the above exclusions and limitations may not apply to You. But in such a case the exclusions and limitations set forth in this section shall be applied to the greatest extent enforceable under applicable law.
|
||||
|
||||
|
||||
## Governing Law
|
||||
|
||||
The laws of the Country, excluding its conflicts of law rules, shall govern this Terms and Your use of the Service. Your use of the Application may also be subject to other local, state, national, or international laws.
|
||||
|
||||
|
||||
## Disputes Resolution
|
||||
|
||||
If You have any concern or dispute about the Service, You agree to first try to resolve the dispute informally by contacting the Company.
|
||||
For European Union (EU) Users
|
||||
|
||||
If You are a European Union consumer, you will benefit from any mandatory provisions of the law of the country in which You are resident.
|
||||
|
||||
|
||||
## United States Legal Compliance
|
||||
|
||||
You represent and warrant that (i) You are not located in a country that is subject to the United States government embargo, or that has been designated by the United States government as a "terrorist supporting" country, and (ii) You are not listed on any United States government list of prohibited or restricted parties.
|
||||
|
||||
|
||||
## Severability and Waiver
|
||||
### Severability
|
||||
|
||||
If any provision of these Terms is held to be unenforceable or invalid, such provision will be changed and interpreted to accomplish the objectives of such provision to the greatest extent possible under applicable law and the remaining provisions will continue in full force and effect.
|
||||
|
||||
### Waiver
|
||||
|
||||
Except as provided herein, the failure to exercise a right or to require performance of an obligation under these Terms shall not affect a party's ability to exercise such right or require such performance at any time thereafter nor shall the waiver of a breach constitute a waiver of any subsequent breach.
|
||||
Translation Interpretation
|
||||
|
||||
These Terms and Conditions may have been translated if We have made them available to You on our Service. You agree that the original English text shall prevail in the case of a dispute.
|
||||
Changes to These Terms and Conditions
|
||||
|
||||
We reserve the right, at Our sole discretion, to modify or replace these Terms at any time. If a revision is material We will make reasonable efforts to provide at least 30 days' notice prior to any new terms taking effect. What constitutes a material change will be determined at Our sole discretion.
|
||||
|
||||
By continuing to access or use Our Service after those revisions become effective, You agree to be bound by the revised terms. If You do not agree to the new terms, in whole or in part, please stop using the website and the Service.
|
||||
|
||||
|
||||
## Contact Us
|
||||
|
||||
If you have any questions about these Terms and Conditions, You can contact us:
|
||||
- By visiting this page on our website: https://anydev.info
|
288
frontend/ios/Gemfile.lock
Normal file
@ -0,0 +1,288 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
CFPropertyList (3.0.7)
|
||||
base64
|
||||
nkf
|
||||
rexml
|
||||
activesupport (5.2.8.1)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 0.7, < 2)
|
||||
minitest (~> 5.1)
|
||||
tzinfo (~> 1.1)
|
||||
addressable (2.8.7)
|
||||
public_suffix (>= 2.0.2, < 7.0)
|
||||
algoliasearch (1.27.5)
|
||||
httpclient (~> 2.8, >= 2.8.3)
|
||||
json (>= 1.5.1)
|
||||
artifactory (3.0.17)
|
||||
atomos (0.1.3)
|
||||
aws-eventstream (1.3.0)
|
||||
aws-partitions (1.1004.0)
|
||||
aws-sdk-core (3.212.0)
|
||||
aws-eventstream (~> 1, >= 1.3.0)
|
||||
aws-partitions (~> 1, >= 1.992.0)
|
||||
aws-sigv4 (~> 1.9)
|
||||
jmespath (~> 1, >= 1.6.1)
|
||||
aws-sdk-kms (1.95.0)
|
||||
aws-sdk-core (~> 3, >= 3.210.0)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sdk-s3 (1.170.1)
|
||||
aws-sdk-core (~> 3, >= 3.210.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sigv4 (1.10.1)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
babosa (1.0.4)
|
||||
base64 (0.2.0)
|
||||
claide (1.1.0)
|
||||
cocoapods (1.10.2)
|
||||
addressable (~> 2.6)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
cocoapods-core (= 1.10.2)
|
||||
cocoapods-deintegrate (>= 1.0.3, < 2.0)
|
||||
cocoapods-downloader (>= 1.4.0, < 2.0)
|
||||
cocoapods-plugins (>= 1.0.0, < 2.0)
|
||||
cocoapods-search (>= 1.0.0, < 2.0)
|
||||
cocoapods-trunk (>= 1.4.0, < 2.0)
|
||||
cocoapods-try (>= 1.1.0, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
escape (~> 0.0.4)
|
||||
fourflusher (>= 2.3.0, < 3.0)
|
||||
gh_inspector (~> 1.0)
|
||||
molinillo (~> 0.6.6)
|
||||
nap (~> 1.0)
|
||||
ruby-macho (~> 1.4)
|
||||
xcodeproj (>= 1.19.0, < 2.0)
|
||||
cocoapods-core (1.10.2)
|
||||
activesupport (> 5.0, < 6)
|
||||
addressable (~> 2.6)
|
||||
algoliasearch (~> 1.0)
|
||||
concurrent-ruby (~> 1.1)
|
||||
fuzzy_match (~> 2.0.4)
|
||||
nap (~> 1.0)
|
||||
netrc (~> 0.11)
|
||||
public_suffix
|
||||
typhoeus (~> 1.0)
|
||||
cocoapods-deintegrate (1.0.5)
|
||||
cocoapods-downloader (1.6.3)
|
||||
cocoapods-plugins (1.0.0)
|
||||
nap
|
||||
cocoapods-search (1.0.1)
|
||||
cocoapods-trunk (1.6.0)
|
||||
nap (>= 0.8, < 2.0)
|
||||
netrc (~> 0.11)
|
||||
cocoapods-try (1.2.0)
|
||||
colored (1.2)
|
||||
colored2 (3.1.2)
|
||||
commander (4.6.0)
|
||||
highline (~> 2.0.0)
|
||||
concurrent-ruby (1.3.4)
|
||||
declarative (0.0.20)
|
||||
digest-crc (0.6.5)
|
||||
rake (>= 12.0.0, < 14.0.0)
|
||||
domain_name (0.6.20240107)
|
||||
dotenv (2.8.1)
|
||||
emoji_regex (3.2.3)
|
||||
escape (0.0.4)
|
||||
ethon (0.16.0)
|
||||
ffi (>= 1.15.0)
|
||||
excon (0.112.0)
|
||||
faraday (1.10.4)
|
||||
faraday-em_http (~> 1.0)
|
||||
faraday-em_synchrony (~> 1.0)
|
||||
faraday-excon (~> 1.1)
|
||||
faraday-httpclient (~> 1.0)
|
||||
faraday-multipart (~> 1.0)
|
||||
faraday-net_http (~> 1.0)
|
||||
faraday-net_http_persistent (~> 1.0)
|
||||
faraday-patron (~> 1.0)
|
||||
faraday-rack (~> 1.0)
|
||||
faraday-retry (~> 1.0)
|
||||
ruby2_keywords (>= 0.0.4)
|
||||
faraday-cookie_jar (0.0.7)
|
||||
faraday (>= 0.8.0)
|
||||
http-cookie (~> 1.0.0)
|
||||
faraday-em_http (1.0.0)
|
||||
faraday-em_synchrony (1.0.0)
|
||||
faraday-excon (1.1.0)
|
||||
faraday-httpclient (1.0.1)
|
||||
faraday-multipart (1.0.4)
|
||||
multipart-post (~> 2)
|
||||
faraday-net_http (1.0.2)
|
||||
faraday-net_http_persistent (1.2.0)
|
||||
faraday-patron (1.0.0)
|
||||
faraday-rack (1.0.0)
|
||||
faraday-retry (1.0.3)
|
||||
faraday_middleware (1.2.1)
|
||||
faraday (~> 1.0)
|
||||
fastimage (2.3.1)
|
||||
fastlane (2.225.0)
|
||||
CFPropertyList (>= 2.3, < 4.0.0)
|
||||
addressable (>= 2.8, < 3.0.0)
|
||||
artifactory (~> 3.0)
|
||||
aws-sdk-s3 (~> 1.0)
|
||||
babosa (>= 1.0.3, < 2.0.0)
|
||||
bundler (>= 1.12.0, < 3.0.0)
|
||||
colored (~> 1.2)
|
||||
commander (~> 4.6)
|
||||
dotenv (>= 2.1.1, < 3.0.0)
|
||||
emoji_regex (>= 0.1, < 4.0)
|
||||
excon (>= 0.71.0, < 1.0.0)
|
||||
faraday (~> 1.0)
|
||||
faraday-cookie_jar (~> 0.0.6)
|
||||
faraday_middleware (~> 1.0)
|
||||
fastimage (>= 2.1.0, < 3.0.0)
|
||||
fastlane-sirp (>= 1.0.0)
|
||||
gh_inspector (>= 1.1.2, < 2.0.0)
|
||||
google-apis-androidpublisher_v3 (~> 0.3)
|
||||
google-apis-playcustomapp_v1 (~> 0.1)
|
||||
google-cloud-env (>= 1.6.0, < 2.0.0)
|
||||
google-cloud-storage (~> 1.31)
|
||||
highline (~> 2.0)
|
||||
http-cookie (~> 1.0.5)
|
||||
json (< 3.0.0)
|
||||
jwt (>= 2.1.0, < 3)
|
||||
mini_magick (>= 4.9.4, < 5.0.0)
|
||||
multipart-post (>= 2.0.0, < 3.0.0)
|
||||
naturally (~> 2.2)
|
||||
optparse (>= 0.1.1, < 1.0.0)
|
||||
plist (>= 3.1.0, < 4.0.0)
|
||||
rubyzip (>= 2.0.0, < 3.0.0)
|
||||
security (= 0.1.5)
|
||||
simctl (~> 1.6.3)
|
||||
terminal-notifier (>= 2.0.0, < 3.0.0)
|
||||
terminal-table (~> 3)
|
||||
tty-screen (>= 0.6.3, < 1.0.0)
|
||||
tty-spinner (>= 0.8.0, < 1.0.0)
|
||||
word_wrap (~> 1.0.0)
|
||||
xcodeproj (>= 1.13.0, < 2.0.0)
|
||||
xcpretty (~> 0.3.0)
|
||||
xcpretty-travis-formatter (>= 0.0.3, < 2.0.0)
|
||||
fastlane-sirp (1.0.0)
|
||||
sysrandom (~> 1.0)
|
||||
ffi (1.17.0)
|
||||
ffi (1.17.0-x86_64-darwin)
|
||||
fourflusher (2.3.1)
|
||||
fuzzy_match (2.0.4)
|
||||
gh_inspector (1.1.3)
|
||||
google-apis-androidpublisher_v3 (0.54.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-apis-core (0.11.3)
|
||||
addressable (~> 2.5, >= 2.5.1)
|
||||
googleauth (>= 0.16.2, < 2.a)
|
||||
httpclient (>= 2.8.1, < 3.a)
|
||||
mini_mime (~> 1.0)
|
||||
representable (~> 3.0)
|
||||
retriable (>= 2.0, < 4.a)
|
||||
rexml
|
||||
google-apis-iamcredentials_v1 (0.17.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-apis-playcustomapp_v1 (0.13.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-apis-storage_v1 (0.31.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-cloud-core (1.7.1)
|
||||
google-cloud-env (>= 1.0, < 3.a)
|
||||
google-cloud-errors (~> 1.0)
|
||||
google-cloud-env (1.6.0)
|
||||
faraday (>= 0.17.3, < 3.0)
|
||||
google-cloud-errors (1.4.0)
|
||||
google-cloud-storage (1.47.0)
|
||||
addressable (~> 2.8)
|
||||
digest-crc (~> 0.4)
|
||||
google-apis-iamcredentials_v1 (~> 0.1)
|
||||
google-apis-storage_v1 (~> 0.31.0)
|
||||
google-cloud-core (~> 1.6)
|
||||
googleauth (>= 0.16.2, < 2.a)
|
||||
mini_mime (~> 1.0)
|
||||
googleauth (1.8.1)
|
||||
faraday (>= 0.17.3, < 3.a)
|
||||
jwt (>= 1.4, < 3.0)
|
||||
multi_json (~> 1.11)
|
||||
os (>= 0.9, < 2.0)
|
||||
signet (>= 0.16, < 2.a)
|
||||
highline (2.0.3)
|
||||
http-cookie (1.0.7)
|
||||
domain_name (~> 0.5)
|
||||
httpclient (2.8.3)
|
||||
i18n (1.14.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jmespath (1.6.2)
|
||||
json (2.8.1)
|
||||
jwt (2.9.3)
|
||||
base64
|
||||
mini_magick (4.13.2)
|
||||
mini_mime (1.1.5)
|
||||
minitest (5.25.1)
|
||||
molinillo (0.6.6)
|
||||
multi_json (1.15.0)
|
||||
multipart-post (2.4.1)
|
||||
nanaimo (0.4.0)
|
||||
nap (1.1.0)
|
||||
naturally (2.2.1)
|
||||
netrc (0.11.0)
|
||||
nkf (0.2.0)
|
||||
optparse (0.6.0)
|
||||
os (1.1.4)
|
||||
plist (3.7.1)
|
||||
public_suffix (6.0.1)
|
||||
rake (13.2.1)
|
||||
representable (3.2.0)
|
||||
declarative (< 0.1.0)
|
||||
trailblazer-option (>= 0.1.1, < 0.2.0)
|
||||
uber (< 0.2.0)
|
||||
retriable (3.1.2)
|
||||
rexml (3.3.9)
|
||||
rouge (2.0.7)
|
||||
ruby-macho (1.4.0)
|
||||
ruby2_keywords (0.0.5)
|
||||
rubyzip (2.3.2)
|
||||
security (0.1.5)
|
||||
signet (0.19.0)
|
||||
addressable (~> 2.8)
|
||||
faraday (>= 0.17.5, < 3.a)
|
||||
jwt (>= 1.5, < 3.0)
|
||||
multi_json (~> 1.10)
|
||||
simctl (1.6.10)
|
||||
CFPropertyList
|
||||
naturally
|
||||
sysrandom (1.0.5)
|
||||
terminal-notifier (2.0.0)
|
||||
terminal-table (3.0.2)
|
||||
unicode-display_width (>= 1.1.1, < 3)
|
||||
thread_safe (0.3.6)
|
||||
trailblazer-option (0.1.2)
|
||||
tty-cursor (0.7.1)
|
||||
tty-screen (0.8.2)
|
||||
tty-spinner (0.9.3)
|
||||
tty-cursor (~> 0.7)
|
||||
typhoeus (1.4.1)
|
||||
ethon (>= 0.9.0)
|
||||
tzinfo (1.2.11)
|
||||
thread_safe (~> 0.1)
|
||||
uber (0.1.0)
|
||||
unicode-display_width (2.6.0)
|
||||
word_wrap (1.0.0)
|
||||
xcodeproj (1.27.0)
|
||||
CFPropertyList (>= 2.3.3, < 4.0)
|
||||
atomos (~> 0.1.3)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
nanaimo (~> 0.4.0)
|
||||
rexml (>= 3.3.6, < 4.0)
|
||||
xcpretty (0.3.0)
|
||||
rouge (~> 2.0.7)
|
||||
xcpretty-travis-formatter (1.0.1)
|
||||
xcpretty (~> 0.2, >= 0.0.7)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
x86_64-darwin-23
|
||||
|
||||
DEPENDENCIES
|
||||
cocoapods
|
||||
fastlane
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.23
|
@ -1,4 +1,4 @@
|
||||
app_identifier("info.anydev.anyway") # The bundle identifier of your app
|
||||
app_identifier("info.anydev.testing") # The bundle identifier of your app
|
||||
apple_id("me@moll.re") # Your Apple Developer Portal username
|
||||
|
||||
itc_team_id("127439860") # App Store Connect Team ID
|
||||
|
@ -1,3 +0,0 @@
|
||||
# The Deliverfile allows you to store various App Store Connect metadata
|
||||
# For more information, check out the docs
|
||||
# https://docs.fastlane.tools/actions/deliver/
|
@ -15,7 +15,7 @@ platform :ios do
|
||||
|
||||
|
||||
desc "Deploy a new version to closed testing (testflight)"
|
||||
lane :deploy_beta do
|
||||
lane :deploy_testing do
|
||||
build_name = ENV["BUILD_NAME"]
|
||||
build_number = ENV["BUILD_NUMBER"]
|
||||
|
||||
@ -28,11 +28,12 @@ platform :ios do
|
||||
readonly: true,
|
||||
)
|
||||
|
||||
|
||||
sh(
|
||||
"flutter",
|
||||
"build",
|
||||
"ipa",
|
||||
"--release",
|
||||
"--debug",
|
||||
"--build-name=#{build_name}",
|
||||
"--build-number=#{build_number}",
|
||||
)
|
||||
@ -63,6 +64,16 @@ platform :ios do
|
||||
readonly: true,
|
||||
)
|
||||
|
||||
# replace secrets by real values, the stupid way
|
||||
sh(
|
||||
"sed",
|
||||
"-i",
|
||||
"",
|
||||
"s/IOS_GOOGLE_MAPS_API_KEY/#{ENV["IOS_GOOGLE_MAPS_API_KEY"]}/g",
|
||||
"../Runner/AppDelegate.swift"
|
||||
|
||||
)
|
||||
|
||||
sh(
|
||||
"flutter",
|
||||
"build",
|
||||
@ -79,11 +90,10 @@ platform :ios do
|
||||
)
|
||||
|
||||
upload_to_app_store(
|
||||
overwrite_screenshots: true,
|
||||
metadata_path: "fastlane/metadata",
|
||||
screenshots_path: "fastlane/screenshots",
|
||||
skip_screenshots: true,
|
||||
skip_metadata: true,
|
||||
precheck_include_in_app_purchases: false,
|
||||
force: true, # Skip HTMl report verification
|
||||
|
||||
submit_for_review: true,
|
||||
automatic_release: true,
|
||||
# automatically release the app after review
|
||||
|
@ -1 +0,0 @@
|
||||
2025 anydev
|
@ -1,7 +0,0 @@
|
||||
AnyWay is an application that helps you plan truly unique city trips. When planning a new trip, you can specify your preferences and constraints and anyway generates a personalized itinerary just for you.
|
||||
|
||||
Anyway follows these core principles:
|
||||
- Personalization: Trips should be match your interests - not just the most popular destinations.
|
||||
- Efficiency: Don't just walk in circles! Anyway creates the most efficient route for you.
|
||||
- Flexibility: Vacations are the time to be spontaneous. Anyway lets you update your plans on the go.
|
||||
- Discoverability: Tourism means exploration. Anyway encourages you to take detours and make spontaneous decisions.
|
@ -1 +0,0 @@
|
||||
tourism, cities, travel, guide
|
@ -1 +0,0 @@
|
||||
https://anydev.info
|
@ -1 +0,0 @@
|
||||
Any.Way
|
@ -1 +0,0 @@
|
||||
https://anydev.info/privacy
|
@ -1 +0,0 @@
|
||||
AnyWay - plan city trips your way!
|
@ -1 +0,0 @@
|
||||
|
@ -1 +0,0 @@
|
||||
Plan city trips your way!
|
@ -1 +0,0 @@
|
||||
|
@ -1 +0,0 @@
|
||||
TRAVEL
|
@ -1 +0,0 @@
|
||||
anydev.anyway@gmail.com
|
@ -1 +0,0 @@
|
||||
Remy
|
@ -1 +0,0 @@
|
||||
Moll
|
@ -1 +0,0 @@
|
||||
+4915128785827
|
@ -1 +0,0 @@
|
||||
|
@ -1,30 +0,0 @@
|
||||
## Screenshots Naming Rules
|
||||
|
||||
Put all screenshots you want to use inside the folder of its language (e.g. `en-US`).
|
||||
The device type will automatically be recognized using the image resolution.
|
||||
|
||||
The screenshots can be named whatever you want, but keep in mind they are sorted
|
||||
alphabetically, in a human-friendly way. See https://github.com/fastlane/fastlane/pull/18200 for more details.
|
||||
|
||||
### Exceptions
|
||||
|
||||
#### iPad Pro (3rd Gen) 12.9"
|
||||
|
||||
Since iPad Pro (3rd Gen) 12.9" and iPad Pro (2nd Gen) 12.9" have the same image
|
||||
resolution, screenshots of the iPad Pro (3rd gen) 12.9" must contain either the
|
||||
string `iPad Pro (12.9-inch) (3rd generation)`, `IPAD_PRO_3GEN_129`, or `ipadPro129`
|
||||
(App Store Connect's internal naming of the display family for the 3rd generation iPad Pro)
|
||||
in its filename to be assigned the correct display family and to be uploaded to
|
||||
the correct screenshot slot in your app's metadata.
|
||||
|
||||
### Other Platforms
|
||||
|
||||
#### Apple TV
|
||||
|
||||
Apple TV screenshots should be stored in a subdirectory named `appleTV` with language
|
||||
folders inside of it.
|
||||
|
||||
#### iMessage
|
||||
|
||||
iMessage screenshots, like the Apple TV ones, should also be stored in a subdirectory
|
||||
named `iMessage`, with language folders inside of it.
|
Before Width: | Height: | Size: 1.6 MiB |
Before Width: | Height: | Size: 2.1 MiB |
Before Width: | Height: | Size: 626 KiB |
Before Width: | Height: | Size: 758 KiB |
Before Width: | Height: | Size: 2.2 MiB |
Before Width: | Height: | Size: 2.5 MiB |
Before Width: | Height: | Size: 574 KiB |
Before Width: | Height: | Size: 800 KiB |
@ -1,26 +1,24 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:anyway/constants.dart';
|
||||
import 'package:anyway/utils/get_first_page.dart';
|
||||
import 'package:anyway/utils/load_trips.dart';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:anyway/constants.dart';
|
||||
|
||||
void main() => runApp(const App());
|
||||
|
||||
// Some global variables
|
||||
final GlobalKey<ScaffoldMessengerState> rootScaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
|
||||
final SavedTrips savedTrips = SavedTrips();
|
||||
// the list of saved trips is then populated implicitly by getFirstPage()
|
||||
|
||||
|
||||
class App extends StatelessWidget {
|
||||
const App({super.key});
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => MaterialApp(
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: APP_NAME,
|
||||
home: getFirstPage(),
|
||||
theme: APP_THEME,
|
||||
scaffoldMessengerKey: rootScaffoldMessengerKey
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -16,27 +16,22 @@ class CurrentTripErrorMessage extends StatefulWidget {
|
||||
class _CurrentTripErrorMessageState extends State<CurrentTripErrorMessage> {
|
||||
@override
|
||||
Widget build(BuildContext context) => Center(
|
||||
child: Column(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
"😢",
|
||||
style: TextStyle(
|
||||
fontSize: 40,
|
||||
const Icon(
|
||||
Icons.error_outline,
|
||||
color: Colors.red,
|
||||
size: 50,
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(left: 10),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
AutoSizeText(
|
||||
// at this point the trip is guaranteed to have an error message
|
||||
widget.trip.errorDescription!,
|
||||
maxLines: 30,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
textAlign: TextAlign.center,
|
||||
|
||||
'Error: ${widget.trip.errorDescription}',
|
||||
maxLines: 3,
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
|
@ -1,18 +1,20 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:anyway/modules/step_between_landmarks.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:anyway/modules/landmark_card.dart';
|
||||
import 'package:anyway/structs/landmark.dart';
|
||||
import 'package:anyway/structs/trip.dart';
|
||||
import 'package:anyway/modules/step_between_landmarks.dart';
|
||||
import 'package:anyway/modules/landmark_card.dart';
|
||||
|
||||
|
||||
// Returns a list of widgets that represent the landmarks matching the given selector
|
||||
List<Widget> landmarksList(Trip trip, {required bool Function(Landmark) selector}) {
|
||||
|
||||
List<Widget> landmarksList(Trip trip) {
|
||||
log("Trip ${trip.uuid} ${trip.landmarks.length} landmarks");
|
||||
|
||||
List<Widget> children = [];
|
||||
|
||||
log("Trip ${trip.uuid} ${trip.landmarks.length} landmarks");
|
||||
|
||||
if (trip.landmarks.isEmpty || trip.landmarks.length <= 1 && trip.landmarks.first.type == typeStart ) {
|
||||
children.add(
|
||||
const Text("No landmarks in this trip"),
|
||||
@ -21,24 +23,17 @@ List<Widget> landmarksList(Trip trip, {required bool Function(Landmark) selector
|
||||
}
|
||||
|
||||
for (Landmark landmark in trip.landmarks) {
|
||||
if (selector(landmark)) {
|
||||
children.add(
|
||||
LandmarkCard(landmark, trip),
|
||||
);
|
||||
|
||||
if (!landmark.visited) {
|
||||
Landmark? nextLandmark = landmark.next;
|
||||
while (nextLandmark != null && nextLandmark.visited) {
|
||||
nextLandmark = nextLandmark.next;
|
||||
}
|
||||
if (nextLandmark != null) {
|
||||
if (landmark.next != null) {
|
||||
children.add(
|
||||
StepBetweenLandmarks(current: landmark, next: nextLandmark!)
|
||||
StepBetweenLandmarks(current: landmark, next: landmark.next!)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
|