Add binoculars theme, auto reformat everything

This commit is contained in:
pietervdvn 2021-09-09 00:05:51 +02:00
parent 38dea806c5
commit 78d6482c88
586 changed files with 115573 additions and 111842 deletions

View file

@ -9,16 +9,14 @@
"VARIANT": "14"
}
},
// Set *default* container specific settings.json values on container create.
"settings": {},
// Add the IDs of extensions you want installed when the container is created.
"extensions": [],
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [1234],
"forwardPorts": [
1234
],
// Use 'postCreateCommand' to run commands after the container is created.
//"postCreateCommand": "npm run init",

View file

@ -1,9 +1,8 @@
Opening a pull request on MapComplete
=====================================
Hey! Thanks for opening a pull request on Mapcomplete! This probably means you want to add a new theme - if so, please follow the checklist below.
If this pull request is for some other issue, please ignore the template.
Hey! Thanks for opening a pull request on Mapcomplete! This probably means you want to add a new theme - if so, please
follow the checklist below. If this pull request is for some other issue, please ignore the template.
Adding your new theme
---------------------
@ -14,4 +13,6 @@ To making merging smooth, please make sure that each of the following conditions
- [ ] The codebase is GPL-licensed. By opening a pull request, the new theme will be GPL too
- [ ] All images are included in the pull request and no images are loaded from an external service (e.g. Wikipedia)
- [ ] The [guidelines on how to make your own theme](https://github.com/pietervdvn/MapComplete/blob/master/Docs/Making_Your_Own_Theme.md) are read and followed
- [ ]
The [guidelines on how to make your own theme](https://github.com/pietervdvn/MapComplete/blob/master/Docs/Making_Your_Own_Theme.md)
are read and followed

View file

@ -1,7 +1,8 @@
Architecture
============
This document aims to give an architectural overview of how MapCompelte is built. It should give some feeling on how everything fits together.
This document aims to give an architectural overview of how MapCompelte is built. It should give some feeling on how
everything fits together.
Servers?
--------
@ -11,24 +12,30 @@ There are no servers for MapComplete, all services are configured by third parti
Minimal HTML - Minimal CSS
--------------------------
There is quasi no HTML. Most of the components are generated by TypeScript and attached dynamically. The html is a barebones skeleton which serves every theme.
There is quasi no HTML. Most of the components are generated by TypeScript and attached dynamically. The html is a
barebones skeleton which serves every theme.
The UIEventSource
-----------------
Most (but not all) objects in MapComplete get all the state they need as a parameter in the constructor. However, as is the case with most graphical applications, there are quite some dynamical values.
Most (but not all) objects in MapComplete get all the state they need as a parameter in the constructor. However, as is
the case with most graphical applications, there are quite some dynamical values.
All values which change regularly are wrapped into a [UIEventSource](https://github.com/pietervdvn/MapComplete/blob/master/Logic/UIEventSource.ts).
An UiEventSource is a wrapper containing a value and offers the possibility to add a callback function which is called every time the value is changed (with setData)
All values which change regularly are wrapped into
a [UIEventSource](https://github.com/pietervdvn/MapComplete/blob/master/Logic/UIEventSource.ts). An UiEventSource is a
wrapper containing a value and offers the possibility to add a callback function which is called every time the value is
changed (with setData)
Furthermore, there are various helper functions, the most widely used one being `map` - generating a new event source with the new value applied.
Note that 'map' will also absorb some changes, e.g. `const someEventSource : UIEventSource<string[]> = ... ; someEventSource.map(list = list.length)` will only trigger when the length of the list has changed.
Furthermore, there are various helper functions, the most widely used one being `map` - generating a new event source
with the new value applied. Note that 'map' will also absorb some changes,
e.g. `const someEventSource : UIEventSource<string[]> = ... ; someEventSource.map(list = list.length)` will only trigger
when the length of the list has changed.
An object which receives an UIEventSource is responsible of responding onto changes of this object. This is especially true for UI-components
An object which receives an UIEventSource is responsible of responding onto changes of this object. This is especially
true for UI-components
UI
--```
UI --```
export default class MyComponent {
@ -37,6 +44,7 @@ export default class MyComponent {
}
}
```
The Graphical User Interface is composed of various UI-elements. For every UI-element, there is a BaseUIElement which creates the actual HTMLElement when needed.
@ -55,9 +63,9 @@ For example:
```
const src : UIEventSource<string> = ... // E.g. user input, data that will be updated...
new VariableUIElement(src)
const src : UIEventSource<string> = ... // E.g. user input, data that will be updated... new VariableUIElement(src)
.AttachTo('some-id') // attach it to the html
```
Note that every component offers support for `onClick( someCallBack)`
@ -109,6 +117,7 @@ This can be constructed as following:
```
// We construct the dropdown element with values and labelshttps://tailwindcss.com/
const isOpened = new Dropdown<string>(Translations.t.is_this_shop_opened_during_holidays,
[
@ -127,6 +136,7 @@ This can be constructed as following:
)
return new Combine([isOpened, extraQuestion])
```
### Constructing a special class
@ -144,6 +154,7 @@ export default class MyComponent {
}
}
```
2. Construct the needed UI in the constructor
@ -166,6 +177,7 @@ export default class MyComponent {
}
}
```
3. You'll notice that you'll end up with one certain component (in this example the combine) to wrap it all together. Change the class to extend this type of component and use super to wrap it all up:

View file

@ -1,5 +1,3 @@
Metatags
==========
@ -7,9 +5,11 @@
Metatags are extra tags available, in order to display more data or to give better questions.
The are calculated automatically on every feature when the data arrives in the webbrowser. This document gives an overview of the available metatags.
The are calculated automatically on every feature when the data arrives in the webbrowser. This document gives an
overview of the available metatags.
**Hint:** when using metatags, add the [query parameter](URL_Parameters.md) `debug=true` to the URL. This will include a box in the popup for features which shows all the properties of the object
**Hint:** when using metatags, add the [query parameter](URL_Parameters.md) `debug=true` to the URL. This will include a
box in the popup for features which shows all the properties of the object
Metatags calculated by MapComplete
@ -17,76 +17,53 @@ The are calculated automatically on every feature when the data arrives in the w
The following values are always calculated, by default, by MapComplete and are available automatically on all elements in every theme
The following values are always calculated, by default, by MapComplete and are available automatically on all elements
in every theme
### _lat, _lon
The latitude and longitude of the point (or centerpoint in the case of a way/area)
### _surface, _surface:ha
The surface area of the feature, in square meters and in hectare. Not set on points and ways
### _length, _length:km
The total length of a feature in meters (and in kilometers, rounded to one decimal for '_length:km'). For a surface, the length of the perimeter
The total length of a feature in meters (and in kilometers, rounded to one decimal for '_length:km'). For a surface, the
length of the perimeter
### Theme-defined keys
If 'units' is defined in the layoutConfig, then this metatagger will rewrite the specified keys to have the canonical form (e.g. `1meter` will be rewritten to `1m`)
If 'units' is defined in the layoutConfig, then this metatagger will rewrite the specified keys to have the canonical
form (e.g. `1meter` will be rewritten to `1m`)
### _country
The country code of the property (with latlon2country)
### _isOpen, _isOpen:description
If 'opening_hours' is present, it will add the current state of the feature (being 'yes' or 'no')
### _width:needed, _width:needed:no_pedestrians, _width:difference
Legacy for a specific project calculating the needed width for safe traffic on a road. Only activated if 'width:carriageway' is present
Legacy for a specific project calculating the needed width for safe traffic on a road. Only activated if 'width:
carriageway' is present
### _direction:numerical, _direction:leftright
_direction:numerical is a normalized, numerical direction based on 'camera:direction' or on 'direction'; it is only present if a valid direction is found (e.g. 38.5 or NE). _direction:leftright is either 'left' or 'right', which is left-looking on the map or 'right-looking' on the map
_direction:numerical is a normalized, numerical direction based on 'camera:direction' or on 'direction'; it is only
present if a valid direction is found (e.g. 38.5 or NE). _direction:leftright is either 'left' or 'right', which is
left-looking on the map or 'right-looking' on the map
### _now:date, _now:datetime, _loaded:date, _loaded:_datetime
Adds the time that the data got loaded - pretty much the time of downloading from overpass. The format is YYYY-MM-DD hh:mm, aka 'sortable' aka ISO-8601-but-not-entirely
Adds the time that the data got loaded - pretty much the time of downloading from overpass. The format is YYYY-MM-DD hh:
mm, aka 'sortable' aka ISO-8601-but-not-entirely
### _last_edit:contributor, _last_edit:contributor:uid, _last_edit:changeset, _last_edit:timestamp, _version_number
Information about the last edit of this object.
@ -95,20 +72,18 @@ Information about the last edit of this object.
In some cases, it is useful to have some tags calculated based on other properties. Some useful tags are available by default (e.g. `lat`, `lon`, `_country`), as detailed above.
In some cases, it is useful to have some tags calculated based on other properties. Some useful tags are available by
default (e.g. `lat`, `lon`, `_country`), as detailed above.
It is also possible to calculate your own tags - but this requires some javascript knowledge.
Before proceeding, some warnings:
- DO NOT DO THIS AS BEGINNER
- **Only do this if all other techniques fail** This should _not_ be done to create a rendering effect, only to calculate a specific value
- **THIS MIGHT BE DISABLED WITHOUT ANY NOTICE ON UNOFFICIAL THEMES** As unofficial themes might be loaded from the internet, this is the equivalent of injecting arbitrary code into the client. It'll be disabled if abuse occurs.
- **Only do this if all other techniques fail** This should _not_ be done to create a rendering effect, only to
calculate a specific value
- **THIS MIGHT BE DISABLED WITHOUT ANY NOTICE ON UNOFFICIAL THEMES** As unofficial themes might be loaded from the
internet, this is the equivalent of injecting arbitrary code into the client. It'll be disabled if abuse occurs.
To enable this feature, add a field `calculatedTags` in the layer object, e.g.:
@ -126,16 +101,12 @@ To enable this feature, add a field `calculatedTags` in the layer object, e.g.:
````
The above code will be executed for every feature in the layer. The feature is accessible as `feat` and is an amended geojson object:
The above code will be executed for every feature in the layer. The feature is accessible as `feat` and is an amended
geojson object:
- `area` contains the surface area (in square meters) of the object
- `lat` and `lon` contain the latitude and longitude
Some advanced functions are available on **feat** as well:
- distanceTo
@ -146,20 +117,25 @@ Some advanced functions are available on **feat** as well:
### distanceTo
Calculates the distance between the feature and a specified point in kilometer. The input should either be a pair of coordinates, a geojson feature or the ID of an object
Calculates the distance between the feature and a specified point in kilometer. The input should either be a pair of
coordinates, a geojson feature or the ID of an object
0. longitude
1. latitude
### overlapWith
Gives a list of features from the specified layer which this feature (partly) overlaps with. If the current feature is a point, all features that embed the point are given. The returned value is `{ feat: GeoJSONFeature, overlap: number}[]` where `overlap` is the overlapping surface are (in m²) for areas, the overlapping length (in meter) if the current feature is a line or `undefined` if the current feature is a point
Gives a list of features from the specified layer which this feature (partly) overlaps with. If the current feature is a
point, all features that embed the point are given. The returned value is `{ feat: GeoJSONFeature, overlap: number}[]`
where `overlap` is the overlapping surface are (in m²) for areas, the overlapping length (in meter) if the current
feature is a line or `undefined` if the current feature is a point
0. ...layerIds - one or more layer ids of the layer from which every feature is checked for overlap)
### closest
Given either a list of geojson features or a single layer name, gives the single object which is nearest to the feature. In the case of ways/polygons, only the centerpoint is considered.
Given either a list of geojson features or a single layer name, gives the single object which is nearest to the feature.
In the case of ways/polygons, only the centerpoint is considered.
0. list of features
@ -169,13 +145,12 @@ Some advanced functions are available on **feat** as well:
For example: `_part_of_walking_routes=feat.memberships().map(r => r.relation.tags.name).join(';')`
### score
Given the path of an aspected routing json file, will calculate the score. This score is wrapped in a UIEventSource, so for further calculations, use `.map(score => ...)`
Given the path of an aspected routing json file, will calculate the score. This score is wrapped in a UIEventSource, so
for further calculations, use `.map(score => ...)`
For example: `_comfort_score=feat.score('https://raw.githubusercontent.com/pietervdvn/AspectedRouting/master/Examples/bicycle/aspects/bicycle.comfort.json')`
For
example: `_comfort_score=feat.score('https://raw.githubusercontent.com/pietervdvn/AspectedRouting/master/Examples/bicycle/aspects/bicycle.comfort.json')`
0. path
Generated from SimpleMetaTagger, ExtraFunction
0. path Generated from SimpleMetaTagger, ExtraFunction

View file

@ -1,4 +1,3 @@
Development and deployment
==========================
@ -6,28 +5,37 @@
This documents attempts to shed some light on these scripts.
Note: these scripts change every now and then - if the documentation here is incorrect or you run into troubles, do leave a message in [the issue tracker](https://github.com/pietervdvn/MapComplete/issues)
Note: these scripts change every now and then - if the documentation here is incorrect or you run into troubles, do
leave a message in [the issue tracker](https://github.com/pietervdvn/MapComplete/issues)
Architecture overview
---------------------
At its core, MapComplete is a static (!) website. There are no servers to host.
The data is fetched from Overpass/OSM/Wikidata/Wikipedia/Mapillary/... and written there directly. This means that any static file server will do to create a self-hosted version of MapComplete.
The data is fetched from Overpass/OSM/Wikidata/Wikipedia/Mapillary/... and written there directly. This means that any
static file server will do to create a self-hosted version of MapComplete.
Development
-----------
**Windows users**: All scripts are made for linux devices. Use the Ubuntu terminal for Windows (or even better - make the switch ;) ). If you are using Visual Studio Code you can use a [WSL Remote](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-wsl) window, or use the Devcontainer (see more details later).
**Windows users**: All scripts are made for linux devices. Use the Ubuntu terminal for Windows (or even better - make
the switch ;) ). If you are using Visual Studio Code you can use
a [WSL Remote](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-wsl) window, or use the
Devcontainer (see more details later).
To develop and build MapComplete, you
0. Make sure you have a recent version of nodejs - at least 12.0, preferably 15
0. Make a fork and clone the repository.
1. Install `npm`. Linux: `sudo apt install npm` (or your favourite package manager), Windows: install nodeJS: https://nodejs.org/en/download/
3. Run `npm run init` and generate some additional dependencies and generated files. Note that it'll install the dependencies too
1. Install `npm`. Linux: `sudo apt install npm` (or your favourite package manager), Windows: install
nodeJS: https://nodejs.org/en/download/
3. Run `npm run init` and generate some additional dependencies and generated files. Note that it'll install the
dependencies too
4. Run `npm run start` to host a local testversion at http://localhost:1234/index.html
5. By default, a landing page with available themes is served. In order to load a single theme, use `layout=themename` or `userlayout=true#<layout configuration>` as [Query parameter](URL_Parameters.md). Note that the shorter URLs (e.g. `bookcases.html`, `aed.html`, ...) _don't_ exist on the development version.
5. By default, a landing page with available themes is served. In order to load a single theme, use `layout=themename`
or `userlayout=true#<layout configuration>` as [Query parameter](URL_Parameters.md). Note that the shorter URLs (
e.g. `bookcases.html`, `aed.html`, ...) _don't_ exist on the development version.
Development using Windows
------------------------
@ -36,12 +44,16 @@
To use the devcontainer in Visual Studio Code:
0. Make sure you have installed the [Remote - Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension and it's dependencies.
0. Make sure you have installed
the [Remote - Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
extension and it's dependencies.
1. Make a fork and clone the repository.
2. After cloning, Visual Studio Code will ask you if you want to use the devcontainer.
3. Then you can either clone it again in a volume (for better performance), or open the current folder in a container.
4. By now, you should be able to run `npm run start` to host a local testversion at http://localhost:1234/index.html
5. By default, a landing page with available themes is served. In order to load a single theme, use `layout=themename` or `userlayout=true#<layout configuration>` as [Query parameter](URL_Parameters.md). Note that the shorter URLs (e.g. `bookcases.html`, `aed.html`, ...) _don't_ exist on the development version.
5. By default, a landing page with available themes is served. In order to load a single theme, use `layout=themename`
or `userlayout=true#<layout configuration>` as [Query parameter](URL_Parameters.md). Note that the shorter URLs (
e.g. `bookcases.html`, `aed.html`, ...) _don't_ exist on the development version.
To use the WSL in Visual Studio Code:
@ -49,10 +61,12 @@
1. Open a remote WSL window using the button in the bottom left.
2. Make a fork and clone the repository.
3. Install `npm` using `sudo apt install npm`.
4. Run `npm run init` and generate some additional dependencies and generated files. Note that it'll install the dependencies too
4. Run `npm run init` and generate some additional dependencies and generated files. Note that it'll install the
dependencies too
5. Run `npm run start` to host a local testversion at http://localhost:1234/index.html
6. By default, a landing page with available themes is served. In order to load a single theme, use `layout=themename` or `userlayout=true#<layout configuration>` as [Query parameter](URL_Parameters.md). Note that the shorter URLs (e.g. `bookcases.html`, `aed.html`, ...) _don't_ exist on the development version.
6. By default, a landing page with available themes is served. In order to load a single theme, use `layout=themename`
or `userlayout=true#<layout configuration>` as [Query parameter](URL_Parameters.md). Note that the shorter URLs (
e.g. `bookcases.html`, `aed.html`, ...) _don't_ exist on the development version.
Automatic deployment
--------------------
@ -71,15 +85,14 @@
- have individual social images
- have individual web manifests
This script can be invoked with `npm run prepare-deploy`
If you want to deploy your fork:
0. `npm run prepare-deploy`
1. `npm run build`
2. Copy the entire `dist` folder to where you host your website. Visiting `index.html` gives you the landing page, visiting `yourwebsite/<theme>` should bring you to the appropriate theme.
2. Copy the entire `dist` folder to where you host your website. Visiting `index.html` gives you the landing page,
visiting `yourwebsite/<theme>` should bring you to the appropriate theme.
Weird errors
------------
@ -96,8 +109,10 @@ Try removing `node_modules`, `package-lock.json` and `.cache`
- `generate:editor-layer-index`: downloads the editor-layer-index-json from osmlab.github.io
- `generate:images`: compiles the SVG's into an asset
- `generate:translations`: compiles the translation file into a javascript file
- `generate:layouts`: uses `index.html` as template to create all the theme index pages. You'll want to run `clean` when done
- `generate:docs`: generates various documents, such as information about available metatags, information to put on the [OSM-wiki](https://wiki.openstreetmap.org/wiki/MapComplete),...
- `generate:layouts`: uses `index.html` as template to create all the theme index pages. You'll want to run `clean` when
done
- `generate:docs`: generates various documents, such as information about available metatags, information to put on
the [OSM-wiki](https://wiki.openstreetmap.org/wiki/MapComplete),...
- `generate:report`: downloads statistics from OsmCha, compiles neat graphs
- `generate:cache:speelplekken`: creates an offline copy of all the data required for one specific (paid for) theme
- `generate:layeroverview`: reads all the theme- and layerconfigurations, compiles them into a single JSON.

View file

@ -1,28 +1,45 @@
Gebruikersgids MapComplete
==========================
MapComplete is een website waar geodata op basis van [OpenStreetMap](https://osm.org), [Wikidata](https://wikidata.org) en andere open bronnen wordt gevisualiseerd en aangevuld.
MapComplete is een website waar geodata op basis van [OpenStreetMap](https://osm.org), [Wikidata](https://wikidata.org)
en andere open bronnen wordt gevisualiseerd en aangevuld.
De getoonde geodata is afhankelijk van het thema - zo is er bijvoorbeeld het thema voor [boekenruilkasten](https://mapcomplete.osm.be/bookcases) [cyclofix](http://mapcomplete.osm.be/cyclofix) die focust op fietspompen, fietswinkels, ...
De getoonde geodata is afhankelijk van het thema - zo is er bijvoorbeeld het thema
voor [boekenruilkasten](https://mapcomplete.osm.be/bookcases) [cyclofix](http://mapcomplete.osm.be/cyclofix) die focust
op fietspompen, fietswinkels, ...
MapComplete mag gratis gebruikt worden. Om de data te raadplegen heb je geen account nodig - de webpagina bezoeken is voldoende.
MapComplete mag gratis gebruikt worden. Om de data te raadplegen heb je geen account nodig - de webpagina bezoeken is
voldoende.
### Data toevoegen
OpenStreetMap is een gedeelde databank van geodata. Om die correct en up to date te houden, voegen we _enkel_ gegevens toe waarvan we zeker weten dat die op dit moment ook zo zijn in de echte wereld. Twijfel je dus over een vraag? Sla de vraag dan over en ga opnieuw ter plaatse kijken. **Beter geen informatie dan foute informatie**.
OpenStreetMap is een gedeelde databank van geodata. Om die correct en up to date te houden, voegen we _enkel_ gegevens
toe waarvan we zeker weten dat die op dit moment ook zo zijn in de echte wereld. Twijfel je dus over een vraag? Sla de
vraag dan over en ga opnieuw ter plaatse kijken. **Beter geen informatie dan foute informatie**.
Daarnaast verwachten we ook dat je op een vriendelijke en correcte manier omgaat met andere leden van de community. Je kan feedback of vragen krijgen over je aanpassingen - bijvoorbeeld wanneer andere bijdragers denken dat er een vergissing is gebeurd. Meestal is de vergissing met een paar heen- en weerberichtjes uitgeklaard. Vergissen is menselijk.
Daarnaast verwachten we ook dat je op een vriendelijke en correcte manier omgaat met andere leden van de community. Je
kan feedback of vragen krijgen over je aanpassingen - bijvoorbeeld wanneer andere bijdragers denken dat er een
vergissing is gebeurd. Meestal is de vergissing met een paar heen- en weerberichtjes uitgeklaard. Vergissen is
menselijk.
Als je bijdragen grote fouten bevatten, kunnen je wijzigingen ongedaan gemaakt worden door andere leden van OpenStreetMap. Dit is echter erg uitzonderlijk. Bij herhaaldelijke grote fouten, (vermoeden van) kwaad opzet of vandalisme kan je account geblokkeerd worden. Merk op dat MapComplete is opgezet om (grote) vergissingen te vermijden, dus dit is bijna onmogelijk.
Als je bijdragen grote fouten bevatten, kunnen je wijzigingen ongedaan gemaakt worden door andere leden van
OpenStreetMap. Dit is echter erg uitzonderlijk. Bij herhaaldelijke grote fouten, (vermoeden van) kwaad opzet of
vandalisme kan je account geblokkeerd worden. Merk op dat MapComplete is opgezet om (grote) vergissingen te vermijden,
dus dit is bijna onmogelijk.
Data hergebruiken
-----------------
De getoonde data (locaties van POI, ...) mogen vrij en gratis hergebruikt worden voor alle doeleinden (ook commercieel), mits de vermelding `Data van OpenStreetMap, vrij beschikbaar onder ODBL` of een gelijkaardige zin. Hiervoor hoef je geen toestemming te vragen.
De getoonde data (locaties van POI, ...) mogen vrij en gratis hergebruikt worden voor alle doeleinden (ook commercieel),
mits de vermelding `Data van OpenStreetMap, vrij beschikbaar onder ODBL` of een gelijkaardige zin. Hiervoor hoef je geen
toestemming te vragen.
Let op: aanpassingen aan de data worden ook als open data beschouwd. Let ook op wanneer je OpenStreetMap-data gaat mengen uit andere databronnen waar copyright op rust; vaak mag dit niet. Voor meer informatie, zie de [volledige copyrightnotice](https://osm.org/copyright).
Let op: aanpassingen aan de data worden ook als open data beschouwd. Let ook op wanneer je OpenStreetMap-data gaat
mengen uit andere databronnen waar copyright op rust; vaak mag dit niet. Voor meer informatie, zie
de [volledige copyrightnotice](https://osm.org/copyright).
Om de data als computerbestand op te vragen, bestaan er [verschillende opties](https://learnosm.org/en/osm-data/getting-data/).
Om de data als computerbestand op te vragen, bestaan
er [verschillende opties](https://learnosm.org/en/osm-data/getting-data/).
Privacy
-------
@ -31,17 +48,24 @@ Privacy
Zolang je je niet aanmeldt, worden er geen persoonsgegevens opgeslaan.
Je computer stuurt echter wel een klein berichtje naar [pietervdvn.goatcounter.com](pietervdvn.goatcounter.com), waar statistieken over de bezoekersaantallen worden bijgehouden. Dit omvat een minimum aan technische gegevens en kan niet gelinkt worden aan een OSM-gebruikersaccount of persoon door de makers van MapComplete.
Je computer stuurt echter wel een klein berichtje naar [pietervdvn.goatcounter.com](pietervdvn.goatcounter.com), waar
statistieken over de bezoekersaantallen worden bijgehouden. Dit omvat een minimum aan technische gegevens en kan niet
gelinkt worden aan een OSM-gebruikersaccount of persoon door de makers van MapComplete.
### Met account
Wanneer je een account maakt, is dit een account op OpenStreetMap. Voor je een account maakt, gelieve hun [privacy statement](https://wiki.osmfoundation.org/wiki/Privacy_Policy) te lezen.
Wanneer je een account maakt, is dit een account op OpenStreetMap. Voor je een account maakt, gelieve
hun [privacy statement](https://wiki.osmfoundation.org/wiki/Privacy_Policy) te lezen.
Een account maken is gratis, je moet enkel een email-adres en gebruikersnaam opgeven. Je email-adres is niet publiek zichtbaar, je gebruikersnaam wel.
Een account maken is gratis, je moet enkel een email-adres en gebruikersnaam opgeven. Je email-adres is niet publiek
zichtbaar, je gebruikersnaam wel.
Je kan opteren om een _pseudoniem_ te gebruiken - je gebruikersnaam hoeft niet je echte naam te zijn. Ook de naam van je huisdier of iets zelfbedacht mag gerust.
Je kan opteren om een _pseudoniem_ te gebruiken - je gebruikersnaam hoeft niet je echte naam te zijn. Ook de naam van je
huisdier of iets zelfbedacht mag gerust.
Wanneer je gegevens aanvult via MapComplete, zal je wijziging **publiek zichtbaar** zijn voor iedereen ter wereld. Dit betekent dus dat iedereen weet dat _gebruikersnaam_ op een bepaalde plaats op een bepaald uur aanwezig was.
Wanneer je gegevens aanvult via MapComplete, zal je wijziging **publiek zichtbaar** zijn voor iedereen ter wereld. Dit
betekent dus dat iedereen weet dat _gebruikersnaam_ op een bepaalde plaats op een bepaald uur aanwezig was.
**Ben je minderjarig?** Vraag toestemming aan je ouders voordat je een account aanmaakt en kies ervoor om je echte naam _niet_ te gebruiken.
**Ben je minderjarig?** Vraag toestemming aan je ouders voordat je een account aanmaakt en kies ervoor om je echte
naam _niet_ te gebruiken.

View file

@ -1,7 +1,8 @@
Making your own theme
=====================
In MapComplete, it is relatively simple to make your own theme. This guide will give some information on how you can do this.
In MapComplete, it is relatively simple to make your own theme. This guide will give some information on how you can do
this.
Requirements
------------
@ -11,17 +12,22 @@ Before you start, you should have the following qualifications:
- You are a longtime contributor and do know the OpenStreetMap tagging scheme very well.
- You are not afraid of editing a .JSON-file
- You're theme will add well-understood tags (aka: the tags have a wiki page, are not controversial and are objective)
- You are in contact with your local OpenStreetMap community and do know some other members to discuss tagging and to help testing
- You are in contact with your local OpenStreetMap community and do know some other members to discuss tagging and to
help testing
If you do not have those qualifications, reach out to the MapComplete community channel on [Telegram](https://t.me/MapComplete)
If you do not have those qualifications, reach out to the MapComplete community channel
on [Telegram](https://t.me/MapComplete)
or [Matrix](https://app.element.io/#/room/#MapComplete:matrix.org).
The custom theme generator
--------------------------
The custom theme generator is a special page of MapComplete, where one can create their own theme. It makes it easier to get started.
The custom theme generator is a special page of MapComplete, where one can create their own theme. It makes it easier to
get started.
However, the custom theme generator is extremely buggy and built before some updates. This means that some features are _not_ available through the custom theme generator. The custom theme generator is good to get the basics of the theme set up, but you will have to edit the raw JSON-file anyway afterwards.
However, the custom theme generator is extremely buggy and built before some updates. This means that some features
are _not_ available through the custom theme generator. The custom theme generator is good to get the basics of the
theme set up, but you will have to edit the raw JSON-file anyway afterwards.
[A quick tutorial for the custom theme generator can be found here](https://www.youtube.com/watch?v=nVbFrNVPxPw).
@ -30,48 +36,67 @@ Loading your theme
If you have your .json file, there are three ways to distribute your theme:
- Take the entire JSON-file and [base64](https://www.base64encode.org/) encode it. Then open up the url `https://mapcomplete.osm.be?userlayout=true#<base64-encoded-json-here>`. Yes, this URL will be huge; and updates are difficult to distribute as you have to send a new URL to everyone. This is however excellent to have a 'quick and dirty' test version up and running as these links can be generated from the customThemeGenerator and can be quickly shared with a few other contributors.
- Host the JSON file on a publicly accessible webserver (e.g. github) and open up `https://mapcomplete.osm.be?userlayout=<url-to-the-raw.json>`
- Take the entire JSON-file and [base64](https://www.base64encode.org/) encode it. Then open up the
url `https://mapcomplete.osm.be?userlayout=true#<base64-encoded-json-here>`. Yes, this URL will be huge; and updates
are difficult to distribute as you have to send a new URL to everyone. This is however excellent to have a 'quick and
dirty' test version up and running as these links can be generated from the customThemeGenerator and can be quickly
shared with a few other contributors.
- Host the JSON file on a publicly accessible webserver (e.g. github) and open
up `https://mapcomplete.osm.be?userlayout=<url-to-the-raw.json>`
- Ask to have your theme included into the official MapComplete - requirements below
### Getting your theme included into the official mapcomplete
Did you make an awesome theme that you want to share with the OpenStreetMap community? Have it included in the main application, which makes it more discoverable.
Did you make an awesome theme that you want to share with the OpenStreetMap community? Have it included in the main
application, which makes it more discoverable.
Your theme has to be:
0) Make sure the theme has an English version. This makes it easier for me to understand what is going on. The more other languages, the better of course!
0) Make sure the theme has an English version. This makes it easier for me to understand what is going on. The more
other languages, the better of course!
1) Make sure your theme has good tagging
3) Make sure there are somewhat decent icons. Note that there is _no_ styleguide at the moment though.
The preferred way to add your theme is via a Pull Request. A Pull Request is less work for the maintainer (which makes it really easy and for me to add it) and your name will be included in the git history (so you'll be listed as contributor). If that is not possible, send the .Json-file and assets, e.g. as a zip in an issue, per email, ...
The preferred way to add your theme is via a Pull Request. A Pull Request is less work for the maintainer (which makes
it really easy and for me to add it) and your name will be included in the git history (so you'll be listed as
contributor). If that is not possible, send the .Json-file and assets, e.g. as a zip in an issue, per email, ...
*Via a pull request:*
1) Fork this repository
2) Go to `assets/themes` and create a new directory `yourtheme`
3) Create a new file `yourtheme.json`, paste the theme configuration in there. You can find your theme configuration in the customThemeBuilder (the tab with the *Floppy disk* icon)
4) Copy all the images into this new directory. **No external sources are allowed!** External image sources leak privacy or can break.
3) Create a new file `yourtheme.json`, paste the theme configuration in there. You can find your theme configuration in
the customThemeBuilder (the tab with the *Floppy disk* icon)
4) Copy all the images into this new directory. **No external sources are allowed!** External image sources leak privacy
or can break.
- Make sure the license is suitable, preferable a Creative Commons license or CC0-license.
- If an SVG version is available, use the SVG version
- Make sure all the links in `yourtheme.json` are updated. You can use `./assets/themes/yourtheme/yourimage.svg` instead of the HTML link
- Make sure all the links in `yourtheme.json` are updated. You can use `./assets/themes/yourtheme/yourimage.svg`
instead of the HTML link
- Create a file `license_info.json` in the theme directory, which contains metadata on every artwork source
5) Add your theme to the code base: add it into "assets/themes" and make sure all the images are there too. Running 'ts-node scripts/fixTheme <path to your theme>' will help downloading the images and attempts to get the licenses if on wikimedia.
6) Add some finishing touches, such as a social image. See [this blog post](https://www.h3xed.com/web-and-internet/how-to-use-og-image-meta-tag-facebook-reddit) for some hints
5) Add your theme to the code base: add it into "assets/themes" and make sure all the images are there too. Running '
ts-node scripts/fixTheme <path to your theme>' will help downloading the images and attempts to get the licenses if
on wikimedia.
6) Add some finishing touches, such as a social image.
See [this blog post](https://www.h3xed.com/web-and-internet/how-to-use-og-image-meta-tag-facebook-reddit) for some
hints
7) Test your theme: run the project as described in [development_deployment](Development_deployment.md)
8) Happy with your theme? Time to open a Pull Request!
9) Thanks a lot for improving MapComplete!
The .JSON-format
----------------
There are three important levels in the .JSON-file:
- The toplevel describes the metadata of the entire theme. It contains the `title`, `description`, `icon`... of the theme. The most important object is `layers`, which is a list of objects describing layers.
- A `layer` describes a layer. It contains the `name`, `icon`, `tags of objects to download from overpass`, and especially the `icon` and a way to ask dynamically render tags and ask questions. A lot of those fields (`icon`, `title`, ...) are actually a `TagRendering`
- A `TagRendering` is an object describing a relationship between what should be shown on screen and the OSM-tagging. It works in two ways: if the correct tag is known, the appropriate text will be shown. If the tag is missing (and a question is defined), the question will be shown.
- The toplevel describes the metadata of the entire theme. It contains the `title`, `description`, `icon`... of the
theme. The most important object is `layers`, which is a list of objects describing layers.
- A `layer` describes a layer. It contains the `name`, `icon`, `tags of objects to download from overpass`, and
especially the `icon` and a way to ask dynamically render tags and ask questions. A lot of those fields (`icon`
, `title`, ...) are actually a `TagRendering`
- A `TagRendering` is an object describing a relationship between what should be shown on screen and the OSM-tagging. It
works in two ways: if the correct tag is known, the appropriate text will be shown. If the tag is missing (and a
question is defined), the question will be shown.
Every field is documented in the source code itself - you can find them here:
@ -82,50 +107,65 @@ Every field is documented in the source code itself - you can find them here:
### MetaTags
There are few tags available that are calculated for convenience - e.g. the country an object is located at. [An overview of all these metatags is available here](Docs/CalculatedTags.md)
There are few tags available that are calculated for convenience - e.g. the country an object is located
at. [An overview of all these metatags is available here](Docs/CalculatedTags.md)
Some hints
------------
### Everything is HTML
All the texts are actually *HTML*-snippets, so you can use `<b>` to add bold, or `<img src=...>` to add images to mappings or tagrenderings.
All the texts are actually *HTML*-snippets, so you can use `<b>` to add bold, or `<img src=...>` to add images to
mappings or tagrenderings.
Some remarks:
- links are disabled when answering a question (e.g. a link in a mapping) as it should trigger the answer - not trigger to open the link.
- If you include images, e.g. to clarify a type, make sure these are _icons_ or _diagrams_ - not actual pictures! If users see a picture, they think it is a picture of _that actual object_, not a type to clarify the type. An icon is however perceived as something more abstract.
- links are disabled when answering a question (e.g. a link in a mapping) as it should trigger the answer - not trigger
to open the link.
- If you include images, e.g. to clarify a type, make sure these are _icons_ or _diagrams_ - not actual pictures! If
users see a picture, they think it is a picture of _that actual object_, not a type to clarify the type. An icon is
however perceived as something more abstract.
Some pitfalls
---------------
### Not publishing
Not publishing because 'it is not good enough'. _Share your theme, even if it is still not great, let the community help it improve_
Not publishing because 'it is not good enough'. _Share your theme, even if it is still not great, let the community help
it improve_
### Thinking in terms of a question
Making a tagrendering as if it were a question only. If you have a question such as: _Does this bench have a backrest?_, it is very tempting to have as options _yes_ for `backrest=yes` and _no_ for `backrest=no`. However, when this data is known, it will simply show a lone _yes_ or _no_ which is very unclear.
Making a tagrendering as if it were a question only. If you have a question such as: _Does this bench have a backrest?_,
it is very tempting to have as options _yes_ for `backrest=yes` and _no_ for `backrest=no`. However, when this data is
known, it will simply show a lone _yes_ or _no_ which is very unclear.
The correct way to handle this is to use _This bench does have a backrest_ and _This bench does not have a backrest_ as answers.
The correct way to handle this is to use _This bench does have a backrest_ and _This bench does not have a backrest_ as
answers.
One has to think first in terms of _what is shown to the user if it is known_, only then in terms of _what is the question I want to ask_
One has to think first in terms of _what is shown to the user if it is known_, only then in terms of _what is the
question I want to ask_
### Forgetting the casual/noob mapper
MapComplete is in the first place a tool to help *non-technical* people visualize their interest and contribute to it. In order to maximize contribution:
MapComplete is in the first place a tool to help *non-technical* people visualize their interest and contribute to it.
In order to maximize contribution:
1. Use simple language. Avoid difficult words and explain jargon
2. Put the simple questions first and the difficult ones on the back. The contributor can then stop at a difficult point and go to the next POI
2. Put the simple questions first and the difficult ones on the back. The contributor can then stop at a difficult point
and go to the next POI
3. Use symbols and images, also in the mappings on questions
4. Make sure the icons (on the map and in the questions) are big enough, clear enough and contrast enough with the background map
4. Make sure the icons (on the map and in the questions) are big enough, clear enough and contrast enough with the
background map
### Using layers to distinguish on attributes
One layer should portray one kind of physical object, e.g. "benches" or "restaurants". It should contain all of them, disregarding other properties.
One layer should portray one kind of physical object, e.g. "benches" or "restaurants". It should contain all of them,
disregarding other properties.
One should not make one layer for benches with a backrest and one layer for benches without. This is confusing for users and poses problems: what if the backrest status is unknown? What if it is some weird value?
Also, it isn't possible to 'move' an attribute to another layer.
One should not make one layer for benches with a backrest and one layer for benches without. This is confusing for users
and poses problems: what if the backrest status is unknown? What if it is some weird value? Also, it isn't possible to '
move' an attribute to another layer.
Instead, make one layer for one kind of object and change the icon based on attributes.
@ -133,12 +173,19 @@ Instead, make one layer for one kind of object and change the icon based on attr
Using layers as filters - this doesn't work!
_All_ data is downloaded in one go and cached locally first. The layer selection (bottom left of the live app) then selects _anything_ that matches the criteria. This match is then passed of to the rendering layer, which selects the layer independently. This means that a feature can show up, even if it's layer is unselected!
_All_ data is downloaded in one go and cached locally first. The layer selection (bottom left of the live app) then
selects _anything_ that matches the criteria. This match is then passed of to the rendering layer, which selects the
layer independently. This means that a feature can show up, even if it's layer is unselected!
For example, in the [cyclofix-theme](https://mapcomplete.osm.org/cyclofix), there is the layer with _bike-wash_ for do it yourself bikecleaning - points marked with `service:bicycle:cleaning`. However, a bicycle repair shop can offer this service too!
For example, in the [cyclofix-theme](https://mapcomplete.osm.org/cyclofix), there is the layer with _bike-wash_ for do
it yourself bikecleaning - points marked with `service:bicycle:cleaning`. However, a bicycle repair shop can offer this
service too!
If all the layers are deselected except the bike wash layer, a shop having this tag will still match and will still show up as shop.
If all the layers are deselected except the bike wash layer, a shop having this tag will still match and will still show
up as shop.
### Not reading the .JSON-specs
There are a few advanced features to do fancy stuff available, which are documented only in the spec above - for example, reusing background images and substituting the colours or HTML-rendering. If you need advanced stuff, read it through!
There are a few advanced features to do fancy stuff available, which are documented only in the spec above - for
example, reusing background images and substituting the colours or HTML-rendering. If you need advanced stuff, read it
through!

View file

@ -4,15 +4,18 @@
## StreetComplete
StreetComplete might look pretty similar to MapComplete at first glance - especially as it was a huge inspiration. However, there are a few huge differences between the two, especially in vision.
StreetComplete might look pretty similar to MapComplete at first glance - especially as it was a huge inspiration.
However, there are a few huge differences between the two, especially in vision.
### Vision
The core philosophy of StreetComplete is **OpenStreetMap is cool! Help to improve it by answering these questions**
The core philosophy of MapComplete is **Here is a map of topic XYZ - enjoy it and update it if there is still some info missing**
The core philosophy of MapComplete is **Here is a map of topic XYZ - enjoy it and update it if there is still some info
missing**
This means that StreetComplete is mainly aimed towards people who are already OpenStreetMap-enthusiasts, whereas MapComplete is aimed to an audience interested in a certain topic.
Of course, the next step is to attempt to inform that audience why having an open map is so cool and that they can contribute as well.
This means that StreetComplete is mainly aimed towards people who are already OpenStreetMap-enthusiasts, whereas
MapComplete is aimed to an audience interested in a certain topic. Of course, the next step is to attempt to inform that
audience why having an open map is so cool and that they can contribute as well.
### Use cases
@ -29,7 +32,9 @@ MapComplete is made to
StreetComplete is an android app, so can only be used on Android Phones.
MapComplete is a web-app, and thus works on all devices. It can be installed as PWA to give an 'app-like'-experience, but can just as well be embedded in other websites. On the other hand PWA are a bit of a second class citizen compared to native apps.
MapComplete is a web-app, and thus works on all devices. It can be installed as PWA to give an 'app-like'-experience,
but can just as well be embedded in other websites. On the other hand PWA are a bit of a second class citizen compared
to native apps.
### Feature comparison
@ -37,22 +42,26 @@ MapComplete is also an OpenStreetMap-viewer, while StreetComplete hides known va
MapComplete will not work offline.
In MapComplete it is easier to add more experimental, extremely detailed and more personal styles, as each topic is separated with its own part.
In MapComplete it is easier to add more experimental, extremely detailed and more personal styles, as each topic is
separated with its own part.
MapComplete is a bit more complex to use. One needs to go hunting for a specific map style rather than getting bunch of quests by default. And is likely to ask far more detailed question (email address and phone number of bicycle shop etc).
After all if it would duplicate StreetComplete it would be a bit pointless and it is pretty hard to compete with SC by being easier to use and more newbie friendly, while there is space for "more complicated/detailed/involved editor working like SC".
MapComplete is a bit more complex to use. One needs to go hunting for a specific map style rather than getting bunch of
quests by default. And is likely to ask far more detailed question (email address and phone number of bicycle shop etc).
After all if it would duplicate StreetComplete it would be a bit pointless and it is pretty hard to compete with SC by
being easier to use and more newbie friendly, while there is space for "more complicated/detailed/involved editor
working like SC".
Also, MapComplete has no requirement to make question easy to answer, making both possible to ask more questions than StreetComplete but making it more complicated to use.
Also, MapComplete has no requirement to make question easy to answer, making both possible to ask more questions than
StreetComplete but making it more complicated to use.
No support for splitting ways in MapComplete (as of now - hopefully it'll get added one day).
MapComplete allows the addition of new points, whereas StreetComplete does not.
## MapContrib
MapContrib is another very similar editor which served as inspiration. MapContrib offers - just like MapComplete - an extensible, thematic map view. However, I never understood the MapContrib user interface.
MapContrib is another very similar editor which served as inspiration. MapContrib offers - just like MapComplete - an
extensible, thematic map view. However, I never understood the MapContrib user interface.
MapContrib also allows to add new points and to edit tags - but it is very cumbersome.

View file

@ -2,18 +2,19 @@
In this document, you'll find a short overview of which (paid) projects have been completed with MapComplete
## Buurtnatuur
Commisioned by Groen (the Belgian Green Party): "a project to crowdsource data about parks, nature reserve and forests"
## Cyclofix
Cycle-related Points of interest (pumps, shops, drinking water, ...). Commissioned by "Brussels Mobility", executed during OSOC
Cycle-related Points of interest (pumps, shops, drinking water, ...). Commissioned by "Brussels Mobility", executed
during OSOC
## Speelplekken in de Antwerpse Zuidrand
Playgrounds, play forests and village green in the southern part of the Province of Antwerp; commisioned by Province of Antwerp
Playgrounds, play forests and village green in the southern part of the Province of Antwerp; commisioned by Province of
Antwerp
## Natuurpunt Map (planned)

View file

@ -1,7 +1,7 @@
# Available types for text fields
The listed types here trigger a special input element. Use them in `tagrendering.freeform.type` of your tagrendering to activate them
The listed types here trigger a special input element. Use them in `tagrendering.freeform.type` of your tagrendering to
activate them
## string
@ -21,7 +21,8 @@ A geographical direction, in degrees. 0° is north, 90° is east, ... Will retur
## length
A geographical length in meters (rounded at two points). Will give an extra minimap with a measurement tool. Arguments: [ zoomlevel, preferredBackgroundMapType (comma separated) ], e.g. `["21", "map,photo"]
A geographical length in meters (rounded at two points). Will give an extra minimap with a measurement tool.
Arguments: [ zoomlevel, preferredBackgroundMapType (comma separated) ], e.g. `["21", "map,photo"]
## wikidata

View file

@ -1,7 +1,10 @@
### Special tag renderings
In a tagrendering, some special values are substituted by an advanced UI-element. This allows advanced features and visualizations to be reused by custom themes or even to query third-party API's. General usage is `{func_name()}`, `{func_name(arg, someotherarg)}` or `{func_name(args):cssStyle}`. Note that you _do not_fcs need to use quotes around your arguments, the comma is enough to separate them. This also implies you cannot use a comma in your args
In a tagrendering, some special values are substituted by an advanced UI-element. This allows advanced features and
visualizations to be reused by custom themes or even to query third-party API's. General usage is `{func_name()}`
, `{func_name(arg, someotherarg)}` or `{func_name(args):cssStyle}`. Note that you _do not_fcs need to use quotes around
your arguments, the comma is enough to separate them. This also implies you cannot use a comma in your args
### all_tags
Prints all key-value pairs of the object - used for debugging
@ -9,13 +12,14 @@
name | default | description
------ | --------- | -------------
#### Example usage
{all_tags()}
### image_carousel
Creates an image carousel for the given sources. An attempt will be made to guess what source is used. Supported: Wikidata identifiers, Wikipedia pages, Wikimedia categories, IMGUR (with attribution, direct links)
Creates an image carousel for the given sources. An attempt will be made to guess what source is used. Supported:
Wikidata identifiers, Wikipedia pages, Wikimedia categories, IMGUR (with attribution, direct links)
name | default | description
------ | --------- | -------------
@ -25,6 +29,7 @@ smart search | true | Also include images given via 'Wikidata', 'wikimedia_commo
#### Example usage
{image_carousel(image,true)}
### image_upload
Creates a button where a user can upload an image to IMGUR
@ -36,6 +41,7 @@ image-key | image | Image tag to add the URL to (or image-tag:0, image-tag:1 whe
#### Example usage
{image_upload(image)}
### minimap
A small map showing the selected feature. Note that no styling is applied, wrap this in a div
@ -47,10 +53,13 @@ idKey | id | (Matches all resting arguments) This argument should be the key of
#### Example usage
`{minimap()}`, `{minimap(17, id, _list_of_embedded_feature_ids_calculated_by_calculated_tag):height:10rem; border: 2px solid black}`
`{minimap()}`
, `{minimap(17, id, _list_of_embedded_feature_ids_calculated_by_calculated_tag):height:10rem; border: 2px solid black}`
### reviews
Adds an overview of the mangrove-reviews of this object. Mangrove.Reviews needs - in order to identify the reviewed object - a coordinate and a name. By default, the name of the object is given, but this can be overwritten
Adds an overview of the mangrove-reviews of this object. Mangrove.Reviews needs - in order to identify the reviewed
object - a coordinate and a name. By default, the name of the object is given, but this can be overwritten
name | default | description
------ | --------- | -------------
@ -59,10 +68,13 @@ fallback | undefined | The identifier to use, if <i>tags[subjectKey]</i> as spec
#### Example usage
<b>{reviews()}<b> for a vanilla review, <b>{reviews(name, play_forest)}</b> to review a play forest. If a name is known, the name will be used as identifier, otherwise 'play_forest' is used
<b>{reviews()}<b> for a vanilla review, <b>{reviews(name, play_forest)}</b> to review a play forest. If a name is known,
the name will be used as identifier, otherwise 'play_forest' is used
### opening_hours_table
Creates an opening-hours table. Usage: {opening_hours_table(opening_hours)} to create a table of the tag 'opening_hours'.
Creates an opening-hours table. Usage: {opening_hours_table(opening_hours)} to create a table of the tag '
opening_hours'.
name | default | description
------ | --------- | -------------
@ -71,9 +83,13 @@ key | opening_hours | The tagkey from which the table is constructed.
#### Example usage
{opening_hours_table(opening_hours)}
### live
Downloads a JSON from the given URL, e.g. '{live(example.org/data.json, shorthand:x.y.z, other:a.b.c, shorthand)}' will download the given file, will create an object {shorthand: json[x][y][z], other: json[a][b][c] out of it and will return 'other' or 'json[a][b][c]. This is made to use in combination with tags, e.g. {live({url}, {url:format}, needed_value)}
Downloads a JSON from the given URL, e.g. '{live(example.org/data.json, shorthand:x.y.z, other:a.b.c, shorthand)}' will
download the given file, will create an object {shorthand: json[x][y][z], other: json[a][b][c] out of it and will
return 'other' or 'json[a][b][c]. This is made to use in combination with tags, e.g. {live({url}, {url:format},
needed_value)}
name | default | description
------ | --------- | -------------
@ -83,7 +99,9 @@ path | undefined | The path (or shorthand) that should be returned
#### Example usage
{live({url},{url:format},hour)} {live(https://data.mobility.brussels/bike/api/counts/?request=live&featureID=CB2105,hour:data.hour_cnt;day:data.day_cnt;year:data.year_cnt,hour)}
{live({url},{url:format},hour)}
{live(https://data.mobility.brussels/bike/api/counts/?request=live&featureID=CB2105,hour:data.hour_cnt;day:data.day_cnt;year:data.year_cnt,hour)}
### histogram
Create a histogram for a list of given values, read from the properties.
@ -98,6 +116,7 @@ colors* | undefined | (Matches all resting arguments - optional) Matches a regex
#### Example usage
`{histogram('some_key')}` with properties being `{some_key: ['a','b','a','c']} to create a histogram
### share_link
Creates a link that (attempts to) open the native 'share'-screen
@ -109,6 +128,7 @@ url | undefined | The url to share (default: current URL)
#### Example usage
{share_link()} to share the current page, {share_link(<some_url>)} to share the given url
### canonical
Converts a short, canonical value into the long, translated text

View file

@ -1,7 +1,8 @@
Statistics
==========
There are some fancy statistics available about MapComplete use. The most important once are listed below, some more graphs (and the scripts to generate them) are [in the tools directory](Tools/)
There are some fancy statistics available about MapComplete use. The most important once are listed below, some more
graphs (and the scripts to generate them) are [in the tools directory](Tools/)
All Time usage
--------------
@ -9,7 +10,8 @@ All Time usage
![](Tools/CumulativeContributors.png)
![](Tools/Cumulative%20changesets%20per%20contributor.png)
Note: in 2020, MapComplete would still make one changeset per answered question. This heavily skews the below graphs towards `buurtnatuur` and `cyclofìx`, two heavily used themes at the beginning.
Note: in 2020, MapComplete would still make one changeset per answered question. This heavily skews the below graphs
towards `buurtnatuur` and `cyclofìx`, two heavily used themes at the beginning.
![](Tools/Cumulative%20changesets%20per%20theme.png)
![](Tools/Theme%20distribution.png)

View file

@ -1,48 +1,59 @@
Tags format
=============
When creating the `json` file describing your layer or theme, you'll have to add a few tags to describe what you want. This document gives an overview of what every expression means and how it behaves in edge cases.
When creating the `json` file describing your layer or theme, you'll have to add a few tags to describe what you want.
This document gives an overview of what every expression means and how it behaves in edge cases.
Strict equality
---------------
Strict equality is denoted by `key=value`. This key matches __only if__ the keypair is present exactly as stated.
**Only normal tags (eventually in an `and`) can be used in places where they are uploaded**. Normal tags are used in the `mappings` of a [TagRendering] (unless `hideInAnswer` is specified), they are used in `addExtraTags` of [Freeform] and are used in the `tags`-list of a preset.
**Only normal tags (eventually in an `and`) can be used in places where they are uploaded**. Normal tags are used in
the `mappings` of a [TagRendering] (unless `hideInAnswer` is specified), they are used in `addExtraTags` of [Freeform]
and are used in the `tags`-list of a preset.
If a different kind of tag specification is given, your theme will fail to parse.
### If key is not present
If you want to check if a key is not present, use `key=` (pronounce as *key is empty*). A tag collection will match this if `key` is missing or if `key` is a literal empty value.
If you want to check if a key is not present, use `key=` (pronounce as *key is empty*). A tag collection will match this
if `key` is missing or if `key` is a literal empty value.
### Removing a key
If a key should be deleted in the OpenStreetMap-database, specify `key=` as well. This can be used e.g. to remove a fixme or value from another mapping if another field is filled out.
If a key should be deleted in the OpenStreetMap-database, specify `key=` as well. This can be used e.g. to remove a
fixme or value from another mapping if another field is filled out.
Strict not equals
-----------------
To check if a key does _not_ equal a certain value, use `key!=value`. This is converted behind the scenes to `key!~^value$`
To check if a key does _not_ equal a certain value, use `key!=value`. This is converted behind the scenes
to `key!~^value$`
### If key is present
This implies that, to check if a key is present, `key!=` can be used. This will only match if the key is present and not empty.
This implies that, to check if a key is present, `key!=` can be used. This will only match if the key is present and not
empty.
Number comparison
-----------------
If the value of a tag is a number (e.g. `key=42`), one can use a filter `key<=42`, `key>=35`, `key>40` or `key<50` to match this, e.g. in conditions for renderings.
These tags cannot be used to generate an answer nor can they be used to request data upstream from overpass.
If the value of a tag is a number (e.g. `key=42`), one can use a filter `key<=42`, `key>=35`, `key>40` or `key<50` to
match this, e.g. in conditions for renderings. These tags cannot be used to generate an answer nor can they be used to
request data upstream from overpass.
Note that the value coming from OSM will first be stripped by removing all non-numeric characters. For example, `length=42 meter` will be interpreted as `length=42` and will thus match `length<=42` and `length>=42`.
In special circumstances (e.g. `surface_area=42 m2` or `length=100 feet`), this will result in erronous values (`surface=422` or if a length in meters is compared to).
However, this can be partially alleviated by using 'Units' to rewrite to a default format.
Note that the value coming from OSM will first be stripped by removing all non-numeric characters. For
example, `length=42 meter` will be interpreted as `length=42` and will thus match `length<=42` and `length>=42`. In
special circumstances (e.g. `surface_area=42 m2` or `length=100 feet`), this will result in erronous
values (`surface=422` or if a length in meters is compared to). However, this can be partially alleviated by using '
Units' to rewrite to a default format.
Regex equals
------------
A tag can also be tested against a regex with `key~regex`. Note that this regex __must match__ the entire value. If the value is allowed to appear anywhere as substring, use `key~.*regex.*`
A tag can also be tested against a regex with `key~regex`. Note that this regex __must match__ the entire value. If the
value is allowed to appear anywhere as substring, use `key~.*regex.*`
Equivalently, `key!~regex` can be used if you _don't_ want to match the regex in order to appear.
@ -52,16 +63,18 @@ Using other tags as variables
**This is an advanced feature - use with caution**
Some tags are automatically set or calculated - see [CalculatedTags](CalculatedTags.md) for an entire overview.
If one wants to apply such a value as tag, use a substituting-tag such, for example`survey:date:={_date:now}`. Note that the separator between key and value here is `:=`.
The text between `{` and `}` is interpreted as a key, and the respective value is substituted into the string.
Some tags are automatically set or calculated - see [CalculatedTags](CalculatedTags.md) for an entire overview. If one
wants to apply such a value as tag, use a substituting-tag such, for example`survey:date:={_date:now}`. Note that the
separator between key and value here is `:=`. The text between `{` and `}` is interpreted as a key, and the respective
value is substituted into the string.
One can also append, e.g. `key:={some_key} fixed text {some_other_key}`.
An assigning tag _cannot_ be used to query OpenStreetMap/Overpass.
If using a key or variable which might not be defined, add a condition in the mapping to hide the option.
This is because, if `some_other_key` is not defined, one might actually upload the literal text `key={some_other_key}` to OSM - which we do not want.
If using a key or variable which might not be defined, add a condition in the mapping to hide the option. This is
because, if `some_other_key` is not defined, one might actually upload the literal text `key={some_other_key}` to OSM -
which we do not want.
To mitigate this, use:

View file

@ -1,8 +1,8 @@
Talk at State of the Map
========================
I'm planning to do a talk/video on MapComplete on _State of the Map 2021_. This document outlines the structure of the talk and serves as my speaker notes.
I'm planning to do a talk/video on MapComplete on _State of the Map 2021_. This document outlines the structure of the
talk and serves as my speaker notes.
Overview
--------
@ -12,15 +12,12 @@ I'm planning to do a talk/video on MapComplete on _State of the Map 2021_. This
a. Where and how did it start? "This project isn't going anywhere"
(buurtnatuur, cyclofix, Antwerpen, Natuurpunt, Oost-Vlaanderen?, Toerisme Vlaanderen?)
b. Where are we now? Some cool statistics
3. The vision
a. Your granny can use it
a. pragmatism - somewhat working today is better then something perfect tomorrow
a. It's a trap! Cool thematic map (as iframe on website) -> the OSM rabbit hole -> easy start -> more features when mapping more -> oh, I can make a theme too!
b. The pareto frontier of 'easy to use' vs 'number of features'
c. The thematic approach (+ disabling/enabling features per theme/view)
3. The vision a. Your granny can use it a. pragmatism - somewhat working today is better then something perfect tomorrow
a. It's a trap! Cool thematic map (as iframe on website) -> the OSM rabbit hole -> easy start -> more features when
mapping more -> oh, I can make a theme too!
b. The pareto frontier of 'easy to use' vs 'number of features' c. The thematic approach (+ disabling/enabling
features per theme/view)
4. The future
a. paid projects? Microgrant for a better theme creator?
b. user contributed themes (see you next talk!)
4. The future a. paid projects? Microgrant for a better theme creator? b. user contributed themes (see you next talk!)
5. OpenStreetMap is Cool!

View file

@ -216,12 +216,6 @@ function createGraph(
}
class Histogram<K> {
total(): number {
let total = 0
Array.from(this.counts.values()).forEach(i => total = total + i)
return total
}
public counts: Map<K, number> = new Map<K, number>()
private sortAtEnd: K[] = []
@ -230,6 +224,11 @@ class Histogram<K> {
keys?.forEach(key => self.bump(key))
}
total(): number {
let total = 0
Array.from(this.counts.values()).forEach(i => total = total + i)
return total
}
public bump(key: K, increase = 1) {
if (this.counts.has(key)) {

View file

@ -1,4 +1,3 @@
URL-parameters and URL-hash
============================
@ -9,8 +8,8 @@ What is a URL parameter?
URL-parameters are extra parts of the URL used to set the state.
For example, if the url is `https://mapcomplete.osm.be/cyclofix?lat=51.0&lon=4.3&z=5&test=true#node/1234`,
the URL-parameters are stated in the part between the `?` and the `#`. There are multiple, all separated by `&`, namely:
For example, if the url is `https://mapcomplete.osm.be/cyclofix?lat=51.0&lon=4.3&z=5&test=true#node/1234`, the
URL-parameters are stated in the part between the `?` and the `#`. There are multiple, all separated by `&`, namely:
- The url-parameter `lat` is `51.0` in this instance
- The url-parameter `lon` is `4.3` in this instance
@ -22,7 +21,8 @@ Finally, the URL-hash is the part after the `#`. It is `node/1234` in this case.
language
----------
The language to display mapcomplete in. Will be ignored in case a logged-in-user did set their language before. If the specified language does not exist, it will default to the first language in the theme.
The language to display mapcomplete in. Will be ignored in case a logged-in-user did set their language before. If the
specified language does not exist, it will default to the first language in the theme.
download-control-toggle
-------------------------
@ -39,7 +39,8 @@ The language to display mapcomplete in. Will be ignored in case a logged-in-user
tab
-----
The tab that is shown in the welcome-message. 0 = the explanation of the theme,1 = OSM-credits, 2 = sharescreen, 3 = more themes, 4 = about mapcomplete (user must be logged in and have >50 changesets) The default value is _0_
The tab that is shown in the welcome-message. 0 = the explanation of the theme,1 = OSM-credits, 2 = sharescreen, 3 =
more themes, 4 = about mapcomplete (user must be logged in and have >50 changesets) The default value is _0_
z
@ -63,7 +64,8 @@ The language to display mapcomplete in. Will be ignored in case a logged-in-user
fs-userbadge
--------------
Disables/Enables the user information pill (userbadge) at the top left. Disabling this disables logging in and thus disables editing all together, effectively putting MapComplete into read-only mode. The default value is _true_
Disables/Enables the user information pill (userbadge) at the top left. Disabling this disables logging in and thus
disables editing all together, effectively putting MapComplete into read-only mode. The default value is _true_
fs-search
@ -87,7 +89,8 @@ The language to display mapcomplete in. Will be ignored in case a logged-in-user
fs-add-new
------------
Disables/Enables the 'add new feature'-popup. (A theme without presets might not have it in the first place) The default value is _true_
Disables/Enables the 'add new feature'-popup. (A theme without presets might not have it in the first place) The default
value is _true_
fs-welcome-message
@ -141,7 +144,8 @@ The language to display mapcomplete in. Will be ignored in case a logged-in-user
test
------
If true, 'dryrun' mode is activated. The app will behave as normal, except that changes to OSM will be printed onto the console instead of actually uploaded to osm.org The default value is _false_
If true, 'dryrun' mode is activated. The app will behave as normal, except that changes to OSM will be printed onto the
console instead of actually uploaded to osm.org The default value is _false_
debug
@ -153,7 +157,8 @@ The language to display mapcomplete in. Will be ignored in case a logged-in-user
overpassUrl
-------------
Point mapcomplete to a different overpass-instance. Example: https://overpass-api.de/api/interpreter The default value is _https://overpass.kumi.de/api/interpreter_
Point mapcomplete to a different overpass-instance. Example: https://overpass-api.de/api/interpreter The default value
is _https://overpass.kumi.de/api/interpreter_
overpassTimeout
@ -170,7 +175,8 @@ Set a different timeout (in seconds) for queries in overpass The default value i
backend
---------
The OSM backend to use - can be used to redirect mapcomplete to the testing backend when using 'osm-test' The default value is _osm_
The OSM backend to use - can be used to redirect mapcomplete to the testing backend when using 'osm-test' The default
value is _osm_
custom-css

View file

@ -3,6 +3,8 @@ What is MapComplete?
MapComplete is a website where people can see a map of Points of Interest (POI) on a specific subject or theme.
If the visitor is logged in with their OpenStreetMap account, information about a selected POI can be enriched by answering questions in the respective popups; this data is sent back directly to OpenStreetMap.
If the visitor is logged in with their OpenStreetMap account, information about a selected POI can be enriched by
answering questions in the respective popups; this data is sent back directly to OpenStreetMap.
While there are some predefined themes available, it is also possible to create your own theme. Have a look on [the OpenStreetMap-wiki](https://wiki.openstreetmap.org/wiki/MapComplete) for a list of (un)official themes.
While there are some predefined themes available, it is also possible to create your own theme. Have a look
on [the OpenStreetMap-wiki](https://wiki.openstreetmap.org/wiki/MapComplete) for a list of (un)official themes.

View file

@ -4,7 +4,6 @@ import Svg from "../../Svg";
import Img from "../../UI/Base/Img";
import {LocalStorageSource} from "../Web/LocalStorageSource";
import {VariableUiElement} from "../../UI/Base/VariableUIElement";
import BaseUIElement from "../../UI/BaseUIElement";
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig";
import {QueryParameters} from "../Web/QueryParameters";

View file

@ -3,6 +3,7 @@ Actors
An **actor** is a module which converts one UIEventSource into another while performing logic.
Typically, it will only expose the constructor taking some UIEventSources (and configuration) and a few fields which are UIEVentSources.
Typically, it will only expose the constructor taking some UIEventSources (and configuration) and a few fields which are
UIEVentSources.
An actor should _never_ have a dependency on 'State' and should _never_ import it

View file

@ -9,11 +9,10 @@ import OsmApiFeatureSource from "../FeatureSource/OsmApiFeatureSource";
* Makes sure the hash shows the selected element and vice-versa.
*/
export default class SelectedFeatureHandler {
private static readonly _no_trigger_on = ["welcome", "copyright", "layers", "new"]
private readonly _featureSource: FeatureSource;
private readonly _hash: UIEventSource<string>;
private readonly _selectedFeature: UIEventSource<any>;
private static readonly _no_trigger_on = ["welcome", "copyright", "layers", "new"]
private readonly _osmApiSource: OsmApiFeatureSource;
constructor(hash: UIEventSource<string>,

View file

@ -1,7 +1,5 @@
import * as L from "leaflet";
import Svg from "../../Svg";
import {UIEventSource} from "../UIEventSource";
import Img from "../../UI/Base/Img";
import ScrollableFullScreen from "../../UI/Base/ScrollableFullScreen";
import AddNewMarker from "../../UI/BigComponents/AddNewMarker";
import FilteredLayer from "../../Models/FilteredLayer";

View file

@ -49,7 +49,6 @@ class TitleElement extends UIEventSource<string> {
}
, [Locale.language, layoutToUse]
)
)

View file

@ -5,8 +5,8 @@ import {UIEventSource} from "./UIEventSource";
export class ElementStorage {
private _elements = new Map<string, UIEventSource<any>>();
public ContainingFeatures = new Map<string, any>();
private _elements = new Map<string, UIEventSource<any>>();
constructor() {

View file

@ -13,10 +13,10 @@ export default class GeoJsonSource implements FeatureSource {
public readonly features: UIEventSource<{ feature: any; freshness: Date }[]>;
public readonly name;
public readonly isOsmCache: boolean
private onFail: ((errorMsg: any, url: string) => void) = undefined;
private readonly layerId: string;
private readonly seenids: Set<string> = new Set<string>()
public readonly isOsmCache: boolean
private constructor(locationControl: UIEventSource<Loc>,
flayer: { isDisplayed: UIEventSource<boolean>, layerDef: LayerConfig },

View file

@ -185,6 +185,60 @@ export class GeoOperations {
return turf.length(feature) * 1000
}
/**
* Generates the closest point on a way from a given point
* @param way The road on which you want to find a point
* @param point Point defined as [lon, lat]
*/
public static nearestPoint(way, point: [number, number]) {
return turf.nearestPointOnLine(way, point, {units: "kilometers"});
}
public static toCSV(features: any[]): string {
const headerValuesSeen = new Set<string>();
const headerValuesOrdered: string[] = []
function addH(key) {
if (!headerValuesSeen.has(key)) {
headerValuesSeen.add(key)
headerValuesOrdered.push(key)
}
}
addH("_lat")
addH("_lon")
const lines: string[] = []
for (const feature of features) {
const properties = feature.properties;
for (const key in properties) {
if (!properties.hasOwnProperty(key)) {
continue;
}
addH(key)
}
}
headerValuesOrdered.sort()
for (const feature of features) {
const properties = feature.properties;
let line = ""
for (const key of headerValuesOrdered) {
const value = properties[key]
if (value === undefined) {
line += ","
} else {
line += JSON.stringify(value) + ","
}
}
lines.push(line)
}
return headerValuesOrdered.map(v => JSON.stringify(v)).join(",") + "\n" + lines.join("\n")
}
/**
* Calculates the intersection between two features.
* Returns the length if intersecting a linestring and a (multi)polygon (in meters), returns a surface area (in m²) if intersecting two (multi)polygons
@ -277,60 +331,6 @@ export class GeoOperations {
return undefined;
}
/**
* Generates the closest point on a way from a given point
* @param way The road on which you want to find a point
* @param point Point defined as [lon, lat]
*/
public static nearestPoint(way, point: [number, number]) {
return turf.nearestPointOnLine(way, point, {units: "kilometers"});
}
public static toCSV(features: any[]): string {
const headerValuesSeen = new Set<string>();
const headerValuesOrdered: string[] = []
function addH(key) {
if (!headerValuesSeen.has(key)) {
headerValuesSeen.add(key)
headerValuesOrdered.push(key)
}
}
addH("_lat")
addH("_lon")
const lines: string[] = []
for (const feature of features) {
const properties = feature.properties;
for (const key in properties) {
if (!properties.hasOwnProperty(key)) {
continue;
}
addH(key)
}
}
headerValuesOrdered.sort()
for (const feature of features) {
const properties = feature.properties;
let line = ""
for (const key of headerValuesOrdered) {
const value = properties[key]
if (value === undefined) {
line += ","
} else {
line += JSON.stringify(value) + ","
}
}
lines.push(line)
}
return headerValuesOrdered.map(v => JSON.stringify(v)).join(",") + "\n" + lines.join("\n")
}
}

View file

@ -18,12 +18,13 @@ export default abstract class ImageAttributionSource {
}
public abstract SourceIcon(backlinkSource?: string): BaseUIElement;
protected abstract DownloadAttribution(url: string): UIEventSource<LicenseInfo>;
/*Converts a value to a URL. Can return null if not applicable*/
public PrepareUrl(value: string): string {
return value;
}
protected abstract DownloadAttribution(url: string): UIEventSource<LicenseInfo>;
}

View file

@ -1,4 +1,3 @@
import $ from "jquery"
import {LicenseInfo} from "./Wikimedia";
import ImageAttributionSource from "./ImageAttributionSource";
import BaseUIElement from "../../UI/BaseUIElement";

View file

@ -18,6 +18,9 @@ interface Params {
export default class MetaTagging {
private static errorPrintCount = 0;
private static readonly stopErrorOutputAt = 10;
/**
* An actor which adds metatags on every feature in the given object
* The features are a list of geojson-features, with a "properties"-field and geometry
@ -86,9 +89,6 @@ export default class MetaTagging {
}
private static errorPrintCount = 0;
private static readonly stopErrorOutputAt = 10;
private static createRetaggingFunc(layer: LayerConfig):
((params: Params, feature: any) => void) {
const calculatedTags: [string, string][] = layer.calculatedTags;

View file

@ -8,11 +8,10 @@ import {GeoOperations} from "../../GeoOperations";
export default class CreateNewNodeAction extends OsmChangeAction {
public newElementId: string = undefined
private readonly _basicTags: Tag[];
private readonly _lat: number;
private readonly _lon: number;
public newElementId: string = undefined
private readonly _snapOnto: OsmWay;
private readonly _reusePointDistance: number;

View file

@ -55,8 +55,6 @@ export default class DeleteAction {
}
deletionStarted = true;
OsmObject.DownloadObject(self._id).addCallbackAndRun(obj => {
if (obj === undefined) {
@ -216,7 +214,6 @@ export default class DeleteAction {
}
}
)

View file

@ -4,7 +4,7 @@
import OsmChangeAction from "./OsmChangeAction";
import {Changes} from "../Changes";
import {ChangeDescription} from "./ChangeDescription";
import {OsmRelation, OsmWay} from "../OsmObject";
import {OsmRelation} from "../OsmObject";
export default class RelationSplitlHandler extends OsmChangeAction {

View file

@ -70,6 +70,88 @@ export class Changes {
.map(c => c.type + "/" + c.id))
}
/**
* Returns a new ID and updates the value for the next ID
*/
public getNewID() {
return Changes._nextId--;
}
/**
* Uploads all the pending changes in one go.
* Triggered by the 'PendingChangeUploader'-actor in Actors
*/
public flushChanges(flushreason: string = undefined) {
if (this.pendingChanges.data.length === 0) {
return;
}
if (this.isUploading.data) {
console.log("Is already uploading... Abort")
return;
}
this.isUploading.setData(true)
console.log("Beginning upload... " + flushreason ?? "");
// At last, we build the changeset and upload
const self = this;
const pending = self.pendingChanges.data;
const neededIds = Changes.GetNeededIds(pending)
console.log("Needed ids", neededIds)
OsmObject.DownloadAll(neededIds, true).addCallbackAndRunD(osmObjects => {
console.log("Got the fresh objects!", osmObjects, "pending: ", pending)
try {
const changes: {
newObjects: OsmObject[],
modifiedObjects: OsmObject[]
deletedObjects: OsmObject[]
} = self.CreateChangesetObjects(pending, osmObjects)
if (changes.newObjects.length + changes.deletedObjects.length + changes.modifiedObjects.length === 0) {
console.log("No changes to be made")
self.pendingChanges.setData([])
self.isUploading.setData(false)
return true; // Unregister the callback
}
State.state.osmConnection.UploadChangeset(
State.state.layoutToUse.data,
State.state.allElements,
(csId) => Changes.createChangesetFor(csId, changes),
() => {
console.log("Upload successfull!")
self.pendingChanges.setData([]);
self.isUploading.setData(false)
},
() => {
console.log("Upload failed - trying again later")
return self.isUploading.setData(false);
} // Failed - mark to try again
)
} catch (e) {
console.error("Could not handle changes - probably an old, pending changeset in localstorage with an invalid format; erasing those", e)
self.pendingChanges.setData([])
self.isUploading.setData(false)
}
return true;
});
}
public applyAction(action: OsmChangeAction) {
const changes = action.Perform(this)
console.log("Received changes:", changes)
this.pendingChanges.data.push(...changes);
this.pendingChanges.ping();
}
private CreateChangesetObjects(changes: ChangeDescription[], downloadedOsmObjects: OsmObject[]): {
newObjects: OsmObject[],
modifiedObjects: OsmObject[]
@ -221,86 +303,4 @@ export class Changes {
return result
}
/**
* Returns a new ID and updates the value for the next ID
*/
public getNewID() {
return Changes._nextId--;
}
/**
* Uploads all the pending changes in one go.
* Triggered by the 'PendingChangeUploader'-actor in Actors
*/
public flushChanges(flushreason: string = undefined) {
if (this.pendingChanges.data.length === 0) {
return;
}
if (this.isUploading.data) {
console.log("Is already uploading... Abort")
return;
}
this.isUploading.setData(true)
console.log("Beginning upload... "+flushreason ?? "");
// At last, we build the changeset and upload
const self = this;
const pending = self.pendingChanges.data;
const neededIds = Changes.GetNeededIds(pending)
console.log("Needed ids", neededIds)
OsmObject.DownloadAll(neededIds, true).addCallbackAndRunD(osmObjects => {
console.log("Got the fresh objects!", osmObjects, "pending: ", pending)
try{
const changes: {
newObjects: OsmObject[],
modifiedObjects: OsmObject[]
deletedObjects: OsmObject[]
} = self.CreateChangesetObjects(pending, osmObjects)
if (changes.newObjects.length + changes.deletedObjects.length + changes.modifiedObjects.length === 0) {
console.log("No changes to be made")
self.pendingChanges.setData([])
self.isUploading.setData(false)
return true; // Unregister the callback
}
State.state.osmConnection.UploadChangeset(
State.state.layoutToUse.data,
State.state.allElements,
(csId) => Changes.createChangesetFor(csId, changes),
() => {
console.log("Upload successfull!")
self.pendingChanges.setData([]);
self.isUploading.setData(false)
},
() => {
console.log("Upload failed - trying again later")
return self.isUploading.setData(false);
} // Failed - mark to try again
)
}catch(e){
console.error("Could not handle changes - probably an old, pending changeset in localstorage with an invalid format; erasing those", e)
self.pendingChanges.setData([])
self.isUploading.setData(false)
}
return true;
});
}
public applyAction(action: OsmChangeAction) {
const changes = action.Perform(this)
console.log("Received changes:", changes)
this.pendingChanges.data.push(...changes);
this.pendingChanges.ping();
}
}

View file

@ -6,8 +6,10 @@ export class Geocoding {
private static readonly host = "https://nominatim.openstreetmap.org/search?";
static Search(query: string,
handleResult: ((places: { display_name: string, lat: number, lon: number, boundingbox: number[],
osm_type: string, osm_id: string}[]) => void),
handleResult: ((places: {
display_name: string, lat: number, lon: number, boundingbox: number[],
osm_type: string, osm_id: string
}[]) => void),
onFail: (() => void)) {
const b = State.state.leafletMap.data.getBounds();
const url = Geocoding.host + "format=json&limit=1&viewbox=" +

View file

@ -47,10 +47,10 @@ export class OsmConnection {
public auth;
public userDetails: UIEventSource<UserDetails>;
public isLoggedIn: UIEventSource<boolean>
private fakeUser: boolean;
_dryRun: boolean;
public preferencesHandler: OsmPreferences;
public changesetHandler: ChangesetHandler;
private fakeUser: boolean;
private _onLoggedIn: ((userDetails: UserDetails) => void)[] = [];
private readonly _iframeMode: Boolean | boolean;
private readonly _singlePage: boolean;
@ -59,6 +59,7 @@ export class OsmConnection {
oauth_secret: string,
url: string
};
private isChecking = false;
constructor(dryRun: boolean,
fakeUser: boolean,
@ -249,7 +250,6 @@ export class OsmConnection {
});
}
private isChecking = false;
private CheckForMessagesContinuously() {
const self = this;
if (this.isChecking) {

View file

@ -15,9 +15,6 @@ export default class AspectedRouting {
delete this.program.unit
}
public evaluate(properties){
return AspectedRouting.interpret(this.program, properties)
}
/**
* Interprets the given Aspected-routing program for the given properties
*/
@ -191,4 +188,8 @@ export default class AspectedRouting {
return result;
}
public evaluate(properties) {
return AspectedRouting.interpret(this.program, properties)
}
}

View file

@ -8,6 +8,14 @@ export class And extends TagsFilter {
this.and = and
}
private static combine(filter: string, choices: string[]): string[] {
const values = [];
for (const or of choices) {
values.push(filter + or);
}
return values;
}
normalize() {
const ands = []
for (const c of this.and) {
@ -20,14 +28,6 @@ export class And extends TagsFilter {
return new And(ands)
}
private static combine(filter: string, choices: string[]): string[] {
const values = [];
for (const or of choices) {
values.push(filter + or);
}
return values;
}
matchesProperties(tags: any): boolean {
for (const tagsFilter of this.and) {
if (!tagsFilter.matchesProperties(tags)) {

View file

@ -52,6 +52,7 @@ export class Tag extends TagsFilter {
}
return [`["${this.key}"="${this.value}"]`];
}
asHumanString(linkToWiki?: boolean, shorten?: boolean) {
let v = this.value;
if (shorten) {

View file

@ -10,6 +10,15 @@ import {AndOrTagConfigJson} from "../../Models/ThemeConfig/Json/TagConfigJson";
import {isRegExp} from "util";
export class TagUtils {
private static comparators
: [string, (a: number, b: number) => boolean][]
= [
["<=", (a, b) => a <= b],
[">=", (a, b) => a >= b],
["<", (a, b) => a < b],
[">", (a, b) => a > b],
]
static ApplyTemplate(template: string, tags: any): string {
for (const k in tags) {
while (template.indexOf("{" + k + "}") >= 0) {
@ -170,15 +179,6 @@ export class TagUtils {
}
}
private static comparators
: [string, (a: number, b: number) => boolean][]
= [
["<=", (a, b) => a <= b],
[">=", (a, b) => a >= b],
["<", (a, b) => a < b],
[">", (a, b) => a > b],
]
private static TagUnsafe(json: AndOrTagConfigJson | string, context: string = ""): TagsFilter {
if (json === undefined) {

View file

@ -69,6 +69,10 @@ export class QueryParameters {
return docs.join("\n\n");
}
public static wasInitialized(key: string): boolean {
return QueryParameters._wasInitialized.has(key)
}
private static addOrder(key) {
if (this.order.indexOf(key) < 0) {
this.order.push(key)
@ -105,10 +109,6 @@ export class QueryParameters {
}
}
public static wasInitialized(key: string) : boolean{
return QueryParameters._wasInitialized.has(key)
}
private static Serialize() {
const parts = []
for (const key of QueryParameters.order) {

View file

@ -6,8 +6,8 @@ export class Denomination {
public readonly canonical: string;
readonly default: boolean;
readonly prefix: boolean;
private readonly _human: Translation;
public readonly alternativeDenominations: string [];
private readonly _human: Translation;
constructor(json: UnitConfigJson, context: string) {
context = `${context}.unit(${json.canonicalDenomination})`

View file

@ -1,5 +1,4 @@
import {UIEventSource} from "../Logic/UIEventSource";
import {TagsFilter} from "../Logic/Tags/TagsFilter";
import LayerConfig from "./ThemeConfig/LayerConfig";
import {And} from "../Logic/Tags/And";

View file

@ -53,10 +53,9 @@ export default class LayoutConfig {
*/
public readonly cacheTimeout?: number;
public readonly units: Unit[] = []
private readonly _official: boolean;
public readonly overpassUrl: string;
public readonly overpassTimeout: number;
private readonly _official: boolean;
constructor(json: LayoutConfigJson, official = true, context?: string) {
this._official = official;

View file

@ -6,7 +6,6 @@ import {TagUtils} from "../../Logic/Tags/TagUtils";
import {And} from "../../Logic/Tags/And";
import ValidatedTextField from "../../UI/Input/ValidatedTextField";
import {Utils} from "../../Utils";
import {SubstitutedTranslation} from "../../UI/SubstitutedTranslation";
/***
* The parsed version of TagRenderingConfigJSON

View file

@ -1,10 +1,12 @@
# MapComplete
> Let a thousand flowers bloom
MapComplete is an OpenStreetMap viewer and editor. It shows map features on a certain topic, and allows to see, edit and add new features to the map.
It can be seen as a webversion [crossover of StreetComplete and MapContrib](Docs/MapComplete_vs_other_editors.md). It tries to be just as easy to use as StreetComplete, but it allows to focus on one single theme per instance (e.g. nature, bicycle infrastructure, ...)
MapComplete is an OpenStreetMap viewer and editor. It shows map features on a certain topic, and allows to see, edit and
add new features to the map. It can be seen as a
webversion [crossover of StreetComplete and MapContrib](Docs/MapComplete_vs_other_editors.md). It tries to be just as
easy to use as StreetComplete, but it allows to focus on one single theme per instance (e.g. nature, bicycle
infrastructure, ...)
The design goals of MapComplete are to be:
@ -13,29 +15,39 @@ The design goals of MapComplete are to be:
- Easy to set up a custom theme
- Easy to fall down the rabbit hole of OSM
The basic functionality is to download some map features from Overpass and then ask certain questions. An answer is sent back to directly to OpenStreetMap.
The basic functionality is to download some map features from Overpass and then ask certain questions. An answer is sent
back to directly to OpenStreetMap.
Furthermore, it shows images present in the `image` tag or, if a `wikidata` or `wikimedia_commons`-tag is present, it follows those to get these images too.
An explicit non-goal of MapComplete is to modify geometries of ways. Although adding a point to a way or splitting a way in two parts might be added one day.
Furthermore, it shows images present in the `image` tag or, if a `wikidata` or `wikimedia_commons`-tag is present, it
follows those to get these images too.
An explicit non-goal of MapComplete is to modify geometries of ways. Although adding a point to a way or splitting a way
in two parts might be added one day.
# Creating your own theme
It is possible to quickly make and distribute your own theme - [please read the documentation on how to do this](Docs/Making_Your_Own_Theme.md).
It is possible to quickly make and distribute your own theme
- [please read the documentation on how to do this](Docs/Making_Your_Own_Theme.md).
## Examples
- [Buurtnatuur.be](http://buurtnatuur.be), developed for the Belgian [Green party](https://www.groen.be/). They also funded the initial development!
- [Cyclofix](https://pietervdvn.github.io/MapComplete/index.html?layout=cyclofix), further development on [Open Summer of Code](https://summerofcode.be/) funded by [Brussels Mobility](https://mobilite-mobiliteit.brussels/en). Landing page at https://cyclofix.osm.be/
- [Bookcases](https://pietervdvn.github.io/MapComplete/index.html?quests=bookcases#element) cause I like to collect them.
- [Map of Maps](https://pietervdvn.github.io/MapComplete/index.html?layout=maps&z=14&lat=50.650&lon=4.2668#element), after a tweet
- [Buurtnatuur.be](http://buurtnatuur.be), developed for the Belgian [Green party](https://www.groen.be/). They also
funded the initial development!
- [Cyclofix](https://pietervdvn.github.io/MapComplete/index.html?layout=cyclofix), further development
on [Open Summer of Code](https://summerofcode.be/) funded
by [Brussels Mobility](https://mobilite-mobiliteit.brussels/en). Landing page at https://cyclofix.osm.be/
- [Bookcases](https://pietervdvn.github.io/MapComplete/index.html?quests=bookcases#element) cause I like to collect
them.
- [Map of Maps](https://pietervdvn.github.io/MapComplete/index.html?layout=maps&z=14&lat=50.650&lon=4.2668#element),
after a tweet
There are plenty more. Discover them in the app.
### Statistics
To see statistics, consult [OsmCha](https://osmcha.org/?filters=%7B%22comment%22%3A%5B%7B%22label%22%3A%22%23mapcomplete%22%2C%22value%22%3A%22%23mapcomplete%22%7D%5D%2C%22date__gte%22%3A%5B%7B%22label%22%3A%222020-07-05%22%2C%22value%22%3A%222020-07-05%22%7D%5D%7D) or the [analytics page](https://pietervdvn.goatcounter.com/)
To see statistics,
consult [OsmCha](https://osmcha.org/?filters=%7B%22comment%22%3A%5B%7B%22label%22%3A%22%23mapcomplete%22%2C%22value%22%3A%22%23mapcomplete%22%7D%5D%2C%22date__gte%22%3A%5B%7B%22label%22%3A%222020-07-05%22%2C%22value%22%3A%222020-07-05%22%7D%5D%7D)
or the [analytics page](https://pietervdvn.goatcounter.com/)
## User journey
@ -49,7 +61,8 @@ A typical user journey would be:
* The user might share the map and/or embed it in the third tab
* The user might discover the other themes in the last tab
1. The user clicks that big tempting button 'login' in order to answer questions - there's enough of these login buttons... The user creates an account.
1. The user clicks that big tempting button 'login' in order to answer questions - there's enough of these login
buttons... The user creates an account.
2. The user answers a question! Hooray! The user transformed into a __contributor__ now.
@ -58,49 +71,57 @@ A typical user journey would be:
3. The user adds a new POI somewhere
* Note that _all messages_ must be read before being able to add a point.
* In other words, sending a message to a misbehaving MapComplete user acts as having a **zero-day-block**. This is added deliberately to make sure new users _have_ to read feedback from the community.
* In other words, sending a message to a misbehaving MapComplete user acts as having a **zero-day-block**. This is
added deliberately to make sure new users _have_ to read feedback from the community.
4. At 50 changesets, the [personal layout](https://pietervdvn.github.io/MapComplete/personal.html) is advertised. The personal theme is a theme where contributors can pick layers from all the official themes. Note that the personal theme is always available.
4. At 50 changesets, the [personal layout](https://pietervdvn.github.io/MapComplete/personal.html) is advertised. The
personal theme is a theme where contributors can pick layers from all the official themes. Note that the personal
theme is always available.
5. At 200 changesets, the tags become visible when answering questions and when adding a new point from a preset. This is to give more control to power users and to teach new users the tagging scheme
5. At 200 changesets, the tags become visible when answering questions and when adding a new point from a preset. This
is to give more control to power users and to teach new users the tagging scheme
6. At 250 changesets, the tags get linked to the wiki
7. At 500 changesets, I expect contributors to be power users and to be comfortable with tagging scheme and such. The custom theme generator is unlocked.
7. At 500 changesets, I expect contributors to be power users and to be comfortable with tagging scheme and such. The
custom theme generator is unlocked.
## License
GPLv3.0 + recommended pingback.
I love it to see where the project ends up. You are free to reuse the software (under GPL) but, when you have made your own change and are using it, I would like to know about it. Drop me a line, give a pingback in the issues,...
I love it to see where the project ends up. You are free to reuse the software (under GPL) but, when you have made your
own change and are using it, I would like to know about it. Drop me a line, give a pingback in the issues,...
## Dev
To develop or deploy a version of MapComplete, have a look [to the guide](Docs/Development_deployment.md).
## Translating MapComplete
The core strings and builtin themes of MapComplete are translated on [Hosted Weblate](https://hosted.weblate.org/projects/mapcomplete/core/).
You can easily make an account and start translating in their web-environment - no installation required.
The core strings and builtin themes of MapComplete are translated
on [Hosted Weblate](https://hosted.weblate.org/projects/mapcomplete/core/). You can easily make an account and start
translating in their web-environment - no installation required.
[![Translation status](https://hosted.weblate.org/widgets/mapcomplete/-/multi-blue.svg)](https://hosted.weblate.org/engage/mapcomplete/)
## Architecture
### High-level overview
The website is purely static. This means that there is no database here, nor one is needed as all the data is kept in OpenStreetMap, Wikimedia (for images), Imgur. Settings are saved in the preferences-space of the OSM-website, amended by some local-storage if the user is not logged-in.
The website is purely static. This means that there is no database here, nor one is needed as all the data is kept in
OpenStreetMap, Wikimedia (for images), Imgur. Settings are saved in the preferences-space of the OSM-website, amended by
some local-storage if the user is not logged-in.
When viewing, the data is loaded from overpass. The data is then converted (in the browser) to geojson, which is rendered by Leaflet.
When viewing, the data is loaded from overpass. The data is then converted (in the browser) to geojson, which is
rendered by Leaflet.
When a map feature is clicked, a popup shows the information, images and questions that are relevant for that object.
The answers given by the user are sent (after a few seconds) to OpenStreetMap directly - if the user is logged in. If not logged in, the user is prompted to do so.
The UI-event-source is a class where the entire system is built upon, it acts as an observable object: another object can register for changes to update when needed.
The answers given by the user are sent (after a few seconds) to OpenStreetMap directly - if the user is logged in. If
not logged in, the user is prompted to do so.
The UI-event-source is a class where the entire system is built upon, it acts as an observable object: another object
can register for changes to update when needed.
### Searching images
@ -114,15 +135,19 @@ Images are fetched from:
Images are uploaded to Imgur, as their API was way easier to handle. The URL is written into the changes.
The idea is that once in a while, the images are transferred to wikipedia or that we hook up wikimedia directly (but I need some help in getting their API working).
The idea is that once in a while, the images are transferred to wikipedia or that we hook up wikimedia directly (but I
need some help in getting their API working).
### Uploading changes
In order to avoid lots of small changesets, a changeset is opened and kept open. The changeset number is saved into the users preferences on OSM.
In order to avoid lots of small changesets, a changeset is opened and kept open. The changeset number is saved into the
users preferences on OSM.
Whenever a change is made -even adding a single tag - the change is uploaded into this changeset. If that fails, the changeset is probably closed and we open a new changeset.
Whenever a change is made -even adding a single tag - the change is uploaded into this changeset. If that fails, the
changeset is probably closed and we open a new changeset.
Note that changesets are closed automatically after one hour of inactivity, so we don't have to worry about closing them.
Note that changesets are closed automatically after one hour of inactivity, so we don't have to worry about closing
them.
# Documentation
@ -130,13 +155,11 @@ All documentation can be found in [here](Docs/)
# Privacy
Privacy is important, we try to leak as little information as possible.
All major personal information is handled by OSM.
Geolocation is available on mobile only through the device's GPS location (so no geolocation is sent of to Google).
Privacy is important, we try to leak as little information as possible. All major personal information is handled by
OSM. Geolocation is available on mobile only through the device's GPS location (so no geolocation is sent of to Google).
TODO: erase cookies of third party websites and API's
# Attribution and Copyright
The code is available under GPL; all map data comes from OpenStreetMap (both foreground and background maps).

View file

@ -12,6 +12,10 @@ export class CenterFlexedElement extends BaseUIElement {
return this._html;
}
AsMarkdown(): string {
return this._html;
}
protected InnerConstructElement(): HTMLElement {
const e = document.createElement("div");
e.innerHTML = this._html;
@ -25,8 +29,4 @@ export class CenterFlexedElement extends BaseUIElement {
e.style.alignItems = "center";
return e;
}
AsMarkdown(): string {
return this._html;
}
}

View file

@ -16,6 +16,10 @@ export default class Combine extends BaseUIElement {
});
}
AsMarkdown(): string {
return this.uiElements.map(el => el.AsMarkdown()).join(this.HasClass("flex-col") ? "\n\n" : " ");
}
protected InnerConstructElement(): HTMLElement {
const el = document.createElement("span")
@ -40,8 +44,4 @@ export default class Combine extends BaseUIElement {
return el;
}
AsMarkdown(): string {
return this.uiElements.map(el => el.AsMarkdown()).join(this.HasClass("flex-col") ? "\n\n" : " ");
}
}

View file

@ -12,14 +12,14 @@ export class FixedUiElement extends BaseUIElement {
return this._html;
}
AsMarkdown(): string {
return this._html;
}
protected InnerConstructElement(): HTMLElement {
const e = document.createElement("span")
e.innerHTML = this._html
return e;
}
AsMarkdown(): string {
return this._html;
}
}

View file

@ -16,6 +16,11 @@ export default class Link extends BaseUIElement {
}
AsMarkdown(): string {
// @ts-ignore
return `[${this._embeddedShow.AsMarkdown()}](${this._href.data ?? this._href})`;
}
protected InnerConstructElement(): HTMLElement {
const embeddedShow = this._embeddedShow?.ConstructElement();
if (embeddedShow === undefined) {
@ -36,9 +41,4 @@ export default class Link extends BaseUIElement {
return el;
}
AsMarkdown(): string {
// @ts-ignore
return `[${this._embeddedShow.AsMarkdown()}](${this._href.data ?? this._href})`;
}
}

View file

@ -13,6 +13,15 @@ export default class List extends BaseUIElement {
.map(Translations.W);
}
AsMarkdown(): string {
if (this._ordered) {
return "\n\n" + this.uiElements.map((el, i) => " " + i + ". " + el.AsMarkdown().replace(/\n/g, ' \n')).join("\n") + "\n"
} else {
return "\n\n" + this.uiElements.map(el => " - " + el.AsMarkdown().replace(/\n/g, ' \n')).join("\n") + "\n"
}
}
protected InnerConstructElement(): HTMLElement {
const el = document.createElement(this._ordered ? "ol" : "ul")
@ -31,13 +40,4 @@ export default class List extends BaseUIElement {
return el;
}
AsMarkdown(): string {
if(this._ordered){
return "\n\n"+this.uiElements.map((el, i) => " "+i+". "+el.AsMarkdown().replace(/\n/g, ' \n') ).join("\n") + "\n"
}else{
return "\n\n"+this.uiElements.map(el => " - "+el.AsMarkdown().replace(/\n/g, ' \n') ).join("\n")+"\n"
}
}
}

View file

@ -18,12 +18,12 @@ import BaseUIElement from "../BaseUIElement";
*/
export default class ScrollableFullScreen extends UIElement {
private static readonly empty = new FixedUiElement("");
private static readonly _actor = ScrollableFullScreen.InitActor();
private static _currentlyOpen: ScrollableFullScreen;
public isShown: UIEventSource<boolean>;
private _component: BaseUIElement;
private _fullscreencomponent: BaseUIElement;
private static readonly _actor = ScrollableFullScreen.InitActor();
private _hashToSet: string;
private static _currentlyOpen : ScrollableFullScreen;
constructor(title: ((mode: string) => BaseUIElement), content: ((mode: string) => BaseUIElement),
hashToSet: string,
@ -46,6 +46,23 @@ export default class ScrollableFullScreen extends UIElement {
})
}
private static clear() {
ScrollableFullScreen.empty.AttachTo("fullscreen")
const fs = document.getElementById("fullscreen");
ScrollableFullScreen._currentlyOpen?.isShown?.setData(false);
fs.classList.add("hidden")
Hash.hash.setData(undefined);
}
private static InitActor() {
Hash.hash.addCallback(hash => {
if (hash === undefined || hash === "") {
ScrollableFullScreen.clear()
}
});
return true;
}
InnerRender(): BaseUIElement {
return this._component;
}
@ -86,21 +103,4 @@ export default class ScrollableFullScreen extends UIElement {
}
private static clear() {
ScrollableFullScreen.empty.AttachTo("fullscreen")
const fs = document.getElementById("fullscreen");
ScrollableFullScreen._currentlyOpen?.isShown?.setData(false);
fs.classList.add("hidden")
Hash.hash.setData(undefined);
}
private static InitActor(){
Hash.hash.addCallback(hash => {
if(hash === undefined || hash === ""){
ScrollableFullScreen.clear()
}
});
return true;
}
}

View file

@ -4,22 +4,13 @@ import Translations from "../i18n/Translations";
export default class Title extends BaseUIElement {
private readonly _embedded: BaseUIElement;
private readonly _level: number;
constructor(embedded: string | BaseUIElement, level: number = 3) {
super()
this._embedded = Translations.W(embedded);
this._level = level;
}
protected InnerConstructElement(): HTMLElement {
const el = this._embedded.ConstructElement()
if(el === undefined){
return undefined;
}
const h = document.createElement("h"+this._level)
h.appendChild(el)
return h;
}
AsMarkdown(): string {
const embedded = " " + this._embedded.AsMarkdown() + " ";
@ -33,4 +24,14 @@ export default class Title extends BaseUIElement{
return "\n" + "#".repeat(this._level) + embedded + "\n\n";
}
protected InnerConstructElement(): HTMLElement {
const el = this._embedded.ConstructElement()
if (el === undefined) {
return undefined;
}
const h = document.createElement("h" + this._level)
h.appendChild(el)
return h;
}
}

View file

@ -9,8 +9,6 @@ import {DownloadPanel} from "./DownloadPanel";
import {SubtleButton} from "../Base/SubtleButton";
import Svg from "../../Svg";
import ExportPDF from "../ExportPDF";
import {Browser} from "leaflet";
import ie = Browser.ie;
import {FixedUiElement} from "../Base/FixedUiElement";
export default class AllDownloads extends ScrollableFullScreen {

View file

@ -37,7 +37,6 @@ export default class Attribution extends Combine {
const mapillary = new Link(Svg.mapillary_black_ui().SetClass("small-image"), mapillaryLink, true);
let editWithJosm = new VariableUiElement(
userDetails.map(userDetails => {

View file

@ -163,8 +163,6 @@ export default class MoreScreen extends Combine {
})
let description = Translations.WT(layout.shortDescription).Clone();
return new SubtleButton(layout.icon,
new Combine([

View file

@ -7,7 +7,6 @@ import {SubtleButton} from "../Base/SubtleButton";
import Translations from "../i18n/Translations";
import BaseUIElement from "../BaseUIElement";
import {VariableUiElement} from "../Base/VariableUIElement";
import Img from "../Base/Img";
import {UIEventSource} from "../../Logic/UIEventSource";
import LayerConfig from "../../Models/ThemeConfig/LayerConfig";

View file

@ -1,4 +1,3 @@
import Locale from "../i18n/Locale";
import {UIEventSource} from "../../Logic/UIEventSource";
import {Translation} from "../i18n/Translation";
import {VariableUiElement} from "../Base/VariableUIElement";

View file

@ -178,8 +178,6 @@ export default class ShareScreen extends Combine {
);
let editLayout: BaseUIElement = new FixedUiElement("");
if ((layoutDefinition !== undefined && State.state?.osmConnection !== undefined)) {
editLayout =

View file

@ -222,7 +222,6 @@ export default class SimpleAddUI extends Toggle {
)
const tagInfo = SimpleAddUI.CreateTagInfoFor(preset);
const cancelButton = new SubtleButton(Svg.close_ui(),

View file

@ -42,7 +42,6 @@ export default class ThemeIntroductionPanel extends VariableUiElement {
const welcomeBack = Translations.t.general.welcomeBack.Clone();
const loginStatus =
new Toggle(
new Toggle(

View file

@ -13,7 +13,6 @@ export default class UploadFlowStateUI extends VariableUiElement{
const t = Translations.t.image;
super(
queue.map(queue => {
const failedReasons = failed.data
const successCount = success.data.length
@ -38,8 +37,6 @@ export default class UploadFlowStateUI extends VariableUiElement{
return stateMessages
}, [failed, success])
);

View file

@ -25,6 +25,7 @@ import LayoutConfig from "../Models/ThemeConfig/LayoutConfig";
export default class ExportPDF {
// dimensions of the map in milimeter
public isRunning = new UIEventSource(true)
// A4: 297 * 210mm
private readonly mapW = 297;
private readonly mapH = 210;
@ -33,8 +34,6 @@ export default class ExportPDF {
private readonly _layout: UIEventSource<LayoutConfig>;
private _screenhotTaken = false;
public isRunning = new UIEventSource(true)
constructor(
options: {
freeDivId: string,

View file

@ -16,8 +16,7 @@ export default class DeleteImage extends Toggle {
.SetClass("rounded-full p-1")
.SetStyle("color:white;background:#ff8c8c")
.onClick(() => {
State.state?.changes?.
applyAction(new ChangeTagAction(tags.data.id, new Tag(key, oldValue), tags.data))
State.state?.changes?.applyAction(new ChangeTagAction(tags.data.id, new Tag(key, oldValue), tags.data))
});
const deleteButton = Translations.t.image.doDelete.Clone()

View file

@ -3,8 +3,10 @@ import {UIEventSource} from "../../Logic/UIEventSource";
export default class ColorPicker extends InputElement<string> {
IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
private readonly value: UIEventSource<string>
private readonly _element: HTMLElement
constructor(
value: UIEventSource<string> = new UIEventSource<string>(undefined)
) {
@ -26,18 +28,16 @@ private readonly _element : HTMLElement
}
}
protected InnerConstructElement(): HTMLElement {
return this._element;
}
GetValue(): UIEventSource<string> {
return this.value;
}
IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
IsValid(t: string): boolean {
return false;
}
protected InnerConstructElement(): HTMLElement {
return this._element;
}
}

View file

@ -13,9 +13,8 @@ import Loc from "../../Models/Loc";
*/
export default class DirectionInput extends InputElement<string> {
public static constructMinimap: ((any) => BaseUIElement);
private readonly _location: UIEventSource<Loc>;
public readonly IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
private readonly _location: UIEventSource<Loc>;
private readonly value: UIEventSource<string>;
private background;

View file

@ -4,8 +4,8 @@ import Translations from "../i18n/Translations";
import BaseUIElement from "../BaseUIElement";
export class FixedInputElement<T> extends InputElement<T> {
private readonly value: UIEventSource<T>;
public readonly IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
private readonly value: UIEventSource<T>;
private readonly _comparator: (t0: T, t1: T) => boolean;
private readonly _el: HTMLElement;
@ -30,10 +30,6 @@ export class FixedInputElement<T> extends InputElement<T> {
})
}
protected InnerConstructElement(): HTMLElement {
return this._el;
}
GetValue(): UIEventSource<T> {
return this.value;
}
@ -42,5 +38,9 @@ export class FixedInputElement<T> extends InputElement<T> {
return this._comparator(t, this.value.data);
}
protected InnerConstructElement(): HTMLElement {
return this._el;
}
}

View file

@ -3,8 +3,10 @@ import BaseUIElement from "../BaseUIElement";
export abstract class InputElement<T> extends BaseUIElement {
abstract GetValue() : UIEventSource<T>;
abstract IsSelected: UIEventSource<boolean>;
abstract GetValue(): UIEventSource<T>;
abstract IsValid(t: T): boolean;
}

View file

@ -6,17 +6,14 @@ import {Utils} from "../../Utils";
import Loc from "../../Models/Loc";
import {GeoOperations} from "../../Logic/GeoOperations";
import DirectionInput from "./DirectionInput";
import {RadioButton} from "./RadioButton";
import {FixedInputElement} from "./FixedInputElement";
/**
* Selects a length after clicking on the minimap, in meters
*/
export default class LengthInput extends InputElement<string> {
private readonly _location: UIEventSource<Loc>;
public readonly IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
private readonly _location: UIEventSource<Loc>;
private readonly value: UIEventSource<string>;
private background;

View file

@ -14,7 +14,27 @@ import * as L from "leaflet";
export default class LocationInput extends InputElement<Loc> {
private static readonly matchLayout = new UIEventSource(new LayoutConfig({
description: "Matchpoint style",
icon: "./assets/svg/crosshair-empty.svg",
id: "matchpoint",
language: ["en"],
layers: [{
id: "matchpoint", source: {
osmTags: {and: []}
},
icon: "./assets/svg/crosshair-empty.svg"
}],
maintainer: "MapComplete",
startLat: 0,
startLon: 0,
startZoom: 0,
title: "Location input",
version: "0"
}));
IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
public readonly snappedOnto: UIEventSource<any> = new UIEventSource<any>(undefined)
private _centerLocation: UIEventSource<Loc>;
private readonly mapBackground: UIEventSource<BaseLayer>;
private readonly _snapTo: UIEventSource<{ feature: any }[]>
@ -22,7 +42,6 @@ export default class LocationInput extends InputElement<Loc> {
private readonly _snappedPoint: UIEventSource<any>
private readonly _maxSnapDistance: number
private readonly _snappedPointTags: any;
public readonly snappedOnto: UIEventSource<any> = new UIEventSource<any>(undefined)
constructor(options: {
mapBackground?: UIEventSource<BaseLayer>,
@ -229,24 +248,4 @@ export default class LocationInput extends InputElement<Loc> {
}
}
private static readonly matchLayout = new UIEventSource(new LayoutConfig({
description: "Matchpoint style",
icon: "./assets/svg/crosshair-empty.svg",
id: "matchpoint",
language: ["en"],
layers: [{
id: "matchpoint", source: {
osmTags: {and: []}
},
icon: "./assets/svg/crosshair-empty.svg"
}],
maintainer: "MapComplete",
startLat: 0,
startLon: 0,
startZoom: 0,
title: "Location input",
version: "0"
}));
}

View file

@ -25,6 +25,19 @@ export class RadioButton<T> extends InputElement<T> {
this._dontStyle = options.dontStyle ?? false
}
IsValid(t: T): boolean {
for (const inputElement of this._elements) {
if (inputElement.IsValid(t)) {
return true;
}
}
return false;
}
GetValue(): UIEventSource<T> {
return this.value;
}
protected InnerConstructElement(): HTMLElement {
const elements = this._elements;
const selectFirstAsDefault = this._selectFirstAsDefault;
@ -166,19 +179,6 @@ export class RadioButton<T> extends InputElement<T> {
return form;
}
IsValid(t: T): boolean {
for (const inputElement of this._elements) {
if (inputElement.IsValid(t)) {
return true;
}
}
return false;
}
GetValue(): UIEventSource<T> {
return this.value;
}
/*
public ShowValue(t: T): boolean {
if (t === undefined) {

View file

@ -3,8 +3,8 @@ import {UIEventSource} from "../../Logic/UIEventSource";
export default class SimpleDatePicker extends InputElement<string> {
IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
private readonly value: UIEventSource<string>
private readonly _element: HTMLElement;
constructor(
@ -30,17 +30,16 @@ export default class SimpleDatePicker extends InputElement<string> {
}
protected InnerConstructElement(): HTMLElement {
return this._element
}
GetValue(): UIEventSource<string> {
return this.value;
}
IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
IsValid(t: string): boolean {
return false;
}
protected InnerConstructElement(): HTMLElement {
return this._element
}
}

View file

@ -95,10 +95,6 @@ export default class OpeningHoursInput extends InputElement<string> {
])
}
protected InnerConstructElement(): HTMLElement {
return this._element.ConstructElement()
}
GetValue(): UIEventSource<string> {
return this._value;
}
@ -107,4 +103,8 @@ export default class OpeningHoursInput extends InputElement<string> {
return true;
}
protected InnerConstructElement(): HTMLElement {
return this._element.ConstructElement()
}
}

View file

@ -25,12 +25,11 @@ export default class OpeningHoursPickerTable extends InputElement<OpeningHour[]>
Translations.t.general.weekdays.abbreviations.sunday
]
public readonly IsSelected: UIEventSource<boolean>;
private readonly source: UIEventSource<OpeningHour[]>;
/*
These html-elements are an overlay over the table columns and act as a host for the ranges in the weekdays
*/
public readonly weekdayElements: HTMLElement[] = Utils.TimesT(7, () => document.createElement("div"))
private readonly source: UIEventSource<OpeningHour[]>;
constructor(source?: UIEventSource<OpeningHour[]>) {
super();
@ -82,8 +81,6 @@ export default class OpeningHoursPickerTable extends InputElement<OpeningHour[]>
fullColumnSpan.appendChild(ranges.ConstructElement())
const fullColumnSpanWrapper = document.createElement("div")
fullColumnSpanWrapper.classList.add("absolute")
fullColumnSpanWrapper.style.zIndex = "10"

View file

@ -30,7 +30,6 @@ export default class EditableTagRendering extends Toggle {
});
const answerWithEditButton = new Combine([answer,
new Toggle(editButton, undefined, State.state.osmConnection.isLoggedIn)])
.SetClass("flex justify-between w-full")

View file

@ -138,6 +138,7 @@ export default class TagRenderingQuestion extends Combine {
}
return Utils.NoNull(configuration.mappings?.map((m, i) => excludeIndex === i ? undefined : m.ifnot))
}
const ff = TagRenderingQuestion.GenerateFreeform(configuration, applicableUnit, tagsSource);
const hasImages = mappings.filter(mapping => mapping.then.ExtractImages().length > 0).length > 0

View file

@ -385,6 +385,7 @@ export default class SpecialVisualizations {
]
static HelpMessage: BaseUIElement = SpecialVisualizations.GenHelpMessage();
private static GenHelpMessage() {
const helpTexts =

View file

@ -5,11 +5,13 @@ import BaseUIElement from "../BaseUIElement";
export default class Translations {
static t = AllTranslationAssets.t;
private static wtcache = {}
constructor() {
throw "Translations is static. If you want to intitialize a new translation, use the singular form"
}
static t = AllTranslationAssets.t;
public static W(s: string | BaseUIElement): BaseUIElement {
if (typeof (s) === "string") {
return new FixedUiElement(s);
@ -20,7 +22,6 @@ export default class Translations {
return s;
}
static T(t: string | any, context = undefined): Translation {
if (t === undefined || t === null) {
return undefined;
@ -39,7 +40,6 @@ export default class Translations {
return new Translation(t, context);
}
private static wtcache = {}
public static WT(s: string | Translation): Translation {
if (s === undefined || s === null) {
return undefined;

View file

@ -422,6 +422,12 @@ export class Utils {
return bestColor ?? hex;
}
public static setDefaults(options, defaults) {
for (let key in defaults) {
if (!(key in options)) options[key] = defaults[key];
}
return options;
}
private static tile2long(x, z) {
return (x / Math.pow(2, z) * 360 - 180);
@ -466,12 +472,5 @@ export class Utils {
b: parseInt(hex.substr(5, 2), 16),
}
}
public static setDefaults(options, defaults) {
for (let key in defaults) {
if (!(key in options)) options[key] = defaults[key];
}
return options;
}
}

View file

@ -1,10 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
<path class="st0" d="m128 64a64 64 0 0 1-64 64 64 64 0 0 1-64-64 64 64 0 0 1 64-64 64 64 0 0 1 64 64" fill="#529add"/>
<path class="st0" d="m128 64a64 64 0 0 1-64 64 64 64 0 0 1-64-64 64 64 0 0 1 64-64 64 64 0 0 1 64 64"
fill="#529add"/>
<path d="m31.992 32.08v87.273a64 64 0 0 0 16 6.5293v-93.803z" fill="#666"/>
<path d="m79.992 32.08v93.84a64 64 0 0 0 16-6.582v-87.258z" fill="#666"/>
<path d="m23.992 44.08c-4.456 0-8.0429 3.587-8.0429 8.043v31.914c0 4.456 3.5869 8.043 8.0429 8.043h79.914c4.456 0 8.043-3.587 8.043-8.043v-31.914c0-4.456-3.587-8.043-8.043-8.043z" fill-opacity=".2"/>
<path d="m24.036 40.08h79.913c4.456 0 8.0433 3.5873 8.0433 8.0433v31.913c0 4.456-3.5873 8.0433-8.0433 8.0433h-79.913c-4.456 0-8.0433-3.5873-8.0433-8.0433v-31.913c0-4.456 3.5873-8.0433 8.0433-8.0433z" fill="#fff" style="paint-order:normal"/>
<path d="m23.992 40.08c-3.8167 0-6.9867 2.6476-7.7949 6.2129l28.746 41.787h14.143l-32.332-48zm16.619 0 32.332 48h14.143l-32.332-48zm28 0 32.332 48h3.0488c3.6926 0 6.7759-2.4795 7.7051-5.8691l-28.943-42.131zm28 0 15.381 22v-14c0-4.432-3.568-8-8-8zm-80.619 26v14c0 4.432 3.568 8 8 8h7.0938z" fill="#dd2e44" style="paint-order:normal"/>
<path d="m24.03 40.08h79.924c4.4531 0 8.038 3.5849 8.038 8.038v31.924c0 4.453-3.5849 8.038-8.038 8.038h-79.924c-4.4531 0-8.038-3.5849-8.038-8.038v-31.924c0-4.453 3.5849-8.038 8.038-8.038z" fill="none" stroke="#555" stroke-linecap="round" stroke-linejoin="round" stroke-width="4" style="paint-order:stroke markers fill"/>
<path d="m23.992 44.08c-4.456 0-8.0429 3.587-8.0429 8.043v31.914c0 4.456 3.5869 8.043 8.0429 8.043h79.914c4.456 0 8.043-3.587 8.043-8.043v-31.914c0-4.456-3.587-8.043-8.043-8.043z"
fill-opacity=".2"/>
<path d="m24.036 40.08h79.913c4.456 0 8.0433 3.5873 8.0433 8.0433v31.913c0 4.456-3.5873 8.0433-8.0433 8.0433h-79.913c-4.456 0-8.0433-3.5873-8.0433-8.0433v-31.913c0-4.456 3.5873-8.0433 8.0433-8.0433z"
fill="#fff" style="paint-order:normal"/>
<path d="m23.992 40.08c-3.8167 0-6.9867 2.6476-7.7949 6.2129l28.746 41.787h14.143l-32.332-48zm16.619 0 32.332 48h14.143l-32.332-48zm28 0 32.332 48h3.0488c3.6926 0 6.7759-2.4795 7.7051-5.8691l-28.943-42.131zm28 0 15.381 22v-14c0-4.432-3.568-8-8-8zm-80.619 26v14c0 4.432 3.568 8 8 8h7.0938z"
fill="#dd2e44" style="paint-order:normal"/>
<path d="m24.03 40.08h79.924c4.4531 0 8.038 3.5849 8.038 8.038v31.924c0 4.453-3.5849 8.038-8.038 8.038h-79.924c-4.4531 0-8.038-3.5849-8.038-8.038v-31.924c0-4.453 3.5849-8.038 8.038-8.038z"
fill="none" stroke="#555" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"
style="paint-order:stroke markers fill"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -1,16 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
<path d="m128 64c0 35.346-28.654 64-64 64-35.346 0-64-28.654-64-64 0-35.346 28.654-64 64-64 35.346 0 64 28.654 64 64" fill="#9bbe55" stroke-width=".2"/>
<path d="m20.021 39.998c-2.2408 0-4.0449 1.8041-4.0449 4.0449v15.91c0 2.2408 1.8042 4.045 4.0449 4.045h11.955v8h-16v8h16v16h8v-16h48v16h8v-16h16v-8h-16v-8h11.955c2.2408 0 4.0449-1.8042 4.0449-4.045v-15.91c0-2.2408-1.8041-4.0449-4.0449-4.0449zm19.955 24h48v8h-48z" fill-opacity=".2" style="paint-order:normal"/>
<path d="m128 64c0 35.346-28.654 64-64 64-35.346 0-64-28.654-64-64 0-35.346 28.654-64 64-64 35.346 0 64 28.654 64 64"
fill="#9bbe55" stroke-width=".2"/>
<path d="m20.021 39.998c-2.2408 0-4.0449 1.8041-4.0449 4.0449v15.91c0 2.2408 1.8042 4.045 4.0449 4.045h11.955v8h-16v8h16v16h8v-16h48v16h8v-16h16v-8h-16v-8h11.955c2.2408 0 4.0449-1.8042 4.0449-4.045v-15.91c0-2.2408-1.8041-4.0449-4.0449-4.0449zm19.955 24h48v8h-48z"
fill-opacity=".2" style="paint-order:normal"/>
<g transform="translate(717 144)">
<path d="m-685.02-84.002h8v32h-8z" fill="#666" style="paint-order:normal"/>
<path d="m-629.02-84.002h8v32h-8z" fill="#666" style="paint-order:normal"/>
<path d="m-696.98-108h87.911c2.2408 0 4.0447 1.804 4.0447 4.0447v15.911c0 2.2408-1.804 4.0447-4.0447 4.0447h-87.911c-2.2408 0-4.0447-1.8039-4.0447-4.0447v-15.911c0-2.2408 1.804-4.0447 4.0447-4.0447z" fill="#ae8862" style="paint-order:normal"/>
<path d="m-696.98-108h87.911c2.2408 0 4.0447 1.804 4.0447 4.0447v15.911c0 2.2408-1.804 4.0447-4.0447 4.0447h-87.911c-2.2408 0-4.0447-1.8039-4.0447-4.0447v-15.911c0-2.2408 1.804-4.0447 4.0447-4.0447z"
fill="#ae8862" style="paint-order:normal"/>
<path d="m-693.02-104h80v4h-80z" fill="#896847" style="paint-order:normal"/>
<path d="m-701.02-72.002h96v4h-96z" fill="#896847" style="paint-order:normal"/>
<path d="m-693.02-92.002h80v4h-80z" fill="#896847" style="paint-order:normal"/>
<path d="m-677.02-96.002a4 4 0 0 1-4 4 4 4 0 0 1-4-4 4 4 0 0 1 4-4 4 4 0 0 1 4 4" fill="#666" style="paint-order:normal"/>
<path d="m-621.02-96.002a4 4 0 0 1-4 4 4 4 0 0 1-4-4 4 4 0 0 1 4-4 4 4 0 0 1 4 4" fill="#666" style="paint-order:normal"/>
<path d="m-677.02-96.002a4 4 0 0 1-4 4 4 4 0 0 1-4-4 4 4 0 0 1 4-4 4 4 0 0 1 4 4" fill="#666"
style="paint-order:normal"/>
<path d="m-621.02-96.002a4 4 0 0 1-4 4 4 4 0 0 1-4-4 4 4 0 0 1 4-4 4 4 0 0 1 4 4" fill="#666"
style="paint-order:normal"/>
<path d="m-701.02-76.002h96v4h-96z" fill="#ae8862" style="paint-order:normal"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -3,10 +3,9 @@
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
id="svg4"
sodipodi:docname="bicycle_library.svg"

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -5,10 +5,9 @@
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns="http://www.w3.org/2000/svg"
width="25.929167mm"
height="30.958698mm"
viewBox="0 0 25.929167 30.958698"

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

View file

@ -5,10 +5,9 @@
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns="http://www.w3.org/2000/svg"
width="51.841461mm"
height="36.68618mm"
viewBox="0 0 51.841461 36.68618"

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View file

@ -1,16 +1,23 @@
<svg width="98" height="124" viewBox="0 0 98 124" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M55.0445 114.094C53.2614 117.981 47.7386 117.981 45.9555 114.094L15.2124 47.085C13.6928 43.7729 16.1129 40 19.7569 40L81.2431 40C84.8871 40 87.3072 43.7729 85.7876 47.085L55.0445 114.094Z" fill="#694E2D"/>
<path d="M55.0445 114.094C53.2614 117.981 47.7386 117.981 45.9555 114.094L15.2124 47.085C13.6928 43.7729 16.1129 40 19.7569 40L81.2431 40C84.8871 40 87.3072 43.7729 85.7876 47.085L55.0445 114.094Z"
fill="#694E2D"/>
<circle cx="49" cy="49" r="49" fill="#694E2D"/>
<path d="M67.5 76.3395H62.0436C65.206 74.0913 67.7862 70.9283 69.476 67.1884H74.8929C79.4101 67.1884 83.0851 63.1243 83.0851 58.1289C83.0851 53.1335 79.4101 49.0695 74.8929 49.0695H71.6699V44.494C71.6699 43.483 70.9288 42.6637 70.0149 42.6637H25.655C24.7411 42.6637 24 43.4829 24 44.494V56.9003C24 65.0531 27.8426 72.2276 33.6265 76.3396H27.3352C26.4212 76.3395 25.6551 77.1588 25.6551 78.1698C25.6551 79.1807 26.4212 80 27.3351 80H44.8888H50.7817H67.5C68.4139 80 69 79.0111 69 78C69 76.9889 68.4139 76.3395 67.5 76.3395ZM74.8931 52.7298C77.5852 52.7298 79.7754 55.1519 79.7754 58.1289C79.7754 61.106 77.5852 63.5281 74.8931 63.5281H70.7897C71.3601 61.4274 71.6702 59.2033 71.6702 56.9001V52.7298H74.8931ZM37.1501 22.8301C39.7848 19.9164 39.7848 15.1754 37.1501 12.2614L37.0263 12.1245C36.3799 11.41 36.3799 10.2511 37.0263 9.53653C37.6727 8.82167 38.7203 8.82167 39.3668 9.53653L39.4906 9.67342C43.4157 14.014 43.4157 21.0775 39.4906 25.4183C38.2143 26.8298 37.5116 28.7061 37.5116 30.7025C37.5116 32.6989 38.2146 34.5752 39.4906 35.987C40.137 36.7015 40.137 37.8604 39.4906 38.575C39.1675 38.9327 38.7438 39.1113 38.3202 39.1113C37.8965 39.1113 37.4732 38.9327 37.1497 38.575C35.2481 36.4725 34.2011 33.6766 34.2011 30.7025C34.2015 27.7285 35.2487 24.9326 37.1501 22.8301ZM46.7302 22.8301C48.0065 21.4186 48.7096 19.5419 48.7096 17.5455C48.7096 15.5492 48.0065 13.6729 46.7302 12.261L46.6064 12.1241C45.96 11.4096 45.96 10.2507 46.6064 9.53614C47.2528 8.82129 48.3004 8.82129 48.9469 9.53614L49.0707 9.67303C50.9723 11.7755 52.0197 14.5718 52.0197 17.5455C52.0197 20.5193 50.9724 23.3154 49.0707 25.4181C47.7944 26.8295 47.0917 28.7058 47.0917 30.7022C47.0917 32.6986 47.7947 34.5749 49.0707 35.9868C49.7172 36.7013 49.7172 37.8601 49.0707 38.5747C48.7476 38.9324 48.324 39.111 47.9003 39.111C47.4766 39.111 47.0533 38.9324 46.7298 38.5747C44.8283 36.4723 43.7812 33.6763 43.7812 30.7022C43.7812 27.7285 44.8286 24.9326 46.7302 22.8301ZM56.3104 22.8297C58.9448 19.9164 58.9448 15.1754 56.3104 12.2614L56.1866 12.1245C55.5402 11.41 55.5402 10.2511 56.1866 9.53653C56.833 8.82167 57.8806 8.82167 58.5272 9.53653L58.651 9.67342C62.576 14.014 62.576 21.0775 58.651 25.4183C57.3746 26.8298 56.6715 28.7061 56.6715 30.7025C56.6715 32.6989 57.3746 34.5752 58.6506 35.9867C59.297 36.7015 59.297 37.8604 58.6506 38.575C58.3275 38.9327 57.9038 39.1113 57.4802 39.1113C57.0565 39.1113 56.6331 38.9327 56.3101 38.5754C54.4085 36.4725 53.3611 33.6766 53.3611 30.7026C53.3615 27.7285 54.4087 24.9326 56.3104 22.8297Z" fill="white"/>
<path d="M67.5 76.3395H62.0436C65.206 74.0913 67.7862 70.9283 69.476 67.1884H74.8929C79.4101 67.1884 83.0851 63.1243 83.0851 58.1289C83.0851 53.1335 79.4101 49.0695 74.8929 49.0695H71.6699V44.494C71.6699 43.483 70.9288 42.6637 70.0149 42.6637H25.655C24.7411 42.6637 24 43.4829 24 44.494V56.9003C24 65.0531 27.8426 72.2276 33.6265 76.3396H27.3352C26.4212 76.3395 25.6551 77.1588 25.6551 78.1698C25.6551 79.1807 26.4212 80 27.3351 80H44.8888H50.7817H67.5C68.4139 80 69 79.0111 69 78C69 76.9889 68.4139 76.3395 67.5 76.3395ZM74.8931 52.7298C77.5852 52.7298 79.7754 55.1519 79.7754 58.1289C79.7754 61.106 77.5852 63.5281 74.8931 63.5281H70.7897C71.3601 61.4274 71.6702 59.2033 71.6702 56.9001V52.7298H74.8931ZM37.1501 22.8301C39.7848 19.9164 39.7848 15.1754 37.1501 12.2614L37.0263 12.1245C36.3799 11.41 36.3799 10.2511 37.0263 9.53653C37.6727 8.82167 38.7203 8.82167 39.3668 9.53653L39.4906 9.67342C43.4157 14.014 43.4157 21.0775 39.4906 25.4183C38.2143 26.8298 37.5116 28.7061 37.5116 30.7025C37.5116 32.6989 38.2146 34.5752 39.4906 35.987C40.137 36.7015 40.137 37.8604 39.4906 38.575C39.1675 38.9327 38.7438 39.1113 38.3202 39.1113C37.8965 39.1113 37.4732 38.9327 37.1497 38.575C35.2481 36.4725 34.2011 33.6766 34.2011 30.7025C34.2015 27.7285 35.2487 24.9326 37.1501 22.8301ZM46.7302 22.8301C48.0065 21.4186 48.7096 19.5419 48.7096 17.5455C48.7096 15.5492 48.0065 13.6729 46.7302 12.261L46.6064 12.1241C45.96 11.4096 45.96 10.2507 46.6064 9.53614C47.2528 8.82129 48.3004 8.82129 48.9469 9.53614L49.0707 9.67303C50.9723 11.7755 52.0197 14.5718 52.0197 17.5455C52.0197 20.5193 50.9724 23.3154 49.0707 25.4181C47.7944 26.8295 47.0917 28.7058 47.0917 30.7022C47.0917 32.6986 47.7947 34.5749 49.0707 35.9868C49.7172 36.7013 49.7172 37.8601 49.0707 38.5747C48.7476 38.9324 48.324 39.111 47.9003 39.111C47.4766 39.111 47.0533 38.9324 46.7298 38.5747C44.8283 36.4723 43.7812 33.6763 43.7812 30.7022C43.7812 27.7285 44.8286 24.9326 46.7302 22.8301ZM56.3104 22.8297C58.9448 19.9164 58.9448 15.1754 56.3104 12.2614L56.1866 12.1245C55.5402 11.41 55.5402 10.2511 56.1866 9.53653C56.833 8.82167 57.8806 8.82167 58.5272 9.53653L58.651 9.67342C62.576 14.014 62.576 21.0775 58.651 25.4183C57.3746 26.8298 56.6715 28.7061 56.6715 30.7025C56.6715 32.6989 57.3746 34.5752 58.6506 35.9867C59.297 36.7015 59.297 37.8604 58.6506 38.575C58.3275 38.9327 57.9038 39.1113 57.4802 39.1113C57.0565 39.1113 56.6331 38.9327 56.3101 38.5754C54.4085 36.4725 53.3611 33.6766 53.3611 30.7026C53.3615 27.7285 54.4087 24.9326 56.3104 22.8297Z"
fill="white"/>
<g filter="url(#filter0_d)">
<path d="M45.4541 63.4281H35.5495L40.952 51.3942H46.3545H50.2563H54.4583M54.4583 51.3942L52.9576 48H55.0586H57.1595M54.4583 51.3942L55.0586 52.937L56.2591 55.4055L59.5607 63.4281M54.4583 51.3942L51.607 56.0226L49.8962 58.7996M48.7556 60.651L49.8962 58.7996M43.053 54.7883L46.0544 61.5767L40.0516 48L41.8524 51.7027M47.8552 62.1938L49.8962 58.7996" stroke="#694E2D" stroke-width="2"/>
<path d="M48.5098 62.9031C48.5098 63.833 47.78 64.563 46.9088 64.563C46.0375 64.563 45.3078 63.833 45.3078 62.9031C45.3078 61.9732 46.0375 61.2432 46.9088 61.2432C47.78 61.2432 48.5098 61.9732 48.5098 62.9031Z" stroke="#694E2D"/>
<path d="M42.007 62.286C42.007 66.0203 39.0694 69 35.5035 69C31.9376 69 29 66.0203 29 62.286C29 58.5517 31.9376 55.572 35.5035 55.572C39.0694 55.572 42.007 58.5517 42.007 62.286Z" stroke="#694E2D" stroke-width="2"/>
<path d="M45.4541 63.4281H35.5495L40.952 51.3942H46.3545H50.2563H54.4583M54.4583 51.3942L52.9576 48H55.0586H57.1595M54.4583 51.3942L55.0586 52.937L56.2591 55.4055L59.5607 63.4281M54.4583 51.3942L51.607 56.0226L49.8962 58.7996M48.7556 60.651L49.8962 58.7996M43.053 54.7883L46.0544 61.5767L40.0516 48L41.8524 51.7027M47.8552 62.1938L49.8962 58.7996"
stroke="#694E2D" stroke-width="2"/>
<path d="M48.5098 62.9031C48.5098 63.833 47.78 64.563 46.9088 64.563C46.0375 64.563 45.3078 63.833 45.3078 62.9031C45.3078 61.9732 46.0375 61.2432 46.9088 61.2432C47.78 61.2432 48.5098 61.9732 48.5098 62.9031Z"
stroke="#694E2D"/>
<path d="M42.007 62.286C42.007 66.0203 39.0694 69 35.5035 69C31.9376 69 29 66.0203 29 62.286C29 58.5517 31.9376 55.572 35.5035 55.572C39.0694 55.572 42.007 58.5517 42.007 62.286Z"
stroke="#694E2D" stroke-width="2"/>
<ellipse cx="63.1725" cy="56.7207" rx="0.217504" ry="0.223607" fill="black" fill-opacity="0.49"/>
</g>
<path d="M66.007 62.714C66.007 66.4483 63.0694 69.4281 59.5035 69.4281C55.9376 69.4281 53 66.4483 53 62.714C53 58.9797 55.9376 56 59.5035 56C63.0694 56 66.007 58.9797 66.007 62.714Z" stroke="#694E2D" stroke-width="2"/>
<path d="M66.007 62.714C66.007 66.4483 63.0694 69.4281 59.5035 69.4281C55.9376 69.4281 53 66.4483 53 62.714C53 58.9797 55.9376 56 59.5035 56C63.0694 56 66.007 58.9797 66.007 62.714Z"
stroke="#694E2D" stroke-width="2"/>
<defs>
<filter id="filter0_d" x="24" y="47" width="43.39" height="31" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<filter id="filter0_d" x="24" y="47" width="43.39" height="31" filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View file

@ -3,10 +3,9 @@
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns="http://www.w3.org/2000/svg"
width="98"
height="124"
viewBox="0 0 98 124"

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -3,10 +3,9 @@
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns="http://www.w3.org/2000/svg"
width="98"
height="98"
viewBox="0 0 98 98"

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -3,7 +3,6 @@
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg27"
version="1.1"

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View file

@ -5,10 +5,9 @@
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
x="0px"
y="0px"
@ -20,8 +19,10 @@
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"><metadata
id="metadata19"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
id="defs17" /><sodipodi:namedview
rdf:resource="http://purl.org/dc/dcmitype/StillImage"/></cc:Work></rdf:RDF></metadata>
<defs
id="defs17"/>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
@ -72,7 +73,8 @@
d="M 150,20 V 285"
id="path828"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" /><circle
sodipodi:nodetypes="cc"/>
<circle
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:15;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path830"
cx="150"

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.2.1, 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"
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
viewBox="0 0 300 300" style="enable-background:new 0 0 300 300;" xml:space="preserve">
<style type="text/css">
.st0{fill:#0181C2;}

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -1,11 +1,14 @@
<svg width="97" height="123" viewBox="0 0 97 123" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M52.1412 111.419C50.4633 115.605 44.5366 115.605 42.8588 111.419L24.7014 66.1099C23.385 62.8252 25.8039 59.25 29.3426 59.25L65.6574 59.25C69.1962 59.25 71.615 62.8252 70.2986 66.11L52.1412 111.419Z" fill="#5675DF"/>
<path d="M52.1412 111.419C50.4633 115.605 44.5366 115.605 42.8588 111.419L24.7014 66.1099C23.385 62.8252 25.8039 59.25 29.3426 59.25L65.6574 59.25C69.1962 59.25 71.615 62.8252 70.2986 66.11L52.1412 111.419Z"
fill="#5675DF"/>
<ellipse cx="48.5" cy="47.5" rx="48.5" ry="47.5" fill="#5675DF"/>
<g filter="url(#filter0_d)">
<path d="M42.2812 53.1875V71H36.2812V25.5H53.0625C58.0417 25.5 61.9375 26.7708 64.75 29.3125C67.5833 31.8542 69 35.2188 69 39.4062C69 43.8229 67.6146 47.2292 64.8438 49.625C62.0938 52 58.1458 53.1875 53 53.1875H42.2812ZM42.2812 48.2812H53.0625C56.2708 48.2812 58.7292 47.5312 60.4375 46.0312C62.1458 44.5104 63 42.3229 63 39.4688C63 36.7604 62.1458 34.5938 60.4375 32.9688C58.7292 31.3438 56.3854 30.5 53.4062 30.4375H42.2812V48.2812Z" fill="white"/>
<path d="M42.2812 53.1875V71H36.2812V25.5H53.0625C58.0417 25.5 61.9375 26.7708 64.75 29.3125C67.5833 31.8542 69 35.2188 69 39.4062C69 43.8229 67.6146 47.2292 64.8438 49.625C62.0938 52 58.1458 53.1875 53 53.1875H42.2812ZM42.2812 48.2812H53.0625C56.2708 48.2812 58.7292 47.5312 60.4375 46.0312C62.1458 44.5104 63 42.3229 63 39.4688C63 36.7604 62.1458 34.5938 60.4375 32.9688C58.7292 31.3438 56.3854 30.5 53.4062 30.4375H42.2812V48.2812Z"
fill="white"/>
</g>
<defs>
<filter id="filter0_d" x="32.2812" y="25.5" width="40.7188" height="53.5" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<filter id="filter0_d" x="32.2812" y="25.5" width="40.7188" height="53.5" filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -1,11 +1,13 @@
<svg width="97" height="123" viewBox="0 0 97 123" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M52.1412 111.419C50.4633 115.605 44.5366 115.605 42.8588 111.419L24.7014 66.1099C23.385 62.8252 25.8039 59.25 29.3426 59.25L65.6574 59.25C69.1962 59.25 71.615 62.8252 70.2986 66.11L52.1412 111.419Z" fill="#5675DF"/>
<path d="M52.1412 111.419C50.4633 115.605 44.5366 115.605 42.8588 111.419L24.7014 66.1099C23.385 62.8252 25.8039 59.25 29.3426 59.25L65.6574 59.25C69.1962 59.25 71.615 62.8252 70.2986 66.11L52.1412 111.419Z"
fill="#5675DF"/>
<ellipse cx="48.5" cy="47.5" rx="48.5" ry="47.5" fill="#5675DF"/>
<g filter="url(#filter0_d)">
<circle cx="39" cy="66" r="2" stroke="white" stroke-width="2"/>
</g>
<g filter="url(#filter1_d)">
<path d="M37.375 67H25L31.75 51.4H38.5H43.375H48.625M48.625 51.4L46.75 47H49.375H52M48.625 51.4L49.375 53.4L50.875 56.6L55 67M48.625 51.4L45.0625 57.4L42.925 61M41.5 63.4L42.925 61M34.375 55.8L38.125 64.6L30.625 47L32.875 51.8M40.375 65.4L42.925 61" stroke="white" stroke-width="2"/>
<path d="M37.375 67H25L31.75 51.4H38.5H43.375H48.625M48.625 51.4L46.75 47H49.375H52M48.625 51.4L49.375 53.4L50.875 56.6L55 67M48.625 51.4L45.0625 57.4L42.925 61M41.5 63.4L42.925 61M34.375 55.8L38.125 64.6L30.625 47L32.875 51.8M40.375 65.4L42.925 61"
stroke="white" stroke-width="2"/>
</g>
<g filter="url(#filter2_d)">
<circle cx="23" cy="67" r="9" stroke="white" stroke-width="2"/>
@ -13,7 +15,8 @@
<g filter="url(#filter3_d)">
<circle cx="55" cy="67" r="9" stroke="white" stroke-width="2"/>
</g>
<path d="M61 77V59.0476V55.9524L62.4814 54.4851C64.4301 52.5549 67.5699 52.5549 69.5186 54.4851L71 55.9524V58.4286V77" stroke="white" stroke-width="2"/>
<path d="M61 77V59.0476V55.9524L62.4814 54.4851C64.4301 52.5549 67.5699 52.5549 69.5186 54.4851L71 55.9524V58.4286V77"
stroke="white" stroke-width="2"/>
<line x1="66" y1="53" x2="66" y2="16" stroke="white" stroke-width="2"/>
<g filter="url(#filter4_d)">
<circle cx="66" cy="23" r="13" fill="white"/>
@ -22,11 +25,13 @@
<circle cx="66" cy="23" r="11" fill="#496DEB"/>
</g>
<g filter="url(#filter6_d)">
<path d="M64.1729 24.9902V30H62.4854V17.2031H67.2051C68.6055 17.2031 69.7012 17.5605 70.4922 18.2754C71.2891 18.9902 71.6875 19.9365 71.6875 21.1143C71.6875 22.3564 71.2979 23.3145 70.5186 23.9883C69.7451 24.6562 68.6348 24.9902 67.1875 24.9902H64.1729ZM64.1729 23.6104H67.2051C68.1074 23.6104 68.7988 23.3994 69.2793 22.9775C69.7598 22.5498 70 21.9346 70 21.1318C70 20.3701 69.7598 19.7607 69.2793 19.3037C68.7988 18.8467 68.1396 18.6094 67.3018 18.5918H64.1729V23.6104Z" fill="white"/>
<path d="M64.1729 24.9902V30H62.4854V17.2031H67.2051C68.6055 17.2031 69.7012 17.5605 70.4922 18.2754C71.2891 18.9902 71.6875 19.9365 71.6875 21.1143C71.6875 22.3564 71.2979 23.3145 70.5186 23.9883C69.7451 24.6562 68.6348 24.9902 67.1875 24.9902H64.1729ZM64.1729 23.6104H67.2051C68.1074 23.6104 68.7988 23.3994 69.2793 22.9775C69.7598 22.5498 70 21.9346 70 21.1318C70 20.3701 69.7598 19.7607 69.2793 19.3037C68.7988 18.8467 68.1396 18.6094 67.3018 18.5918H64.1729V23.6104Z"
fill="white"/>
</g>
<line x1="43" y1="78" x2="72" y2="78" stroke="white" stroke-width="2"/>
<defs>
<filter id="filter0_d" x="32" y="63" width="14" height="14" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<filter id="filter0_d" x="32" y="63" width="14" height="14" filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
@ -35,7 +40,8 @@
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter1_d" x="19.4777" y="46" width="40.4518" height="30" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<filter id="filter1_d" x="19.4777" y="46" width="40.4518" height="30" filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
@ -44,7 +50,8 @@
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter2_d" x="9" y="57" width="28" height="28" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<filter id="filter2_d" x="9" y="57" width="28" height="28" filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
@ -53,7 +60,8 @@
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter3_d" x="41" y="57" width="28" height="28" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<filter id="filter3_d" x="41" y="57" width="28" height="28" filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
@ -62,7 +70,8 @@
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter4_d" x="49" y="10" width="34" height="34" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<filter id="filter4_d" x="49" y="10" width="34" height="34" filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
@ -71,7 +80,8 @@
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter5_d" x="51" y="12" width="30" height="30" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<filter id="filter5_d" x="51" y="12" width="30" height="30" filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
@ -80,7 +90,8 @@
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter6_d" x="58.4854" y="17.2031" width="17.2021" height="20.7969" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<filter id="filter6_d" x="58.4854" y="17.2031" width="17.2021" height="20.7969" filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>

Before

Width:  |  Height:  |  Size: 6 KiB

After

Width:  |  Height:  |  Size: 7 KiB

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.2.1, 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"
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
viewBox="0 0 300 300" style="enable-background:new 0 0 300 300;" xml:space="preserve">
<style type="text/css">
.st0{fill:#0181C2;}
@ -99,7 +99,8 @@
C-1180.6,246.5-1181.2,246-1181.5,245.3z"/>
<path class="st5" d="M-1190.8,240.4c-1,0.6-2.2,0.6-3.3,0c-0.3-0.2-0.6-0.4-0.9-0.6c0.4-0.5,0.8-0.9,1.2-1.4
C-1192.8,239.2-1191.8,239.8-1190.8,240.4z"/>
<path class="st5" d="M-1167.7,249.2c-3.2-0.3-6.3-0.9-9.5-1.7c0-0.2,0.1-0.3,0.1-0.5C-1173.8,248.2-1170.6,248.9-1167.7,249.2z"
<path class="st5"
d="M-1167.7,249.2c-3.2-0.3-6.3-0.9-9.5-1.7c0-0.2,0.1-0.3,0.1-0.5C-1173.8,248.2-1170.6,248.9-1167.7,249.2z"
/>
<path class="st5" d="M-1190.7,234.8c1.5,0.9,2,2.9,1.1,4.5c-0.3,0.5-0.7,0.9-1.2,1.1c-1-0.6-2-1.3-3-2
C-1192.8,237.2-1191.8,236-1190.7,234.8z"/>
@ -140,7 +141,8 @@
L-1115.1,219.6z"/>
<path class="st6" d="M-1178.1,219.6h-12c1.8,0,3.2,1.4,3.2,3.2v14.8h12v-14.8C-1174.9,221-1176.3,219.6-1178.1,219.6
L-1178.1,219.6z"/>
<path class="st6" d="M-1038.4,110.7h-183.4c-4.4,0-8-3.6-8-8.1v-9.9h199.5v9.9C-1030.4,107.1-1034,110.7-1038.4,110.7z"/>
<path class="st6"
d="M-1038.4,110.7h-183.4c-4.4,0-8-3.6-8-8.1v-9.9h199.5v9.9C-1030.4,107.1-1034,110.7-1038.4,110.7z"/>
</g>
<path class="st6" d="M-1042.4,92.8v9.9c0,4.5-3.6,8.1-8,8.1h12c4.4,0,8-3.6,8-8.1v-9.9L-1042.4,92.8z"/>
<path class="st6" d="M-1038.4,231.6h-183.4c-4.4,0-8,3.6-8,8.1v7.9c0,1.1,0.9,2,2,2h195.5c1.1,0,2-0.9,2-2v-7.9

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.2.1, 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"
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
viewBox="0 0 300 300" style="enable-background:new 0 0 300 300;" xml:space="preserve">
<style type="text/css">
.st0{fill:#0181C2;}

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.2.1, 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"
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
viewBox="0 0 300 300" style="enable-background:new 0 0 300 300;" xml:space="preserve">
<style type="text/css">
.st0{fill:#0181C2;}

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.2.1, 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"
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
viewBox="0 0 300 300" style="enable-background:new 0 0 300 300;" xml:space="preserve">
<style type="text/css">
.st0{fill:#0181C2;}

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.2.1, 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"
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
viewBox="0 0 300 300" style="enable-background:new 0 0 300 300;" xml:space="preserve">
<style type="text/css">
.st0{fill:#0181C2;}

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View file

@ -3,10 +3,9 @@
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns="http://www.w3.org/2000/svg"
width="98"
height="98"
viewBox="0 0 98 98"

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View file

@ -1,8 +1,10 @@
<svg width="104" height="123" viewBox="0 0 104 123" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M60.0445 113.094C58.2614 116.981 52.7386 116.981 50.9555 113.094L20.2124 46.085C18.6928 42.7729 21.1129 39 24.7569 39L86.2431 39C89.8871 39 92.3072 42.7729 90.7876 46.085L60.0445 113.094Z" fill="#171615"/>
<path d="M60.0445 113.094C58.2614 116.981 52.7386 116.981 50.9555 113.094L20.2124 46.085C18.6928 42.7729 21.1129 39 24.7569 39L86.2431 39C89.8871 39 92.3072 42.7729 90.7876 46.085L60.0445 113.094Z"
fill="#171615"/>
<circle cx="55" cy="49" r="49" fill="#171615"/>
<g clip-path="url(#clip0)" filter="url(#filter0_d)">
<path d="M59.2519 79.0738C60.5075 79.0738 61.7117 78.5751 62.5995 77.6872C63.4874 76.7994 63.9862 76.2998 63.9862 75.0442C63.9862 73.7886 63.4874 73.3516 62.5996 72.4637C61.7117 71.5759 60.5075 71.0771 59.2519 71.0771L53.3555 71.0815V69.4784L54.8823 69.4739C56.1376 69.4729 57.3412 68.9738 58.2288 68.0862C59.1164 67.1986 60.2656 66.2038 60.2666 64.9485L60.3118 33.5699C60.3119 33.2223 60.3118 32.5699 60.401 32.2506C60.5341 31.9295 60.547 31.5699 60.725 31.3919C60.9708 31.1462 61.1038 30.9511 61.4249 30.8181C61.746 30.6852 62.6524 30.5698 63 30.5699C63.3475 30.5699 63.9907 30.5669 64.3118 30.7C64.6329 30.833 64.9889 31.2478 65.3118 31.5699C65.5575 31.8156 65.5753 31.9295 65.7083 32.2506C65.8412 32.5717 65.9096 32.9158 65.9096 33.2634L65.9169 59.1411L64.8659 59.1411C64.5926 59.1418 64.3306 59.2497 64.136 59.4415C63.9414 59.6334 63.8298 59.8938 63.8251 60.167L63.7587 64.9175C63.7491 65.609 63.8771 66.2955 64.1351 66.9371C64.393 67.5787 64.776 68.1626 65.2616 68.6549C65.7472 69.1473 66.3258 69.5382 66.9638 69.805C67.6017 70.0718 68.2864 70.2091 68.9779 70.2091L72.1237 70.2091C72.4005 70.209 72.666 70.0991 72.8617 69.9033C73.0574 69.7076 73.1674 69.4422 73.1674 69.1654L73.1674 64.7367C73.1674 64.5979 73.1396 64.4605 73.0857 64.3326C73.0319 64.2046 72.9531 64.0887 72.8539 63.9916C72.7547 63.8944 72.6372 63.8181 72.5081 63.7669C72.3791 63.7158 72.2411 63.6909 72.1023 63.6938L70.1412 63.7358L70.091 60.1693C70.0863 59.8961 69.9747 59.6356 69.7801 59.4438C69.5855 59.2519 69.3235 59.1441 69.0502 59.1433L68.3794 59.1411L68.7232 33.5699C68.7232 32.3143 68.1997 30.4577 67.3118 29.5699C66.424 28.682 65.5 28.0699 63 28.0699C60.7903 28.0699 59.6997 28.682 58.8118 29.5699C57.924 30.4577 57.5395 32.0115 57.5395 33.2671L57.5395 64.7441C57.5383 65.4457 57.2591 66.1183 56.7629 66.6144C56.2668 67.1105 55.5943 67.3898 54.8926 67.391L53.3555 67.391V35.2151C53.3555 34.9383 53.2455 34.6729 53.0498 34.4771C52.854 34.2814 52.5886 34.1715 52.3118 34.1714L51.4973 34.1714L51.4973 25.1871L60.7872 25.1871C61.064 25.187 61.3294 25.0771 61.5252 24.8814C61.7209 24.6856 61.8309 24.4202 61.8309 24.1434V18.9766C61.8308 18.6998 61.7209 18.4344 61.5252 18.2386C61.3294 18.0429 61.064 17.933 60.7872 17.9329L35.6913 17.9329C35.4145 17.9329 35.1491 18.0429 34.9534 18.2386C34.7577 18.4344 34.6477 18.6998 34.6476 18.9766L34.6476 24.1434C34.6477 24.4202 34.7577 24.6856 34.9534 24.8814C35.1491 25.0771 35.4145 25.187 35.6913 25.1871L44.9812 25.1871L44.9812 34.1714L44.1543 34.1714C43.8775 34.1715 43.6121 34.2814 43.4164 34.4771C43.2206 34.6729 43.1107 34.9383 43.1106 35.2151L43.1106 71.0771L37.2266 71.0771C35.971 71.0771 34.7668 71.5759 33.879 72.4637C32.9911 73.3516 32.4923 73.7886 32.4923 75.0442C32.4923 76.2998 32.9911 76.7994 33.879 77.6872C34.7668 78.575 35.971 79.0738 37.2266 79.0738L59.2519 79.0738ZM68.0612 64.8135C68.0631 64.951 68.0922 65.0869 68.1468 65.2131C68.2014 65.3394 68.2805 65.4536 68.3794 65.5493C68.4783 65.6449 68.5952 65.72 68.7232 65.7703C68.8512 65.8206 68.988 65.8451 69.1255 65.8424L71.0749 65.8033L71.0771 68.1246L68.975 68.1246C68.5599 68.1247 68.149 68.0423 67.7661 67.8822C67.3832 67.722 67.0359 67.4874 66.7445 67.1918C66.4531 66.8963 66.2234 66.5458 66.0686 66.1607C65.9139 65.7756 65.8372 65.3635 65.8431 64.9485L65.8926 61.2248H68.0154L68.0612 64.8135ZM36.735 23.0997L36.735 20.0203L59.7435 20.0203L59.7435 23.0997L50.4536 23.0997L46.0249 23.0997L36.735 23.0997ZM47.0686 25.1871L49.4099 25.1871L49.4099 34.1714L47.0686 34.1714V25.1871ZM44.8543 36.2588H46.0249L50.4536 36.2588L51.6243 36.2588L51.6243 67.3865L44.8543 67.3865L44.8543 36.2588ZM44.8543 69.4739L51.6243 69.4739L51.6243 74.0296L44.8543 74.0296L44.8543 69.4739ZM34.5797 75.0442C34.5929 74.3464 34.876 74.4479 35.3696 73.9543C35.8631 73.4608 36.5287 73.1777 37.2266 73.1645L43.1106 73.1645L43.1106 74.3061C43.1107 74.5829 43.2206 74.8483 43.4163 75.0441C43.6121 75.2398 43.8775 75.3498 44.1543 75.3498L52.3118 75.3542C52.5886 75.3542 52.854 75.2442 53.0498 75.0485C53.2455 74.8528 53.3555 74.5873 53.3555 74.3105V73.1689L59.2519 73.1645C59.5999 73.163 59.9448 73.2305 60.2666 73.363C60.5884 73.4955 60.8808 73.6904 61.1268 73.9365C61.3729 74.1825 61.5678 73.7078 61.7003 74.0296C61.8328 74.3514 61.9003 74.6962 61.8988 75.0442C61.8856 75.7421 61.6025 75.7031 61.1089 76.1966C60.6154 76.6902 59.9498 76.9733 59.2519 76.9864L37.2266 76.9864C36.8786 76.9879 36.5337 76.9205 36.2119 76.788C35.8901 76.6555 35.5978 76.4606 35.3517 76.2145C35.1056 75.9684 34.9107 75.676 34.7782 75.3542C34.6457 75.0324 34.5783 75.3922 34.5797 75.0442Z" fill="white"/>
<path d="M59.2519 79.0738C60.5075 79.0738 61.7117 78.5751 62.5995 77.6872C63.4874 76.7994 63.9862 76.2998 63.9862 75.0442C63.9862 73.7886 63.4874 73.3516 62.5996 72.4637C61.7117 71.5759 60.5075 71.0771 59.2519 71.0771L53.3555 71.0815V69.4784L54.8823 69.4739C56.1376 69.4729 57.3412 68.9738 58.2288 68.0862C59.1164 67.1986 60.2656 66.2038 60.2666 64.9485L60.3118 33.5699C60.3119 33.2223 60.3118 32.5699 60.401 32.2506C60.5341 31.9295 60.547 31.5699 60.725 31.3919C60.9708 31.1462 61.1038 30.9511 61.4249 30.8181C61.746 30.6852 62.6524 30.5698 63 30.5699C63.3475 30.5699 63.9907 30.5669 64.3118 30.7C64.6329 30.833 64.9889 31.2478 65.3118 31.5699C65.5575 31.8156 65.5753 31.9295 65.7083 32.2506C65.8412 32.5717 65.9096 32.9158 65.9096 33.2634L65.9169 59.1411L64.8659 59.1411C64.5926 59.1418 64.3306 59.2497 64.136 59.4415C63.9414 59.6334 63.8298 59.8938 63.8251 60.167L63.7587 64.9175C63.7491 65.609 63.8771 66.2955 64.1351 66.9371C64.393 67.5787 64.776 68.1626 65.2616 68.6549C65.7472 69.1473 66.3258 69.5382 66.9638 69.805C67.6017 70.0718 68.2864 70.2091 68.9779 70.2091L72.1237 70.2091C72.4005 70.209 72.666 70.0991 72.8617 69.9033C73.0574 69.7076 73.1674 69.4422 73.1674 69.1654L73.1674 64.7367C73.1674 64.5979 73.1396 64.4605 73.0857 64.3326C73.0319 64.2046 72.9531 64.0887 72.8539 63.9916C72.7547 63.8944 72.6372 63.8181 72.5081 63.7669C72.3791 63.7158 72.2411 63.6909 72.1023 63.6938L70.1412 63.7358L70.091 60.1693C70.0863 59.8961 69.9747 59.6356 69.7801 59.4438C69.5855 59.2519 69.3235 59.1441 69.0502 59.1433L68.3794 59.1411L68.7232 33.5699C68.7232 32.3143 68.1997 30.4577 67.3118 29.5699C66.424 28.682 65.5 28.0699 63 28.0699C60.7903 28.0699 59.6997 28.682 58.8118 29.5699C57.924 30.4577 57.5395 32.0115 57.5395 33.2671L57.5395 64.7441C57.5383 65.4457 57.2591 66.1183 56.7629 66.6144C56.2668 67.1105 55.5943 67.3898 54.8926 67.391L53.3555 67.391V35.2151C53.3555 34.9383 53.2455 34.6729 53.0498 34.4771C52.854 34.2814 52.5886 34.1715 52.3118 34.1714L51.4973 34.1714L51.4973 25.1871L60.7872 25.1871C61.064 25.187 61.3294 25.0771 61.5252 24.8814C61.7209 24.6856 61.8309 24.4202 61.8309 24.1434V18.9766C61.8308 18.6998 61.7209 18.4344 61.5252 18.2386C61.3294 18.0429 61.064 17.933 60.7872 17.9329L35.6913 17.9329C35.4145 17.9329 35.1491 18.0429 34.9534 18.2386C34.7577 18.4344 34.6477 18.6998 34.6476 18.9766L34.6476 24.1434C34.6477 24.4202 34.7577 24.6856 34.9534 24.8814C35.1491 25.0771 35.4145 25.187 35.6913 25.1871L44.9812 25.1871L44.9812 34.1714L44.1543 34.1714C43.8775 34.1715 43.6121 34.2814 43.4164 34.4771C43.2206 34.6729 43.1107 34.9383 43.1106 35.2151L43.1106 71.0771L37.2266 71.0771C35.971 71.0771 34.7668 71.5759 33.879 72.4637C32.9911 73.3516 32.4923 73.7886 32.4923 75.0442C32.4923 76.2998 32.9911 76.7994 33.879 77.6872C34.7668 78.575 35.971 79.0738 37.2266 79.0738L59.2519 79.0738ZM68.0612 64.8135C68.0631 64.951 68.0922 65.0869 68.1468 65.2131C68.2014 65.3394 68.2805 65.4536 68.3794 65.5493C68.4783 65.6449 68.5952 65.72 68.7232 65.7703C68.8512 65.8206 68.988 65.8451 69.1255 65.8424L71.0749 65.8033L71.0771 68.1246L68.975 68.1246C68.5599 68.1247 68.149 68.0423 67.7661 67.8822C67.3832 67.722 67.0359 67.4874 66.7445 67.1918C66.4531 66.8963 66.2234 66.5458 66.0686 66.1607C65.9139 65.7756 65.8372 65.3635 65.8431 64.9485L65.8926 61.2248H68.0154L68.0612 64.8135ZM36.735 23.0997L36.735 20.0203L59.7435 20.0203L59.7435 23.0997L50.4536 23.0997L46.0249 23.0997L36.735 23.0997ZM47.0686 25.1871L49.4099 25.1871L49.4099 34.1714L47.0686 34.1714V25.1871ZM44.8543 36.2588H46.0249L50.4536 36.2588L51.6243 36.2588L51.6243 67.3865L44.8543 67.3865L44.8543 36.2588ZM44.8543 69.4739L51.6243 69.4739L51.6243 74.0296L44.8543 74.0296L44.8543 69.4739ZM34.5797 75.0442C34.5929 74.3464 34.876 74.4479 35.3696 73.9543C35.8631 73.4608 36.5287 73.1777 37.2266 73.1645L43.1106 73.1645L43.1106 74.3061C43.1107 74.5829 43.2206 74.8483 43.4163 75.0441C43.6121 75.2398 43.8775 75.3498 44.1543 75.3498L52.3118 75.3542C52.5886 75.3542 52.854 75.2442 53.0498 75.0485C53.2455 74.8528 53.3555 74.5873 53.3555 74.3105V73.1689L59.2519 73.1645C59.5999 73.163 59.9448 73.2305 60.2666 73.363C60.5884 73.4955 60.8808 73.6904 61.1268 73.9365C61.3729 74.1825 61.5678 73.7078 61.7003 74.0296C61.8328 74.3514 61.9003 74.6962 61.8988 75.0442C61.8856 75.7421 61.6025 75.7031 61.1089 76.1966C60.6154 76.6902 59.9498 76.9733 59.2519 76.9864L37.2266 76.9864C36.8786 76.9879 36.5337 76.9205 36.2119 76.788C35.8901 76.6555 35.5978 76.4606 35.3517 76.2145C35.1056 75.9684 34.9107 75.676 34.7782 75.3542C34.6457 75.0324 34.5783 75.3922 34.5797 75.0442Z"
fill="white"/>
<rect x="44.3118" y="35.5698" width="8" height="39" fill="white"/>
<rect x="35.3118" y="19.5699" width="25" height="4" fill="white"/>
<rect x="46.3118" y="21.5698" width="4" height="14" fill="white"/>
@ -11,10 +13,12 @@
<rect x="68.3118" y="64.5699" width="3" height="4" fill="white"/>
<rect x="56" y="42" width="5" height="10" fill="#171615"/>
</g>
<rect x="72.4167" y="53.8615" width="29.0549" height="7.85787" transform="rotate(43.5782 72.4167 53.8615)" fill="#F00D0D"/>
<rect x="72.4167" y="53.8615" width="29.0549" height="7.85787" transform="rotate(43.5782 72.4167 53.8615)"
fill="#F00D0D"/>
<path d="M68.2141 73.9097L88.6128 54L94.0003 59.5199L73.6016 79.4295L68.2141 73.9097Z" fill="#F00D0D"/>
<defs>
<filter id="filter0_d" x="-3" y="2" width="102.479" height="102.479" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<filter id="filter0_d" x="-3" y="2" width="102.479" height="102.479" filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

View file

@ -3,10 +3,9 @@
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns="http://www.w3.org/2000/svg"
width="123"
height="123"
viewBox="0 0 123 123"

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -1,8 +1,10 @@
<svg width="99" height="123" viewBox="0 0 99 123" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M55.0445 113.094C53.2614 116.981 47.7386 116.981 45.9555 113.094L15.2124 46.085C13.6928 42.7729 16.1129 39 19.7569 39L81.2431 39C84.8871 39 87.3072 42.7729 85.7876 46.085L55.0445 113.094Z" fill="#E2783D"/>
<path d="M55.0445 113.094C53.2614 116.981 47.7386 116.981 45.9555 113.094L15.2124 46.085C13.6928 42.7729 16.1129 39 19.7569 39L81.2431 39C84.8871 39 87.3072 42.7729 85.7876 46.085L55.0445 113.094Z"
fill="#E2783D"/>
<circle cx="50" cy="49" r="49" fill="#E2783D"/>
<g clip-path="url(#clip0)" filter="url(#filter0_d)">
<path d="M59.2519 79.0738C60.5075 79.0738 61.7117 78.5751 62.5995 77.6872C63.4874 76.7994 63.9862 76.2998 63.9862 75.0442C63.9862 73.7886 63.4874 73.3516 62.5996 72.4637C61.7117 71.5759 60.5075 71.0771 59.2519 71.0771L53.3555 71.0815V69.4784L54.8823 69.4739C56.1376 69.4729 57.3412 68.9738 58.2288 68.0862C59.1164 67.1986 60.2656 66.2038 60.2666 64.9485L60.3118 33.5699C60.3119 33.2223 60.3118 32.5699 60.401 32.2506C60.5341 31.9295 60.547 31.5699 60.725 31.3919C60.9708 31.1462 61.1038 30.9511 61.4249 30.8181C61.746 30.6852 62.6524 30.5698 63 30.5699C63.3475 30.5699 63.9907 30.5669 64.3118 30.7C64.6329 30.833 64.9889 31.2478 65.3118 31.5699C65.5575 31.8156 65.5753 31.9295 65.7083 32.2506C65.8412 32.5717 65.9096 32.9158 65.9096 33.2634L65.9169 59.1411L64.8659 59.1411C64.5926 59.1418 64.3306 59.2497 64.136 59.4415C63.9414 59.6334 63.8298 59.8938 63.8251 60.167L63.7587 64.9175C63.7491 65.609 63.8771 66.2955 64.1351 66.9371C64.393 67.5787 64.776 68.1626 65.2616 68.6549C65.7472 69.1473 66.3258 69.5382 66.9638 69.805C67.6017 70.0718 68.2864 70.2091 68.9779 70.2091L72.1237 70.2091C72.4005 70.209 72.666 70.0991 72.8617 69.9033C73.0574 69.7076 73.1674 69.4422 73.1674 69.1654L73.1674 64.7367C73.1674 64.5979 73.1396 64.4605 73.0857 64.3326C73.0319 64.2046 72.9531 64.0887 72.8539 63.9916C72.7547 63.8944 72.6372 63.8181 72.5081 63.7669C72.3791 63.7158 72.2411 63.6909 72.1023 63.6938L70.1412 63.7358L70.091 60.1693C70.0863 59.8961 69.9747 59.6356 69.7801 59.4438C69.5855 59.2519 69.3235 59.1441 69.0502 59.1433L68.3794 59.1411L68.7232 33.5699C68.7232 32.3143 68.1997 30.4577 67.3118 29.5699C66.424 28.682 65.5 28.0699 63 28.0699C60.7903 28.0699 59.6997 28.682 58.8118 29.5699C57.924 30.4577 57.5395 32.0115 57.5395 33.2671L57.5395 64.7441C57.5383 65.4457 57.2591 66.1183 56.7629 66.6144C56.2668 67.1105 55.5943 67.3898 54.8926 67.391L53.3555 67.391V35.2151C53.3555 34.9383 53.2455 34.6729 53.0498 34.4771C52.854 34.2814 52.5886 34.1715 52.3118 34.1714L51.4973 34.1714L51.4973 25.1871L60.7872 25.1871C61.064 25.187 61.3294 25.0771 61.5252 24.8814C61.7209 24.6856 61.8309 24.4202 61.8309 24.1434V18.9766C61.8308 18.6998 61.7209 18.4344 61.5252 18.2386C61.3294 18.0429 61.064 17.933 60.7872 17.9329L35.6913 17.9329C35.4145 17.9329 35.1491 18.0429 34.9534 18.2386C34.7577 18.4344 34.6477 18.6998 34.6476 18.9766L34.6476 24.1434C34.6477 24.4202 34.7577 24.6856 34.9534 24.8814C35.1491 25.0771 35.4145 25.187 35.6913 25.1871L44.9812 25.1871L44.9812 34.1714L44.1543 34.1714C43.8775 34.1715 43.6121 34.2814 43.4164 34.4771C43.2206 34.6729 43.1107 34.9383 43.1106 35.2151L43.1106 71.0771L37.2266 71.0771C35.971 71.0771 34.7668 71.5759 33.879 72.4637C32.9911 73.3516 32.4923 73.7886 32.4923 75.0442C32.4923 76.2998 32.9911 76.7994 33.879 77.6872C34.7668 78.575 35.971 79.0738 37.2266 79.0738L59.2519 79.0738ZM68.0612 64.8135C68.0631 64.951 68.0922 65.0869 68.1468 65.2131C68.2014 65.3394 68.2805 65.4536 68.3794 65.5493C68.4783 65.6449 68.5952 65.72 68.7232 65.7703C68.8512 65.8206 68.988 65.8451 69.1255 65.8424L71.0749 65.8033L71.0771 68.1246L68.975 68.1246C68.5599 68.1247 68.149 68.0423 67.7661 67.8822C67.3832 67.722 67.0359 67.4874 66.7445 67.1918C66.4531 66.8963 66.2234 66.5458 66.0686 66.1607C65.9139 65.7756 65.8372 65.3635 65.8431 64.9485L65.8926 61.2248H68.0154L68.0612 64.8135ZM36.735 23.0997L36.735 20.0203L59.7435 20.0203L59.7435 23.0997L50.4536 23.0997L46.0249 23.0997L36.735 23.0997ZM47.0686 25.1871L49.4099 25.1871L49.4099 34.1714L47.0686 34.1714V25.1871ZM44.8543 36.2588H46.0249L50.4536 36.2588L51.6243 36.2588L51.6243 67.3865L44.8543 67.3865L44.8543 36.2588ZM44.8543 69.4739L51.6243 69.4739L51.6243 74.0296L44.8543 74.0296L44.8543 69.4739ZM34.5797 75.0442C34.5929 74.3464 34.876 74.4479 35.3696 73.9543C35.8631 73.4608 36.5287 73.1777 37.2266 73.1645L43.1106 73.1645L43.1106 74.3061C43.1107 74.5829 43.2206 74.8483 43.4163 75.0441C43.6121 75.2398 43.8775 75.3498 44.1543 75.3498L52.3118 75.3542C52.5886 75.3542 52.854 75.2442 53.0498 75.0485C53.2455 74.8528 53.3555 74.5873 53.3555 74.3105V73.1689L59.2519 73.1645C59.5999 73.163 59.9448 73.2305 60.2666 73.363C60.5884 73.4955 60.8808 73.6904 61.1268 73.9365C61.3729 74.1825 61.5678 73.7078 61.7003 74.0296C61.8328 74.3514 61.9003 74.6962 61.8988 75.0442C61.8856 75.7421 61.6025 75.7031 61.1089 76.1966C60.6154 76.6902 59.9498 76.9733 59.2519 76.9864L37.2266 76.9864C36.8786 76.9879 36.5337 76.9205 36.2119 76.788C35.8901 76.6555 35.5978 76.4606 35.3517 76.2145C35.1056 75.9684 34.9107 75.676 34.7782 75.3542C34.6457 75.0324 34.5783 75.3922 34.5797 75.0442Z" fill="white"/>
<path d="M59.2519 79.0738C60.5075 79.0738 61.7117 78.5751 62.5995 77.6872C63.4874 76.7994 63.9862 76.2998 63.9862 75.0442C63.9862 73.7886 63.4874 73.3516 62.5996 72.4637C61.7117 71.5759 60.5075 71.0771 59.2519 71.0771L53.3555 71.0815V69.4784L54.8823 69.4739C56.1376 69.4729 57.3412 68.9738 58.2288 68.0862C59.1164 67.1986 60.2656 66.2038 60.2666 64.9485L60.3118 33.5699C60.3119 33.2223 60.3118 32.5699 60.401 32.2506C60.5341 31.9295 60.547 31.5699 60.725 31.3919C60.9708 31.1462 61.1038 30.9511 61.4249 30.8181C61.746 30.6852 62.6524 30.5698 63 30.5699C63.3475 30.5699 63.9907 30.5669 64.3118 30.7C64.6329 30.833 64.9889 31.2478 65.3118 31.5699C65.5575 31.8156 65.5753 31.9295 65.7083 32.2506C65.8412 32.5717 65.9096 32.9158 65.9096 33.2634L65.9169 59.1411L64.8659 59.1411C64.5926 59.1418 64.3306 59.2497 64.136 59.4415C63.9414 59.6334 63.8298 59.8938 63.8251 60.167L63.7587 64.9175C63.7491 65.609 63.8771 66.2955 64.1351 66.9371C64.393 67.5787 64.776 68.1626 65.2616 68.6549C65.7472 69.1473 66.3258 69.5382 66.9638 69.805C67.6017 70.0718 68.2864 70.2091 68.9779 70.2091L72.1237 70.2091C72.4005 70.209 72.666 70.0991 72.8617 69.9033C73.0574 69.7076 73.1674 69.4422 73.1674 69.1654L73.1674 64.7367C73.1674 64.5979 73.1396 64.4605 73.0857 64.3326C73.0319 64.2046 72.9531 64.0887 72.8539 63.9916C72.7547 63.8944 72.6372 63.8181 72.5081 63.7669C72.3791 63.7158 72.2411 63.6909 72.1023 63.6938L70.1412 63.7358L70.091 60.1693C70.0863 59.8961 69.9747 59.6356 69.7801 59.4438C69.5855 59.2519 69.3235 59.1441 69.0502 59.1433L68.3794 59.1411L68.7232 33.5699C68.7232 32.3143 68.1997 30.4577 67.3118 29.5699C66.424 28.682 65.5 28.0699 63 28.0699C60.7903 28.0699 59.6997 28.682 58.8118 29.5699C57.924 30.4577 57.5395 32.0115 57.5395 33.2671L57.5395 64.7441C57.5383 65.4457 57.2591 66.1183 56.7629 66.6144C56.2668 67.1105 55.5943 67.3898 54.8926 67.391L53.3555 67.391V35.2151C53.3555 34.9383 53.2455 34.6729 53.0498 34.4771C52.854 34.2814 52.5886 34.1715 52.3118 34.1714L51.4973 34.1714L51.4973 25.1871L60.7872 25.1871C61.064 25.187 61.3294 25.0771 61.5252 24.8814C61.7209 24.6856 61.8309 24.4202 61.8309 24.1434V18.9766C61.8308 18.6998 61.7209 18.4344 61.5252 18.2386C61.3294 18.0429 61.064 17.933 60.7872 17.9329L35.6913 17.9329C35.4145 17.9329 35.1491 18.0429 34.9534 18.2386C34.7577 18.4344 34.6477 18.6998 34.6476 18.9766L34.6476 24.1434C34.6477 24.4202 34.7577 24.6856 34.9534 24.8814C35.1491 25.0771 35.4145 25.187 35.6913 25.1871L44.9812 25.1871L44.9812 34.1714L44.1543 34.1714C43.8775 34.1715 43.6121 34.2814 43.4164 34.4771C43.2206 34.6729 43.1107 34.9383 43.1106 35.2151L43.1106 71.0771L37.2266 71.0771C35.971 71.0771 34.7668 71.5759 33.879 72.4637C32.9911 73.3516 32.4923 73.7886 32.4923 75.0442C32.4923 76.2998 32.9911 76.7994 33.879 77.6872C34.7668 78.575 35.971 79.0738 37.2266 79.0738L59.2519 79.0738ZM68.0612 64.8135C68.0631 64.951 68.0922 65.0869 68.1468 65.2131C68.2014 65.3394 68.2805 65.4536 68.3794 65.5493C68.4783 65.6449 68.5952 65.72 68.7232 65.7703C68.8512 65.8206 68.988 65.8451 69.1255 65.8424L71.0749 65.8033L71.0771 68.1246L68.975 68.1246C68.5599 68.1247 68.149 68.0423 67.7661 67.8822C67.3832 67.722 67.0359 67.4874 66.7445 67.1918C66.4531 66.8963 66.2234 66.5458 66.0686 66.1607C65.9139 65.7756 65.8372 65.3635 65.8431 64.9485L65.8926 61.2248H68.0154L68.0612 64.8135ZM36.735 23.0997L36.735 20.0203L59.7435 20.0203L59.7435 23.0997L50.4536 23.0997L46.0249 23.0997L36.735 23.0997ZM47.0686 25.1871L49.4099 25.1871L49.4099 34.1714L47.0686 34.1714V25.1871ZM44.8543 36.2588H46.0249L50.4536 36.2588L51.6243 36.2588L51.6243 67.3865L44.8543 67.3865L44.8543 36.2588ZM44.8543 69.4739L51.6243 69.4739L51.6243 74.0296L44.8543 74.0296L44.8543 69.4739ZM34.5797 75.0442C34.5929 74.3464 34.876 74.4479 35.3696 73.9543C35.8631 73.4608 36.5287 73.1777 37.2266 73.1645L43.1106 73.1645L43.1106 74.3061C43.1107 74.5829 43.2206 74.8483 43.4163 75.0441C43.6121 75.2398 43.8775 75.3498 44.1543 75.3498L52.3118 75.3542C52.5886 75.3542 52.854 75.2442 53.0498 75.0485C53.2455 74.8528 53.3555 74.5873 53.3555 74.3105V73.1689L59.2519 73.1645C59.5999 73.163 59.9448 73.2305 60.2666 73.363C60.5884 73.4955 60.8808 73.6904 61.1268 73.9365C61.3729 74.1825 61.5678 73.7078 61.7003 74.0296C61.8328 74.3514 61.9003 74.6962 61.8988 75.0442C61.8856 75.7421 61.6025 75.7031 61.1089 76.1966C60.6154 76.6902 59.9498 76.9733 59.2519 76.9864L37.2266 76.9864C36.8786 76.9879 36.5337 76.9205 36.2119 76.788C35.8901 76.6555 35.5978 76.4606 35.3517 76.2145C35.1056 75.9684 34.9107 75.676 34.7782 75.3542C34.6457 75.0324 34.5783 75.3922 34.5797 75.0442Z"
fill="white"/>
<rect x="44.3118" y="35.5698" width="8" height="39" fill="white"/>
<rect x="35.3118" y="19.5699" width="25" height="4" fill="white"/>
<rect x="46.3119" y="21.5698" width="4" height="14" fill="white"/>
@ -11,7 +13,8 @@
<rect x="68.3118" y="64.5699" width="3" height="4" fill="white"/>
</g>
<defs>
<filter id="filter0_d" x="-3" y="2" width="102.479" height="102.479" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<filter id="filter0_d" x="-3" y="2" width="102.479" height="102.479" filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>

Before

Width:  |  Height:  |  Size: 6 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View file

@ -1,27 +1,36 @@
<svg width="98" height="121" viewBox="0 0 98 121" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M53.0072 111.614C51.1916 115.395 45.8084 115.395 43.9928 111.614L13.4024 47.9145C11.8084 44.5952 14.2275 40.75 17.9097 40.75L79.0903 40.75C82.7725 40.75 85.1916 44.5952 83.5976 47.9145L53.0072 111.614Z" fill="#32ADF2"/>
<path d="M53.0072 111.614C51.1916 115.395 45.8084 115.395 43.9928 111.614L13.4024 47.9145C11.8084 44.5952 14.2275 40.75 17.9097 40.75L79.0903 40.75C82.7725 40.75 85.1916 44.5952 83.5976 47.9145L53.0072 111.614Z"
fill="#32ADF2"/>
<circle cx="49" cy="49" r="49" fill="#32ADF2"/>
<g filter="url(#filter0_d)">
<path d="M62.84 50.816C63.9413 50.7413 64.912 50.704 65.752 50.704C68.1973 50.704 69.42 52.188 69.42 55.156C69.42 58.4787 68.0853 60.14 65.416 60.14C64.632 60.14 63.7733 60.07 62.84 59.93V50.816ZM65.416 59.16C66.0693 59.16 66.564 58.9967 66.9 58.67C67.236 58.3433 67.4553 57.914 67.558 57.382C67.6607 56.8407 67.712 56.164 67.712 55.352C67.712 54.2693 67.5673 53.3873 67.278 52.706C66.9887 52.0247 66.4473 51.684 65.654 51.684C65.3087 51.684 64.9167 51.7073 64.478 51.754V59.076C64.814 59.132 65.1267 59.16 65.416 59.16ZM72.3803 50.76V60H70.7423V50.76H72.3803ZM77.5646 55.73V60H75.9266V55.898L73.2386 50.76H75.0306L76.8506 54.554L78.5726 50.76H80.2526L77.5646 55.73Z" fill="#FFFBFB"/>
<path d="M62.84 50.816C63.9413 50.7413 64.912 50.704 65.752 50.704C68.1973 50.704 69.42 52.188 69.42 55.156C69.42 58.4787 68.0853 60.14 65.416 60.14C64.632 60.14 63.7733 60.07 62.84 59.93V50.816ZM65.416 59.16C66.0693 59.16 66.564 58.9967 66.9 58.67C67.236 58.3433 67.4553 57.914 67.558 57.382C67.6607 56.8407 67.712 56.164 67.712 55.352C67.712 54.2693 67.5673 53.3873 67.278 52.706C66.9887 52.0247 66.4473 51.684 65.654 51.684C65.3087 51.684 64.9167 51.7073 64.478 51.754V59.076C64.814 59.132 65.1267 59.16 65.416 59.16ZM72.3803 50.76V60H70.7423V50.76H72.3803ZM77.5646 55.73V60H75.9266V55.898L73.2386 50.76H75.0306L76.8506 54.554L78.5726 50.76H80.2526L77.5646 55.73Z"
fill="#FFFBFB"/>
</g>
<g filter="url(#filter1_d)">
<path d="M39.0246 31.9734L35.4086 34.9306L35.3903 34.9459C34.5486 35.6731 34.0429 36.7274 34.0026 37.8384C33.9731 38.6517 34.1956 39.4521 34.6251 40.1313L38.1101 36.6498C38.4539 36.3063 39.0114 36.3063 39.3553 36.6498C39.6992 36.9933 39.6992 37.5503 39.3553 37.8939L35.8705 41.3753C36.5103 41.7791 37.2574 42 38.0217 42C38.0696 42 38.1176 41.9991 38.1656 41.9974C39.2777 41.9571 40.333 41.4519 41.0609 40.6109L44.0362 36.9802L39.0246 31.9734Z" fill="#FFF7F7"/>
<path d="M39.0246 31.9734L35.4086 34.9306L35.3903 34.9459C34.5486 35.6731 34.0429 36.7274 34.0026 37.8384C33.9731 38.6517 34.1956 39.4521 34.6251 40.1313L38.1101 36.6498C38.4539 36.3063 39.0114 36.3063 39.3553 36.6498C39.6992 36.9933 39.6992 37.5503 39.3553 37.8939L35.8705 41.3753C36.5103 41.7791 37.2574 42 38.0217 42C38.0696 42 38.1176 41.9991 38.1656 41.9974C39.2777 41.9571 40.333 41.4519 41.0609 40.6109L44.0362 36.9802L39.0246 31.9734Z"
fill="#FFF7F7"/>
<path d="M42.008 29.5336L40.394 30.8535L45.1573 35.6121L46.4786 33.9998L42.008 29.5336Z" fill="#FFF7F7"/>
<path d="M44.8629 29.9L46.0573 28.7068L47.3023 29.9507L46.1079 31.1439L44.8629 29.9Z" fill="#FFF7F7"/>
<path d="M52.5127 22.2598L57.2054 17.5716L58.4505 18.8155L53.7578 23.5036L52.5127 22.2598Z" fill="#FFF7F7"/>
<path d="M57.5981 15.4757L61.0772 12L63.9954 14.9153L60.5163 18.3911L57.5981 15.4757Z" fill="#FFF7F7"/>
<path d="M60.4798 30.9612C59.5828 30.0651 58.4814 29.5914 57.295 29.5914C56.9717 29.5914 56.6419 29.627 56.3147 29.6972C55.9636 29.7724 55.582 29.6566 55.3244 29.3991L44.7335 18.8186C44.4694 18.5548 44.3563 18.1695 44.4387 17.813C44.8015 16.2466 44.358 14.7415 43.1901 13.5748C42.1736 12.5592 40.822 12 39.3843 12C38.6498 12 37.9365 12.1457 37.2643 12.4332L36.8657 12.6037L39.9617 15.6966L37.7009 17.9551L34.6051 14.8621L34.4344 15.2604C34.016 16.2367 33.8969 17.3068 34.0898 18.3552C34.2874 19.4288 34.8017 20.4057 35.577 21.1804C36.474 22.0765 37.5753 22.5502 38.7617 22.5502C39.0851 22.5502 39.415 22.5146 39.7421 22.4444C39.8146 22.4288 39.8888 22.421 39.963 22.421C40.2476 22.421 40.5281 22.5382 40.7325 22.7425L51.3233 33.323C51.5877 33.587 51.7007 33.9726 51.618 34.3292C51.2554 35.8951 51.6988 37.4001 52.8667 38.5668C53.8832 39.5824 55.2348 40.1417 56.6725 40.1416C57.4071 40.1416 58.1204 39.9958 58.7924 39.7084L59.1912 39.5379L56.0952 36.445L58.3559 34.1866L61.4517 37.2794L61.6224 36.8811C62.0408 35.9049 62.1599 34.8348 61.967 33.7865C61.7694 32.7128 61.2551 31.7358 60.4798 30.9612Z" fill="#FFF7F7"/>
<path d="M60.4798 30.9612C59.5828 30.0651 58.4814 29.5914 57.295 29.5914C56.9717 29.5914 56.6419 29.627 56.3147 29.6972C55.9636 29.7724 55.582 29.6566 55.3244 29.3991L44.7335 18.8186C44.4694 18.5548 44.3563 18.1695 44.4387 17.813C44.8015 16.2466 44.358 14.7415 43.1901 13.5748C42.1736 12.5592 40.822 12 39.3843 12C38.6498 12 37.9365 12.1457 37.2643 12.4332L36.8657 12.6037L39.9617 15.6966L37.7009 17.9551L34.6051 14.8621L34.4344 15.2604C34.016 16.2367 33.8969 17.3068 34.0898 18.3552C34.2874 19.4288 34.8017 20.4057 35.577 21.1804C36.474 22.0765 37.5753 22.5502 38.7617 22.5502C39.0851 22.5502 39.415 22.5146 39.7421 22.4444C39.8146 22.4288 39.8888 22.421 39.963 22.421C40.2476 22.421 40.5281 22.5382 40.7325 22.7425L51.3233 33.323C51.5877 33.587 51.7007 33.9726 51.618 34.3292C51.2554 35.8951 51.6988 37.4001 52.8667 38.5668C53.8832 39.5824 55.2348 40.1417 56.6725 40.1416C57.4071 40.1416 58.1204 39.9958 58.7924 39.7084L59.1912 39.5379L56.0952 36.445L58.3559 34.1866L61.4517 37.2794L61.6224 36.8811C62.0408 35.9049 62.1599 34.8348 61.967 33.7865C61.7694 32.7128 61.2551 31.7358 60.4798 30.9612Z"
fill="#FFF7F7"/>
</g>
<g filter="url(#filter2_d)">
<path d="M37.5636 72.4372H24.7595L31.7436 56.4962H38.7276H43.7716H49.2037M49.2037 56.4962L47.2636 52H49.9797H52.6957M49.2037 56.4962L49.9797 58.5399L51.5317 61.8098L55.7997 72.4372M49.2037 56.4962L45.5176 62.6273L43.306 66.306M41.8316 68.7585L43.306 66.306M34.4596 60.9924L38.3396 69.9847L30.5796 52L32.9076 56.9049M40.6676 70.8022L43.306 66.306" stroke="white" stroke-width="2"/>
<path d="M41.6601 71.7418C41.6601 73.0707 40.6438 74.103 39.4441 74.103C38.2444 74.103 37.2281 73.0707 37.2281 71.7418C37.2281 70.4128 38.2444 69.3806 39.4441 69.3806C40.6438 69.3806 41.6601 70.4128 41.6601 71.7418Z" stroke="white"/>
<path d="M33.4001 70.9243C33.4001 76.0653 29.4565 80.1429 24.7001 80.1429C19.9436 80.1429 16 76.0653 16 70.9243C16 65.7833 19.9436 61.7057 24.7001 61.7057C29.4565 61.7057 33.4001 65.7833 33.4001 70.9243Z" stroke="white" stroke-width="2"/>
<path d="M37.5636 72.4372H24.7595L31.7436 56.4962H38.7276H43.7716H49.2037M49.2037 56.4962L47.2636 52H49.9797H52.6957M49.2037 56.4962L49.9797 58.5399L51.5317 61.8098L55.7997 72.4372M49.2037 56.4962L45.5176 62.6273L43.306 66.306M41.8316 68.7585L43.306 66.306M34.4596 60.9924L38.3396 69.9847L30.5796 52L32.9076 56.9049M40.6676 70.8022L43.306 66.306"
stroke="white" stroke-width="2"/>
<path d="M41.6601 71.7418C41.6601 73.0707 40.6438 74.103 39.4441 74.103C38.2444 74.103 37.2281 73.0707 37.2281 71.7418C37.2281 70.4128 38.2444 69.3806 39.4441 69.3806C40.6438 69.3806 41.6601 70.4128 41.6601 71.7418Z"
stroke="white"/>
<path d="M33.4001 70.9243C33.4001 76.0653 29.4565 80.1429 24.7001 80.1429C19.9436 80.1429 16 76.0653 16 70.9243C16 65.7833 19.9436 61.7057 24.7001 61.7057C29.4565 61.7057 33.4001 65.7833 33.4001 70.9243Z"
stroke="white" stroke-width="2"/>
</g>
<g filter="url(#filter3_d)">
<path d="M64 71.5C64 76.7932 59.9251 81 55 81C50.0749 81 46 76.7932 46 71.5C46 66.2068 50.0749 62 55 62C59.9251 62 64 66.2068 64 71.5Z" stroke="white" stroke-width="2"/>
<path d="M64 71.5C64 76.7932 59.9251 81 55 81C50.0749 81 46 76.7932 46 71.5C46 66.2068 50.0749 62 55 62C59.9251 62 64 66.2068 64 71.5Z"
stroke="white" stroke-width="2"/>
</g>
<defs>
<filter id="filter0_d" x="58.84" y="50.704" width="25.4126" height="17.436" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<filter id="filter0_d" x="58.84" y="50.704" width="25.4126" height="17.436" filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
@ -30,7 +39,8 @@
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter1_d" x="30" y="12" width="37.9954" height="38" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<filter id="filter1_d" x="30" y="12" width="37.9954" height="38" filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
@ -39,7 +49,8 @@
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter2_d" x="11" y="51" width="54.7667" height="38.1429" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<filter id="filter2_d" x="11" y="51" width="54.7667" height="38.1429" filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
@ -48,7 +59,8 @@
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter3_d" x="41" y="61" width="28" height="29" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<filter id="filter3_d" x="41" y="61" width="28" height="29" filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Some files were not shown because too many files have changed in this diff Show more