v1.0.9 changes from 1.1.1

This commit is contained in:
saifullah-N
2022-12-21 16:26:22 +05:30
parent 44d80a59cc
commit e93296ef00
102 changed files with 18572 additions and 5777 deletions

24
src/svelte-components/.gitignore vendored Normal file
View File

@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@@ -0,0 +1,48 @@
# Svelte + TS + Vite
This template should help get you started developing with Svelte and TypeScript in Vite.
## Recommended IDE Setup
[VS Code](https://code.visualstudio.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode).
## Need an official Svelte framework?
Check out [SvelteKit](https://github.com/sveltejs/kit#readme), which is also powered by Vite. Deploy anywhere with its serverless-first approach and adapt to various platforms, with out of the box support for TypeScript, SCSS, and Less, and easily-added support for mdsvex, GraphQL, PostCSS, Tailwind CSS, and more.
## Technical considerations
**Why use this over SvelteKit?**
- It brings its own routing solution which might not be preferable for some users.
- It is first and foremost a framework that just happens to use Vite under the hood, not a Vite app.
`vite dev` and `vite build` wouldn't work in a SvelteKit environment, for example.
This template contains as little as possible to get started with Vite + TypeScript + Svelte, while taking into account the developer experience with regards to HMR and intellisense. It demonstrates capabilities on par with the other `create-vite` templates and is a good starting point for beginners dipping their toes into a Vite + Svelte project.
Should you later need the extended capabilities and extensibility provided by SvelteKit, the template has been structured similarly to SvelteKit so that it is easy to migrate.
**Why `global.d.ts` instead of `compilerOptions.types` inside `jsconfig.json` or `tsconfig.json`?**
Setting `compilerOptions.types` shuts out all other types not explicitly listed in the configuration. Using triple-slash references keeps the default TypeScript setting of accepting type information from the entire workspace, while also adding `svelte` and `vite/client` type information.
**Why include `.vscode/extensions.json`?**
Other templates indirectly recommend extensions via the README, but this file allows VS Code to prompt the user to install the recommended extension upon opening the project.
**Why enable `allowJs` in the TS template?**
While `allowJs: false` would indeed prevent the use of `.js` files in the project, it does not prevent the use of JavaScript syntax in `.svelte` files. In addition, it would force `checkJs: false`, bringing the worst of both worlds: not being able to guarantee the entire codebase is TypeScript, and also having worse typechecking for the existing JavaScript. In addition, there are valid use cases in which a mixed codebase may be relevant.
**Why is HMR not preserving my local component state?**
HMR state preservation comes with a number of gotchas! It has been disabled by default in both `svelte-hmr` and `@sveltejs/vite-plugin-svelte` due to its often surprising behavior. You can read the details [here](https://github.com/rixo/svelte-hmr#svelte-hmr).
If you have state that's important to retain within a component, consider creating an external store which would not be replaced by HMR.
```ts
// store.ts
// An extremely simple external store
import { writable } from 'svelte/store'
export default writable(0)
```

View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Svelte + TS + Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

10382
src/svelte-components/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,31 @@
{
"name": "svelte-components",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"postbuild": "smui-theme compile dist/smui.css -i src/theme",
"preview": "vite preview",
"check": "svelte-check --tsconfig ./tsconfig.json"
},
"devDependencies": {
"@sveltejs/kit": "^1.0.0-next.392",
"@sveltejs/vite-plugin-svelte": "^1.0.1",
"@tsconfig/svelte": "^3.0.0",
"node-sass": "^7.0.1",
"polyfill-object.fromentries": "^1.0.1",
"smui-theme": "^6.0.0-beta.16",
"string.prototype.matchall": "^4.0.7",
"svelte": "^3.49.0",
"svelte-check": "^2.8.0",
"svelte-icon": "^1.2.4",
"svelte-material-ui": "^6.0.0-beta.16",
"svelte-preprocess": "^4.10.7",
"svelte-tiny-virtual-list": "^2.0.5",
"tslib": "^2.4.0",
"typescript": "^4.7.4",
"vite": "^3.0.2"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,215 @@
<script lang="ts">
import WifiConnectionDialog from "$dialogs/WifiConnectionDialog.svelte";
import ChangeHostnameDialog from "$dialogs/ChangeHostnameDialog.svelte";
import Button, { Label } from "@smui/button";
import List, { Item, Graphic, Text, Meta } from "@smui/list";
import Card from "@smui/card";
import { networkInfo, type WifiNetwork } from "$lib/NetworkInfo";
import {GET} from "$lib/api"
import {processNetworkInfo} from "$lib/NetworkInfo"
let networkData = GET("network")
networkData.then(value=>processNetworkInfo(value))
let changeHostnameDialog = {
open: false,
};
let wifiConnectionDialog = {
open: false,
network: {} as WifiNetwork,
};
function getWifiStrengthStyle(network: WifiNetwork) {
const strength = Math.ceil((Number(network.Quality) / 100) * 4);
switch (strength) {
case 0:
return "clip-path: circle(0px at 12.5px 19px);";
case 1:
return "clip-path: circle(4px at 12.5px 19px);";
case 2:
return "clip-path: circle(8px at 12.5px 19px);";
case 3:
return "clip-path: circle(14px at 12.5px 19px);";
case 4:
return "";
}
}
function onChangeHostname() {
changeHostnameDialog = {
open: true,
};
}
function onNetworkSelected(network: WifiNetwork) {
wifiConnectionDialog = {
open: true,
network,
};
}
</script>
<WifiConnectionDialog {...wifiConnectionDialog} />
<ChangeHostnameDialog {...changeHostnameDialog} />
<div class="admin-network-view">
<h1>Network Info</h1>
<div class="pure-form pure-form-aligned">
<div class="pure-control-group">
<label for="hostname">Hostname</label>
<Card id="hostname" variant="outlined">
<Text id="hostname">
{$networkInfo.hostname}
</Text>
</Card>
<Button on:click={onChangeHostname} touch variant="raised">
<Label>Change</Label>
</Button>
</div>
</div>
<div class="pure-form pure-form-aligned">
<div class="pure-control-group">
<label for="ip-addresses">IP Addresses</label>
<Card id="ip-addresses" variant="outlined">
{#each $networkInfo.ipAddresses as ipAddress}
<div>
<Text id="hostname">
{ipAddress}
</Text>
</div>
{/each}
</Card>
</div>
</div>
<div class="pure-form pure-form-aligned">
<div class="pure-control-group">
<label for="wifi">Wi-Fi</label>
<div class="wifi-networks">
<Card id="wifi" variant="outlined">
<List>
{#if $networkInfo.wifi.networks.length === 0}
<Item class="wifi-network">
<Text>Scanning...</Text>
</Item>
{:else}
{#each $networkInfo.wifi.networks as network}
<Item
class="wifi-network"
on:SMUI:action={() =>
onNetworkSelected(network)}
>
<Graphic
class="strength {$networkInfo.wifi
.ssid === network.Name
? 'active'
: ''}"
>
<span class="fa fa-wifi background" />
<span
class="fa fa-wifi"
style={getWifiStrengthStyle(
network
)}
/>
</Graphic>
<Text style="margin-right: 20px;"
>{network.Name}</Text
>
{#if network.Encryption !== "Open"}
<Meta>
<span class="fa fa-lock" />
</Meta>
{/if}
</Item>
{/each}
{/if}
</List>
</Card>
<em style="display: block;">
Click on a Wi-Fi network to connect or disconnect.
</em>
</div>
</div>
</div>
</div>
<style lang="scss">
$primary: #0078e7;
$very-dark: #555;
$text: #777;
$grey: #bbb;
$light: #ddd;
:global {
.admin-network-view {
.pure-form-aligned .pure-control-group label {
vertical-align: top;
font-size: 15pt;
font-weight: bold;
}
button {
margin: 0;
}
.mdc-card {
width: 400px;
min-height: 38px;
display: inline-block;
vertical-align: top;
margin-bottom: 20px;
margin-right: 20px;
padding: 5px 15px;
}
.wifi-networks {
display: inline-block;
.mdc-card {
padding: 0;
margin-bottom: 5px;
}
}
.wifi-network {
.lock {
font-size: 20px;
vertical-align: text-bottom;
}
.strength {
border-radius: 50%;
padding: 3px;
background-color: $light;
color: $very-dark;
margin-right: 10px;
position: relative;
&.active {
background-color: $primary;
color: white;
}
span {
position: absolute;
top: 5px;
font-size: 22px;
&.background {
opacity: 0.25;
}
}
}
}
}
}
</style>

View File

@@ -0,0 +1,196 @@
<script lang="ts">
import configTemplate from "../../../resources/config-template.json";
import { Config, DisplayUnits } from "$lib/ConfigStore";
import { ControllerMethods } from "$lib/RegisterControllerMethods";
import { onMount } from "svelte";
type ValueType =
| string
| number
| { title: string; value: string | number };
type Template = {
type?: string;
values?: Array<ValueType>;
unit?: "string";
iunit?: "string";
min?: number;
max?: number;
step?: number;
help?: string;
default?: string | number;
scale?: number;
};
const namesByKey = {
"gamepad-default-type": "Default type",
"probing-prompts": "Show safety prompts",
"probe-xdim": "Probe block width",
"probe-ydim": "Probe block length",
"probe-zdim": "Probe block height",
"probe-fast-seek": "Fast seek speed",
"probe-slow-seek": "Slow seek speed",
"program-start": "On program start",
"tool-change": "On tool change",
"program-end": "On program end",
"max-deviation": "Maximum deviation",
"junction-accel": "Junction acceleration",
};
export let key: string;
let keyParts: string[];
let template: Template;
let name: string;
let title: string;
let units: string;
let value;
onMount(() => {
keyParts = (key || "").split(".");
template = getTemplate();
name = keyParts[keyParts.length - 1];
name = namesByKey[name] || name;
title = getTitle();
value = getValue();
});
$: metric = $DisplayUnits === "METRIC";
$: if (template) {
units = metric || !template.iunit ? template.unit : template.iunit;
}
function getTemplate(): Template {
let template = configTemplate;
for (const part of keyParts) {
template = template[part];
}
return template as Template;
}
function getTitle(): string {
const help = template.help ? `${template.help}\n` : "";
return `${help}Default: ${template.default} ${template.unit || ""}`;
}
function getValue(): string | number {
let value: any = $Config;
for (const part of keyParts) {
value = value[part];
}
if (template.scale) {
if (metric) {
return Number.parseFloat(value.toFixed(3));
}
return Number.parseFloat((value / template.scale).toFixed(4));
}
return value;
}
function onChange(event) {
Config.update((config) => {
let target = config;
for (const part of keyParts.slice(0, -1)) {
target = target[part];
}
const value = getValueFromElement(event.target);
target[keyParts[keyParts.length - 1]] = value;
return config;
});
ControllerMethods.dispatch("config-changed");
}
function getValueFromElement(element) {
switch (template.type) {
case "float":
case "int":
return Number(element.value);
case "bool":
return element.checked;
default:
return element.value;
}
}
function getOptionValue(opt: ValueType) {
switch (typeof opt) {
case "object":
return opt.value || opt;
default:
return opt;
}
}
function getOptionTitle(opt: ValueType) {
switch (typeof opt) {
case "object":
return opt.title || opt;
default:
return opt;
}
}
</script>
{#if template}
<div class="pure-control-group" {title}>
<label for={name}>{name}</label>
{#if template.values}
<select {name} bind:value on:change={onChange}>
{#each template.values as opt}
<option
value={getOptionValue(opt)}
disabled={opt === "-----"}
>
{getOptionTitle(opt)}
</option>
{/each}
</select>
{:else if template.type === "bool"}
<input
{name}
type="checkbox"
checked={value}
on:change={onChange}
/>
{:else if template.type === "float"}
<input
{name}
type="number"
min={template.min}
max={template.max}
step={template.step || "any"}
bind:value
on:keyup={onChange}
/>
{:else if template.type === "int"}
<input
{name}
type="number"
min={template.min}
max={template.max}
bind:value
on:keyup={onChange}
/>
{:else if template.type === "string"}
<input {name} type="text" bind:value on:keyup={onChange} />
{:else if template.type == "text"}
<textarea {name} bind:value on:keyup={onChange} />
{/if}
<label for="" class="units">{units || ""}</label>
<slot name="extra" />
</div>
{/if}

View File

@@ -0,0 +1,62 @@
<script lang="ts">
import RemoteDiagnosticsDialog from "$dialogs/RemoteDiagnosticsDialog.svelte";
import Button, { Label } from "@smui/button";
let showRemoteDiagnosticsDialog = false;
</script>
<RemoteDiagnosticsDialog bind:open={showRemoteDiagnosticsDialog} />
<h2>Support & Contact Info</h2>
<p>
Please visit
<a href="https://onefinitycnc.com/support" target="_blank">
onefinitycnc.com/support
</a>
for a variety of support resources, and to find our contact information.
</p>
<Button
touch
variant="raised"
on:click={() => (showRemoteDiagnosticsDialog = true)}
>
<Label>Remote Diagnostics</Label>
</Button>
<h2>Discussion Forum</h2>
<p>
Check out our support and discussion forum at
<a href="https://forum.onefinitycnc.com" target="_blank"
>forum.onefinitycnc.com</a
>. Register on the site and post a message. We can't wait to hear from you.
</p>
<p>
We also maintain a list of
<a
href="https://forum.onefinitycnc.com/t/what-cad-cam-software-can-be-used-to-make-gcode-files-for-the-onefinity-cnc/10253"
target="_blank"
>
recommended software packages
</a>
on the forum.
</p>
<h2>Credits & Acknowledgements</h2>
<h4 style="margin-bottom: 0;">Artwork</h4>
<p style="margin-top: 0;">
Special thanks to
<a href="https://www.instagram.com/fierysquirrelart/" target="_blank">
@fierysquirrelart
</a>
for many of the graphics used in the controller.
</p>
<h4 style="margin-bottom: 0;">Buildbotics</h4>
<p style="margin-top: 0;">
This controller is based on the
<a href="http://buildbotics.com" target="_blank"
>Buildbotics CNC Controller</a
>.
</p>

View File

@@ -0,0 +1,129 @@
<script lang="ts">
import configTemplate from "../../../resources/config-template.json";
import ScreenRotationDialog from "$dialogs/ScreenRotationDialog.svelte";
import ConfigTemplatedInput from "./ConfigTemplatedInput.svelte";
import SetTimeDialog from "$dialogs/SetTimeDialog.svelte";
import Button, { Label } from "@smui/button";
const gcodeURL = "https://linuxcnc.org/docs/html/gcode/g-code.html";
let showScreenRotationDialog = false;
let showSetTimeDialog = false;
</script>
<ScreenRotationDialog bind:open={showScreenRotationDialog} />
<SetTimeDialog bind:open={showSetTimeDialog} />
<div class="settings-view">
<h1>Settings</h1>
<div class="pure-form pure-form-aligned">
<h2>User Interface</h2>
<fieldset>
<div class="pure-control-group">
<label for="screen-rotation" />
<Button
name="screen-rotation"
touch
variant="raised"
on:click={() => (showScreenRotationDialog = true)}
>
<Label>Change Screen Rotation</Label>
</Button>
</div>
<div class="pure-control-group">
<label for="set-time" />
<Button
name="set-time"
touch
variant="raised"
on:click={() => (showSetTimeDialog = true)}
>
<Label>Change Time & Timezone</Label>
</Button>
</div>
</fieldset>
<h2>Gamepads / Joypads</h2>
<fieldset>
<ConfigTemplatedInput key={`settings.gamepad-default-type`} />
<div class="tip">
If your gamepad doesn't work as expected, try one of the other
types.
</div>
</fieldset>
<h2>Probing</h2>
<fieldset>
<ConfigTemplatedInput key={`settings.probing-prompts`} />
<div class="tip">
Onefinity highly recommends that you keep the safety prompts
enabled. If you choose to live dangerously, and disable the
safety prompts, Onefinity cannot be held responsible.
</div>
<br />
{#each Object.keys(configTemplate.probe) as key}
{#if key !== "probe-diameter"}
<ConfigTemplatedInput key={`probe.${key}`} />
{/if}
{/each}
</fieldset>
<fieldset>
<h2>GCode</h2>
{#each Object.keys(configTemplate.gcode) as key}
<ConfigTemplatedInput key={`gcode.${key}`} />
{/each}
</fieldset>
<h2>Path Accuracy</h2>
<fieldset>
<ConfigTemplatedInput key={`settings.max-deviation`} />
<div class="tip">
Lower the maximum deviation to follow the programmed path more
precisely but at a slower speed.
</div>
<div class="tip">
In order to improve traversal speed, the path planner may merge
consecutive moves or round off sharp corners if doing so would
deviate from the program path by less than the maximum
deviation.
</div>
<div class="tip">
GCode commands
<a href={`${gcodeURL}#gcode:g61`} target="_blank">G61, G61.1</a>
and <a href={`${gcodeURL}#gcode:g64`} target="_blank">G64</a> also
affect path planning accuracy.
</div>
</fieldset>
<h2>Cornering Speed (Advanced)</h2>
<fieldset>
<ConfigTemplatedInput key={`settings.junction-accel`} />
<div class="tip">
Junction acceleration limits the cornering speed the planner
will allow. Increasing this value will allow for faster
traversal of corners but may cause the planner to violate axis
jerk limits and stall the motors. Use with caution.
</div>
</fieldset>
</div>
</div>
<style lang="scss">
.settings-view {
.tip {
margin-left: 210px;
margin-bottom: 15px;
font-style: italic;
font-size: 90%;
line-height: 1.5;
}
}
</style>

View File

@@ -0,0 +1,90 @@
<script lang="ts">
import TextField from "@smui/textfield";
import Icon from "@smui/textfield/icon";
import HelperText from "@smui/textfield/helper-text";
import MenuSurface, {
type MenuSurfaceComponentDev,
} from "@smui/menu-surface";
import List, { Item, Text } from "@smui/list";
import { virtualKeyboardChange } from "$lib/CustomActions";
import { onDestroy } from "svelte";
let menuSurface: MenuSurfaceComponentDev;
let menuTimeout;
let optionSelected: boolean = false;
export let value: string;
export let options: string[][];
export let valid: boolean;
export let helperText: string;
onDestroy(() => {
if (menuTimeout) {
clearTimeout(menuTimeout);
menuTimeout = undefined;
}
});
function showMenu(show: boolean) {
if (show && optionSelected) {
return;
}
optionSelected = false;
if (menuTimeout) {
clearTimeout(menuTimeout);
}
// Use a timeout to "debounce" the display of the menu.
menuTimeout = setTimeout(() => menuSurface.setOpen(show), 100);
}
</script>
<div class="textfield-with-options">
<TextField
bind:value
on:focusin={() => showMenu(true)}
on:focusout={() => showMenu(false)}
use={[virtualKeyboardChange((v) => (value = v))]}
{...$$restProps}
>
<div slot="trailingIcon">
{#if valid}
<Icon class="fa fa-check-circle-o" style="color: green;" />
{/if}
</div>
<HelperText persistent slot="helper">{helperText}</HelperText>
</TextField>
<MenuSurface bind:this={menuSurface} anchorCorner="BOTTOM_LEFT">
<div style="display: flex; flex-direction: row;">
{#each options as group}
<List>
{#each group as option}
<Item
on:SMUI:action={() => {
value = option;
showMenu(false);
optionSelected = true;
}}
>
<Text>{option}</Text>
</Item>
{/each}
</List>
{/each}
</div>
</MenuSurface>
</div>
<style lang="scss">
:global {
.textfield-with-options {
.mdc-deprecated-list-item {
height: 32px;
}
}
}
</style>

View File

@@ -0,0 +1,101 @@
<script lang="ts">
import Dialog, {
Title,
Content,
Actions,
InitialFocus,
} from "@smui/dialog";
import Button, { Label } from "@smui/button";
import TextField from "@smui/textfield";
import MessageDialog from "$dialogs/MessageDialog.svelte";
import * as api from "$lib/api";
import { virtualKeyboardChange } from "$lib/CustomActions";
// https://man7.org/linux/man-pages/man7/hostname.7.html
//
// Each element of the hostname must be from 1 to 63 characters long
// and the entire hostname, including the dots, can be at most 253
// characters long. Valid characters for hostnames are ASCII(7)
// letters from a to z, the digits from 0 to 9, and the hyphen (-).
// A hostname may not start with a hyphen.
const pattern = /[a-zA-Z0-9][a-zA-Z0-9-]{0,62}/;
export let open = false;
let rebooting = false;
let redirectTimeout = 45;
let hostname = "";
$: setTimeout(() => {
hostname = (hostname.match(pattern) || [""])[0].toLowerCase();
}, 0);
$: if (open) {
hostname = "";
}
async function onConfirm() {
rebooting = true;
await api.PUT("hostname", { hostname });
await api.PUT("reboot");
const interval = setInterval(() => {
if (0 < redirectTimeout) {
redirectTimeout -= 1;
} else {
clearInterval(interval);
location.hostname = getRedirectTarget();
}
}, 1000);
}
function getRedirectTarget() {
if (location.hostname.endsWith(".local")) {
return `${hostname}.local`;
}
if (location.hostname.endsWith(".lan")) {
return `${hostname}.lan`;
}
return hostname;
}
</script>
<MessageDialog open={rebooting} title="Rebooting" noaction>
Rebooting to apply the hostname change...
</MessageDialog>
<Dialog
bind:open
scrimClickAction=""
aria-labelledby="change-hostname-dialog-title"
aria-describedby="change-hostname-dialog-content"
>
<Title id="change-hostname-dialog-title">Change Hostname</Title>
<Content id="change-hostname-dialog-content">
<TextField
bind:value={hostname}
use={[InitialFocus, virtualKeyboardChange((v) => (hostname = v))]}
label="New Hostname"
spellcheck="false"
variant="filled"
style="width: 100%;"
/>
</Content>
<Actions>
<Button>
<Label>Cancel</Label>
</Button>
<Button
defaultAction
on:click={onConfirm}
disabled={hostname.length === 0}
>
<Label>Confirm & Reboot</Label>
</Button>
</Actions>
</Dialog>

View File

@@ -0,0 +1,244 @@
<script lang="ts" context="module">
import { writable } from "svelte/store";
import HomeMachineDialog from "$dialogs/HomeMachineDialog.svelte";
import ProbeDialog from "$dialogs/ProbeDialog.svelte";
import ScreenRotationDialog from "$dialogs/ScreenRotationDialog.svelte";
import UploadDialog from "$dialogs/UploadDialog.svelte";
import SetTimeDialog from "./SetTimeDialog.svelte";
import ManualHomeAxisDialog from "./ManualHomeAxisDialog.svelte";
import SetAxisPositionDialog from "./SetAxisPositionDialog.svelte";
import MoveToZeroDialog from "./MoveToZeroDialog.svelte";
import ShutdownDialog from "./ShutdownDialog.svelte";
import MessageDialog from "./MessageDialog.svelte";
const HomeMachineDialogProps = writable<HomeMachineDialogPropsType>();
type HomeMachineDialogPropsType = {
open: boolean;
home: () => void;
};
const ProbeDialogProps = writable<ProbeDialogPropsType>();
type ProbeDialogPropsType = {
open: boolean;
probeType: "xyz" | "z";
};
const ScreenRotationDialogProps = writable<ScreenRotationDialogPropsType>();
type ScreenRotationDialogPropsType = {
open: boolean;
};
const UploadDialogProps = writable<UploadDialogPropsType>();
type UploadDialogPropsType = {
open: boolean;
file: File;
onComplete: () => void;
};
const SetTimeDialogProps = writable<SetTimeDialogPropsType>();
type SetTimeDialogPropsType = {
open: boolean;
};
const ManualHomeAxisDialogProps = writable<ManualHomeAxisDialogPropsType>();
type ManualHomeAxisDialogPropsType = {
open: boolean;
axis: string;
};
const SetAxisPositionDialogProps =
writable<SetAxisPositionDialogPropsType>();
type SetAxisPositionDialogPropsType = {
open: boolean;
axis: string;
};
const MoveToZeroDialogProps = writable<MoveToZeroDialogPropsType>();
type MoveToZeroDialogPropsType = {
open: boolean;
axes: "xy" | "z";
};
const ShutdownDialogProps = writable<ShutdownDialogPropsType>();
type ShutdownDialogPropsType = {
open: boolean;
};
const MessageDialogProps = writable<MessageDialogPropsType>();
type MessageDialogPropsType = {
open: boolean;
title: string;
message: string;
noaction: boolean;
};
export function showDialog(
dialog: "HomeMachine",
props: Omit<HomeMachineDialogPropsType, "open">
);
export function showDialog(
dialog: "Probe",
props: Omit<ProbeDialogPropsType, "open">
);
export function showDialog(
dialog: "ScreenRotation",
props: Omit<ScreenRotationDialogPropsType, "open">
);
export function showDialog(
dialog: "Upload",
props: Omit<UploadDialogPropsType, "open">
);
export function showDialog(
dialog: "SetTime",
props: Omit<SetTimeDialogPropsType, "open">
);
export function showDialog(
dialog: "ManualHomeAxis",
props: Omit<ManualHomeAxisDialogPropsType, "open">
);
export function showDialog(
dialog: "SetAxisPosition",
props: Omit<SetAxisPositionDialogPropsType, "open">
);
export function showDialog(
dialog: "MoveToZero",
props: Omit<MoveToZeroDialogPropsType, "open">
);
export function showDialog(
dialog: "Shutdown",
props: Omit<ShutdownDialogPropsType, "open">
);
export function showDialog(
dialog: "Message",
props: Omit<MessageDialogPropsType, "open">
);
export function showDialog(dialog: string, props: any) {
switch (dialog) {
case "HomeMachine":
HomeMachineDialogProps.set({ ...props, open: true });
break;
case "Probe":
ProbeDialogProps.set({ ...props, open: true });
break;
case "ScreenRotation":
ScreenRotationDialogProps.set({ ...props, open: true });
break;
case "Upload":
UploadDialogProps.set({ ...props, open: true });
break;
case "SetTime":
SetTimeDialogProps.set({ ...props, open: true });
break;
case "ManualHomeAxis":
ManualHomeAxisDialogProps.set({ ...props, open: true });
break;
case "SetAxisPosition":
SetAxisPositionDialogProps.set({ ...props, open: true });
break;
case "MoveToZero":
MoveToZeroDialogProps.set({ ...props, open: true });
break;
case "Shutdown":
ShutdownDialogProps.set({ ...props, open: true });
break;
case "Message":
MessageDialogProps.set({ ...props, open: true });
break;
default:
throw new Error(`Unknown dialog '${dialog}'`);
}
}
</script>
<script lang="ts">
import { onMount, onDestroy } from "svelte";
let bodyObserver: MutationObserver;
let keyboardObserver: MutationObserver;
onMount(() => {
bodyObserver = new MutationObserver(() => {
const virtualKeyboard = document.getElementById(
"virtualKeyboardChromeExtension"
);
if (virtualKeyboard) {
bodyObserver.disconnect();
bodyObserver = undefined;
const virtualKeyboardOverlay = document.getElementById(
"virtualKeyboardChromeExtensionOverlayScrollExtend"
);
keyboardObserver = new MutationObserver(() => {
const open =
virtualKeyboard.getAttribute("_state") === "open";
const keyboardHeight = Number.parseFloat(
virtualKeyboardOverlay.style.height
);
const dialogContainers =
document.querySelectorAll<HTMLDivElement>(
".mdc-dialog .mdc-dialog__container"
);
for (let dialogContainer of dialogContainers) {
dialogContainer.style["marginBottom"] = open
? `${keyboardHeight}px`
: "";
}
});
keyboardObserver.observe(virtualKeyboard, { attributes: true });
}
});
bodyObserver.observe(document.querySelector("body"), {
subtree: false,
childList: true,
});
});
onDestroy(() => {
if (bodyObserver) {
bodyObserver.disconnect();
bodyObserver = undefined;
}
if (keyboardObserver) {
keyboardObserver.disconnect();
keyboardObserver = undefined;
}
});
</script>
<HomeMachineDialog {...$HomeMachineDialogProps} />
<ProbeDialog {...$ProbeDialogProps} />
<ScreenRotationDialog {...$ScreenRotationDialogProps} />
<UploadDialog {...$UploadDialogProps} />
<SetTimeDialog {...$SetTimeDialogProps} />
<ManualHomeAxisDialog {...$ManualHomeAxisDialogProps} />
<SetAxisPositionDialog {...$SetAxisPositionDialogProps} />
<MoveToZeroDialog {...$MoveToZeroDialogProps} />
<ShutdownDialog {...$ShutdownDialogProps} />
<MessageDialog {...$MessageDialogProps} />

View File

@@ -0,0 +1,33 @@
<script lang="ts">
import Dialog, {
Title,
Content,
Actions,
InitialFocus,
} from "@smui/dialog";
import Button, { Label } from "@smui/button";
export let open;
export let home: () => any;
</script>
<Dialog
bind:open
scrimClickAction=""
aria-labelledby="home-machine-dialog-title"
aria-describedby="home-machine-dialog-content"
>
<Title id="home-machine-dialog-title">Home Machine</Title>
<Content id="home-machine-dialog-content">Home the machine?</Content>
<Actions>
<Button>
<Label>Cancel</Label>
</Button>
<Button defaultAction use={[InitialFocus]} on:click={home}>
<Label>OK</Label>
</Button>
</Actions>
</Dialog>

View File

@@ -0,0 +1,54 @@
<script lang="ts">
import Dialog, {
Title,
Content,
Actions,
InitialFocus,
} from "@smui/dialog";
import TextField from "@smui/textfield";
import Button, { Label } from "@smui/button";
import { ControllerMethods } from "$lib/RegisterControllerMethods";
import { virtualKeyboardChange } from "$lib/CustomActions";
export let open: boolean;
export let axis = "";
let value = 0;
function onConfirm() {
ControllerMethods.set_home(axis, value);
}
</script>
<Dialog
bind:open
scrimClickAction=""
aria-labelledby="manual-home-axis-dialog-title"
aria-describedby="manual-home-axis-dialog-content"
>
<Title id="manual-home-axis-dialog-title">
Manually Home {axis.toUpperCase()} Axis
</Title>
<Content id="manual-home-axis-dialog-content">
<p>Set axis absolute position</p>
<TextField
label="Absolute"
type="number"
bind:value
use={[InitialFocus, virtualKeyboardChange((v) => (value = v))]}
variant="filled"
style="width: 100%;"
/>
</Content>
<Actions>
<Button>
<Label>Cancel</Label>
</Button>
<Button defaultAction on:click={onConfirm}>
<Label>Set</Label>
</Button>
</Actions>
</Dialog>

View File

@@ -0,0 +1,36 @@
<script lang="ts">
import Dialog, {
Title,
Content,
Actions,
InitialFocus,
} from "@smui/dialog";
import Button, { Label } from "@smui/button";
export let open: boolean;
export let title = "";
export let message = "";
export let noaction = false;
</script>
<Dialog
bind:open
scrimClickAction=""
escapeKeyAction=""
aria-labelledby="message-dialog-title"
aria-describedby="message-dialog-content"
>
<Title id="message-dialog-title">{title}</Title>
<Content id="message-dialog-content">
<slot>{message}</slot>
</Content>
{#if !noaction}
<Actions>
<Button defaultAction use={[InitialFocus]}>
<Label>OK</Label>
</Button>
</Actions>
{/if}
</Dialog>

View File

@@ -0,0 +1,33 @@
<script lang="ts">
import Dialog, { Title, Actions, InitialFocus } from "@smui/dialog";
import Button, { Label } from "@smui/button";
import { ControllerMethods } from "$lib/RegisterControllerMethods";
export let open;
export let axes: "xy" | "z";
</script>
<Dialog
bind:open
scrimClickAction=""
aria-labelledby="move-to-zero-dialog-title"
aria-describedby="move-to-zero-dialog-content"
>
<Title id="move-to-zero-dialog-title">
Move to {(axes || "").toUpperCase()} origin?
</Title>
<Actions>
<Button>
<Label>Cancel</Label>
</Button>
<Button
defaultAction
use={[InitialFocus]}
on:click={() => ControllerMethods.gotoZero(axes)}
>
<Label>Confirm</Label>
</Button>
</Actions>
</Dialog>

View File

@@ -0,0 +1,517 @@
<script type="ts">
import Dialog, { Title, Content, Actions } from "@smui/dialog";
import Button, { Label } from "@smui/button";
import LinearProgress from "@smui/linear-progress";
import { waitForChange } from "$lib/StoreHelpers";
import { ControllerMethods } from "$lib/RegisterControllerMethods";
import { Config } from "$lib/ConfigStore";
import { writable, type Writable } from "svelte/store";
import {
probingActive,
probeContacted,
probingComplete,
probingFailed,
probingStarted,
} from "$lib/ControllerState";
import { numberWithUnit } from "$lib/RegexHelpers";
import TextFieldWithOptions from "$components/TextFieldWithOptions.svelte";
import Icon from "svelte-icon";
import BitDiameter from "../svgs/probe-bit-diameter.svg?raw";
import CheckXYZ from "../svgs/probe-check-xyz.svg?raw";
import CheckZ from "../svgs/probe-check-z.svg?raw";
import PlaceXYZ from "../svgs/probe-place-xyz.svg?raw";
import PlaceZ from "../svgs/probe-place-z.svg?raw";
import PutAwayXYZ from "../svgs/probe-put-away-xyz.svg?raw";
import PutAwayZ from "../svgs/probe-put-away-z.svg?raw";
const ValidSteps = [
"None",
"CheckProbe",
"BitDimensions",
"PlaceProbeBlock",
"Probe",
"Done",
] as const;
type Step = typeof ValidSteps[number];
function isStep(str): str is Step {
return ValidSteps.includes(str);
}
const stepLabels: Record<Step, string> = {
None: "",
CheckProbe: "Check probe",
BitDimensions: "Bit dimensions",
PlaceProbeBlock: "Place probe block",
Probe: "Probe",
Done: "Done",
};
const cancelled = writable(false);
const userAcknowledged = writable(false);
const imperialBits: `${number}/${number} in`[] = [
"1/2 in",
"3/8 in",
"1/4 in",
"1/8 in",
"1/16 in",
"1/32 in",
];
const metricBits: `${number} mm`[] = [
"12 mm",
"10 mm",
"8 mm",
"6 mm",
"4 mm",
"3 mm",
];
export let open;
export let probeType: "xyz" | "z";
let currentStep: Step = "None";
let cutterDiameterString: string = "";
let cutterDiameterMetric: number;
let showCancelButton = true;
let steps: Step[] = [];
let nextButton = {
label: "Next",
disabled: false,
allowClose: false,
};
$: metric = $Config.settings?.units === "METRIC";
$: cutterDiameterMetric = numberWithUnit
.parse(cutterDiameterString)
?.toMetric();
$: if (open) {
cutterDiameterString = localStorage.getItem("cutterDiameter") ?? "";
// Svelte appears not to like it when you invoke
// an async function from a reactive statement, so we
// use requestAnimationFrame to call 'begin' at a later moment.
requestAnimationFrame(begin);
}
$: if (cutterDiameterString) {
updateButtons();
}
async function begin() {
try {
$probingActive = true;
assertValidProbeType();
$probingFailed = false;
const enableSafety = $Config.settings["probing-prompts"];
steps = [
enableSafety ? "CheckProbe" : undefined,
probeType === "xyz" ? "BitDimensions" : undefined,
enableSafety ? "PlaceProbeBlock" : undefined,
"Probe",
"Done",
].filter<Step>(isStep);
await stepCompleted("CheckProbe", probeContacted);
if (probeType === "xyz") {
await stepCompleted("BitDimensions", userAcknowledged);
localStorage.setItem(
"cutterDiameter",
numberWithUnit.normalize(cutterDiameterString)
);
}
await stepCompleted("PlaceProbeBlock", userAcknowledged);
await stepCompleted("Probe", probingComplete, probingFailed);
await stepCompleted("Done", userAcknowledged);
if (probeType === "xyz") {
ControllerMethods.gotoZero("xy");
}
} catch (err) {
if (err.message !== "cancelled") {
console.error("Error during probing:", err);
}
} finally {
$probingActive = false;
currentStep = "None";
if ($probingStarted) {
ControllerMethods.stop();
}
clearFlags();
}
}
function assertValidProbeType() {
switch (probeType) {
case "xyz":
case "z":
break;
default:
throw new Error(`Invalid probe type: ${probeType}`);
}
}
async function stepCompleted(
nextStep: Step,
...writables: Array<Writable<any>>
) {
currentStep = nextStep;
if (!steps.includes(currentStep)) {
return;
}
clearFlags();
updateButtons();
if (currentStep === "Probe") {
executeProbe();
}
await Promise.race([
...writables.map((writable) => waitForChange(writable)),
waitForChange(cancelled),
]);
if ($cancelled) {
throw new Error("cancelled");
}
}
function clearFlags(foo: string = "") {
$cancelled = false;
$probeContacted = false;
$probingStarted = false;
$probingComplete = false;
$userAcknowledged = false;
}
function updateButtons() {
showCancelButton = true;
nextButton = {
label: "Next",
disabled: false,
allowClose: false,
};
switch (currentStep) {
case "CheckProbe":
case "Probe":
nextButton.disabled = true;
break;
case "BitDimensions":
nextButton.disabled = !isFinite(cutterDiameterMetric);
break;
case "Done":
showCancelButton = false;
nextButton = {
disabled: false,
label: "Done",
allowClose: true,
};
break;
}
}
function executeProbe() {
const probeBlockWidth = $Config.probe["probe-xdim"];
const probeBlockLength = $Config.probe["probe-ydim"];
const probeBlockHeight = $Config.probe["probe-zdim"];
const slowSeek = $Config.probe["probe-slow-seek"];
const fastSeek = $Config.probe["probe-fast-seek"];
const cutterLength = 12.7;
const zLift = 1;
const xOffset = probeBlockWidth + cutterDiameterMetric / 2.0;
const yOffset = probeBlockLength + cutterDiameterMetric / 2.0;
const zOffset = probeBlockHeight;
if (probeType === "z") {
ControllerMethods.send(`
G21
G92 Z0
G38.2 Z -25.4 F${fastSeek}
G91 G1 Z 1
G38.2 Z -2 F${slowSeek}
G92 Z ${zOffset}
G91 G0 Z 25
M2
`);
} else {
// After probing Z, we want to drop the bit down:
// Ideally, 12.7mm/0.5in
// And we don't want to be more than 90% down on the probe block
// Also, add zlift to compensate for the fact that we lift after probing Z
const plunge = Math.min(cutterLength, zOffset * 0.9) + zLift;
ControllerMethods.send(`
G21
G92 X0 Y0 Z0
G38.2 Z -25 F${fastSeek}
G91 G1 Z 1
G38.2 Z -2 F${slowSeek}
G92 Z ${zOffset}
G91 G0 Z ${zLift}
G91 G0 X 20
G91 G0 Z ${-plunge}
G38.2 X -20 F${fastSeek}
G91 G1 X 1
G38.2 X -2 F${slowSeek}
G92 X ${xOffset}
G91 G0 X 1
G91 G0 Y 20
G91 G0 X -20
G38.2 Y -20 F${fastSeek}
G91 G1 Y 1
G38.2 Y -2 F${slowSeek}
G92 Y ${yOffset}
G91 G0 Y 3
G91 G0 Z 25
M2
`);
}
}
</script>
<Dialog
bind:open
class="probe-dialog"
scrimClickAction=""
aria-labelledby="probe-dialog-title"
aria-describedby="probe-dialog-content"
surface$style="width: 700px; max-width: calc(100vw - 32px);"
>
<Title id="probe-dialog-title">Probing {probeType?.toUpperCase()}</Title>
<Content id="probe-dialog-content" style="overflow: visible;">
<div class="steps">
<p>
<b>Step {steps.indexOf(currentStep) + 1} of {steps.length}</b>
</p>
<ul>
{#each steps as step}
<li class:active={currentStep === step}>
{stepLabels[step]}
</li>
{/each}
</ul>
</div>
<div style="width: 100%">
{#if currentStep === "CheckProbe"}
<p>
Attach the probe magnet to the collet, then touch the probe
block to the bit.
</p>
<Icon
data={probeType === "xyz" ? CheckXYZ : CheckZ}
size="300px"
class="probe-icon-svg"
/>
{:else if currentStep === "BitDimensions"}
<TextFieldWithOptions
label="Cutter diameter"
variant="filled"
spellcheck="false"
style="width: 100%;"
bind:value={cutterDiameterString}
options={[imperialBits, metricBits]}
valid={isFinite(cutterDiameterMetric)}
helperText={`Examples: 1/2", 10 mm, 0.25 in`}
/>
<Icon data={BitDiameter} size="150px" class="probe-icon-svg" />
{:else if currentStep === "PlaceProbeBlock"}
<p>
{#if probeType === "xyz"}
Place the probe block face up, on the lower-left corner
of your workpiece.
{:else}
Place the probe block face down, with the bit above the
recess.
{/if}
</p>
<Icon
data={probeType === "xyz" ? PlaceXYZ : PlaceZ}
width="304px"
height="129px"
class="probe-icon-svg"
/>
<p>
The probing procedure will begin as soon as you click
'Next'.
</p>
{:else if currentStep === "Probe"}
<p>Probing in progress...</p>
<LinearProgress indeterminate />
{:else if currentStep === "Done"}
{#if $probingFailed}
<h3>Emergency Stop!</h3>
<p>Could not find the probe block during probing!</p>
<p>
Make sure the tip of the bit is less than {metric
? "25mm"
: "1 in"}
above the probe block, and try again.
</p>
{:else}
<p>Don't forget to put away the probe!</p>
<Icon
data={probeType === "xyz" ? PutAwayXYZ : PutAwayZ}
width="329px"
height="256px"
class="probe-icon-svg"
/>
{#if probeType === "xyz"}
<p>The machine will now move to the XY origin.</p>
<p>Watch your hands!</p>
{/if}
{/if}
{/if}
</div>
</Content>
<Actions>
{#if showCancelButton}
<Button on:click={() => ($cancelled = true)}>
<Label>Cancel</Label>
</Button>
{/if}
<Button
defaultAction
data-mdc-dialog-action={nextButton.allowClose ? "close" : ""}
disabled={nextButton.disabled}
on:click={() => ($userAcknowledged = true)}
>
<Label>
{nextButton.label}
</Label>
</Button>
</Actions>
</Dialog>
<style lang="scss">
$primary: #0078e7;
$very-dark: #555;
$text: #777;
$grey: #bbb;
$light: #ddd;
:global {
.probe-dialog {
.mdc-linear-progress {
height: 10px;
margin: 10px 0;
}
.mdc-linear-progress__bar-inner {
border-top-width: 10px;
}
.probe-icon-svg {
display: block;
margin: 20px auto;
}
#probe-dialog-content {
display: flex;
flex-direction: row;
}
.bit-dimensions {
display: flex;
flex-direction: column;
}
.steps {
margin-right: 50px;
ul {
margin: 0 auto;
list-style-type: none;
counter-reset: steps;
margin: 0;
font-family: sans-serif;
padding-inline-start: 20px;
}
ul li {
padding: 0 0 12px 30px;
position: relative;
margin: 0;
white-space: nowrap;
color: $text;
&:after {
position: absolute;
top: 3px;
left: 0.5px;
content: "";
border: 2px solid $text;
border-radius: 50%;
display: inline-block;
height: 11px;
width: 11px;
text-align: center;
line-height: 12px;
background: transparent;
}
&:before {
position: absolute;
left: 7px;
top: 22px;
bottom: 0;
content: "";
width: 0;
border-left: 2px solid $text;
}
&:last-of-type:before {
border: none;
}
&.active {
color: $primary;
font-weight: bold;
&:after {
border: 3px solid $primary;
top: 2.5px;
left: 0;
}
}
}
}
}
}
</style>

View File

@@ -0,0 +1,67 @@
<script lang="ts">
import * as api from "$lib/api";
import TextField from "@smui/textfield";
import Dialog, {
Title,
Content,
Actions,
InitialFocus,
} from "@smui/dialog";
import Button, { Label } from "@smui/button";
import { virtualKeyboardChange } from "$lib/CustomActions";
export let open;
let code = "";
async function onContinue() {
const url = `remote-diagnostics?command=connect&code=${code}`;
const result = await api.GET(url);
if (result.code === 401) {
alert("The 6-digit code you provided was incorrect");
} else {
alert("Success!");
}
}
</script>
<Dialog
bind:open
scrimClickAction=""
aria-labelledby="remote-diagnostics-dialog-title"
aria-describedby="remote-diagnostics-dialog-content"
>
<Title id="remote-diagnostics-dialog-title">Remote Diagnostics</Title>
<Content id="remote-diagnostics-dialog-content">
<p>
This feature enables remote diagnosis of customer issues. It
requires a 6-digit code that is provided by Onefinity support during
a live support session.
</p>
<TextField
bind:value={code}
label="6-digit code"
type="number"
variant="filled"
invalid={code?.length !== 6}
use={[InitialFocus, virtualKeyboardChange((v) => (code = v))]}
/>
</Content>
<Actions>
<Button>
<Label>Cancel</Label>
</Button>
<Button
defaultAction
on:click={onContinue}
disabled={code?.length !== 6}
>
<Label>Continue</Label>
</Button>
</Actions>
</Dialog>

View File

@@ -0,0 +1,81 @@
<script type="ts">
import Dialog, {
Title,
Content,
Actions,
InitialFocus,
} from "@smui/dialog";
import Button, { Label } from "@smui/button";
import Radio from "@smui/radio";
import FormField from "@smui/form-field";
import MessageDialog from "$dialogs/MessageDialog.svelte";
import * as Api from "$lib/api";
import { onMount } from "svelte";
const options = [
{ value: 0, label: "Normal" },
{ value: 1, label: "Upside-down" },
];
export let open;
let currentValue;
let value;
let rebooting;
onMount(async () => {
const result = await Api.GET("screen-rotation");
currentValue = value = result.rotated ? 1 : 0;
});
async function onConfirm() {
rebooting = true;
await Api.PUT("screen-rotation", { rotated: value === 1 });
}
</script>
<MessageDialog open={rebooting} title="Rebooting" noaction>
Rebooting to apply the new screen rotation...
</MessageDialog>
<Dialog
bind:open
scrimClickAction=""
aria-labelledby="screen-rotation-dialog-title"
aria-describedby="screen-rotation-dialog-content"
>
<Title id="screen-rotation-dialog-title">Screen Rotation</Title>
<Content id="screen-rotation-dialog-content">
{#each options as option}
<FormField>
<Radio bind:group={value} value={option.value} />
<span slot="label">
{option.label}
</span>
</FormField>
{/each}
</Content>
<Actions>
<Button use={[InitialFocus]}>
<Label>Cancel</Label>
</Button>
<Button
defaultAction
disabled={value === currentValue}
on:click={onConfirm}
>
<Label>Confirm & Reboot</Label>
</Button>
</Actions>
</Dialog>
<style lang="scss">
:global {
#screen-rotation-dialog-content {
display: flex;
flex-direction: column;
}
}
</style>

View File

@@ -0,0 +1,72 @@
<script lang="ts">
import Dialog, {
Title,
Content,
Actions,
InitialFocus,
} from "@smui/dialog";
import TextField from "@smui/textfield";
import Button, { Label } from "@smui/button";
import { ControllerMethods } from "$lib/RegisterControllerMethods";
import { virtualKeyboardChange } from "$lib/CustomActions";
export let open: boolean;
export let axis = "";
let value = 0;
let homed = false;
let wasOpen = false;
$: if (open != wasOpen) {
if (open) {
homed = ControllerMethods.isAxisHomed(axis);
}
wasOpen = open;
}
function onUnhome() {
ControllerMethods.unhome(axis);
}
function onConfirm() {
ControllerMethods.set_position(axis, value);
}
</script>
<Dialog
bind:open
scrimClickAction=""
aria-labelledby="set-axis-position-dialog-title"
aria-describedby="set-axis-position-dialog-content"
>
<Title id="set-axis-position-dialog-title">
Set {axis.toUpperCase()} Axis Position
</Title>
<Content id="set-axis-position-dialog-content">
<TextField
label="Position"
type="number"
bind:value
use={[InitialFocus, virtualKeyboardChange((v) => (value = v))]}
spellcheck="false"
variant="filled"
style="width: 100%;"
/>
</Content>
<Actions>
<Button>
<Label>Cancel</Label>
</Button>
{#if homed}
<Button on:click={onUnhome}>
<Label>Unhome</Label>
</Button>
{/if}
<Button defaultAction on:click={onConfirm}>
<Label>Set</Label>
</Button>
</Actions>
</Dialog>

View File

@@ -0,0 +1,290 @@
<script lang="ts">
import Dialog, {
Title,
Content,
Actions,
InitialFocus,
} from "@smui/dialog";
import Button, { Label } from "@smui/button";
import TextField from "@smui/textfield";
import Select, { Option } from "@smui/select";
import CircularProgress from "@smui/circular-progress";
import VirtualList from "svelte-tiny-virtual-list";
import * as api from "$lib/api";
import { virtualKeyboardChange } from "$lib/CustomActions";
const itemHeight = 35;
type Timezone = {
label: string;
value: string;
};
export let open = false;
let year = "";
let month = "";
let day = "";
let hour = "";
let minute = "";
let am = true;
let wasOpen = false;
let loading = true;
let timezones: Timezone[] = [];
let currentTimezoneIndex: number;
let selectedTimezoneIndex: number;
let networkTimeSynchronized: boolean;
$: if (open != wasOpen) {
if (!wasOpen) {
loadData();
}
wasOpen = open;
}
async function loadData() {
loading = true;
const result = await api.GET("time");
parseTimezones(result.timezones);
parseTimeinfo(result.timeinfo);
const date = new Date();
year = date.getFullYear().toString();
month = (date.getMonth() + 1).toString();
day = date.getDate().toString();
hour = date.getHours().toString();
minute = date.getMinutes().toString();
am = date.getHours() >= 12;
loading = false;
}
function parseTimeinfo(str: string) {
const matches = Array.from(str.matchAll(/\s*([^:]+):\s+(.+)/gm));
let currentTimezoneValue;
for (const match of matches) {
let [, label, value] = match;
switch (label) {
case "Time zone":
currentTimezoneValue = value.split(" ")[0];
break;
case "NTP synchronized":
networkTimeSynchronized = false;
break;
}
}
currentTimezoneIndex = timezones.findIndex(
(tz) => tz.value === currentTimezoneValue
);
selectedTimezoneIndex = currentTimezoneIndex;
}
function parseTimezones(str: string) {
const matches = Array.from(str.matchAll(/\s*(\S+)\s*/gm));
timezones = [];
for (let [, value] of matches) {
timezones.push({
label: value.replace(/_/g, " "),
value,
});
}
// Sort alphabetically, but with the current timezone at the top of the list
timezones.sort((a, b) => {
switch (true) {
case a.value === "UTC":
return -1;
case b.value === "UTC":
return 1;
default:
return a.value.localeCompare(b.value);
}
});
}
async function onConfirm() {
const YY = year.toString().padStart(2, "0");
const MM = month.toString().padStart(2, "0");
const DD = day.toString().padStart(2, "0");
let hh = hour.toString().padStart(2, "0");
const mm = minute.toString().padStart(2, "0");
if (Number(hour) < 12 && !am) {
hh = (hour + 12).toString().padStart(2, "0");
}
await api.PUT("time", {
datetime: `${YY}-${MM}-${DD} ${hh}:${mm}:00`,
timezone: timezones[selectedTimezoneIndex].value,
});
}
</script>
<Dialog
bind:open
scrimClickAction=""
aria-labelledby="set-time-dialog-title"
aria-describedby="set-time-dialog-content"
>
<Title id="set-time-dialog-title">Change Time & Timezone</Title>
<Content id="set-time-dialog-content">
{#if loading}
<div style="display: flex; justify-content: center">
<CircularProgress
style="height: 32px; width: 32px;"
indeterminate
/>
</div>
{:else}
{#if networkTimeSynchronized}
<p>
Because this controller is connected to the internet, the
time is managed automatically, and cannot be manually set.
</p>
{:else}
<p>
Any time the controller is turned off, the time will need to
be reset. If you connect the controller to the internet, the
time will be managed automatically.
</p>
<TextField
bind:value={year}
use={[
InitialFocus,
virtualKeyboardChange((v) => (year = v)),
]}
label="Year"
type="number"
variant="filled"
style="width: 70px;"
/>
<TextField
bind:value={month}
use={[virtualKeyboardChange((v) => (month = v))]}
label="Month"
type="number"
variant="filled"
style="width: 70px;"
/>
<TextField
bind:value={day}
use={[virtualKeyboardChange((v) => (day = v))]}
label="Day"
type="number"
variant="filled"
style="width: 70px;"
/>
<span style="display: inline-block; width: 20px;" />
<TextField
bind:value={hour}
use={[virtualKeyboardChange((v) => (hour = v))]}
label="Hour"
type="number"
variant="filled"
style="width: 70px;"
/>
<TextField
bind:value={minute}
use={[virtualKeyboardChange((v) => (minute = v))]}
label="Minute"
type="number"
variant="filled"
style="width: 70px;"
/>
<Select
label=""
bind:value={am}
style="width: 90px;"
variant="filled"
>
<Option value={true}>AM</Option>
<Option value={false}>PM</Option>
</Select>
{/if}
<div class="timezones-container" style="margin-top: 30px;">
<VirtualList
width="100%"
height={itemHeight * 6}
itemCount={timezones.length}
itemSize={itemHeight}
scrollToIndex={currentTimezoneIndex}
scrollToAlignment="center"
>
<div
slot="item"
let:index
let:style
{style}
class="timezone"
class:selected={index === selectedTimezoneIndex}
on:click={() => (selectedTimezoneIndex = index)}
>
{timezones[index].label}
</div>
</VirtualList>
</div>
{/if}
</Content>
<Actions>
<Button>
<Label>Cancel</Label>
</Button>
<Button
defaultAction
disabled={selectedTimezoneIndex === -1}
on:click={onConfirm}
>
<Label>Confirm</Label>
</Button>
</Actions>
</Dialog>
<style lang="scss">
@use "sass:color";
$primary: #0078e7;
$very-dark: #555;
$text: #777;
$grey: #bbb;
$light: #ddd;
.timezones-container {
:global {
.virtual-list-wrapper {
border: 1px solid #ccc;
border-radius: 3px;
overflow-x: hidden;
overflow-y: scroll;
}
}
.timezone {
font-size: 14px;
display: flex;
align-items: center;
margin: 0;
padding-left: 10px;
&.selected {
color: $primary;
background-color: color.adjust($primary, $lightness: 50%);
font-weight: bold;
}
}
}
</style>

View File

@@ -0,0 +1,38 @@
<script lang="ts">
import Dialog, { Title, Actions, InitialFocus } from "@smui/dialog";
import Button, { Label } from "@smui/button";
import * as Api from "$lib/api";
export let open;
function shutdown() {
Api.PUT("shutdown");
}
function restart() {
Api.PUT("reboot");
}
</script>
<Dialog
bind:open
scrimClickAction=""
aria-labelledby="shutdown-dialog-title"
aria-describedby="shutdown-dialog-content"
>
<Title id="shutdown-dialog-title">Confirm Shutdown?</Title>
<Actions>
<Button>
<Label>Cancel</Label>
</Button>
<Button on:click={shutdown}>
<Label>Shutdown</Label>
</Button>
<Button use={[InitialFocus]} on:click={restart}>
<Label>Restart</Label>
</Button>
</Actions>
</Dialog>

View File

@@ -0,0 +1,83 @@
<script lang="ts">
import Dialog, {
Title,
Content,
Actions,
InitialFocus,
} from "@smui/dialog";
import Button, { Label } from "@smui/button";
import LinearProgress from "@smui/linear-progress";
export let open = false;
export let file: File;
export let onComplete: () => void;
let wasOpen = false;
let xhr;
let progress;
$: if (open != wasOpen) {
if (!wasOpen) {
beginUpload();
}
wasOpen = open;
}
$: if (!open) {
xhr = undefined;
}
async function beginUpload() {
progress = 0;
xhr = new XMLHttpRequest();
xhr.upload.onload = () => {
open = false;
if (onComplete) {
onComplete();
}
};
xhr.upload.onerror = () => {
open = false;
alert("Upload failed.");
};
xhr.upload.onabort = () => {
open = false;
};
xhr.upload.onprogress = (event) => {
progress = event.loaded / event.total;
};
xhr.open("PUT", `/api/file/${encodeURIComponent(file.name)}`);
xhr.send(file);
}
function onCancel() {
xhr.abort();
}
</script>
<Dialog
bind:open
scrimClickAction=""
aria-labelledby="upload-dialog-title"
aria-describedby="upload-dialog-content"
>
<Title id="upload-dialog-title">
Uploading {#if file}{file.name}...{/if}
</Title>
<Content id="upload-dialog-content">
<LinearProgress {progress} />
</Content>
<Actions>
<Button on:click={onCancel} use={[InitialFocus]}>
<Label>Cancel</Label>
</Button>
</Actions>
</Dialog>

View File

@@ -0,0 +1,112 @@
<script lang="ts">
import Dialog, {
Title,
Content,
Actions,
InitialFocus,
} from "@smui/dialog";
import Button, { Label } from "@smui/button";
import TextField from "@smui/textfield";
import Icon from "@smui/textfield/icon";
import HelperText from "@smui/textfield/helper-text";
import MessageDialog from "$dialogs/MessageDialog.svelte";
import type { WifiNetwork } from "$lib/NetworkInfo";
import * as api from "$lib/api";
import { virtualKeyboardChange } from "$lib/CustomActions";
export let open = false;
export let network: WifiNetwork;
let rebooting = false;
let password = "";
let showPassword = false;
$: needPassword = !network?.active && network?.Encryption !== "Open";
$: connectOrDisconnect = network?.active ? "Disconnect" : "Connect";
$: connectToOrDisconnectFrom = network?.active
? "Disconnect from"
: "Connect to";
$: if (open) {
password = "";
}
async function onConfirm() {
rebooting = true;
await api.PUT("network", {
wifi: {
enabled: !network.active,
ssid: network.Name,
password,
},
});
}
</script>
<MessageDialog open={rebooting} title="Rebooting" noaction>
Rebooting to apply Wifi changes...
</MessageDialog>
<Dialog
bind:open
scrimClickAction=""
aria-labelledby="wifi-connection-dialog-title"
aria-describedby="wifi-connection-dialog-content"
>
<Title id="wifi-connection-dialog-title">
{connectToOrDisconnectFrom}
{network.Name}
</Title>
<Content id="wifi-connection-dialog-content">
{#if needPassword}
<TextField
bind:value={password}
use={[
InitialFocus,
virtualKeyboardChange((v) => (password = v)),
]}
label="Password"
spellcheck="false"
variant="filled"
type={showPassword ? "text" : "password"}
style="width: 100%;"
>
<div
slot="trailingIcon"
on:click={() => (showPassword = !showPassword)}
>
<Icon
class={`fa ${showPassword ? "fa-eye-slash" : "fa-eye"}`}
/>
</div>
<HelperText persistent slot="helper">
Wifi passwords must be 8 to 128 characters
</HelperText>
</TextField>
{/if}
<p>
<em>
Clicking {connectOrDisconnect} will reboot the controller to apply
the changes.
</em>
</p>
</Content>
<Actions>
<Button>
<Label>Cancel</Label>
</Button>
<Button
defaultAction
on:click={onConfirm}
disabled={needPassword &&
(password.length < 8 || password.length > 128)}
>
<Label>{connectOrDisconnect} & Reboot</Label>
</Button>
</Actions>
</Dialog>

View File

@@ -0,0 +1,14 @@
import { writable } from "svelte/store";
type DisplayUnits = "METRIC" | "IMPERIAL";
export const Config = writable<Record<string, any>>({});
export const DisplayUnits = writable<DisplayUnits>();
export function handleConfigUpdate(config: Record<string, any>) {
Config.set(config);
}
export function setDisplayUnits(value: DisplayUnits) {
DisplayUnits.set(value);
}

View File

@@ -0,0 +1,32 @@
import { get, writable } from "svelte/store";
import { processNetworkInfo } from "./NetworkInfo";
export const networkInfo = writable({});
export const probingActive = writable(false);
export const probeContacted = writable(false);
export const probingStarted = writable(false);
export const probingFailed = writable(false);
export const probingComplete = writable(false);
export function handleControllerStateUpdate(state: Record<string, any>) {
if (get(probingActive)) {
if (state.pw === 0) {
probeContacted.set(true);
}
if (state.log?.msg === "Switch not found") {
probingFailed.set(true);
}
if (state.cycle !== "idle") {
probingStarted.set(true);
}
if (state.cycle === "idle" && get(probingStarted)) {
probingStarted.set(false);
probingComplete.set(true);
}
}
}

View File

@@ -0,0 +1,15 @@
import type { HTMLActionEntry } from "@smui/common/internal";
export function virtualKeyboardChange(cb: (v: any) => void): HTMLActionEntry {
const func = (node: HTMLElement, cb: (value: any) => void) => {
const input = node.querySelector("input");
if (!input) {
console.error("Could not find the textfield's <input>:", node);
throw new Error("Could not find the textfield's <input>");
}
input.addEventListener("keyup", () => cb(input.value));
};
return [ func, cb ];
}

View File

@@ -0,0 +1,81 @@
import { writable } from "svelte/store";
export type WifiNetwork = {
Quality: string;
Channel: string;
Frequency: string;
Mode: string;
"Bit Rates": string;
Name: string;
Address: string;
Encryption: string;
"Signal Level": string;
"Noise Level": string;
lastSeen: number;
active: boolean;
};
export type NetworkInfo = {
ipAddresses: Array<string>;
hostname: string;
wifi: {
ssid: string;
networks: Array<WifiNetwork>;
};
};
const empty: NetworkInfo = {
ipAddresses: [],
hostname: "",
wifi: {
ssid: "",
networks: []
}
};
export const networkInfo = writable<NetworkInfo>(empty);
export function processNetworkInfo(rawNetworkInfo: NetworkInfo) {
const now = Date.now();
const networksByName: Record<string, WifiNetwork> = {};
for (const network of rawNetworkInfo.wifi.networks) {
if (network.Name) {
network.lastSeen = now;
network.active = rawNetworkInfo.wifi.ssid === network.Name;
// There can be many entries for the same ssid, so
// we want to take the one with the highest quality
const currentNetwork = networksByName[network.Name] ?? { Quality: 0 };
if (network.Quality >= currentNetwork.Quality) {
networksByName[network.Name] = network;
}
}
}
for (const network of Object.values(networksByName)) {
if (network.lastSeen - now > 30000) {
delete networksByName[network.Name];
}
}
networkInfo.set({
ipAddresses: rawNetworkInfo.ipAddresses,
hostname: rawNetworkInfo.hostname,
wifi: {
ssid: rawNetworkInfo.wifi.ssid,
networks: Object.values(networksByName).sort((a, b) => {
switch (true) {
case a.active:
return -1;
case b.active:
return 1;
default:
return a.Name.localeCompare(b.Name);
}
})
}
});
}

View File

@@ -0,0 +1,85 @@
function numberWithUnitToMetric() {
return this.metric ? this.value : this.value * 25.4;
}
function isPojo(value) {
if (value === null || typeof value !== "object") {
return false;
}
return Object.getPrototypeOf(value) === Object.prototype;
}
const fractions = [
{ value: 0.75, formatted: "3/4" },
{ value: 0.625, formatted: "5/8" },
{ value: 0.5, formatted: "1/2" },
{ value: 0.375, formatted: "3/8" },
{ value: 0.25, formatted: "1/4" },
{ value: 0.1875, formatted: "3/16" },
{ value: 0.125, formatted: "1/8" },
{ value: 0.09375, formatted: "3/32" },
{ value: 0.0625, formatted: "1/16" },
{ value: 0.03125, formatted: "1/32" },
];
function formatFraction(value: number) {
const fraction = fractions.find(f => f.value === value);
return fraction ? fraction.formatted : value.toString();
}
export const numberWithUnit = {
regex: /^\s*(?:(\d+)\s*\/\s*(\d+)|(\d*\.\d+)|(\d+(?:\.\d+)?))\s*("|in|inch|inches|mm|millimeters)\s*$/,
parse: function(str: string) {
// eslint-disable-next-line prefer-const
let [ , numerator, denominator, decimal1, decimal2, unit ]: any = str?.match(numberWithUnit.regex) ?? [];
numerator = Number.parseFloat(numerator);
denominator = Number.parseFloat(denominator);
decimal1 = Number.parseFloat(decimal1);
decimal2 = Number.parseFloat(decimal2);
const metric = (unit ?? "").includes("m");
switch (true) {
case isFinite(numerator) && isFinite(denominator):
return {
value: numerator / denominator,
metric,
toMetric: numberWithUnitToMetric
};
case isFinite(decimal1) && decimal1 !== 0:
return {
value: decimal1,
metric,
toMetric: numberWithUnitToMetric
};
case isFinite(decimal2) && decimal2 !== 0:
return {
value: decimal2,
metric,
toMetric: numberWithUnitToMetric
};
default:
return undefined;
}
},
normalize: function(str) {
const value = this.parse(str);
switch (true) {
case !isPojo(value):
return "";
case value.metric:
return `${value.value} mm`;
default:
return `${formatFraction(value.value)} in`;
}
}
};

View File

@@ -0,0 +1,44 @@
interface RegisterableControllerMethods {
stop: () => void;
send: (gcode: string) => void;
dispatch: (event: string, ...args: any[]) => void;
isAxisHomed: (axis: string) => boolean;
unhome: (axis: string) => void;
set_position: (axis: string, value: number) => void;
set_home: (axis: string, value: number) => void;
}
interface ControllerMethods extends RegisterableControllerMethods {
gotoZero: (axes: "xy" | "z") => void;
}
export let ControllerMethods: ControllerMethods;
export function registerControllerMethods(methods: Partial<RegisterableControllerMethods>) {
ControllerMethods = {
...ControllerMethods,
...methods,
gotoZero
};
}
function gotoZero(axes: "xy" | "z") {
let axesClause = "";
switch (axes.toLowerCase()) {
case "xy":
axesClause = "X0Y0";
break;
case "z":
axesClause = "Z0";
break;
default:
throw new Error(`Invalid axes: ${axes}`);
}
ControllerMethods.send(`
G90
G0 ${axesClause}
`);
}

View File

@@ -0,0 +1,18 @@
import { get, type Writable } from "svelte/store";
export function listenForChange<T>(writable: Writable<T>, cb: (value: T) => void) {
const priorValue = get(writable);
const unsubscribe = writable.subscribe((value) => {
if (value !== priorValue) {
unsubscribe();
cb(value);
}
});
}
export function waitForChange<T>(writable: Writable<T>): Promise<T> {
return new Promise((resolve) => {
listenForChange(writable, (value) => resolve(value));
});
}

View File

@@ -0,0 +1,41 @@
type HttpMethod = "GET" | "PUT" | "POST" | "DELETE";
async function doFetch(method: HttpMethod, url: string, data: any, config: RequestInit) {
try {
const response = await fetch(`/api/${url}`, {
...config,
method,
cache: "no-cache",
body: (typeof data === "object")
? JSON.stringify(data)
: undefined,
headers: (typeof data === "object")
? {
"Content-Type": "application/json; charset=utf-8"
}
: {}
});
return await response.json();
} catch (error) {
console.debug(`API Error: ${url}: ${error}`);
throw error;
}
}
export function GET(url: string, config: RequestInit = {}) {
return doFetch("GET", url, undefined, config);
}
export function PUT(url: string, data: any = undefined, config: RequestInit = {}) {
return doFetch("PUT", url, data, config);
}
export function POST(url: string, data: any = undefined, config: RequestInit = {}) {
return doFetch("POST", url, data, config);
}
export function DELETE(url: string, config = {}) {
return doFetch("DELETE", url, undefined, config);
}

View File

@@ -0,0 +1,39 @@
import "polyfill-object.fromentries";
import matchAll from "string.prototype.matchall";
matchAll.shim();
import AdminNetworkView from "$components/AdminNetworkView.svelte";
import SettingsView from "$components/SettingsView.svelte";
import HelpView from "$components/HelpView.svelte";
import DialogHost, { showDialog } from "$dialogs/DialogHost.svelte";
import { handleConfigUpdate, setDisplayUnits } from "$lib/ConfigStore";
import { handleControllerStateUpdate } from "$lib/ControllerState";
import { registerControllerMethods } from "$lib/RegisterControllerMethods";
export function createComponent(component: string, target: HTMLElement, props: Record<string, any>) {
switch (component) {
case "AdminNetworkView":
return new AdminNetworkView({ target, props });
case "SettingsView":
return new SettingsView({ target, props });
case "HelpView":
return new HelpView({ target, props });
case "DialogHost":
return new DialogHost({ target, props });
default:
throw new Error("Unknown component");
}
}
export {
showDialog,
handleControllerStateUpdate,
handleConfigUpdate,
registerControllerMethods,
setDisplayUnits
};

View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100.88 191.47">
<polygon
points="21.64 186.89 12.57 189.89 3.5 186.89 3.5 88.81 1.5 85.76 1.5 1.5 23.64 1.5 23.64 85.76 21.64 88.81 21.64 186.89"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="3.5" y1="88.81" x2="21.64" y2="88.81"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="3.5" y1="185.56" x2="21.64" y2="177.06"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="3.5" y1="174.91" x2="21.64" y2="166.4"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="3.5" y1="164.21" x2="21.64" y2="155.71"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="3.5" y1="153.6" x2="21.64" y2="145.09"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="3.5" y1="142.9" x2="21.64" y2="134.4"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="3.5" y1="131.88" x2="21.64" y2="123.37"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="3.5" y1="121.18" x2="21.64" y2="112.68"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="3.5" y1="110.57" x2="21.64" y2="102.06"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="3.5" y1="99.87" x2="21.64" y2="91.37"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<g>
<line x1="27.28" y1="1.5" x2="29.78" y2="1.5"
style="fill:none; stroke:#a7a9ac; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="31.28" y1="1.5" x2="38.5" y2="1.5"
style="fill:none; stroke:#a7a9ac; stroke-dasharray:0 0 0 0 2.49 1.5 2.49 1.5; stroke-miterlimit:10; stroke-width:2px;" />
<polyline points="39.25 1.5 41.75 1.5 41.75 4"
style="fill:none; stroke:#a7a9ac; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="41.75" y1="6.64" x2="41.75" y2="19.39"
style="fill:none; stroke:#a7a9ac; stroke-dasharray:0 0 0 0 4.4 2.64 4.4 2.64; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="41.75" y1="20.71" x2="41.75" y2="82.72"
style="fill:none; stroke:#a7a9ac; stroke-dasharray:0 0 0 0 0 0 4.4 2.64 4.4 2.64 4.4 2.64; stroke-miterlimit:10; stroke-width:2px;" />
<polyline points="41.75 84.04 41.75 86.54 39.25 86.54"
style="fill:none; stroke:#a7a9ac; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="37.76" y1="86.54" x2="30.53" y2="86.54"
style="fill:none; stroke:#a7a9ac; stroke-dasharray:0 0 0 0 2.49 1.5 2.49 1.5; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="29.78" y1="86.54" x2="27.28" y2="86.54"
style="fill:none; stroke:#a7a9ac; stroke-miterlimit:10; stroke-width:2px;" />
</g>
<g>
<line x1="27.28" y1="90.04" x2="29.78" y2="90.04"
style="fill:none; stroke:#a7a9ac; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="30.59" y1="90.04" x2="34.53" y2="90.04"
style="fill:none; stroke:#a7a9ac; stroke-dasharray:0 0 0 0 1.36 .81 1.36 .81; stroke-miterlimit:10; stroke-width:2px;" />
<polyline points="34.94 90.04 37.44 90.04 37.44 92.54"
style="fill:none; stroke:#a7a9ac; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="37.44" y1="95.64" x2="37.44" y2="110.63"
style="fill:none; stroke:#a7a9ac; stroke-dasharray:0 0 0 0 5.17 3.1 5.17 3.1; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="37.44" y1="112.18" x2="37.44" y2="185.03"
style="fill:none; stroke:#a7a9ac; stroke-dasharray:0 0 0 0 0 0 5.17 3.1 5.17 3.1 5.17 3.1; stroke-miterlimit:10; stroke-width:2px;" />
<polyline points="37.44 186.58 37.44 189.08 34.94 189.08"
style="fill:none; stroke:#a7a9ac; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="34.13" y1="189.08" x2="30.22" y2="189.08"
style="fill:none; stroke:#a7a9ac; stroke-dasharray:0 0 0 0 1.35 .81 1.35 .81; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="29.81" y1="189.08" x2="27.31" y2="189.08"
style="fill:none; stroke:#a7a9ac; stroke-miterlimit:10; stroke-width:2px;" />
</g>
<line x1="41.75" y1="44.02" x2="56.79" y2="44.02"
style="fill:none; stroke:#a7a9ac; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="37.44" y1="138.65" x2="56.79" y2="138.65"
style="fill:none; stroke:#a7a9ac; stroke-miterlimit:10; stroke-width:2px;" />
<circle cx="78.33" cy="44.02" r="21.54"
style="fill:none; stroke:#a7a9ac; stroke-miterlimit:10; stroke-width:2px;" />
<circle cx="78.33" cy="138.65" r="21.54"
style="fill:none; stroke:#a7a9ac; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="68.56" y1="34.24" x2="88.11" y2="53.8"
style="fill:none; stroke:#be1e2d; stroke-miterlimit:10; stroke-width:4px;" />
<line x1="88.11" y1="34.24" x2="68.56" y2="53.8"
style="fill:none; stroke:#be1e2d; stroke-miterlimit:10; stroke-width:4px;" />
<polyline points="64.73 141.61 72.43 149.31 91.94 129.81"
style="fill:none; stroke:#00a651; stroke-miterlimit:10; stroke-width:4px;" />
</svg>

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@@ -0,0 +1,243 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 307.88 290.65">
<g>
<polygon
points="306.38 163.14 243.73 245.91 98.03 245.91 98.03 230.65 160.68 147.88 306.38 147.88 306.38 163.14"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<polyline points="306.38 147.88 243.73 230.65 98.03 230.65"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="243.73" y1="230.65" x2="243.73" y2="245.91"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
</g>
<g>
<g>
<line x1="146.89" y1="186.96" x2="146.89" y2="190.46"
style="fill:none; stroke:#37b34a; stroke-miterlimit:10; stroke-width:1.75px;" />
<line x1="146.89" y1="191.76" x2="146.89" y2="202.85"
style="fill:none; stroke:#37b34a; stroke-dasharray:0 0 0 0 4.56 1.3 4.56 1.3; stroke-miterlimit:10; stroke-width:1.75px;" />
<line x1="146.89" y1="203.5" x2="146.89" y2="207"
style="fill:none; stroke:#37b34a; stroke-miterlimit:10; stroke-width:1.75px;" />
</g>
<polyline points="142.67 191.08 146.89 185.87 150.95 190.95"
style="fill:none; stroke:#37b34a; stroke-miterlimit:10; stroke-width:1.75px;" />
</g>
<g>
<polygon points="150.06 174.24 132.23 197.79 90.77 197.79 90.77 186.45 108.6 162.89 150.06 162.89 150.06 174.24"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<polyline points="150.06 162.89 132.23 186.45 90.77 186.45"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="132.23" y1="186.45" x2="132.23" y2="197.79"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<ellipse cx="138.4" cy="167.46" rx="3.83" ry="1.56" style="fill:none; stroke:#231f20; stroke-miterlimit:10;" />
<circle cx="110.61" cy="192.12" r="3.12" style="fill:none; stroke:#231f20; stroke-miterlimit:10;" />
<g>
<polygon points="123.91 172.78 120.77 169.36 118.81 171.98 121.94 175.4 123.91 172.78"
style="fill:#29b473; opacity:.42;" />
<polygon points="120.79 176.92 117.66 173.5 115.69 176.12 118.83 179.54 120.79 176.92"
style="fill:#29b473; opacity:.42;" />
<polygon points="117.09 181.85 117.68 181.06 114.55 177.65 111.39 181.85 114.47 181.55 117.09 181.85"
style="fill:#29b473; opacity:.42;" />
<polygon points="127.88 167.49 122.18 167.49 121.92 167.84 125.05 171.25 127.88 167.49"
style="fill:#29b473; opacity:.42;" />
</g>
</g>
<g>
<g>
<g>
<path
d="M1.25,178.73c8.14-4.37,16.49-8.51,25.42-10.9s16.85-8.86,25.66-6.05c3.11,.99,4.86,.29,7.84,1.63,7.16,3.22,14.5,6.16,22.19,7.73,.92,.19,1.85,.36,2.75,.64,.76,.24,1.49,.57,2.23,.85,3.03,1.13,6.35,1.46,9.56,1.07,1.51-.18,3.03-.52,4.52-.25s2.98,1.36,3.1,2.87c.15,1.87-1.69,3.22-3.31,4.16-5.19,3.04-10.67,6.16-16.68,6.31-1.06,.03-2.12-.04-3.16,.13-.96,.16-1.87,.52-2.8,.81-5.16,1.61-10.98,.91-15.62-1.86-.45-.27-.97-.56-1.45-.36-.27,.11-.46,.36-.64,.6-5.22,6.94-13.45,11.53-22.1,12.33"
style="fill:#fff;" />
<path
d="M1.88,179.81c5.74-3.07,11.56-6.05,17.66-8.36,2.91-1.1,5.89-1.89,8.85-2.83,2.68-.84,5.25-1.98,7.82-3.08s5.22-2.2,7.99-2.8,5.43-.39,8.23,.37c2.52,.69,5.09,.51,7.53,1.56,2.93,1.27,5.84,2.56,8.82,3.7s6.08,2.19,9.2,3.02c1.49,.4,2.99,.73,4.5,1.04,1.66,.34,3.14,.9,4.73,1.47,2.8,1,5.85,1.37,8.81,1.13,1.5-.12,2.99-.5,4.5-.43,1.2,.05,3.18,.83,2.69,2.38-.36,1.13-1.67,1.85-2.62,2.42-1.33,.79-2.68,1.56-4.05,2.3-2.68,1.44-5.47,2.72-8.45,3.39s-6.08,.21-9.05,1.18-5.77,1.32-8.75,.89c-1.5-.22-3-.62-4.4-1.2s-2.85-1.93-4.35-1.72c-1.35,.19-2.09,1.71-2.9,2.64-.98,1.12-2.04,2.17-3.17,3.15-4.66,4.01-10.59,6.55-16.7,7.15-1.59,.16-1.6,2.66,0,2.5,5.78-.57,11.36-2.61,16.08-6.01,2.3-1.65,4.4-3.57,6.18-5.77,.18-.22,.7-1.1,.95-1.15,.34-.07,1.44,.81,1.81,.98,1.47,.71,3.01,1.26,4.61,1.6,2.93,.63,5.97,.65,8.91,.02,1.49-.32,2.91-1.01,4.41-1.23,1.65-.24,3.34-.05,5-.27,3.13-.41,6.08-1.52,8.91-2.88s5.65-2.73,7.99-4.62c2.05-1.66,3.05-4.46,1-6.58-2.35-2.43-5.65-1.48-8.6-1.24-3.43,.27-6.5-.44-9.69-1.64s-6.65-1.57-9.9-2.54-6.43-2.13-9.56-3.41c-1.61-.66-3.21-1.34-4.8-2.05-1.38-.61-2.73-1.24-4.23-1.49-1.3-.22-2.63-.22-3.92-.5-1.45-.31-2.83-.8-4.32-.97-2.8-.32-5.64,.17-8.31,1-3.25,1.01-6.32,2.49-9.46,3.78-3.37,1.38-6.89,2.22-10.33,3.39-7.25,2.48-14.12,5.94-20.86,9.55-1.42,.76-.16,2.92,1.26,2.16h0Z"
style="fill:#231f20;" />
</g>
<g>
<path
d="M90.74,193.11c-1.29,.17-2.57,.39-3.84,.65-.92,.19-1.85,.39-2.79,.36-.92-.04-1.82-.31-2.72-.51-4.42-.97-7.32-.5-11.78,.27"
style="fill:#fff;" />
<path
d="M90.41,191.9c-1.83,.25-3.67,.77-5.5,.93s-3.78-.62-5.62-.86c-3.38-.43-6.69,.12-10.01,.69-1.58,.27-.91,2.68,.66,2.41,3.37-.58,6.73-1.08,10.14-.47,1.83,.33,3.52,.91,5.4,.66s3.72-.7,5.6-.96c1.59-.22,.91-2.63-.66-2.41h0Z"
style="fill:#231f20;" />
</g>
<g>
<path
d="M69.76,187.81c-1.62,2.32-1,5.49-1.75,8.21-.39,1.43-1.18,2.75-1.38,4.22-.21,1.55,.25,3.1,.55,4.63,.07,.36,.13,.74,0,1.09-.11,.31-.36,.55-.59,.8-1.37,1.46-2.16,3.44-2.16,5.44"
style="fill:#fff;" />
<path
d="M68.68,187.18c-1.16,1.8-1.31,3.87-1.49,5.95-.09,1.07-.22,2.11-.57,3.14-.37,1.08-.89,2.12-1.12,3.24s-.17,2.25,.01,3.38c.1,.62,.27,1.23,.37,1.85,.12,.73,.02,.88-.44,1.43-1.45,1.71-2.2,3.8-2.26,6.03-.04,1.61,2.46,1.61,2.5,0,.03-1.13,.28-2.2,.82-3.2,.48-.88,1.34-1.51,1.76-2.41,.38-.82,.19-1.66,.03-2.51-.26-1.28-.63-2.59-.39-3.9,.36-1.96,1.39-3.66,1.65-5.68s.12-4.25,1.28-6.06c.88-1.36-1.29-2.61-2.16-1.26h0Z"
style="fill:#231f20;" />
</g>
<g>
<path
d="M67.04,206.15c1.3-.46,2.66-.76,4.03-.87,.35-.03,.69-.05,1.03-.11,.48-.09,.93-.27,1.39-.44,3.91-1.5,8.12-2.77,12.23-2.02"
style="fill:#fff;" />
<path
d="M67.37,207.35c1.57-.54,3.1-.69,4.72-.93,1.39-.21,2.71-.89,4.04-1.33,2.97-.99,6.13-1.71,9.26-1.18,1.57,.27,2.25-2.14,.66-2.41-3.36-.57-6.69-.06-9.92,.96-1.44,.46-2.88,1.23-4.37,1.5-1.73,.31-3.37,.4-5.07,.98-1.51,.52-.86,2.94,.66,2.41h0Z"
style="fill:#231f20;" />
</g>
<g>
<path
d="M58.89,226.43c-2.05-4.85,.54-11.14,5.42-13.14,2.12-.87,4.51-.99,6.57-2,2.05-1,3.61-2.78,5.6-3.89,2.67-1.49,5.93-1.66,8.55-3.22,1.82-1.08,3.21-2.76,4.88-4.07,2.03-1.59,4.44-2.59,6.82-3.58,1.75-.73,3.72-1.46,5.49-.79,2.12,.8,3.09,3.41,2.7,5.64s-1.83,4.12-3.34,5.8c-7.7,8.57-18.19,14.03-28.44,19.3-2.72,1.4-5.45,2.8-8.28,3.96-2.26,.92-4.6,1.69-6.7,2.94-1.64,.98-3.1,2.23-4.66,3.35-5.43,3.91-11.97,6.11-18.6,6.96-6.63,.86-13.38,.43-19.99-.57"
style="fill:#fff;" />
<path
d="M60.1,226.09c-1.55-3.87-.15-8.67,3.4-10.97,2.14-1.39,4.8-1.45,7.13-2.37s4.01-2.79,6.14-4.07c2.27-1.37,4.99-1.67,7.41-2.69s4.22-3.03,6.29-4.72,4.72-2.79,7.21-3.78c2.31-.91,5.06-1.29,5.9,1.63,.7,2.44-.84,4.79-2.36,6.57-1.71,2.01-3.64,3.85-5.65,5.56-4.04,3.43-8.55,6.28-13.16,8.88s-9.7,5.28-14.66,7.65c-2.68,1.28-5.5,2.22-8.2,3.46-2.54,1.16-4.6,2.92-6.86,4.52-10.84,7.7-24.78,8.03-37.46,6.14-1.57-.23-2.25,2.17-.66,2.41,12.35,1.84,25.58,1.74,36.69-4.67,2.65-1.53,4.89-3.64,7.52-5.2,2.79-1.66,5.97-2.56,8.92-3.9,5.5-2.5,10.9-5.39,16.16-8.37s9.92-6.02,14.27-9.85c3.62-3.19,8.96-7.83,8-13.24-.39-2.22-1.92-4.25-4.2-4.73-2.8-.6-5.73,.98-8.21,2.11-2.8,1.27-4.98,2.98-7.24,5.02-1.1,.99-2.27,1.84-3.66,2.37s-2.94,.87-4.39,1.36-2.72,1.1-3.93,1.98c-1.3,.94-2.48,2.07-3.9,2.83-2.74,1.46-6.03,1.3-8.65,3.12-4.22,2.94-6.21,8.78-4.27,13.61,.59,1.47,3.01,.83,2.41-.66h0Z"
style="fill:#231f20;" />
</g>
<g>
<path
d="M110.32,191.95c2.31,.23,4.18,2.27,4.64,4.55s-.3,4.67-1.62,6.57c-1.32,1.91-3.14,3.4-5.01,4.77-6.3,4.62-13.39,8.15-20.87,10.4"
style="fill:#fff;" />
<path
d="M109.98,193.15c3.4,.48,4.45,4.11,3.45,7.02-1.14,3.32-4.23,5.56-6.99,7.49-5.91,4.13-12.43,7.28-19.32,9.38-1.53,.47-.88,2.88,.66,2.41,8.11-2.47,15.89-6.34,22.57-11.59,3.04-2.38,5.73-5.52,5.97-9.55,.21-3.46-2.09-7.07-5.68-7.57-1.57-.22-2.25,2.19-.66,2.41h0Z"
style="fill:#231f20;" />
</g>
<g>
<path d="M85.05,190.29l-.83,3.58" style="fill:#fff;" />
<path
d="M83.84,189.96l-.83,3.58c-.15,.64,.2,1.38,.87,1.54,.64,.15,1.38-.19,1.54-.87l.83-3.58c.15-.64-.2-1.38-.87-1.54-.64-.15-1.38,.19-1.54,.87h0Z"
style="fill:#231f20;" />
</g>
<g>
<path d="M84.5,198.52c-.06,.99-.02,1.98,.13,2.96" style="fill:#fff;" />
<path
d="M83.25,198.52c-.07,1.1,0,2.2,.17,3.29,.04,.29,.33,.61,.57,.75,.27,.16,.66,.22,.96,.13s.59-.29,.75-.57l.13-.3c.06-.22,.06-.44,0-.66-.01-.08-.02-.15-.03-.23l.04,.33c-.12-.9-.15-1.82-.1-2.73,.02-.31-.15-.67-.37-.88s-.57-.38-.88-.37-.66,.12-.88,.37-.34,.54-.37,.88h0Z"
style="fill:#231f20;" />
</g>
<g>
<path d="M72.52,210.78c-.46,1.52-.91,3.05-1.05,4.64s.08,3.24,.9,4.6" style="fill:#fff;" />
<path
d="M71.31,210.44c-.99,3.32-1.88,7-.02,10.2,.81,1.39,2.97,.13,2.16-1.26-1.47-2.53-.52-5.62,.28-8.27,.19-.65-.23-1.36-.87-1.54s-1.34,.22-1.54,.87h0Z"
style="fill:#231f20;" />
</g>
<g>
<path d="M84.74,205.93c-.61,1.54-.48,3.36,.34,4.8" style="fill:#fff;" />
<path
d="M83.54,205.6c-.71,1.86-.5,4.03,.46,5.76,.32,.57,1.15,.81,1.71,.45s.79-1.1,.45-1.71c-.05-.09-.1-.18-.15-.28-.02-.05-.05-.09-.07-.14-.05-.12-.04-.1,.03,.08,.01-.04-.08-.21-.1-.26-.03-.09-.06-.17-.08-.26-.06-.2-.11-.41-.14-.61v-.08c-.03-.14-.03-.1,0,.1,.02-.09-.02-.22-.03-.31-.01-.18-.01-.37,0-.55,0-.11,0-.21,.02-.31,0-.05,0-.1,.02-.16-.03,.2-.03,.23-.01,.1,.07-.39,.17-.77,.31-1.14,.23-.61-.26-1.4-.87-1.54-.71-.16-1.29,.22-1.54,.87h0Z"
style="fill:#231f20;" />
</g>
<g>
<path d="M52.32,198.92c-4.57,5.84-6,13.57-6.04,20.99-.02,2.89,.15,5.85-.65,8.63" style="fill:#fff;" />
<path
d="M51.25,198.29c-3.09,4.01-4.82,8.88-5.6,13.85-.38,2.44-.58,4.9-.61,7.36-.04,2.92,.16,5.85-.61,8.71-.42,1.56,1.99,2.22,2.41,.66,.71-2.63,.7-5.34,.69-8.04,0-2.54,.09-5.09,.46-7.61,.72-4.93,2.35-9.68,5.41-13.66,.98-1.27-1.19-2.52-2.16-1.26h0Z"
style="fill:#231f20;" />
</g>
<g>
<path d="M43.94,197.7c-.58,3.78-3.36,6.94-6.64,8.9s-7.05,2.93-10.75,3.87" style="fill:#fff;" />
<path
d="M42.73,197.37c-1.3,7.8-9.97,10.24-16.52,11.9-1.56,.39-.9,2.81,.66,2.41,4.15-1.05,8.48-2.15,12.04-4.64,3.06-2.14,5.59-5.25,6.22-9.01,.26-1.57-2.15-2.25-2.41-.66h0Z"
style="fill:#231f20;" />
</g>
<g>
<path
d="M91.16,173.72c.9,.4,1.5,1.25,2.27,1.85,1.63,1.28,3.91,1.36,5.95,.98,.45-.08,.91-.19,1.3-.43s.71-.64,.75-1.1c.06-.7-.53-1.28-1.06-1.74"
style="fill:#fff;" />
<path
d="M90.53,174.79c.58,.28,.96,.69,1.44,1.14s1.03,.91,1.63,1.22c1.28,.66,2.75,.9,4.19,.83s3.25-.23,4.25-1.39c.56-.65,.78-1.51,.56-2.34-.2-.75-.77-1.36-1.34-1.86-.51-.44-1.27-.5-1.77,0-.45,.45-.51,1.32,0,1.77,.19,.17,.4,.34,.56,.54,0,0,.17,.36,.14,.17,0-.03,.04-.03,.05-.05-.06,.15-.05,.1-.12,.17-.11,.1-.29,.17-.46,.21-.96,.28-1.98,.34-2.99,.26-.84-.07-1.76-.34-2.47-.89-.81-.63-1.44-1.49-2.4-1.95-.61-.29-1.35-.17-1.71,.45-.32,.55-.16,1.42,.45,1.71h0Z"
style="fill:#231f20;" />
</g>
</g>
<g>
<g>
<path
d="M1.25,178.57c8.14-4.37,16.49-8.51,25.42-10.9,8.93-2.39,16.85-8.86,25.66-6.05,3.11,.99,4.86,.29,7.84,1.63,7.16,3.22,14.5,6.16,22.19,7.73,.92,.19,1.85,.36,2.75,.64,.76,.24,1.49,.57,2.23,.85,3.03,1.13,6.35,1.46,9.56,1.07,1.51-.18,3.03-.52,4.52-.25s2.98,1.36,3.1,2.87c.15,1.87-1.69,3.22-3.31,4.16-5.19,3.04-10.67,6.16-16.68,6.31-1.06,.03-2.12-.04-3.16,.13-.96,.16-1.87,.52-2.8,.81-5.16,1.61-10.98,.91-15.62-1.86-.45-.27-.97-.56-1.45-.36-.27,.11-.46,.36-.64,.6"
style="fill:#fff;" />
<path
d="M1.88,179.65c4.86-2.6,9.78-5.14,14.87-7.25,2.49-1.03,5.01-1.96,7.58-2.76,2.41-.74,4.83-1.37,7.18-2.29,4.42-1.74,8.72-4.06,13.44-4.92,2.29-.42,4.6-.32,6.84,.33s4.33,.55,6.45,1.12c2.51,.67,4.91,2.06,7.31,3.05s5.01,1.99,7.57,2.84,5.29,1.63,7.99,2.22c1.22,.27,2.46,.45,3.65,.83,1.32,.42,2.57,1.02,3.92,1.38,2.52,.68,5.18,.89,7.77,.63,1.78-.18,5.97-1.37,6.75,1.15,.63,2.02-3.24,3.63-4.54,4.37-2.34,1.34-4.72,2.63-7.25,3.57-2.8,1.04-5.51,1.41-8.47,1.47-2.79,.06-5.28,1.39-8.03,1.68s-5.61-.04-8.26-.98c-2.04-.72-4.85-3.38-6.68-1.03-.98,1.25,.78,3.03,1.77,1.77,.36-.46,.86,.14,1.3,.37,.49,.26,.99,.5,1.5,.72,1.24,.54,2.53,.97,3.85,1.26,2.53,.55,5.13,.63,7.68,.24,1.24-.19,2.43-.52,3.63-.9,1.41-.46,2.68-.62,4.16-.63,2.68-.02,5.3-.5,7.82-1.4s5.08-2.18,7.48-3.54c2-1.13,4.41-2.21,5.78-4.13,1.29-1.8,.98-4.13-.71-5.56-2.12-1.78-4.81-1.28-7.34-.97-2.82,.34-5.69,.13-8.4-.74-1.34-.43-2.61-1.04-3.97-1.39s-2.89-.6-4.32-.94c-5.66-1.37-11.12-3.43-16.46-5.74-2.36-1.02-4.53-2.1-7.12-2.39-1.12-.12-2.24-.2-3.33-.49-1.24-.33-2.43-.68-3.71-.82-4.99-.56-9.77,1.38-14.26,3.29-2.63,1.12-5.26,2.29-8,3.12-3.06,.92-6.11,1.8-9.1,2.95-6.07,2.35-11.88,5.29-17.61,8.36-1.42,.76-.16,2.92,1.26,2.16h0Z"
style="fill:#231f20;" />
</g>
<path d="M69.76,189.67c1.61,0,1.61-2.5,0-2.5s-1.61,2.5,0,2.5h0Z" style="fill:#231f20;" />
<g>
<path
d="M91.16,173.56c.9,.4,1.5,1.25,2.27,1.85,1.63,1.28,3.91,1.36,5.95,.98,.45-.08,.91-.19,1.3-.43s.71-.64,.75-1.1c.06-.7-.53-1.28-1.06-1.74"
style="fill:#fff;" />
<path
d="M90.53,174.64c.58,.28,.96,.69,1.44,1.14s1.03,.91,1.63,1.22c1.28,.66,2.75,.9,4.19,.83s3.25-.23,4.25-1.39c.56-.65,.78-1.51,.56-2.34-.2-.75-.77-1.36-1.34-1.86-.51-.44-1.27-.5-1.77,0-.45,.45-.51,1.32,0,1.77,.19,.17,.4,.34,.56,.54,0,0,.17,.36,.14,.17,0-.03,.04-.03,.05-.05-.06,.15-.05,.1-.12,.17-.11,.1-.29,.17-.46,.21-.96,.28-1.98,.34-2.99,.26-.84-.07-1.76-.34-2.47-.89-.81-.63-1.44-1.49-2.4-1.95-.61-.29-1.35-.17-1.71,.45-.32,.55-.16,1.42,.45,1.71h0Z"
style="fill:#231f20;" />
</g>
</g>
</g>
<g>
<path
d="M107.25,200.34c-.57,.69-1.44,1.13-2.4,1.13-1.72,0-3.12-1.4-3.12-3.12,0-.71,.24-1.36,.63-1.88l5.79-6.56c.56-.56,1.34-.91,2.2-.91,1.72,0,3.12,1.4,3.12,3.12,0,.91-.39,1.72-1,2.29l-5.22,5.93Z"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10;" />
<path
d="M107.97,198.36c0,.75-.27,1.45-.71,1.99-.57,.69-1.44,1.13-2.4,1.13-1.72,0-3.12-1.4-3.12-3.12,0-.71,.24-1.36,.63-1.88,.57-.75,1.47-1.23,2.48-1.23,1.72,0,3.12,1.4,3.12,3.12Z"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10;" />
</g>
<g>
<polygon
points="142.87 164.83 137.76 166.52 132.66 164.83 132.66 109.62 131.53 107.91 131.53 60.47 144 60.47 144 107.91 142.87 109.62 142.87 164.83"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="132.66" y1="109.62" x2="142.87" y2="109.62"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="132.66" y1="164.09" x2="142.87" y2="159.3"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="132.66" y1="158.09" x2="142.87" y2="153.3"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="132.66" y1="152.07" x2="142.87" y2="147.28"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="132.66" y1="146.09" x2="142.87" y2="141.31"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="132.66" y1="140.07" x2="142.87" y2="135.28"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="132.66" y1="133.87" x2="142.87" y2="129.08"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="132.66" y1="127.85" x2="142.87" y2="123.06"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="132.66" y1="121.87" x2="142.87" y2="117.08"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="132.66" y1="115.85" x2="142.87" y2="111.06"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
</g>
<path d="M169.68,0V57.54c0,2.23-1.82,4.05-4.05,4.05h-56.36c-2.23,0-4.05-1.82-4.05-4.05V0"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<rect x="125.74" y="61.6" width="24.04" height="24.04"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<rect x="122.08" y="85.64" width="31.37" height="19.04"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="134.29" y1="85.64" x2="134.29" y2="104.68"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="148.31" y1="85.64" x2="148.31" y2="104.68"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<ellipse cx="128.14" cy="95.16" rx="2.39" ry="4.57"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<path
d="M113.51,99.73c-1.32,0-2.39-2.05-2.39-4.57s1.07-4.57,2.39-4.57h14.44c1.32,0,2.39,2.05,2.39,4.57s-1.07,4.57-2.39,4.57h-14.44Z"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<ellipse cx="113.51" cy="95.16" rx="2.39" ry="4.57"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<g>
<g>
<line x1="127.88" y1="202.38" x2="127.88" y2="205.88"
style="fill:none; stroke:#37b34a; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="127.88" y1="207.38" x2="127.88" y2="220.16"
style="fill:none; stroke:#37b34a; stroke-dasharray:0 0 0 0 5.26 1.5 5.26 1.5; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="127.88" y1="220.92" x2="127.88" y2="224.42"
style="fill:none; stroke:#37b34a; stroke-miterlimit:10; stroke-width:2px;" />
</g>
<polyline points="122.99 207.33 127.88 201.28 132.72 207.33"
style="fill:none; stroke:#37b34a; stroke-miterlimit:10; stroke-width:2px;" />
</g>
<g>
<g>
<line x1="95.86" y1="94.9" x2="92.36" y2="94.9"
style="fill:none; stroke:#37b34a; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="90.8" y1="94.9" x2="77.59" y2="94.9"
style="fill:none; stroke:#37b34a; stroke-dasharray:0 0 0 0 5.44 1.55 5.44 1.55; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="76.81" y1="94.9" x2="56.6" y2="94.9"
style="fill:none; stroke:#37b34a; stroke-dasharray:0 0 0 0 0 0 5.44 1.55 5.44 1.55 5.44 1.55; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="55.82" y1="94.9" x2="52.32" y2="94.9"
style="fill:none; stroke:#37b34a; stroke-miterlimit:10; stroke-width:2px;" />
</g>
<polyline points="90.9 90 96.95 94.9 90.9 99.73"
style="fill:none; stroke:#37b34a; stroke-miterlimit:10; stroke-width:2px;" />
</g>
<path
d="M111.84,93.61c-5.44,.15-10.02,3.72-13.85,7.24-2.01,1.85-3.9,3.81-5.83,5.74s-4.16,3.88-6.06,6.02c-4.2,4.74-7.49,10.2-10.3,15.85-2.66,5.36-5.36,10.73-7.5,16.33-2.35,6.16-3.71,12.57-4.38,19.12-.1,1.01,.94,1.88,1.88,1.88,1.1,0,1.77-.86,1.88-1.88,.57-5.54,1.71-10.99,3.56-16.25s4.22-10.04,6.62-14.91c2.64-5.36,5.4-10.68,9.12-15.38,3.31-4.18,7.41-7.76,11.19-11.51s8.22-8.36,13.67-8.51c2.41-.07,2.42-3.82,0-3.75h0Z"
style="fill:#231f20;" />
<path
d="M59.12,233.43c2.05,17.35-4.54,34.73-17.73,46.21-3.46,3.02-7.33,5.53-11.45,7.56-2.17,1.06-.27,4.3,1.89,3.24,16.06-7.89,27.69-23.39,30.62-41.06,.88-5.28,1.04-10.63,.41-15.94-.12-1.01-.78-1.88-1.88-1.88-.92,0-1.99,.86-1.88,1.88h0Z"
style="fill:#231f20;" />
<path
d="M103.49,197.11c-7.6,6.84-13.89,15.16-18.3,24.39-2.34,4.9-4.19,10.04-7.16,14.61s-6.89,8.75-10.54,12.93c-4.48,5.13-8.96,10.26-13.44,15.38-1.58,1.81,1.06,4.47,2.65,2.65,3.93-4.5,7.87-9.01,11.8-13.51,3.72-4.25,7.58-8.42,10.96-12.96s5.44-9.33,7.66-14.32c2.1-4.74,4.55-9.28,7.51-13.54,3.31-4.76,7.2-9.1,11.52-12.98,1.8-1.62-.86-4.26-2.65-2.65h0Z"
style="fill:#231f20;" />
</svg>

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -0,0 +1,275 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 307.88 288.65">
<g>
<polygon
points="306.38 161.14 243.73 243.91 98.03 243.91 98.03 228.65 160.68 145.88 306.38 145.88 306.38 161.14"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<polyline points="306.38 145.88 243.73 228.65 98.03 228.65"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="243.73" y1="228.65" x2="243.73" y2="243.91"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
</g>
<g>
<g>
<line x1="146.89" y1="184.96" x2="146.89" y2="188.46"
style="fill:none; stroke:#39b54a; stroke-miterlimit:10; stroke-width:1.75px;" />
<line x1="146.89" y1="189.76" x2="146.89" y2="200.85"
style="fill:none; stroke:#39b54a; stroke-dasharray:0 0 0 0 4.56 1.3 4.56 1.3; stroke-miterlimit:10; stroke-width:1.75px;" />
<line x1="146.89" y1="201.5" x2="146.89" y2="205"
style="fill:none; stroke:#39b54a; stroke-miterlimit:10; stroke-width:1.75px;" />
</g>
<polyline points="142.67 189.08 146.89 183.87 150.95 188.95"
style="fill:none; stroke:#39b54a; stroke-miterlimit:10; stroke-width:1.75px;" />
</g>
<g>
<polygon
points="150.06 172.24 132.23 195.79 90.77 195.79 90.77 184.45 108.6 160.89 118.18 160.89 118.19 163.9 150.06 163.9 150.06 172.24"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<polyline points="149.25 164.78 137.31 180.56 137.3 178.27 136.9 178.28 132.23 184.45 90.77 184.45"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="132.23" y1="184.45" x2="132.23" y2="195.79"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<ellipse cx="138.4" cy="165.46" rx="3.83" ry="1.56" style="fill:none; stroke:#231f20; stroke-miterlimit:10;" />
<circle cx="110.61" cy="190.12" r="3.12" style="fill:none; stroke:#231f20; stroke-miterlimit:10;" />
</g>
<g>
<g>
<polygon
points="149.65 164.78 149.65 172.23 131.83 195.79 131.83 184.45 136.5 178.28 136.9 178.27 136.91 180.56 148.85 164.78 149.65 164.78"
style="fill:#fff;" />
<polygon
points="117.79 163.9 149.65 163.9 149.65 164.78 148.85 164.78 136.91 180.56 136.9 178.27 136.5 178.28 136.3 177.75 107.89 177.75 107.89 177.3 117.79 163.9"
style="fill:#8dc63f;" />
<polygon
points="136.3 177.75 136.5 178.28 131.83 184.45 110.21 184.45 90.37 184.45 108.19 160.89 116.92 160.89 104.6 177.75 107.89 177.75 136.3 177.75"
style="fill:#ed1c24;" />
<path d="M131.83,184.45v11.34h-21.62v-2.55c1.72,0,3.12-1.4,3.12-3.12s-1.4-3.12-3.12-3.12v-2.55h21.62Z"
style="fill:#fff;" />
<circle cx="110.21" cy="190.12" r="3.12" style="fill:#fff;" />
<path d="M110.21,193.24v2.55h-19.84v-11.34h19.84v2.55c-1.72,0-3.12,1.39-3.12,3.12s1.4,3.12,3.12,3.12Z"
style="fill:#fff;" />
<polygon
points="104.6 177.75 116.92 160.89 117.77 160.89 117.79 163.9 107.89 177.3 107.89 177.75 104.6 177.75"
style="fill:#fff;" />
</g>
<g>
<polygon
points="149.65 164.78 149.65 172.23 131.83 195.79 110.21 195.79 90.37 195.79 90.37 184.45 108.19 160.89 116.92 160.89 117.77 160.89 117.79 163.9 149.65 163.9 149.65 164.78"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<polyline
points="148.85 164.78 136.91 180.56 136.9 178.27 136.5 178.28 131.83 184.45 110.21 184.45 90.37 184.45"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="131.83" y1="184.45" x2="131.83" y2="195.79"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<circle cx="110.21" cy="190.12" r="3.12" style="fill:none; stroke:#231f20; stroke-miterlimit:10;" />
<polyline points="116.92 160.89 104.6 177.75 107.89 177.75 136.3 177.75"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="117.79" y1="163.9" x2="107.89" y2="177.3"
style="fill:none; stroke:#231f20; stroke-linecap:round; stroke-miterlimit:10; stroke-width:2px;" />
</g>
</g>
<g>
<g>
<g>
<path
d="M1.25,176.73c8.14-4.37,16.49-8.51,25.42-10.9,8.93-2.39,16.85-8.86,25.66-6.05,3.11,.99,4.86,.29,7.84,1.63,7.16,3.22,14.5,6.16,22.19,7.73,.92,.19,1.85,.36,2.75,.64,.76,.24,1.49,.57,2.23,.85,3.03,1.13,6.35,1.46,9.56,1.07,1.51-.18,3.03-.52,4.52-.25s2.98,1.36,3.1,2.87c.15,1.87-1.69,3.22-3.31,4.16-5.19,3.04-10.67,6.16-16.68,6.31-1.06,.03-2.12-.04-3.16,.13-.96,.16-1.87,.52-2.8,.81-5.16,1.61-10.98,.91-15.62-1.86-.45-.27-.97-.56-1.45-.36-.27,.11-.46,.36-.64,.6-5.22,6.94-13.45,11.53-22.1,12.33"
style="fill:#fff;" />
<path
d="M1.88,177.81c5.74-3.07,11.56-6.05,17.66-8.36,2.91-1.1,5.89-1.89,8.85-2.83,2.68-.84,5.25-1.98,7.82-3.08s5.22-2.2,7.99-2.8,5.43-.39,8.23,.37c2.52,.69,5.09,.51,7.53,1.56,2.93,1.27,5.84,2.56,8.82,3.7s6.08,2.19,9.2,3.02c1.49,.4,2.99,.73,4.5,1.04,1.66,.34,3.14,.9,4.73,1.47,2.8,1,5.85,1.37,8.81,1.13,1.5-.12,2.99-.5,4.5-.43,1.2,.05,3.18,.83,2.69,2.38-.36,1.13-1.67,1.85-2.62,2.42-1.33,.79-2.68,1.56-4.05,2.3-2.68,1.44-5.47,2.72-8.45,3.39s-6.08,.21-9.05,1.18-5.77,1.32-8.75,.89c-1.5-.22-3-.62-4.4-1.2s-2.85-1.93-4.35-1.72c-1.35,.19-2.09,1.71-2.9,2.64-.98,1.12-2.04,2.17-3.17,3.15-4.66,4.01-10.59,6.55-16.7,7.15-1.59,.16-1.6,2.66,0,2.5,5.78-.57,11.36-2.61,16.08-6.01,2.3-1.65,4.4-3.57,6.18-5.77,.18-.22,.7-1.1,.95-1.15,.34-.07,1.44,.81,1.81,.98,1.47,.71,3.01,1.26,4.61,1.6,2.93,.63,5.97,.65,8.91,.02,1.49-.32,2.91-1.01,4.41-1.23,1.65-.24,3.34-.05,5-.27,3.13-.41,6.08-1.52,8.91-2.88s5.65-2.73,7.99-4.62c2.05-1.66,3.05-4.46,1-6.58-2.35-2.43-5.65-1.48-8.6-1.24-3.43,.27-6.5-.44-9.69-1.64s-6.65-1.57-9.9-2.54-6.43-2.13-9.56-3.41c-1.61-.66-3.21-1.34-4.8-2.05-1.38-.61-2.73-1.24-4.23-1.49-1.3-.22-2.63-.22-3.92-.5-1.45-.31-2.83-.8-4.32-.97-2.8-.32-5.64,.17-8.31,1-3.25,1.01-6.32,2.49-9.46,3.78-3.37,1.38-6.89,2.22-10.33,3.39-7.25,2.48-14.12,5.94-20.86,9.55-1.42,.76-.16,2.92,1.26,2.16h0Z"
style="fill:#231f20;" />
</g>
<g>
<path
d="M90.74,191.11c-1.29,.17-2.57,.39-3.84,.65-.92,.19-1.85,.39-2.79,.36-.92-.04-1.82-.31-2.72-.51-4.42-.97-7.32-.5-11.78,.27"
style="fill:#fff;" />
<path
d="M90.41,189.9c-1.83,.25-3.67,.77-5.5,.93s-3.78-.62-5.62-.86c-3.38-.43-6.69,.12-10.01,.69-1.58,.27-.91,2.68,.66,2.41,3.37-.58,6.73-1.08,10.14-.47,1.83,.33,3.52,.91,5.4,.66s3.72-.7,5.6-.96c1.59-.22,.91-2.63-.66-2.41h0Z"
style="fill:#231f20;" />
</g>
<g>
<path
d="M69.76,185.81c-1.62,2.32-1,5.49-1.75,8.21-.39,1.43-1.18,2.75-1.38,4.22-.21,1.55,.25,3.1,.55,4.63,.07,.36,.13,.74,0,1.09-.11,.31-.36,.55-.59,.8-1.37,1.46-2.16,3.44-2.16,5.44"
style="fill:#fff;" />
<path
d="M68.68,185.18c-1.16,1.8-1.31,3.87-1.49,5.95-.09,1.07-.22,2.11-.57,3.14-.37,1.08-.89,2.12-1.12,3.24s-.17,2.25,.01,3.38c.1,.62,.27,1.23,.37,1.85,.12,.73,.02,.88-.44,1.43-1.45,1.71-2.2,3.8-2.26,6.03-.04,1.61,2.46,1.61,2.5,0,.03-1.13,.28-2.2,.82-3.2,.48-.88,1.34-1.51,1.76-2.41,.38-.82,.19-1.66,.03-2.51-.26-1.28-.63-2.59-.39-3.9,.36-1.96,1.39-3.66,1.65-5.68s.12-4.25,1.28-6.06c.88-1.36-1.29-2.61-2.16-1.26h0Z"
style="fill:#231f20;" />
</g>
<g>
<path
d="M67.04,204.15c1.3-.46,2.66-.76,4.03-.87,.35-.03,.69-.05,1.03-.11,.48-.09,.93-.27,1.39-.44,3.91-1.5,8.12-2.77,12.23-2.02"
style="fill:#fff;" />
<path
d="M67.37,205.35c1.57-.54,3.1-.69,4.72-.93,1.39-.21,2.71-.89,4.04-1.33,2.97-.99,6.13-1.71,9.26-1.18,1.57,.27,2.25-2.14,.66-2.41-3.36-.57-6.69-.06-9.92,.96-1.44,.46-2.88,1.23-4.37,1.5-1.73,.31-3.37,.4-5.07,.98-1.51,.52-.86,2.94,.66,2.41h0Z"
style="fill:#231f20;" />
</g>
<g>
<path
d="M58.89,224.43c-2.05-4.85,.54-11.14,5.42-13.14,2.12-.87,4.51-.99,6.57-2,2.05-1,3.61-2.78,5.6-3.89,2.67-1.49,5.93-1.66,8.55-3.22,1.82-1.08,3.21-2.76,4.88-4.07,2.03-1.59,4.44-2.59,6.82-3.58,1.75-.73,3.72-1.46,5.49-.79,2.12,.8,3.09,3.41,2.7,5.64s-1.83,4.12-3.34,5.8c-7.7,8.57-18.19,14.03-28.44,19.3-2.72,1.4-5.45,2.8-8.28,3.96-2.26,.92-4.6,1.69-6.7,2.94-1.64,.98-3.1,2.23-4.66,3.35-5.43,3.91-11.97,6.11-18.6,6.96-6.63,.86-13.38,.43-19.99-.57"
style="fill:#fff;" />
<path
d="M60.1,224.09c-1.55-3.87-.15-8.67,3.4-10.97,2.14-1.39,4.8-1.45,7.13-2.37s4.01-2.79,6.14-4.07c2.27-1.37,4.99-1.67,7.41-2.69s4.22-3.03,6.29-4.72,4.72-2.79,7.21-3.78c2.31-.91,5.06-1.29,5.9,1.63,.7,2.44-.84,4.79-2.36,6.57-1.71,2.01-3.64,3.85-5.65,5.56-4.04,3.43-8.55,6.28-13.16,8.88s-9.7,5.28-14.66,7.65c-2.68,1.28-5.5,2.22-8.2,3.46-2.54,1.16-4.6,2.92-6.86,4.52-10.84,7.7-24.78,8.03-37.46,6.14-1.57-.23-2.25,2.17-.66,2.41,12.35,1.84,25.58,1.74,36.69-4.67,2.65-1.53,4.89-3.64,7.52-5.2,2.79-1.66,5.97-2.56,8.92-3.9,5.5-2.5,10.9-5.39,16.16-8.37s9.92-6.02,14.27-9.85c3.62-3.19,8.96-7.83,8-13.24-.39-2.22-1.92-4.25-4.2-4.73-2.8-.6-5.73,.98-8.21,2.11-2.8,1.27-4.98,2.98-7.24,5.02-1.1,.99-2.27,1.84-3.66,2.37s-2.94,.87-4.39,1.36-2.72,1.1-3.93,1.98c-1.3,.94-2.48,2.07-3.9,2.83-2.74,1.46-6.03,1.3-8.65,3.12-4.22,2.94-6.21,8.78-4.27,13.61,.59,1.47,3.01,.83,2.41-.66h0Z"
style="fill:#231f20;" />
</g>
<g>
<path
d="M110.32,189.95c2.31,.23,4.18,2.27,4.64,4.55s-.3,4.67-1.62,6.57c-1.32,1.91-3.14,3.4-5.01,4.77-6.3,4.62-13.39,8.15-20.87,10.4"
style="fill:#fff;" />
<path
d="M109.98,191.15c3.4,.48,4.45,4.11,3.45,7.02-1.14,3.32-4.23,5.56-6.99,7.49-5.91,4.13-12.43,7.28-19.32,9.38-1.53,.47-.88,2.88,.66,2.41,8.11-2.47,15.89-6.34,22.57-11.59,3.04-2.38,5.73-5.52,5.97-9.55,.21-3.46-2.09-7.07-5.68-7.57-1.57-.22-2.25,2.19-.66,2.41h0Z"
style="fill:#231f20;" />
</g>
<g>
<path d="M85.05,188.29l-.83,3.58" style="fill:#fff;" />
<path
d="M83.84,187.96l-.83,3.58c-.15,.64,.2,1.38,.87,1.54,.64,.15,1.38-.19,1.54-.87l.83-3.58c.15-.64-.2-1.38-.87-1.54-.64-.15-1.38,.19-1.54,.87h0Z"
style="fill:#231f20;" />
</g>
<g>
<path d="M84.5,196.52c-.06,.99-.02,1.98,.13,2.96" style="fill:#fff;" />
<path
d="M83.25,196.52c-.07,1.1,0,2.2,.17,3.29,.04,.29,.33,.61,.57,.75,.27,.16,.66,.22,.96,.13s.59-.29,.75-.57l.13-.3c.06-.22,.06-.44,0-.66-.01-.08-.02-.15-.03-.23l.04,.33c-.12-.9-.15-1.82-.1-2.73,.02-.31-.15-.67-.37-.88s-.57-.38-.88-.37-.66,.12-.88,.37-.34,.54-.37,.88h0Z"
style="fill:#231f20;" />
</g>
<g>
<path d="M72.52,208.78c-.46,1.52-.91,3.05-1.05,4.64s.08,3.24,.9,4.6" style="fill:#fff;" />
<path
d="M71.31,208.44c-.99,3.32-1.88,7-.02,10.2,.81,1.39,2.97,.13,2.16-1.26-1.47-2.53-.52-5.62,.28-8.27,.19-.65-.23-1.36-.87-1.54s-1.34,.22-1.54,.87h0Z"
style="fill:#231f20;" />
</g>
<g>
<path d="M84.74,203.93c-.61,1.54-.48,3.36,.34,4.8" style="fill:#fff;" />
<path
d="M83.54,203.6c-.71,1.86-.5,4.03,.46,5.76,.32,.57,1.15,.81,1.71,.45s.79-1.1,.45-1.71c-.05-.09-.1-.18-.15-.28-.02-.05-.05-.09-.07-.14-.05-.12-.04-.1,.03,.08,.01-.04-.08-.21-.1-.26-.03-.09-.06-.17-.08-.26-.06-.2-.11-.41-.14-.61v-.08c-.03-.14-.03-.1,0,.1,.02-.09-.02-.22-.03-.31-.01-.18-.01-.37,0-.55,0-.11,0-.21,.02-.31,0-.05,0-.1,.02-.16-.03,.2-.03,.23-.01,.1,.07-.39,.17-.77,.31-1.14,.23-.61-.26-1.4-.87-1.54-.71-.16-1.29,.22-1.54,.87h0Z"
style="fill:#231f20;" />
</g>
<g>
<path d="M52.32,196.92c-4.57,5.84-6,13.57-6.04,20.99-.02,2.89,.15,5.85-.65,8.63" style="fill:#fff;" />
<path
d="M51.25,196.29c-3.09,4.01-4.82,8.88-5.6,13.85-.38,2.44-.58,4.9-.61,7.36-.04,2.92,.16,5.85-.61,8.71-.42,1.56,1.99,2.22,2.41,.66,.71-2.63,.7-5.34,.69-8.04,0-2.54,.09-5.09,.46-7.61,.72-4.93,2.35-9.68,5.41-13.66,.98-1.27-1.19-2.52-2.16-1.26h0Z"
style="fill:#231f20;" />
</g>
<g>
<path d="M43.94,195.7c-.58,3.78-3.36,6.94-6.64,8.9s-7.05,2.93-10.75,3.87" style="fill:#fff;" />
<path
d="M42.73,195.37c-1.3,7.8-9.97,10.24-16.52,11.9-1.56,.39-.9,2.81,.66,2.41,4.15-1.05,8.48-2.15,12.04-4.64,3.06-2.14,5.59-5.25,6.22-9.01,.26-1.57-2.15-2.25-2.41-.66h0Z"
style="fill:#231f20;" />
</g>
<g>
<path
d="M91.16,171.72c.9,.4,1.5,1.25,2.27,1.85,1.63,1.28,3.91,1.36,5.95,.98,.45-.08,.91-.19,1.3-.43s.71-.64,.75-1.1c.06-.7-.53-1.28-1.06-1.74"
style="fill:#fff;" />
<path
d="M90.53,172.79c.58,.28,.96,.69,1.44,1.14s1.03,.91,1.63,1.22c1.28,.66,2.75,.9,4.19,.83s3.25-.23,4.25-1.39c.56-.65,.78-1.51,.56-2.34-.2-.75-.77-1.36-1.34-1.86-.51-.44-1.27-.5-1.77,0-.45,.45-.51,1.32,0,1.77,.19,.17,.4,.34,.56,.54,0,0,.17,.36,.14,.17,0-.03,.04-.03,.05-.05-.06,.15-.05,.1-.12,.17-.11,.1-.29,.17-.46,.21-.96,.28-1.98,.34-2.99,.26-.84-.07-1.76-.34-2.47-.89-.81-.63-1.44-1.49-2.4-1.95-.61-.29-1.35-.17-1.71,.45-.32,.55-.16,1.42,.45,1.71h0Z"
style="fill:#231f20;" />
</g>
</g>
<g>
<g>
<path
d="M1.25,176.57c8.14-4.37,16.49-8.51,25.42-10.9,8.93-2.39,16.85-8.86,25.66-6.05,3.11,.99,4.86,.29,7.84,1.63,7.16,3.22,14.5,6.16,22.19,7.73,.92,.19,1.85,.36,2.75,.64,.76,.24,1.49,.57,2.23,.85,3.03,1.13,6.35,1.46,9.56,1.07,1.51-.18,3.03-.52,4.52-.25s2.98,1.36,3.1,2.87c.15,1.87-1.69,3.22-3.31,4.16-5.19,3.04-10.67,6.16-16.68,6.31-1.06,.03-2.12-.04-3.16,.13-.96,.16-1.87,.52-2.8,.81-5.16,1.61-10.98,.91-15.62-1.86-.45-.27-.97-.56-1.45-.36-.27,.11-.46,.36-.64,.6"
style="fill:#fff;" />
<path
d="M1.88,177.65c4.86-2.6,9.78-5.14,14.87-7.25,2.49-1.03,5.01-1.96,7.58-2.76,2.41-.74,4.83-1.37,7.18-2.29,4.42-1.74,8.72-4.06,13.44-4.92,2.29-.42,4.6-.32,6.84,.33s4.33,.55,6.45,1.12c2.51,.67,4.91,2.06,7.31,3.05s5.01,1.99,7.57,2.84,5.29,1.63,7.99,2.22c1.22,.27,2.46,.45,3.65,.83,1.32,.42,2.57,1.02,3.92,1.38,2.52,.68,5.18,.89,7.77,.63,1.78-.18,5.97-1.37,6.75,1.15,.63,2.02-3.24,3.63-4.54,4.37-2.34,1.34-4.72,2.63-7.25,3.57-2.8,1.04-5.51,1.41-8.47,1.47-2.79,.06-5.28,1.39-8.03,1.68s-5.61-.04-8.26-.98c-2.04-.72-4.85-3.38-6.68-1.03-.98,1.25,.78,3.03,1.77,1.77,.36-.46,.86,.14,1.3,.37,.49,.26,.99,.5,1.5,.72,1.24,.54,2.53,.97,3.85,1.26,2.53,.55,5.13,.63,7.68,.24,1.24-.19,2.43-.52,3.63-.9,1.41-.46,2.68-.62,4.16-.63,2.68-.02,5.3-.5,7.82-1.4s5.08-2.18,7.48-3.54c2-1.13,4.41-2.21,5.78-4.13,1.29-1.8,.98-4.13-.71-5.56-2.12-1.78-4.81-1.28-7.34-.97-2.82,.34-5.69,.13-8.4-.74-1.34-.43-2.61-1.04-3.97-1.39s-2.89-.6-4.32-.94c-5.66-1.37-11.12-3.43-16.46-5.74-2.36-1.02-4.53-2.1-7.12-2.39-1.12-.12-2.24-.2-3.33-.49-1.24-.33-2.43-.68-3.71-.82-4.99-.56-9.77,1.38-14.26,3.29-2.63,1.12-5.26,2.29-8,3.12-3.06,.92-6.11,1.8-9.1,2.95-6.07,2.35-11.88,5.29-17.61,8.36-1.42,.76-.16,2.92,1.26,2.16h0Z"
style="fill:#231f20;" />
</g>
<path d="M69.76,187.67c1.61,0,1.61-2.5,0-2.5s-1.61,2.5,0,2.5h0Z" style="fill:#231f20;" />
<g>
<path
d="M91.16,171.56c.9,.4,1.5,1.25,2.27,1.85,1.63,1.28,3.91,1.36,5.95,.98,.45-.08,.91-.19,1.3-.43s.71-.64,.75-1.1c.06-.7-.53-1.28-1.06-1.74"
style="fill:#fff;" />
<path
d="M90.53,172.64c.58,.28,.96,.69,1.44,1.14s1.03,.91,1.63,1.22c1.28,.66,2.75,.9,4.19,.83s3.25-.23,4.25-1.39c.56-.65,.78-1.51,.56-2.34-.2-.75-.77-1.36-1.34-1.86-.51-.44-1.27-.5-1.77,0-.45,.45-.51,1.32,0,1.77,.19,.17,.4,.34,.56,.54,0,0,.17,.36,.14,.17,0-.03,.04-.03,.05-.05-.06,.15-.05,.1-.12,.17-.11,.1-.29,.17-.46,.21-.96,.28-1.98,.34-2.99,.26-.84-.07-1.76-.34-2.47-.89-.81-.63-1.44-1.49-2.4-1.95-.61-.29-1.35-.17-1.71,.45-.32,.55-.16,1.42,.45,1.71h0Z"
style="fill:#231f20;" />
</g>
</g>
</g>
<g>
<path
d="M107.25,198.34c-.57,.69-1.44,1.13-2.4,1.13-1.72,0-3.12-1.4-3.12-3.12,0-.71,.24-1.36,.63-1.88l5.79-6.56c.56-.56,1.34-.91,2.2-.91,1.72,0,3.12,1.4,3.12,3.12,0,.91-.39,1.72-1,2.29l-5.22,5.93Z"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10;" />
<path
d="M107.97,196.36c0,.75-.27,1.45-.71,1.99-.57,.69-1.44,1.13-2.4,1.13-1.72,0-3.12-1.4-3.12-3.12,0-.71,.24-1.36,.63-1.88,.57-.75,1.47-1.23,2.48-1.23,1.72,0,3.12,1.4,3.12,3.12Z"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10;" />
</g>
<g>
<polygon
points="142.87 164.83 137.76 166.52 132.66 164.83 132.66 109.62 131.53 107.91 131.53 60.47 144 60.47 144 107.91 142.87 109.62 142.87 164.83"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="132.66" y1="109.62" x2="142.87" y2="109.62"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="132.66" y1="164.09" x2="142.87" y2="159.3"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="132.66" y1="158.09" x2="142.87" y2="153.3"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="132.66" y1="152.07" x2="142.87" y2="147.28"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="132.66" y1="146.09" x2="142.87" y2="141.31"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="132.66" y1="140.07" x2="142.87" y2="135.28"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="132.66" y1="133.87" x2="142.87" y2="129.08"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="132.66" y1="127.85" x2="142.87" y2="123.06"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="132.66" y1="121.87" x2="142.87" y2="117.08"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="132.66" y1="115.85" x2="142.87" y2="111.06"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
</g>
<path d="M169.68,0V57.54c0,2.23-1.82,4.05-4.05,4.05h-56.36c-2.23,0-4.05-1.82-4.05-4.05V0"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<rect x="125.74" y="61.6" width="24.04" height="24.04"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<rect x="122.08" y="85.64" width="31.37" height="19.04"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="134.29" y1="85.64" x2="134.29" y2="104.68"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="148.31" y1="85.64" x2="148.31" y2="104.68"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<ellipse cx="128.14" cy="95.16" rx="2.39" ry="4.57"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<path
d="M113.51,99.73c-1.32,0-2.39-2.05-2.39-4.57s1.07-4.57,2.39-4.57h14.44c1.32,0,2.39,2.05,2.39,4.57s-1.07,4.57-2.39,4.57h-14.44Z"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<ellipse cx="113.51" cy="95.16" rx="2.39" ry="4.57"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<g>
<g>
<line x1="127.88" y1="200.38" x2="127.88" y2="203.88"
style="fill:none; stroke:#39b54a; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="127.88" y1="205.38" x2="127.88" y2="218.16"
style="fill:none; stroke:#39b54a; stroke-dasharray:0 0 0 0 5.26 1.5 5.26 1.5; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="127.88" y1="218.92" x2="127.88" y2="222.42"
style="fill:none; stroke:#39b54a; stroke-miterlimit:10; stroke-width:2px;" />
</g>
<polyline points="122.99 205.33 127.88 199.28 132.72 205.33"
style="fill:none; stroke:#39b54a; stroke-miterlimit:10; stroke-width:2px;" />
</g>
<g>
<g>
<line x1="95.86" y1="94.9" x2="92.36" y2="94.9"
style="fill:none; stroke:#39b54a; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="90.8" y1="94.9" x2="77.59" y2="94.9"
style="fill:none; stroke:#39b54a; stroke-dasharray:0 0 0 0 5.44 1.55 5.44 1.55; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="76.81" y1="94.9" x2="56.6" y2="94.9"
style="fill:none; stroke:#39b54a; stroke-dasharray:0 0 0 0 0 0 5.44 1.55 5.44 1.55 5.44 1.55; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="55.82" y1="94.9" x2="52.32" y2="94.9"
style="fill:none; stroke:#39b54a; stroke-miterlimit:10; stroke-width:2px;" />
</g>
<polyline points="90.9 90 96.95 94.9 90.9 99.73"
style="fill:none; stroke:#39b54a; stroke-miterlimit:10; stroke-width:2px;" />
</g>
<path
d="M111.84,93.61c-5.44,.15-10.02,3.72-13.85,7.24-2.01,1.85-3.9,3.81-5.83,5.74s-4.16,3.88-6.06,6.02c-4.2,4.74-7.48,10.2-10.3,15.85-2.6,5.24-5.32,10.43-7.5,15.87-2.39,5.97-3.72,12.19-4.38,18.58-.1,1.01,.94,1.88,1.88,1.88,1.1,0,1.77-.86,1.88-1.88,.56-5.4,1.68-10.7,3.56-15.79s4.27-9.66,6.62-14.38c2.66-5.35,5.4-10.67,9.12-15.37,3.31-4.18,7.41-7.76,11.19-11.51s8.22-8.36,13.67-8.51c2.41-.07,2.42-3.82,0-3.75h0Z"
style="fill:#231f20;" />
<path
d="M59.12,231.43c2.05,17.35-4.54,34.73-17.73,46.21-3.46,3.02-7.33,5.53-11.45,7.56-2.17,1.06-.27,4.3,1.89,3.24,16.06-7.89,27.69-23.39,30.62-41.06,.88-5.28,1.04-10.63,.41-15.94-.12-1.01-.78-1.88-1.88-1.88-.92,0-1.99,.86-1.88,1.88h0Z"
style="fill:#231f20;" />
<path
d="M103.49,195.11c-7.6,6.84-13.89,15.16-18.3,24.39-2.34,4.9-4.19,10.04-7.16,14.61s-6.89,8.75-10.54,12.93c-4.48,5.13-8.96,10.26-13.44,15.38-1.58,1.81,1.06,4.47,2.65,2.65,3.93-4.5,7.87-9.01,11.8-13.51,3.72-4.25,7.58-8.42,10.96-12.96s5.44-9.33,7.66-14.32c2.1-4.74,4.55-9.28,7.51-13.54,3.31-4.76,7.2-9.1,11.52-12.98,1.8-1.62-.86-4.26-2.65-2.65h0Z"
style="fill:#231f20;" />
<polyline points="117.33 160.89 105.01 177.76 136.71 177.76"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="118.19" y1="163.9" x2="108.3" y2="177.3"
style="fill:none; stroke:#231f20; stroke-linecap:round; stroke-miterlimit:10; stroke-width:2px;" />
</svg>

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 303.91 128.94">
<polygon
points="167.2 14.19 171.09 20.83 167.49 22.75 163.59 16.12 152.92 21.83 151.59 19.59 162.28 13.87 158.38 7.24 161.99 5.31 165.88 11.95 176.56 6.23 177.87 8.48 167.2 14.19"
style="fill:#be1e2d;" />
<polygon
points="277.18 14.19 281.07 20.83 277.47 22.75 273.57 16.12 262.9 21.83 261.58 19.59 272.26 13.87 268.36 7.24 271.97 5.31 275.86 11.95 286.55 6.23 287.86 8.48 277.18 14.19"
style="fill:#be1e2d;" />
<polygon
points="234.48 71.98 238.37 78.62 234.77 80.55 230.87 73.91 220.2 79.62 218.88 77.38 229.56 71.67 225.66 65.03 229.27 63.1 233.16 69.74 243.85 64.02 245.15 66.27 234.48 71.98"
style="fill:#be1e2d;" />
<polygon
points="200.71 41.95 204.59 48.59 200.99 50.51 197.09 43.88 186.42 49.59 185.1 47.35 195.78 41.63 191.88 35 195.5 33.07 199.38 39.71 210.07 33.99 211.38 36.24 200.71 41.95"
style="fill:#be1e2d;" />
<polyline points="112.27 66.96 118.93 76.72 136.87 63.1"
style="fill:none; stroke:#00a651; stroke-miterlimit:10; stroke-width:4px;" />
<polygon points="302.41 16.76 239.77 99.53 94.07 99.53 94.07 84.27 156.71 1.5 302.41 1.5 302.41 16.76"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<polyline points="302.41 1.5 239.77 84.27 94.07 84.27"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="239.77" y1="84.27" x2="239.77" y2="99.53"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<polygon points="60.79 103.89 42.96 127.44 1.5 127.44 1.5 116.1 19.33 92.55 60.79 92.55 60.79 103.89"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<polyline points="60.79 92.55 42.96 116.1 1.5 116.1"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="42.96" y1="116.1" x2="42.96" y2="127.44"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<ellipse cx="49.13" cy="97.11" rx="3.83" ry="1.56" style="fill:none; stroke:#231f20; stroke-miterlimit:10;" />
<circle cx="21.34" cy="121.77" r="3.12" style="fill:none; stroke:#231f20; stroke-miterlimit:10;" />
<g>
<polygon points="34.63 102.43 31.5 99.01 29.54 101.63 32.67 105.05 34.63 102.43" style="fill:#bcbec0;" />
<polygon points="31.52 106.57 28.39 103.16 26.42 105.77 29.56 109.19 31.52 106.57" style="fill:#bcbec0;" />
<polygon points="27.82 111.51 28.41 110.72 25.28 107.3 22.12 111.51 25.2 111.2 27.82 111.51"
style="fill:#bcbec0;" />
<polygon points="38.61 97.14 32.91 97.14 32.65 97.49 35.78 100.91 38.61 97.14" style="fill:#bcbec0;" />
</g>
<g>
<line x1="93.77" y1="75.66" x2="91.3" y2="76.07"
style="fill:none; stroke:#a7a9ac; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="87.94" y1="76.63" x2="71.68" y2="79.35"
style="fill:none; stroke:#a7a9ac; stroke-dasharray:0 0 0 0 5.68 3.41 5.68 3.41; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="70" y1="79.64" x2="44.78" y2="83.86"
style="fill:none; stroke:#a7a9ac; stroke-dasharray:0 0 0 0 0 0 5.68 3.41 5.68 3.41 5.68 3.41; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="43.1" y1="84.14" x2="40.63" y2="84.55"
style="fill:none; stroke:#a7a9ac; stroke-miterlimit:10; stroke-width:3px;" />
</g>
<polyline points="82.19 71.95 93.77 75.66 85.96 83.49"
style="fill:none; stroke:#a7a9ac; stroke-miterlimit:10; stroke-width:3px;" />
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 326.35 123.59">
<polygon points="324.85 16.76 262.21 99.53 116.51 99.53 116.51 84.27 179.15 1.5 324.85 1.5 324.85 16.76"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<polygon points="206.56 67.29 185.57 36.09 197.9 27.68 210.04 45.9 256.99 10.26 266.02 22.15 206.56 67.29"
style="fill:#00a651;" />
<polyline points="324.85 1.5 262.21 84.27 116.51 84.27"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="262.21" y1="84.27" x2="262.21" y2="99.53"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<g>
<line x1="159.81" y1="65.69" x2="157.36" y2="66.17"
style="fill:none; stroke:#a7a9ac; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="154.33" y1="66.76" x2="139.7" y2="69.61"
style="fill:none; stroke:#a7a9ac; stroke-dasharray:0 0 0 0 5.14 3.08 5.14 3.08; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="138.19" y1="69.91" x2="67.04" y2="83.78"
style="fill:none; stroke:#a7a9ac; stroke-dasharray:0 0 0 0 0 0 5.14 3.08 5.14 3.08 5.14 3.08; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="65.53" y1="84.07" x2="63.07" y2="84.55"
style="fill:none; stroke:#a7a9ac; stroke-miterlimit:10; stroke-width:3px;" />
</g>
<polyline points="151.51 61.52 163.08 65.23 155.28 73.06"
style="fill:none; stroke:#a7a9ac; stroke-miterlimit:10; stroke-width:3px;" />
<g>
<g>
<polygon
points="60.79 91.08 60.79 98.53 42.96 122.09 42.96 110.74 47.63 104.58 48.03 104.56 48.04 106.86 59.98 91.08 60.79 91.08"
style="fill:#fff;" />
<polygon
points="28.92 90.2 60.79 90.2 60.79 91.08 59.98 91.08 48.04 106.86 48.03 104.56 47.63 104.58 47.44 104.05 19.03 104.05 19.03 103.6 28.92 90.2"
style="fill:#8dc63f;" />
<polygon
points="47.44 104.05 47.63 104.58 42.96 110.74 21.34 110.74 1.5 110.74 19.33 87.19 28.06 87.19 15.74 104.05 19.03 104.05 47.44 104.05"
style="fill:#ed1c24;" />
<path d="M42.96,110.74v11.35H21.34v-2.56c1.73,0,3.12-1.39,3.12-3.11s-1.39-3.12-3.12-3.12v-2.56h21.62Z"
style="fill:#fff;" />
<path
d="M21.34,113.3c1.73,0,3.12,1.39,3.12,3.12s-1.39,3.11-3.12,3.11-3.11-1.39-3.11-3.11,1.39-3.12,3.11-3.12Z"
style="fill:#fff;" />
<path d="M21.34,119.53v2.56H1.5v-11.35H21.34v2.56c-1.72,0-3.11,1.39-3.11,3.12s1.39,3.11,3.11,3.11Z"
style="fill:#fff;" />
<polygon points="15.74 104.05 28.06 87.19 28.91 87.19 28.92 90.2 19.03 103.6 19.03 104.05 15.74 104.05"
style="fill:#fff;" />
</g>
<g>
<polygon
points="60.79 91.08 60.79 98.53 42.96 122.09 21.34 122.09 1.5 122.09 1.5 110.74 19.33 87.19 28.06 87.19 28.91 87.19 28.92 90.2 60.79 90.2 60.79 91.08"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<polyline points="59.98 91.08 48.04 106.86 48.03 104.56 47.63 104.58 42.96 110.74 21.34 110.74 1.5 110.74"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="42.96" y1="110.74" x2="42.96" y2="122.09"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<path
d="M21.34,113.3c1.73,0,3.12,1.39,3.12,3.12s-1.39,3.11-3.12,3.11-3.11-1.39-3.11-3.11,1.39-3.12,3.11-3.12Z"
style="fill:none; stroke:#231f20; stroke-miterlimit:10;" />
<polyline points="28.06 87.19 15.74 104.05 19.03 104.05 47.44 104.05"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="28.92" y1="90.2" x2="19.03" y2="103.6"
style="fill:none; stroke:#231f20; stroke-linecap:round; stroke-miterlimit:10; stroke-width:2px;" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -0,0 +1,115 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 328.41 256.15">
<g>
<polygon
points="326.91 163.14 264.27 245.91 118.57 245.91 118.57 230.65 181.21 147.88 326.91 147.88 326.91 163.14"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<polyline points="326.91 147.88 264.27 230.65 118.57 230.65"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="264.27" y1="230.65" x2="264.27" y2="245.91"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
</g>
<g>
<polygon points="111.56 197.79 93.74 221.34 52.27 221.34 52.27 210 70.1 186.45 111.56 186.45 111.56 197.79"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<polyline points="111.56 186.45 93.74 210 52.27 210"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="93.74" y1="210" x2="93.74" y2="221.34"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<ellipse cx="99.9" cy="191.01" rx="3.83" ry="1.56" style="fill:none; stroke:#231f20; stroke-miterlimit:10;" />
<circle cx="72.12" cy="215.67" r="3.12" style="fill:none; stroke:#231f20; stroke-miterlimit:10;" />
<g>
<polygon points="85.41 196.33 82.28 192.91 80.31 195.53 83.44 198.95 85.41 196.33"
style="fill:#2bb673; opacity:.42;" />
<polygon points="82.3 200.48 79.16 197.06 77.2 199.68 80.33 203.09 82.3 200.48"
style="fill:#2bb673; opacity:.42;" />
<polygon points="78.59 205.41 79.19 204.62 76.05 201.2 72.89 205.41 75.97 205.1 78.59 205.41"
style="fill:#2bb673; opacity:.42;" />
<polygon points="89.38 191.04 83.68 191.04 83.42 191.39 86.56 194.81 89.38 191.04"
style="fill:#2bb673; opacity:.42;" />
</g>
</g>
<g>
<path
d="M69.35,223.89c-.57,.69-1.44,1.13-2.4,1.13-1.72,0-3.12-1.4-3.12-3.12,0-.71,.24-1.36,.63-1.88l5.79-6.56c.56-.56,1.34-.91,2.2-.91,1.72,0,3.12,1.4,3.12,3.12,0,.91-.39,1.72-1,2.29l-5.22,5.93Z"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10;" />
<path
d="M70.06,221.91c0,.75-.27,1.45-.71,1.99-.57,.69-1.44,1.13-2.4,1.13-1.72,0-3.12-1.4-3.12-3.12,0-.71,.24-1.36,.63-1.88,.57-.75,1.47-1.23,2.48-1.23,1.72,0,3.12,1.4,3.12,3.12Z"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10;" />
</g>
<g>
<polygon
points="163.4 164.83 158.3 166.52 153.19 164.83 153.19 109.62 152.06 107.91 152.06 60.47 164.53 60.47 164.53 107.91 163.4 109.62 163.4 164.83"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="153.19" y1="109.62" x2="163.4" y2="109.62"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="153.19" y1="164.09" x2="163.4" y2="159.3"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="153.19" y1="158.09" x2="163.4" y2="153.3"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="153.19" y1="152.07" x2="163.4" y2="147.28"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="153.19" y1="146.09" x2="163.4" y2="141.31"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="153.19" y1="140.07" x2="163.4" y2="135.28"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="153.19" y1="133.87" x2="163.4" y2="129.08"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="153.19" y1="127.85" x2="163.4" y2="123.06"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="153.19" y1="121.87" x2="163.4" y2="117.08"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="153.19" y1="115.85" x2="163.4" y2="111.06"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
</g>
<path d="M190.21,0V57.54c0,2.23-1.82,4.05-4.05,4.05h-56.36c-2.23,0-4.05-1.82-4.05-4.05V0"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<rect x="146.28" y="61.6" width="24.04" height="24.04"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<rect x="142.61" y="85.64" width="31.37" height="19.04"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="154.82" y1="85.64" x2="154.82" y2="104.68"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="168.85" y1="85.64" x2="168.85" y2="104.68"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<ellipse cx="148.67" cy="95.16" rx="2.39" ry="4.57"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<path
d="M71.21,99.73c-1.32,0-2.39-2.05-2.39-4.57s1.07-4.57,2.39-4.57h14.44c1.32,0,2.39,2.05,2.39,4.57s-1.07,4.57-2.39,4.57h-14.44Z"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<ellipse cx="71.21" cy="95.16" rx="2.39" ry="4.57"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<g>
<g>
<line x1="94.11" y1="94.84" x2="97.61" y2="94.84"
style="fill:none; stroke:#ed1c24; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="99.16" y1="94.84" x2="112.38" y2="94.84"
style="fill:none; stroke:#ed1c24; stroke-dasharray:0 0 0 0 5.44 1.55 5.44 1.55; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="113.16" y1="94.84" x2="133.36" y2="94.84"
style="fill:none; stroke:#ed1c24; stroke-dasharray:0 0 0 0 0 0 5.44 1.55 5.44 1.55 5.44 1.55; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="134.14" y1="94.84" x2="137.64" y2="94.84"
style="fill:none; stroke:#ed1c24; stroke-miterlimit:10; stroke-width:2px;" />
</g>
<polyline points="99.06 99.73 93.02 94.84 99.06 90"
style="fill:none; stroke:#ed1c24; stroke-miterlimit:10; stroke-width:2px;" />
</g>
<g>
<g>
<line x1="116.95" y1="190.46" x2="120.38" y2="189.78"
style="fill:none; stroke:#ed1c24; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="121.44" y1="189.58" x2="130.44" y2="187.81"
style="fill:none; stroke:#ed1c24; stroke-dasharray:0 0 0 0 3.78 1.08 3.78 1.08; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="130.97" y1="187.71" x2="144.73" y2="185"
style="fill:none; stroke:#ed1c24; stroke-dasharray:0 0 0 0 0 0 3.78 1.08 3.78 1.08 3.78 1.08; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="145.26" y1="184.9" x2="148.7" y2="184.23"
style="fill:none; stroke:#ed1c24; stroke-miterlimit:10; stroke-width:2px;" />
</g>
<polyline points="122.75 194.3 115.88 190.67 120.88 184.75"
style="fill:none; stroke:#ed1c24; stroke-miterlimit:10; stroke-width:2px;" />
</g>
<path
d="M69.9,93.3c-9.07-.24-17.32,4.41-24.11,10.04s-11.88,12.04-15.84,19.44c-3.11,5.81-5.51,11.98-5.9,18.6-.35,5.97,.4,12,1.35,17.89,2.21,13.7,5.99,27.09,8.74,40.68,1.18,5.8,2.23,11.68,2.47,17.61,.23,5.59-.33,11.4-3.15,16.41-2.42,4.3-6.54,6.35-11.01,7.98-5.9,2.15-11.79,4.15-17.12,7.56-1.66,1.06-3.24,2.24-4.78,3.47-.8,.64-.65,1.98,0,2.65,.77,.79,1.87,.63,2.65,0,5.19-4.16,11.12-6.84,17.35-9.03,4.73-1.67,9.74-3.29,13.34-6.97,4.21-4.31,5.86-10.66,6.38-16.5,.48-5.48-.24-11.05-1.1-16.46-2.14-13.43-5.87-26.56-8.58-39.87-1.26-6.18-2.38-12.42-2.75-18.72-.32-5.39,0-10.38,1.81-15.46,2.77-7.7,7.16-14.85,12.71-20.85s12.9-11.91,21.18-14c2.09-.53,4.2-.76,6.36-.7,2.41,.06,2.41-3.69,0-3.75h0Z"
style="fill:#231f20;" />
<path
d="M64.5,221.06c-1.88,3.18-2.66,6.86-3.58,10.4-.78,3.05-1.59,6.62-4.02,8.83-1.32,1.2-3.18,1.8-4.87,2.26-2.03,.56-4.11,.84-6.21,.96-4.68,.27-9.37-.13-14.04-.35-5.05-.24-10.18-.31-15.11,.94-2.34,.59-1.35,4.21,1,3.62,9.17-2.32,18.84,.08,28.16-.46,4.16-.24,8.99-.9,12.5-3.33,3.09-2.14,4.57-5.69,5.59-9.17,1.15-3.94,1.71-8.22,3.82-11.8,1.23-2.08-2.01-3.97-3.24-1.89h0Z"
style="fill:#231f20;" />
</svg>

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@@ -0,0 +1,134 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 328.41 256.15">
<g>
<g>
<polygon
points="111.57 190.34 111.57 197.79 93.74 221.35 93.74 210.01 98.41 203.84 98.81 203.83 98.82 206.12 110.76 190.34 111.57 190.34"
style="fill:#fff;" />
<polygon
points="98.22 203.31 69.81 203.31 69.81 202.86 79.7 189.46 111.57 189.46 111.57 190.34 110.76 190.34 98.82 206.12 98.81 203.83 98.41 203.84 98.22 203.31"
style="fill:#8dc63f;" />
<polygon
points="98.22 203.31 98.41 203.84 93.74 210.01 72.12 210.01 52.28 210.01 70.11 186.45 78.83 186.45 66.52 203.31 69.81 203.31 98.22 203.31"
style="fill:#ed1c24;" />
<path d="M93.74,210.01v11.34h-21.62v-2.56c1.72,0,3.12-1.39,3.12-3.11s-1.4-3.12-3.12-3.12v-2.55h21.62Z"
style="fill:#fff;" />
<path
d="M72.12,212.56c1.72,0,3.12,1.39,3.12,3.12s-1.4,3.11-3.12,3.11-3.12-1.39-3.12-3.11,1.4-3.12,3.12-3.12Z"
style="fill:#fff;" />
<path d="M72.12,218.79v2.56h-19.84v-11.34h19.84v2.55c-1.72,0-3.12,1.39-3.12,3.12s1.4,3.11,3.12,3.11Z"
style="fill:#fff;" />
<polygon points="79.7 189.46 69.81 202.86 69.81 203.31 66.52 203.31 78.83 186.45 79.68 186.45 79.7 189.46"
style="fill:#fff;" />
</g>
<g>
<polygon
points="111.57 190.34 111.57 197.79 93.74 221.35 72.12 221.35 52.28 221.35 52.28 210.01 70.11 186.45 78.83 186.45 79.68 186.45 79.7 189.46 111.57 189.46 111.57 190.34"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<polyline
points="110.76 190.34 98.82 206.12 98.81 203.83 98.41 203.84 93.74 210.01 72.12 210.01 52.28 210.01"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="93.74" y1="210.01" x2="93.74" y2="221.35"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<path
d="M72.12,212.56c1.72,0,3.12,1.39,3.12,3.12s-1.4,3.11-3.12,3.11-3.12-1.39-3.12-3.11,1.4-3.12,3.12-3.12Z"
style="fill:none; stroke:#231f20; stroke-miterlimit:10;" />
<polyline points="78.83 186.45 66.52 203.31 69.81 203.31 98.22 203.31"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="79.7" y1="189.46" x2="69.81" y2="202.86"
style="fill:none; stroke:#231f20; stroke-linecap:round; stroke-miterlimit:10; stroke-width:2px;" />
</g>
</g>
<g>
<polygon
points="326.91 163.14 264.27 245.91 118.57 245.91 118.57 230.65 181.21 147.88 326.91 147.88 326.91 163.14"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<polyline points="326.91 147.88 264.27 230.65 118.57 230.65"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="264.27" y1="230.65" x2="264.27" y2="245.91"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
</g>
<g>
<path
d="M69.35,223.89c-.57,.69-1.44,1.13-2.4,1.13-1.72,0-3.12-1.4-3.12-3.12,0-.71,.24-1.36,.63-1.88l5.79-6.56c.56-.56,1.34-.91,2.2-.91,1.72,0,3.12,1.4,3.12,3.12,0,.91-.39,1.72-1,2.29l-5.22,5.93Z"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10;" />
<path
d="M70.06,221.91c0,.75-.27,1.45-.71,1.99-.57,.69-1.44,1.13-2.4,1.13-1.72,0-3.12-1.4-3.12-3.12,0-.71,.24-1.36,.63-1.88,.57-.75,1.47-1.23,2.48-1.23,1.72,0,3.12,1.4,3.12,3.12Z"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10;" />
</g>
<g>
<polygon
points="163.4 164.83 158.3 166.52 153.19 164.83 153.19 109.62 152.06 107.91 152.06 60.47 164.53 60.47 164.53 107.91 163.4 109.62 163.4 164.83"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="153.19" y1="109.62" x2="163.4" y2="109.62"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="153.19" y1="164.09" x2="163.4" y2="159.3"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="153.19" y1="158.09" x2="163.4" y2="153.3"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="153.19" y1="152.07" x2="163.4" y2="147.28"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="153.19" y1="146.09" x2="163.4" y2="141.31"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="153.19" y1="140.07" x2="163.4" y2="135.28"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="153.19" y1="133.87" x2="163.4" y2="129.08"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="153.19" y1="127.85" x2="163.4" y2="123.06"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="153.19" y1="121.87" x2="163.4" y2="117.08"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="153.19" y1="115.85" x2="163.4" y2="111.06"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
</g>
<path d="M190.21,0V57.54c0,2.23-1.82,4.05-4.05,4.05h-56.36c-2.23,0-4.05-1.82-4.05-4.05V0"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<rect x="146.28" y="61.6" width="24.04" height="24.04"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<rect x="142.61" y="85.64" width="31.37" height="19.04"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="154.82" y1="85.64" x2="154.82" y2="104.68"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<line x1="168.85" y1="85.64" x2="168.85" y2="104.68"
style="fill:none; stroke:#231f20; stroke-miterlimit:10; stroke-width:3px;" />
<ellipse cx="148.67" cy="95.16" rx="2.39" ry="4.57"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<path
d="M71.21,99.73c-1.32,0-2.39-2.05-2.39-4.57s1.07-4.57,2.39-4.57h14.44c1.32,0,2.39,2.05,2.39,4.57s-1.07,4.57-2.39,4.57h-14.44Z"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<ellipse cx="71.21" cy="95.16" rx="2.39" ry="4.57"
style="fill:#fff; stroke:#231f20; stroke-miterlimit:10; stroke-width:2px;" />
<g>
<g>
<line x1="94.11" y1="94.84" x2="97.61" y2="94.84"
style="fill:none; stroke:#ed1c24; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="99.16" y1="94.84" x2="112.38" y2="94.84"
style="fill:none; stroke:#ed1c24; stroke-dasharray:0 0 0 0 5.44 1.55 5.44 1.55; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="113.16" y1="94.84" x2="133.36" y2="94.84"
style="fill:none; stroke:#ed1c24; stroke-dasharray:0 0 0 0 0 0 5.44 1.55 5.44 1.55 5.44 1.55; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="134.14" y1="94.84" x2="137.64" y2="94.84"
style="fill:none; stroke:#ed1c24; stroke-miterlimit:10; stroke-width:2px;" />
</g>
<polyline points="99.06 99.73 93.02 94.84 99.06 90"
style="fill:none; stroke:#ed1c24; stroke-miterlimit:10; stroke-width:2px;" />
</g>
<g>
<g>
<line x1="116.95" y1="190.46" x2="120.38" y2="189.78"
style="fill:none; stroke:#ed1c24; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="121.44" y1="189.58" x2="130.44" y2="187.81"
style="fill:none; stroke:#ed1c24; stroke-dasharray:0 0 0 0 3.78 1.08 3.78 1.08; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="130.97" y1="187.71" x2="144.73" y2="185"
style="fill:none; stroke:#ed1c24; stroke-dasharray:0 0 0 0 0 0 3.78 1.08 3.78 1.08 3.78 1.08; stroke-miterlimit:10; stroke-width:2px;" />
<line x1="145.26" y1="184.9" x2="148.7" y2="184.23"
style="fill:none; stroke:#ed1c24; stroke-miterlimit:10; stroke-width:2px;" />
</g>
<polyline points="122.75 194.3 115.88 190.67 120.88 184.75"
style="fill:none; stroke:#ed1c24; stroke-miterlimit:10; stroke-width:2px;" />
</g>
<path
d="M69.9,93.3c-9.07-.24-17.32,4.41-24.11,10.04s-11.88,12.04-15.84,19.44c-3.11,5.81-5.51,11.98-5.9,18.6-.35,5.97,.4,12,1.35,17.89,2.21,13.7,5.99,27.09,8.74,40.68,1.18,5.8,2.23,11.68,2.47,17.61,.23,5.59-.33,11.4-3.15,16.41-2.42,4.3-6.54,6.35-11.01,7.98-5.9,2.15-11.79,4.15-17.12,7.56-1.66,1.06-3.24,2.24-4.78,3.47-.8,.64-.65,1.98,0,2.65,.77,.79,1.87,.63,2.65,0,5.19-4.16,11.12-6.84,17.35-9.03,4.73-1.67,9.74-3.29,13.34-6.97,4.21-4.31,5.86-10.66,6.38-16.5,.48-5.48-.24-11.05-1.1-16.46-2.14-13.43-5.87-26.56-8.58-39.87-1.26-6.18-2.38-12.42-2.75-18.72-.32-5.39,0-10.38,1.81-15.46,2.77-7.7,7.16-14.85,12.71-20.85s12.9-11.91,21.18-14c2.09-.53,4.2-.76,6.36-.7,2.41,.06,2.41-3.69,0-3.75h0Z"
style="fill:#231f20;" />
<path
d="M64.5,221.06c-1.88,3.18-2.66,6.86-3.58,10.4-.78,3.05-1.59,6.62-4.02,8.83-1.32,1.2-3.18,1.8-4.87,2.26-2.03,.56-4.11,.84-6.21,.96-4.68,.27-9.37-.13-14.04-.35-5.05-.24-10.18-.31-15.11,.94-2.34,.59-1.35,4.21,1,3.62,9.17-2.32,18.84,.08,28.16-.46,4.16-.24,8.99-.9,12.5-3.33,3.09-2.14,4.57-5.69,5.59-9.17,1.15-3.94,1.71-8.22,3.82-11.8,1.23-2.08-2.01-3.97-3.24-1.89h0Z"
style="fill:#231f20;" />
</svg>

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

@@ -0,0 +1,46 @@
@use "sass:color";
@use "@material/theme/color-palette";
// Svelte Colors!
@use "@material/theme/index" as theme with (
$primary: #0078e7,
$secondary: #676778,
$surface: #fff,
$background: #fff,
$error: color-palette.$red-900,
$on-surface: #777
);
@use "@material/elevation/mdc-elevation";
@use "@material/list";
@include list.deprecated-core-styles;
:root {
--mdc-theme-text-primary-on-background: #777;
.mdc-dialog .mdc-dialog__container {
transition: margin-bottom 0.5s;
}
.mdc-dialog .mdc-dialog__content {
color: #777;
}
.mdc-dialog .mdc-dialog__title {
color: #777;
font-weight: bold;
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Firefox */
input[type="number"] {
-moz-appearance: textfield;
}
}

View File

@@ -0,0 +1,12 @@
@use 'sass:color';
@use '@material/theme/color-palette';
// Svelte Colors! (Dark Theme)
@use '@material/theme/index' as theme with (
$primary: #ff3e00,
$secondary: color.scale(#676778, $whiteness: -10%),
$surface: color.adjust(color-palette.$grey-900, $blue: +4),
$background: #000,
$error: color-palette.$red-700
);

View File

@@ -0,0 +1,2 @@
/// <reference types="svelte" />
/// <reference types="vite/client" />

View File

@@ -0,0 +1,7 @@
import sveltePreprocess from "svelte-preprocess";
export default {
// Consult https://github.com/sveltejs/svelte-preprocess
// for more information about preprocessors
preprocess: sveltePreprocess()
};

View File

@@ -0,0 +1,27 @@
{
"extends": "@tsconfig/svelte/tsconfig.json",
"compilerOptions": {
"target": "esnext",
"useDefineForClassFields": true,
"module": "esnext",
"resolveJsonModule": true,
"baseUrl": ".",
"paths": {
"$lib/*": ["src/lib/*"],
"$components/*": ["src/components/*"],
"$dialogs/*": ["src/dialogs/*"]
},
/**
* Typecheck JS in `.svelte` and `.js` files by default.
* Disable checkJs if you'd like to use dynamic types in JS.
* Note that setting allowJs false does not prevent the use
* of JS in `.svelte` files.
*/
"allowJs": true,
"checkJs": true,
"isolatedModules": true,
"moduleSuffixes": [".svelte", ""]
},
"include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"],
"references": [{ "path": "./tsconfig.node.json" }]
}

View File

@@ -0,0 +1,8 @@
{
"compilerOptions": {
"composite": true,
"module": "esnext",
"moduleResolution": "node"
},
"include": ["vite.config.ts"]
}

View File

@@ -0,0 +1,26 @@
import { defineConfig } from "vite";
import { svelte } from "@sveltejs/vite-plugin-svelte";
import { resolve } from "path";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
svelte()
],
resolve: {
alias: {
$lib: resolve("./src/lib"),
$dialogs: resolve("./src/dialogs"),
$components: resolve("./src/components")
}
},
build: {
target: "chrome60",
lib: {
entry: resolve(__dirname, "src/main.ts"),
name: "SvelteComponents",
formats: [ "iife" ],
fileName: () => "index.js"
}
}
});