Convert the whole site to use Pelican instead of Jekyll
1
content/.well-known/dat
Normal file
@@ -0,0 +1 @@
|
||||
dat://f2f8fde752df4c5c69506b22fbcc62fd572829c9a72e5053c15d13170b731461
|
88
content/.well-known/keybase.txt
Normal file
@@ -0,0 +1,88 @@
|
||||
==================================================================
|
||||
https://keybase.io/gergelypolonkai
|
||||
--------------------------------------------------------------------
|
||||
|
||||
I hereby claim:
|
||||
|
||||
* I am an admin of https://gergely.polonkai.eu
|
||||
* I am gergelypolonkai (https://keybase.io/gergelypolonkai) on keybase.
|
||||
* I have a public key with fingerprint 13D6 0476 B35A FCA8 BC01 3A32 F42B BA58 B074 0C4C
|
||||
|
||||
To do so, I am signing this object:
|
||||
|
||||
{
|
||||
"body": {
|
||||
"key": {
|
||||
"eldest_kid": "0101ceab57f101e57c410a43bdc8d929f98285ab06539bff10fda8b753edc5f6cc910a",
|
||||
"fingerprint": "13d60476b35afca8bc013a32f42bba58b0740c4c",
|
||||
"host": "keybase.io",
|
||||
"key_id": "f42bba58b0740c4c",
|
||||
"kid": "0101ceab57f101e57c410a43bdc8d929f98285ab06539bff10fda8b753edc5f6cc910a",
|
||||
"uid": "71a6ab9599863d4b04753bed0d7f6b19",
|
||||
"username": "gergelypolonkai"
|
||||
},
|
||||
"merkle_root": {
|
||||
"ctime": 1509017295,
|
||||
"hash_meta": "d9782d9deba8b4b08e84498faa9f35ad2ebe9470bd368defd2a9810a31aa75b6",
|
||||
"seqno": 1632302
|
||||
},
|
||||
"revoke": {
|
||||
"sig_ids": [
|
||||
"17d13b369e345bc73cf3120c9a42e61ea78de28fdfbf9897780a8bb6e9f952dc0f"
|
||||
]
|
||||
},
|
||||
"service": {
|
||||
"hostname": "gergely.polonkai.eu",
|
||||
"protocol": "https:"
|
||||
},
|
||||
"type": "web_service_binding",
|
||||
"version": 1
|
||||
},
|
||||
"ctime": 1509017302,
|
||||
"expire_in": 157680000,
|
||||
"prev": "44dc7f3d5323a6c9f8b70e5276a300cd40406c53ce17cdde5613b585adc4fea9",
|
||||
"seqno": 12,
|
||||
"tag": "signature"
|
||||
}
|
||||
|
||||
which yields the signature:
|
||||
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
Version: Keybase OpenPGP v2.0.76
|
||||
Comment: https://keybase.io/crypto
|
||||
|
||||
yMPWAnicrZN9TFVlHMevgjbvQF5qOlKUDirxIpz3l2u+MKFVu3f8USQEeX3ezvV0
|
||||
4Z7bveeiqGg6c+LLiKmbQqJpCtnK8DW1NSVzBIJmKmG4MmabbCmmtykz7Dkst9z6
|
||||
s/PPOc/Z9/f9fX+f53nOxsc4nKPuZ58s+cKKc4/qbFsbcZTePXd1OQNNXM24ljN+
|
||||
MvIiFZiELa/fwIyLYTmWQwRASdHpF5EUJHIsEAWIkYo1XtM1lVclAFlZEjSoU5GO
|
||||
gQoVSSAYSbqMkEb1TA6jGwEfCQVDRsCitpyAZVZUZChIQEe0ALGcAAReF3kIgaRC
|
||||
VhFZJCJauNgM2xU0HARhkmuY9B9deEfi/Yf+f84dGbFTOCADqEmapsoCFiHNLgmQ
|
||||
YBYrugw5zRaGSSgAKglV00F9pKI6aFaYAT8wmJocppKE/BXEGzJNy2aMLMNWchKr
|
||||
sZzCaxKdE4QXeyuJBagB1hSVxxomkGai3VSiiqKm6gBoOiWGeQKJJiosxIKsYqJj
|
||||
HmgqzStwACgSlGmcMHk3YNIOssALLE8ThEiV6Sd287Dho/TCjKuM4RTMCVCQNSKI
|
||||
EkSKgHSB41mkAZEnMkeAQu15Vcc6pMQ0RVFZmgjKhAKUeIxYnXm7xm4WqjLQiLm9
|
||||
XU9jyH3CIZdEaLBgyLRMZFZQwWLLCoZdNh6rOmhXLCHQ+4+XFxoBTM8MragiobBh
|
||||
BugwVPk0OTpaDkOWBo0Q8Rq2QlJklaWP3YdUUUtRxEjRBSxRDkBGmk43mSUSr8hA
|
||||
YFmERVZkZSQJiHAKwphIMgUi0aOBkagToP0LJW1lAR/1pAADwIqECFPTdqY81jHK
|
||||
6Rg7ZrR9mRzOcYlPrtgeR8LwzLmNgwXNzf2+Ceq4aAK++cG6LeUH9u2f4QGPWh3h
|
||||
w7Wx41dtLSuoOVYSt2+b2dm+/nHfC7daEy5IRW/x0YL2xPy2lom/7Dbi6zcsO+Tc
|
||||
MyehK6nhdm2MJ++e68z4S+ndv76+5nPg/3b077sGSy7z+g7psCM9Njlzd88nsYlL
|
||||
X75dJ26/k9nblJDS1t/SXDxlyuxpO8tc7++9n93a5ahP9TQ6nj9Y0rPubsKM1Mdl
|
||||
8/JPnJ46dWDlrJw1bT+mrL4wqe5W0sm0rPQTj2BaZNJ7pVNbVo9/Jt09PWnr9Y2v
|
||||
peOtTi2DzCk6d3D4p1L51bieNSeaXuLfuHotGOXMuPmucikxv+RAc07Kxb6uvqwH
|
||||
mycOXmkI6MMfXy/+JryLG6oqTm26wXX8tunLcZXu75JOvTjwdVrWRndvU/oqvc4/
|
||||
4c9bQ+7T67scD/N6+/fWl2845Vt16fzsg9OyZh5rzPzUYn5oaOju6KlDnxUML/g+
|
||||
O/m45+LR2rzojbOvPFwEDm05Ujh/0YX985aUeRZu+6gwv78+552M6ULu5WtN1QfY
|
||||
6oF7PU2V3UbX/Vlrr2c4t2GhV+1IxhXxyRnOe8c/nH7k57nu9YlxnRM7ht6Muek+
|
||||
6mss9E76ozRSdOXhnZVdC2ImR5YVfpUxOXj+zgpvrrCzL7ph0QPfitrnPHOj/nbj
|
||||
8pjTWwae3RSI/2vH2UtjQwu3p/wNxkcCqw==
|
||||
=SRX1
|
||||
-----END PGP MESSAGE-----
|
||||
|
||||
And finally, I am proving ownership of this host by posting or
|
||||
appending to this document.
|
||||
|
||||
View my publicly-auditable identity here: https://keybase.io/gergelypolonkai
|
||||
|
||||
==================================================================
|
||||
|
25
content/blog/2011-05-12-ethical-hacking-2011.rst
Normal file
@@ -0,0 +1,25 @@
|
||||
Ethical Hacking 2012
|
||||
####################
|
||||
|
||||
:date: 2011-05-12T20:54:42Z
|
||||
:category: blog
|
||||
:tags: conference
|
||||
:url: blog/2011/5/12/ethical-hacking-2011.html
|
||||
:save_as: blog/2011/5/12/ethical-hacking-2011.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
Today I went to the Ethical Hacking conference with my boss. It was my first appearance at such
|
||||
conferences, but I hope there will be more. Although we just started to redesign our IT security
|
||||
infrastructure with a 90% clear goal, it was nice to hear that everything is vulnerable. I was
|
||||
thinking if we should sell all our IT equipments, fire all our colleagues (you know, to prevent
|
||||
social engineering), and move to the South Americas to herd llamas or sheep, so the only danger
|
||||
would be some lurking pumas or jaguars. Or I simply leave my old background image on my desktop,
|
||||
from the well-known game, which says: Trust is a weakness.
|
||||
|
||||
Anyways, the conference was really nice. We heard about the weaknesses of Android, Oracle, and
|
||||
even FireWire. They showed some demos about everything, exploited some free and commercial
|
||||
software with no problem at all. We have seen how much power the virtualisation admin has
|
||||
(although I think it can be prevented, but I’m not sure yet). However, in the end, we could see
|
||||
that the Cloud is secure (or at least it can be, in a few months or so), so I’m not totally
|
||||
pessimistic. See you next time at Hacktivity!
|
@@ -0,0 +1,75 @@
|
||||
Gentoo hardened desktop with GNOME 3 – Round one
|
||||
################################################
|
||||
|
||||
:date: 2011-05-12T20:32:41Z
|
||||
:url: blog/2011/5/12/gentoo-hardened-desktop-with-gnome-3-round-one.html
|
||||
:save_as: blog/2011/5/12/gentoo-hardened-desktop-with-gnome-3-round-one.html
|
||||
:category: blog
|
||||
:tags: gentoo,gnome3,selinux
|
||||
:author: Gergely Polonkai
|
||||
:status: published
|
||||
|
||||
After having some hard times with Ubuntu (upgrading from 10.10 to 11.04), I decided to switch back
|
||||
to my old friend, Gentoo. As I’m currently learning about Linux hardening, I decided to use the
|
||||
new SELinux profile, which supports the v2 reference policy.
|
||||
|
||||
Installation was pretty easy, using the `Gentoo x86 Handbook
|
||||
<http://www.gentoo.org/doc/hu/handbook/handbook-x86.xml>`_. This profile automatically turns on
|
||||
the ``USE=selinux`` flag (so does the old SELinux profile), but deprecated ``FEATURE=loadpolicy``
|
||||
(which is turned on by the profile, so portage will complain about it until you disable it in
|
||||
``/etc/make.conf``).
|
||||
|
||||
For the kernel, I chose ``hardened-sources-2.6.37-r7``. This seems to be recent enough for my
|
||||
security testing needs. I turned on both SELinux, PaX and grsecurity. So far, I have no problem
|
||||
with it, but I don’t have X installed yet, which will screw up things for sure.
|
||||
|
||||
After having those hard times with Ubuntu mentioned before, I decided not to install Grub2 yet, as
|
||||
it renders things unusable (eg. my Windows 7 installation, which I sometimes need at the office).
|
||||
So I installed Grub 0.97 (this is the only version marked as stable, as I remember), touched
|
||||
``/.autorelabel``, and reboot.
|
||||
|
||||
My first mistake was using an UUID as the root device on the kernel parameter list (I don’t want
|
||||
to list all the small mistakes like forgetting to include to correct SATA driver from my kernel
|
||||
and such). Maybe I was lame, but after including ``/dev/sda5`` instead of the UUID thing, it
|
||||
worked like…
|
||||
|
||||
Well, charm would not be the good word. For example, I forgot to install the ``lvm2`` package, so
|
||||
nothing was mounted except my root partition. After I installed it with the install CD, I assumed
|
||||
everything will be all right, but I was wrong.
|
||||
|
||||
``udev`` and LVM is a critical point in a hardened environment. ``udev`` itself doesn’t want to
|
||||
work without the ``CONFIG_DEVFS_TEMPFS=y`` kernel option, so I also had to change that. It seemed
|
||||
that it can be done without the install CD, as it compiled the kernel with no problems. However,
|
||||
when it reached the point when it compresses the kernel with gzip, it stopped with a ``Permission
|
||||
denied`` message (although it was running with root privileges).
|
||||
|
||||
The most beautiful thing in the hardened environment with Mandatory Access Control enabled is that
|
||||
root is not a real power user any more by default. You can get this kind of messages many times.
|
||||
There are many tools to debug these, I will talk about these later.
|
||||
|
||||
So, my ``gzip`` needed a fix. After digging a bit on the Internet, I found that the guilty thing
|
||||
is text relocation, which can be corrected if ``gzip`` is compiled with PIC enabled. Thus, I
|
||||
turned on ``USE=pic`` flag globally, and tried to remerge gzip. Of course it failed, as it had to
|
||||
use gzip to unpack the gzip sources. So it did when I tried to install the PaX tools and
|
||||
``gradm`` to turn these checks off. The install CD came to the rescue again, with which I
|
||||
successfully recompiled gzip, and with this new gzip, I compressed my new kernel, with which udev
|
||||
started successfully. So far, so good, let’s try to reboot!
|
||||
|
||||
Damn, LVM is still not working. So I decided to finally consult the Gentoo hardened guide. It
|
||||
says that the LVM startup scripts under ``/lib/rcscripts/…`` must be modified, so LVM will put its
|
||||
lock files under ``/etc/lvm/lock`` instead of ``/dev/.lvm``. After this step and a reboot, LVM
|
||||
worked fine (finally).
|
||||
|
||||
The next thing was the file system labelling. SELinux should automatically relabel the entire
|
||||
file system at boot time whenever it finds the ``/.autorelabel`` file. Well, in my case it didn’t
|
||||
happen. After checking the `Gentoo Hardening <http://wiki.gentoo.org/wiki/Hardened_Gentoo>`_
|
||||
docs, I realised that the ``rlpkg`` program does exactly the same (as far as I know, it is
|
||||
designed specifically for Gentoo). So I ran ``rlpkg``, and was kind of shocked. It says it will
|
||||
relabel ext2, ext3, xfs and JFS partitions. Oh great, no ext4 support? Well, consulting the
|
||||
forums and adding some extra lines to ``/etc/portage/package.keywords`` solved the problem
|
||||
(``rlpkg`` and some dependencies had to have the ``~x86`` keyword set). Thus, ``rlpkg``
|
||||
relabelled my file systems (I checked some directories with ``ls -lZ``, it seemed good for me).
|
||||
|
||||
Now it seems that everything is working fine, except the tons of audit messages. Tomorrow I will
|
||||
check them with ``audit2why`` or ``audit2allow`` to see if it is related with my SELinux lameness,
|
||||
or with a bug in the policy included with Gentoo.
|
32
content/blog/2011-05-13-zabbix-performance-tip.rst
Normal file
@@ -0,0 +1,32 @@
|
||||
Zabbix performance tip
|
||||
######################
|
||||
|
||||
:date: 2011-05-13T19:03:31Z
|
||||
:category: blog
|
||||
:tags: zabbix,monitoring
|
||||
:url: blog/2011/5/13/zabbix-performance-tip.html
|
||||
:save_as: blog/2011/5/13/zabbix-performance-tip.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
Recently I have switched from `MRTG <http://oss.oetiker.ch/mrtg/>`_ + `Cacti
|
||||
<http://www.cacti.net/>`_ + `Nagios <http://www.nagios.org/>`_ + `Gnokii
|
||||
<http://www.gnokii.org/>`_ to `Zabbix <http://www.zabbix.com/>`_, and I must say I’m more than
|
||||
satisfied with it. It can do anything the former tools did, and much more. First of all, it can
|
||||
do the same monitoring as Nagios did, but it does much more fine. It can check several parameters
|
||||
within one request, so network traffic is kept down. Also, its web front-end can generate any
|
||||
kinds of graphs from the collected data, which took Cacti away. Also, it can do SNMP queries
|
||||
(v1-v3), so querying my switches’ port states and traffic made easy, taking MRTG out of the
|
||||
picture (I know Cacti can do it either, it had historical reasons we had both tools installed).
|
||||
And the best part: it can send SMS messages via a GSM modem natively, while Nagios had to use
|
||||
Gnokii. The trade-off is, I had to install Zabbix agent on all my monitored machines, but I think
|
||||
it worths the price. I even have had to install NRPE to monitor some parameters, which can be a
|
||||
pain on Windows hosts, while Zabbix natively supports Windows, Linux and Mac OS/X.
|
||||
|
||||
So I only had to create a MySQL database (which I already had for NOD32 central management), and
|
||||
install Zabbix server. Everything went fine, until I reached about 1300 monitored parameters.
|
||||
MySQL seemed to be a bit slow on disk writes, so my Zabbix “queue” filled up in no time. After
|
||||
reading some forums, I decided to switch to PostgreSQL instead. Now it works like charm, even
|
||||
with the default Debian settings. However, I will have to add several more parameters, and my
|
||||
boss wants as many graphs as you can imagine, so I’m more than sure that I will have to fine tune
|
||||
my database later.
|
@@ -0,0 +1,26 @@
|
||||
Gentoo hardened desktop with GNOME 3 – Round two
|
||||
################################################
|
||||
|
||||
:date: 2011-05-18T10:28:14Z
|
||||
:category: blog
|
||||
:tags: gentoo,gnome3,selinux
|
||||
:url: blog/2011/5/18/gentoo-hardened-desktop-with-gnome-3-round-two.html
|
||||
:save_as: blog/2011/5/18/gentoo-hardened-desktop-with-gnome-3-round-two.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
After several hours of ``package.keywords``/``package.use`` editing and package compiling, I
|
||||
managed to install GNOME 3 on my notebook. Well, I mean, the GNOME 3 packages. Unfortunately the
|
||||
``fglrx`` driver didn’t seem to recognise my ATI Mobility M56P card, and the open source driver
|
||||
didn’t want to give me GLX support. When I finally found some clues on what should I do, I had to
|
||||
use my notebook for work, so I installed Fedora 14 on it. Then I realised that GNOME 3 is already
|
||||
included in Rawhide (Fedora 15), so I quickly downloaded and installed that instead. Now I have
|
||||
to keep this machine in a working state for a few days, so I will learn SELinux stuff in its
|
||||
native environment.
|
||||
|
||||
When I installed Fedora 14, the first AVC message popped up after about ten minutes. That was a
|
||||
good thing, as I wanted to see ``setroubleshoot`` in action. However, in Fedora 15, the AVC
|
||||
bubbles didn’t show up even after a day. I raised my left eyebrow and said that’s impossible,
|
||||
SELinux must be disabled. And it’s not! It’s even in enforcing mode! And it works just fine. I
|
||||
like it, and I hope I will be able to get the same results with Gentoo if I can get back to
|
||||
testing…
|
@@ -0,0 +1,34 @@
|
||||
Citrix XenServer 5.5 vs. Debian 5.0 upgrade to 6.0
|
||||
##################################################
|
||||
|
||||
:date: 2011-05-27T17:33:41Z
|
||||
:category: blog
|
||||
:tags: citrix-xenserver,debian
|
||||
:url: blog/2011/5/27/citrix-xenserver-vs-debian-5-0-upgrade-to-6-0.html
|
||||
:save_as: blog/2011/5/27/citrix-xenserver-vs-debian-5-0-upgrade-to-6-0.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
Few weeks ago I’ve upgraded two of our Debian based application servers from 5.0 to 6.0.
|
||||
Everything went fine, as the upgraded packages worked well with the 4.2 JBoss instances. For the
|
||||
new kernel we needed a reboot, but as the network had to be rebuilt, I postponed this reboot until
|
||||
the network changes. With the network, everything went fine again, we successfully migrated our
|
||||
mail servers behind a firewall. Also the Xen server (5.5.0, upgrade to 5.6 still has to wait for
|
||||
a week or so) revolted well with some storage disks added. But the application servers remained
|
||||
silent…
|
||||
|
||||
After checking the console, I realised that they don’t have an active console. And when I tried
|
||||
to manually start them, XenServer refused with a message regarding ``pygrub``.
|
||||
|
||||
To understand the problem, I had to understand how XenServer boots Debian. It reads the
|
||||
``grub.conf`` on the first partition’s root or ``/boot`` directory, and starts the first option,
|
||||
without asking (correct me, if I’m mistaken somewhere). However, this ``pygrub`` thing can not
|
||||
parse the new, grub2 config. This is kinda frustrating.
|
||||
|
||||
For the first step, I quickly installed a new Debian 5.0 system from my template. Then I attached
|
||||
the disks of the faulty virtual machine, and mounted all its partitions. This way I could reach
|
||||
my faulty 6.0 system with a chroot shell, from which I could install the ``grub-legacy`` package
|
||||
instead of grub, install the necessary kernel and XenServer tools (which were missing from both
|
||||
machines somehow), then halt the rescue system, and start up the original instance.
|
||||
|
||||
Next week I will do an upgrade on the XenServer to 5.6.1. I hope no such problems will occur.
|
@@ -0,0 +1,23 @@
|
||||
Oracle Database “incompatible” with Oracle Linux?
|
||||
#################################################
|
||||
|
||||
:date: 2011-05-27T17:53:31Z
|
||||
:category: blog
|
||||
:tags: linux,oracle
|
||||
:url: blog/2011/5/27/oracle-database-incompatible-with-oracle-linux.html
|
||||
:save_as: blog/2011/5/27/oracle-database-incompatible-with-oracle-linux.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
Today I gave a shot to install `Oracle Linux
|
||||
<http://www.oracle.com/us/technologies/linux/overview/index.html>`_. I thought I could easily
|
||||
install an Oracle DBA on it. Well, I was naive.
|
||||
|
||||
As only the 5.2 version is supported by XenServer 5.5, I downloaded that version of Oracle Linux.
|
||||
Installing it was surprisingly fast and easy, it asked almost nothing, and booted without any
|
||||
problems.
|
||||
|
||||
After this came the DBA, 10.2, which bloated an error message in my face saying that this is an
|
||||
unsupported version of Linux. Bah.
|
||||
|
||||
Is it only me, or is it really strange that Oracle doesn’t support their own distro?
|
@@ -0,0 +1,29 @@
|
||||
Proxy only non-existing files with mod_proxy and mod_rewrite
|
||||
############################################################
|
||||
|
||||
:date: 2011-06-10T14:20:43Z
|
||||
:category: blog
|
||||
:tags: apache
|
||||
:url: blog/2011/6/10/proxy-only-non-existing-files-with-mod-proxy-and-mod-rewrite.html
|
||||
:save_as: blog/2011/6/10/proxy-only-non-existing-files-with-mod-proxy-and-mod-rewrite.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
Today I got an interesting task. I had to upload some pdf documents to a site. The domain is
|
||||
ours, but we don’t have access to the application server that is hosting the page yet. Until we
|
||||
get it in our hands, I did a trick.
|
||||
|
||||
I enabled `mod_rewrite`, `mod_proxy` and `mod_proxy_http`, then added the following lines to my
|
||||
apache config:
|
||||
|
||||
.. code-block:: apache
|
||||
|
||||
RewriteEngine on
|
||||
RewriteRule ^/$ http://172.16.72.131:8080/ [QSA,L,P]
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^/(.*) http://172.16.72.131:8080/$1 [QSA,L,P]
|
||||
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
|
||||
I’m not totally sure it’s actually secure, but it works for now.
|
26
content/blog/2011-09-18-inverse-of-sort.rst
Normal file
@@ -0,0 +1,26 @@
|
||||
Inverse of `sort`
|
||||
#################
|
||||
|
||||
:date: 2011-09-18T14:57:31Z
|
||||
:category: blog
|
||||
:tags: linux,command-line
|
||||
:url: blog/2011/9/18/inverse-of-sort.html
|
||||
:save_as: blog/2011/9/18/inverse-of-sort.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
I’m using \*NIX systems for about 14 years now, but it can still show me new things. Today I had
|
||||
to generate a bunch of random names. I’ve create a small perl script which generates permutations
|
||||
of some usual Hungarian first and last names, occasionally prefixing it with a ‘Dr.’ title or
|
||||
using double first names. For some reasons I forgot to include uniqueness check in the script.
|
||||
When I ran it in the command line, I realized the mistake, so I appended ``| sort | uniq`` to the
|
||||
command line. So I had around 200 unique names, but in alphabetical order, which was awful for my
|
||||
final goal. Thus, I tried shell commands like ``rand`` to create a random order, and when many of
|
||||
my tries failed, the idea popped in my mind (not being a native English speaker): “I don’t have to
|
||||
create »random order«, but »shuffle the list«. So I started typing ``shu``, pressed Tab in the
|
||||
Bash shell, and voilà! ``shuf`` is the winner, it does just exactly what I need:
|
||||
|
||||
**NAME**
|
||||
shuf - generate random permutations
|
||||
|
||||
Thank you, Linux Core Utils! :)
|
@@ -0,0 +1,14 @@
|
||||
Why you should always test your software with production data
|
||||
#############################################################
|
||||
|
||||
:date: 2011-12-11T12:14:51Z
|
||||
:category: blog
|
||||
:tags: development,testing,ranting
|
||||
:url: blog/2011/12/11/why-you-should-always-test-your-software-with-production-data.html
|
||||
:save_as: blog/2011/12/11/why-you-should-always-test-your-software-with-production-data.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
I’m writing a software for my company in PHP, using the Symfony 2 framework. I’ve finished all
|
||||
the work, created some sample data, it loaded perfectly. Now I put the whole thing into
|
||||
production and tried to upload the production data into it. Guess what… it didn’t load.
|
25
content/blog/2012-03-20-php-5-4-released.rst
Normal file
@@ -0,0 +1,25 @@
|
||||
PHP 5.4 released
|
||||
################
|
||||
|
||||
:date: 2012-03-20T13:31:12Z
|
||||
:category: blog
|
||||
:tags: php
|
||||
:url: blog/2012/3/20/php-5-4-released.html
|
||||
:save_as: blog/2012/3/20/php-5-4-released.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
After a long time of waiting, PHP announced 5.4 release on 1 March (also, today they announced
|
||||
that they finally migrate to Git, which is sweet from my point of view, but it doesn’t really
|
||||
matter).
|
||||
|
||||
About a year ago we became very agressive towards a developer who created our internal e-learning
|
||||
system. Their database was very insecure, and they didn’t really follow industry standards in
|
||||
many ways. Thus, we forced them to move from Windows + Apache 2.0 + PHP 5.2 + MySQL 4.0 to Debian
|
||||
Linux 6.0 + Apache 2.2 + PHP 5.3 + MySQL 5.1. It was fun (well, from our point of view), as their
|
||||
coders… well… they are not so good. The code that ran “smoothly” on the old system failed at many
|
||||
points on the new one. So they code and code, and write more code. And they still didn’t finish.
|
||||
And now 5.4 is here. Okay, I know it will take some time to get into the Debian repositories, but
|
||||
it’s here. And they removed ``register_globals``, which will kill that funny code again at so
|
||||
many points that they will soon get to rewrite the whole code to make it work. And I just sit
|
||||
here in my so-much-comfortable chair, and laugh. Am I evil?
|
29
content/blog/2012-03-27-fast-world-fast-updates.rst
Normal file
@@ -0,0 +1,29 @@
|
||||
Fast world, fast updates
|
||||
########################
|
||||
|
||||
:date: 2012-03-27T06:18:43Z
|
||||
:category: blog
|
||||
:tags: linux
|
||||
:url: blog/2012/3/27/fast-world-fast-updates.html
|
||||
:save_as: blog/2012/3/27/fast-world-fast-updates.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
We live in a fast world, that’s for sure. When I first heard about Ubuntu Linux and their goals,
|
||||
I was happy: they gave a Debian to everyone, but in different clothes. It had fresh software in
|
||||
it, and even they gave support of a kind. It was easy to install and use, even if one had no
|
||||
Linux experience before. So people liked it. I’ve even installed it on some of my servers
|
||||
because of the new package versions that came more often. Thus I got an up to date system.
|
||||
However, it had a price. After a while, security updates came more and more often, and when I had
|
||||
a new critical update every two or three days, I’ve decided to move back to Debian. Fortunately I
|
||||
did this at the time of a new release, so I didn’t really loose any features.
|
||||
|
||||
After a few years passed, even Debian is heading this very same way. But as I see, the cause is
|
||||
not the same. It seems that upstream software is hitting these bugs, and even the Debian guys
|
||||
don’t have the time to check for them. At the time of a GNOME version bump (yes, GNOME 3 is a
|
||||
really big one for the UN\*X-like OSes), when hundreds of packages need to be checked, security
|
||||
bugs show off more often. On the other hand however, Debian is releasing a new security update
|
||||
every day (I had one on each of the last three days). This, of course, is good from one point of
|
||||
view as we get a system that is more secure, but most administrators don’t have maintenance
|
||||
windows this often. I can think of some alternatives like Fedora, but do I really have to change?
|
||||
Dear fellow developers, please code more carefully instead!
|
23
content/blog/2012-06-14-wordpress-madness.rst
Normal file
@@ -0,0 +1,23 @@
|
||||
Wordpress madness
|
||||
#################
|
||||
|
||||
:date: 2012-06-14T06:40:12Z
|
||||
:category: blog
|
||||
:tags: wordpress,ranting
|
||||
:url: blog/2012/6/14/wordpress-madness.html
|
||||
:save_as: blog/2012/6/14/wordpress-madness.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
I’m a bit fed up that I had to install `MySQL <http://www.mysql.com/>`_ on my server to have
|
||||
`Wordpress <http://wordpress.org/>`_ working, so I’ve Googled a bit to find a solution for my
|
||||
pain. I found `this <http://codex.wordpress.org/Using_Alternative_Databases>`_. I don’t know
|
||||
when this post was written, but I think it’s a bit out of date. I mean come on, PDO is the part
|
||||
of PHP for ages now, and they say adding a DBAL to the dependencies would be a project as large as
|
||||
(or larger than) WP itself. Well, yes, but PHP is already a dependency, isn’t it? Remove it
|
||||
guys, it’s too large!
|
||||
|
||||
Okay, to be serious… Having a heavily MySQL dependent codebase is a bad thing in my opinion, and
|
||||
changing it is no easy task. But once it is done, it would be a child’s play to keep it up to
|
||||
date, and to port WP to other database backends. And it would be more than enough to call it 4.0,
|
||||
and raising version numbers fast is a must nowadays (right, Firefox and Linux Kernel guys?)
|
@@ -0,0 +1,25 @@
|
||||
SSH login FAILed on Red Had Enterprise Linux 6.2
|
||||
################################################
|
||||
|
||||
:date: 2012-06-18T18:28:45Z
|
||||
:category: blog
|
||||
:tags: linux,selinux,ssh,red-hat
|
||||
:url: blog/2012/6/18/ssh-login-failed-on-red-hat-enterprise-linux-6-2.html
|
||||
:save_as: blog/2012/6/18/ssh-login-failed-on-red-hat-enterprise-linux-6-2.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
Now this was a mistake I should not have done…
|
||||
|
||||
About a month ago I have moved my AWS EC2 machine from Amazon Linux to RHEL 6.2. This was good.
|
||||
I have moved all my files and stuff, recreated my own user, everything was just fine. Then I
|
||||
copied my `gitosis <https://github.com/tv42/gitosis>`_ account (user ``git`` and its home
|
||||
directory). Then I tried to log in. It failed. I was blaming OpenSSH for a week or so, changed
|
||||
the config file in several ways, tried to change the permissions on ``~git/.ssh/*``, but still
|
||||
nothing. Permission were denied, I was unable to push any of my development changes. Now after a
|
||||
long time of trying, I coincidently ``tail -f``-ed ``/var/log/audit/audit.log`` (wanted to open
|
||||
``auth.log`` instead) and that was my first good point. It told me that ``sshd`` was unable to
|
||||
read ``~git/.ssh/authorized_keys``, which gave me the idea to run ``restorecon`` on ``/home/git``.
|
||||
It solved the problem.
|
||||
|
||||
All hail SELinux and RBAC!
|
@@ -0,0 +1,31 @@
|
||||
Upgrades requiring a reboot on Linux? At last!
|
||||
##############################################
|
||||
|
||||
:date: 2012-06-22T20:04:51Z
|
||||
:category: blog
|
||||
:tags: linux
|
||||
:url: blog/2012/6/22/upgrades-requiring-a-reboot-on-linux-at-last.html
|
||||
:save_as: blog/2012/6/22/upgrades-requiring-a-reboot-on-linux-at-last.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
I’ve recently received an article on Google+ about Fedora’s new idea: package upgrades that
|
||||
require a reboot. The article said that Linux guys have lost their primary adoo: “Haha! I don’t
|
||||
have to reboot my system to install system upgrades!” My answer was always this: “Well, actually
|
||||
you should…”
|
||||
|
||||
I think this can be a great idea if distros implement it well. PackageKit was a good first step
|
||||
on this road. That software could easily solve such an issue. However, it is sooo easy to do it
|
||||
wrong. The kernel, of course, can not be upgraded online (or could it be? I have some theories on
|
||||
this subject, wonder if it can be implemented…), but other packages are much different. From the
|
||||
users’ point of view the best would be if the packages would be upgraded in the background
|
||||
seemlessly. E.g. PackageKit should check if the given executable is running. If not, it should
|
||||
upgrade it, while notifying the user like “Hey dude, don’t start Anjuta now, I’m upgrading it!”,
|
||||
or simply denying to start it. Libraries are a bit different, as PackageKit should check if any
|
||||
running executables are using the library. Meanwhile, PK should also keep a notification
|
||||
somewhere telling the users that some packages could be upgraded, but without stopping
|
||||
this-and-that, it can not be done.
|
||||
|
||||
I know these things are easier said than done. But I think (a) users should tell such ideas to
|
||||
the developers and (b) developers (mostly large companies, like Microsoft or Apple) should listen
|
||||
to them, and at least think of these ideas. Some users are not as stupid as they think…
|
@@ -0,0 +1,67 @@
|
||||
Some thoughts about that dead Linux Desktop
|
||||
###########################################
|
||||
|
||||
:date: 2012-09-05T09:01:31Z
|
||||
:category: blog
|
||||
:tags: linux,ranting
|
||||
:url: blog/2012/9/5/some-thoughts-about-that-dead-linux-desktop.html
|
||||
:save_as: blog/2012/9/5/some-thoughts-about-that-dead-linux-desktop.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
There were some arguments in the near past on `What Killed the Linux Desktop
|
||||
<http://tirania.org/blog/archive/2012/Aug-29.html>`_. After reading many replies, like `Linus
|
||||
Torvalds’s
|
||||
<http://www.zdnet.com/linus-torvalds-on-the-linux-desktops-popularity-problems-7000003641/>`_, I
|
||||
have my own thoughts, too.
|
||||
|
||||
I know my place in the world, especially in the online community. I’m a Linux user for about 15
|
||||
years and a Linux administrator for 10 years now, beginning with WindowMaker and something that I
|
||||
remember as GNOME without a version number. I have committed some minor code chunks and
|
||||
translations in some minor projects, so I’m not really into it from the “write” side (well, until
|
||||
now, since I have began to write this blog, and much more, but don’t give a penny for my words
|
||||
until you see it).
|
||||
|
||||
I’m using Linux since 2.2 and GNOME since 1.whatever. It’s nice that a program compiled years ago
|
||||
still runs on today’s Linux kernel, especially if you see old DOS/Windows software failing to
|
||||
start on a new Windows 7 machine. I understand Linus’ point that breaking external APIs is bad,
|
||||
and I think it can work well on the kernel’s level. But the desktop level is much different. As
|
||||
the Linux Desktop has such competitors (like OS/X and Windows’ Aero and Metro), they have to give
|
||||
something new to the users almost every year to keep up with them. Eye candies are a must (yes,
|
||||
of course my techy fellows, they are worthless, but users *need* it), and they can not be created
|
||||
without extending APIs. And the old API… well, it fades away fast. I don’t really understand
|
||||
however, why they have to totally disappear, like `GTK_DIALOG_NO_SEPARATOR
|
||||
<http://developer.gnome.org/gtk/stable/GtkDialog.html#GtkDialogFlags>`_ in Gtk+3. It could be
|
||||
replaced with a 0 value (e.g: it won’t do anything). This way my old Gtk+2 program could compile
|
||||
with Gtk+3 nicely. Also, there could be a small software that goes through your source code and
|
||||
warn you about such deprecated (and no-doer but still working) things. Porting applications
|
||||
between Gtk+ (and thus, GNOME) versions became a real pain, which makes less enthusiast
|
||||
programmers stop developing for Linux. Since I’m a GNOME guy for years, I can tell nothing about
|
||||
Qt and KDE, but for the GNOME guys, this is a bad thing. As of alternatives, there is Java. No,
|
||||
wait… it turned out recently that `it has several security bugs
|
||||
<http://www.theregister.co.uk/2012/08/31/critical_flaw_found_in_patched_java>`_. Also it’s not
|
||||
that multiplatform as they say (I can’t find the article on that at the moment, but I have proof).
|
||||
Also, the JVMs out there eat up so much resources, which makes it a bit hard and expensive to use.
|
||||
|
||||
Also, I see another problem: those blasted package managers. RPM, DPKG, Portage, whatever. What
|
||||
the hell? Why are there so many? Why do developers reinvent the wheel? The nave is too small or
|
||||
there are to few spokes? Come on… we live in an open source world! Contribute to the one and
|
||||
only package manager (which one is that I don’t actually care)! I’m sure the two (three, many)
|
||||
bunches of develoeprs could make a deal. Thus, it could become better and “outsider” companies
|
||||
would be happier to distribute their software for Linux platforms.
|
||||
|
||||
And now that we get to the big companies. I don’t really understand them. nVidia and ATI made
|
||||
their own closed source drivers for Linux. Some other hardware vendors also write Linux drivers,
|
||||
and as the kernel API doesn’t really change, they will work for a long time. But what about
|
||||
desktop application vendors? Well, they try to stick to a desktop environment or two, and if they
|
||||
change too frequently, they stop developing for Linux, like Skype did (OK, maybe Skype has other
|
||||
reasons, but you see my point). But why? The main part for Linux programs is the Linux kernel
|
||||
and the basic userland like libc/stdlib++. If you write graphical software, it will have to use
|
||||
X-Windows. Yes, it’s much different in many ways, mostly because they have a… well… pretty ugly
|
||||
design by default. But still, it’s the same on every Linux distributions, as it became somewhat
|
||||
an industry standard, as it was already on the market back in the old UN\*X days. The protocol
|
||||
itself changed just like the Linux kernel: almost no change at all, just some new features.
|
||||
|
||||
So what kills the Linux desktop in my opinion is these constant wars inside, and the lack of
|
||||
support from the outside. Open Source is good, but until these (mostly the first) problems are
|
||||
not resolved, Linux Desktop can do nothing on the market. It’s a downward spiral hard to escape.
|
@@ -0,0 +1,73 @@
|
||||
How to start becoming a web developer
|
||||
#####################################
|
||||
|
||||
:date: 2012-09-07T18:12:12Z
|
||||
:category: blog
|
||||
:tags: development,technology
|
||||
:url: blog/2012/9/7/how-to-start-becoming-a-web-developer.html
|
||||
:save_as: blog/2012/9/7/how-to-start-becoming-a-web-developer.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
A friend of mine asked me today how to become a web developer. It took me a while, but I made up
|
||||
a checklist. It’s short, but it’s enough for the first steps.
|
||||
|
||||
First of all, learn English
|
||||
===========================
|
||||
|
||||
Well, if you read this, maybe this was a bad first point…
|
||||
|
||||
Choose a language and stick to it!
|
||||
==================================
|
||||
|
||||
For the UN\*X/Linux line, there is PHP. It’s free, easy to learn, and has many free tools and
|
||||
documentations available. It can be used in a functional or an object-oriented way.
|
||||
|
||||
C# is another good way to start, but for the Windows line. It’s fully object oriented, and the
|
||||
web is full of tutorials, how-tos and other resources.
|
||||
|
||||
Learn the basics of the system you are working on
|
||||
=================================================
|
||||
|
||||
To become a good developer, learn at least the basics of the system you are working on. Basic
|
||||
commands can always come in handy. Debugging (yes, you will do tons of bugs for sure) can become
|
||||
much easier if you know the huge set of tools provided by your OS. You should also try to develop
|
||||
in the chosen environment. Chose PHP? Get a Linux desktop! ASP.NET? Get a Windows. Everything
|
||||
will be much easier!
|
||||
|
||||
Learn the basics of the web server you are using
|
||||
================================================
|
||||
|
||||
PHP can run on `Apache <http://httpd.apache.org/>`_ (as a module), or any CGI-capable webserver,
|
||||
like `lighttpd <http://www.lighttpd.net/>`_ or `nginx <http://nginx.org/>`_ (well, it can also run
|
||||
on IIS, but trust me: you don’t want that). ASP.NET is designed for IIS, and although some
|
||||
scripts can be run under a mono-capable server, it should still stay there.
|
||||
|
||||
Whichever you choose, learn the basics! How to start and stop the service,
|
||||
basic configuration methods, modules/extensions, and so on. It’s more than sure
|
||||
that you will face some issues while developing, so it can never hurt.
|
||||
|
||||
Keep your versions under control
|
||||
================================
|
||||
|
||||
Version control is critical nowadays. It gives you a basic backup solution, can come in handy
|
||||
with debugging, and if you ever want to work in a team, you will badly need it.
|
||||
|
||||
Subversion is a bit out of date now, and it’s kind of hard to set up.
|
||||
|
||||
Git is no easy. You will have to learn a lot of stuff, but basicly it’s just another version
|
||||
control system. Just choose if you want to stick to merge-then-commit or rebase-then-commit, get
|
||||
a client, and get on the run.
|
||||
|
||||
Microsoft’s Team Foundation is another good way if you are working in a team. It provides several
|
||||
other features besides version controlling, and is well integrated into Visual Studio, which is
|
||||
highly recommended for Windows based development.
|
||||
|
||||
Choose an environment to work in
|
||||
================================
|
||||
|
||||
There are so many good tools out there. You should choose according to the language and OS on
|
||||
what you are working on. `Zend Studio <http://www.zend.com/en/products/studio>`_ or `Netbeans
|
||||
<https://netbeans.org/>`_ are both good tools for PHP development, while `Visual Studio
|
||||
<http://www.visualstudio.com/>`_ is a best buy for Windows development. Both of these have many
|
||||
ups and downs, but once you get in touch with their deeper parts, you will like them.
|
17
content/blog/2012-09-10-do-not-track-in-ie10-vs-apache.rst
Normal file
@@ -0,0 +1,17 @@
|
||||
Do-Not-Track in IE10 vs. Apache
|
||||
###############################
|
||||
|
||||
:date: 2012-09-10 20:22:32Z
|
||||
:category: blog
|
||||
:tags: apache,technology
|
||||
:url: blog/2012/9/10/do-not-track-in-ie10-vs-apache.html
|
||||
:save_as: blog/2012/9/10/do-not-track-in-ie10-vs-apache.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
`Apache developer decided not to accept Do-Not-Track headers from IE10 users
|
||||
<http://arstechnica.com/security/2012/09/apache-webserver-updated-to-ignore-do-not-track-settings-in-ie-10/>`_,
|
||||
because it’s enabled by default. So… if I install a plugin that hides the fact from the web
|
||||
server that I’m using IE10, I become eligible of using it. But if I do this, I simply became
|
||||
eligible because I consciously installed that addon, so I could actually use it without hiding the
|
||||
fact. Sorry if I’m a bit Philosoraptorish…
|
@@ -0,0 +1,74 @@
|
||||
Symfony 2 – Create role- and class-based ACLs with your roles coming from the ORM
|
||||
#################################################################################
|
||||
|
||||
:date: 2012-09-16T18:39:25Z
|
||||
:category: blog
|
||||
:tags: php,symfony
|
||||
:url: blog/2012/9/16/symfony-2-create-role-and-class-based-acls-with-your-roles-coming-from-the-orm.html
|
||||
:save_as: blog/2012/9/16/symfony-2-create-role-and-class-based-acls-with-your-roles-coming-from-the-orm.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
During the last weeks I had some serious issues with one of my private Symfony 2 projects. One of
|
||||
my goals was to create a dynamic security system, e.g my administrators wanted to create roles,
|
||||
and grant these roles access to different object types (classes) and/or objects.
|
||||
|
||||
So I have created a ``User`` entity, which implements ``UserInterface`` and
|
||||
``AdvancedUserInterface``, the latter for the possibility to enable/disable accounts and such. It
|
||||
had a ``$roles`` property, which was a ``ManyToMany`` relation to the ``Role`` entity, which
|
||||
implemented ``RoleInterface``. Also I have created my own role hierarchy service that implements
|
||||
``RoleHierarchyInterface``.
|
||||
|
||||
So far so good, first tests. It soon turned out that if ``User::getRoles()`` returns a
|
||||
``DoctrineCollection`` as it does by default, then the standard
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
$this->get('security.context')->isGranted('ROLE_ADMIN');
|
||||
|
||||
doesn’t work. I know, it should not be hard coded, as my roles and permission tables are dynamic,
|
||||
I have just tested. So I fixed my ``User`` entity so ``getRoles()`` returns an array of ``Role``
|
||||
objects instead of the ``DoctrineCollection``. Also I implemented a ``getRolesCollection()``
|
||||
method to return the original collection, but I think it will never be used.
|
||||
|
||||
After that, I had to implement some more features so I put this task away. Then, I tried to
|
||||
create my first ACL.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
$securityIdentity = new RoleSecurityIdentity('ROLE_ADMIN');
|
||||
$objectIdentity = new ObjectIdentity('newsClass', 'Acme\\DemoBundle\\Entity\\News');
|
||||
$acl = $aclProvider->createAcl($objectIdentity);
|
||||
$acl->insertClassAce($securityIdentity, MaskBuilder::MASK_OWNER);
|
||||
$aclProvider->updateAcl($acl);
|
||||
|
||||
I was about to check if the user who is logged in has an ``OWNER`` permission on the ``User``
|
||||
class.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
$this->objectIdentity = new ObjectIdentity(self::OBJECT_ID, self::OBJECT_FQCN);
|
||||
if ($this->securityContext->isGranted('OWNER', $this->objectIdentity) === false) {
|
||||
throw new AccessDeniedException('You don’t have the required permissions!');
|
||||
}
|
||||
|
||||
The ACL was defined based on a role, so everyone who had the ``ROLE_ADMIN`` role should gain
|
||||
access to the user listing page. But they didn’t. It took several weeks to find the cause, I
|
||||
have put it on `stackoverflow
|
||||
<http://stackoverflow.com/questions/12057795/symfony-2-1-this-getsecurity-context-isgrantedrole-admin-returns-fa>`_
|
||||
and the Symfony Google Group, but no usable answers.
|
||||
|
||||
Then I went off for debugging. Setting up NetBeans for xdebug-based PHP debugging was real fun
|
||||
under Fedora, but that’s another story. After a while I have found that Symfony’s basic access
|
||||
decision manager checks for ``$role->getRole()`` only if ``$role`` is an instance of
|
||||
``Symfony\Component\Security\Core\Role\Role``, instead of checking if the object implements
|
||||
``Symfony\Component\Security\Core\Role\RoleInterface``. So I’ve checked if the bug is already
|
||||
reported. It turned out that it was, and my solution was available in a specific commit about a
|
||||
year ago, but as `Johannes Schmitt commented, it would introduce a security issue
|
||||
<https://github.com/symfony/symfony/commit/af70ac8d777873c49347ac828a817a400006cbea>`_, so it was
|
||||
reverted. Unfortunately neither Johannes Schmitt, nor Fabien Potencier (nor anyone else) could (or
|
||||
wanted) to tell about this issue. So the final (and somewhat hack-like) solution was to extend
|
||||
``Symfony\Component\Security\Core\Role\Role``. And boom! It worked.
|
36
content/blog/2012-10-07-smsgateway-and-smssender.rst
Normal file
@@ -0,0 +1,36 @@
|
||||
SmsGateway and SmsSender
|
||||
########################
|
||||
|
||||
:date: 2012-10-07T00:10:26Z
|
||||
:category: blog
|
||||
:tags: development,php,symfony
|
||||
:url: blog/2012/10/7/smsgateway-and-smssender.html
|
||||
:save_as: blog/2012/10/7/smsgateway-and-smssender.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
I have just uploaded my SmsGateway, SmsSender and SmsSenderBundle packages to `GitHub
|
||||
<http://github.com/gergelypolonkai>`_ and `Packagist <http://packagist.org>`_. I hope some of you
|
||||
will find it useful.
|
||||
|
||||
* SmsGateway
|
||||
|
||||
* `SmsGateway on GitHub`_
|
||||
* `SmsGateway on Packagist`_
|
||||
|
||||
* SmsSender
|
||||
|
||||
* `SmsSender on GitHub`_
|
||||
* `SmsSender on Packagist`_
|
||||
|
||||
* SmsSenderBundle
|
||||
|
||||
* `SmsSenderBundle on GitHub`_
|
||||
* `SmsSenderBundle on Packagist`_
|
||||
|
||||
.. _SmsGateway on GitHub: https://github.com/gergelypolonkai/smsgateway
|
||||
.. _SmsGateway on Packagist: https://packagist.org/packages/gergelypolonkai/smsgateway
|
||||
.. _SmsSender on GitHub: https://github.com/gergelypolonkai/smssender
|
||||
.. _SmsSender on Packagist: https://packagist.org/packages/gergelypolonkai/smssender
|
||||
.. _SmsSenderBundle on GitHub: https://github.com/gergelypolonkai/smssender-bundle
|
||||
.. _SmsSenderBundle on Packagist: https://packagist.org/packages/gergelypolonkai/smssender-bundle
|
@@ -0,0 +1,22 @@
|
||||
Changing the session cookie’s name in Symfony 2
|
||||
###############################################
|
||||
|
||||
:date: 2012-10-13T12:49:28Z
|
||||
:category: blog
|
||||
:tags: symfony,development
|
||||
:url: blog/2012/10/13/changing-the-session-cookie-s-name-in-symfony-2.html
|
||||
:save_as: blog/2012/10/13/changing-the-session-cookie-s-name-in-symfony-2.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
I have a development server, on which I have several Symfony 2.x projects under the same hostname
|
||||
in different directories. Now I’m facing a funny problem which is caused by that the cookies
|
||||
Symfony places for each of my projects have the same name.
|
||||
|
||||
To change this, you will have to modify the ``config.yml`` file like this:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
session:
|
||||
name: SiteSpecificSessionName
|
||||
lifetime: 3600
|
@@ -0,0 +1,52 @@
|
||||
Symfony 2 Configuration – Array of associative arrays
|
||||
#####################################################
|
||||
|
||||
:date: 2012-12-20T12:03:23Z
|
||||
:category: blog
|
||||
:tags: php,symfony
|
||||
:url: blog/2012/12/20/symfony-2-configuration-array-of-associative-arrays.html
|
||||
:save_as: blog/2012/12/20/symfony-2-configuration-array-of-associative-arrays.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
Few days ago I have struggled with a problem using Symfony2 configuration. I
|
||||
wanted to add the following kind of configuration to ``config.yml``:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
acme_demo:
|
||||
transitions:
|
||||
- { hc_cba: 180 }
|
||||
- { cba_hc: -1 }
|
||||
|
||||
The problem was that the stuff under ``transitions`` is dynamic, so those ``hc_cba`` and
|
||||
``cba_hc`` tags can be pretty much anything. After hitting many errors, I came to the solution:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
$rootNode
|
||||
->children()
|
||||
->arrayNode('state_machine')
|
||||
->requiresAtLeastOneElement()
|
||||
->beforeNormalization()
|
||||
->ifArray()
|
||||
->then(function($values) {
|
||||
$ret = array();
|
||||
foreach ($values as $value) {
|
||||
foreach ($value as $transition => $time) {
|
||||
$ret[] = array('transition' => $transition, 'time' => e);
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
})
|
||||
->end()
|
||||
->prototype('array')
|
||||
->children()
|
||||
->scalarNode('transition')->end()
|
||||
->scalarNode('time')->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
;
|
13
content/blog/2013-01-05-development-man-pages-on-fedora.rst
Normal file
@@ -0,0 +1,13 @@
|
||||
Development man pages on Fedora
|
||||
###############################
|
||||
|
||||
:date: 2013-01-05T18:20:41Z
|
||||
:category: blog
|
||||
:tags: development,fedora
|
||||
:url: blog/2013/1/5/development-man-pages-on-fedora.html
|
||||
:save_as: blog/2013/1/5/development-man-pages-on-fedora.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
If you use Fedora (like me), and can’t find the development manual pages for e.g. ``printf(3)``
|
||||
(like me), just ``yum install man-pages`` (like me).
|
@@ -0,0 +1,99 @@
|
||||
Registering an enum type in GLib’s type system
|
||||
##############################################
|
||||
|
||||
:date: 2013-01-06T02:34:03Z
|
||||
:category: blog
|
||||
:tags: c,development,glib
|
||||
:url: blog/2013/1/6/registering-an-enum-type-in-glib-s-type-system.html
|
||||
:save_as: blog/2013/1/6/registering-an-enum-type-in-glib-s-type-system.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
I faced a problem in my `GLib <https://developer.gnome.org/glib/>`_ self-teaching project, `wMUD
|
||||
<https://github.com/gergelypolonkai/wmud>`_ today. I wanted to register a signal for a
|
||||
``GObject``, whose handler should accept two ``enum`` parameters for which I had to register a new
|
||||
``GEnum`` type in the ``GObject`` type system. However, the `documentation on this feature
|
||||
<https://developer.gnome.org/gobject/unstable/gtype-non-instantiable.html>`_ (thanks for pointing
|
||||
out goes to `hashem` on ``#gnome-hackers``) is not… uhm… obvious. Making the long story short, I
|
||||
have checked with the ``GIO`` sources for an example, and using that, I have created this small,
|
||||
working chunk:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#ifndef __WMUD_CLIENT_STATE_H__
|
||||
#define __WMUD_CLIENT_STATE_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
/**
|
||||
* WmudClientState:
|
||||
* @WMUD_CLIENT_STATE_FRESH: Client is newly connected. Waiting for a login
|
||||
* player name
|
||||
* @WMUD_CLIENT_STATE_PASSWAIT: Login player name is entered, waiting for a
|
||||
* login password
|
||||
* @WMUD_CLIENT_STATE_MENU: Authentication was successful, player is now in the
|
||||
* main game menu
|
||||
* @WMUD_CLIENT_STATE_INGAME: Character login was successful, player is now
|
||||
* in-game
|
||||
* @WMUD_CLIENT_STATE_YESNO: Player was asked a yes/no question, and we are
|
||||
* waiting for the answer. client.yesNoCallback MUST be set at this point!
|
||||
* TODO: if wmudClient had a prevState field, and there would be some hooks
|
||||
* that are called before and after the client enters a new state, this
|
||||
* could be a three-state stuff, in which the player can enter e.g ? as
|
||||
* the answer, so they would be presented with the question again.
|
||||
* @WMUD_CLIENT_STATE_REGISTERING: Registering a new player. Waiting for the
|
||||
* e-mail address to be given
|
||||
* @WMUD_CLIENT_STATE_REGEMAIL_CONFIRM: E-mail address entered séms valid,
|
||||
* waiting for confirmation
|
||||
*
|
||||
* Game client states.
|
||||
*/
|
||||
typedef enum {
|
||||
WMUD_CLIENT_STATE_FRESH,
|
||||
WMUD_CLIENT_STATE_PASSWAIT,
|
||||
WMUD_CLIENT_STATE_MENU,
|
||||
WMUD_CLIENT_STATE_INGAME,
|
||||
WMUD_CLIENT_STATE_YESNO,
|
||||
WMUD_CLIENT_STATE_REGISTERING,
|
||||
WMUD_CLIENT_STATE_REGEMAIL_CONFIRM
|
||||
} WmudClientState;
|
||||
|
||||
|
||||
GType wmud_client_state_get_type (void) G_GNUC_CONST;
|
||||
#define WMUD_TYPE_CLIENT_STATE (wmud_client_state_get_type())
|
||||
|
||||
#endif /* __WMUD_CLIENT_STATE_H__ */
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include "wmudclientstate.h"
|
||||
|
||||
GType
|
||||
wmud_client_state_get_type (void)
|
||||
{
|
||||
static volatile gsize g_define_type_id__volatile = 0;
|
||||
|
||||
if (g_once_init_enter(&g_define_type_id__volatile)) {
|
||||
static const GEnumValue values[] = {
|
||||
{ WMUD_CLIENT_STATE_FRESH, "WMUD_CLIENT_STATE_FRESH", "fresh" },
|
||||
{ WMUD_CLIENT_STATE_PASSWAIT, "WMUD_CLIENT_STATE_PASSWAIT", "passwait" },
|
||||
{ WMUD_CLIENT_STATE_MENU, "WMUD_CLIENT_STATE_MENU", "menu" },
|
||||
{ WMUD_CLIENT_STATE_INGAME, "WMUD_CLIENT_STATE_INGAME", "ingame" },
|
||||
{ WMUD_CLIENT_STATE_YESNO, "WMUD_CLIENT_STATE_YESNO", "yesno" },
|
||||
{ WMUD_CLIENT_STATE_REGISTERING, "WMUD_CLIENT_STATE_REGISTERING", "registering" },
|
||||
{ WMUD_CLIENT_STATE_REGEMAIL_CONFIRM, "WMUD_CLIENT_STATE_REGEMAIL_CONFIRM", "regemail-confirm" },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
GType g_define_type_id = g_enum_register_static(g_intern_static_string("WmudClientState"), values);
|
||||
g_once_init_leave(&g_define_type_id__volatile, g_define_type_id);
|
||||
}
|
||||
|
||||
return g_define_type_id__volatile;
|
||||
}
|
||||
|
||||
Still, it can be made more perfect by using the `glib-mkenums
|
||||
<http://developer.gnome.org/gobject/stable/glib-mkenums.html>`_ tool. I will read through the
|
||||
GLib Makefiles tomorrow for some hints on this.
|
||||
|
||||
Edit: you can find the glib-mkenums solution `here
|
||||
<{filename}2014-08-16-registering-an-enum-type-in-glib-glib-mkenums-magic.rst>`_.
|
16
content/blog/2013-01-14-git-rm-cached-madness.rst
Normal file
@@ -0,0 +1,16 @@
|
||||
git rm --cached madness
|
||||
#######################
|
||||
|
||||
:date: 2013-01-14T21:38:00Z
|
||||
:category: blog
|
||||
:tags: development,git
|
||||
:url: blog/2013/1/14/git-rm-cached-madness.html
|
||||
:save_as: blog/2013/1/14/git-rm-cached-madness.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
I have recently learned about ``git rm --cached``. It’s a very good tool, as it removes a file
|
||||
from tracking, without removing your local copy of it. However, be warned that if you use ``git
|
||||
pull`` in another working copy, the file will be removed from there! If you accidentally put the
|
||||
configuration of a production project, and remove it on your dev machine, it can cause a lot of
|
||||
trouble ;)
|
@@ -0,0 +1,53 @@
|
||||
JMS\\DiExtraBundle’s GrepPatternFinder – grep exits with status code 2 on Fedora 18
|
||||
###################################################################################
|
||||
|
||||
:date: 2013-01-17T00:32:12Z
|
||||
:category: blog
|
||||
:tags: fedora,selinux,symfony
|
||||
:url: blog/2013/1/17/jms-diextrabundle-s-greppatternfinder-grep-exits-with-status-code-2-on-fedora-18.html
|
||||
:save_as: blog/2013/1/17/jms-diextrabundle-s-greppatternfinder-grep-exits-with-status-code-2-on-fedora-18.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
Yesterday I’ve upgraded my development machines from Fedora 17 to Fedora
|
||||
18. Although it went well, my `Symfony <http://symfony.com/>`_ projects stopped working with a
|
||||
message like this:
|
||||
|
||||
.. code-block:: log
|
||||
|
||||
RuntimeException: Command "/usr/bin/grep --fixed-strings --directories=recurse --devices=skip --files-with-matches --with-filename --color=never --include=*.php 'JMS\DiExtraBundle\Annotation'
|
||||
'/var/www/html/gergelypolonkaiweb/app/../src'
|
||||
'/var/www/html/gergelypolonkaiweb/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle'
|
||||
'/var/www/html/gergelypolonkaiweb/vendor/symfony/symfony/src/Symfony/Bundle/SecurityBundle'
|
||||
'/var/www/html/gergelypolonkaiweb/vendor/symfony/symfony/src/Symfony/Bundle/TwigBundle'
|
||||
'/var/www/html/gergelypolonkaiweb/vendor/symfony/monolog-bundle/Symfony/Bundle/MonologBundle'
|
||||
'/var/www/html/gergelypolonkaiweb/vendor/symfony/swiftmailer-bundle/Symfony/Bundle/SwiftmailerBundle'
|
||||
'/var/www/html/gergelypolonkaiweb/vendor/symfony/assetic-bundle/Symfony/Bundle/AsseticBundle'
|
||||
'/var/www/html/gergelypolonkaiweb/vendor/doctrine/doctrine-bundle/Doctrine/Bundle/DoctrineBundle'
|
||||
'/var/www/html/gergelypolonkaiweb/vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle'
|
||||
'/var/www/html/gergelypolonkaiweb/vendor/jms/aop-bundle/JMS/AopBundle'
|
||||
'/var/www/html/gergelypolonkaiweb/vendor/jms/security-extra-bundle/JMS/SecurityExtraBundle'
|
||||
'/var/www/html/gergelypolonkaiweb/vendor/doctrine/doctrine-migrations-bundle/Doctrine/Bundle/MigrationsBundle'
|
||||
'/var/www/html/gergelypolonkaiweb/vendor/friendsofsymfony/jsrouting-bundle/FOS/JsRoutingBundle'
|
||||
'/var/www/html/gergelypolonkaiweb/vendor/avalanche123/imagine-bundle/Avalanche/Bundle/ImagineBundle'
|
||||
'/var/www/html/gergelypolonkaiweb/vendor/genemu/form-bundle/Genemu/Bundle/FormBundle'
|
||||
'/var/www/html/gergelypolonkaiweb/src/GergelyPolonkai/FrontBundle'
|
||||
'/var/www/html/gergelypolonkaiweb/src/GergelyPolonkai/GeshiBundle'
|
||||
'/var/www/html/gergelypolonkaiweb/vendor/symfony/symfony/src/Symfony/Bundle/WebProfilerBundle'
|
||||
'/var/www/html/gergelypolonkaiweb/vendor/sensio/distribution-bundle/Sensio/Bundle/DistributionBundle'
|
||||
'/var/www/html/gergelypolonkaiweb/vendor/sensio/generator-bundle/Sensio/Bundle/GeneratorBundle'" exited with non-successful status code "2".
|
||||
|
||||
After getting through my logs and such, I’ve finally found out that the new SELinux policy is
|
||||
causing the trouble together with git. Eventually, my ``.git/logs`` directory is tagged as
|
||||
``unconfined_u:object_r:httpd_log_t:s0``. ``httpd_log_t`` type is not readable by the
|
||||
``system_u:system_r:httpd_t:s0`` user, which makes ``/usr/bin/grep`` throw an access denied error.
|
||||
To fix this, I needed to do
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
semanage fcontext -a -t httpd_sys_content_t '/var/www(/.*)?/\.git/logs(/.*)?'
|
||||
|
||||
as root. This makes ``.git`` directories readable for the httpd process, thus, for ``grep``. The
|
||||
optimal solution would be to tell ``GrepPatternFinder`` to ignore version control stuff, so the
|
||||
``httpd`` process would have no access to them at all. Also, in production, removing the ``.git``
|
||||
or ``.svn`` directories could be a good idea.
|
@@ -0,0 +1,33 @@
|
||||
mount: device or resource busy after enabling multipath
|
||||
#######################################################
|
||||
|
||||
:date: 2013-02-19T23:09:05Z
|
||||
:category: blog
|
||||
:tags: linux,heartbeat-cluster
|
||||
:url: blog/2013/2/19/mount-device-or-resource-busy-after-enabling-multipath.html
|
||||
:save_as: blog/2013/2/19/mount-device-or-resource-busy-after-enabling-multipath.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
We have a heartbeat cluster with two nodes. It has been running for several months without
|
||||
problems. The shared storage is on an IBM DS3400, on which we have a large volume formatted with
|
||||
ext4.
|
||||
|
||||
Today I decided to reboot the active node for security reasons. So I’ve switched to the passive
|
||||
node, which failed at the first step: it was unable to mount the storage (``/dev/sda1``). After
|
||||
whining for a few moments, I tried to mount it by hand, which told me
|
||||
|
||||
.. code-block:: log
|
||||
|
||||
/dev/sda1 already mounted or /data is busy
|
||||
|
||||
I’ve quickly made sure that none of that was true. After checking this-and-that, it turned out
|
||||
that the passive node had ``multipathd`` running, so I looked under ``/dev/mapper``, and found two
|
||||
symlinks there, ``<long-long WWN>`` and ``<long-long WWN>-part1``. As the partition table and the
|
||||
disk size was the same as on ``/dev/sda``, I tried to
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
mount /dev/<long-long WWN>-part1 /data
|
||||
|
||||
and voilà! It worked like charm!
|
@@ -0,0 +1,23 @@
|
||||
Why I stopped using annotation based routing in Symfony today
|
||||
#############################################################
|
||||
|
||||
:date: 2013-02-27T23:10:24Z
|
||||
:category: blog
|
||||
:tags: development,symfony
|
||||
:url: blog/2013/2/27/why-i-stopped-using-annotation-based-routing-in-symfony-today.html
|
||||
:save_as: blog/2013/2/27/why-i-stopped-using-annotation-based-routing-in-symfony-today.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
I have read several opinions about routing configuration in Symfony. I stayed with annotation
|
||||
based routing as it was convinient for me to see the URL right above the controller action. This
|
||||
was because by just checking the URL, I remembered the controlling code, as they always were fresh
|
||||
ones. Well, until today.
|
||||
|
||||
I had to take a look into an old (Sf 2.0, last commit was about 3 months ago) project of mine. In
|
||||
the same run I’ve upgraded the whole project to 2.2 (it was a fast one, thanks for `JMikola@GitHub
|
||||
<https://github.com/jmikola>`_ for the quick reply on my issue with `JmikolaJsAssetsHelperBundle
|
||||
<https://github.com/jmikola/JmikolaJsAssetsHelperBundle>`_ again!). After that I went on to the
|
||||
requested change. Now, finding a route in about 40 controller files spread between 3 bundles can
|
||||
really be a pain! So I’ve finished with annotation based routing. It’s still a nice feature,
|
||||
it’s simply not for me.
|
@@ -0,0 +1,41 @@
|
||||
Fedora can’t change Active Directory password via kpasswd
|
||||
#########################################################
|
||||
|
||||
:date: 2013-03-05T08:55:04Z
|
||||
:category: blog
|
||||
:tags: fedora,kerberos,active-directory
|
||||
:url: blog/2013/3/5/fedora-can-t-change-active-directory-password-via-kpasswd.html
|
||||
:save_as: blog/2013/3/5/fedora-can-t-change-active-directory-password-via-kpasswd.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
I wanted to change my AD password today. As the AD is actually a Kerberos server, I was pretty
|
||||
sure that ``kpasswd`` will do the trick. However, ``kpasswd`` output looked like this:
|
||||
|
||||
.. code-block:: output
|
||||
|
||||
$ kpasswd
|
||||
Password for polonkai.gergely@EXAMPLE.LOCAL:
|
||||
Enter new password:
|
||||
Enter it again:
|
||||
kpasswd: Cannot find KDC for requested realm changing password
|
||||
|
||||
I’ve checked ``kinit`` and ``klist``, everything looked fine. After a while it came
|
||||
to my mind that password changing is done through the kadmin server, not
|
||||
through the KDC. It seems that when I set up the Active Directory membership,
|
||||
the ``admin_server`` directive is not get written to ``krb5.conf``. So all I had to
|
||||
do was to put
|
||||
|
||||
.. code-block:: conf
|
||||
|
||||
admin_server = ad.example.local
|
||||
|
||||
in that file, and voilà!
|
||||
|
||||
.. code-block:: output
|
||||
|
||||
$ kpasswd
|
||||
Password for polonkai.gergely@EXAMPLE.LOCAL:
|
||||
Enter new password:
|
||||
Enter it again:
|
||||
Password changed.
|
25
content/blog/2013-03-05-haversine-in-mysql.rst
Normal file
@@ -0,0 +1,25 @@
|
||||
Haversine in MySQL
|
||||
##################
|
||||
|
||||
:date: 2013-03-05T12:49:28Z
|
||||
:category: blog
|
||||
:tags: mysql,development
|
||||
:url: blog/2013/3/5/haversine-in-mysql.html
|
||||
:save_as: blog/2013/3/5/haversine-in-mysql.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
Just insert it in your database, feed them two Google coordinates, and you get the distance in
|
||||
kilometres. If you happen to need it in miles, change the constant ``12756.200`` in the
|
||||
``RETURN`` row to ``7922.6`` instead.
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
DELIMITER $$
|
||||
|
||||
CREATE FUNCTION `haversine` (lng1 FLOAT, lat1 FLOAT, lng2 FLOAT, lat2 FLOAT)
|
||||
RETURNS float NO SQL DETERMINISTIC
|
||||
BEGIN
|
||||
SET @a = ABS(POWER(SIN(RADIANS(lat1 - lat2)) / 2, 2) + COS(RADIANS(lat1)) * COS(RADIANS(lat2)) * POWER(SIN(RADIANS(lng1 - lng2)) / 2, 2));
|
||||
RETURN 12756.200 * ATAN2(SQRT(@a), SQRT(1 - @a));
|
||||
END$$
|
25
content/blog/2013-03-13-dvorak-and-me.rst
Normal file
@@ -0,0 +1,25 @@
|
||||
Dvorak and me
|
||||
#############
|
||||
|
||||
:date: 2013-03-13T21:20:13Z
|
||||
:category: blog
|
||||
:tags: linux
|
||||
:url: blog/2013/3/13/dvorak-and-me.html
|
||||
:save_as: blog/2013/3/13/dvorak-and-me.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
A few months ago I have decided to switch to the Dvorak layout. After using QWERTY (well, QWERTZ,
|
||||
to be precise) for almost 17 years, it was a hard decision, but now I think it worthed the try. I
|
||||
started with the UK (Dvorak with UK punctuation) layout, and in about four weeks, I’ve almost
|
||||
reached my original typing speed. Today I have modified the Hungarian xkb definitions file to add
|
||||
the Hungarian accended letters like ű to the layout, so I don’t have to use dead keys anymore
|
||||
(which apparently turned out to be a problem, as the Linux version of Java doesn’t support dead
|
||||
keys at all).
|
||||
|
||||
Best thing is, as I never learned proper 10-finger typing, but learned Dvorak that way, I can
|
||||
switch between QWERTY and Dvorak more or less painlessly (about 10 minutes of confusion, so to
|
||||
say).
|
||||
|
||||
Conclusion: I don’t know yet if this was actually a good decision, but it wasn’t bad, after all.
|
||||
But seeing people’s faces when they try to type on my machine totally worths it.
|
25
content/blog/2013-04-09-renaming-a-symfony-2-bundle.rst
Normal file
@@ -0,0 +1,25 @@
|
||||
Renaming a Symfony 2 bundle
|
||||
###########################
|
||||
|
||||
:date: 2013-04-09T22:29:48Z
|
||||
:category: blog
|
||||
:tags: development,symfony
|
||||
:url: blog/2013/4/9/renaming-a-symfony-2-bundle.html
|
||||
:save_as: blog/2013/4/9/renaming-a-symfony-2-bundle.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
Today I’ve realised that the name I gave to one of my Symfony 2 bundles should be something else.
|
||||
To rename a bundle, one must do four things (at least).
|
||||
|
||||
1. Change the namespace from ``Vendor\OldBundle`` to ``Vendor\NewBundle`` in every PHP class
|
||||
(sounds like pain? It is…)
|
||||
2. Change the name of files and classes. Some files under ``src/Vendor/OldBundle`` (and the
|
||||
classes in them) contain the name of the bundle, like
|
||||
``OldBundle/DependencyInjection/VendorOldBundleExtension.php`` and
|
||||
``OldBundle/VendorOldBundle.php``. You should rename them, or Symfony won’t find the classes
|
||||
defined in them! When done, rename the whole bundle directory either.
|
||||
3. Change the configuration files accordingly, including ``AppKernel.php``. These config files
|
||||
are usually ``routing.yml``, ``services.yml``, and in some cases, ``config.yml``.
|
||||
4. Change the references in other parts of your code. A ``grep -r OldBundle .`` will usually
|
||||
help…
|
@@ -0,0 +1,107 @@
|
||||
Installing OTRS in Fedora 18 with SELinux enabled
|
||||
#################################################
|
||||
|
||||
:date: 2013-05-06T06:01:52Z
|
||||
:category: blog
|
||||
:tags: fedora,selinux,otrs
|
||||
:url: blog/2013/5/6/installing-otrs-in-fedora-18-with-selinux-enabled.html
|
||||
:save_as: blog/2013/5/6/installing-otrs-in-fedora-18-with-selinux-enabled.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
I’ve read somewhere in an OTRS installation howto that if you want to install OTRS, you will have
|
||||
to disable SELinux. Well, I won’t.
|
||||
|
||||
During the last few months, I have been using Fedora 18 with SELinux on all of my desktop machines
|
||||
and on my notebook, and I had no problems at all. Meanwhile I got familiar with SELinux itself,
|
||||
and got used to solving problems caused by it. So I started ``tail -f /var/log/httpd/error_log``
|
||||
in one terminal (to see if something Apache related thing appears), ``tail -f
|
||||
/var/log/audit/audit.log`` in another (to see errors caused by SELinux), opened the admin manual
|
||||
at the installation chapter, took a deep breath, and went on.
|
||||
|
||||
Throughout this article, I will refer to OTRS 3.2.6 as OTRS and Fedora 18 (with only “stock”
|
||||
repositories) as Fedora. I assume that you have already installed OTRS in a non-SELinux
|
||||
environment before, and that you have at least some basic knowledge about SELinux, MAC, RBAC, and
|
||||
all the like. I’m installing OTRS in ``/opt/otrs``, so if you install it somewhere else, you will
|
||||
have to modify the paths below. Also, if you happen to install under ``/var/www`` (I wouldn’t
|
||||
recommend it), that directory already has the ``httpd_sys_content_t`` type, so you won’t have to
|
||||
set it explicitly.
|
||||
|
||||
As the first step I have unpacked the archive to ``/opt/otrs``. This directory is the OTRS
|
||||
default, many config files have it hardcoded, and changing it is no easy task.
|
||||
|
||||
Running ``otrs.CheckModules.pl`` gave me a list of missing perl modules. Red Hat and Fedora makes
|
||||
it easy to install these, as you don’t have to know the RPM package name, just the perl module
|
||||
name:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
yum install 'perl(Crypt::SSLeay)' \
|
||||
'perl(DBD::Pg)' \
|
||||
'perl(GD)' \
|
||||
'perl(JSON::XS)' \
|
||||
'perl(GD::Text)' \
|
||||
'perl(GD::Graph)' \
|
||||
'perl(Mail::IMAPClient)' \
|
||||
'perl(Net::DNS)' \
|
||||
'perl(PDF::API2)' \
|
||||
'perl(Text::CSV_XS)' \
|
||||
'perl(YAML::XS)'
|
||||
|
||||
I also needed to install ``mod_perl``. Although ``otrs.CheckModules.pl`` didn’t mention it, the
|
||||
default settings use syslog as the logging module, so unless you change it in ``Config.pm``, you
|
||||
will also need to install ``'perl(Unix::Syslog)'``, either.
|
||||
|
||||
The default SELinux policy doesn’t permit any network connection to be initiated by Apache httpd.
|
||||
As OTRS needs to connect to its database, you need to enable it explicitly. In older
|
||||
distributions, the ``httpd_can_network_connect`` was the SELinux boolean for this, but recent
|
||||
installations also have a ``httpd_can_network_connect_db`` flag. As far as I know, this enables
|
||||
all network connections to the well-known database servers’ default port, but I will have to check
|
||||
for it. For me, with a MySQL listening on its standard port, the ``setsebool
|
||||
httpd_can_network_connect_db=1`` command just did it.
|
||||
|
||||
With SELinux enabled, Apache won’t be able to read anything that’s not marked with the
|
||||
``httpd_sys_content_t`` type, nor write anywhere without the ``httpd_sys_rw_content_t`` type. The
|
||||
trivial, quick and dirty solution is to label all the files as ``httpd_sys_rw_content_t``, and let
|
||||
everything go. However, the goal of SELinux is just the opposite of this: grant access only to
|
||||
what is really needed. After many trial-and-error steps, it finally turned out that for OTRS to
|
||||
work correctly, you must set
|
||||
|
||||
* ``httpd_sys_content_t``
|
||||
|
||||
* on ``/opt/otrs/var/httpd/htdocs``
|
||||
|
||||
* ``httpd_script_exec_t``
|
||||
|
||||
* on ``/opt/otrs/bin/cgi-bin``
|
||||
|
||||
* ``httpd_sys_rw_content_t``
|
||||
|
||||
* on ``/opt/otrs/Kernel``
|
||||
* on ``/opt/otrs/var/sessions``
|
||||
* on ``/opt/otrs/var/log`` (unless you use syslog for logging)
|
||||
* on ``/opt/otrs/var/packages`` (this is used only when you download an .opm package)
|
||||
* on ``/opt/otrs/var/stats``
|
||||
* on ``/opt/otrs/var/tmp``
|
||||
* on ``/opt/otrs/bin`` (I wonder why this is required, though)
|
||||
|
||||
To do this, use the following command:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
semanage fcontext -a -t <context> <directory regex>
|
||||
|
||||
Where ``<directory regex>`` is something like ``/opt/otrs/Kernel(/.*)?``. When this is done, all
|
||||
you have to do is running ``restorecon -vR /opt/otrs`` so it will relabel everything with the
|
||||
correct types (you can omit ``-v``, I just like to see what my software do).
|
||||
|
||||
The last thing I faced is that Fedora is more restrictive on reading directories other than
|
||||
``/var/www``. It has a ``Require all denied`` on ``<Directory />``, and a ``Require all granted``
|
||||
on ``<Directory /var/www>``, so ``/opt/otrs/var/httpd/htdocs`` will throw a ``403 Forbidden
|
||||
(client denied by server configuration)`` error. To get rid of this, I had to modify
|
||||
``scripts/apache2-httpd.include.conf`` and add ``Require all granted`` to both the ``cgi-bin`` and
|
||||
``htdocs`` directories.
|
||||
|
||||
As I will have to use OTRS in a production environment soon with SELinux enabled, it is more than
|
||||
sure that this list will change in the near future. As there are no official documentation on
|
||||
this (I haven’t find one yet), I have to do it with the trial-and-error way, so be patient!
|
25
content/blog/2013-09-16-swe-glib-final-release.rst
Normal file
@@ -0,0 +1,25 @@
|
||||
SWE-GLib final release
|
||||
######################
|
||||
|
||||
:date: 2013-09-16T21:37:17Z
|
||||
:category: blog
|
||||
:tags: development,astrology
|
||||
:url: blog/2013/9/16/swe-glib-final-release.html
|
||||
:save_as: blog/2013/9/16/swe-glib-final-release.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
Few of you may know that I’m interested in astrology. About two months ago I have decided to
|
||||
create an astrologers’ software for the GNOME desktop. Since then, I have contacted Jean-André
|
||||
Santoni, who created a software called `Astrognome <https://code.google.com/p/astrognome/>`_ some
|
||||
years ago. We exchanged some e-mails, and after several weeks of coding, I’m proud to present
|
||||
`SWE-GLib <https://github.com/gergelypolonkai/swe-glib>`_ 1.0.1. This is “just” a library which
|
||||
wraps `Swiss Ephemeris <http://www.astro.com/swisseph/>`_, creating a nice GLib-ish interface
|
||||
around it. See the project page and the built-in GTK-Doc document for more information.
|
||||
|
||||
The astrologer’s software I’m writing will be Astrognome (you can check the `GitHub repository
|
||||
<https://github.com/gergelypolonkai/astrognome>`_ already, thanks for Jean-André for letting me
|
||||
use the name). It is currently in pre-alpha status, but already utilizes SWE-GLib (it just can’t
|
||||
display the results yet). If you happen to be interested in astrology and/or Astrognome, fork the
|
||||
repository and contribute! You can also contact me (or open an enhancement issue on GitHub) if
|
||||
you have any ideas.
|
@@ -0,0 +1,22 @@
|
||||
From Symfony to Django in two days
|
||||
##################################
|
||||
|
||||
:date: 2013-09-24T14:05:22Z
|
||||
:category: blog
|
||||
:tags: development,symfony,django
|
||||
:url: blog/2013/9/24/from-symfony-to-django-in-two-days.html
|
||||
:save_as: blog/2013/9/24/from-symfony-to-django-in-two-days.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
I was a Python hater for a long time, although I can’t really tell why. It didn’t fit in my mind,
|
||||
maybe. I was programming in BASIC, Pascal (none of these would come to my mind now, though), C,
|
||||
PHP, Perl, JavaScript, and different shell “languages” like awk, sed or bash.
|
||||
|
||||
After I could not fit my next Symfony app on my cloud server (it is pretty low on storage), I have
|
||||
decided to move slowly to Django. My first task was simple: transition my web page (this one)
|
||||
from PHP + Symfony 2 to Python + Django. The results: the “static” pages are already working, the
|
||||
blog listing is almost ready (some styling issues are still around), only tagging remains. And
|
||||
this is after about 6 hours of work. Oh, and the admin site is included with Django, so I don’t
|
||||
have to port that. I have also decided to finally integrate a comment feature in the Django
|
||||
version.
|
25
content/blog/2013-11-05-first-impressions-of-windows-8.rst
Normal file
@@ -0,0 +1,25 @@
|
||||
First impressions of Windows 8
|
||||
##############################
|
||||
|
||||
:date: 2013-11-05T08:14:50Z
|
||||
:category: blog
|
||||
:tags: windows
|
||||
:url: blog/2013/11/5/first-impressions-of-windows-8.html
|
||||
:save_as: blog/2013/11/5/first-impressions-of-windows-8.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
Many of you may know my commitment to Linux and Open Source Software. But this doesn’t mean I
|
||||
hate proprietary software like many others do. I think everything has its own place in the world,
|
||||
and this goes for software as well.
|
||||
|
||||
A few days ago I got my hands on a new notebook, thanks to my company. It was shipped with
|
||||
Windows 8 by default, and although I installed Fedora 19 in an instant (which went smoothlessly,
|
||||
even with Secure Boot enabled), I’ve decided to give a try to this new Windows Version.
|
||||
|
||||
Being a heavy Windows 7 user, my first thought was “What the hell is this?” But in a day, I got
|
||||
totally used to it. I don’t miss the Start button at all. The applications already installed
|
||||
were almost enough for me (I still need Office. Maybe I’ll also enroll for Office 365 later…),
|
||||
and the games are great and beautiful too. So overall, this new version may be totally different
|
||||
(by the looks), but it seems almost the same Windows as we know it. So if you don’t freak out by
|
||||
touching something new, go give it a try: don’t instant-remove 8 in favour of 7!
|
@@ -0,0 +1,60 @@
|
||||
List Git branches and their remote tracking branches side by side
|
||||
#################################################################
|
||||
|
||||
:date: 2014-07-18T21:46:45Z
|
||||
:category: blog
|
||||
:tags: git
|
||||
:url: blog/2014/7/18/list-git-branches-and-their-remote-tracking-branches-side-by-side.html
|
||||
:save_as: blog/2014/7/18/list-git-branches-and-their-remote-tracking-branches-side-by-side.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
I had a hard time following my own branches in a project. They got pretty numerous, and I wasn’t
|
||||
sure if I pushed them to ``origin`` at all. ``git branch -a`` can list all the branches,
|
||||
including remote ones, but, as my list grew too big, it was impossible to follow it any more.
|
||||
|
||||
Thus, I have created a small script called ``git-branches-with-remotes``, which does the work for
|
||||
me. Its only requirements are git (of course), and the ``column`` command, which is pretty
|
||||
obviously present on every POSIX compliant systems (even OSX).
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
#! /bin/sh
|
||||
|
||||
COLUMN=`which column 2> /dev/null`
|
||||
if test -z $COLUMN
|
||||
then
|
||||
echo "\`column' is not found in PATH. Cannot continue."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
current_branch=`git rev-parse --abbrev-ref HEAD`
|
||||
|
||||
for branch in $(git for-each-ref --shell --format='%(refname)' refs/heads | sed -e s/^\'refs\\/heads\\/// -e s/\'$//)
|
||||
do
|
||||
remote=`git config branch.$branch.remote`
|
||||
merge=`git config branch.$branch.merge | sed -e 's/^refs\/heads\///'`
|
||||
|
||||
[ x"$current_branch" == x"$branch" ] && echo -n '*'
|
||||
|
||||
echo -n "$branch"
|
||||
|
||||
if ! test -z $merge
|
||||
then
|
||||
echo -en "\t"
|
||||
echo -n $remote
|
||||
echo -n /
|
||||
echo -n $merge
|
||||
fi
|
||||
|
||||
echo
|
||||
done | $COLUMN -t
|
||||
|
||||
I just put it in my path, and ``git branches-with-remotes`` does the work!
|
||||
|
||||
Edit (16 August): I have added some code to mark the current branch (if any) with an asterisk.
|
||||
Also, I have put this script `in a gist
|
||||
<https://gist.github.com/gergelypolonkai/8af6a3e86b57dd4c250e>`_.
|
||||
|
||||
Edit (26 February, 2015): It turns out that ``git branch -vv`` shows the same information and some
|
||||
more: it also shows if the branches are diverged, and the first line of the last commit’s message.
|
@@ -0,0 +1,148 @@
|
||||
Registering an enum type in GLib, glib-mkenums magic
|
||||
####################################################
|
||||
|
||||
:date: 2014-08-16T15:10:54Z
|
||||
:category: blog
|
||||
:tags: development,c,glib
|
||||
:url: blog/2014/8/16/registering-an-enum-type-in-glib-glib-mkenums-magic.html
|
||||
:save_as: blog/2014/8/16/registering-an-enum-type-in-glib-glib-mkenums-magic.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
In `this post <{filename}2013-01-06-registering-an-enum-type-in-glib-s-type-system.rst>`_ I said I
|
||||
will get through the GLib Makefiles to add an enum type to GLib in a more sophisticated way.
|
||||
|
||||
In my other project, `SWE-GLib <https://github.com/gergelypolonkai/swe-glib>`_ I already used this
|
||||
method. The following two rules in ``Makefile.am`` create ``gswe-enumtypes.h`` and
|
||||
``gswe-enumtypes.c``.
|
||||
|
||||
.. code-block:: makefile
|
||||
|
||||
gswe_enum_headers = headers-that-contain-enums.h
|
||||
|
||||
gswe-enumtypes.h: $(gswe_enum_headers) gswe-enumtypes.h.template
|
||||
$(GLIB_MKENUMS) --template $(filter %.template,$^) $(filter-out %.template,$^) > \
|
||||
gswe-enumtypes.h.tmp && mv gswe-enumtypes.h.tmp gswe-enumtypes.h
|
||||
gswe-enumtypes.c: $(gswe_enum_headers) gswe-enumtypes.h gswe-enumtypes.c.template
|
||||
$(GLIB_MKENUMS) --template $(filter %.template,$^) $(filter-out %.template,$^) > \
|
||||
gswe-enumtypes.c.tmp && mv gswe-enumtypes.c.tmp gswe-enumtypes.c
|
||||
|
||||
``$(GLIB_MKENUMS)`` is set in ``configure`` using
|
||||
|
||||
.. code-block:: m4
|
||||
|
||||
AC_PATH_PROG([GLIB_MKENUMS], [glib-mkenums])
|
||||
|
||||
This approach requires the GNU Autotools (you can get rid of it by changing ``$(GLIB_MKENUMS)`` to
|
||||
the path to ``glib-mkenums`` binary), and two template files, one for the header and one for the
|
||||
code. ``$(gswe_enum_headers)`` contains a list of all the header files that have enum types
|
||||
defined throughout the project.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/*** BEGIN file-header ***/
|
||||
/* gswe-enumtypes.h - Enumeration types for SWE-GLib
|
||||
*
|
||||
* Copyright © 2013 Gergely Polonkai
|
||||
*
|
||||
* SWE-GLib is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* SWE-GLib is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef __GSWE_ENUM_TYPES_H__
|
||||
#define __GSWE_ENUM_TYPES_H__
|
||||
#include <glib-object.h>
|
||||
|
||||
/*** END file-header ***/
|
||||
|
||||
/*** BEGIN file-production ***/
|
||||
/* enumerations from "@filename@" */
|
||||
|
||||
#include "@filename@"
|
||||
/*** END file-production ***/
|
||||
|
||||
/*** BEGIN value-header ***/
|
||||
GType @enum_name@_get_type(void);
|
||||
#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type())
|
||||
/*** END value-header ***/
|
||||
|
||||
/*** BEGIN file-tail ***/
|
||||
|
||||
#endif /* __GSWE_ENUM_TYPES_H__ */
|
||||
/*** END file-tail ***/
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/*** BEGIN file-header ***/
|
||||
/* gswe-enumtypes.c - Enumeration types for SWE-GLib
|
||||
*
|
||||
* Copyright © 2013 Gergely Polonkai
|
||||
*
|
||||
* SWE-GLib is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* SWE-GLib is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "swe-glib.h"
|
||||
#include "gswe-enumtypes.h"
|
||||
#include "@filename@"
|
||||
|
||||
/*** END file-header ***/
|
||||
|
||||
/*** BEGIN file-production ***/
|
||||
/* enumerations from "@filename@" */
|
||||
/*** END file-production ***/
|
||||
|
||||
/*** BEGIN value-header ***/
|
||||
GType
|
||||
@enum_name@_get_type(void)
|
||||
{
|
||||
static volatile gsize g_define_type_id__volatile = 0;
|
||||
|
||||
gswe_init();
|
||||
|
||||
if (g_once_init_enter(&g;_define_type_id__volatile)) {
|
||||
static const G@Type@Value values[] = {
|
||||
/*** END value-header ***/
|
||||
|
||||
/*** BEGIN value-production ***/
|
||||
{
|
||||
@VALUENAME@,
|
||||
"@VALUENAME@",
|
||||
"@valuenick@"
|
||||
},
|
||||
/*** END value-production ***/
|
||||
|
||||
/*** BEGIN value-tail ***/
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
GType g_define_type_id = g_@type@_register_static(
|
||||
g_intern_static_string("@EnumName@"),
|
||||
values
|
||||
);
|
||||
|
||||
g_once_init_leave(&g;_define_type_id__volatile, g_define_type_id);
|
||||
}
|
||||
|
||||
return g_define_type_id__volatile;
|
||||
}
|
||||
|
||||
/*** END value-tail ***/
|
14
content/blog/2014-09-17-nyanmacs.rst
Normal file
@@ -0,0 +1,14 @@
|
||||
NyanMacs
|
||||
########
|
||||
|
||||
:date: 2014-09-17T12:45:42Z
|
||||
:category: blog
|
||||
:tags: emacs
|
||||
:url: blog/2014/9/17/nyanmacs.html
|
||||
:save_as: blog/2014/9/17/nyanmacs.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
I was a Vi/ViM user for years. For several reasons I had to change to Emacs now and then. And
|
||||
then, I found `this <https://github.com/TeMPOraL/nyan-mode/>`_. I surrender. Emacs is just
|
||||
better. (And this addon is working even in plain text mode without graphics)
|
@@ -0,0 +1,40 @@
|
||||
Rounding numbers to N decimals in Emacs
|
||||
#######################################
|
||||
|
||||
:date: 2014-10-07T10:28:50Z
|
||||
:category: blog
|
||||
:tags: emacs,development
|
||||
:url: blog/2014/10/7/rounding-numbers-to-n-decimals-in-emacs.html
|
||||
:save_as: blog/2014/10/7/rounding-numbers-to-n-decimals-in-emacs.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
I have recently faced a problem, where I had a bunch of SVG files with a large amount of fraction
|
||||
numbers in the path definitions. These images were displayed in small size, so this amount of
|
||||
precision was irrelevant, and these numbers took almost half of my SVG images’ size. So I created
|
||||
an Elisp defun to round these numbers to 2 decimals:
|
||||
|
||||
.. code-block:: lisp
|
||||
|
||||
(defun get-number-at-point ()
|
||||
(interactive)
|
||||
(skip-chars-backward "0123456789.-")
|
||||
(or (looking-at "[0123456789.-]+")
|
||||
(error "No number at point"))
|
||||
(string-to-number (match-string 0)))
|
||||
|
||||
(defun round-number-at-point-to-decimals (decimal-count)
|
||||
(interactive "NDecimal count: ")
|
||||
(let ((mult (expt 10 decimal-count)))
|
||||
(replace-match (number-to-string
|
||||
(/
|
||||
(fround
|
||||
(*
|
||||
mult
|
||||
(get-number-at-point)))
|
||||
mult)))))
|
||||
|
||||
This finds the first digit of the number under point (the cursor), and reduces its digits to the
|
||||
given amount (or the number given with :kbd:`C-u`). It has some drawbacks, though, as it cannot
|
||||
handle exponential forms (e.g. ``1e-1234``), but these were rare in my case, and its hard to
|
||||
iterate through all numbers. I will come over this latter problem soon(ish).
|
@@ -0,0 +1,44 @@
|
||||
Using Git bisect to find the first good commit
|
||||
##############################################
|
||||
|
||||
:date: 2015-02-26T10:42:56Z
|
||||
:category: blog
|
||||
:tags: git
|
||||
:url: blog/2015/2/26/using-git-bisect-to-find-the-first-good-commit.html
|
||||
:save_as: blog/2015/2/26/using-git-bisect-to-find-the-first-good-commit.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
Few months ago we “implemented” a bug in our software, which was released to the customers. We
|
||||
continued development for two weeks when the first customer ticket arrived about the bug. We
|
||||
successfully reproduced it with the customer’s version, but not with the development sources; it
|
||||
turned out that one of the developers unconsciously fixed the bug. The devs spent some hours
|
||||
finding where the fix lied before coming to me like “There is ``git-bisect`` which we can use to
|
||||
find the commit where we messed up things. Is there a way to find where we fixed it?”
|
||||
|
||||
For those who don’t know this feature, you have to mark a known “good” and “bad” commit, then
|
||||
git-bisect will go through the commits between this two, present you the corresponding snapshots,
|
||||
and you have to mark each of them as “good” or “bad”. At the end, you will get a commit hash
|
||||
where the bug first occured.
|
||||
|
||||
As it turned out, our developers’ problem rooted in the naming convention of git-bisect: they
|
||||
assumed that the “good” commit must be a working one, while a “bad” one must be the buggy. In
|
||||
this case, we did the following:
|
||||
|
||||
The commit with the customer’s release tag was marked as good (even though this had the bug), and
|
||||
the latest commit on our development branch was marked as “bad” (even though the bug was fixed by
|
||||
then). Now with every snapshot presented by git-bisect we had to do the opposite what you usually
|
||||
do: mark commits still having the bug as “good”, and commits that don’t as “bad”. At the end, we
|
||||
had the hash of the commit that fixed the bug (among some other things; luckily, the developer who
|
||||
pushed that commit had a workflow that introduced a lot of cherry-picking and squashing before the
|
||||
push, so he could easily find the bit that actually fixed the problem in his local repository with
|
||||
the same technique).
|
||||
|
||||
`This StackOverflow answer <http://stackoverflow.com/a/17153598/1305139>`_ suggests the very same,
|
||||
but with some aliases:
|
||||
|
||||
.. code-block:: dosini
|
||||
|
||||
[alias]
|
||||
bisect-fixed = bisect bad
|
||||
bisect-unfixed = bisect good
|
@@ -0,0 +1,19 @@
|
||||
Good bye, Digital Ocean! Hello again, GitHub!
|
||||
#############################################
|
||||
|
||||
:date: 2015-04-25T21:18:56Z
|
||||
:category: blog
|
||||
:url: blog/2015/4/25/good-bye-digital-ocean-hello-again-github.html
|
||||
:save_as: blog/2015/4/25/good-bye-digital-ocean-hello-again-github.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
Few years ago I have signed up for a `Digital Ocean <https://www.digitalocean.com/>`_ account. I
|
||||
used one single droplet for my private needs, like hosting my private Git repositories and my
|
||||
blog. However, as I didn’t host anything else there except my blog, I decided to shut it down.
|
||||
From now on, my blog is on `GitHub Pages <https://pages.github.com/>`_, as it provides just
|
||||
everything I need (except automatically converting my resume to PDF. But I can live without
|
||||
that.)
|
||||
|
||||
I’m really sorry, Digital Ocean Guys, your hosting is awesome and I’ll keep recommending you to
|
||||
others, but paying for a droplet for one single blog is overkill.
|
@@ -0,0 +1,60 @@
|
||||
Cross browser border-radius SASS mixin with varargs
|
||||
###################################################
|
||||
|
||||
:date: 2015-04-27T22:59:56Z
|
||||
:category: blog
|
||||
:tags: css,sass
|
||||
:url: blog/2015/4/28/cross-browser-border-radius-sass-mixin-with-varargs.html
|
||||
:save_as: blog/2015/4/28/cross-browser-border-radius-sass-mixin-with-varargs.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
Few days ago I needed to create style sheets with many rounded boxes, where different corners had
|
||||
to be rounded differently (think about Bootstrap’s `button groups
|
||||
<http://getbootstrap.com/components/#btn-groups>`_).
|
||||
|
||||
CSS has this nifty shorthand to specify border width in one line, like with ``border-width: 1px
|
||||
2px 3px 4px``, but it lacks the same for ``border-radius``. So I decided to create something
|
||||
similar using `Sass mixins <http://sass-lang.com/guide#topic-6>`_ with dynamic parameters.
|
||||
Another nice feature you get using the ``border-width`` shorthand is that you can specify less
|
||||
than four parameters, and the values will be applied on different sides of your box, so in the end
|
||||
all side will have the whole ``border-width`` set.
|
||||
|
||||
I wanted to achieve the same for my ``border-radius`` mixin, although I
|
||||
could not start specifically with the `top` side. I decided to go with
|
||||
the top right corner for the first parameter, while trying to keep a
|
||||
sane repeating pattern. Here is the result:
|
||||
|
||||
.. code-block:: sass
|
||||
|
||||
=border-width($t, $r: $t, $b: $t, $l: $r)
|
||||
border-top-width: $t
|
||||
border-right-width: $r
|
||||
border-bottom-width: $b
|
||||
border-left-width: $l
|
||||
|
||||
=border-top-right-radius($value)
|
||||
border-top-right-radius: $value
|
||||
-moz-border-top-right-radius: $value
|
||||
-webkit-border-top-right-radius: $value
|
||||
|
||||
=border-top-left-radius($value)
|
||||
border-top-left-radius: $value
|
||||
-moz-border-top-left-radius: $value
|
||||
-webkit-border-top-left-radius: $value
|
||||
|
||||
=border-bottom-right-radius($value)
|
||||
border-bottom-right-radius: $value
|
||||
-moz-border-bottom-right-radius: $value
|
||||
-webkit-border-bottom-right-radius: $value
|
||||
|
||||
=border-bottom-left-radius($value)
|
||||
border-bottom-left-radius: $value
|
||||
-moz-border-bottom-left-radius: $value
|
||||
-webkit-border-bottom-left-radius: $value
|
||||
|
||||
=border-radius($tr, $br: $tr, $bl: $br, $tl: $tr)
|
||||
+border-top-right-radius($tr)
|
||||
+border-bottom-right-radius($br)
|
||||
+border-bottom-left-radius($bl)
|
||||
+border-top-left-radius($tl)
|
154
content/blog/2015-06-07-paramconverter-a-la-django.rst
Normal file
@@ -0,0 +1,154 @@
|
||||
@ParamConverter à la Django
|
||||
###########################
|
||||
|
||||
:date: 2015-06-07T18:14:32Z
|
||||
:category: blog
|
||||
:tags: python,django
|
||||
:url: 2015/06/07/paramconverter-a-la-django/
|
||||
:save_as: 2015/06/07/paramconverter-a-la-django/index.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
One thing I really miss from `Django <https://www.djangoproject.com/>`_ is `Symfony
|
||||
<http://symfony.com/>`_’s `@ParamConverter
|
||||
<http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/converters.html>`_. It
|
||||
made my life so much easier while developing with Symfony. In Django, of course, there is
|
||||
`get_object_or_404
|
||||
<https://docs.djangoproject.com/en/dev/topics/http/shortcuts/#get-object-or-404>`_ but, for
|
||||
example, in one of my projects I had a view that had to resolve 6(!) objects from the URL, and
|
||||
writing ``get_object_or_404`` six times is not what a programmer likes to do (yes, this view had a
|
||||
refactor later on). A quick Google search gave me one `usable result
|
||||
<http://openclassrooms.com/forum/sujet/middleware-django-genre-paramconverter-doctrine>`_ (in
|
||||
French), but it was very generalized that I cannot always use. Also, it was using a middleware,
|
||||
which may introduce performance issues sometimes :sup:`[citation needed]`. So I decided to go
|
||||
with decorators, and at the end, I came up with this:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import re
|
||||
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.db import models
|
||||
|
||||
def convert_params(*params_to_convert, **options):
|
||||
"""
|
||||
Convert parameters to objects. Each parameter to this decorator
|
||||
must be a model instance (subclass of django.db.models.Model) or a
|
||||
tuple with the following members:
|
||||
* model: a Model subclass
|
||||
* param_name: the name of the parameter that holds the value to be
|
||||
matched. If not exists, or is None, the model’s class name will
|
||||
be converted from ModelName to model_name form, suffixed with
|
||||
"_id". E.g. for MyModel, the default will be my_model_id
|
||||
* the field name against which the value in param_name will be
|
||||
matched. If not exists or is None, the default will be "id"
|
||||
* obj_param_name: the name of the parameter that will hold the
|
||||
resolved object. If not exists or None, the default value will
|
||||
be the model’s class name converted from ModelName to model_name
|
||||
form, e.g. for MyModel, the default value will be my_model.
|
||||
The values are resolved with get_object_or_404, so if the given
|
||||
object doesn’t exist, it will redirect to a 404 page. If you want
|
||||
to allow non-existing models, pass prevent_404=True as a keyword
|
||||
argument.
|
||||
"""
|
||||
|
||||
prevent_404 = options.pop('prevent_404', False)
|
||||
|
||||
def is_model(m):
|
||||
return issubclass(type(m), models.base.ModelBase)
|
||||
|
||||
if len(params_to_convert) == 0:
|
||||
raise ValueError("Must pass at least one parameter spec!")
|
||||
|
||||
if (
|
||||
len(params_to_convert) == 1 and \
|
||||
hasattr(params_to_convert[0], '__call__') and \
|
||||
not is_model(params_to_convert[0])):
|
||||
raise ValueError("This decorator must have arguments!")
|
||||
|
||||
def convert_params_decorator(func):
|
||||
def wrapper(*args, **kwargs):
|
||||
converted_params = ()
|
||||
for pspec in params_to_convert:
|
||||
# If the current pspec is not a tuple, let’s assume
|
||||
# it’s a model class
|
||||
if not isinstance(pspec, tuple):
|
||||
pspec = (pspec,)
|
||||
|
||||
# First, and the only required element in the
|
||||
# parameters is the model name which this object
|
||||
# belongs to
|
||||
model = pspec[0]
|
||||
|
||||
if not is_model(model):
|
||||
raise ValueError(
|
||||
"First value in pspec must be a Model subclass!")
|
||||
|
||||
# We will calculate these soon…
|
||||
param_name = None
|
||||
calc_obj_name = re.sub(
|
||||
'([a-z0-9])([A-Z])',
|
||||
r'\1_\2',
|
||||
re.sub(
|
||||
'(.)([A-Z][a-z]+)',
|
||||
r'\1_\2',
|
||||
model.__name__)).lower()
|
||||
obj_field_name = None
|
||||
|
||||
# The second element, if not None, is the keyword
|
||||
# parameter name that holds the value to convert
|
||||
if len(pspec) < 2 or pspec[1] is None:
|
||||
param_name = calc_obj_name + '_id'
|
||||
else:
|
||||
param_name = pspec[1]
|
||||
|
||||
if param_name in converted_params:
|
||||
raise ValueError('%s is already converted' % param_name)
|
||||
|
||||
converted_params += (param_name,)
|
||||
field_value = kwargs.pop(param_name)
|
||||
|
||||
# The third element is the field name which must be
|
||||
# equal to the specified value. If it doesn’t exist or
|
||||
# None, it defaults to 'id'
|
||||
if (len(pspec) < 3) or pspec[2] is None:
|
||||
obj_field_name = 'id'
|
||||
else:
|
||||
obj_field_name = pspec[2]
|
||||
|
||||
# The fourth element is the parameter name for the
|
||||
# object. If the parameter already exists, we consider
|
||||
# it an error
|
||||
if (len(pspec) < 4) or pspec[3] is None:
|
||||
obj_param_name = calc_obj_name
|
||||
else:
|
||||
obj_param_name = pspec[3]
|
||||
|
||||
if obj_param_name in kwargs:
|
||||
raise KeyError(
|
||||
"'%s' already exists as a parameter" % obj_param_name)
|
||||
|
||||
filter_kwargs = {obj_field_name: field_value}
|
||||
|
||||
if (prevent_404):
|
||||
kwargs[obj_param_name] = model.objects.filter(
|
||||
**filter_kwargs).first()
|
||||
else:
|
||||
kwargs[obj_param_name] = get_object_or_404(
|
||||
model,
|
||||
**filter_kwargs)
|
||||
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
return convert_params_decorator
|
||||
|
||||
Now I can decorate my views, either class or function based, with ``@convert_params(User,
|
||||
(Article, 'aid'), (Paragraph, None, 'pid'), (AnotherObject, None, None, 'obj'))`` and all the
|
||||
magic happens in the background. The ``user_id`` parameter passed to my function will be popped
|
||||
off, and be resolved against the ``User`` model by using the ``id`` field; the result is put in
|
||||
the new ``user`` parameter. For Article, the ``aid`` parameter will be matched against the ``id``
|
||||
field of the ``Article`` model putting the result into ``article``, and finally, the
|
||||
``another_object_id`` will be matched against the ``id`` field of the ``AnotherObject`` model, but
|
||||
in this case, the result is passed to the original function as ``obj``.
|
17
content/blog/2015-08-19-foss-failmeter.rst
Normal file
@@ -0,0 +1,17 @@
|
||||
F/OSS Fail meter
|
||||
################
|
||||
|
||||
:date: 2015-08-19T10:12:19Z
|
||||
:category: blog
|
||||
:tags: development
|
||||
:url: 2015/08/19/foss-failmeter/
|
||||
:save_as: 2015/08/19/foss-failmeter/index.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
I have recently bumped into `this article <http://spot.livejournal.com/308370.html>`_. Naturally,
|
||||
I quickly calculated the FAIL metrics for all my projects (most of them are pretty high). To ease
|
||||
calculation, I made up a `small page <{static}../failmeter/index.html>`_ based on this list
|
||||
(although I have divided the points by 5; I really don’t understand why spot is using such big
|
||||
points if all of them can be divided by 5). Feel free to use it, and if you have any
|
||||
recommendations (point additions/removal, new categories, etc.), leave me a comment!
|
201
content/blog/2015-08-27-how-my-email-gets-to-that-other-guy.rst
Normal file
@@ -0,0 +1,201 @@
|
||||
How my e-mail gets to that other guy?
|
||||
#####################################
|
||||
|
||||
:date: 2015-08-27T21:47:19Z
|
||||
:category: blog
|
||||
:tags: technology
|
||||
:url: 2015/08/27/how-my-email-gets-to-that-other-guy/
|
||||
:save_as: 2015/08/27/how-my-email-gets-to-that-other-guy/index.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
A friend of mine asked me how it is possible that she pushes buttons on her keyboard and mouse,
|
||||
and in an instant her peer reads the text she had in her mind. This is a step-by-step
|
||||
introduction of what happens in-between.
|
||||
|
||||
From your mind to your computer
|
||||
===============================
|
||||
|
||||
When you decide to write an e-mail to an acquaintance of yours, you open up your mailing software
|
||||
(this document doesn’t cover using mail applications you access through your browsers, just plain
|
||||
old Thunderbird, Outlook or similar programs. However, it gets the same after the mail left your
|
||||
computer), and press the “New Mail” button. What happens during this process is not covered in
|
||||
this article, but feel free to ask me in a comment! Now that you have your Mail User Agent (MUA)
|
||||
up and running, you begin typing.
|
||||
|
||||
When you press a button on your keyboard or mouse, a bunch of bits gets through the wire (or
|
||||
through air, if you went wireless) and get into your computer. I guess you learned about Morse
|
||||
during school; imagine two `Morse operators
|
||||
<http://www.uscupstate.edu/academics/education/aam/lessons/susan_sawyer/morse%20code.jpg>`_, one
|
||||
in your keyboard/mouse, and one in your computer. Whenever you press a key, that tiny creature
|
||||
sends a series of short and long beeps (called 0 or 1 bits, respectively) to the operator in your
|
||||
computer (fun fact: have you ever seen someone typing at an amazing speed of 5 key presses per
|
||||
second? Now imagine that whenever that guy presses a key on their keyboard, that tiny little
|
||||
Morse operator pressing his button 16 times for each key press, with perfect timing so that the
|
||||
receiving operator can decide if that was a short or long beep.)
|
||||
|
||||
Now that the code got to the operator inside the machine, it’s up to him to decode it. The funny
|
||||
thing about keyboards and computers is that the computer doesn’t receive the message “Letter Q was
|
||||
pressed”, but instead “The second button on the second row was pressed” (a number called scan
|
||||
code). At this time the operator decodes this information (in this example it is most likely this
|
||||
Morse code: ``···-···· -··-····``) and checks one of his tables titled “Current Keyboard Layout.”
|
||||
It says this specific key corresponds to letter ‘Q’, so it forwards this information (I mean the
|
||||
letter; after this step your computer doesn’t care which plastic slab you hit, just the letter
|
||||
‘Q’) to your MUA, inserts it into the mail in its memory, then displaying it happily (more about
|
||||
this step later).
|
||||
|
||||
When you finish your letter you press the send button of your MUA. First it converts all the
|
||||
pretty letters and pictures to something a computer can understand (yes, those Morse codes, or
|
||||
more precisely, zeros and ones, again). Then it adds loads of meta data, like your name and
|
||||
e-mail address, the current date and time including the time zone and pass it to the sending parts
|
||||
of the MUA so the next step can begin.
|
||||
|
||||
IP addresses, DNS and protocols
|
||||
===============================
|
||||
|
||||
The Internet is a huge amount of computers connected with each other, all of them having at least
|
||||
one address called IP address that looks something like this: ``123.234.112.221``. These are four
|
||||
numbers between 0 and 255 inclusive, separated by dots. This makes it possible to have
|
||||
4,294,967,296 computers. With the rules of address assignment added, this is actually reduced to
|
||||
3,702,258,432; a huge number, still, but it is not enough, as in the era of the Internet of Things
|
||||
everything is interconnected, up to and possibly including your toaster. Thus, we are slowly
|
||||
transitioning to a new addressing scheme that looks like this:
|
||||
``1234:5678:90ab:dead:beef:9876:5432:1234``. This gives an enormous amount of
|
||||
340,282,366,920,938,463,463,374,607,431,768,211,456 addresses, with only
|
||||
4,325,185,976,917,036,918,000,125,705,034,137,602 of them being reserved, which gives us only a
|
||||
petty 335,957,180,944,021,426,545,374,481,726,734,073,854 available.
|
||||
|
||||
Imagine a large city with `that many buildings
|
||||
<http://www.digitallifeplus.com/wp-content/uploads/2012/07/new-york-city-aerial-5.jpg>`_, all of
|
||||
them having only a number: their IP address. No street names, no company names, no nothing. But
|
||||
people tend to be bad at memorizing numbers, so they started to give these buildings names. For
|
||||
example there is a house with the number ``216.58.209.165``, but between each other, people call
|
||||
it ``gmail.com``. Much better, isn’t it? Unfortunately, when computers talk, they only
|
||||
understand numbers so we have to provide them just that.
|
||||
|
||||
As remembering this huge number of addresses is a bit inconvenient, we created Domain Name
|
||||
Service, or DNS for short. A “domain name” usually (but not always) consist of two strings of
|
||||
letters, separated by dots (e.g. polonkai.eu, gmail.com, my-very-long-domain.co.uk, etc.), and a
|
||||
hostname is a domain name occasionally prefixed with something (e.g. **www**.gmail.com,
|
||||
**my-server**.my-very-long-domain.co.uk, etc.) One of the main jobs of DNS is to keep record of
|
||||
hostname/address pairs. When you enter ``gmail.com`` (which happens to be both a domain name and a
|
||||
hostname) in your browser’s address bar, your computer asks the DNS service if it knows the actual
|
||||
address of the building that people call ``gmail.com``. If it does, it will happily tell your
|
||||
computer the number of that building.
|
||||
|
||||
Another DNS job is to store some meta data about these domain names. For such meta data there are
|
||||
record types, one of these types being the Mail eXchanger, or MX. This record of a domain tells
|
||||
the world who is handling incoming mails for the specified domain. For ``gmail.com`` this is
|
||||
``gmail-smtp-in.l.google.com`` (among others; there can be multiple records of the same type, in
|
||||
which case they usually have priorities, too.)
|
||||
|
||||
One more rule: when two computers talk to each other they use so called protocols. These
|
||||
protocols define a set of rules on how they should communicate; this includes message formatting,
|
||||
special code words and such.
|
||||
|
||||
From your computer to the mail server
|
||||
=====================================
|
||||
|
||||
Your MUA has two settings called SMTP server address SMTP port number (see about that later).
|
||||
SMTP stands for Simple Mail Transfer Protocol, and defines the rules on how your MUA, or another
|
||||
mail handling computer should communicate with a mail handling computer when *sending* mail. Most
|
||||
probably your Internet Service Provider gave you an SMTP server name, like ``smtp.aol.com`` and a
|
||||
port number like ``587``.
|
||||
|
||||
When you hit that send button of yours, your computer will check with the DNS service for the
|
||||
address of the SMTP server, which, for ``smtp.aol.com``, is ``64.12.88.133``. The computer puts
|
||||
this name/address pair into its memory, so it doesn’t have to ask the DNS again (this technique is
|
||||
called caching and is widely used wherever time consuming operations happen).
|
||||
|
||||
Then it will send your message to the given port number of this newly fetched address. If you
|
||||
imagined computers as office buildings, you can imagine port numbers as departments and there can
|
||||
be 65535 of them in one building. The port number of SMTP is usually 25, 465 or 587 depending on
|
||||
many things we don’t cover here. Your MUA prepares your letter, adding your e-mail address and
|
||||
the recipients’, together with other information that may be useful for transferring your mail.
|
||||
It then puts this well formatted message in an envelope and writes “to building ``64.12.88.133``,
|
||||
dept. ``587``”, and puts it on the wire so it gets there (if the wire is broken, the building does
|
||||
not exist or there is no such department, you will get an error message from your MUA). Your
|
||||
address and the recipient’s address are inside the envelope; other than the MUA, your own computer
|
||||
is not concerned about it.
|
||||
|
||||
The mailing department (or instead lets call it the Mail Transfer Agent, A.K.A. MTA) now opens
|
||||
this envelope and reads the letter. All of it, letter by letter, checking if your MUA formatted
|
||||
it well. More than probably it also runs your message through several filters to decide if you
|
||||
are a bad guy sending some unwanted letter (also known as spam), but most importantly it fetches
|
||||
the recipients address. It is possible, e.g. when you send an e-mail within the same
|
||||
organization, that the recipient’s address is handled by this very same computer. In this case
|
||||
the MTA puts the mail to the recipient’s mailbox and the next step is skipped.
|
||||
|
||||
From one server to another
|
||||
==========================
|
||||
|
||||
Naturally, it is possible to send an e-mail from one company to another, so these MTAs don’t just
|
||||
wait for e-mails from you, but also communicate with each other. When you send a letter from your
|
||||
``example@aol.com`` address to me at ``gergely@polonkai.eu``, this is what happens.
|
||||
|
||||
In this case, the MTA that initially received the e-mail from you (which happened to be your
|
||||
Internet Service Provider’s SMTP server) turns to the DNS again. It will ask for the MX record of
|
||||
the domain name specified by the e-mail address, (the part after the ``@`` character, in my case,
|
||||
``polonkai.eu``), because the server mentioned that must be contacted, so they can deliver your
|
||||
mail for me. My domain is configured so its primary MX record is ``aspmx.l.google.com`` and the
|
||||
secondary is ``alt1.aspmx.l.google.com`` (and 5 more. Google likes to play it safe.) The MTA
|
||||
then gets the first server name, asks the DNS for its address, and tries to send a message to the
|
||||
``173.194.67.27`` (the address of ``aspmx.l.google.com``), same department. But unlike your MUA,
|
||||
MTAs don’t have a pre-defined port number for other MTAs (although there can be exceptions).
|
||||
Instead, they use well-known port numbers, ``465`` and ``25``. If the MTA on that server cannot
|
||||
be contacted for any reason, it tries the next one on the list of MX records. If none of the
|
||||
servers can be contacted, it will retry based on a set of rules defined by the administrators,
|
||||
which usually means it will retry after 1, 4, 24 and 48 hours. If there is still no answer after
|
||||
that many attempts, you will get an error message back, in the form of an e-mail sent directly by
|
||||
the SMTP server.
|
||||
|
||||
Once the other MTA could be contacted, your message is sent there. The original envelope you used
|
||||
is discarded, and a new one is used with the address and dept. number (port) of the receiving MTA.
|
||||
Also, your message gets altered a little bit, as most MTAs are kind enough (ie. not sneaky) to add
|
||||
a clause to your message stating “the MTA at <organization> has checked and forwarded this
|
||||
message.”
|
||||
|
||||
It is possible, though not likely, that your message gets through more than two MTAs (one at your
|
||||
ISP and one at the receiver’s) before arriving to its destination. At the end, an MTA will say
|
||||
that “OK, this recipient address is handled by me”, your message stops and stays there, put in
|
||||
your peer’s mailbox.
|
||||
|
||||
The mailbox
|
||||
-----------
|
||||
|
||||
Now that the MTA has passed your mail to the mailbox team (I call it a team instead of department
|
||||
because the tasks described here are usually handled by the MTA, too), it reads it. (Pesky little
|
||||
guys these mail handling departments, aren’t they?) If the mailbox has some filtering rules, like
|
||||
“if XY sends me a letter, mark it as important” or “if the letter has a specific word in its
|
||||
subject, put it in the XY folder”, it executes them, but the main point is to land the message in
|
||||
the actual post box of the recipient.
|
||||
|
||||
From the post box to the recipients computer
|
||||
============================================
|
||||
|
||||
When the recipient opens their MUA, it will look to a setting usually called “Incoming mail
|
||||
server”. Just like the SMTP server, it has a name and port number, along with a server type.
|
||||
This type can vary from provider to provider, and is usually one of POP3 (pretty old protocol,
|
||||
doesn’t even support folders on its own), IMAP (a newer one, with folders and message flags like
|
||||
“important”), MAPI (a dialect of IMAP, created by Microsoft as far as I know), or plain old mbox
|
||||
files on the receiving computer (this last option is pretty rare nowadays, so I don’t cover this
|
||||
option. Also, if you use these, you most probably don’t really need this article to understand
|
||||
how these things work.) This latter setting defines the protocol, telling your MUA how to “speak”
|
||||
to the post box.
|
||||
|
||||
So your MUA turns to the DNS once more to get the address of your incoming mail server and
|
||||
contacts it, using the protocol set by the server type. At the end, the recipients computer will
|
||||
receive a bunch of envelopes including the one that contains your message. The MUA opens them one
|
||||
by one and reads them, making a list ordered by their sender or subject, or the date of sending.
|
||||
|
||||
From the recipient’s comupter to their eyes
|
||||
===========================================
|
||||
|
||||
When the recipient then clicks on one of these mails, the MUA will fetch all the relevant bits
|
||||
like the sender, the subject line, the date of sending and the contents itself and sends it to the
|
||||
“printing” department (I use quotes as they don’t really print your mail on paper, they just
|
||||
convert it to a nice image so the recipient can see it. This is sometimes referred to as a
|
||||
rendering engine). Based on a bunch of rules they pretty-print it and send it to your display as
|
||||
a new series of Morse codes. Your display then decides how it will present it to the user: draw
|
||||
the pretty pictures if it is a computer screen, or just raise and lower some hard dots that
|
||||
represents letters on a Braille terminal.
|
@@ -0,0 +1,131 @@
|
||||
Emacs: Implement a GObject’s virtual function
|
||||
#############################################
|
||||
|
||||
:date: 2016-01-13T13:31:12Z
|
||||
:category: blog
|
||||
:tags: c,development,emacs
|
||||
:url: 2016/01/13/emacs-implement-a-gobject-s-virtual-function/
|
||||
:save_as: 2016/01/13/emacs-implement-a-gobject-s-virtual-function/index.html
|
||||
:status: published
|
||||
:author: "Gergely Polonkai"
|
||||
|
||||
I have recently started creating a GLib implementation of the Matrix.org API. For that, I have
|
||||
created a GObject interface, MatrixAPI, which has as many virtual functions as API calls (which is
|
||||
a lot, and expanding). This way I ended up with the following scenario.
|
||||
|
||||
In ``matrix-api.h`` I had a struct like this, with a lot more elements:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
typedef struct {
|
||||
void (*initial_sync)(MatrixAPI *api,
|
||||
MatrixAPICallback callback,
|
||||
gpointer user_data,
|
||||
GError **error);
|
||||
void (*sync)(MatrixAPI *api,
|
||||
MatrixAPICallback callback,
|
||||
gpointer user_data,
|
||||
GError **error);
|
||||
…
|
||||
|
||||
And in ``matrix-http-api.c``, which implements ``MatrixAPI``, I have a function like this (again,
|
||||
with a lot more elements):
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
static void
|
||||
matrix_http_api_matrix_api_init(GObjectInterface *iface)
|
||||
{
|
||||
iface->initial_sync = i_initial_sync;
|
||||
iface->sync = i_sync;
|
||||
…
|
||||
}
|
||||
|
||||
And every time I wanted to implement a new function from the vtable, I had to copy the prototype,
|
||||
and add an ``iface->foo_bar = i_foo_bar`` line and an actual function header for ``i_foo_bar``
|
||||
with the same parameters. That’s a cumbersome job for more than 40 function headers. But Emacs
|
||||
comes to the rescue!
|
||||
|
||||
.. code-block:: lisp
|
||||
|
||||
(require 'thingatpt)
|
||||
|
||||
(defun get-point(symbol &optional arg)
|
||||
"Get point, optionally running a command beforehand"
|
||||
|
||||
(funcall symbol arg)
|
||||
(point))
|
||||
|
||||
(defun copy-symbol-at-point()
|
||||
"Copy the symbol under point"
|
||||
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(let ((beg (get-point 'beginning-of-thing 'symbol))
|
||||
(end (get-point 'end-of-thing 'symbol)))
|
||||
|
||||
(copy-region-as-kill beg end))))
|
||||
|
||||
(defun implement-gobject-vfunc()
|
||||
"Change a vtable line of a GObject interface to an implementation line like:
|
||||
void (*my_iface_func)(type1 param1, type2 param2, ...);
|
||||
to
|
||||
iface->my_iface_func = i_my_iface_func;"
|
||||
|
||||
(interactive)
|
||||
|
||||
(save-excursion
|
||||
(let ((beg ((lambda()
|
||||
(search-forward "(*")
|
||||
(point))))
|
||||
(end ((lambda()
|
||||
(back-to-indentation)
|
||||
(point)))))
|
||||
(kill-region beg end))
|
||||
(copy-symbol-at-point)
|
||||
(insert "iface->")
|
||||
(end-of-thing 'symbol)
|
||||
(delete-char 1)
|
||||
(let ((beg (point))
|
||||
(end ((lambda()
|
||||
(find-list-end)
|
||||
(point)))))
|
||||
(kill-region beg end))
|
||||
(insert " = i_")
|
||||
(yank 2))
|
||||
(next-line)
|
||||
(beginning-of-line))
|
||||
|
||||
(defun implement-gobject-vfunc-prototype()
|
||||
"Change a vtable line of a GObject interface to an implementation prototype line like:
|
||||
void (*my_iface_func)(type1 param1, type2 param2, ...);
|
||||
to
|
||||
static void
|
||||
i_my_iface_func(type1 param1, type2 param2, ...)"
|
||||
|
||||
(interactive)
|
||||
|
||||
(let ((beg ((lambda()
|
||||
(back-to-indentation)
|
||||
(point))))
|
||||
(end ((lambda()
|
||||
(beginning-of-line)
|
||||
(point)))))
|
||||
(kill-region beg end))
|
||||
(insert "static ")
|
||||
(search-forward "(*")
|
||||
(delete-char -3)
|
||||
(newline)
|
||||
(insert "i_")
|
||||
(end-of-thing 'symbol)
|
||||
(delete-char 1)
|
||||
(let ((beg (point))
|
||||
(end ((lambda()
|
||||
(find-list-end)
|
||||
(point)))))
|
||||
(indent-region beg end))
|
||||
(delete-char 1))
|
||||
|
||||
Now all I have to do is to copy the whole vtable entry into ``matrix_http_api_matrix_api_init()``,
|
||||
execute :kbd:`M-x implement-gobject-vfunc`, then put the same vtable entry somewhere before the
|
||||
interface init function, and execute :kbd:`M-x implement-gobject-vfunc-prototype`.
|
32
content/blog/2016-02-26-vala-interface-madness.rst
Normal file
@@ -0,0 +1,32 @@
|
||||
Vala interface madness
|
||||
######################
|
||||
|
||||
:date: 2016-02-26T13:07:52Z
|
||||
:category: blog
|
||||
:tags: vala,development
|
||||
:url: 2016/02/26/vala-interface-madness/
|
||||
:save_as: 2016/02/26/vala-interface-madness/index.html
|
||||
:status: published
|
||||
:author: "Gergely Polonkai"
|
||||
|
||||
Although I have just started making it in C, I decided to move my Matrix GLib SDK to Vala. First
|
||||
to learn a new language, and second because it is much easier to write GObject based stuff with
|
||||
it.
|
||||
|
||||
For the first step I created a ``.vapi`` file from my existing sources, so the whole SDK prototype
|
||||
was available for me in Vala.
|
||||
|
||||
I had a ``MatrixEvent`` class that implemented the ``GInitable`` interface, and many others were
|
||||
subclassed ``MatrixEvent``. For some reason I don’t remember, I created the following header for
|
||||
one of the event classes:
|
||||
|
||||
.. code-block:: vala
|
||||
|
||||
public class MatrixPresenceEvent : GLib.Object, GLib.Initable {
|
||||
|
||||
This is nice and everything, but as I didn’t create an ``init()`` method for
|
||||
``MatrixPresenceEvent``, it tried to use the one from the parent class and somehow got into an
|
||||
infinite loop. The Vala transformer (``valac``), however, doesn’t mention this.
|
||||
|
||||
Lessons learned: if you implement an interface on a subclass that is implemented by the parent
|
||||
don’t forget to add the necessary functions to the subclass.
|
@@ -0,0 +1,38 @@
|
||||
Emacs package to generate GObject boilerplate
|
||||
#############################################
|
||||
|
||||
:date: 2016-09-28T15:40:15Z
|
||||
:category: blog
|
||||
:tags: gnome,development
|
||||
:url: 2016/09/28/emacs-package-to-generate-gobject-boilerplate/
|
||||
:save_as: 2016/09/28/emacs-package-to-generate-gobject-boilerplate/index.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
Before I started using Vala (and sometimes even after that) I often needed to generate new classes
|
||||
based on `GObject <https://developer.gnome.org/gobject/stable/>`_.
|
||||
|
||||
If you have ever worked with GObject in C, you know how tedious it can be. You need a pretty long
|
||||
boilerplate just to register your class, and, if you want to be introspectable (and readable,
|
||||
actually), your function names can grow really long.
|
||||
|
||||
To overcome this problem back in my ViM days, I used template files, where I could replace class
|
||||
prefixes and names with a few keyboard macros. As I never really dug into ViM scripting other
|
||||
than using some plugins, I never got farther than that. `Then came Emacs
|
||||
<{filename}2014-09-17-nyanmacs.rst>`_.
|
||||
|
||||
I use Emacs for about two years now very extensively, up to and including GLib-based development.
|
||||
I tried the template approach, but it felt to be a really poor experience, especially given that I
|
||||
made my feet wet with Emacs Lisp. So I dug deeper, and created a package for that.
|
||||
|
||||
.. image:: {static}../images/screenshot-gobgen.png
|
||||
:alt: A screenshot of GobGen in action
|
||||
|
||||
GobGen has its own buffer with some widgets, a bit similar to ``customize``. You can enter the
|
||||
name of your new object and its parent, specify some settings. Then you press Generate, and you
|
||||
are presented with two new buffers, one for the ``.c`` and another for the ``.h`` boilerplate.
|
||||
|
||||
There are a lot of things to do, actually. There is already an open issue for creating a major
|
||||
mode for this buffer, and there are some minor switches I’d like to add, but it is already usable.
|
||||
You can grab it from `MELPA <https://melpa.org/#/gobgen>`_ (my first package there; woo!) or from
|
||||
my `GitHub account <https://github.com/gergelypolonkai/gobgen.el>`_.
|
63
content/blog/2016-10-04-git-merge-stages.rst
Normal file
@@ -0,0 +1,63 @@
|
||||
git-merge stages
|
||||
################
|
||||
|
||||
:date: 2016-10-04T12:46:00Z
|
||||
:category: blog
|
||||
:tags: git
|
||||
:url: 2016/10/04/git-merge-stages/
|
||||
:save_as: 2016/10/04/git-merge-stages/index.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
This was a mail to my company’s internal Git mailing list, after I realised many colleagues can’t
|
||||
wrap their heads around merge conflicts.
|
||||
|
||||
Hello all,
|
||||
|
||||
I just saw this on the `git-users <https://groups.google.com/forum/#!forum/git-users>`_ list
|
||||
and thought it could help you when you bump into a merge conflict. It is an excerpt from a
|
||||
mail by Konstantin Khomoutov (one of the main contributors on the list), with a few
|
||||
modifications of mine. Happy debugging :)
|
||||
|
||||
When a merge conflict is detected for a file, Git:
|
||||
|
||||
1. Updates the entry for that file in the index to make it contain
|
||||
several so-called “stages”:
|
||||
|
||||
* `0`: “Ours” version – that one which was there in this index entry
|
||||
before we begun to merge. At the beginning of the conflict, like
|
||||
right after the `git merge` or `git rebase` command this won’t
|
||||
exist (unless you had the file in the index, which you didn’t, did
|
||||
you?). When you resolve the conflict and use `git add
|
||||
my/conflicting/file.cc`, this will be the version added to the
|
||||
staging area (index), thus, the resolution of the conflict.
|
||||
* `1`: The version from the common ancestor commit, ie. the version
|
||||
of the file both of you modified.
|
||||
* `2`: The version from `HEAD`. During a merge, this is the current
|
||||
branch. During a rebase, this is the branch or commit you are
|
||||
rebasing onto, which usually will be `origin/develop`).
|
||||
* `3`: The version being merged, or the commit you are rebasing.
|
||||
2. Updates the file in the work tree to contain conflict markers and
|
||||
the conflicting chunks of text between them (and the text from the
|
||||
common ancestor if the `diff3` style of conflict markers was set).
|
||||
|
||||
Now you can use the numbers in point 1 to access the different stages
|
||||
of the conflicting file. For example, to see the common ancestor (the
|
||||
version both of you modified), use
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
git show :1:my/conflicting/file.cc
|
||||
|
||||
Or, to see the difference between the two conflicting versions, try
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
git diff :2:my/conflicting/file.cc :3:my/conflicting/file.cc
|
||||
|
||||
|
||||
**Note** that you can’t use the ``:0:`` stage *before* you stage your resolution with ``git
|
||||
add``, and you can’t use the ``:2:`` and ``:3:`` stages *after* you staged the resolution.
|
||||
|
||||
Fun fact: behind the scenes, these are the files (*revisions*) ``git mergetool`` accesses when
|
||||
it presents you the conflict visually.
|
76
content/blog/2016-11-03-how-i-started-with-emacs.rst
Normal file
@@ -0,0 +1,76 @@
|
||||
How I started with Emacs
|
||||
########################
|
||||
|
||||
:date: 2016-11-03T09:58:41Z
|
||||
:category: blog
|
||||
:tags: emacs
|
||||
:url: 2016/11/03/how-i-started-with-emacs/
|
||||
:save_as: 2016/11/03/how-i-started-with-emacs/index.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
Sacha Chua has a nice `Emacs chat intro <http://sachachua.com/blog/2013/04/emacs-chat-intro/>`_
|
||||
article back from 2013. I write this post half because she asks there about my (OK, anyone’s)
|
||||
first Emacs moments, and half because I plan to do it for months now.
|
||||
|
||||
I wanted to start using Emacs 6(ish) years ago, and I was like “:kbd:`C-x` what”? (Note that back
|
||||
around 1998, I was among the people who exited ``vi`` by killing it from another terminal after a
|
||||
bunch of tries & fails like `these <http://osxdaily.com/2014/06/12/how-to-quit-vim/>`_.)
|
||||
|
||||
I tried to come back to Emacs a lot of times. And I mean a *lot*, about every two months. I
|
||||
suddenly learned what these cryptic key chord descriptions mean (``C`` is for :kbd:`Control` and
|
||||
``M`` is for :kbd:`Meta`, which is actually :kbd:`Alt`), but somehow it didn’t *click*. I
|
||||
remained a ViM power user with a huge pile of 3:sup:`rd` party plugins. Then `I found Nyan-macs
|
||||
<{filename}2014-09-17-nyanmacs.rst>`_), which converted me to Emacs, and it is final now. Many of
|
||||
my friends thought I’m just kidding this being the cause, but I’m not. I’m a huge fan of Nyan cat
|
||||
(did you know there is even a site called `nyan.cat <http://nyan.cat/>`_?) and since then I have
|
||||
it in my mode line:
|
||||
|
||||
.. image:: {static}../images/nyan-modeline.png
|
||||
:alt: Nyan modeline
|
||||
|
||||
…in my ``eshell`` prompt:
|
||||
|
||||
.. image:: {static}../images/nyan-eshell.png
|
||||
:alt: eshell prompt with a Nyan cat
|
||||
|
||||
…and I also `zone out <https://www.emacswiki.org/emacs/ZoneMode>`_ with Nyan cat:
|
||||
|
||||
.. image:: {static}../images/nyan-zone.png
|
||||
:alt: a text-based animation with Nyan cat
|
||||
|
||||
Now on to more serious stuff. After browsing through all the packages provided by `ELPA
|
||||
<http://elpa.gnu.org/>`_, I found tons of useful (and sometimes, less useful) packages, like `Helm
|
||||
<https://github.com/emacs-helm/helm/wiki>`_, `company <http://company-mode.github.io/>`_, `gtags
|
||||
<https://www.emacswiki.org/emacs/GnuGlobal>`_ (which introduced me to GNU Global, removing
|
||||
Exuberant ctags from my life), `magit <https://magit.vc/>`_, `Projectile
|
||||
<http://batsov.com/projectile/>`_, and `Org <http://orgmode.org/>`_ (OK, it’s actually part of
|
||||
Emacs for a while, but still). I still use these few, but in a month or two, I started to
|
||||
`version control <https://github.com/gergelypolonkai/my-emacs-d>`_ my ``.emacs.d`` directory, so I
|
||||
can easily transfer it between my home and work machine (and for a few weeks now, even to my
|
||||
phone: I’m using Termux on Android). Then, over these two years I wrote some packages like
|
||||
`GobGen <https://github.com/gergelypolonkai/gobgen.el>`_, and a small addon for Calendar providing
|
||||
`Hungarian holidays <https://github.com/gergelypolonkai/hungarian-holidays>`_, and I found a lot
|
||||
more (in no particular order):
|
||||
|
||||
* `git-gutter <https://github.com/syohex/emacs-git-gutter>`_
|
||||
* `multiple-cursors <https://github.com/magnars/multiple-cursors.el>`_
|
||||
* `origami <https://github.com/gregsexton/origami.el>`_
|
||||
* `ace-window <https://github.com/abo-abo/ace-window>`_
|
||||
* `avy <https://github.com/abo-abo/avy>`_
|
||||
* `beacon <https://github.com/Malabarba/beacon>`_
|
||||
|
||||
…and a lot more.
|
||||
|
||||
What is more important (to me) is that I started using the `use-package
|
||||
<https://github.com/jwiegley/use-package>`_ package, which can automatically download packages
|
||||
that are not installed on my current local system. Together with `auto-package-update
|
||||
<https://github.com/rranelli/auto-package-update.el>`_, it is *very* practical.
|
||||
|
||||
In addition, I started to follow the blogs of a bunch of Emacs users/gurus. I’ve already
|
||||
mentioned `Sacha Chua <http://sachachua.com/>`_. She’s a charming, cheerful person, writing a lot
|
||||
about Emacs and project management (among other things). Another one is `Bozhidar Batsov
|
||||
<http://batsov.com/>`_, who, among other things, had an initiate to lay down the foundation of a
|
||||
`common Elisp coding style <https://github.com/bbatsov/emacs-lisp-style-guide>`_. Another
|
||||
favourite of mine is `Endless Parentheses <http://endlessparentheses.com/>`_, whence I got a lot
|
||||
of ideas.
|
38
content/blog/2016-11-10-edit-file-as-other-user-in-emacs.rst
Normal file
@@ -0,0 +1,38 @@
|
||||
Edit file as another user in Emacs
|
||||
##################################
|
||||
|
||||
:date: 2016-11-10T08:57:12Z
|
||||
:category: blog
|
||||
:tags: development,emacs
|
||||
:url: 2016/11/10/edit-file-as-other-user-in-emacs/
|
||||
:save_as: 2016/11/10/edit-file-as-other-user-in-emacs/index.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
I have recently found `this article <http://emacsredux.com/blog/2013/04/21/edit-files-as-root/>`_
|
||||
by Bozhidar Batsov on opening the current file as root. I barely use `tramp
|
||||
<https://www.gnu.org/software/tramp/>`_ for sudo access, but when I do, I almost never use root as
|
||||
the target user. So I decided to fix it for my needs.
|
||||
|
||||
.. code-block:: lisp
|
||||
|
||||
(defun open-this-file-as-other-user (user)
|
||||
"Edit current file as USER, using `tramp' and `sudo'. If the current
|
||||
buffer is not visiting a file, prompt for a file name."
|
||||
(interactive "sEdit as user (default: root): ")
|
||||
(when (string= "" user)
|
||||
(setq user "root"))
|
||||
(let* ((filename (or buffer-file-name
|
||||
(read-file-name (format "Find file (as %s): "
|
||||
user))))
|
||||
(tramp-path (concat (format "/sudo:%s@localhost:" user) filename)))
|
||||
(if buffer-file-name
|
||||
(find-alternate-file tramp-path)
|
||||
(find-file tramp-path))))
|
||||
|
||||
If the user is not specified, the default is still root. Also, if the current buffer is not
|
||||
visiting a file, I prompt for a filename. As I’m not an ``ido`` user, I didn’t bother calling
|
||||
``ido-read-file-name``; `helm <https://github.com/emacs-helm/helm/wiki>`_ overrides
|
||||
``read-file-name`` for me anyway.
|
||||
|
||||
Unlike Bozhidar, I barely use this feature, so I didn’t bind this to a key.
|
46
content/blog/2016-11-18-get-passwords-from-id-manager.rst
Normal file
@@ -0,0 +1,46 @@
|
||||
Get account data programatically from id-manager
|
||||
################################################
|
||||
|
||||
:date: 2016-11-18T12:43:13Z
|
||||
:category: blog
|
||||
:tags: emacs
|
||||
:url: 2016/11/18/get-passwords-from-id-manager/
|
||||
:save_as: 2016/11/18/get-passwords-from-id-manager/index.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
I recently started using `id-manager <https://github.com/kiwanami/emacs-id-manager>`_. It is a
|
||||
nice little package that can store your passwords, encrypting them with GPG. My original reason
|
||||
was to store my GitHub access token for `github-notifier
|
||||
<https://github.com/xuchunyang/github-notifier.el>`_, but it soon turned out, it’s not *that*
|
||||
easy.
|
||||
|
||||
``id-manager`` is a nice package when it comes to storing your password and retrieving them for
|
||||
your own eyes. But it cannot retrieve account data programatically. Taking a look into its
|
||||
source code, I came up with this solution:
|
||||
|
||||
.. code-block:: lisp
|
||||
|
||||
(defun gpolonkai/idm-record-get-field (record field)
|
||||
"Get FIELD of an id-manager RECORD."
|
||||
(let ((funcname (intern (concat "idm-record-" (symbol-name field)))))
|
||||
(when (fboundp funcname)
|
||||
(funcall funcname record))))
|
||||
|
||||
(defun gpolonkai/idm-get-field-for-account (account field)
|
||||
"Get id-manager password for ACCOUNT."
|
||||
(let ((db (idm-load-db))
|
||||
(lookup-record nil))
|
||||
(dolist (record (funcall db 'get-all-records) password)
|
||||
(when (string= account (idm-record-name record))
|
||||
(setq lookup-record (gpolonkai/idm-record-get-field record field))))
|
||||
lookup-record))
|
||||
|
||||
(defmacro gpolonkai/idm-get-password-for-account (account)
|
||||
`(gpolonkai/idm-get-field-for-account ,account 'password))
|
||||
|
||||
(defmacro gpolonkai/idm-get-id-for-account (account)
|
||||
`(gpolonkai/idm-get-field-for-account ,account 'account-id))
|
||||
|
||||
I currently need only the account ID (ie. the username) and the password, but it’s pretty easy to
|
||||
add a macro to get the ``memo`` or ``update-time`` fields, too.
|
@@ -0,0 +1,80 @@
|
||||
Add Python docstring to the beginning of anything in Emacs
|
||||
##########################################################
|
||||
|
||||
:date: 2016-11-30T07:52:37Z
|
||||
:category: blog
|
||||
:tags: development,python,emacs
|
||||
:url: 2016/11/30/add-python-docstring-to-the-beginning-of-anything/
|
||||
:save_as: 2016/11/30/add-python-docstring-to-the-beginning-of-anything/index.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
Now that I write Python code for a living, I write a lot of functions, classes, and modules. What
|
||||
I still tend to forget, and also find tedious, is adding docstrings. Unlike many developers,
|
||||
writing documentation is not an enemy of mine, but it usually comes to my mind when I finish
|
||||
implementation. The procedure, roughly, is this:
|
||||
|
||||
* Decide where I am (in a function, in a class but not in one of its methods, or not inside such a
|
||||
block at all)
|
||||
* Go to the beginning of the thing
|
||||
* Insert ``"""``
|
||||
* Leave a blank line
|
||||
* Insert ``"""``
|
||||
|
||||
One of my mottos is if something takes more than one step and you have to do it more than twice,
|
||||
you should automate it after the first time. This puts a small(ish) overhead on the second
|
||||
invocation (when you implement the automation), but it usually worth the time.
|
||||
|
||||
Since I use Emacs for pretty much everything coding-related (and many more, but that’s the topic
|
||||
of a different post), I wrote a small function to do it for me.
|
||||
|
||||
.. code-block:: lisp
|
||||
|
||||
(defun gpolonkai/prog-in-string-p ()
|
||||
"Return `t' if point is inside a string."
|
||||
(nth 3 (syntax-ppss)))
|
||||
|
||||
(defun gpolonkai/prog-in-comment-p ()
|
||||
"Return `t' if point is inside a comment."
|
||||
(nth 4 (syntax-ppss)))
|
||||
|
||||
(defun gpolonkai/python-add-docstring ()
|
||||
"Add a Python docstring to the current thing. If point is
|
||||
inside a function, add docstring to that. If point is in a
|
||||
class, add docstring to that. If neither, add docstring to the
|
||||
beginning of the file."
|
||||
(interactive)
|
||||
(save-restriction
|
||||
(widen)
|
||||
(beginning-of-defun)
|
||||
(if (not (looking-at-p "\\(def\\|class\\) "))
|
||||
(progn
|
||||
(goto-char (point-min))
|
||||
(back-to-indentation)
|
||||
(forward-char)
|
||||
(while (gpolonkai/prog-in-comment-p)
|
||||
(forward-line)
|
||||
(back-to-indentation)
|
||||
(forward-char)))
|
||||
(search-forward ":")
|
||||
(while (or (gpolonkai/prog-in-string-p)
|
||||
(gpolonkai/prog-in-comment-p))
|
||||
(search-forward ":")))
|
||||
(if (eq 1 (count-lines 1 (point)))
|
||||
(open-line-above)
|
||||
(open-line-below))
|
||||
(insert "\"\"\"")
|
||||
(open-line-below)
|
||||
(insert "\"\"\"")
|
||||
(open-line-above)))
|
||||
|
||||
There are still a lot of things to improve:
|
||||
|
||||
* it always inserts double quotes (althoug I couldn’t show a use-case when single quotes are
|
||||
preferred)
|
||||
* it doesn’t check for an existing docstring, just happily inserts a new one (leaving the old one
|
||||
alone, but generating a syntax error this way)
|
||||
* it would also be nice if I could jump to the beginning of a file even from a class method. I
|
||||
guess I will use prefix keys for that, but I’m not sure yet.
|
||||
|
||||
You can bet I will implement these features, so check back soon for an updated version!
|
40
content/blog/2016-12-08-slugify-in-python3.rst
Normal file
@@ -0,0 +1,40 @@
|
||||
Slugify in Python 3
|
||||
###################
|
||||
|
||||
:date: 2016-12-08T12:54:19Z
|
||||
:category: blog
|
||||
:tags: development,python
|
||||
:url: 2016/12/08/slugify-in-python3/
|
||||
:save_as: 2016/12/08/slugify-in-python3/index.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
Today I needed a function to create a slug (an ASCII-only representation of a string). I went
|
||||
Googling a bit, and found an excellend `Flask snippet <http://flask.pocoo.org/snippets/5/>`_.
|
||||
Problem is, it is designed for Python 2, so I came up with a Python 3 version.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import re
|
||||
from unicodedata import normalize
|
||||
|
||||
_punctuation_re = re.compile(r'[\t !"#$%&\'()*\-/<=>?@\[\\\]^_`{|},.]+')
|
||||
|
||||
def slugify(text, delim='-'):
|
||||
"""
|
||||
Generate an ASCII-only slug.
|
||||
"""
|
||||
|
||||
result = []
|
||||
for word in _punctuation_re.split(text.lower()):
|
||||
word = normalize('NFKD', word) \
|
||||
.encode('ascii', 'ignore') \
|
||||
.decode('utf-8')
|
||||
|
||||
if word:
|
||||
result.append(word)
|
||||
|
||||
return delim.join(result)
|
||||
|
||||
As I don’t really like the transliteration done in the first example (e.g. converting ü to ue), I
|
||||
went with the second example.
|
@@ -0,0 +1,246 @@
|
||||
Finding non-translated strings in Python code
|
||||
#############################################
|
||||
|
||||
:date: 2016-12-22T09:35:11Z
|
||||
:category: blog
|
||||
:tags: development,python
|
||||
:url: 2016/12/22/finding-non-translated-strings-in-python-code/
|
||||
:save_as: 2016/12/22/finding-non-translated-strings-in-python-code/index.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
When creating multilingual software, be it on the web, mobile, or desktop, you will eventually
|
||||
fail to mark strings as translatable. I know, I know, we developers are superhuman and never do
|
||||
that, but somehow I stopped trusting myself recently, so I came up with an idea.
|
||||
|
||||
Right now I assist in the creation of a multilingual site/web application, where a small part of
|
||||
the strings come from the Python code instead of HTML templates. Call it bad practice if you
|
||||
like, but I could not find a better way yet.
|
||||
|
||||
As a start, I tried to parse the source files with simple regular expressions, so I could find
|
||||
anything between quotation marks or apostrophes. This attempt quickly failed with strings that
|
||||
had such characters inside, escaped or not; my regexps became so complex I lost all hope. Then
|
||||
the magic word “lexer” came to mind.
|
||||
|
||||
While searching for ready made Python lexers, I bumped into the awesome ``ast`` module. AST
|
||||
stands for Abstract Syntax Tree, and this module does that: parses a Python file and returns a
|
||||
tree of nodes. For walking through these nodes there is a ``NodeVisitor`` class (among other
|
||||
means), which is meant to be subclassed. You add a bunch of ``visitN`` methods (where ``N`` is an
|
||||
``ast`` class name like ``Str`` or ``Call``), instantiate it, and call its ``visit()`` method with
|
||||
the root node. For example, the ``visitStr()`` method will be invoked for every string it finds.
|
||||
|
||||
How does it work?
|
||||
=================
|
||||
|
||||
Before getting into the details, let’s me present you the code I made:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import ast
|
||||
import gettext
|
||||
from gettext import gettext as _
|
||||
import sys
|
||||
|
||||
|
||||
def get_func_name(node):
|
||||
cls = node.__class__.__name__
|
||||
|
||||
if cls == 'Call':
|
||||
return get_func_name(node.func)
|
||||
elif cls == 'Attribute':
|
||||
return '{}.{}'.format(
|
||||
get_func_name(node.value),
|
||||
node.attr)
|
||||
elif cls == 'Name':
|
||||
return get_func_name(node.id)
|
||||
elif cls == 'str':
|
||||
return node
|
||||
elif cls == 'Str':
|
||||
return "<String literal>"
|
||||
elif cls == 'Subscript':
|
||||
return '{}[{}]'.format(get_func_name(node.value),
|
||||
get_func_name(node.slice))
|
||||
elif cls == 'Index':
|
||||
return get_func_name(node.value)
|
||||
else:
|
||||
print('ERROR: Unknown class: {}'.format(cls))
|
||||
|
||||
|
||||
class ShowStrings(ast.NodeVisitor):
|
||||
TRANSLATION_FUNCTIONS = [
|
||||
'_', # gettext.gettext is often imported under this name
|
||||
'gettext',
|
||||
'gettext.gettext',
|
||||
# FIXME: this list is pretty much incomplete
|
||||
]
|
||||
UNTRANSLATED = 'untranslated 9'
|
||||
|
||||
def __init__(self, filename=None):
|
||||
super(ShowStrings, self).__init__()
|
||||
|
||||
self.in_call = []
|
||||
self.filename = filename or '<parsed string>'
|
||||
|
||||
def visit_with_trace(self, node, func):
|
||||
self.in_call.append((func, node.lineno, node.col_offset))
|
||||
self.visit(node)
|
||||
self.in_call.pop()
|
||||
|
||||
def visit_Str(self, node):
|
||||
# TODO: make it possible to ignore untranslated strings
|
||||
# TODO: make this ignore docstrings
|
||||
|
||||
# if we are not in a translator function, issue a warning
|
||||
if not self.in_call or \
|
||||
self.in_call[-1][0] not in self.TRANSLATION_FUNCTIONS:
|
||||
try:
|
||||
funcname = self.in_call[-1][0]
|
||||
except IndexError:
|
||||
funcname = None
|
||||
|
||||
funcall_msg = "outside a function call" if funcname is None \
|
||||
else "inside a call to {funcname}".format(
|
||||
funcname=funcname)
|
||||
|
||||
print("WARNING: Untranslated string found at "
|
||||
"{filename}:{line}:{col} {funcall_msg}".format(
|
||||
filename=self.filename,
|
||||
line=node.lineno,
|
||||
col=node.col_offset,
|
||||
funcall_msg=funcall_msg))
|
||||
|
||||
def visit_Call(self, node):
|
||||
# if we are in a translator function, issue a warninc
|
||||
if self.in_call and self.in_call[-1][0] in self.TRANSLATION_FUNCTIONS:
|
||||
print("WARNING: function call within a translation function at "
|
||||
"{filename}:{line}:{col}".format(filename=self.filename,
|
||||
line=node.lineno,
|
||||
col=node.col_offset))
|
||||
funcname = get_func_name(node)
|
||||
|
||||
for arg in node.args:
|
||||
self.visit_with_trace(arg, funcname)
|
||||
|
||||
for kwarg in node.keywords:
|
||||
self.visit_with_trace(kwarg.value, funcname)
|
||||
|
||||
def generic_visit(self, node):
|
||||
# if we are inside a translator function, issue a warning
|
||||
if self.in_call and self.in_call[-1][0] in self.TRANSLATION_FUNCTIONS:
|
||||
# Some ast nodes, like Add don’t have position information
|
||||
if hasattr(node, 'lineno'):
|
||||
print("WARNING: something not a string ({klass}) found in a "
|
||||
"translation function at {filename}:{line}:{col}".format(
|
||||
filename=self.filename,
|
||||
klass=node.__class__.__name__,
|
||||
line=node.lineno,
|
||||
col=node.col_offset))
|
||||
else:
|
||||
print("WARNING: something not a string ({klass}) found in a "
|
||||
"translation function. Position unknown; function call "
|
||||
"is at {filename}:{line}:{col}".format(
|
||||
filename=self.filename,
|
||||
klass=node.__class__.__name__,
|
||||
line=self.in_call[-1][1],
|
||||
col=self.in_call[-1][2]))
|
||||
|
||||
super(ShowStrings, self).generic_visit(node)
|
||||
|
||||
|
||||
def tst(*args, **kwargs):
|
||||
pass
|
||||
|
||||
|
||||
def actual_tests():
|
||||
_('translated 1')
|
||||
tst(_('translated 2'))
|
||||
tst(gettext.gettext('translated 3'))
|
||||
tst(_('translated 4') + 'native 1')
|
||||
tst('native 2'
|
||||
'native 3')
|
||||
tst(_('native 4' + 'native 5'))
|
||||
tst('native 6', b='native 7')
|
||||
tst(_(tst('hello!')))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
filename = sys.argv[1]
|
||||
except IndexError:
|
||||
filename = __file__
|
||||
print("INFO: No filename specified, checking myself.")
|
||||
|
||||
with open(filename, 'r') as f:
|
||||
code = f.read()
|
||||
|
||||
root = ast.parse(code)
|
||||
|
||||
show_strings = ShowStrings(filename=filename)
|
||||
show_strings.visit(root)
|
||||
|
||||
The class initialization does two things: creates an empty ``in_call`` list (this will hold our
|
||||
primitive backtrace), and saves the filename, if provided.
|
||||
|
||||
``visitCall``, again, has two tasks. First, it checks if we are inside a translation function.
|
||||
If so, it reports the fact that we are translating something that is not a raw string. Although
|
||||
it is not necessarily a bad thing, I consider it bad practice as it may result in undefined
|
||||
behaviour.
|
||||
|
||||
Its second task is to walk through the positional and keyword arguments of the function call. For
|
||||
each argument it calls the ``visit_with_trace()`` method.
|
||||
|
||||
This method updates the ``in_call`` property with the current function name and the position of
|
||||
the call. This latter is needed because ``ast`` doesn’t store position information for every node
|
||||
(operators are a notable example). Then it simply visits the argument node, which is needed
|
||||
because ``NodeVisitor.visit()`` is not recursive. When the visit is done (which, with really
|
||||
deeply nested calls like ``visit(this(call(iff(you(dare)))))`` will be recursive), the current
|
||||
function name is removed from ``in_call``, so subsequent calls on the same level see the same
|
||||
“backtrace”.
|
||||
|
||||
The ``generic_visit()`` method is called for every node that doesn’t have a named visitor (like
|
||||
``visitCall`` or ``visitStr``. For the same reason we generate a warning in ``visitCall``, we do
|
||||
the same here. If there is anything but a raw string inside a translation function call,
|
||||
developers should know about it.
|
||||
|
||||
The last and I think the most important method is ``visitStr``. All it does is checking the last
|
||||
element of the ``in_call`` list, and generates a warning if a raw string is found somewhere that
|
||||
is not inside a translation function call.
|
||||
|
||||
For accurate reports, there is a ``get_func_name()`` function that takes an ``ast`` node as an
|
||||
argument. As function call can be anything from actual functions to object methods, this goes all
|
||||
down the node’s properties, and recursively reconstructs the name of the actual function.
|
||||
|
||||
Finally, there are some test functions in this code. ``tst`` and
|
||||
``actual_tests`` are there so if I run a self-check on this script, it will
|
||||
find these strings and report all the untranslated strings and all the
|
||||
potential problems like the string concatenation.
|
||||
|
||||
Drawbacks
|
||||
=========
|
||||
|
||||
There are several drawbacks here. First, translation function names are built in, to the
|
||||
``TRANSLATION_FUNCTIONS`` property of the ``ShowString`` class. You must change this if you use
|
||||
other translation functions like ``dngettext``, or if you use a translation library other than
|
||||
``gettext``.
|
||||
|
||||
Second, it cannot ignore untranslated strings right now. It would be great if a pragma like
|
||||
``flake8``’s ``# noqa`` or ``coverage.py``’s ``# pragma: no cover`` could be added. However,
|
||||
``ast`` doesn’t parse comment blocks, so this proves to be challenging.
|
||||
|
||||
Third, it reports docstrings as untranslated. Clearly, this is wrong, as docstrings generally
|
||||
don’t have to be translated. Ignoring them, again, is a nice challenge I couldn’t yet overcome.
|
||||
|
||||
The ``get_func_name()`` helper is everything but done. As long as I cannot remove that final
|
||||
``else`` clause, there may be error reports. If that happens, the reported class should be
|
||||
treated in a new ``elif`` branch.
|
||||
|
||||
Finally (and the most easily fixed), the warnings are simply printed on the console. It is nice,
|
||||
but it should be optional; the problems identified should be stored so the caller can obtain it as
|
||||
an array.
|
||||
|
||||
Bottom line
|
||||
===========
|
||||
|
||||
Finding strings in Python sources is not as hard as I imagined. It was fun to learn using the
|
||||
``ast`` module, and it does a great job. Once I can overcome the drawbacks above, this script
|
||||
will be a fantastic piece of code that can assist me in my future tasks.
|
@@ -0,0 +1,39 @@
|
||||
Rename automatically named foreign keys with Alembic
|
||||
####################################################
|
||||
|
||||
:date: 2017-01-02T09:41:23Z
|
||||
:category: blog
|
||||
:tags: mysql,development,flask,python
|
||||
:url: 2017/01/02/rename-automatically-named-foreign-keys-with-alembic/
|
||||
:save_as: 2017/01/02/rename-automatically-named-foreign-keys-with-alembic/index.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
I have recently messed up my Alembic migrations while modifying my SQLAlchemy models. To start
|
||||
with, I didn’t update the auto-generated migration files to name the indexes/foreign keys a name,
|
||||
so Alembic used its own naming scheme. This is not an actual problem until you have to modify
|
||||
columns that have such constraints. I have since fixed this problem, but first I had to find
|
||||
which column references what (I had no indexes other than primary key back then, so I could go
|
||||
with foreign keys only). Here is a query I put together, mostly using `this article
|
||||
<http://www.binarytides.com/list-foreign-keys-in-mysql/>`_.
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
SELECT constraint_name,
|
||||
CONCAT(table_name, '.', column_name) AS 'foreign key',
|
||||
CONCAT(referenced_table_name, '.', referenced_column_name) AS 'references'
|
||||
FROM information_schema.key_column_usage
|
||||
WHERE referenced_table_name IS NOT NULL AND
|
||||
table_schema = 'my_app';
|
||||
|
||||
Now I could easily drop such constraints using
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
alembic.op.drop_constraint('users_ibfk1', 'users', type_='foreignkey')
|
||||
|
||||
and recreate them with
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
alembic.op.create_foreign_key('fk_user_client', 'users', 'clients', ['client_id'], ['id'])
|
@@ -0,0 +1,85 @@
|
||||
Category-based logging with Flask
|
||||
#################################
|
||||
|
||||
:date: 2017-03-26T22:00:52Z
|
||||
:category: blog
|
||||
:tags: development,python,flask
|
||||
:url: 2017/03/27/category-based-logging-with-flask/
|
||||
:save_as: 2017/03/27/category-based-logging-with-flask/index.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
I’m in a team who are developing a Flask-based web application, which uses logging extensively.
|
||||
For a while now it spews out a lot of lines so the need arose to index them in ElasticSearch, and
|
||||
more importantly, to search through them for auditing purposes. This latter user story brought up
|
||||
one more question: why don’t we categorize our log messages? I quickly came up with an extended
|
||||
log format (``[auth]`` is the new category name):
|
||||
|
||||
.. code-block:: log
|
||||
|
||||
[2017-01-14 00:55:42,554] [8286] [INFO] [auth] invalid password for john@example.com [at __init__.py:12, in function utils.validate_login]
|
||||
|
||||
Here, ``[auth]`` is the category name. In the ideal solution, all I’d have to
|
||||
do is adding ``%(category)s`` to my formatter, and I could call
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
app.logger.info(message, extra={'auth': 'invalid password'})
|
||||
|
||||
to achieve this output. Unfortunately, ``Flask.logger`` (and, in the background, the ``logging``
|
||||
module) is not that easy to tame.
|
||||
|
||||
As it turns out, a Flask application’s ``logger`` property is a subclass of ``logging.Logger``, so
|
||||
my first idea was to monkey patch that class. When the app’s logger is initialised, it subclasses
|
||||
``logging.Logger`` and tweaks the log level so it goes down to ``logging.DEBUG`` if the app is
|
||||
running in debug mode. This is done by using a different logger class depending on the app
|
||||
config. Fortunately it doesn’t directly subclass ``logging.Logger``; it calls
|
||||
``logging.getLoggerClass()`` to find which class it should extend. To achieve my goals, all I had
|
||||
to do is to subclass the original logger class, and pass it to ``logging.setLoggerClass()``
|
||||
*before* I initialise my app, and I have a fail-safe(ish) solution. So far so good, on to the
|
||||
extra category parameter.
|
||||
|
||||
Now if you add a new variable to the formatter like my new ``%(category)s``, you get a nifty
|
||||
``KeyError`` saying there is no ``category`` in the format expansion dictionary. If you add
|
||||
``category='auth'`` to the ``app.logger.info()`` calls and its cousins, it’s fine, because these
|
||||
methods use the magic ``**kwarg`` argument to swallow it. Everything goes well until control
|
||||
arrives to the ``_log()`` method: it complains about that extra ``category`` keyword argument.
|
||||
Taking a peek at Python’s internals, I found two things: ``info()`, `error()``, and co. pass
|
||||
``*args`` and ``**kwargs`` to ``_log()`` unmodified, and the ``_log()`` method doesn’t have
|
||||
``**kwargs`` present in its definition to swallow it. A little doc reading later I found that if
|
||||
I want to pass extra arguments for such a formatter, I should do it via the ``extra`` keyword
|
||||
argument to ``_log()``. A call like ``app.logger.info('invalid password', extra={'category':
|
||||
'auth'})`` solved the problem. Now *that* is tedious.
|
||||
|
||||
My first idea was to override all the standard logging methods like ``info()`` and ``error()``,
|
||||
and handle ``category`` there. But this resulted in lots of repeating code. I changed the
|
||||
specification a bit, so my calls would look like ``info('message', category='auth)`` instead of
|
||||
the original plan of ``info('auth', 'message')``: as the logging methods pass all keyword
|
||||
arguments to ``_log()``, I can handle it there. So at the end, my new logger class only patches
|
||||
``_log()``, by picking out ``category`` from the kwarg list, and inserting it to ``extra`` before
|
||||
calling ``super``.
|
||||
|
||||
As you can see, this is a bit ugly solution. It requires me, the app
|
||||
author, to know about Flask’s internals (that I can set my own logging class
|
||||
before the app is created, and so the app will use it.) This means if Flask
|
||||
developers change the way how logging is done, I have to adapt and find a
|
||||
workaround for the new version (well, unless they let me directly set the
|
||||
logging class. That would make it easy.)
|
||||
|
||||
What is worse, I must know about Python internals. I know the ``extra`` kwarg is documented well
|
||||
(I just failed to notice), but this made adding a new formatter variable so hard. Python version
|
||||
doesn’t change as often as Flask version in this project, and I think the standard library won’t
|
||||
really change until 4.0, so I don’t think my tampering with a “protected” method will cause any
|
||||
trouble in the future. Still, this makes me feel a bit uneasy.
|
||||
|
||||
All the above can be circumvented if this class, and the whole solution have some tests. As my
|
||||
class uses the same method as Flask (use ``logging.getLoggerClass()`` as a base class instead of
|
||||
using ``logging.Logger()`` directly), if the base logger class changes in Python or in the running
|
||||
environment, my app won’t care. By checking if the app logger can use my special ``category``
|
||||
variable (ie. it doesn’t raise an exception *and* the category actually gets into the log output),
|
||||
I made sure my class is used as a base in Flask, so if they change the way they construct
|
||||
``app.logger``, I will know about it when I first run my tests after upgrading Flask.
|
||||
|
||||
If you are interested in such functionality (and more), you can grab it from `GitHub
|
||||
<https://github.com/gergelypolonkai/flask-logging-extras>`_, or via `PyPI
|
||||
<https://pypi.python.org/pypi/Flask-Logging-Extras/>`_.
|
@@ -0,0 +1,29 @@
|
||||
Add SysAdmin day to Emacs Calendar
|
||||
##################################
|
||||
|
||||
:date: 2017-10-02T09:37:52Z
|
||||
:category: blog
|
||||
:tags: emacs
|
||||
:url: 2017/10/02/add-sysadmin-day-to-emacs-calendar/
|
||||
:save_as: 2017/10/02/add-sysadmin-day-to-emacs-calendar/index.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
I’m a SysAdmin since 1998. Maybe a bit earlier, if you count managing our home computer. This
|
||||
means `SysAdmin Day <http://sysadminday.com/>`_ is also celebrating me. However, my Emacs
|
||||
Calendar doesn’t show it for some reason.
|
||||
|
||||
The solution is pretty easy:
|
||||
|
||||
.. code-block:: lisp
|
||||
|
||||
(add-to-list 'holiday-other-holidays '(holiday-float 7 5 -1 "SysAdmin Day") t)
|
||||
|
||||
Now invoke :kbd:`M-x holidays-list` for any year, choosing “Other” as the category, and there you
|
||||
go:
|
||||
|
||||
.. code-block:: log
|
||||
|
||||
…
|
||||
Friday, July 28, 2017: SysAdmin Day
|
||||
…
|
54
content/blog/2018-06-26-please-welcome-calendar-social.rst
Normal file
@@ -0,0 +1,54 @@
|
||||
Please welcome Calendar.social
|
||||
##############################
|
||||
|
||||
:date: 2018-06-26T05:36:00Z
|
||||
:category: blog
|
||||
:tags: development
|
||||
:url: 2018/06/26/please-welcome-calendar-social/
|
||||
:save_as: 2018/06/26/please-welcome-calendar-social/index.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
I started looking at decentralised/federated tools some years ago, but other than Matrix I didn’t
|
||||
use any of them until recently. Then this February I joined the Fediverse (federated universe) by
|
||||
spinning up my own `Mastodon <https://joinmastodon.org/>`_ instance. I’m not going to lie, this
|
||||
place is pure awesome. I follow only 53 people but unlike on Twitter or Facebook, I can’t just
|
||||
scroll through my timeline; I have to read them all. These 53 accounts are real persons over the
|
||||
Internet with meaningful posts. I could never find this on the noisy Twitter or Facebook timeline
|
||||
during the last 10 or so years.
|
||||
|
||||
Bragging aside, and given my strive for learning, I wanted to give back something to this
|
||||
community. I thought about an image sharing platform where people can share their photo albums
|
||||
with each other, but I realised I’m not that good at image handling. So I decided to make a
|
||||
calendar instead.
|
||||
|
||||
My app, creatively codenamed Calendar.social, aims to be a calendar service similar to Google
|
||||
Calendar (and, obviously, any calendar app you can find out there) but instead of using emails, it
|
||||
will use ActivityPub to share all the details (although I might add e-mail support sooner or
|
||||
later.)
|
||||
|
||||
I have a *lot* on my mind about what this tool should/could do when it’s done. In no particular
|
||||
order, here’s a list of them:
|
||||
|
||||
* events that can be private (only you and the (optional) guests see them), or public (anyone can
|
||||
see them). They will have all the usual fields like start/end time, location, and maybe an icon
|
||||
and a cover photo
|
||||
* multiple calendars you would expect from a calendar app. This way you can separate your
|
||||
birthday reminders from the dentist appointments
|
||||
* event sharing over ActivityPub and other channels (to be decided, but I think you can take email
|
||||
and maybe Matrix for granted.)
|
||||
* full calendar sharing. The other party can get access from a very basic free/busy level to full
|
||||
write access (which might be a good idea for family or company wide calendars.)
|
||||
* Holiday calendars that store national/bank holidays. Users can subscribe to them to see the
|
||||
holidays of a given country/area, and optionally set them as busy (on holiday weekdays) or free
|
||||
(on weekends that are actually workdays for some reason.)
|
||||
* Reminders! Because you obviously don’t want to forget the birthday of your significant other,
|
||||
your anniversary, or your barber appointment.
|
||||
* All this developed with time zones, localisation, and accessibility in mind.
|
||||
|
||||
That, and anything more that comes to my mind.
|
||||
|
||||
You can follow the development `here <https://gitea.polonkai.eu/gergely/calendar-social>`_. Also,
|
||||
feel free to ping me with your ideas on my `Mastodon account <https://social.polonkai.eu/@gergely>`_, `Matrix
|
||||
<https://matrix.to/#/@gergely:polonkai.eu>`_, or any other channels you can find under the
|
||||
“Contact me” menu.
|
37
content/blog/2018-07-19-recurring-events.rst
Normal file
@@ -0,0 +1,37 @@
|
||||
Recurring events are hard
|
||||
#########################
|
||||
|
||||
:date: 2018-07-19T13:22:00Z
|
||||
:category: blog
|
||||
:tags: development
|
||||
:url: 2018/07/19/recurring-events/
|
||||
:save_as: 2018/07/19/recurring-events/index.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
It was almost a month ago when I `announced
|
||||
<{filename}2018-06-26-please-welcome-calendar-social.rst>`_ the development of Calendar.social.
|
||||
Since then I’m over some interesting and some less interesting stuff; (web) development, after
|
||||
all, is just a recurrence of patterns. Speaking of recurrence, I arrived to a really interesting
|
||||
topic: recurring events.
|
||||
|
||||
My initial thought was like “oh, that’s easy! Let’s insert all future occurences as a separate
|
||||
``Event`` object, linking to the original one for the details. That makes handling exceptions
|
||||
easy, as I just have to update/delete that specific instance.” Well, not really. I mean, an
|
||||
event repeating daily *forever* would fill up the database quickly, isn’t it? That’s when I
|
||||
decided to look how other projects do it.
|
||||
|
||||
As it turns out, my first thought is about the same as everyone else has their mind, with about
|
||||
the same reasons. Then, they usually turn down the idea just like I did. And instead, they
|
||||
implement recurrence patterns and exception patterns.
|
||||
|
||||
My favourite is `this article
|
||||
<https://github.com/bmoeskau/Extensible/blob/master/recurrence-overview.md>`_ so far. The author
|
||||
suggests to use the recurrence patterns specced by `RFC2445
|
||||
<http://www.ietf.org/rfc/rfc2445.txt>`_ (the spec for the iCalendar format). The interesting part
|
||||
in this solution is how to query recurring events: you simply store the timestamp of the last
|
||||
occurence of the events (or, if the event repeats forever, the greatest timestamp your database
|
||||
supports.)
|
||||
|
||||
Choosing the maximum date seemed to be the tricky one, but it turned out both Python and popular
|
||||
SQL backends support dates up to the end of year 9999.
|
@@ -0,0 +1,220 @@
|
||||
Check if the last Git commit has test coverage
|
||||
##############################################
|
||||
|
||||
:date: 2018-07-26T12:49:52Z
|
||||
:category: blog
|
||||
:tags: python,development,testing
|
||||
:url: 2018/07/26/check-if-last-git-commit-has-test-coverage/
|
||||
:save_as: 2018/07/26/check-if-last-git-commit-has-test-coverage/index.html
|
||||
:status: published
|
||||
:author: Gergely Polonkai
|
||||
|
||||
I use Python at work and for private projects. I also aim to write tests for my code, especially
|
||||
recently. And as I usually don’t start from 100% code coverage (TDD is not my game), I at least
|
||||
want to know if the code I just wrote have full coverage.
|
||||
|
||||
The trick is to collect all the lines that changed, and all the lines that has no coverage. Then
|
||||
compare the two, and you have the uncovered lines that changed!
|
||||
|
||||
Getting the list of changed lines
|
||||
=================================
|
||||
|
||||
Recently, I bumped into
|
||||
`this article <https://adam.younglogic.com/2018/07/testing-patch-has-test/>`_. It is a great awk
|
||||
script that lists the lines that changed in the latest commit. I have really no problem with awk,
|
||||
but I’m pretty sure it can be done in Python, as that is my main language nowadays.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def get_changed_lines():
|
||||
"""Get the line numbers that changed in the last commit
|
||||
"""
|
||||
|
||||
git_output = subprocess.check_output('git show', shell=True).decode('utf-8')
|
||||
|
||||
current_file = None
|
||||
lines = {}
|
||||
left = 0
|
||||
right = 0
|
||||
|
||||
for line in git_output.split('\n'):
|
||||
match = re.match(r'^@@ -([0-9]+),[0-9]+ [+]([0-9]+),[0-9]+ @@', line)
|
||||
|
||||
if match:
|
||||
left = int(match.groups()[0])
|
||||
right = int(match.groups()[1])
|
||||
|
||||
continue
|
||||
|
||||
if re.match(r'^\+\+\+', line):
|
||||
current_file = line[6:]
|
||||
|
||||
continue
|
||||
|
||||
if re.match(r'^-', line):
|
||||
left += 1
|
||||
|
||||
continue
|
||||
|
||||
if re.match(r'^[+]', line):
|
||||
# Save this line number as changed
|
||||
lines.setdefault(current_file, [])
|
||||
lines[current_file].append(right)
|
||||
right += 1
|
||||
|
||||
continue
|
||||
|
||||
left += 1
|
||||
right += 1
|
||||
|
||||
return lines
|
||||
|
||||
OK, not as short as the awk script, but works just fine.
|
||||
|
||||
Getting the uncovered lines
|
||||
===========================
|
||||
|
||||
Coverage.py can list the uncovered lines with ``coverage report --show-missing``. For
|
||||
Calendar.social, this looks something like this:
|
||||
|
||||
.. code-block:: log
|
||||
|
||||
Name Stmts Miss Cover Missing
|
||||
----------------------------------------------------------------------
|
||||
calsocial/__init__.py 173 62 64% 44, 138-148, 200, 239-253, 261-280, 288-295, 308-309, 324-346, 354-363
|
||||
calsocial/__main__.py 3 3 0% 4-9
|
||||
calsocial/account.py 108 51 53% 85-97, 105-112, 125, 130-137, 148-160, 169-175, 184-200, 209-212, 221-234
|
||||
calsocial/app_state.py 10 0 100%
|
||||
calsocial/cache.py 73 11 85% 65-70, 98, 113, 124, 137, 156-159
|
||||
calsocial/calendar_system/__init__.py 10 3 70% 32, 41, 48
|
||||
calsocial/calendar_system/gregorian.py 77 0 100%
|
||||
calsocial/config_development.py 11 11 0% 4-17
|
||||
calsocial/config_testing.py 12 0 100%
|
||||
calsocial/forms.py 198 83 58% 49, 59, 90, 136-146, 153, 161-169, 188-195, 198-206, 209-212, 228-232, 238-244, 252-253, 263-267, 273-277, 317-336, 339-342, 352-354, 362-374, 401-413
|
||||
calsocial/models.py 372 92 75% 49-51, 103-106, 177, 180-188, 191-200, 203, 242-248, 257-268, 289, 307, 349, 352-359, 378, 392, 404-409, 416, 444, 447, 492-496, 503, 510, 516, 522, 525, 528, 535-537, 545-551, 572, 606-617, 620, 652, 655, 660, 700, 746-748, 762-767, 774-783, 899, 929, 932
|
||||
calsocial/security.py 15 3 80% 36, 56-58
|
||||
calsocial/utils.py 42 5 88% 45-48, 52-53
|
||||
----------------------------------------------------------------------
|
||||
TOTAL 1104 324 71%
|
||||
|
||||
All we have to do is converting these ranges into a list of numbers, and compare it with the
|
||||
result of the previous function:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def get_uncovered_lines(changed_lines):
|
||||
"""Get the full list of lines that has not been covered by tests
|
||||
"""
|
||||
|
||||
column_widths = []
|
||||
uncovered_lines = {}
|
||||
|
||||
for line in sys.stdin:
|
||||
line = line.strip()
|
||||
|
||||
if line.startswith('---'):
|
||||
continue
|
||||
|
||||
if line.startswith('Name '):
|
||||
match = re.match(r'^(Name +)(Stmts +)(Miss +)(Cover +)Missing$', line)
|
||||
assert match
|
||||
|
||||
column_widths = [len(col) for col in match.groups()]
|
||||
|
||||
continue
|
||||
|
||||
name = [
|
||||
line[sum(column_widths[0:idx]):sum(column_widths[0:idx]) + width].strip()
|
||||
for idx, width in enumerate(column_widths)][0]
|
||||
missing = line[sum(column_widths):].strip()
|
||||
|
||||
for value in missing.split(', '):
|
||||
if not value:
|
||||
continue
|
||||
|
||||
try:
|
||||
number = int(value)
|
||||
except ValueError:
|
||||
first, last = value.split('-')
|
||||
lines = range(int(first), int(last) + 1)
|
||||
else:
|
||||
lines = range(number, number + 1)
|
||||
|
||||
for lineno in lines:
|
||||
if name in changed_lines and lineno not in changed_lines[name]:
|
||||
uncovered_lines.setdefault(name, [])
|
||||
uncovered_lines[name].append(lineno)
|
||||
|
||||
return uncovered_lines
|
||||
|
||||
At the end we have a dictionary that has filenames as keys, and a list of changed but uncovered
|
||||
lines.
|
||||
|
||||
Converting back to ranges
|
||||
=========================
|
||||
|
||||
To make the final result more readable, let’s convert them back to a nice ``from_line-to_line``
|
||||
range list first:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def line_numbers_to_ranges():
|
||||
"""List the lines that has not been covered
|
||||
"""
|
||||
|
||||
changed_lines = get_changed_lines()
|
||||
uncovered_lines = get_uncovered_lines(changed_lines)
|
||||
|
||||
line_list = []
|
||||
|
||||
for filename, lines in uncovered_lines.items():
|
||||
lines = sorted(lines)
|
||||
last_value = None
|
||||
|
||||
ranges = []
|
||||
|
||||
for lineno in lines:
|
||||
if last_value and last_value + 1 == lineno:
|
||||
ranges[-1].append(lineno)
|
||||
else:
|
||||
ranges.append([lineno])
|
||||
|
||||
last_value = lineno
|
||||
|
||||
range_list = []
|
||||
|
||||
for range_ in ranges:
|
||||
first = range_.pop(0)
|
||||
|
||||
if range_:
|
||||
range_list.append(f'{first}-{range_[-1]}')
|
||||
else:
|
||||
range_list.append(str(first))
|
||||
|
||||
line_list.append((filename, ', '.join(range_list)))
|
||||
|
||||
return line_list
|
||||
|
||||
Printing the result
|
||||
===================
|
||||
|
||||
Now all that is left is to print the result on the screen in a format digestable by a human being:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def tabular_print(uncovered_lines):
|
||||
"""Print the list of uncovered lines on the screen in a tabbed format
|
||||
"""
|
||||
|
||||
max_filename_len = max(len(data[0]) for data in uncovered_lines)
|
||||
|
||||
for filename, lines in uncovered_lines:
|
||||
print(filename.ljust(max_filename_len + 2) + lines)
|
||||
|
||||
And we are done.
|
||||
|
||||
Conclusion
|
||||
==========
|
||||
|
||||
This task never seemed hard to accomplish, but somehow I never put enough energy into it to make
|
||||
it happen. Kudos to Adam Young doing some legwork for me!
|
12
content/drafts/cut-at-ten.rst
Normal file
@@ -0,0 +1,12 @@
|
||||
cut-at-ten
|
||||
##########
|
||||
|
||||
:status: draft
|
||||
:author: Gergely Polonkai
|
||||
:date: 2019-11-03T07:21Z
|
||||
|
||||
.. code-block:: lisp
|
||||
|
||||
(defun cut-at-ten ()
|
||||
(while (re-search-forward "," (save-excursion (end-of-line) (point)) t 10)
|
||||
(newline-and-indent)))
|
15
content/drafts/gtk-actionable-in-action.rst
Normal file
@@ -0,0 +1,15 @@
|
||||
GtkActionable in action
|
||||
#######################
|
||||
|
||||
:status: draft
|
||||
:author: "Gergely Polonkai"
|
||||
:date: 2017-09-17T00:00Z
|
||||
|
||||
I have seen several people (including myself) struggling with disabling/enabling menu items,
|
||||
toolbar buttons and similar UI interfaces based on different conditions. It gets even worse if
|
||||
there are multiple representations of the same action in the same application, e.g. a menu item
|
||||
and a toolbar button exists for the same action. But with GTK+ 3.4, we have GtkAction, which is
|
||||
exactly for this kind of situations.
|
||||
|
||||
.. include:: ../files/gtk-actionable-test.glade
|
||||
:code: xml
|
@@ -0,0 +1,14 @@
|
||||
Measuring code coverage with codecov for libtool projects
|
||||
#########################################################
|
||||
|
||||
:author: Gergely Polonkai
|
||||
:status: draft
|
||||
:date: 2017-09-17T02:00Z
|
||||
|
||||
I have recently found `codecov <https://codecov.io/>`_; they offer free services for public GitHub
|
||||
projects. As I have recently started writing tests for my SWE-GLib project, I decided to give it
|
||||
a go. Things are not this easy if you use GNU Autotools and libtool, though…
|
||||
|
||||
The problem here is that these tools generate output under ``src/.libs/`` (given that your sources
|
||||
are under ``src/``) and ``gcov`` has hard times finding the coverage data files. Well, at least
|
||||
in the codecov environment, it works fine on my machine.
|
55
content/drafts/programming-as-i-see-it.rst
Normal file
@@ -0,0 +1,55 @@
|
||||
Programming, as I see it
|
||||
########################
|
||||
|
||||
:category: blog
|
||||
:status: draft
|
||||
:author: Gergely Polonkai
|
||||
:date: 2017-09-17T02:00Z
|
||||
|
||||
since my age of around 11, i write code. i began with basic, which is, well, the most basic
|
||||
language i have ever seen. simply writing ``10 print "hello world!"`` does the job (with assembly
|
||||
it would be tens of lines as i recall). then i moved to pascal, then delphi (which is basically
|
||||
the same thing). the next step was a bit longer, as i started learning more languages after this,
|
||||
like perl (for dynamic web pages), c (for desktop applications), tcl (for eggdrop programming.
|
||||
yes, i might have been a weird kid), php (again, for dynamic web pages. it was becoming
|
||||
mainstream back then).
|
||||
|
||||
many of my classmates looked down on me, as they thought i was a geek (hell i was, but i wouldn’t
|
||||
have confessed it then), and called me a nerd. for a few months maybe i was depressed, but after
|
||||
that i realised that this is the thing i want to do in my life, this is the thing i’m good at.
|
||||
|
||||
Most people I ask why don’t they code say “it’s too hard”. I’ve attended some courses (both
|
||||
online and offline, and I was like “Whoa! Coding is extremely hard! What the hell! I will never
|
||||
learn it!”, but right after the course I realised that everything is just fine, I can still write
|
||||
programs, and it’s eeeeasy. So then, what’s the problem?
|
||||
|
||||
After looking through many course papers, I found that most teachers do it totally wrong. A
|
||||
programming language is just that: a language. You don’t start learning Spanish by going into a
|
||||
classic literature conference in Madrid and doing a speech, but learn the basic vocabulary and
|
||||
grammar. The same goes for coding. You learn the vocabulary (the basic commands or keywords) and
|
||||
grammar (syntax). I had several ideas how this could be taught, just didn’t have the background
|
||||
to do it.
|
||||
|
||||
The idea of teaching programming lingers in my head for years now, and a few days ago, I’ve bumped
|
||||
into `this video <https://www.youtube.com/watch?v=dU1xS07N-FA>`_. So it seems that technology
|
||||
superstars like Bill Gates and Mark Zuckerberg wants to do the same. Maybe they don’t have enough
|
||||
high quality coders at hand. Well of course, if teachers make it awfully hard to learn it! So a
|
||||
bunch of guys sat together and created `code.org <http://www.code.org/>`_ to achieve my old dream.
|
||||
I like the idea. And although I have almost no visitor on this blog of mine, allow me to give you
|
||||
a few points on how I see programming.
|
||||
|
||||
Great learning process
|
||||
======================
|
||||
|
||||
When you write programs, especially during the first years, you adapt a new way of thinking and
|
||||
learning. If you learn it as an adult, it can be a bit of a pain, but as a child, it’s easy as
|
||||
learning how the wheels of those little cars spin).
|
||||
|
||||
A job
|
||||
=====
|
||||
|
||||
Art
|
||||
===
|
||||
|
||||
Magic
|
||||
=====
|
315
content/drafts/writing-a-gnome-shell-extension.rst
Normal file
@@ -0,0 +1,315 @@
|
||||
Writing a GNOME Shell extension
|
||||
###############################
|
||||
|
||||
:date: 2017-09-17T03:00Z
|
||||
|
||||
I could not find a good tutorial on how to write a GNOME Shell extension. There is a so called
|
||||
step by step `instruction list
|
||||
<https://wiki.gnome.org/Projects/GnomeShell/Extensions/StepByStepTutorial>`_ on how to do it, but
|
||||
it has its flaws, including grammar and clearance. As I wanted to create an extension for my SWE
|
||||
GLib library to display the current position of some planets, I dug into existing (and working)
|
||||
extensions’ source code and made up something. Comments welcome!
|
||||
|
||||
---
|
||||
|
||||
GNOME Shell extensions are written in JavaScript and are interpreted by `GJS
|
||||
<https://wiki.gnome.org/action/show/Projects/Gjs>`_. Using introspected libraries from JavaScript
|
||||
is not a problem for me (see SWE GLib’s `Javascript example
|
||||
<https://github.com/gergelypolonkai/swe-glib/blob/master/examples/basic.js>`_; it’s not beautiful,
|
||||
but it’s working), but wrapping your head around the Shell’s concept can take some time.
|
||||
|
||||
The Shell is a Clutter stage, and all the buttons (including the top-right “Activities” button)
|
||||
are actors on this stage. You can add practically anything to the Shell panel that you can add to
|
||||
a Clutter stage.
|
||||
|
||||
The other thing to remember is the lifecycle of a Shell extension. After calling ``init()``, there
|
||||
are two ways forward: you either use a so called extension controller, or plain old JavaScript
|
||||
functions ``enable()`` and ``disable()``; I will go on with the former method for reasons
|
||||
discussed later.
|
||||
|
||||
If you are fine with the ``enable()``/``disable()`` function version, you can ease your job with
|
||||
the following command:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
gnome-shell-extension-tool --create-extension
|
||||
|
||||
This will ask you a few parameters and create the necessary files for you. On what these
|
||||
parameters should look like, please come with me to the next section.
|
||||
|
||||
Placement and naming
|
||||
====================
|
||||
|
||||
Extensions reside under ``$HOME/.local/share/gnome-shell/extensions``, where each of them have its
|
||||
own directory. The directory name has to be unique, of course; to achieve this, they are usually
|
||||
the same as the UUID of the extension.
|
||||
|
||||
The UUID is a string of alphanumeric characters, with some extras added. Generally, it should
|
||||
match this regular expression: ``^[-a-zA-Z0-9@._]+$``. The convention is to use the form
|
||||
``extension-name@author-id``, e.g. ``Planets@gergely.polonkai.eu``. Please see `this link
|
||||
<https://wiki.gnome.org/Projects/GnomeShell/Extensions/UUIDGuidelines>`_ for some more information
|
||||
about this.
|
||||
|
||||
Anatomy of an extension
|
||||
=======================
|
||||
|
||||
Extensions consist of two main parts, ``metadata.json`` and ``extension.js``.
|
||||
|
||||
The ``metadata.json`` file contains compatibility information and, well, some meta data:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"shell-version": ["3.18"],
|
||||
"uuid": "planets@gergely.polonkai.eu",
|
||||
"name": "Planets",
|
||||
"description": "Display current planet positions"
|
||||
}
|
||||
|
||||
Here, ``shell-version`` must contain all versions of GNOME Shell that is known to load and display
|
||||
your extension correctly. You can insert minor versions here, like I did, or exact version
|
||||
numbers, like ``3.18.1``.
|
||||
|
||||
In the ``extension.js`` file, which contains the actual extension code, the only thing you
|
||||
actually need is an ``init()`` function:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
function init(extensionMeta) {
|
||||
// Do whatever it takes to initialize your extension, like initializing the translations.
|
||||
// However, never do any widget magic here yet.
|
||||
|
||||
// Then return the controller object
|
||||
return new ExtensionController(extensionMeta);
|
||||
}
|
||||
|
||||
Extension controller
|
||||
====================
|
||||
|
||||
So far so good, but what is this extension controller thing? It is an object which is capable of
|
||||
managing your GNOME Shell extension. Whenever the extension is loaded, its ``enable()`` method is
|
||||
called; when the extension is unloaded, you guessed it, the ``disable()`` method gets called.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
function ExtensionController(extensionMeta) {
|
||||
return {
|
||||
extensionMeta: extensionMeta,
|
||||
extension: null,
|
||||
|
||||
enable: function() {
|
||||
this.extension = new PlanetsExtension(this.extensionMeta);
|
||||
|
||||
Main.panel.addToStatusArea("planets", this.extension, 0, "right");
|
||||
},
|
||||
|
||||
disable: function() {
|
||||
this.extension.actor.destroy();
|
||||
this.extension.destroy();
|
||||
|
||||
this.extension = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
This controller will create a new instance of the ``PlanetsExtension`` class and add it to the
|
||||
panel’s right side when loaded. Upon unloading, the extension’s actor gets destroyed (which, as
|
||||
you will see later, gets created behind the scenes, not directly by us), together with the
|
||||
extension itself. Also, for safety measures, the extension is set to ``null``.
|
||||
|
||||
The extension
|
||||
=============
|
||||
|
||||
The extension is a bit more tricky, as, for convenience reasons, it should extend an existing
|
||||
panel widget type.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
function PlanetsExtension(extensionMeta) {
|
||||
this._init(extensionMeta);
|
||||
}
|
||||
|
||||
PlanetsExtension.prototype = {
|
||||
__proto__ = PanelMenu.Button.prototype,
|
||||
|
||||
_init: function(extensionMeta) {
|
||||
PanelMenu.Button.prototype._init.call(this, 0.0);
|
||||
|
||||
this.extensionMeta = extensionMeta;
|
||||
|
||||
this.panelContainer = new St.BoxLayout({style_class: 'panel-box'});
|
||||
this.actor.add_actor(this.panelContainer);
|
||||
this.actor.add_style_class_name('panel-status-button');
|
||||
|
||||
this.panelLabel = new St.Label({
|
||||
text: 'Loading',
|
||||
y_align: Clutter.ActorAlign.CENTER
|
||||
});
|
||||
|
||||
this.panelContainer.add(this.panelLabel);
|
||||
}
|
||||
};
|
||||
|
||||
Here we extend the ``Button`` class of ``panelMenu``, so we will be able to do some action upon
|
||||
activate.
|
||||
|
||||
The only parameter passed to the parent’s ``_init()`` function is ``menuAlignment``, with the
|
||||
value ``0.0``, which is used to position the menu arrow. (*Note: I cannot find any documentation
|
||||
on this, but it seems that with the value ``0.0``, a menu arrow is not added.*)
|
||||
|
||||
The extension class in its current form is capable of creating the actual panel button displaying
|
||||
the text “Loading” in its center.
|
||||
|
||||
Loading up the extension
|
||||
========================
|
||||
|
||||
Now with all the necessary import lines added:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
// The PanelMenu module that contains Button
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
// The St class that contains lots of UI functions
|
||||
const St = imports.gi.St;
|
||||
// Clutter, which is used for displaying everything
|
||||
const Clutter = imports.gi.Clutter;
|
||||
|
||||
As soon as this file is ready, you can restart your Shell (press :kbd:`Alt-F2` and enter the
|
||||
command ``r``), and load the extension with e.g. the GNOME Tweak Tool. You will see the Planets
|
||||
button on the right. This little label showing the static text “Planets”, however, is pretty
|
||||
boring, so let’s add some action.
|
||||
|
||||
Adding some periodical change
|
||||
=============================
|
||||
|
||||
Since the planets’ position continuously change, we should update our widget every minute or
|
||||
so. Let’s patch our ``_init()`` a bit:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
this.last_update = 0;
|
||||
|
||||
MainLoop.timeout_add(1, Lang.bind(this, function() {
|
||||
this.last_update++;
|
||||
this.panelLabel.set_text("Update_count: " + this.last_update);
|
||||
}))
|
||||
|
||||
This, of course, needs a new import line for ``MainLoop`` to become available:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
const MainLoop = imports.mainloop;
|
||||
const Lang = imports.lang;
|
||||
|
||||
Now if you restart your Shell, your brand new extension will increase
|
||||
its counter every second. This, however, presents some problems.
|
||||
|
||||
SWE GLib queries can sometimes be expensive, both in CPU and disk operations, so updating our
|
||||
widget every second may present problems. Also, planets don’t go **that** fast. We may update
|
||||
our timeout value from ``1`` to ``60`` or something, but why don’t just give our user a chance to
|
||||
set it?
|
||||
|
||||
Introducing settings
|
||||
====================
|
||||
|
||||
Getting settings from ``GSettings`` is barely straightforward, especially for software installed
|
||||
in a non-GNOME directory (which includes extensions). To make our lives easier, I copied over a
|
||||
`convenience library
|
||||
<https://github.com/projecthamster/shell-extension/blob/master/convenience.js>`_ from the `Hamster
|
||||
project <https://projecthamster.wordpress.com/>`_’s extension, originally written by Giovanni
|
||||
Campagna. The relevant function here is ``getSettings()``:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
/**
|
||||
* getSettings:
|
||||
* @schema: (optional): the GSettings schema id
|
||||
*
|
||||
* Builds and return a GSettings schema for @schema, using schema files
|
||||
* in extensionsdir/schemas. If @schema is not provided, it is taken from
|
||||
* metadata['settings-schema'].
|
||||
*/
|
||||
function getSettings(schema) {
|
||||
let extension = ExtensionUtils.getCurrentExtension();
|
||||
|
||||
schema = schema || extension.metadata['settings-schema'];
|
||||
|
||||
const GioSSS = Gio.SettingsSchemaSource;
|
||||
|
||||
// check if this extension was built with "make zip-file", and thus
|
||||
// has the schema files in a subfolder
|
||||
// otherwise assume that extension has been installed in the
|
||||
// same prefix as gnome-shell (and therefore schemas are available
|
||||
// in the standard folders)
|
||||
let schemaDir = extension.dir.get_child('schemas');
|
||||
let schemaSource;
|
||||
if (schemaDir.query_exists(null))
|
||||
schemaSource = GioSSS.new_from_directory(schemaDir.get_path(),
|
||||
GioSSS.get_default(),
|
||||
false);
|
||||
else
|
||||
schemaSource = GioSSS.get_default();
|
||||
|
||||
let schemaObj = schemaSource.lookup(schema, true);
|
||||
if (!schemaObj)
|
||||
throw new Error('Schema ' + schema + ' could not be found for extension '
|
||||
+ extension.metadata.uuid + '. Please check your installation.');
|
||||
|
||||
return new Gio.Settings({ settings_schema: schemaObj });
|
||||
}
|
||||
|
||||
You can either incorporate this function into your ``extension.js`` file, or just use
|
||||
``convenience.js`` file like I (and the Hamster applet) did and import it:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Me = ExtensionUtils.getCurrentExtension;
|
||||
const Convenience = Me.imports.convenience;
|
||||
|
||||
Now let’s create the settings definition. GSettings schema files are XML files. We want to add
|
||||
only one settings for now, the refresh interval.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<schemalist>
|
||||
<schema id="org.gnome.shell.extensions.planets" path="/org/gnome/shell/extensions/planets/">
|
||||
<key name="refresh-interval" type="i">
|
||||
<default>30</default>
|
||||
<summary>Refresh interval of planet data</summary>
|
||||
<description>Interval in seconds. Sets how often the planet positions are recalculated. Setting this too low (e.g. below 30) may raise performance issues.</description>
|
||||
</key>
|
||||
</schema>
|
||||
</schemalist>
|
||||
|
||||
you need to compile these settings with
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
glib-compile-schemas --strict schemas/
|
||||
|
||||
Now let’s utilize this new setting. In the extension’s ``_init()`` function, add the following
|
||||
line:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
this._settings = Convenience.getSettings();
|
||||
|
||||
And, for ``getSettings()`` to work correctly, we also need to extend our ``metadata.json`` file:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
"settings-schema": "planets"
|
||||
|
||||
After another restart (please, GNOME guys, add an option to reload extensions!), your brand new
|
||||
widget will refresh every 30 seconds.
|
||||
|
||||
Displaying the planet positions
|
||||
===============================
|
||||
|
||||
The settings panel
|
||||
==================
|
||||
|
||||
Start an application
|
||||
====================
|
54
content/drafts/writing-an-sdk.rst
Normal file
@@ -0,0 +1,54 @@
|
||||
Lessons you learn while writing an SDK
|
||||
######################################
|
||||
|
||||
:tags: development
|
||||
:author: Gergely Polonkai
|
||||
:date: 2017-09-17T01:00Z
|
||||
|
||||
In the last few months I’ve been working on a GLib based SDK for client applications that want to
|
||||
communicate with a Matrix.org homeserver.
|
||||
|
||||
For whoever doesn’t know it, Matrix is a decentralized network of servers (Homeservers). Clients
|
||||
can connect to them via HTTP and send messages (events, in Matrix terminology) to each other.
|
||||
They are called events because these messages can be pretty much anything from instant messages
|
||||
through automated notifications to files or, well, actual events (such as a vCalendar); anything
|
||||
that you can serialize to JSON can go through this network.
|
||||
|
||||
My original intention was to integrate Matrix based chat into Telepathy, a DBus based messaging
|
||||
framework used by e.g. the GNOME desktop (more specifically Empathy, GNOME's chat client.) After
|
||||
announcing my plans among the Matrix devs, I quickly learned some things:
|
||||
|
||||
1. they are more than open to any development ideas
|
||||
2. they really wanted to see this working
|
||||
3. they would have been happy if there were a GLib or Qt based SDK
|
||||
|
||||
With my (far from complete) knowledge in GLib I decided to move on with this last point, hoping
|
||||
that it will help me much when I finally implement the Telepathy plugin.
|
||||
|
||||
Matrix devs are open minded
|
||||
===========================
|
||||
|
||||
What I learned very quickly is that Matrix devs are very open minded folks from different parts of
|
||||
the world. They are all individuals with their own ideas, experiences and quirks, yet, when it
|
||||
comes to that, they steer towards their goals as a community. Thus, getting additional
|
||||
information from them while reading the spec was super easy.
|
||||
|
||||
The specification is easy to understand
|
||||
=======================================
|
||||
|
||||
Except when it is not. For these cases, see the previous point.
|
||||
|
||||
Jokes aside, anyone who worked with communications protocols or JSON APIs before can get along
|
||||
with it fast. The endpoints are all documented, and if something is unclear, they are happy to
|
||||
help (especially if you patch up the spec afterwards.)
|
||||
|
||||
Copying the SDK for a different language is not (always) what you want
|
||||
======================================================================
|
||||
|
||||
I started my SDK in C, trying to mimic the Python SDK. This was a double fail: the Python SDK was
|
||||
a volatile WiP, and C and Python are fundamentally different.
|
||||
|
||||
During the upcoming weeks this became clear and I switched to the Vala language. It is much
|
||||
easier to write GObject based stuff in Vala, although I had to fall back to C to get some features
|
||||
working. I also planned and implemented a more object oriented API, which is easier to use in the
|
||||
GObject world.
|
12
content/failmeter/css/failmeter.css
Normal file
@@ -0,0 +1,12 @@
|
||||
body {
|
||||
padding-top: 80px;
|
||||
}
|
||||
|
||||
.fail:hover {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.progress {
|
||||
margin-bottom: 0;
|
||||
background-color: #cacaca;
|
||||
}
|
186
content/failmeter/index.html
Normal file
@@ -0,0 +1,186 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>F/OSS Fail meter</title>
|
||||
<meta name="date" content="2015-08-14T12:23:34Z">
|
||||
|
||||
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" integrity="sha256-MfvZlkHCEqatNoGiOXveE8FIwMzZg4W85qfrfIFBfYc= sha512-dTfge/zgoMYpP7QbHy4gWMEGsbsdZeCXz7irItjcC3sPUFtf0kuFbDz/ixG7ArTxmDjLXDmezHubeNikyKGVyQ==" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="css/failmeter.css" type="text/css">
|
||||
|
||||
<script src="//code.jquery.com/jquery-2.1.4.min.js"></script>
|
||||
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js" integrity="sha256-Sk3nkD6mLTMOF0EOpNtsIry+s1CsaqQC1rVLTAy+0yc= sha512-K1qjQ+NcF2TYO/eI3M6v8EiNYZfA95pQumfvcVrTHtwQVDG+aHRqLi/ETn2uB+1JqwYqVG3LIvdm9lj6imS/pQ==" crossorigin="anonymous"></script>
|
||||
<script src="js/failmeter.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-default navbar-fixed-top">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand">Fail meter for F/OSS projects</a>
|
||||
</div>
|
||||
<div class="navbar-text" id="failtext"></div>
|
||||
<p class="navbar-text navbar-right">
|
||||
Based on <a href="http://spot.livejournal.com/308370.html" class="navbar-link">this article</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div id="failmeter" class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;">
|
||||
<span id="points">0</span>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container">
|
||||
<h2>Size</h2>
|
||||
<ul class="fail-list list-group">
|
||||
<li class="list-group-item fail" data-points="1">The source code is more than 100 MB.</li>
|
||||
<li class="list-group-item fail" data-points="1">If the source code also exceeds 100 MB when it is compressed</li>
|
||||
</ul>
|
||||
|
||||
<h2>Source Control</h2>
|
||||
<ul class="fail-list list-group">
|
||||
<li class="list-group-item fail" data-points="2">There is no publicly available source control (e.g. cvs, svn, bzr, git)</li>
|
||||
<li class="list-group-item">There is publicly available source control, but:
|
||||
<ul class="fail-list list-group">
|
||||
<li class="list-group-item fail" data-points="1">There is no web viewer for it</li>
|
||||
<li class="list-group-item fail" data-points="1">There is no documentation on how to use it for new users</li>
|
||||
<li class="list-group-item fail" data-points="6">You've written your own source control for this code</li>
|
||||
<li class="list-group-item fail" data-points="10">You don't actually use the existing source control</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>Building From Source</h2>
|
||||
<ul class="fail-list list-group">
|
||||
<li class="list-group-item fail" data-points="4">There is no documentation on how to build from source</li>
|
||||
<li class="list-group-item fail" data-points="2">Documentation exists on how to build from source, but it doesn't work</li>
|
||||
<li class="list-group-item">Your source is configured…
|
||||
<ul class="list-group fail-list choose-one">
|
||||
<li class="list-group-item fail" data-points="2">…with a handwritten shell script</li>
|
||||
<li class="list-group-item fail" data-points="4">…by editing flat text config files</li>
|
||||
<li class="list-group-item fail" data-points="6">…by editing code header files manually</li>
|
||||
<li class="list-group-item fail" data-points="10">Your source isn't configurable</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="list-group-item">You source builds with…
|
||||
<ul class="list-group fail-list choose-one">
|
||||
<li class="list-group-item fail" data-points="2">…something that isn't GNU Make</li>
|
||||
<li class="list-group-item fail" data-points="10">…a third-party proprietary build tools</li>
|
||||
<li class="list-group-item fail" data-points="20">…something you wrote for this code</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>Bundling</h2>
|
||||
<ul class="fail-list list-group">
|
||||
<li class="list-group-item fail" data-points="4">Your source only comes with other code projects that it depends on</li>
|
||||
<li class="list-group-item fail" data-points="2">Your source code cannot be built without first building the bundled code bits</li>
|
||||
<li class="list-group-item fail" data-points="8">You have modified those other bundled code bits</li>
|
||||
</ul>
|
||||
|
||||
<h2>Libraries</h2>
|
||||
<ul class="fail-list list-group">
|
||||
<li class="list-group-item fail" data-points="4">Your code only builds static libraries</li>
|
||||
<li class="list-group-item fail" data-points="4">Your code can build shared libraries, but only unversioned ones</li>
|
||||
<li class="list-group-item fail" data-points="4">Your source does not try to use system libraries if present</li>
|
||||
</ul>
|
||||
|
||||
<h2>System Install</h2>
|
||||
<ul class="fail-list list-group">
|
||||
<li class="list-group-item fail" data-points="2">Your code tries to install into /opt or /usr/local without explicitly telling it to do so</li>
|
||||
<li class="list-group-item fail" data-points="4">Your code has no "make install"</li>
|
||||
<li class="list-group-item fail" data-points="6">Your code doesn't work outside of the source directory</li>
|
||||
</ul>
|
||||
|
||||
<h2>Code Oddities</h2>
|
||||
<ul class="fail-list list-group">
|
||||
<li class="list-group-item fail" data-points="1">Your code uses Windows line breaks ("DOS format" files)</li>
|
||||
<li class="list-group-item fail" data-points="4">Your code depends on specific compiler feature functionality</li>
|
||||
<li class="list-group-item fail" data-points="10">Your code depends on specific compiler bugs</li>
|
||||
<li class="list-group-item fail" data-points="20">Your code depends on Microsoft Visual Anything</li>
|
||||
</ul>
|
||||
|
||||
<h2>Communication</h2>
|
||||
<ul class="fail-list list-group">
|
||||
<li class="list-group-item fail" data-points="1">Your project does not announce releases on a mailing list</li>
|
||||
<li class="list-group-item fail" data-points="2">Your project does not have a mailing list</li>
|
||||
<li class="list-group-item fail" data-points="4">Your project does not have a bug tracker</li>
|
||||
<li class="list-group-item fail" data-points="10">Your project does not have a website</li>
|
||||
<li class="list-group-item fail" data-points="20">Your project is sourceforge vaporware</li>
|
||||
</ul>
|
||||
|
||||
<h2>Releases</h2>
|
||||
<ul class="fail-list list-group">
|
||||
<li class="list-group-item fail" data-points="2">Your project does not do sanely versioned releases (Major, Minor)</li>
|
||||
<li class="list-group-item fail" data-points="4">Your project does not do versioned releases</li>
|
||||
<li class="list-group-item fail" data-points="10">Your project does not do releases</li>
|
||||
<li class="list-group-item fail" data-points="20">Your project only does releases as attachments in web forum posts</li>
|
||||
<li class="list-group-item">Your releases are <em>only</em> in
|
||||
<ul class="list-group choose-one">
|
||||
<li class="list-group-item fail" data-points="1">.zip format</li>
|
||||
<li class="list-group-item fail" data-points="2">OSX .zip format</li>
|
||||
<li class="list-group-item fail" data-points="4">.rar format</li>
|
||||
<li class="list-group-item fail" data-points="10">.arj format</li>
|
||||
<li class="list-group-item fail" data-points="20">an encapsulation format that you invented</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="list-group-item fail" data-points="2">Your release does not unpack into a versioned top-level directory (e.g. <code>glibc-2.4.2/</code>)</li>
|
||||
<li class="list-group-item fail" data-points="5">Your release does not unpack into a top-level directory (e.g. <code>glibc/</code>)</li>
|
||||
<li class="list-group-item fail" data-points="10">Your release unpacks into an absurd number of directories (e.g. <code>home/johndoe/glibc-svn/tarball/glibc/src/</code>)</li>
|
||||
</ul>
|
||||
|
||||
<h2>History</h2>
|
||||
<ul class="fail-list list-group">
|
||||
<li class="list-group-item fail" data-points="2">Your code is a fork of another project</li>
|
||||
<li class="list-group-item fail" data-points="10">Your primary developers were not involved with the parent project</li>
|
||||
<li class="list-group-item">Until open sourcing it, your code was proprietary for:
|
||||
<ul class="list-group choose-one">
|
||||
<li class="list-group-item fail" data-points="2">1-2 years</li>
|
||||
<li class="list-group-item fail" data-points="4">3-5 years</li>
|
||||
<li class="list-group-item fail" data-points="6">6-10 years</li>
|
||||
<li class="list-group-item fail" data-points="10">10+ years</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>Licensing</h2>
|
||||
<ul class="fail-list list-group">
|
||||
<li class="list-group-item fail" data-points="2">Your code does not have per-file licensing</li>
|
||||
<li class="list-group-item fail" data-points="4">Your code contains inherent license incompatibilities</li>
|
||||
<li class="list-group-item fail" data-points="6">Your code does not have any notice of licensing intent</li>
|
||||
<li class="list-group-item fail" data-points="10">Your code doesn't include a copy of the license text</li>
|
||||
<li class="list-group-item fail" data-points="20">Your code doesn't have a license</li>
|
||||
</ul>
|
||||
|
||||
<h2>Documentation</h2>
|
||||
<ul class="fail-list list-group">
|
||||
<li class="list-group-item fail" data-points="2">Your code doesn't have a changelog</li>
|
||||
<li class="list-group-item fail" data-points="4">Your code doesn't have any documentation</li>
|
||||
<li class="list-group-item fail" data-points="6">Your website doesn't have any documentation</li>
|
||||
</ul>
|
||||
|
||||
<script>
|
||||
append_point_values();
|
||||
calc_max_points();
|
||||
update_points();
|
||||
|
||||
$('.fail').click(function() {
|
||||
parent = $(this).parent();
|
||||
|
||||
if (parent.hasClass('choose-one')) {
|
||||
newState = !$(this).hasClass('active');
|
||||
parent.children().removeClass('active');
|
||||
if (newState) {
|
||||
$(this).addClass('active');
|
||||
} else {
|
||||
$(this).removeClass('active');
|
||||
}
|
||||
} else {
|
||||
$(this).toggleClass('active');
|
||||
}
|
||||
|
||||
update_points();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
70
content/failmeter/js/failmeter.js
Normal file
@@ -0,0 +1,70 @@
|
||||
var max_points = 0;
|
||||
var points = 0;
|
||||
|
||||
function append_point_values() {
|
||||
$('li[data-points]').each(function() {
|
||||
points = $(this).attr('data-points');
|
||||
$(this).append(' [' + points + ' points of FAIL]');
|
||||
});
|
||||
}
|
||||
|
||||
function calc_max_points() {
|
||||
$('ul:not(.choose-one) > li[data-points]').each(function() {
|
||||
points = $(this).attr('data-points');
|
||||
max_points += +points;
|
||||
});
|
||||
|
||||
$('li:has(ul.choose-one)').each(function() {
|
||||
var this_max = NaN;
|
||||
$(this).children('ul.choose-one').children('li').each(function() {
|
||||
points = +$(this).attr('data-points');
|
||||
|
||||
if (isNaN(this_max) || points > this_max) {
|
||||
this_max = points;
|
||||
}
|
||||
});
|
||||
|
||||
max_points += this_max;
|
||||
});
|
||||
}
|
||||
|
||||
function update_points() {
|
||||
var points = 0;
|
||||
|
||||
$('.active').each(function() {
|
||||
points += +$(this).attr('data-points');
|
||||
});
|
||||
|
||||
if (max_points == 0) {
|
||||
percent = 0;
|
||||
} else {
|
||||
percent = points / max_points * 100;
|
||||
}
|
||||
|
||||
$('#failmeter').attr('aria-valuenow', percent).css('width', percent + '%');
|
||||
$('#points').html(points + '/' + max_points);
|
||||
|
||||
if (percent == 0) {
|
||||
failtext = 'Perfect! All signs point to succes!';
|
||||
type = 'success';
|
||||
} else if (percent < 1.6) {
|
||||
failtext = 'You are probably doing okay, but you could be better.';
|
||||
type = 'success';
|
||||
} else if (percent < 3.8) {
|
||||
failtext = 'Babies cry when your code is downloaded.';
|
||||
type = 'info';
|
||||
} else if (percent < 5.7) {
|
||||
failtext = 'Kittens die when your code is downloaded.';
|
||||
type = 'warning';
|
||||
} else if (percent < 8.2) {
|
||||
failtext = 'HONK HONK. THE FAILBOAT HAS ARRIVED!';
|
||||
type = 'danger';
|
||||
} else {
|
||||
failtext = 'So much fail, your code should have its own reality show.';
|
||||
type = 'danger';
|
||||
}
|
||||
|
||||
$('#failmeter').removeClass('progress-bar-success progress-bar-info progress-bar-warning progress-bar-danger');
|
||||
$('#failmeter').addClass('progress-bar-' + type);
|
||||
$('#failtext').html(failtext);
|
||||
}
|
BIN
content/favicon.ico
Normal file
After Width: | Height: | Size: 1.1 KiB |
4
content/files/geekcode.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
-----BEGIN GEEK CODE BLOCK-----
|
||||
Version: 3.1
|
||||
GCM/CS/IT/O d--(+) s++:- a C++$ UB++L++++$ P++ L+++$ E++>$ W+++$ N o? K w+ O M- V PS+ PE Y+ PGP+(++) t+ 5 X R !tv b+ DI++ D+ G e h----() r+++ y++++
|
||||
-----END GEEK CODE BLOCK-----
|
124
content/files/gtk-actionable-test.glade
Normal file
@@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.16.1 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.10"/>
|
||||
<object class="GtkAccelGroup" id="accelgroup1"/>
|
||||
<object class="GtkActionGroup" id="actiongroup1">
|
||||
<property name="accel_group">accelgroup1</property>
|
||||
</object>
|
||||
<object class="GtkAction" id="radio_action">
|
||||
<property name="label" translatable="yes">Radio Action Label</property>
|
||||
</object>
|
||||
<object class="GtkWindow" id="window1">
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkMenuBar" id="menubar1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="menuitem1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">_File</property>
|
||||
<property name="use_underline">True</property>
|
||||
<child type="submenu">
|
||||
<object class="GtkMenu" id="menu1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkRadioMenuItem" id="imagemenuitem1">
|
||||
<property name="use_action_appearance">True</property>
|
||||
<property name="related_action">radio_action</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Radio 1</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_as_radio">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRadioMenuItem" id="imagemenuitem2">
|
||||
<property name="use_action_appearance">True</property>
|
||||
<property name="related_action">radio_action</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Radio 2</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_as_radio">True</property>
|
||||
<property name="group">imagemenuitem1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRadioMenuItem" id="imagemenuitem3">
|
||||
<property name="use_action_appearance">True</property>
|
||||
<property name="related_action">radio_action</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Radio 3</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_as_radio">True</property>
|
||||
<property name="group">imagemenuitem1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparatorMenuItem" id="separatormenuitem1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckMenuItem" id="imagemenuitem5">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparatorMenuItem" id="separatormenuitem2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="menuitem2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">menuitem2</property>
|
||||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToolbar" id="toolbar1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="width">1</property>
|
||||
<property name="height">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
132
content/gergely@polonkai.eu.asc
Normal file
@@ -0,0 +1,132 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQINBFGVyIEBEADyJd0ZKYSGRKO44QShxeeU3xE6JQBFHRaObxZr5kZ1DkmG1hbm
|
||||
iVoRe0bwAUmYjaiK2YasQ0x/Sjl9C+KOYsovv33/td+s429d8dJQqiF2gppKI1wC
|
||||
1Mbc8BJgq/QZn0K9y1bu5RgqWfRqZInvbpxj5ovtCC0iVgoO2wv9v/u81jagaT+3
|
||||
Aswumi7JHXQgtZtYsKjTm1w2e/968AwRK3rAymrK4tKcf2/YkoL4SlZEnkFia42C
|
||||
sFSHBXbaSNJFQG6KHtQiMCKvI4OpOxTdlrw11BEuwPuC8qsRMt0F5CH7VPUBiysq
|
||||
NcuGhXhEPsVVZsL13jR8VZMY4sis1rwDqY8GI8nmH2dJ2OfGkr5EzLrSQ0NKGJ8Z
|
||||
9YA79cxwnvBE/vKik0Td4/j8yJNGWHR63tpw0VgER2OSS61QWNsq+uBHr6AvjY71
|
||||
kud3ojocKaO9xkud3O/7IBD9tU2PZskaS6rUDkaHh8a02R2qJToDYG0H7R5J+v+y
|
||||
Cupi/kNmtY1V+jQQ4QdO574pGiTZTWCPkqHGWjMWf90u3ISakdfrLWJdtgNKkprD
|
||||
6GjpuWDL7MiVnvCTxahFiBiLczKxLhm+vt05DNDfRCiS7wAPv7U3luw/tkOyC9tN
|
||||
pZd/zcdF4iDFw+CBc/H+t8mi6lp0CaoajtaCGvIpCXQzMmCGw5oZeAA7nwARAQAB
|
||||
tDJHZXJnZWx5IFBvbG9ua2FpIChXMDBkNXQwY2spIDxnZXJnZWx5QHBvbG9ua2Fp
|
||||
LmV1PokCTgQTAQoAOAIbAwIeAQIXgAYLCQgHAwIGFQgCCQoLAxYCARYhBBPWBHaz
|
||||
WvyovAE6MvQruliwdAxMBQJaXgYgAAoJEPQruliwdAxM/CMQAMxTiMnZ8P7QHErp
|
||||
ptnQNJq7dygWNmIGWvdBlMg3ePGROTOBp74A5QOf/guzj+85aeIihjYNzP4DZX4B
|
||||
wvOxuL3SnqsrYbJjkVqhxplvAfrNhqrVwxYJF0+fwuLaqr0UwAjlHdH30N5OjUPL
|
||||
BTHvdBi5eb7HE19YsghvAiE0Q3i/TjaUtPsRa/JUBwS0DVD0cYhWy953wFY2Tn9X
|
||||
FpoY3XtuNlwSQReYj4aOEjFOEomhkb0Adgldad3EpJQBTkcduyiJWtyfaKy7CSn8
|
||||
HgVlhZ6AyNY5BeV4km5vEROGz476UtZh7j6dsvsUfTs+mdwyGVEmejY1e5GqZAN4
|
||||
NBWJBq5uqR9qJC16AOHZZtV1FHskENpO9DcckwnP9dAwvynKhR1NwXmAJa/WI+WA
|
||||
D7fwO5b/MQnYS6VFWTs0r+FaKCKhU26rOBFEUUDtMckexESIPvTRSx/++xenOUjT
|
||||
vcgViZyRfiiU87JO/yWPY0s3Rhh1fsv3Sl+IlPymaoIEI0YDdfgR79d0QQxZwYba
|
||||
AoTZ+fwjfTk7585pbcNfi+6WV16vx57Zk+ipY4RPaa990thPOYXYZq7NDsKUeYxU
|
||||
sm8N6LBvVllQgF/9X5COj4gLwic3crAV/RNvym60FAQ4wK2QASNa7lxJh6Fe8pOc
|
||||
1KY/hiRXADK37BGEyPqJHBpOTr1iuQINBFGVyIEBEADLCj4bc16zjenpGcAxOjAl
|
||||
ItEEkvW9D1hgTtN4mT8FcZsaGRwH7HKhjmL85l1EwqsnDLR2BCyspp8S4D0MLg6v
|
||||
yZSP3XGs7EASzqNgfgwSKSfpejUknMFtJeaWCheA2jyvUt2FwGnaEpd7QFl2O4Of
|
||||
muJXUN5RipKSIcBC+AlRK8uZkTgXAgND0RY5ZlqeoOww+Cnt5La5mKta8DBwSAen
|
||||
z5RM3xyPUBbnkx7n5F0FGLhklJguilfn+MFhS50IQpCrIaAIWc72hWc+lDz9Tht3
|
||||
zcUzsVsbRdh4dSw7Ya7QSc53ozveuvXGXihKgSCwUjPrPq5C0MIs6+o0uvebj3Pp
|
||||
BOKA4C6CS0R9ycxCFB9Xl4wO2c8bGzKPnD5TjoReeEAsmgH0BNX3FdpKWA4mBFY2
|
||||
xqkW/xSN+JgKhcllOsuyhG4zUOwUpKfGm9tQUz4DXiPHCJXFMVYxIxt9rnc+5jBa
|
||||
j2H8NVNOMeXuwoSkNDCqgfDdBKr5r/ntTNJmJ/Sdmosf4GQzyFv1W4InW6FRSLTD
|
||||
BXtqWsGq6OvrcfgaZkt0b24/u7TzxOXuKpW3NLx8uFusNR0ZJ1tbei9ryzrnweqY
|
||||
hu/tBnqoApMXl4VaWp+O4ujHohSzl/O0rXtYITNDex4nNyXUJjllNDayzEihVvzw
|
||||
enwvq+Xg3NY8bt2Y2MpEiwARAQABiQI2BBgBCgAgAhsMFiEEE9YEdrNa/Ki8AToy
|
||||
9Cu6WLB0DEwFAlpeBi0ACgkQ9Cu6WLB0DEwzeRAAmkBpax4kEs1S5saXy9MmMS+G
|
||||
6ZcOzMynSW3GF2u/XOqDPErpSn/BesOuOmyw9WY30D8YOb25CVwkNzBv85S70Esc
|
||||
y7sMBopjZ11cJt3K47syp2f+CwdgAx+kHoRoCVNnE+CdsA6COXUV/ulF4HMpNJqW
|
||||
h174pg2cFkphdGAMVpqwuIvLVGioL2q7KK7Sbr01VgD7v45qA2V8ZbidjHp5fZWE
|
||||
tmUiF0ETZQdbbHmsiOqIyip7CYjIoxcGhxq4Y5NlBxCZY8Z1lcJtuAr0B2umEMh0
|
||||
Pg8DZyUobC0cilUhQAOzYVsZi/xrhYC91gnWXYSRoOJ9vEz20XUMztMEuppRVmON
|
||||
c+V8DyO78VAgvDclGrj+GRTWpbB3kgJxeelCXnm16TrOwl+J2qQZ/rtCuZRHZ3ZF
|
||||
/LPsg9T7/XTZHkcKheAnIH9Y59dPslTttENO40EBD9VxJGOYFntBykjTXPWhG6Eh
|
||||
yxKjg87ZP5B9uS8pMOZS4GFYoLKd82Lpf9uItzOMNInTPw2Vi7Qx4J466msOvDa/
|
||||
x9cd9PjEoG2S8Uac0+vJaEVcENc5y+Qmk17vY0lbyjtABC2vr7Vq1U9t00nQurjQ
|
||||
ASUGFFde9E8KPbMILIoMMHzJB+GYQ2Yu45AI2y/xWzlQCmP32ZEG66l9NVrcVkhx
|
||||
QVo+0DLn+NkGRR8Phuy5Ag0EWlzXfQEQAOpgMmUwZWVv1K+8De3xT1/8Yrqhp+z0
|
||||
8wkg3ztOsrRfTBimALcgbF+IrJ15r4s8Tcqx7pwc+Gi5ijWTDJvJFneeJP+EgyM5
|
||||
OYAroySP5oc5IrZuB9kTs6ol7ta5hlrCqlNSM/lgxaTqABliv8LhhpJVYjigyfoE
|
||||
5hZTQ2+pL252qAm55vldG8CIVuWBllSlRaljVu25GSRj9hJfq3g94vaAQ9vMzPHp
|
||||
+tKWUwg4PoO9p5VyP2oU9HawkkbJZskimMmyxAIHkidTmhcJh0Fa9XbZT5lH6QCg
|
||||
DAVJdxBH5+fRak6/YM96zaebQ/RW+Dmbgo8ysb+M/B09ysIuxD0Iii9MvVyqkYPD
|
||||
jyY98Kale800YwXWCDQ4mSDDO+loFWkGLp/NdztXEa5Wm+zEaGZhY3MtwupfbKk/
|
||||
/bAdduUMylN0JAxkr9d3V+i7+ltJBAJf1R5s37fYYMkWN5SfgsRCgyib7+d9FCoC
|
||||
afP3+RDjV55fIPQYFAmWH56PxXZvMQ7rOvpI1xUjomN4bxdvZY6oXyks+mgdddbT
|
||||
BP9nPwZ9WCldYpEAZNUW6/Fxe6si/Khe7VWH23oXtt6ECEIX+ctyAn6hD1nDlGgR
|
||||
UWl+eVCXSzmxWYRPt57g8Ysy99tUhfC3MFxRzdR+d5rxb/Xu9mBXsPI84n+0Hbgj
|
||||
hR7ry9iZG6p1ABEBAAGJBGwEGAEKACAWIQQT1gR2s1r8qLwBOjL0K7pYsHQMTAUC
|
||||
WlzXfQIbAgJACRD0K7pYsHQMTMF0IAQZAQoAHRYhBJrFyL2SFE2hJshDqgMcyLAQ
|
||||
SguHBQJaXNd9AAoJEAMcyLAQSguHww8QAKY2Qc8EenhBiW1XQ61g1hdu6v8j7ika
|
||||
FpHrkf7zAdAgE1zpPRXU+6Pu0f63Y9Y3/lsMy1iE5jb6+ZbIXEgLZ1BdYDFWrdhy
|
||||
U3m3jURlVdHBhqcA7kHHjei44CwrBzi9zPnFExI2o87YtS7Dk2fvJP3Ds3Yru66L
|
||||
BcdXndM+Iz6oZsEIRfI7BeFPWN1IXg8Q2VRjl+g6zXBHRHo4lRAxbfTAi3kFGcRM
|
||||
Y/OhNGsSNA6sgq9CL35gG86HoSv89EMmWe2ZoGTu3DVJNy98q5bs31dUyNoYKoQn
|
||||
/xUs4rpj5LgRO3tAaixEUMCzFevnQI+nZ6cj/JZRLG+EEdaRUXoUz3jJxSfyisj4
|
||||
rFPyjAG373f449/1cqkb850OczOLU9FEGBLbl9B6S8iQZ7LSwwqVsw7Hwd/8eEND
|
||||
9gXVjstGcgbRZgzgykQu5OAmc/R5JjJyTk5wIebVAxWXiUlO11mxE9ogYBMdc0ux
|
||||
hrm4yu1xvFEOvADIBRfuWHTk2FUlORFnYIN/Oq4XfuO/ysvYjfoTom9gKMMmfEn/
|
||||
Y0ZL+wy27jcIfX8BBhUyFQG9UWyZgkNQmuNgxPReZOWi1DrLzY/Q+PwafWJtDx3p
|
||||
LJuYEqNXJsJ16BJ5srPpdia0SEQ1VQJe92nUf27QAs9fDcUrv1KRVDCp81MJGhIf
|
||||
Gkm7QNwNblqMKF0P/jPGeEbbdoMxgBcgeH6cTbB8pq4EDmQnWF7mRQJJ+//1bbZY
|
||||
Q6Pxv+HxEGF6R/rcJF9sCxn7Bu1ZDR4Tq0mGQvFkoFnyj4SADzt0Dwbq/CsNY1Sz
|
||||
5TpiIFhG8gin0F812RqGY1wmcRWLRsUVsBpJwXGdguo06om7ofXdeZZckM6EUujH
|
||||
RyRQHa8+F88ZoUb5X2+BYgD0iScxqG+sqGM5cSY8R4/CrELKAwX0mnYvpU6jMk+D
|
||||
cPEnuccObJaR42CaqpCZEv5f7MwI1RMb7OZAt+vHBB5Di1kNCGUzrMcv7n/6H3g2
|
||||
N+z9D4FlLHdPIV4LRCP2kkTAArjtNFokkXZWbkX1ZSJrR4MQUT4+cGVu8JkyGePT
|
||||
AiHPDMAgggLS85lh5835/G56HJqku/w0CMrJmUvP8Dt8HuSaepOaCLlgTp/dM/lJ
|
||||
emA5UK0k5SLOuJmru+6SZmlz7YzWJhQqFyAFnbC96x9/xy1gQvdYRCqMuMQVtMRL
|
||||
Gt91e5wkTIvTyiugH4qf62WFuCfqpRsyI3d3+8eyKtiJibsFzRJSBdBNuvqyH9UQ
|
||||
vkzD8i1IsI+0r7cNrIJia57LbVmEVr6Af5ZqZ9wgQS2W/Rqm8/fvLuruWnCJE6jo
|
||||
wwe8Xil3EHO4Lz6yPiz5MG+4uS1AeVxSM1XYkhgvhYyFWj3VF4xobs3I2+GCuQIN
|
||||
BFpc17wBEACmy9i8mQtd1GUCB8sk6Q7qzWuS8Dd/TJhDAVWVNPmzlPeB+FxIemAq
|
||||
IbFNFxDiH+4H7zd3ntkpUnoj5u3D/Mrlwo0/rf8HM3XYOaElEaYfGarCAPobUYbV
|
||||
opb9b9a9xYdHhbm/k6SYgax7wF7Q4gRuKvo3PMtcegO2dyVSWQuDW2fK2VXTGuJb
|
||||
w8nWq/Lpr2JpxQw6mVaftAXP96UuuvlOSvEFBmkPrczeiv1rtqLRZ40JiEX80XFA
|
||||
+uf9YGzmVWD3CSh9RCIk5R2AysT6yVF2S4ijmhyn4oT++Gq/uFIqGWi6q+fIpLwp
|
||||
qyHyyS4XA1c1QfKXG27hmYGj59xvgw8uQKriMV6d8N5Wh5wBT7gqKYWKo15lXpom
|
||||
/ac9vXESCPvASYqco6/qwbR8BvnsjpLMv9RsouMj92p9HxNEtY/qm7l36PbXc38s
|
||||
Jkdr5QuQQzLhC5LZsuOHewHPaTxg4U67p1d5apAecWrL2kJwAjcArFr+SlJWgbgw
|
||||
pW43xqsInodj44lK5fiO0umRCSEL5NVGYB5k0aUDBds+wOerCpy1onzt5wUlGCf8
|
||||
oy2ixJSpHFxnczTzc3EyEEJYd76ScElYWPBDD+97MuZpYn4f9c8I868NgIFQ19aj
|
||||
ys5RJC0bAWYCT/YlJt5MYM9ssLCSFoXWqjlMtv+QAhMoLcXTVHP61wARAQABiQI2
|
||||
BBgBCgAgFiEEE9YEdrNa/Ki8AToy9Cu6WLB0DEwFAlpc17wCGwwACgkQ9Cu6WLB0
|
||||
DEwM1xAAjerPLAf3KqhzSNBgte29NYXXMt2EW3X8LxwSNsuXaPIPrVnO5qPhLLNf
|
||||
amqZ6qKyfxrPJ/KKLIClx4LAjs6Z9CxEyXvm6gdIOQaKt09p6Z/GglqJn5tNtxJW
|
||||
RgegDvdJFo82bRE5N9NdpJbvyWJhmUXHY1FTVKs5OePOa4DfnXNOJL+ReEl2ZTU4
|
||||
v301vAPyCCLfrVoCLChoi/Qg/PfcwV3x8RmBHZq2Q6Jvdyv0SMBvDO7C8LIdCNFA
|
||||
HENkw0F1/LY2yZIKnnWTSLP+R7V11vLSEzOgpxx1qC2ierDcxjdZdxzYW+jVICKI
|
||||
TH8Wn8zejPuqYvlRTZfSRq0EzqZNcc/1LWjZJb3zWCf14KGEcvVfvBCaFhflpTE1
|
||||
J3BPZ0NXcqIA0nHHOg9hatvjnozWXapi8uwt01oM4w+4+vjA8sm3t79UbJ3DrJzc
|
||||
atuXBN0gFQKoMqZdkIOejjctWVjZRF0dFDbxH1G5Rp+raH6N2sA+wHpeSCjYLbFg
|
||||
bjRaK0aM29d5+1kqV4oft4+2jPu/ss9AvwLj9k5sk6cFPL7L5MR/WEOJ7Sc+QmM2
|
||||
7uyDAhKwXYVXrDT7Cf3xomUwaoQo4EtVrIEjMFYBwl7+MY0YW5nZ1yAWj3qXWzdT
|
||||
8tXEpQ4ZFjPQUJxAfyOmDUghPLGbFAA6AtROHwbZqpWf2LrYmxe5Ag0EWlzXzAEQ
|
||||
AN2sn2uK9Z+0BhaUe36tPv44PnZK2CMji6vE/iAZr1mGK0cHvRHSDPFhLwZtefYj
|
||||
0O0iBV6nI0t3L5JNvoJDxMmp00ZkG7yEIQdDlqL5Je9WqIu09aY3s47UKA7pCg1s
|
||||
qpX092u+5B0qkQdzH4mp136aZPBR2TXWTbHoUMxOwpb2OaTct86EdltdTbEUkVHm
|
||||
MfvciPj2Pw/41zQReL+FTWJaVq5vgUkkvOdVtruXxL8umgIwB5e27k9mWVB5w2UZ
|
||||
1uI9B8cGU2y0F6upQRmYJerQirVc+5z6lnI+zMOi6nEFH8exqEejZmFubZpMQ6vi
|
||||
zyZe0SGLQxTFLgWqpHHq/VOE2tsENzGU6rVFRquP8djl7/26SQaqqPH8b5y+5XDN
|
||||
CSpNLWL3X2g/yKStlYIH6JzsGgA3vNS4be8ugXiwyXeDIo5um9cyMK3QxLPRU6cO
|
||||
/haS1thZGV7uNqZe150APQLYIsO2nikqKmPgGblLqGfVZK56uWjW8kbxIullzdLM
|
||||
3xsHeUcANKaaVrcBd2g2JQRdjVKI9dddvzOGAy++sCyXHR8fCeWYWIQukeOHZUmC
|
||||
N3lLojg2IWxSh/J5XnBf8jQndyqsxX2y0QvYll7GqXG713xUy+gN/CEavTJXgLER
|
||||
2a/eaYHvFovnMk7/5wvAsvKhoOUGzZl04j3KH5mQiF4rABEBAAGJAjYEGAEKACAW
|
||||
IQQT1gR2s1r8qLwBOjL0K7pYsHQMTAUCWlzXzAIbIAAKCRD0K7pYsHQMTKIBD/4r
|
||||
YOFjFMzHTRewOiqWIa60DQI153MZf3eQfOYEatrXOWB9NcO3iUzgK/8zpubgso5u
|
||||
6Sa9+rrPW2CxW//N2jthFNs7h7FAqCXxQNpymC/BjbG9uP3xTlGk4fy0cddp7htn
|
||||
JvIeb2cKTwzBc2iFp408wWCKiVROxQC+2KBhppMl9B11U4nTUuAJ06grwK83NLl6
|
||||
9Nk8arMEs+cRDgwiJfgeViRu4leXI6Mztchpj+8fsUCOLqaK9SsTS7Oh1j9wVJQT
|
||||
vezqKe41PhjmHKIk4kVNHuOB2Nu1HSqqQJ4mp1F+lqd7GGQT+/7TGIqTP+EVTLox
|
||||
aw9jaC66v/QVhO+jGGlRBbNUMT24is3tXOg4GN2xq55sEJSnWEP9S0r1nqu+mtcj
|
||||
Go716YZgpPbU/BltRdFO07zHS6pKSWtoaqt2J29bk4XBLgQ6Otn6sXBJJlYoopF/
|
||||
iG0X4dt0SAZgD49AEcDdwGn81aAY0wlYYLy3ngZTfMyIplpTkQVlGZ3N0Fmptc5B
|
||||
JBbkgjIn+ThyQhkK37npm6YfaWStcGZWmvVQcSkaweuH/ifuuCRYEVD6kRN3Ytvo
|
||||
jRixSuRWDfcfVtZ3EIYSi74LStf80ecCqNgzmmow9IOeC80Epy2vciTgMaRYzAMw
|
||||
WCnMUi1MXE2xy5yZXtc66Hv5zR6+EUWS+rPYBXYLaQ==
|
||||
=ZVqC
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
16
content/gerrit-dashboard-generator/README.md
Normal file
@@ -0,0 +1,16 @@
|
||||
Title: README for the Gerrit dashboard generator
|
||||
Status: draft
|
||||
Date: 2017-09-17T03:00Z
|
||||
---
|
||||
|
||||
# Dashboard URL generator for Gerrit
|
||||
|
||||
This little HTML file will generate URLs for Gerrit Dashboards. As constructing such URL is a real PITA, I created this tool to make my, and fellow developers’ life easier.
|
||||
|
||||
## Usage
|
||||
|
||||
To use the tool, put it on a static webserver (opening it from your local machine won’t work, as it loads its dependencies from CDN hosts). For example, if you have Python installed, you can use
|
||||
|
||||
python -m SimpleHTTPServer 8000
|
||||
|
||||
and access the page via http://127.0.0.1:8000/. Static (ie. local machine-compatible) version is on the table, so if you can’t fire up a static webserver, check back soon(ish).
|
335
content/gerrit-dashboard-generator/index.html
Normal file
@@ -0,0 +1,335 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Gerrit Dashboard URL generator</title>
|
||||
<meta name="date" content="2016-08-17T15:15Z">
|
||||
<meta name="save_as" content="gerrit-dashboard-generator/index.html">
|
||||
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.1.0.slim.min.js"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container" id="main">
|
||||
<div class="modal fade" id="helpModal" tabindex="-1" role="dialog" aria-labelledby="helpModalLabel">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title" id="helpModalLabel">Help</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p><a href="https://gerrit-review.googlesource.com/Documentation/user-dashboards.html">Gerrit dashboards</a> are a powerful way to filter changes in a project into multiple categories. For example, you can construct a dashboard to show the changes in one project grouped by state (drafts, opened, reviewed, abandoned, closed).</p>
|
||||
<p>One way to create dashboards is to modify the project configuration. Most developers don’t have the necessary rights for this. The other way is to construct a special dashboard link. Anyone with access to the Gerrit instance can do that, but doing so is really painful. The goal of this tool is to lend a helping hand in that.</p>
|
||||
<p>The <strong>Gerrit base URL</strong> is the base URL of your Gerrit instance.</p>
|
||||
<p><strong>Dashboard title</strong> will be the title of your dashboard, and will be displayed on the top of the page.</p>
|
||||
<p>To create a new section, just press the <strong>+ Add secion</strong> button. You can name all the sections by filling the <strong>Section title</strong> field. If you omit that, it will be called <em>Section <n></em>, where <n> is the index of the section (numbered from 1; sorry about that.)</p>
|
||||
<p>If you decide a section is not needed, press the big red <strong>- Remove</strong> button next to the section title.</p>
|
||||
<p>To add a new filter to a section, press the <strong>+ Add filter</strong> button. You can choose the filter type (e.g. you can filter on branch name, state, project, and many other fields. There is a list at the bottom of this panel.) When you find the correct filtering field, just enter a filter value in the input box. If you actually want to <strong>exclude</strong> changes matching that filter, tick the checkbox on the right of the input box.</p>
|
||||
<p>Gerrit filters are concatenated together by <strong>AND</strong> operators. If you want to match on, for example, multiple branches, don’t create multiple <em>Branch</em> filters, but separate the branch names with colons (:), like <code>master:develop</code>.</p>
|
||||
<p>If you decide a filter is not needed, select the <strong>Delete this filter</strong> from the filter type dropdown.</p>
|
||||
<p>The dashboard URL on the bottom of the page will update with every change you make, just like the <strong>Try it!</strong> button’s target URL.</p>
|
||||
<p>You can add dashboards to the <strong>My</strong> tab of the Gerrit page. Navigate to <strong>Settings > Preferences</strong> and Enter a name in the input field under <strong>My Menu</strong>, and enter the generated <strong>Dashboard URL</strong> in the URL field, then press the <strong>+</strong> button on the left. Using the arrows on the rigt of the table you can reorganize the different dashboards you add here; the first link will be opened when you login to Gerrit. (<em>Hint</em>: You can add pretty much anything as the URL of a page, like basic queries or your settings page.)</p>
|
||||
<p>Finally, the list of filters currently supported by this tool:</p>
|
||||
|
||||
<dl>
|
||||
<dt>Project</dt>
|
||||
<dd>The project where you want the changes from. If you don’t specify this, changes from <em>all</em> projects will be shown!</dd>
|
||||
|
||||
<dt>Branch</dt>
|
||||
<dd>The branch for which the change was submitted.</dd>
|
||||
|
||||
<dt>State</dt>
|
||||
<dd>The change state. Some possible values are <em>starred</em> (will match on changes starred by the current user), <em>reviewed</em> (will match on changes with at least one non-zero vote in any category), <em>owner</em> (will match on changes owned by the current user), <em>reviewer</em> (will match on changes where the current user is added as a reviewer), <em>open</em> (will match on any open changes, ie. that is not merged nor abandoned yet), <em>draft</em> (will match on draft changes), <em>closed</em> (will match on closed changes, ie. merged or abandoned), <em>merged</em> (will match on changes that have been merged to the target branch), <em>mergeable</em> (will match on changes that have no merge conflicts).</dd>
|
||||
</dl>
|
||||
|
||||
<p>If you want me to add new filter fields, have a problem to report, or you have a feature in your mind I could add, contact me!</p>
|
||||
|
||||
<h4>Known limitations</h4>
|
||||
|
||||
<ul>
|
||||
<li>It is impossible to create complex queries with this tool (like closed changes on branch a <strong>OR</strong> drafts on branch b). Even though the example I provided is a bit silly, there are use cases where you want to do such complex queries, but if you need that, you are on your own. Sorry.</li>
|
||||
<li>This page is not protected from XSS, CSRF, You-Name-It-Vulnerability, so use it with care. Gerrit, on the other hand, provides such protections, so your forgery will be prevented anyway.</li>
|
||||
<li>This page is tested only in Google Chrome. If you bump into problems in other browsers, contact me!</li>
|
||||
</ul>
|
||||
|
||||
<h4>Contact</h4>
|
||||
|
||||
<p>…in order of preference</p>
|
||||
|
||||
<ul>
|
||||
<li>You have a problem with the tool? Or maybe a feature idea? <a href="https://github.com/gergelypolonkai/gerrit-dashboard-generator/issues">Open an issue on GitHub</a>!</li>
|
||||
<li>Matrix (<a href="https://vector.im/beta/#/user/@gergely:polonkai.eu">@gergely:polonkai.eu</a></li>
|
||||
<li><a href="mailto:gergely@polonkai.eu">e-mail</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="jumbotron">
|
||||
<h1>Gerrit Dashboard URL generator</h1>
|
||||
<p>You can use this site to generate a dashboard URL for your Gerrit instance.</p>
|
||||
<p><a class="btn btn-primary btn-lg" id="help-button" data-toggle="modal" data-target="#helpModal">Tell me the rules</a></p>
|
||||
</div>
|
||||
<form class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label for="gerrit-base" class="col-sm-2 control-label">Gerrit base URL</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="gerrit-base" placeholder="URL">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="dashboard-title" class="col-sm-2 control-label">Dashboard title</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="dashboard-title" placeholder="Title">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<h2 id="dashboard-title-header">Dashboard title goes here</h2>
|
||||
<hr id="last-hr">
|
||||
<button id="new-section">+ Add section</button>
|
||||
<hr>
|
||||
<form class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label for="dashboard-title" class="col-sm-2 control-label">Dashboard URL</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="dashboard-url" readonly="true">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<a id="test-link" href="#" target="_blank" class="hidden">Try it!</a>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
String.prototype.replaceAll = function(find, replacement) {
|
||||
var str = this;
|
||||
|
||||
return str.replace(new RegExp(find, 'g'), replacement);
|
||||
};
|
||||
|
||||
var filterList = {
|
||||
"project": "Project",
|
||||
"branch": "Branch",
|
||||
"is": "State"
|
||||
}
|
||||
|
||||
function filter_div(title) {
|
||||
filter_list = $('<ul></ul>')
|
||||
.addClass('dropdown-menu');
|
||||
|
||||
for (var key in filterList) {
|
||||
filter_list.append($('<li></li>')
|
||||
.append($('<a></a>')
|
||||
.attr('href', '#')
|
||||
.attr('data-field', key)
|
||||
.addClass('filter-chooser')
|
||||
.append(filterList[key])));
|
||||
}
|
||||
|
||||
filter_list.append($('<li></li>')
|
||||
.attr('role', 'separator')
|
||||
.addClass('divider'));
|
||||
|
||||
filter_list.append($('<li></li>')
|
||||
.append($('<a></a>')
|
||||
.attr('href', '#')
|
||||
.addClass('filter-delete')
|
||||
.append('Delete this filter')));
|
||||
|
||||
return $('<div></div>')
|
||||
.addClass('input-group')
|
||||
.append($('<div></div>')
|
||||
.addClass('input-group-btn')
|
||||
.append($('<button></button>')
|
||||
.addClass('btn')
|
||||
.addClass('btn-default')
|
||||
.addClass('dropdown-toggle')
|
||||
.attr('data-toggle', 'dropdown')
|
||||
.attr('aria-haspopup', 'true')
|
||||
.attr('aria-expanded', 'false')
|
||||
.append('<span>Field</span> ')
|
||||
.append($('<span></span>')
|
||||
.addClass('caret')))
|
||||
.append(filter_list))
|
||||
.append($('<input>')
|
||||
.addClass('form-control')
|
||||
.addClass('filter-value'))
|
||||
.append($('<span></span>')
|
||||
.addClass('input-group-addon')
|
||||
.append($('<input type="checkbox">')
|
||||
.addClass('negate')));
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
$('test-link').hide();
|
||||
|
||||
$('#new-section').click(function() {
|
||||
section_div = $('<div></div>')
|
||||
.addClass('dashboard-section')
|
||||
.append($('<h3>Title of the section </h3>')
|
||||
.append($('<a></a>')
|
||||
.addClass('btn')
|
||||
.addClass('btn-danger')
|
||||
.addClass('section-delete')
|
||||
.append('- Remove section')));
|
||||
|
||||
filter_add_button = $('<button></button>')
|
||||
.addClass('new-filter')
|
||||
.append('+ Add filter');
|
||||
|
||||
title_group = $('<div></div>')
|
||||
.addClass('form-group')
|
||||
.append($('<label></label>')
|
||||
.addClass('col-sm-2')
|
||||
.addClass('control-label')
|
||||
.append('Section title'))
|
||||
.append($('<div></div>')
|
||||
.addClass('col-sm-10')
|
||||
.append($('<input type="text">')
|
||||
.addClass('form-control')
|
||||
.addClass('section-title')));
|
||||
|
||||
section_div.append(title_group);
|
||||
section_div.append(filter_add_button);
|
||||
|
||||
section_div.insertBefore($('#last-hr'));
|
||||
|
||||
$(document).trigger('dashboard:changed');
|
||||
});
|
||||
});
|
||||
|
||||
$('#main').on('keyup', '.section-title', function() {
|
||||
title = $(this).val();
|
||||
|
||||
if (title == '') {
|
||||
title = 'Title of the section';
|
||||
}
|
||||
|
||||
$(this).parent().parent().prev()[0].innerHTML = title;
|
||||
|
||||
$(document).trigger('dashboard:changed');
|
||||
});
|
||||
|
||||
$('#main').on('click', '.section-delete', function() {
|
||||
if (window.confirm("Are you sure you want to remove this whole section?")) {
|
||||
$(this).parent().parent().remove();
|
||||
|
||||
$(document).trigger('dashboard:changed');
|
||||
}
|
||||
});
|
||||
|
||||
$('#main').on('click', '.new-filter', function() {
|
||||
filter_row = filter_div();
|
||||
filter_row.insertBefore($(this));
|
||||
|
||||
$(document).trigger('dashboard:changed');
|
||||
});
|
||||
|
||||
$('#main').on('click', '.filter-chooser', function() {
|
||||
input = $(this).parent().parent().parent().next();
|
||||
button_text = $(this).parent().parent().prev().children().first()[0];
|
||||
field = $(this).data().field;
|
||||
input.data('field', field);
|
||||
button_text.innerHTML = filterList[field];
|
||||
|
||||
$(document).trigger('dashboard:changed');
|
||||
});
|
||||
|
||||
$('#main').on('click', '.filter-delete', function() {
|
||||
if (window.confirm("Are you sure you want to remove this filter?")) {
|
||||
$(this).parent().parent().parent().parent().remove();
|
||||
|
||||
$(document).trigger('dashboard:changed');
|
||||
}
|
||||
});
|
||||
|
||||
$('#main').on('keyup', '.filter-value, #gerrit-base, #dashboard-title', function() {
|
||||
if ($(this).attr('id') == 'dashboard-title') {
|
||||
title = $(this).val();
|
||||
|
||||
if (title == '') {
|
||||
title = 'Title of the Dashboard';
|
||||
}
|
||||
|
||||
$('#dashboard-title-header')[0].innerHTML = title;
|
||||
}
|
||||
|
||||
$(document).trigger('dashboard:changed');
|
||||
});
|
||||
|
||||
$('#main').on('change', '.negate', function() {
|
||||
$(document).trigger('dashboard:changed');
|
||||
});
|
||||
|
||||
$('#dashboard-url').on('click', function() {
|
||||
$(this).select();
|
||||
});
|
||||
|
||||
$(document).on('dashboard:changed', function() {
|
||||
var params = {
|
||||
title: $('#dashboard-title').val()
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
|
||||
$('.dashboard-section').each(function() {
|
||||
i++;
|
||||
section_title = $(this).find('.section-title').val();
|
||||
|
||||
if (section_title == '') {
|
||||
section_title = 'Section ' + i;
|
||||
}
|
||||
|
||||
var filters = new Array();
|
||||
|
||||
$(this).find('.filter-value').each(function() {
|
||||
field = $(this).data().field;
|
||||
value = $(this).val();
|
||||
if ($(this).parent().find('.negate')[0].checked) {
|
||||
field = '-' + field;
|
||||
}
|
||||
|
||||
if (value.indexOf(' ') > -1) {
|
||||
value = '"' + value + '"';
|
||||
}
|
||||
|
||||
if ((field === undefined) || (value == '')) {
|
||||
$(this).parent().addClass('has-error');
|
||||
} else {
|
||||
$(this).parent().removeClass('has-error');
|
||||
|
||||
if (value.indexOf(':') > -1) {
|
||||
filters.push('(' + value.split(':').map(function(v) {return field + ':' + v}).join(' OR ') + ')');
|
||||
} else {
|
||||
filters.push(field + ':' + value);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
params[section_title] = filters.join(" ");
|
||||
});
|
||||
|
||||
sections = $.param(params)
|
||||
.replaceAll('%20', '+')
|
||||
.replaceAll('%3A', ':')
|
||||
.replaceAll('%2F', '/');
|
||||
|
||||
url = '#/dashboard/?' + sections;
|
||||
|
||||
$('#dashboard-url').val(url);
|
||||
|
||||
url = $('#gerrit-base').val() + url;
|
||||
|
||||
$('#test-link')
|
||||
.attr('href', url)
|
||||
.removeClass('hidden');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
BIN
content/images/nyan-eshell.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
content/images/nyan-modeline.png
Normal file
After Width: | Height: | Size: 162 KiB |
BIN
content/images/nyan-zone.png
Normal file
After Width: | Height: | Size: 24 KiB |
232
content/images/profile.svg
Normal file
@@ -0,0 +1,232 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.3.1 r9886"
|
||||
width="900"
|
||||
height="900"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="Jomagam by Juci.svg"
|
||||
inkscape:export-filename="/home/BROKERNET-GROUP/polonkai.gergely/Dropbox/Jomagam by Juci favicon.png"
|
||||
inkscape:export-xdpi="1.6"
|
||||
inkscape:export-ydpi="1.6"><metadata
|
||||
id="metadata8"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs6"><clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath16"><path
|
||||
d="m 0,1190.551 841.89,0 L 841.89,0 0,0 0,1190.551 z"
|
||||
id="path18"
|
||||
inkscape:connector-curvature="0" /></clipPath></defs><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1021"
|
||||
id="namedview4"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="0.70710678"
|
||||
inkscape:cx="304.5347"
|
||||
inkscape:cy="432.05546"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g10"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:snap-page="true"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"><sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="450,450"
|
||||
id="guide3178" /><sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="450,450"
|
||||
id="guide3180" /></sodipodi:namedview><g
|
||||
id="g10"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="PG_Vector"
|
||||
transform="matrix(1.25,0,0,-1.25,-201.75833,1487.0383)"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path22"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 519.65518,970.65954 c 8.739,0.76 18.998,9.499 25.838,14.818 6.839,5.32 14.818,6.84 23.558,6.08 6.838,-0.76 48.254,-7.219 47.115,-13.679 -1.52,-7.979 -12.539,-7.979 -17.859,-6.459 -6.839,2.28 -13.678,5.319 -20.517,7.219 -11.02,2.28 -28.117,5.7 -38.757,0.76" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path26"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 519.25388,969.07604 c 7.846,1.007 14.499,5.339 20.763,9.904 3.755,2.738 7.205,5.92 11.234,8.258 4.88,2.832 11.275,3.341 16.774,2.671 11.536,-1.405 23.174,-3.606 34.348,-6.792 2.683,-0.765 9.831,-2.207 10.878,-5.4 1.359,-4.147 -5.791,-5.439 -8.21,-5.453 -5.09,-0.028 -10.023,2.543 -14.683,4.299 -15.521,5.846 -36.499,10.811 -52.464,4.006 -3.726,-1.588 -0.308,-3.444 2.279,-2.342 10.231,4.362 22.824,1.469 33.295,-0.626 9.977,-1.996 19.039,-8.192 29.308,-8.587 6.261,-0.241 13.479,1.936 16.006,8.147 1.769,4.348 -5.071,6.465 -7.953,7.513 -12.167,4.425 -25.509,6.495 -38.299,8.23 -7.882,1.07 -16.319,0.372 -23.493,-3.284 -9.845,-5.017 -17.485,-15.9 -28.98,-17.377 -2.783,-0.357 -4.822,-3.684 -0.803,-3.167" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path30"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 647.69428,959.60584 c -5.333,-4.912 -4.42,-10.96 -2.134,-17.272 1.087,-3 2.488,-5.871 3.425,-8.927 1.678,-5.482 1.606,-11.701 2.307,-17.362 1.657,-13.415 10.161,-24.637 13.471,-37.641 1.37,-5.38 1.971,-12.215 -2.773,-16.121 -5.588,-4.602 -15.018,0.822 -20.424,3.275 -3.86,1.752 -7.716,3.291 -11.888,4.101 -7.417,1.439 -14.661,-1.886 -22.04,-0.988 -11.136,1.357 -5.041,17.951 1.543,21.116 3.496,1.68 -1.797,2.224 -3.509,1.401 -6.866,-3.3 -10.925,-10.949 -9.595,-18.477 1.446,-8.186 11.471,-7.471 17.627,-6.691 5.501,0.697 10.503,1.504 15.953,-0.135 5.378,-1.618 10.298,-4.56 15.56,-6.499 7.184,-2.646 17.624,-2.519 23.062,3.771 9.084,10.509 -1.765,28.732 -6.456,38.912 -4.333,9.403 -4.842,18.872 -6.31,29.033 -1.168,8.077 -10.91,20.752 -3.241,27.814 2.398,2.207 -3.349,1.821 -4.578,0.69" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path34"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 662.90128,963.44034 c 3.04,8.359 31.917,32.677 33.438,16.338 1.519,-16.718 -22.039,-12.159 -32.677,-16.338" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path38"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 665.76168,963.94234 c 2.152,5.327 22.347,26.55 26.974,17.918 1.423,-2.656 0.903,-6.467 -0.284,-9.068 -1.636,-3.589 -5.821,-4.531 -9.313,-5.149 -6.842,-1.211 -13.887,-1.106 -20.486,-3.514 -3.882,-1.416 -0.206,-2.19 2.019,-1.378 8.625,3.146 18.395,1.328 26.881,5.377 5.718,2.728 11.845,11.81 5.404,17.279 -5.003,4.248 -15.226,-1.975 -19.402,-4.699 -6.366,-4.154 -14.565,-10.472 -17.514,-17.77 -0.43,-1.067 5.114,-0.499 5.721,1.004" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path42"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 520.82218,954.52484 c 22.434,0.264 49.55,13.637 68.72,-3.634 1.567,-1.412 7.01,0.825 5.373,2.301 -20.603,18.562 -47.868,5.007 -71.866,4.725 -2.226,-0.026 -6.143,-3.438 -2.227,-3.392" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path46"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 653.00578,947.08734 c 6.661,-0.194 33.356,8.188 33.216,-3.422 -0.02,-1.596 5.769,-0.576 5.795,1.553 0.168,13.854 -29.533,4.728 -36.698,4.937 -2.041,0.06 -6.225,-2.954 -2.313,-3.068" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path50"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 665.56148,946.72164 c -7.22,-3.04 -0.76,-11.019 5.319,-11.019 6.08,0 10.259,7.979 4.56,12.159" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path54"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 664.40428,947.95984 c -3.177,-1.482 -5.961,-4.064 -4.516,-7.813 1.332,-3.455 5.292,-5.658 8.803,-6.049 4.22,-0.47 8.481,1.424 10.952,4.861 2.38,3.31 1.58,7.578 -1.515,10.05 -1.643,1.311 -7.021,-0.981 -5.375,-2.294 1.823,-1.456 2.76,-3.247 2.333,-5.598 -0.315,-1.73 -1.719,-3.781 -3.626,-3.708 -2.873,0.109 -9.197,5.997 -4.742,8.074 0.707,0.33 2.458,1.391 1.531,2.386 -0.878,0.941 -2.845,0.557 -3.845,0.091" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path58"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 610.64448,857.31484 c -4.052,-8.228 -10.829,-11.826 -19.727,-12.74 -6.781,-0.697 -13.363,0.073 -19.948,-2.041 -11.811,-3.792 -15.259,-17.369 -25.64,-23.048 -3.38,-1.849 1.961,-1.633 3.367,-0.864 5.663,3.098 9.551,7.618 13.434,12.674 1.906,2.48 3.869,4.876 6.196,6.977 3.61,3.261 7.685,3.445 12.327,3.516 13.929,0.213 28.966,2.81 35.716,16.516 0.478,0.971 -4.983,0.517 -5.725,-0.99" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path62"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 557.23918,820.62684 c -14.352,-10.616 -20.204,-27.121 -31.314,-40.377 -8.212,-9.798 -23.672,-19.801 -16.767,-34.545 0.913,-1.95 6.571,-0.102 5.796,1.552 -6.512,13.905 8.295,23.793 16.35,32.932 5.08,5.762 8.681,13.077 12.846,19.504 4.903,7.567 10.415,14.67 17.714,20.068 2.62,1.938 -3.209,1.913 -4.625,0.866" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path66"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 615.16888,854.37394 c 3.667,-7.75 21.753,-11.241 25.029,-1.392 1.029,3.092 -4.75,2.816 -5.508,0.537 -1.728,-5.195 -11.976,-1.291 -13.726,2.408 -1.144,2.418 -6.859,0.695 -5.795,-1.553" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path70"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 650.14248,850.92174 c -0.745,-9.934 5.588,-18.93 9.863,-27.428 1.385,-2.754 1.503,-3.047 -1.272,-4.685 -2.671,-1.577 -5.775,-2.322 -8.798,-2.845 -5.942,-1.029 -12.115,-0.604 -18.052,0.199 -12.044,1.628 -23.889,6.134 -35.215,10.356 -4.364,1.628 -8.368,2.226 -12.98,1.452 -5.317,-0.892 -10.783,-4.218 -16.098,-1.561 -1.457,0.729 -6.815,-1.486 -4.679,-2.553 8.016,-4.008 15.533,2.074 23.559,1.65 5.841,-0.308 12.467,-4.112 18.009,-5.96 5.093,-1.697 10.267,-3.257 15.474,-4.565 14.751,-3.706 34.352,-4.785 46.745,5.671 0.242,0.204 0.798,0.665 0.621,1.077 -4.042,9.45 -12.228,19.245 -11.417,30.05 0.15,2.01 -5.636,0.791 -5.76,-0.858" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path74"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 569.95308,816.75774 c 0.987,-12.188 18.904,-16.562 28.499,-18.946 13.859,-3.444 27.472,-3.137 37.284,8.48 0.238,0.283 -4.609,0.221 -5.703,-1.073 -2.455,-2.908 -5.325,-5.737 -9.069,-6.885 -3.208,-0.982 -6.915,-0.419 -10.157,0.053 -4.535,0.661 -9.045,1.864 -13.43,3.173 -8.009,2.392 -20.828,6.88 -21.629,16.751 -0.074,0.922 -5.913,-0.1 -5.795,-1.553" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path78"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 652.21088,810.04874 c -5.682,-8.583 -11.531,-17.167 -16.947,-25.912 -4.691,-7.573 -2.809,-15.877 0.466,-23.54 3.763,-8.808 7.047,-17.606 6.742,-27.344 -0.293,-9.298 -5.354,-20.822 -12.929,-26.477 -3.151,-2.353 1.749,-3.316 3.645,-1.902 15.019,11.215 17.597,31.034 12.167,47.773 -3.206,9.88 -10.07,19.053 -5.488,29.696 2.101,4.879 6.069,9.327 8.949,13.787 2.945,4.561 5.823,9.164 8.819,13.69 1.548,2.338 -4.317,1.903 -5.424,0.229" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path82"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 619.34858,740.00484 c 1.793,-9.024 4.636,-18.394 0.651,-27.243 -3.249,-7.215 -11.093,-14.999 -19.132,-16.296 -3.099,-0.5 -4.498,-4.715 -0.559,-4.08 9.492,1.532 17.385,7.932 22.779,15.671 7.282,10.448 4.357,21.921 2.056,33.501 -0.514,2.585 -6.321,1.096 -5.795,-1.553" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path86"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 602.20208,726.15864 c 0.315,-9.326 -8.25,-18.223 -16.232,-21.912 -3.589,-1.659 -0.408,-5.09 2.638,-3.683 9.385,4.337 19.859,14.913 19.485,25.963 -0.108,3.189 -5.985,2.411 -5.891,-0.368" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path90"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 583.37498,729.72844 c -5.05,-8.992 -10.76,-16.269 -21.323,-18.471 -3.657,-0.762 -2.517,-4.777 1.08,-4.027 12.498,2.605 19.786,11.112 25.792,21.806 1.609,2.866 -4.285,2.942 -5.549,0.692" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path94"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 566.77538,732.32164 c -6.334,-5.881 -11.186,-13.786 -20.424,-14.943 -2.545,-0.319 -5.015,-3.098 -0.957,-2.59 5.396,0.676 10.233,2.5 14.579,5.787 4.514,3.413 7.979,8.11 12.113,11.947 1.031,0.959 -0.887,1.287 -1.455,1.266 -1.379,-0.051 -2.835,-0.519 -3.856,-1.467" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path98"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 553.40718,740.56044 c -4.594,-7.337 -12.351,-13.475 -21.376,-10.607 -2.063,0.656 -6.832,-2.355 -3.475,-3.422 12.079,-3.839 23.982,3.62 30.3,13.711 1.549,2.474 -4.327,2.11 -5.449,0.318" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path102"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 682.46768,933.64984 c -3.94,-17.48 3.4,-35.168 -1.42,-52.577 -4.211,-15.21 -15.344,-29.051 -15.344,-45.317 0,-0.806 5.795,-0.013 5.795,1.553 0,15.86 10.744,30.064 15.253,44.831 5.281,17.296 -2.509,35.147 1.419,52.576 0.255,1.13 -5.397,0.293 -5.703,-1.066" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path106"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 651.45698,1106.7465 c 15.201,-11.729 24.591,-26.634 30.122,-44.904 3.446,-11.386 4.709,-22.954 5.539,-34.777 0.433,-6.16 0.912,-12.307 1.764,-18.426 0.758,-5.452 2.856,-10.63596 4.179,-15.95796 0.437,-1.76 6.243,-0.244 5.795,1.552 -1.328,5.346 -3.26,10.51296 -4.179,15.95896 -1.024,6.071 -1.333,12.292 -1.763,18.427 -0.832,11.856 -2.193,23.338 -5.54,34.776 -5.403,18.47 -15.218,33.714 -30.507,45.511 -1.486,1.147 -6.754,-1.123 -5.41,-2.16" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path110"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 642.71378,1103.5975 c -12.842,-1.804 -22.769,8.963 -35.264,10.7 -12.757,1.773 -24.802,-1.339 -36.282,-6.784 -5.458,-2.589 -10.726,-5.554 -16.2,-8.115 -7.82,-3.658 -14.991,-4.655 -23.574,-4.52 -13.041,0.205 -23.106,-3.92 -33.054,-12.245 -19.468,-16.294 -27.4,-41.739 -30.656,-66.126 -2.032,-15.215 -4.322,-30.17896 -7.574,-45.19696 -3.302,-15.243 -6.875,-30.427 -9.333,-45.838 -0.88,-5.529 -1.546,-11.088 -2.051,-16.663 -0.242,-2.676 5.626,-1.675 5.831,0.591 2.762,30.501 11.868,59.892 16.712,90.052 2.072,12.90196 2.99,25.76696 6.349,38.44896 3.416,12.895 8.849,25.692 17.599,35.894 4.242,4.945 9.568,9.294 15.045,12.777 7.027,4.468 14.514,4.642 22.574,4.524 13.229,-0.196 23.837,4.89 35.353,10.833 13.129,6.776 26.547,11.549 41.415,7.664 6.064,-1.585 11.284,-5.155 16.886,-7.802 4.969,-2.347 10.189,-2.651 15.564,-1.895 2.982,0.419 4.638,4.26 0.66,3.701" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path114"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 441.87398,969.27184 c -0.086,-9.163 -1.376,-18.324 -4.25,-27.049 -2.561,-7.778 -7.016,-14.74 -9.049,-22.726 -0.683,-2.685 5.237,-1.942 5.858,0.495 2.121,8.335 7.062,15.574 9.413,23.823 2.429,8.525 3.801,17.082 3.885,25.952 0.028,2.937 -5.834,1.98 -5.857,-0.495" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path118"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 428.22598,983.18154 c -0.126,-13.803 -3.634,-26.896 -13.412,-37.029 -1.278,-1.325 4.272,-0.647 5.262,0.379 10.105,10.471 13.815,23.926 13.946,38.203 0.009,1.021 -5.78,0.181 -5.796,-1.553" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path122"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 418.99218,982.69574 c -5.593,3.597 -8.523,9.997 -13.913,13.835 -5.079,3.61696 -11.005,1.865 -15.979,-0.938 -15.196,-8.561 -16.355,-29.519 -16.166,-44.94 0.214,-17.344 4.91,-34.757 17.014,-47.614 10.092,-10.72 24.413,-16.244 38.26,-20.199 1.826,-0.521 6.82,2.202 3.552,3.136 -12.207,3.486 -24.157,8.258 -33.777,16.76 -10.872,9.607 -16.229,23.352 -18.395,37.402 -1.308,8.481 -0.94,17.11 -0.021,25.607 0.815,7.526 1.807,14.869 5.998,21.339 2.215,3.418 5.456,6.065 9.085,7.851 3.146,1.549 6.216,-1.388 8.228,-3.395 3.923,-3.911 6.754,-8.587 11.5,-11.639 1.581,-1.017 6.946,1.295 4.614,2.795" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path126"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 429.74558,904.14934 c 4.695,-13.758 4.808,-28.257 6.042,-42.591 1.094,-12.705 3.472,-25.64 7.692,-37.688 4.402,-12.568 12.339,-21.713 22.8,-29.759 5.601,-4.309 11.501,-8.197 17.012,-12.629 6.35,-5.104 12.308,-10.685 18.476,-16.003 1.571,-1.355 6.985,0.895 5.379,2.28 -11.16,9.622 -22.251,18.842 -34.109,27.594 -10.959,8.089 -19.002,17.207 -23.763,30.07 -4.216,11.392 -6.264,23.847 -7.522,35.889 -1.56,14.939 -1.302,30.005 -6.211,44.39 -0.705,2.065 -6.463,0.404 -5.796,-1.553" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path130"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 678.61908,1071.6263 c 5.318,-1.33 12.266,-0.993 14.445,4.979 2.601,7.124 -3.383,17.237 -6.59,23.137 -5.981,11.007 -13.785,21.078 -22.383,30.153 -4.116,4.343 -8.572,8.533 -13.977,11.216 -4.935,2.448 -10.481,3.705 -15.685,5.441 -11.429,3.814 -22.389,8.969 -33.104,14.439 -9.623,4.913 -18.995,9.111 -29.806,10.462 -13.083,1.636 -26.569,1.155 -39.711,0.646 -23.016,-0.891 -45.99,-3.396 -67.847,-11.033 -21.218,-7.414 -40.837,-19.392 -56.534,-35.576 -7.666,-7.904 -12.171,-17.279 -16.004,-27.47 -4.698,-12.489 -7.95,-25.548 -10.239,-38.681 -1.072,-6.153 -1.481,-12.421 -2.077,-18.633 -0.588,-6.124 -1.946,-12.184 -1.873,-18.346 0.032,-2.696 0.424,-5.4 0.689,-8.079 0.344,-3.487 -0.079,-6.911 0.048,-10.377 0.226,-6.17996 2.869,-11.88496 3.139,-18.06296 0.087,-1.962 5.897,-0.759 5.796,1.553 -0.32,7.3 -3.379,13.74196 -2.922,21.16596 0.45,7.307 -1.591,14.394 -0.493,21.718 2.315,15.447 3.24,30.783 6.905,46.033 3.424,14.249 7.882,29.624 16.375,41.724 7.569,10.782 19.366,19.621 30.323,26.673 24.251,15.607 52.867,21.345 81.214,23.36 14.169,1.007 28.442,1.306 42.635,0.67 12.061,-0.54 22.225,-3.809 32.942,-9.178 12.873,-6.447 25.756,-12.611 39.474,-17.061 6.881,-2.233 13.345,-4.077 18.999,-8.801 10.907,-9.113 19.933,-21.292 27.141,-33.439 3.336,-5.621 6.309,-11.716 7.724,-18.131 0.456,-2.063 0.585,-4.162 0.037,-6.212 -0.673,-2.514 -3.221,-1.518 -5.12,-1.043 -1.924,0.481 -6.847,-2.415 -3.521,-3.247" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path134"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 404.28808,878.69184 c 5.97,-19.507 8.159,-39.821 6.255,-60.144 -0.895,-9.561 -2.901,-18.994 -5.687,-28.174 -2.968,-9.78 -7.526,-19.015 -10.824,-28.687 -0.661,-1.938 5.139,-1.166 5.79,0.745 3.301,9.68 7.726,18.939 10.824,28.687 3.09,9.723 4.906,19.822 5.856,29.966 1.862,19.893 -0.584,40.095 -6.418,59.16 -0.611,1.995 -6.388,0.382 -5.796,-1.553" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path138"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 585.12688,681.99504 c -1.835,-6.336 -1.178,-12.876 -1.076,-19.381 0.108,-7.028 -0.804,-14.101 -1.096,-21.122 -0.113,-2.706 -0.157,-5.408 0.024,-8.111 0.175,-2.632 0.86,-5.767 -0.335,-8.254 -1.226,-2.551 -4.504,-4.232 -6.732,-5.805 -2.501,-1.766 -4.581,-3.819 -6.66,-6.062 -9.418,-10.163 -15.53,-22.889 -20.969,-35.476 -2.975,-6.887 -5.708,-13.881 -8.949,-20.649 -3.46,-7.224 -7.358,-14.2 -10.265,-21.68 -1.153,-2.97 4.651,-2.629 5.491,-0.469 2.681,6.902 6.151,13.423 9.457,20.037 3.627,7.256 6.57,14.837 9.756,22.291 5.901,13.806 12.748,26.944 23.36,37.747 3.462,3.525 8.432,5.141 11.001,9.597 2.377,4.124 0.516,11.068 0.607,15.564 0.145,7.141 0.885,14.256 1.145,21.392 0.257,7.062 -0.917,14.008 1.085,20.925 0.729,2.518 -5.174,1.769 -5.844,-0.544" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path142"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 390.46768,769.62344 c -7.392,0.154 -12.729,-3.572 -14.93,-10.607 -3.211,-10.265 -0.249,-20.877 3.715,-30.441 5.416,-13.066 11.224,-25.88 17.738,-38.437 6.91,-13.319 13.907,-26.267 19.59,-40.175 2.446,-5.984 5.063,-11.909 8.408,-17.448 3.526,-5.843 7.757,-11.229 11.333,-17.043 3.128,-5.088 5.8,-10.414 9.353,-15.234 3.552,-4.821 8.363,-8.597 12.61,-12.771 4.792,-4.71 9.567,-9.379 15.157,-13.148 5.458,-3.681 11.728,-6.367 17.492,-9.544 11.503,-6.34 22.278,-13.677 31.303,-23.293 0.945,-1.007 6.227,1.115 5.476,1.916 -7.909,8.427 -17.127,15.076 -27.072,20.895 -10.045,5.88 -20.788,10.323 -29.582,18.096 -8.537,7.547 -17.649,15.625 -23.583,25.409 -3.039,5.011 -5.816,10.126 -9.105,14.987 -3.498,5.167 -7.132,10.204 -10.121,15.694 -6.113,11.23 -9.712,23.66 -15.755,34.955 -6.204,11.594 -12.45,23.165 -18.07,35.058 -5.207,11.019 -11.132,22.862 -13.739,34.815 -0.912,4.186 -0.814,8.598 -0.279,12.825 0.365,2.872 2.075,11.368 6.261,11.281 1.124,-0.023 6.582,2.152 3.8,2.21" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path146"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 640.92968,702.55704 c 9.753,-6.598 20.642,-11.134 31.593,-15.33 11.865,-4.546 23.62,-9.171 35.334,-14.101 12.848,-5.406 25.845,-10.548 39.142,-14.755 12.571,-3.978 23.997,-10.899 35.847,-16.539 2.582,-1.229 6.67,2.508 3.289,4.117 -11.344,5.398 -22.246,11.698 -34.105,15.949 -13.137,4.711 -26.231,9.246 -39.131,14.611 -11.278,4.69 -22.491,9.358 -33.932,13.642 -11.611,4.348 -23.29,8.919 -33.609,15.901 -2.285,1.546 -7.258,-1.58 -4.428,-3.495" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path150"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 365.91158,740.76504 c 0.868,-18.275 -25.202,-25.549 -38.362,-31.247 -11.191,-4.846 -21.739,-11.333 -32.296,-17.394 -12.988,-7.457 -26.397,-14.311 -38.794,-22.74 -3.241,-2.204 1.801,-2.788 3.561,-1.591 12.923,8.786 26.928,15.926 40.467,23.7 11.406,6.549 22.778,13.078 34.923,18.162 13.759,5.759 37.17,14.258 36.297,32.663 -0.084,1.756 -5.898,0.602 -5.796,-1.553" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path154"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 530.64838,487.02824 c 4.489,1.93 7.703,5.298 10.885,8.912 4.9,5.566 10.626,10.177 16.453,14.74 12.608,9.872 25.418,19.451 40.074,26.097 6.298,2.856 13.616,5.48 20.594,5.719 4.485,0.153 8.944,-0.382 13.424,0.154 9.138,1.093 6.927,10.161 6.217,16.848 -0.852,8.014 -2.243,16.477 -0.869,24.497 0.122,0.71 0.337,1.387 0.575,2.065 0.526,1.5 -1.891,0.42 -0.359,0.21 1.958,-0.268 3.862,-1.043 5.703,-1.726 4.469,-1.661 8.784,-3.74 13.105,-5.744 3.652,-1.693 7.395,-3.176 11.123,-4.695 2.832,-1.153 7.241,-2.304 9.93,-0.236 2.438,1.874 2.885,6.132 2.879,8.916 -0.01,6.139 -0.751,12.43 -1.994,18.43 -3.535,17.061 -12.175,33.468 -20.532,48.581 -8.729,15.785 -15.179,33.006 -26.452,47.252 -1.152,1.456 -6.728,-0.526 -5.399,-2.205 7.42,-9.378 12.6,-19.954 17.668,-30.712 5.111,-10.847 11.549,-21.01 16.774,-31.803 4.77,-9.858 9.051,-20.357 11.755,-30.979 1.264,-4.965 1.69,-10.041 2.175,-15.123 0.26,-2.728 1.178,-9.532 -1.476,-11.572 1.152,0.384 2.304,0.767 3.456,1.149 -3.868,0.094 -8.16,2.613 -11.699,4.075 -3.158,1.303 -6.223,2.853 -9.335,4.262 -5.205,2.356 -12.629,6.591 -18.597,4.992 -5.68,-1.522 -5.533,-8.02 -5.586,-12.833 -0.072,-6.642 0.907,-13.22 1.506,-19.817 0.169,-1.869 0.495,-3.722 0.656,-5.594 0.125,-1.449 0.019,-2.864 -0.273,-4.283 -0.305,-1.483 -0.741,-1.081 -2.307,-1.142 -3.74,-0.149 -7.505,0.357 -11.238,0.04 -11.42,-0.973 -22.088,-5.582 -32.169,-10.734 -11.722,-5.989 -22.182,-14.237 -32.561,-22.24 -5.045,-3.891 -10.054,-7.879 -14.668,-12.28 -3.803,-3.626 -6.671,-8.918 -11.667,-11.067 -3.731,-1.603 -0.285,-3.235 2.229,-2.154" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path158"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 350.83588,722.89204 c -5.492,-12.675 -6.728,-26.303 -6.663,-39.984 0.069,-14.428 1.077,-28.843 1.228,-43.276 0.171,-16.36 0.964,-32.708 1.846,-49.042 0.423,-7.848 0.878,-15.694 1.312,-23.54 0.265,-4.792 -0.71,-10.378 0.986,-14.958 3.679,-9.929 16.103,3.065 19.632,5.89 4.606,3.688 11.379,5.626 16.887,7.425 6.892,2.25 14.019,3.861 21.174,4.998 6.402,1.018 12.897,1.605 19.324,2.461 2.895,0.385 6.928,0.812 9.594,-0.705 1.503,-0.855 1.846,-4.244 2.295,-5.708 2.035,-6.629 5.86,-12.645 8.393,-19.09 1.191,-3.027 2.157,-6.922 5.51,-8.153 4.818,-1.769 11.796,-0.425 16.755,-0.206 4.352,0.191 8.684,0.069 12.825,-1.396 3.99,-1.411 7.503,-4.375 10.808,-6.934 11.955,-9.26 22.587,-19.449 29.962,-32.836 1.276,-2.316 6.79,-0.131 5.301,2.572 -6.282,11.401 -15.213,21.519 -25.45,29.531 -5.057,3.959 -10.058,8.044 -15.798,10.973 -6.289,3.209 -13.989,2.556 -20.794,2.23 -3.186,-0.152 -6.396,-0.179 -9.584,-0.031 -1.768,0.083 -2.107,1.856 -2.7,3.283 -2.849,6.862 -6.302,13.468 -9.018,20.378 -1.208,3.072 -1.34,6.562 -4.047,8.766 -3.73,3.04 -11.087,1.963 -15.321,1.398 -13.115,-1.746 -26.032,-3.198 -38.767,-7.008 -5.69,-1.704 -11.268,-3.859 -16.6,-6.476 -4.809,-2.359 -8.34,-6.22 -12.518,-9.474 -3.815,-2.97 -2.748,9.384 -2.865,11.532 -0.462,8.501 -0.957,17 -1.42,25.501 -0.891,16.337 -1.629,32.682 -1.846,49.043 -0.184,13.868 -0.938,27.699 -1.207,41.562 -0.267,13.798 0.772,27.78 6.317,40.576 1.334,3.08 -4.51,3.1 -5.551,0.698" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path162"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 373.96578,881.67274 c -12.686,0.555 -22.858,-7.416 -30.871,-16.478 -8.576,-9.699 -15.37,-21.702 -19.715,-33.879 -6.524,-18.284 -9.48,-38.065 -12.363,-57.182 -1.462,-9.69 -2.763,-19.402 -4.165,-29.1 -1.36,-9.407 -1.103,-19.23 -4.662,-28.181 -1.267,-3.186 4.564,-3.314 5.572,-0.778 2.898,7.289 3.468,15.072 4.195,22.809 0.832,8.848 2.358,17.662 3.61,26.459 2.606,18.311 5.503,36.606 10.211,54.512 3.442,13.09 8.794,25.104 16.551,36.227 6.559,9.403 16.997,21.737 29.684,21.182 2.931,-0.129 5.868,4.238 1.953,4.409" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path166"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 377.11858,865.56334 c -8.317,0.262 -13.875,-4.482 -18.668,-10.82 -6.405,-8.471 -13.046,-16.709 -18.098,-26.095 -5.72,-10.626 -8.09,-22.858 -10.492,-34.577 -2.517,-12.284 -4.14,-24.797 -4.225,-37.348 -0.008,-1.185 5.783,-0.289 5.796,1.553 0.136,20.273 3.889,41.375 10.081,60.68 2.991,9.325 8.403,17.707 14.178,25.521 2.375,3.214 4.917,6.3 7.288,9.517 2.325,3.154 5.936,9.123 10.441,8.981 1.368,-0.043 6.677,2.494 3.699,2.588" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path170"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 382.30758,857.54674 c -23.68,-12.641 -24.306,-43.878 -32.324,-66.326 -0.47,-1.316 5.172,-0.628 5.735,0.951 3.905,10.932 5.949,22.441 9.377,33.523 3.649,11.797 9.171,24.75 20.613,30.859 3.41,1.82 -1.923,1.782 -3.401,0.993" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path174"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 397.34468,853.14344 c -6.584,-2.528 -8.869,-9.616 -10.323,-15.931 -1.617,-7.027 -2.085,-14.398 -2.112,-21.595 -0.005,-1.55 5.789,-0.533 5.796,1.553 0.021,5.867 0.497,11.733 1.441,17.524 0.765,4.691 2.208,14.389 7.402,16.384 3.808,1.461 0.286,3.021 -2.204,2.065" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path178"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 580.72558,951.45304 c -0.456,-3.119 -5.252,-5.001 -10.711,-4.202 -5.461,0.8 -9.518,3.976 -9.061,7.096 0.457,3.119 5.252,5.001 10.711,4.202 5.461,-0.8 9.519,-3.976 9.061,-7.096" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path182"
|
||||
style="fill:none;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 580.72558,951.45304 c -0.456,-3.119 -5.252,-5.001 -10.711,-4.202 -5.461,0.8 -9.518,3.976 -9.061,7.096 0.457,3.119 5.252,5.001 10.711,4.202 5.461,-0.8 9.519,-3.976 9.061,-7.096 z" /></g></svg>
|
After Width: | Height: | Size: 27 KiB |
BIN
content/images/screenshot-gobgen.png
Normal file
After Width: | Height: | Size: 33 KiB |
78
content/minari/css/minari.css
Normal file
@@ -0,0 +1,78 @@
|
||||
.year {
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
font-size: 200%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.holiday {
|
||||
text-align: center;
|
||||
font-size: 150%;
|
||||
font-weight: bold;
|
||||
margin: .5em 0;
|
||||
}
|
||||
|
||||
table.month {
|
||||
float: left;
|
||||
border: 2px solid black;
|
||||
margin-right: 1em;
|
||||
margin-bottom: 1em;
|
||||
border-collapse: collapse;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.clear {
|
||||
float: none;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.month-row {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
td {
|
||||
text-align: center;
|
||||
padding: .1em;
|
||||
white-space: nowrap;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.monthname td {
|
||||
font-weight: bold;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.daynames {
|
||||
border-bottom: 2px solid black;
|
||||
}
|
||||
|
||||
.daynames td {
|
||||
font-weight: bold;
|
||||
border: 1px solid black;
|
||||
width: 16.66%;
|
||||
}
|
||||
|
||||
.prevYear {
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nextYear {
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.today {
|
||||
background-color: #a5ffff;
|
||||
}
|
||||
|
||||
.date-popover {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.holiday .small {
|
||||
font-size: 75%;
|
||||
font-weight: normal;
|
||||
}
|
BIN
content/minari/fonts/glyphicons-halflings-regular.eot
Normal file
288
content/minari/fonts/glyphicons-halflings-regular.svg
Normal file
@@ -0,0 +1,288 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata></metadata>
|
||||
<defs>
|
||||
<font id="glyphicons_halflingsregular" horiz-adv-x="1200" >
|
||||
<font-face units-per-em="1200" ascent="960" descent="-240" />
|
||||
<missing-glyph horiz-adv-x="500" />
|
||||
<glyph horiz-adv-x="0" />
|
||||
<glyph horiz-adv-x="400" />
|
||||
<glyph unicode=" " />
|
||||
<glyph unicode="*" d="M600 1100q15 0 34 -1.5t30 -3.5l11 -1q10 -2 17.5 -10.5t7.5 -18.5v-224l158 158q7 7 18 8t19 -6l106 -106q7 -8 6 -19t-8 -18l-158 -158h224q10 0 18.5 -7.5t10.5 -17.5q6 -41 6 -75q0 -15 -1.5 -34t-3.5 -30l-1 -11q-2 -10 -10.5 -17.5t-18.5 -7.5h-224l158 -158 q7 -7 8 -18t-6 -19l-106 -106q-8 -7 -19 -6t-18 8l-158 158v-224q0 -10 -7.5 -18.5t-17.5 -10.5q-41 -6 -75 -6q-15 0 -34 1.5t-30 3.5l-11 1q-10 2 -17.5 10.5t-7.5 18.5v224l-158 -158q-7 -7 -18 -8t-19 6l-106 106q-7 8 -6 19t8 18l158 158h-224q-10 0 -18.5 7.5 t-10.5 17.5q-6 41 -6 75q0 15 1.5 34t3.5 30l1 11q2 10 10.5 17.5t18.5 7.5h224l-158 158q-7 7 -8 18t6 19l106 106q8 7 19 6t18 -8l158 -158v224q0 10 7.5 18.5t17.5 10.5q41 6 75 6z" />
|
||||
<glyph unicode="+" d="M450 1100h200q21 0 35.5 -14.5t14.5 -35.5v-350h350q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-350v-350q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v350h-350q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5 h350v350q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode=" " />
|
||||
<glyph unicode="¥" d="M825 1100h250q10 0 12.5 -5t-5.5 -13l-364 -364q-6 -6 -11 -18h268q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-125v-100h275q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-125v-174q0 -11 -7.5 -18.5t-18.5 -7.5h-148q-11 0 -18.5 7.5t-7.5 18.5v174 h-275q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h125v100h-275q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h118q-5 12 -11 18l-364 364q-8 8 -5.5 13t12.5 5h250q25 0 43 -18l164 -164q8 -8 18 -8t18 8l164 164q18 18 43 18z" />
|
||||
<glyph unicode=" " horiz-adv-x="650" />
|
||||
<glyph unicode=" " horiz-adv-x="1300" />
|
||||
<glyph unicode=" " horiz-adv-x="650" />
|
||||
<glyph unicode=" " horiz-adv-x="1300" />
|
||||
<glyph unicode=" " horiz-adv-x="433" />
|
||||
<glyph unicode=" " horiz-adv-x="325" />
|
||||
<glyph unicode=" " horiz-adv-x="216" />
|
||||
<glyph unicode=" " horiz-adv-x="216" />
|
||||
<glyph unicode=" " horiz-adv-x="162" />
|
||||
<glyph unicode=" " horiz-adv-x="260" />
|
||||
<glyph unicode=" " horiz-adv-x="72" />
|
||||
<glyph unicode=" " horiz-adv-x="260" />
|
||||
<glyph unicode=" " horiz-adv-x="325" />
|
||||
<glyph unicode="€" d="M744 1198q242 0 354 -189q60 -104 66 -209h-181q0 45 -17.5 82.5t-43.5 61.5t-58 40.5t-60.5 24t-51.5 7.5q-19 0 -40.5 -5.5t-49.5 -20.5t-53 -38t-49 -62.5t-39 -89.5h379l-100 -100h-300q-6 -50 -6 -100h406l-100 -100h-300q9 -74 33 -132t52.5 -91t61.5 -54.5t59 -29 t47 -7.5q22 0 50.5 7.5t60.5 24.5t58 41t43.5 61t17.5 80h174q-30 -171 -128 -278q-107 -117 -274 -117q-206 0 -324 158q-36 48 -69 133t-45 204h-217l100 100h112q1 47 6 100h-218l100 100h134q20 87 51 153.5t62 103.5q117 141 297 141z" />
|
||||
<glyph unicode="₽" d="M428 1200h350q67 0 120 -13t86 -31t57 -49.5t35 -56.5t17 -64.5t6.5 -60.5t0.5 -57v-16.5v-16.5q0 -36 -0.5 -57t-6.5 -61t-17 -65t-35 -57t-57 -50.5t-86 -31.5t-120 -13h-178l-2 -100h288q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-138v-175q0 -11 -5.5 -18 t-15.5 -7h-149q-10 0 -17.5 7.5t-7.5 17.5v175h-267q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h117v100h-267q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h117v475q0 10 7.5 17.5t17.5 7.5zM600 1000v-300h203q64 0 86.5 33t22.5 119q0 84 -22.5 116t-86.5 32h-203z" />
|
||||
<glyph unicode="−" d="M250 700h800q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="⌛" d="M1000 1200v-150q0 -21 -14.5 -35.5t-35.5 -14.5h-50v-100q0 -91 -49.5 -165.5t-130.5 -109.5q81 -35 130.5 -109.5t49.5 -165.5v-150h50q21 0 35.5 -14.5t14.5 -35.5v-150h-800v150q0 21 14.5 35.5t35.5 14.5h50v150q0 91 49.5 165.5t130.5 109.5q-81 35 -130.5 109.5 t-49.5 165.5v100h-50q-21 0 -35.5 14.5t-14.5 35.5v150h800zM400 1000v-100q0 -60 32.5 -109.5t87.5 -73.5q28 -12 44 -37t16 -55t-16 -55t-44 -37q-55 -24 -87.5 -73.5t-32.5 -109.5v-150h400v150q0 60 -32.5 109.5t-87.5 73.5q-28 12 -44 37t-16 55t16 55t44 37 q55 24 87.5 73.5t32.5 109.5v100h-400z" />
|
||||
<glyph unicode="◼" horiz-adv-x="500" d="M0 0z" />
|
||||
<glyph unicode="☁" d="M503 1089q110 0 200.5 -59.5t134.5 -156.5q44 14 90 14q120 0 205 -86.5t85 -206.5q0 -121 -85 -207.5t-205 -86.5h-750q-79 0 -135.5 57t-56.5 137q0 69 42.5 122.5t108.5 67.5q-2 12 -2 37q0 153 108 260.5t260 107.5z" />
|
||||
<glyph unicode="⛺" d="M774 1193.5q16 -9.5 20.5 -27t-5.5 -33.5l-136 -187l467 -746h30q20 0 35 -18.5t15 -39.5v-42h-1200v42q0 21 15 39.5t35 18.5h30l468 746l-135 183q-10 16 -5.5 34t20.5 28t34 5.5t28 -20.5l111 -148l112 150q9 16 27 20.5t34 -5zM600 200h377l-182 112l-195 534v-646z " />
|
||||
<glyph unicode="✉" d="M25 1100h1150q10 0 12.5 -5t-5.5 -13l-564 -567q-8 -8 -18 -8t-18 8l-564 567q-8 8 -5.5 13t12.5 5zM18 882l264 -264q8 -8 8 -18t-8 -18l-264 -264q-8 -8 -13 -5.5t-5 12.5v550q0 10 5 12.5t13 -5.5zM918 618l264 264q8 8 13 5.5t5 -12.5v-550q0 -10 -5 -12.5t-13 5.5 l-264 264q-8 8 -8 18t8 18zM818 482l364 -364q8 -8 5.5 -13t-12.5 -5h-1150q-10 0 -12.5 5t5.5 13l364 364q8 8 18 8t18 -8l164 -164q8 -8 18 -8t18 8l164 164q8 8 18 8t18 -8z" />
|
||||
<glyph unicode="✏" d="M1011 1210q19 0 33 -13l153 -153q13 -14 13 -33t-13 -33l-99 -92l-214 214l95 96q13 14 32 14zM1013 800l-615 -614l-214 214l614 614zM317 96l-333 -112l110 335z" />
|
||||
<glyph unicode="" d="M700 650v-550h250q21 0 35.5 -14.5t14.5 -35.5v-50h-800v50q0 21 14.5 35.5t35.5 14.5h250v550l-500 550h1200z" />
|
||||
<glyph unicode="" d="M368 1017l645 163q39 15 63 0t24 -49v-831q0 -55 -41.5 -95.5t-111.5 -63.5q-79 -25 -147 -4.5t-86 75t25.5 111.5t122.5 82q72 24 138 8v521l-600 -155v-606q0 -42 -44 -90t-109 -69q-79 -26 -147 -5.5t-86 75.5t25.5 111.5t122.5 82.5q72 24 138 7v639q0 38 14.5 59 t53.5 34z" />
|
||||
<glyph unicode="" d="M500 1191q100 0 191 -39t156.5 -104.5t104.5 -156.5t39 -191l-1 -2l1 -5q0 -141 -78 -262l275 -274q23 -26 22.5 -44.5t-22.5 -42.5l-59 -58q-26 -20 -46.5 -20t-39.5 20l-275 274q-119 -77 -261 -77l-5 1l-2 -1q-100 0 -191 39t-156.5 104.5t-104.5 156.5t-39 191 t39 191t104.5 156.5t156.5 104.5t191 39zM500 1022q-88 0 -162 -43t-117 -117t-43 -162t43 -162t117 -117t162 -43t162 43t117 117t43 162t-43 162t-117 117t-162 43z" />
|
||||
<glyph unicode="" d="M649 949q48 68 109.5 104t121.5 38.5t118.5 -20t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-150 152.5t-126.5 127.5t-93.5 124.5t-33.5 117.5q0 64 28 123t73 100.5t104 64t119 20 t120.5 -38.5t104.5 -104z" />
|
||||
<glyph unicode="" d="M407 800l131 353q7 19 17.5 19t17.5 -19l129 -353h421q21 0 24 -8.5t-14 -20.5l-342 -249l130 -401q7 -20 -0.5 -25.5t-24.5 6.5l-343 246l-342 -247q-17 -12 -24.5 -6.5t-0.5 25.5l130 400l-347 251q-17 12 -14 20.5t23 8.5h429z" />
|
||||
<glyph unicode="" d="M407 800l131 353q7 19 17.5 19t17.5 -19l129 -353h421q21 0 24 -8.5t-14 -20.5l-342 -249l130 -401q7 -20 -0.5 -25.5t-24.5 6.5l-343 246l-342 -247q-17 -12 -24.5 -6.5t-0.5 25.5l130 400l-347 251q-17 12 -14 20.5t23 8.5h429zM477 700h-240l197 -142l-74 -226 l193 139l195 -140l-74 229l192 140h-234l-78 211z" />
|
||||
<glyph unicode="" d="M600 1200q124 0 212 -88t88 -212v-250q0 -46 -31 -98t-69 -52v-75q0 -10 6 -21.5t15 -17.5l358 -230q9 -5 15 -16.5t6 -21.5v-93q0 -10 -7.5 -17.5t-17.5 -7.5h-1150q-10 0 -17.5 7.5t-7.5 17.5v93q0 10 6 21.5t15 16.5l358 230q9 6 15 17.5t6 21.5v75q-38 0 -69 52 t-31 98v250q0 124 88 212t212 88z" />
|
||||
<glyph unicode="" d="M25 1100h1150q10 0 17.5 -7.5t7.5 -17.5v-1050q0 -10 -7.5 -17.5t-17.5 -7.5h-1150q-10 0 -17.5 7.5t-7.5 17.5v1050q0 10 7.5 17.5t17.5 7.5zM100 1000v-100h100v100h-100zM875 1000h-550q-10 0 -17.5 -7.5t-7.5 -17.5v-350q0 -10 7.5 -17.5t17.5 -7.5h550 q10 0 17.5 7.5t7.5 17.5v350q0 10 -7.5 17.5t-17.5 7.5zM1000 1000v-100h100v100h-100zM100 800v-100h100v100h-100zM1000 800v-100h100v100h-100zM100 600v-100h100v100h-100zM1000 600v-100h100v100h-100zM875 500h-550q-10 0 -17.5 -7.5t-7.5 -17.5v-350q0 -10 7.5 -17.5 t17.5 -7.5h550q10 0 17.5 7.5t7.5 17.5v350q0 10 -7.5 17.5t-17.5 7.5zM100 400v-100h100v100h-100zM1000 400v-100h100v100h-100zM100 200v-100h100v100h-100zM1000 200v-100h100v100h-100z" />
|
||||
<glyph unicode="" d="M50 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM650 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5zM50 500h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM650 500h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M50 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5zM850 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM850 700h200q21 0 35.5 -14.5t14.5 -35.5v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 300h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM850 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5 t35.5 14.5z" />
|
||||
<glyph unicode="" d="M50 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 1100h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5zM50 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 700h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 300h700q21 0 35.5 -14.5t14.5 -35.5v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M465 477l571 571q8 8 18 8t17 -8l177 -177q8 -7 8 -17t-8 -18l-783 -784q-7 -8 -17.5 -8t-17.5 8l-384 384q-8 8 -8 18t8 17l177 177q7 8 17 8t18 -8l171 -171q7 -7 18 -7t18 7z" />
|
||||
<glyph unicode="" d="M904 1083l178 -179q8 -8 8 -18.5t-8 -17.5l-267 -268l267 -268q8 -7 8 -17.5t-8 -18.5l-178 -178q-8 -8 -18.5 -8t-17.5 8l-268 267l-268 -267q-7 -8 -17.5 -8t-18.5 8l-178 178q-8 8 -8 18.5t8 17.5l267 268l-267 268q-8 7 -8 17.5t8 18.5l178 178q8 8 18.5 8t17.5 -8 l268 -267l268 268q7 7 17.5 7t18.5 -7z" />
|
||||
<glyph unicode="" d="M507 1177q98 0 187.5 -38.5t154.5 -103.5t103.5 -154.5t38.5 -187.5q0 -141 -78 -262l300 -299q8 -8 8 -18.5t-8 -18.5l-109 -108q-7 -8 -17.5 -8t-18.5 8l-300 299q-119 -77 -261 -77q-98 0 -188 38.5t-154.5 103t-103 154.5t-38.5 188t38.5 187.5t103 154.5 t154.5 103.5t188 38.5zM506.5 1023q-89.5 0 -165.5 -44t-120 -120.5t-44 -166t44 -165.5t120 -120t165.5 -44t166 44t120.5 120t44 165.5t-44 166t-120.5 120.5t-166 44zM425 900h150q10 0 17.5 -7.5t7.5 -17.5v-75h75q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5 t-17.5 -7.5h-75v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-75q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h75v75q0 10 7.5 17.5t17.5 7.5z" />
|
||||
<glyph unicode="" d="M507 1177q98 0 187.5 -38.5t154.5 -103.5t103.5 -154.5t38.5 -187.5q0 -141 -78 -262l300 -299q8 -8 8 -18.5t-8 -18.5l-109 -108q-7 -8 -17.5 -8t-18.5 8l-300 299q-119 -77 -261 -77q-98 0 -188 38.5t-154.5 103t-103 154.5t-38.5 188t38.5 187.5t103 154.5 t154.5 103.5t188 38.5zM506.5 1023q-89.5 0 -165.5 -44t-120 -120.5t-44 -166t44 -165.5t120 -120t165.5 -44t166 44t120.5 120t44 165.5t-44 166t-120.5 120.5t-166 44zM325 800h350q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-350q-10 0 -17.5 7.5 t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
|
||||
<glyph unicode="" d="M550 1200h100q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM800 975v166q167 -62 272 -209.5t105 -331.5q0 -117 -45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5 t-184.5 123t-123 184.5t-45.5 224q0 184 105 331.5t272 209.5v-166q-103 -55 -165 -155t-62 -220q0 -116 57 -214.5t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5q0 120 -62 220t-165 155z" />
|
||||
<glyph unicode="" d="M1025 1200h150q10 0 17.5 -7.5t7.5 -17.5v-1150q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v1150q0 10 7.5 17.5t17.5 7.5zM725 800h150q10 0 17.5 -7.5t7.5 -17.5v-750q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v750 q0 10 7.5 17.5t17.5 7.5zM425 500h150q10 0 17.5 -7.5t7.5 -17.5v-450q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v450q0 10 7.5 17.5t17.5 7.5zM125 300h150q10 0 17.5 -7.5t7.5 -17.5v-250q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5 v250q0 10 7.5 17.5t17.5 7.5z" />
|
||||
<glyph unicode="" d="M600 1174q33 0 74 -5l38 -152l5 -1q49 -14 94 -39l5 -2l134 80q61 -48 104 -105l-80 -134l3 -5q25 -44 39 -93l1 -6l152 -38q5 -43 5 -73q0 -34 -5 -74l-152 -38l-1 -6q-15 -49 -39 -93l-3 -5l80 -134q-48 -61 -104 -105l-134 81l-5 -3q-44 -25 -94 -39l-5 -2l-38 -151 q-43 -5 -74 -5q-33 0 -74 5l-38 151l-5 2q-49 14 -94 39l-5 3l-134 -81q-60 48 -104 105l80 134l-3 5q-25 45 -38 93l-2 6l-151 38q-6 42 -6 74q0 33 6 73l151 38l2 6q13 48 38 93l3 5l-80 134q47 61 105 105l133 -80l5 2q45 25 94 39l5 1l38 152q43 5 74 5zM600 815 q-89 0 -152 -63t-63 -151.5t63 -151.5t152 -63t152 63t63 151.5t-63 151.5t-152 63z" />
|
||||
<glyph unicode="" d="M500 1300h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-75h-1100v75q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5zM500 1200v-100h300v100h-300zM1100 900v-800q0 -41 -29.5 -70.5t-70.5 -29.5h-700q-41 0 -70.5 29.5t-29.5 70.5 v800h900zM300 800v-700h100v700h-100zM500 800v-700h100v700h-100zM700 800v-700h100v700h-100zM900 800v-700h100v700h-100z" />
|
||||
<glyph unicode="" d="M18 618l620 608q8 7 18.5 7t17.5 -7l608 -608q8 -8 5.5 -13t-12.5 -5h-175v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v375h-300v-375q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v575h-175q-10 0 -12.5 5t5.5 13z" />
|
||||
<glyph unicode="" d="M600 1200v-400q0 -41 29.5 -70.5t70.5 -29.5h300v-650q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v1100q0 21 14.5 35.5t35.5 14.5h450zM1000 800h-250q-21 0 -35.5 14.5t-14.5 35.5v250z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM525 900h50q10 0 17.5 -7.5t7.5 -17.5v-275h175q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5z" />
|
||||
<glyph unicode="" d="M1300 0h-538l-41 400h-242l-41 -400h-538l431 1200h209l-21 -300h162l-20 300h208zM515 800l-27 -300h224l-27 300h-170z" />
|
||||
<glyph unicode="" d="M550 1200h200q21 0 35.5 -14.5t14.5 -35.5v-450h191q20 0 25.5 -11.5t-7.5 -27.5l-327 -400q-13 -16 -32 -16t-32 16l-327 400q-13 16 -7.5 27.5t25.5 11.5h191v450q0 21 14.5 35.5t35.5 14.5zM1125 400h50q10 0 17.5 -7.5t7.5 -17.5v-350q0 -10 -7.5 -17.5t-17.5 -7.5 h-1050q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h50q10 0 17.5 -7.5t7.5 -17.5v-175h900v175q0 10 7.5 17.5t17.5 7.5z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM525 900h150q10 0 17.5 -7.5t7.5 -17.5v-275h137q21 0 26 -11.5t-8 -27.5l-223 -275q-13 -16 -32 -16t-32 16l-223 275q-13 16 -8 27.5t26 11.5h137v275q0 10 7.5 17.5t17.5 7.5z " />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM632 914l223 -275q13 -16 8 -27.5t-26 -11.5h-137v-275q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v275h-137q-21 0 -26 11.5t8 27.5l223 275q13 16 32 16 t32 -16z" />
|
||||
<glyph unicode="" d="M225 1200h750q10 0 19.5 -7t12.5 -17l186 -652q7 -24 7 -49v-425q0 -12 -4 -27t-9 -17q-12 -6 -37 -6h-1100q-12 0 -27 4t-17 8q-6 13 -6 38l1 425q0 25 7 49l185 652q3 10 12.5 17t19.5 7zM878 1000h-556q-10 0 -19 -7t-11 -18l-87 -450q-2 -11 4 -18t16 -7h150 q10 0 19.5 -7t11.5 -17l38 -152q2 -10 11.5 -17t19.5 -7h250q10 0 19.5 7t11.5 17l38 152q2 10 11.5 17t19.5 7h150q10 0 16 7t4 18l-87 450q-2 11 -11 18t-19 7z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM540 820l253 -190q17 -12 17 -30t-17 -30l-253 -190q-16 -12 -28 -6.5t-12 26.5v400q0 21 12 26.5t28 -6.5z" />
|
||||
<glyph unicode="" d="M947 1060l135 135q7 7 12.5 5t5.5 -13v-362q0 -10 -7.5 -17.5t-17.5 -7.5h-362q-11 0 -13 5.5t5 12.5l133 133q-109 76 -238 76q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5h150q0 -117 -45.5 -224 t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5q192 0 347 -117z" />
|
||||
<glyph unicode="" d="M947 1060l135 135q7 7 12.5 5t5.5 -13v-361q0 -11 -7.5 -18.5t-18.5 -7.5h-361q-11 0 -13 5.5t5 12.5l134 134q-110 75 -239 75q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5h-150q0 117 45.5 224t123 184.5t184.5 123t224 45.5q192 0 347 -117zM1027 600h150 q0 -117 -45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5q-192 0 -348 118l-134 -134q-7 -8 -12.5 -5.5t-5.5 12.5v360q0 11 7.5 18.5t18.5 7.5h360q10 0 12.5 -5.5t-5.5 -12.5l-133 -133q110 -76 240 -76q116 0 214.5 57t155.5 155.5t57 214.5z" />
|
||||
<glyph unicode="" d="M125 1200h1050q10 0 17.5 -7.5t7.5 -17.5v-1150q0 -10 -7.5 -17.5t-17.5 -7.5h-1050q-10 0 -17.5 7.5t-7.5 17.5v1150q0 10 7.5 17.5t17.5 7.5zM1075 1000h-850q-10 0 -17.5 -7.5t-7.5 -17.5v-850q0 -10 7.5 -17.5t17.5 -7.5h850q10 0 17.5 7.5t7.5 17.5v850 q0 10 -7.5 17.5t-17.5 7.5zM325 900h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 900h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 700h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 700h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 500h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 500h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 300h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 300h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5z" />
|
||||
<glyph unicode="" d="M900 800v200q0 83 -58.5 141.5t-141.5 58.5h-300q-82 0 -141 -59t-59 -141v-200h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h900q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-100zM400 800v150q0 21 15 35.5t35 14.5h200 q20 0 35 -14.5t15 -35.5v-150h-300z" />
|
||||
<glyph unicode="" d="M125 1100h50q10 0 17.5 -7.5t7.5 -17.5v-1075h-100v1075q0 10 7.5 17.5t17.5 7.5zM1075 1052q4 0 9 -2q16 -6 16 -23v-421q0 -6 -3 -12q-33 -59 -66.5 -99t-65.5 -58t-56.5 -24.5t-52.5 -6.5q-26 0 -57.5 6.5t-52.5 13.5t-60 21q-41 15 -63 22.5t-57.5 15t-65.5 7.5 q-85 0 -160 -57q-7 -5 -15 -5q-6 0 -11 3q-14 7 -14 22v438q22 55 82 98.5t119 46.5q23 2 43 0.5t43 -7t32.5 -8.5t38 -13t32.5 -11q41 -14 63.5 -21t57 -14t63.5 -7q103 0 183 87q7 8 18 8z" />
|
||||
<glyph unicode="" d="M600 1175q116 0 227 -49.5t192.5 -131t131 -192.5t49.5 -227v-300q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v300q0 127 -70.5 231.5t-184.5 161.5t-245 57t-245 -57t-184.5 -161.5t-70.5 -231.5v-300q0 -10 -7.5 -17.5t-17.5 -7.5h-50 q-10 0 -17.5 7.5t-7.5 17.5v300q0 116 49.5 227t131 192.5t192.5 131t227 49.5zM220 500h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460q0 8 6 14t14 6zM820 500h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460 q0 8 6 14t14 6z" />
|
||||
<glyph unicode="" d="M321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM900 668l120 120q7 7 17 7t17 -7l34 -34q7 -7 7 -17t-7 -17l-120 -120l120 -120q7 -7 7 -17 t-7 -17l-34 -34q-7 -7 -17 -7t-17 7l-120 119l-120 -119q-7 -7 -17 -7t-17 7l-34 34q-7 7 -7 17t7 17l119 120l-119 120q-7 7 -7 17t7 17l34 34q7 8 17 8t17 -8z" />
|
||||
<glyph unicode="" d="M321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM766 900h4q10 -1 16 -10q96 -129 96 -290q0 -154 -90 -281q-6 -9 -17 -10l-3 -1q-9 0 -16 6 l-29 23q-7 7 -8.5 16.5t4.5 17.5q72 103 72 229q0 132 -78 238q-6 8 -4.5 18t9.5 17l29 22q7 5 15 5z" />
|
||||
<glyph unicode="" d="M967 1004h3q11 -1 17 -10q135 -179 135 -396q0 -105 -34 -206.5t-98 -185.5q-7 -9 -17 -10h-3q-9 0 -16 6l-42 34q-8 6 -9 16t5 18q111 150 111 328q0 90 -29.5 176t-84.5 157q-6 9 -5 19t10 16l42 33q7 5 15 5zM321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5 t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM766 900h4q10 -1 16 -10q96 -129 96 -290q0 -154 -90 -281q-6 -9 -17 -10l-3 -1q-9 0 -16 6l-29 23q-7 7 -8.5 16.5t4.5 17.5q72 103 72 229q0 132 -78 238 q-6 8 -4.5 18.5t9.5 16.5l29 22q7 5 15 5z" />
|
||||
<glyph unicode="" d="M500 900h100v-100h-100v-100h-400v-100h-100v600h500v-300zM1200 700h-200v-100h200v-200h-300v300h-200v300h-100v200h600v-500zM100 1100v-300h300v300h-300zM800 1100v-300h300v300h-300zM300 900h-100v100h100v-100zM1000 900h-100v100h100v-100zM300 500h200v-500 h-500v500h200v100h100v-100zM800 300h200v-100h-100v-100h-200v100h-100v100h100v200h-200v100h300v-300zM100 400v-300h300v300h-300zM300 200h-100v100h100v-100zM1200 200h-100v100h100v-100zM700 0h-100v100h100v-100zM1200 0h-300v100h300v-100z" />
|
||||
<glyph unicode="" d="M100 200h-100v1000h100v-1000zM300 200h-100v1000h100v-1000zM700 200h-200v1000h200v-1000zM900 200h-100v1000h100v-1000zM1200 200h-200v1000h200v-1000zM400 0h-300v100h300v-100zM600 0h-100v91h100v-91zM800 0h-100v91h100v-91zM1100 0h-200v91h200v-91z" />
|
||||
<glyph unicode="" d="M500 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-682 682l1 475q0 10 7.5 17.5t17.5 7.5h474zM319.5 1024.5q-29.5 29.5 -71 29.5t-71 -29.5t-29.5 -71.5t29.5 -71.5t71 -29.5t71 29.5t29.5 71.5t-29.5 71.5z" />
|
||||
<glyph unicode="" d="M500 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-682 682l1 475q0 10 7.5 17.5t17.5 7.5h474zM800 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-56 56l424 426l-700 700h150zM319.5 1024.5q-29.5 29.5 -71 29.5t-71 -29.5 t-29.5 -71.5t29.5 -71.5t71 -29.5t71 29.5t29.5 71.5t-29.5 71.5z" />
|
||||
<glyph unicode="" d="M300 1200h825q75 0 75 -75v-900q0 -25 -18 -43l-64 -64q-8 -8 -13 -5.5t-5 12.5v950q0 10 -7.5 17.5t-17.5 7.5h-700q-25 0 -43 -18l-64 -64q-8 -8 -5.5 -13t12.5 -5h700q10 0 17.5 -7.5t7.5 -17.5v-950q0 -10 -7.5 -17.5t-17.5 -7.5h-850q-10 0 -17.5 7.5t-7.5 17.5v975 q0 25 18 43l139 139q18 18 43 18z" />
|
||||
<glyph unicode="" d="M250 1200h800q21 0 35.5 -14.5t14.5 -35.5v-1150l-450 444l-450 -445v1151q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M822 1200h-444q-11 0 -19 -7.5t-9 -17.5l-78 -301q-7 -24 7 -45l57 -108q6 -9 17.5 -15t21.5 -6h450q10 0 21.5 6t17.5 15l62 108q14 21 7 45l-83 301q-1 10 -9 17.5t-19 7.5zM1175 800h-150q-10 0 -21 -6.5t-15 -15.5l-78 -156q-4 -9 -15 -15.5t-21 -6.5h-550 q-10 0 -21 6.5t-15 15.5l-78 156q-4 9 -15 15.5t-21 6.5h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-650q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h750q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5 t7.5 17.5v650q0 10 -7.5 17.5t-17.5 7.5zM850 200h-500q-10 0 -19.5 -7t-11.5 -17l-38 -152q-2 -10 3.5 -17t15.5 -7h600q10 0 15.5 7t3.5 17l-38 152q-2 10 -11.5 17t-19.5 7z" />
|
||||
<glyph unicode="" d="M500 1100h200q56 0 102.5 -20.5t72.5 -50t44 -59t25 -50.5l6 -20h150q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5h150q2 8 6.5 21.5t24 48t45 61t72 48t102.5 21.5zM900 800v-100 h100v100h-100zM600 730q-95 0 -162.5 -67.5t-67.5 -162.5t67.5 -162.5t162.5 -67.5t162.5 67.5t67.5 162.5t-67.5 162.5t-162.5 67.5zM600 603q43 0 73 -30t30 -73t-30 -73t-73 -30t-73 30t-30 73t30 73t73 30z" />
|
||||
<glyph unicode="" d="M681 1199l385 -998q20 -50 60 -92q18 -19 36.5 -29.5t27.5 -11.5l10 -2v-66h-417v66q53 0 75 43.5t5 88.5l-82 222h-391q-58 -145 -92 -234q-11 -34 -6.5 -57t25.5 -37t46 -20t55 -6v-66h-365v66q56 24 84 52q12 12 25 30.5t20 31.5l7 13l399 1006h93zM416 521h340 l-162 457z" />
|
||||
<glyph unicode="" d="M753 641q5 -1 14.5 -4.5t36 -15.5t50.5 -26.5t53.5 -40t50.5 -54.5t35.5 -70t14.5 -87q0 -67 -27.5 -125.5t-71.5 -97.5t-98.5 -66.5t-108.5 -40.5t-102 -13h-500v89q41 7 70.5 32.5t29.5 65.5v827q0 24 -0.5 34t-3.5 24t-8.5 19.5t-17 13.5t-28 12.5t-42.5 11.5v71 l471 -1q57 0 115.5 -20.5t108 -57t80.5 -94t31 -124.5q0 -51 -15.5 -96.5t-38 -74.5t-45 -50.5t-38.5 -30.5zM400 700h139q78 0 130.5 48.5t52.5 122.5q0 41 -8.5 70.5t-29.5 55.5t-62.5 39.5t-103.5 13.5h-118v-350zM400 200h216q80 0 121 50.5t41 130.5q0 90 -62.5 154.5 t-156.5 64.5h-159v-400z" />
|
||||
<glyph unicode="" d="M877 1200l2 -57q-83 -19 -116 -45.5t-40 -66.5l-132 -839q-9 -49 13 -69t96 -26v-97h-500v97q186 16 200 98l173 832q3 17 3 30t-1.5 22.5t-9 17.5t-13.5 12.5t-21.5 10t-26 8.5t-33.5 10q-13 3 -19 5v57h425z" />
|
||||
<glyph unicode="" d="M1300 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-850q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v850h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM175 1000h-75v-800h75l-125 -167l-125 167h75v800h-75l125 167z" />
|
||||
<glyph unicode="" d="M1100 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-650q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v650h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM1167 50l-167 -125v75h-800v-75l-167 125l167 125v-75h800v75z" />
|
||||
<glyph unicode="" d="M50 1100h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 500h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M250 1100h700q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM250 500h700q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000 q-21 0 -35.5 14.5t-14.5 35.5zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5zM0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100 q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5z" />
|
||||
<glyph unicode="" d="M50 1100h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 500h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 1100h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 800h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 500h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 500h800q21 0 35.5 -14.5t14.5 -35.5v-100 q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 200h800 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M400 0h-100v1100h100v-1100zM550 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM550 800h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM267 550l-167 -125v75h-200v100h200v75zM550 500h300q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM550 200h600 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM900 0h-100v1100h100v-1100zM50 800h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM1100 600h200v-100h-200v-75l-167 125l167 125v-75zM50 500h300q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h600 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M75 1000h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53v650q0 31 22 53t53 22zM1200 300l-300 300l300 300v-600z" />
|
||||
<glyph unicode="" d="M44 1100h1112q18 0 31 -13t13 -31v-1012q0 -18 -13 -31t-31 -13h-1112q-18 0 -31 13t-13 31v1012q0 18 13 31t31 13zM100 1000v-737l247 182l298 -131l-74 156l293 318l236 -288v500h-1000zM342 884q56 0 95 -39t39 -94.5t-39 -95t-95 -39.5t-95 39.5t-39 95t39 94.5 t95 39z" />
|
||||
<glyph unicode="" d="M648 1169q117 0 216 -60t156.5 -161t57.5 -218q0 -115 -70 -258q-69 -109 -158 -225.5t-143 -179.5l-54 -62q-9 8 -25.5 24.5t-63.5 67.5t-91 103t-98.5 128t-95.5 148q-60 132 -60 249q0 88 34 169.5t91.5 142t137 96.5t166.5 36zM652.5 974q-91.5 0 -156.5 -65 t-65 -157t65 -156.5t156.5 -64.5t156.5 64.5t65 156.5t-65 157t-156.5 65z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 173v854q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57z" />
|
||||
<glyph unicode="" d="M554 1295q21 -72 57.5 -143.5t76 -130t83 -118t82.5 -117t70 -116t49.5 -126t18.5 -136.5q0 -71 -25.5 -135t-68.5 -111t-99 -82t-118.5 -54t-125.5 -23q-84 5 -161.5 34t-139.5 78.5t-99 125t-37 164.5q0 69 18 136.5t49.5 126.5t69.5 116.5t81.5 117.5t83.5 119 t76.5 131t58.5 143zM344 710q-23 -33 -43.5 -70.5t-40.5 -102.5t-17 -123q1 -37 14.5 -69.5t30 -52t41 -37t38.5 -24.5t33 -15q21 -7 32 -1t13 22l6 34q2 10 -2.5 22t-13.5 19q-5 4 -14 12t-29.5 40.5t-32.5 73.5q-26 89 6 271q2 11 -6 11q-8 1 -15 -10z" />
|
||||
<glyph unicode="" d="M1000 1013l108 115q2 1 5 2t13 2t20.5 -1t25 -9.5t28.5 -21.5q22 -22 27 -43t0 -32l-6 -10l-108 -115zM350 1100h400q50 0 105 -13l-187 -187h-368q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v182l200 200v-332 q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5zM1009 803l-362 -362l-161 -50l55 170l355 355z" />
|
||||
<glyph unicode="" d="M350 1100h361q-164 -146 -216 -200h-195q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-103q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5z M824 1073l339 -301q8 -7 8 -17.5t-8 -17.5l-340 -306q-7 -6 -12.5 -4t-6.5 11v203q-26 1 -54.5 0t-78.5 -7.5t-92 -17.5t-86 -35t-70 -57q10 59 33 108t51.5 81.5t65 58.5t68.5 40.5t67 24.5t56 13.5t40 4.5v210q1 10 6.5 12.5t13.5 -4.5z" />
|
||||
<glyph unicode="" d="M350 1100h350q60 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-219q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5z M643 639l395 395q7 7 17.5 7t17.5 -7l101 -101q7 -7 7 -17.5t-7 -17.5l-531 -532q-7 -7 -17.5 -7t-17.5 7l-248 248q-7 7 -7 17.5t7 17.5l101 101q7 7 17.5 7t17.5 -7l111 -111q8 -7 18 -7t18 7z" />
|
||||
<glyph unicode="" d="M318 918l264 264q8 8 18 8t18 -8l260 -264q7 -8 4.5 -13t-12.5 -5h-170v-200h200v173q0 10 5 12t13 -5l264 -260q8 -7 8 -17.5t-8 -17.5l-264 -265q-8 -7 -13 -5t-5 12v173h-200v-200h170q10 0 12.5 -5t-4.5 -13l-260 -264q-8 -8 -18 -8t-18 8l-264 264q-8 8 -5.5 13 t12.5 5h175v200h-200v-173q0 -10 -5 -12t-13 5l-264 265q-8 7 -8 17.5t8 17.5l264 260q8 7 13 5t5 -12v-173h200v200h-175q-10 0 -12.5 5t5.5 13z" />
|
||||
<glyph unicode="" d="M250 1100h100q21 0 35.5 -14.5t14.5 -35.5v-438l464 453q15 14 25.5 10t10.5 -25v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-438l464 453q15 14 25.5 10t10.5 -25v-438l464 453q15 14 25.5 10t10.5 -25v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5 t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M1200 1050v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -10.5 -25t-25.5 10l-492 480q-15 14 -15 35t15 35l492 480q15 14 25.5 10t10.5 -25v-438l464 453q15 14 25.5 10t10.5 -25z" />
|
||||
<glyph unicode="" d="M243 1074l814 -498q18 -11 18 -26t-18 -26l-814 -498q-18 -11 -30.5 -4t-12.5 28v1000q0 21 12.5 28t30.5 -4z" />
|
||||
<glyph unicode="" d="M250 1000h200q21 0 35.5 -14.5t14.5 -35.5v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5zM650 1000h200q21 0 35.5 -14.5t14.5 -35.5v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v800 q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M1100 950v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5z" />
|
||||
<glyph unicode="" d="M500 612v438q0 21 10.5 25t25.5 -10l492 -480q15 -14 15 -35t-15 -35l-492 -480q-15 -14 -25.5 -10t-10.5 25v438l-464 -453q-15 -14 -25.5 -10t-10.5 25v1000q0 21 10.5 25t25.5 -10z" />
|
||||
<glyph unicode="" d="M1048 1102l100 1q20 0 35 -14.5t15 -35.5l5 -1000q0 -21 -14.5 -35.5t-35.5 -14.5l-100 -1q-21 0 -35.5 14.5t-14.5 35.5l-2 437l-463 -454q-14 -15 -24.5 -10.5t-10.5 25.5l-2 437l-462 -455q-15 -14 -25.5 -9.5t-10.5 24.5l-5 1000q0 21 10.5 25.5t25.5 -10.5l466 -450 l-2 438q0 20 10.5 24.5t25.5 -9.5l466 -451l-2 438q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M850 1100h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-464 -453q-15 -14 -25.5 -10t-10.5 25v1000q0 21 10.5 25t25.5 -10l464 -453v438q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M686 1081l501 -540q15 -15 10.5 -26t-26.5 -11h-1042q-22 0 -26.5 11t10.5 26l501 540q15 15 36 15t36 -15zM150 400h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M885 900l-352 -353l352 -353l-197 -198l-552 552l552 550z" />
|
||||
<glyph unicode="" d="M1064 547l-551 -551l-198 198l353 353l-353 353l198 198z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM650 900h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-150h-150 q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5t35.5 -14.5h150v-150q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v150h150q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5h-150v150q0 21 -14.5 35.5t-35.5 14.5z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM850 700h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5 t35.5 -14.5h500q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM741.5 913q-12.5 0 -21.5 -9l-120 -120l-120 120q-9 9 -21.5 9 t-21.5 -9l-141 -141q-9 -9 -9 -21.5t9 -21.5l120 -120l-120 -120q-9 -9 -9 -21.5t9 -21.5l141 -141q9 -9 21.5 -9t21.5 9l120 120l120 -120q9 -9 21.5 -9t21.5 9l141 141q9 9 9 21.5t-9 21.5l-120 120l120 120q9 9 9 21.5t-9 21.5l-141 141q-9 9 -21.5 9z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM546 623l-84 85q-7 7 -17.5 7t-18.5 -7l-139 -139q-7 -8 -7 -18t7 -18 l242 -241q7 -8 17.5 -8t17.5 8l375 375q7 7 7 17.5t-7 18.5l-139 139q-7 7 -17.5 7t-17.5 -7z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM588 941q-29 0 -59 -5.5t-63 -20.5t-58 -38.5t-41.5 -63t-16.5 -89.5 q0 -25 20 -25h131q30 -5 35 11q6 20 20.5 28t45.5 8q20 0 31.5 -10.5t11.5 -28.5q0 -23 -7 -34t-26 -18q-1 0 -13.5 -4t-19.5 -7.5t-20 -10.5t-22 -17t-18.5 -24t-15.5 -35t-8 -46q-1 -8 5.5 -16.5t20.5 -8.5h173q7 0 22 8t35 28t37.5 48t29.5 74t12 100q0 47 -17 83 t-42.5 57t-59.5 34.5t-64 18t-59 4.5zM675 400h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM675 1000h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5 t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5zM675 700h-250q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h75v-200h-75q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h350q10 0 17.5 7.5t7.5 17.5v50q0 10 -7.5 17.5 t-17.5 7.5h-75v275q0 10 -7.5 17.5t-17.5 7.5z" />
|
||||
<glyph unicode="" d="M525 1200h150q10 0 17.5 -7.5t7.5 -17.5v-194q103 -27 178.5 -102.5t102.5 -178.5h194q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-194q-27 -103 -102.5 -178.5t-178.5 -102.5v-194q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v194 q-103 27 -178.5 102.5t-102.5 178.5h-194q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h194q27 103 102.5 178.5t178.5 102.5v194q0 10 7.5 17.5t17.5 7.5zM700 893v-168q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v168q-68 -23 -119 -74 t-74 -119h168q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-168q23 -68 74 -119t119 -74v168q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-168q68 23 119 74t74 119h-168q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h168 q-23 68 -74 119t-119 74z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM759 823l64 -64q7 -7 7 -17.5t-7 -17.5l-124 -124l124 -124q7 -7 7 -17.5t-7 -17.5l-64 -64q-7 -7 -17.5 -7t-17.5 7l-124 124l-124 -124q-7 -7 -17.5 -7t-17.5 7l-64 64 q-7 7 -7 17.5t7 17.5l124 124l-124 124q-7 7 -7 17.5t7 17.5l64 64q7 7 17.5 7t17.5 -7l124 -124l124 124q7 7 17.5 7t17.5 -7z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM782 788l106 -106q7 -7 7 -17.5t-7 -17.5l-320 -321q-8 -7 -18 -7t-18 7l-202 203q-8 7 -8 17.5t8 17.5l106 106q7 8 17.5 8t17.5 -8l79 -79l197 197q7 7 17.5 7t17.5 -7z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5q0 -120 65 -225 l587 587q-105 65 -225 65zM965 819l-584 -584q104 -62 219 -62q116 0 214.5 57t155.5 155.5t57 214.5q0 115 -62 219z" />
|
||||
<glyph unicode="" d="M39 582l522 427q16 13 27.5 8t11.5 -26v-291h550q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-550v-291q0 -21 -11.5 -26t-27.5 8l-522 427q-16 13 -16 32t16 32z" />
|
||||
<glyph unicode="" d="M639 1009l522 -427q16 -13 16 -32t-16 -32l-522 -427q-16 -13 -27.5 -8t-11.5 26v291h-550q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h550v291q0 21 11.5 26t27.5 -8z" />
|
||||
<glyph unicode="" d="M682 1161l427 -522q13 -16 8 -27.5t-26 -11.5h-291v-550q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v550h-291q-21 0 -26 11.5t8 27.5l427 522q13 16 32 16t32 -16z" />
|
||||
<glyph unicode="" d="M550 1200h200q21 0 35.5 -14.5t14.5 -35.5v-550h291q21 0 26 -11.5t-8 -27.5l-427 -522q-13 -16 -32 -16t-32 16l-427 522q-13 16 -8 27.5t26 11.5h291v550q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M639 1109l522 -427q16 -13 16 -32t-16 -32l-522 -427q-16 -13 -27.5 -8t-11.5 26v291q-94 -2 -182 -20t-170.5 -52t-147 -92.5t-100.5 -135.5q5 105 27 193.5t67.5 167t113 135t167 91.5t225.5 42v262q0 21 11.5 26t27.5 -8z" />
|
||||
<glyph unicode="" d="M850 1200h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94l-249 -249q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l249 249l-94 94q-14 14 -10 24.5t25 10.5zM350 0h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l249 249 q8 7 18 7t18 -7l106 -106q7 -8 7 -18t-7 -18l-249 -249l94 -94q14 -14 10 -24.5t-25 -10.5z" />
|
||||
<glyph unicode="" d="M1014 1120l106 -106q7 -8 7 -18t-7 -18l-249 -249l94 -94q14 -14 10 -24.5t-25 -10.5h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l249 249q8 7 18 7t18 -7zM250 600h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94 l-249 -249q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l249 249l-94 94q-14 14 -10 24.5t25 10.5z" />
|
||||
<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM704 900h-208q-20 0 -32 -14.5t-8 -34.5l58 -302q4 -20 21.5 -34.5 t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5zM675 400h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5z" />
|
||||
<glyph unicode="" d="M260 1200q9 0 19 -2t15 -4l5 -2q22 -10 44 -23l196 -118q21 -13 36 -24q29 -21 37 -12q11 13 49 35l196 118q22 13 45 23q17 7 38 7q23 0 47 -16.5t37 -33.5l13 -16q14 -21 18 -45l25 -123l8 -44q1 -9 8.5 -14.5t17.5 -5.5h61q10 0 17.5 -7.5t7.5 -17.5v-50 q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 -7.5t-7.5 -17.5v-175h-400v300h-200v-300h-400v175q0 10 -7.5 17.5t-17.5 7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5h61q11 0 18 3t7 8q0 4 9 52l25 128q5 25 19 45q2 3 5 7t13.5 15t21.5 19.5t26.5 15.5 t29.5 7zM915 1079l-166 -162q-7 -7 -5 -12t12 -5h219q10 0 15 7t2 17l-51 149q-3 10 -11 12t-15 -6zM463 917l-177 157q-8 7 -16 5t-11 -12l-51 -143q-3 -10 2 -17t15 -7h231q11 0 12.5 5t-5.5 12zM500 0h-375q-10 0 -17.5 7.5t-7.5 17.5v375h400v-400zM1100 400v-375 q0 -10 -7.5 -17.5t-17.5 -7.5h-375v400h400z" />
|
||||
<glyph unicode="" d="M1165 1190q8 3 21 -6.5t13 -17.5q-2 -178 -24.5 -323.5t-55.5 -245.5t-87 -174.5t-102.5 -118.5t-118 -68.5t-118.5 -33t-120 -4.5t-105 9.5t-90 16.5q-61 12 -78 11q-4 1 -12.5 0t-34 -14.5t-52.5 -40.5l-153 -153q-26 -24 -37 -14.5t-11 43.5q0 64 42 102q8 8 50.5 45 t66.5 58q19 17 35 47t13 61q-9 55 -10 102.5t7 111t37 130t78 129.5q39 51 80 88t89.5 63.5t94.5 45t113.5 36t129 31t157.5 37t182 47.5zM1116 1098q-8 9 -22.5 -3t-45.5 -50q-38 -47 -119 -103.5t-142 -89.5l-62 -33q-56 -30 -102 -57t-104 -68t-102.5 -80.5t-85.5 -91 t-64 -104.5q-24 -56 -31 -86t2 -32t31.5 17.5t55.5 59.5q25 30 94 75.5t125.5 77.5t147.5 81q70 37 118.5 69t102 79.5t99 111t86.5 148.5q22 50 24 60t-6 19z" />
|
||||
<glyph unicode="" d="M653 1231q-39 -67 -54.5 -131t-10.5 -114.5t24.5 -96.5t47.5 -80t63.5 -62.5t68.5 -46.5t65 -30q-4 7 -17.5 35t-18.5 39.5t-17 39.5t-17 43t-13 42t-9.5 44.5t-2 42t4 43t13.5 39t23 38.5q96 -42 165 -107.5t105 -138t52 -156t13 -159t-19 -149.5q-13 -55 -44 -106.5 t-68 -87t-78.5 -64.5t-72.5 -45t-53 -22q-72 -22 -127 -11q-31 6 -13 19q6 3 17 7q13 5 32.5 21t41 44t38.5 63.5t21.5 81.5t-6.5 94.5t-50 107t-104 115.5q10 -104 -0.5 -189t-37 -140.5t-65 -93t-84 -52t-93.5 -11t-95 24.5q-80 36 -131.5 114t-53.5 171q-2 23 0 49.5 t4.5 52.5t13.5 56t27.5 60t46 64.5t69.5 68.5q-8 -53 -5 -102.5t17.5 -90t34 -68.5t44.5 -39t49 -2q31 13 38.5 36t-4.5 55t-29 64.5t-36 75t-26 75.5q-15 85 2 161.5t53.5 128.5t85.5 92.5t93.5 61t81.5 25.5z" />
|
||||
<glyph unicode="" d="M600 1094q82 0 160.5 -22.5t140 -59t116.5 -82.5t94.5 -95t68 -95t42.5 -82.5t14 -57.5t-14 -57.5t-43 -82.5t-68.5 -95t-94.5 -95t-116.5 -82.5t-140 -59t-159.5 -22.5t-159.5 22.5t-140 59t-116.5 82.5t-94.5 95t-68.5 95t-43 82.5t-14 57.5t14 57.5t42.5 82.5t68 95 t94.5 95t116.5 82.5t140 59t160.5 22.5zM888 829q-15 15 -18 12t5 -22q25 -57 25 -119q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 59 23 114q8 19 4.5 22t-17.5 -12q-70 -69 -160 -184q-13 -16 -15 -40.5t9 -42.5q22 -36 47 -71t70 -82t92.5 -81t113 -58.5t133.5 -24.5 t133.5 24t113 58.5t92.5 81.5t70 81.5t47 70.5q11 18 9 42.5t-14 41.5q-90 117 -163 189zM448 727l-35 -36q-15 -15 -19.5 -38.5t4.5 -41.5q37 -68 93 -116q16 -13 38.5 -11t36.5 17l35 34q14 15 12.5 33.5t-16.5 33.5q-44 44 -89 117q-11 18 -28 20t-32 -12z" />
|
||||
<glyph unicode="" d="M592 0h-148l31 120q-91 20 -175.5 68.5t-143.5 106.5t-103.5 119t-66.5 110t-22 76q0 21 14 57.5t42.5 82.5t68 95t94.5 95t116.5 82.5t140 59t160.5 22.5q61 0 126 -15l32 121h148zM944 770l47 181q108 -85 176.5 -192t68.5 -159q0 -26 -19.5 -71t-59.5 -102t-93 -112 t-129 -104.5t-158 -75.5l46 173q77 49 136 117t97 131q11 18 9 42.5t-14 41.5q-54 70 -107 130zM310 824q-70 -69 -160 -184q-13 -16 -15 -40.5t9 -42.5q18 -30 39 -60t57 -70.5t74 -73t90 -61t105 -41.5l41 154q-107 18 -178.5 101.5t-71.5 193.5q0 59 23 114q8 19 4.5 22 t-17.5 -12zM448 727l-35 -36q-15 -15 -19.5 -38.5t4.5 -41.5q37 -68 93 -116q16 -13 38.5 -11t36.5 17l12 11l22 86l-3 4q-44 44 -89 117q-11 18 -28 20t-32 -12z" />
|
||||
<glyph unicode="" d="M-90 100l642 1066q20 31 48 28.5t48 -35.5l642 -1056q21 -32 7.5 -67.5t-50.5 -35.5h-1294q-37 0 -50.5 34t7.5 66zM155 200h345v75q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-75h345l-445 723zM496 700h208q20 0 32 -14.5t8 -34.5l-58 -252 q-4 -20 -21.5 -34.5t-37.5 -14.5h-54q-20 0 -37.5 14.5t-21.5 34.5l-58 252q-4 20 8 34.5t32 14.5z" />
|
||||
<glyph unicode="" d="M650 1200q62 0 106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -93 100 -113v-64q0 -21 -13 -29t-32 1l-205 128l-205 -128q-19 -9 -32 -1t-13 29v64q0 20 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5v41 q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44z" />
|
||||
<glyph unicode="" d="M850 1200h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-150h-1100v150q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-50h500v50q0 21 14.5 35.5t35.5 14.5zM1100 800v-750q0 -21 -14.5 -35.5 t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v750h1100zM100 600v-100h100v100h-100zM300 600v-100h100v100h-100zM500 600v-100h100v100h-100zM700 600v-100h100v100h-100zM900 600v-100h100v100h-100zM100 400v-100h100v100h-100zM300 400v-100h100v100h-100zM500 400 v-100h100v100h-100zM700 400v-100h100v100h-100zM900 400v-100h100v100h-100zM100 200v-100h100v100h-100zM300 200v-100h100v100h-100zM500 200v-100h100v100h-100zM700 200v-100h100v100h-100zM900 200v-100h100v100h-100z" />
|
||||
<glyph unicode="" d="M1135 1165l249 -230q15 -14 15 -35t-15 -35l-249 -230q-14 -14 -24.5 -10t-10.5 25v150h-159l-600 -600h-291q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h209l600 600h241v150q0 21 10.5 25t24.5 -10zM522 819l-141 -141l-122 122h-209q-21 0 -35.5 14.5 t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h291zM1135 565l249 -230q15 -14 15 -35t-15 -35l-249 -230q-14 -14 -24.5 -10t-10.5 25v150h-241l-181 181l141 141l122 -122h159v150q0 21 10.5 25t24.5 -10z" />
|
||||
<glyph unicode="" d="M100 1100h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5z" />
|
||||
<glyph unicode="" d="M150 1200h200q21 0 35.5 -14.5t14.5 -35.5v-250h-300v250q0 21 14.5 35.5t35.5 14.5zM850 1200h200q21 0 35.5 -14.5t14.5 -35.5v-250h-300v250q0 21 14.5 35.5t35.5 14.5zM1100 800v-300q0 -41 -3 -77.5t-15 -89.5t-32 -96t-58 -89t-89 -77t-129 -51t-174 -20t-174 20 t-129 51t-89 77t-58 89t-32 96t-15 89.5t-3 77.5v300h300v-250v-27v-42.5t1.5 -41t5 -38t10 -35t16.5 -30t25.5 -24.5t35 -19t46.5 -12t60 -4t60 4.5t46.5 12.5t35 19.5t25 25.5t17 30.5t10 35t5 38t2 40.5t-0.5 42v25v250h300z" />
|
||||
<glyph unicode="" d="M1100 411l-198 -199l-353 353l-353 -353l-197 199l551 551z" />
|
||||
<glyph unicode="" d="M1101 789l-550 -551l-551 551l198 199l353 -353l353 353z" />
|
||||
<glyph unicode="" d="M404 1000h746q21 0 35.5 -14.5t14.5 -35.5v-551h150q21 0 25 -10.5t-10 -24.5l-230 -249q-14 -15 -35 -15t-35 15l-230 249q-14 14 -10 24.5t25 10.5h150v401h-381zM135 984l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-400h385l215 -200h-750q-21 0 -35.5 14.5 t-14.5 35.5v550h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
|
||||
<glyph unicode="" d="M56 1200h94q17 0 31 -11t18 -27l38 -162h896q24 0 39 -18.5t10 -42.5l-100 -475q-5 -21 -27 -42.5t-55 -21.5h-633l48 -200h535q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-50q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v50h-300v-50 q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v50h-31q-18 0 -32.5 10t-20.5 19l-5 10l-201 961h-54q-20 0 -35 14.5t-15 35.5t15 35.5t35 14.5z" />
|
||||
<glyph unicode="" d="M1200 1000v-100h-1200v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500zM0 800h1200v-800h-1200v800z" />
|
||||
<glyph unicode="" d="M200 800l-200 -400v600h200q0 41 29.5 70.5t70.5 29.5h300q42 0 71 -29.5t29 -70.5h500v-200h-1000zM1500 700l-300 -700h-1200l300 700h1200z" />
|
||||
<glyph unicode="" d="M635 1184l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-601h150q21 0 25 -10.5t-10 -24.5l-230 -249q-14 -15 -35 -15t-35 15l-230 249q-14 14 -10 24.5t25 10.5h150v601h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
|
||||
<glyph unicode="" d="M936 864l249 -229q14 -15 14 -35.5t-14 -35.5l-249 -229q-15 -15 -25.5 -10.5t-10.5 24.5v151h-600v-151q0 -20 -10.5 -24.5t-25.5 10.5l-249 229q-14 15 -14 35.5t14 35.5l249 229q15 15 25.5 10.5t10.5 -25.5v-149h600v149q0 21 10.5 25.5t25.5 -10.5z" />
|
||||
<glyph unicode="" d="M1169 400l-172 732q-5 23 -23 45.5t-38 22.5h-672q-20 0 -38 -20t-23 -41l-172 -739h1138zM1100 300h-1000q-41 0 -70.5 -29.5t-29.5 -70.5v-100q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v100q0 41 -29.5 70.5t-70.5 29.5zM800 100v100h100v-100h-100 zM1000 100v100h100v-100h-100z" />
|
||||
<glyph unicode="" d="M1150 1100q21 0 35.5 -14.5t14.5 -35.5v-850q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v850q0 21 14.5 35.5t35.5 14.5zM1000 200l-675 200h-38l47 -276q3 -16 -5.5 -20t-29.5 -4h-7h-84q-20 0 -34.5 14t-18.5 35q-55 337 -55 351v250v6q0 16 1 23.5t6.5 14 t17.5 6.5h200l675 250v-850zM0 750v-250q-4 0 -11 0.5t-24 6t-30 15t-24 30t-11 48.5v50q0 26 10.5 46t25 30t29 16t25.5 7z" />
|
||||
<glyph unicode="" d="M553 1200h94q20 0 29 -10.5t3 -29.5l-18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q19 0 33 -14.5t14 -35t-13 -40.5t-31 -27q-8 -4 -23 -9.5t-65 -19.5t-103 -25t-132.5 -20t-158.5 -9q-57 0 -115 5t-104 12t-88.5 15.5t-73.5 17.5t-54.5 16t-35.5 12l-11 4 q-18 8 -31 28t-13 40.5t14 35t33 14.5h17l118 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3.5 32t28.5 13zM498 110q50 -6 102 -6q53 0 102 6q-12 -49 -39.5 -79.5t-62.5 -30.5t-63 30.5t-39 79.5z" />
|
||||
<glyph unicode="" d="M800 946l224 78l-78 -224l234 -45l-180 -155l180 -155l-234 -45l78 -224l-224 78l-45 -234l-155 180l-155 -180l-45 234l-224 -78l78 224l-234 45l180 155l-180 155l234 45l-78 224l224 -78l45 234l155 -180l155 180z" />
|
||||
<glyph unicode="" d="M650 1200h50q40 0 70 -40.5t30 -84.5v-150l-28 -125h328q40 0 70 -40.5t30 -84.5v-100q0 -45 -29 -74l-238 -344q-16 -24 -38 -40.5t-45 -16.5h-250q-7 0 -42 25t-66 50l-31 25h-61q-45 0 -72.5 18t-27.5 57v400q0 36 20 63l145 196l96 198q13 28 37.5 48t51.5 20z M650 1100l-100 -212l-150 -213v-375h100l136 -100h214l250 375v125h-450l50 225v175h-50zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M600 1100h250q23 0 45 -16.5t38 -40.5l238 -344q29 -29 29 -74v-100q0 -44 -30 -84.5t-70 -40.5h-328q28 -118 28 -125v-150q0 -44 -30 -84.5t-70 -40.5h-50q-27 0 -51.5 20t-37.5 48l-96 198l-145 196q-20 27 -20 63v400q0 39 27.5 57t72.5 18h61q124 100 139 100z M50 1000h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5zM636 1000l-136 -100h-100v-375l150 -213l100 -212h50v175l-50 225h450v125l-250 375h-214z" />
|
||||
<glyph unicode="" d="M356 873l363 230q31 16 53 -6l110 -112q13 -13 13.5 -32t-11.5 -34l-84 -121h302q84 0 138 -38t54 -110t-55 -111t-139 -39h-106l-131 -339q-6 -21 -19.5 -41t-28.5 -20h-342q-7 0 -90 81t-83 94v525q0 17 14 35.5t28 28.5zM400 792v-503l100 -89h293l131 339 q6 21 19.5 41t28.5 20h203q21 0 30.5 25t0.5 50t-31 25h-456h-7h-6h-5.5t-6 0.5t-5 1.5t-5 2t-4 2.5t-4 4t-2.5 4.5q-12 25 5 47l146 183l-86 83zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500 q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M475 1103l366 -230q2 -1 6 -3.5t14 -10.5t18 -16.5t14.5 -20t6.5 -22.5v-525q0 -13 -86 -94t-93 -81h-342q-15 0 -28.5 20t-19.5 41l-131 339h-106q-85 0 -139.5 39t-54.5 111t54 110t138 38h302l-85 121q-11 15 -10.5 34t13.5 32l110 112q22 22 53 6zM370 945l146 -183 q17 -22 5 -47q-2 -2 -3.5 -4.5t-4 -4t-4 -2.5t-5 -2t-5 -1.5t-6 -0.5h-6h-6.5h-6h-475v-100h221q15 0 29 -20t20 -41l130 -339h294l106 89v503l-342 236zM1050 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5 v500q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M550 1294q72 0 111 -55t39 -139v-106l339 -131q21 -6 41 -19.5t20 -28.5v-342q0 -7 -81 -90t-94 -83h-525q-17 0 -35.5 14t-28.5 28l-9 14l-230 363q-16 31 6 53l112 110q13 13 32 13.5t34 -11.5l121 -84v302q0 84 38 138t110 54zM600 972v203q0 21 -25 30.5t-50 0.5 t-25 -31v-456v-7v-6v-5.5t-0.5 -6t-1.5 -5t-2 -5t-2.5 -4t-4 -4t-4.5 -2.5q-25 -12 -47 5l-183 146l-83 -86l236 -339h503l89 100v293l-339 131q-21 6 -41 19.5t-20 28.5zM450 200h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M350 1100h500q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5t35.5 -14.5zM600 306v-106q0 -84 -39 -139t-111 -55t-110 54t-38 138v302l-121 -84q-15 -12 -34 -11.5t-32 13.5l-112 110 q-22 22 -6 53l230 363q1 2 3.5 6t10.5 13.5t16.5 17t20 13.5t22.5 6h525q13 0 94 -83t81 -90v-342q0 -15 -20 -28.5t-41 -19.5zM308 900l-236 -339l83 -86l183 146q22 17 47 5q2 -1 4.5 -2.5t4 -4t2.5 -4t2 -5t1.5 -5t0.5 -6v-5.5v-6v-7v-456q0 -22 25 -31t50 0.5t25 30.5 v203q0 15 20 28.5t41 19.5l339 131v293l-89 100h-503z" />
|
||||
<glyph unicode="" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM914 632l-275 223q-16 13 -27.5 8t-11.5 -26v-137h-275 q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h275v-137q0 -21 11.5 -26t27.5 8l275 223q16 13 16 32t-16 32z" />
|
||||
<glyph unicode="" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM561 855l-275 -223q-16 -13 -16 -32t16 -32l275 -223q16 -13 27.5 -8 t11.5 26v137h275q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5h-275v137q0 21 -11.5 26t-27.5 -8z" />
|
||||
<glyph unicode="" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM855 639l-223 275q-13 16 -32 16t-32 -16l-223 -275q-13 -16 -8 -27.5 t26 -11.5h137v-275q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v275h137q21 0 26 11.5t-8 27.5z" />
|
||||
<glyph unicode="" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM675 900h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-275h-137q-21 0 -26 -11.5 t8 -27.5l223 -275q13 -16 32 -16t32 16l223 275q13 16 8 27.5t-26 11.5h-137v275q0 10 -7.5 17.5t-17.5 7.5z" />
|
||||
<glyph unicode="" d="M600 1176q116 0 222.5 -46t184 -123.5t123.5 -184t46 -222.5t-46 -222.5t-123.5 -184t-184 -123.5t-222.5 -46t-222.5 46t-184 123.5t-123.5 184t-46 222.5t46 222.5t123.5 184t184 123.5t222.5 46zM627 1101q-15 -12 -36.5 -20.5t-35.5 -12t-43 -8t-39 -6.5 q-15 -3 -45.5 0t-45.5 -2q-20 -7 -51.5 -26.5t-34.5 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -91t-29.5 -79q-9 -34 5 -93t8 -87q0 -9 17 -44.5t16 -59.5q12 0 23 -5t23.5 -15t19.5 -14q16 -8 33 -15t40.5 -15t34.5 -12q21 -9 52.5 -32t60 -38t57.5 -11 q7 -15 -3 -34t-22.5 -40t-9.5 -38q13 -21 23 -34.5t27.5 -27.5t36.5 -18q0 -7 -3.5 -16t-3.5 -14t5 -17q104 -2 221 112q30 29 46.5 47t34.5 49t21 63q-13 8 -37 8.5t-36 7.5q-15 7 -49.5 15t-51.5 19q-18 0 -41 -0.5t-43 -1.5t-42 -6.5t-38 -16.5q-51 -35 -66 -12 q-4 1 -3.5 25.5t0.5 25.5q-6 13 -26.5 17.5t-24.5 6.5q1 15 -0.5 30.5t-7 28t-18.5 11.5t-31 -21q-23 -25 -42 4q-19 28 -8 58q6 16 22 22q6 -1 26 -1.5t33.5 -4t19.5 -13.5q7 -12 18 -24t21.5 -20.5t20 -15t15.5 -10.5l5 -3q2 12 7.5 30.5t8 34.5t-0.5 32q-3 18 3.5 29 t18 22.5t15.5 24.5q6 14 10.5 35t8 31t15.5 22.5t34 22.5q-6 18 10 36q8 0 24 -1.5t24.5 -1.5t20 4.5t20.5 15.5q-10 23 -31 42.5t-37.5 29.5t-49 27t-43.5 23q0 1 2 8t3 11.5t1.5 10.5t-1 9.5t-4.5 4.5q31 -13 58.5 -14.5t38.5 2.5l12 5q5 28 -9.5 46t-36.5 24t-50 15 t-41 20q-18 -4 -37 0zM613 994q0 -17 8 -42t17 -45t9 -23q-8 1 -39.5 5.5t-52.5 10t-37 16.5q3 11 16 29.5t16 25.5q10 -10 19 -10t14 6t13.5 14.5t16.5 12.5z" />
|
||||
<glyph unicode="" d="M756 1157q164 92 306 -9l-259 -138l145 -232l251 126q6 -89 -34 -156.5t-117 -110.5q-60 -34 -127 -39.5t-126 16.5l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5t15 37.5l600 599q-34 101 5.5 201.5t135.5 154.5z" />
|
||||
<glyph unicode="" horiz-adv-x="1220" d="M100 1196h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 1096h-200v-100h200v100zM100 796h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 696h-500v-100h500v100zM100 396h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 296h-300v-100h300v100z " />
|
||||
<glyph unicode="" d="M150 1200h900q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM700 500v-300l-200 -200v500l-350 500h900z" />
|
||||
<glyph unicode="" d="M500 1200h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5zM500 1100v-100h200v100h-200zM1200 400v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v200h1200z" />
|
||||
<glyph unicode="" d="M50 1200h300q21 0 25 -10.5t-10 -24.5l-94 -94l199 -199q7 -8 7 -18t-7 -18l-106 -106q-8 -7 -18 -7t-18 7l-199 199l-94 -94q-14 -14 -24.5 -10t-10.5 25v300q0 21 14.5 35.5t35.5 14.5zM850 1200h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94 l-199 -199q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l199 199l-94 94q-14 14 -10 24.5t25 10.5zM364 470l106 -106q7 -8 7 -18t-7 -18l-199 -199l94 -94q14 -14 10 -24.5t-25 -10.5h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l199 199 q8 7 18 7t18 -7zM1071 271l94 94q14 14 24.5 10t10.5 -25v-300q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -25 10.5t10 24.5l94 94l-199 199q-7 8 -7 18t7 18l106 106q8 7 18 7t18 -7z" />
|
||||
<glyph unicode="" d="M596 1192q121 0 231.5 -47.5t190 -127t127 -190t47.5 -231.5t-47.5 -231.5t-127 -190.5t-190 -127t-231.5 -47t-231.5 47t-190.5 127t-127 190.5t-47 231.5t47 231.5t127 190t190.5 127t231.5 47.5zM596 1010q-112 0 -207.5 -55.5t-151 -151t-55.5 -207.5t55.5 -207.5 t151 -151t207.5 -55.5t207.5 55.5t151 151t55.5 207.5t-55.5 207.5t-151 151t-207.5 55.5zM454.5 905q22.5 0 38.5 -16t16 -38.5t-16 -39t-38.5 -16.5t-38.5 16.5t-16 39t16 38.5t38.5 16zM754.5 905q22.5 0 38.5 -16t16 -38.5t-16 -39t-38 -16.5q-14 0 -29 10l-55 -145 q17 -23 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5t-61.5 25.5t-25.5 61.5q0 32 20.5 56.5t51.5 29.5l122 126l1 1q-9 14 -9 28q0 23 16 39t38.5 16zM345.5 709q22.5 0 38.5 -16t16 -38.5t-16 -38.5t-38.5 -16t-38.5 16t-16 38.5t16 38.5t38.5 16zM854.5 709q22.5 0 38.5 -16 t16 -38.5t-16 -38.5t-38.5 -16t-38.5 16t-16 38.5t16 38.5t38.5 16z" />
|
||||
<glyph unicode="" d="M546 173l469 470q91 91 99 192q7 98 -52 175.5t-154 94.5q-22 4 -47 4q-34 0 -66.5 -10t-56.5 -23t-55.5 -38t-48 -41.5t-48.5 -47.5q-376 -375 -391 -390q-30 -27 -45 -41.5t-37.5 -41t-32 -46.5t-16 -47.5t-1.5 -56.5q9 -62 53.5 -95t99.5 -33q74 0 125 51l548 548 q36 36 20 75q-7 16 -21.5 26t-32.5 10q-26 0 -50 -23q-13 -12 -39 -38l-341 -338q-15 -15 -35.5 -15.5t-34.5 13.5t-14 34.5t14 34.5q327 333 361 367q35 35 67.5 51.5t78.5 16.5q14 0 29 -1q44 -8 74.5 -35.5t43.5 -68.5q14 -47 2 -96.5t-47 -84.5q-12 -11 -32 -32 t-79.5 -81t-114.5 -115t-124.5 -123.5t-123 -119.5t-96.5 -89t-57 -45q-56 -27 -120 -27q-70 0 -129 32t-93 89q-48 78 -35 173t81 163l511 511q71 72 111 96q91 55 198 55q80 0 152 -33q78 -36 129.5 -103t66.5 -154q17 -93 -11 -183.5t-94 -156.5l-482 -476 q-15 -15 -36 -16t-37 14t-17.5 34t14.5 35z" />
|
||||
<glyph unicode="" d="M649 949q48 68 109.5 104t121.5 38.5t118.5 -20t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-150 152.5t-126.5 127.5t-93.5 124.5t-33.5 117.5q0 64 28 123t73 100.5t104 64t119 20 t120.5 -38.5t104.5 -104zM896 972q-33 0 -64.5 -19t-56.5 -46t-47.5 -53.5t-43.5 -45.5t-37.5 -19t-36 19t-40 45.5t-43 53.5t-54 46t-65.5 19q-67 0 -122.5 -55.5t-55.5 -132.5q0 -23 13.5 -51t46 -65t57.5 -63t76 -75l22 -22q15 -14 44 -44t50.5 -51t46 -44t41 -35t23 -12 t23.5 12t42.5 36t46 44t52.5 52t44 43q4 4 12 13q43 41 63.5 62t52 55t46 55t26 46t11.5 44q0 79 -53 133.5t-120 54.5z" />
|
||||
<glyph unicode="" d="M776.5 1214q93.5 0 159.5 -66l141 -141q66 -66 66 -160q0 -42 -28 -95.5t-62 -87.5l-29 -29q-31 53 -77 99l-18 18l95 95l-247 248l-389 -389l212 -212l-105 -106l-19 18l-141 141q-66 66 -66 159t66 159l283 283q65 66 158.5 66zM600 706l105 105q10 -8 19 -17l141 -141 q66 -66 66 -159t-66 -159l-283 -283q-66 -66 -159 -66t-159 66l-141 141q-66 66 -66 159.5t66 159.5l55 55q29 -55 75 -102l18 -17l-95 -95l247 -248l389 389z" />
|
||||
<glyph unicode="" d="M603 1200q85 0 162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5v953q0 21 30 46.5t81 48t129 37.5t163 15zM300 1000v-700h600v700h-600zM600 254q-43 0 -73.5 -30.5t-30.5 -73.5t30.5 -73.5t73.5 -30.5t73.5 30.5 t30.5 73.5t-30.5 73.5t-73.5 30.5z" />
|
||||
<glyph unicode="" d="M902 1185l283 -282q15 -15 15 -36t-14.5 -35.5t-35.5 -14.5t-35 15l-36 35l-279 -267v-300l-212 210l-308 -307l-280 -203l203 280l307 308l-210 212h300l267 279l-35 36q-15 14 -15 35t14.5 35.5t35.5 14.5t35 -15z" />
|
||||
<glyph unicode="" d="M700 1248v-78q38 -5 72.5 -14.5t75.5 -31.5t71 -53.5t52 -84t24 -118.5h-159q-4 36 -10.5 59t-21 45t-40 35.5t-64.5 20.5v-307l64 -13q34 -7 64 -16.5t70 -32t67.5 -52.5t47.5 -80t20 -112q0 -139 -89 -224t-244 -97v-77h-100v79q-150 16 -237 103q-40 40 -52.5 93.5 t-15.5 139.5h139q5 -77 48.5 -126t117.5 -65v335l-27 8q-46 14 -79 26.5t-72 36t-63 52t-40 72.5t-16 98q0 70 25 126t67.5 92t94.5 57t110 27v77h100zM600 754v274q-29 -4 -50 -11t-42 -21.5t-31.5 -41.5t-10.5 -65q0 -29 7 -50.5t16.5 -34t28.5 -22.5t31.5 -14t37.5 -10 q9 -3 13 -4zM700 547v-310q22 2 42.5 6.5t45 15.5t41.5 27t29 42t12 59.5t-12.5 59.5t-38 44.5t-53 31t-66.5 24.5z" />
|
||||
<glyph unicode="" d="M561 1197q84 0 160.5 -40t123.5 -109.5t47 -147.5h-153q0 40 -19.5 71.5t-49.5 48.5t-59.5 26t-55.5 9q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -26 13.5 -63t26.5 -61t37 -66q6 -9 9 -14h241v-100h-197q8 -50 -2.5 -115t-31.5 -95q-45 -62 -99 -112 q34 10 83 17.5t71 7.5q32 1 102 -16t104 -17q83 0 136 30l50 -147q-31 -19 -58 -30.5t-55 -15.5t-42 -4.5t-46 -0.5q-23 0 -76 17t-111 32.5t-96 11.5q-39 -3 -82 -16t-67 -25l-23 -11l-55 145q4 3 16 11t15.5 10.5t13 9t15.5 12t14.5 14t17.5 18.5q48 55 54 126.5 t-30 142.5h-221v100h166q-23 47 -44 104q-7 20 -12 41.5t-6 55.5t6 66.5t29.5 70.5t58.5 71q97 88 263 88z" />
|
||||
<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM935 1184l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-900h-200v900h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
|
||||
<glyph unicode="" d="M1000 700h-100v100h-100v-100h-100v500h300v-500zM400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM801 1100v-200h100v200h-100zM1000 350l-200 -250h200v-100h-300v150l200 250h-200v100h300v-150z " />
|
||||
<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1000 1050l-200 -250h200v-100h-300v150l200 250h-200v100h300v-150zM1000 0h-100v100h-100v-100h-100v500h300v-500zM801 400v-200h100v200h-100z " />
|
||||
<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1000 700h-100v400h-100v100h200v-500zM1100 0h-100v100h-200v400h300v-500zM901 400v-200h100v200h-100z" />
|
||||
<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1100 700h-100v100h-200v400h300v-500zM901 1100v-200h100v200h-100zM1000 0h-100v400h-100v100h200v-500z" />
|
||||
<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM900 1000h-200v200h200v-200zM1000 700h-300v200h300v-200zM1100 400h-400v200h400v-200zM1200 100h-500v200h500v-200z" />
|
||||
<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1200 1000h-500v200h500v-200zM1100 700h-400v200h400v-200zM1000 400h-300v200h300v-200zM900 100h-200v200h200v-200z" />
|
||||
<glyph unicode="" d="M350 1100h400q162 0 256 -93.5t94 -256.5v-400q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5z" />
|
||||
<glyph unicode="" d="M350 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-163 0 -256.5 92.5t-93.5 257.5v400q0 163 94 256.5t256 93.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM440 770l253 -190q17 -12 17 -30t-17 -30l-253 -190q-16 -12 -28 -6.5t-12 26.5v400q0 21 12 26.5t28 -6.5z" />
|
||||
<glyph unicode="" d="M350 1100h400q163 0 256.5 -94t93.5 -256v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 163 92.5 256.5t257.5 93.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM350 700h400q21 0 26.5 -12t-6.5 -28l-190 -253q-12 -17 -30 -17t-30 17l-190 253q-12 16 -6.5 28t26.5 12z" />
|
||||
<glyph unicode="" d="M350 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -163 -92.5 -256.5t-257.5 -93.5h-400q-163 0 -256.5 94t-93.5 256v400q0 165 92.5 257.5t257.5 92.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM580 693l190 -253q12 -16 6.5 -28t-26.5 -12h-400q-21 0 -26.5 12t6.5 28l190 253q12 17 30 17t30 -17z" />
|
||||
<glyph unicode="" d="M550 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h450q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-450q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM338 867l324 -284q16 -14 16 -33t-16 -33l-324 -284q-16 -14 -27 -9t-11 26v150h-250q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h250v150q0 21 11 26t27 -9z" />
|
||||
<glyph unicode="" d="M793 1182l9 -9q8 -10 5 -27q-3 -11 -79 -225.5t-78 -221.5l300 1q24 0 32.5 -17.5t-5.5 -35.5q-1 0 -133.5 -155t-267 -312.5t-138.5 -162.5q-12 -15 -26 -15h-9l-9 8q-9 11 -4 32q2 9 42 123.5t79 224.5l39 110h-302q-23 0 -31 19q-10 21 6 41q75 86 209.5 237.5 t228 257t98.5 111.5q9 16 25 16h9z" />
|
||||
<glyph unicode="" d="M350 1100h400q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-450q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h450q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400 q0 165 92.5 257.5t257.5 92.5zM938 867l324 -284q16 -14 16 -33t-16 -33l-324 -284q-16 -14 -27 -9t-11 26v150h-250q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h250v150q0 21 11 26t27 -9z" />
|
||||
<glyph unicode="" d="M750 1200h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -10.5 -25t-24.5 10l-109 109l-312 -312q-15 -15 -35.5 -15t-35.5 15l-141 141q-15 15 -15 35.5t15 35.5l312 312l-109 109q-14 14 -10 24.5t25 10.5zM456 900h-156q-41 0 -70.5 -29.5t-29.5 -70.5v-500 q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v148l200 200v-298q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5h300z" />
|
||||
<glyph unicode="" d="M600 1186q119 0 227.5 -46.5t187 -125t125 -187t46.5 -227.5t-46.5 -227.5t-125 -187t-187 -125t-227.5 -46.5t-227.5 46.5t-187 125t-125 187t-46.5 227.5t46.5 227.5t125 187t187 125t227.5 46.5zM600 1022q-115 0 -212 -56.5t-153.5 -153.5t-56.5 -212t56.5 -212 t153.5 -153.5t212 -56.5t212 56.5t153.5 153.5t56.5 212t-56.5 212t-153.5 153.5t-212 56.5zM600 794q80 0 137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137t57 137t137 57z" />
|
||||
<glyph unicode="" d="M450 1200h200q21 0 35.5 -14.5t14.5 -35.5v-350h245q20 0 25 -11t-9 -26l-383 -426q-14 -15 -33.5 -15t-32.5 15l-379 426q-13 15 -8.5 26t25.5 11h250v350q0 21 14.5 35.5t35.5 14.5zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5z M900 200v-50h100v50h-100z" />
|
||||
<glyph unicode="" d="M583 1182l378 -435q14 -15 9 -31t-26 -16h-244v-250q0 -20 -17 -35t-39 -15h-200q-20 0 -32 14.5t-12 35.5v250h-250q-20 0 -25.5 16.5t8.5 31.5l383 431q14 16 33.5 17t33.5 -14zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5z M900 200v-50h100v50h-100z" />
|
||||
<glyph unicode="" d="M396 723l369 369q7 7 17.5 7t17.5 -7l139 -139q7 -8 7 -18.5t-7 -17.5l-525 -525q-7 -8 -17.5 -8t-17.5 8l-292 291q-7 8 -7 18t7 18l139 139q8 7 18.5 7t17.5 -7zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50 h-100z" />
|
||||
<glyph unicode="" d="M135 1023l142 142q14 14 35 14t35 -14l77 -77l-212 -212l-77 76q-14 15 -14 36t14 35zM655 855l210 210q14 14 24.5 10t10.5 -25l-2 -599q-1 -20 -15.5 -35t-35.5 -15l-597 -1q-21 0 -25 10.5t10 24.5l208 208l-154 155l212 212zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5 v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50h-100z" />
|
||||
<glyph unicode="" d="M350 1200l599 -2q20 -1 35 -15.5t15 -35.5l1 -597q0 -21 -10.5 -25t-24.5 10l-208 208l-155 -154l-212 212l155 154l-210 210q-14 14 -10 24.5t25 10.5zM524 512l-76 -77q-15 -14 -36 -14t-35 14l-142 142q-14 14 -14 35t14 35l77 77zM50 300h1000q21 0 35.5 -14.5 t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50h-100z" />
|
||||
<glyph unicode="" d="M1200 103l-483 276l-314 -399v423h-399l1196 796v-1096zM483 424v-230l683 953z" />
|
||||
<glyph unicode="" d="M1100 1000v-850q0 -21 -14.5 -35.5t-35.5 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200z" />
|
||||
<glyph unicode="" d="M1100 1000l-2 -149l-299 -299l-95 95q-9 9 -21.5 9t-21.5 -9l-149 -147h-312v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM1132 638l106 -106q7 -7 7 -17.5t-7 -17.5l-420 -421q-8 -7 -18 -7 t-18 7l-202 203q-8 7 -8 17.5t8 17.5l106 106q7 8 17.5 8t17.5 -8l79 -79l297 297q7 7 17.5 7t17.5 -7z" />
|
||||
<glyph unicode="" d="M1100 1000v-269l-103 -103l-134 134q-15 15 -33.5 16.5t-34.5 -12.5l-266 -266h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM1202 572l70 -70q15 -15 15 -35.5t-15 -35.5l-131 -131 l131 -131q15 -15 15 -35.5t-15 -35.5l-70 -70q-15 -15 -35.5 -15t-35.5 15l-131 131l-131 -131q-15 -15 -35.5 -15t-35.5 15l-70 70q-15 15 -15 35.5t15 35.5l131 131l-131 131q-15 15 -15 35.5t15 35.5l70 70q15 15 35.5 15t35.5 -15l131 -131l131 131q15 15 35.5 15 t35.5 -15z" />
|
||||
<glyph unicode="" d="M1100 1000v-300h-350q-21 0 -35.5 -14.5t-14.5 -35.5v-150h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM850 600h100q21 0 35.5 -14.5t14.5 -35.5v-250h150q21 0 25 -10.5t-10 -24.5 l-230 -230q-14 -14 -35 -14t-35 14l-230 230q-14 14 -10 24.5t25 10.5h150v250q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M1100 1000v-400l-165 165q-14 15 -35 15t-35 -15l-263 -265h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM935 565l230 -229q14 -15 10 -25.5t-25 -10.5h-150v-250q0 -20 -14.5 -35 t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35v250h-150q-21 0 -25 10.5t10 25.5l230 229q14 15 35 15t35 -15z" />
|
||||
<glyph unicode="" d="M50 1100h1100q21 0 35.5 -14.5t14.5 -35.5v-150h-1200v150q0 21 14.5 35.5t35.5 14.5zM1200 800v-550q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v550h1200zM100 500v-200h400v200h-400z" />
|
||||
<glyph unicode="" d="M935 1165l248 -230q14 -14 14 -35t-14 -35l-248 -230q-14 -14 -24.5 -10t-10.5 25v150h-400v200h400v150q0 21 10.5 25t24.5 -10zM200 800h-50q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v-200zM400 800h-100v200h100v-200zM18 435l247 230 q14 14 24.5 10t10.5 -25v-150h400v-200h-400v-150q0 -21 -10.5 -25t-24.5 10l-247 230q-15 14 -15 35t15 35zM900 300h-100v200h100v-200zM1000 500h51q20 0 34.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-34.5 -14.5h-51v200z" />
|
||||
<glyph unicode="" d="M862 1073l276 116q25 18 43.5 8t18.5 -41v-1106q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v397q-4 1 -11 5t-24 17.5t-30 29t-24 42t-11 56.5v359q0 31 18.5 65t43.5 52zM550 1200q22 0 34.5 -12.5t14.5 -24.5l1 -13v-450q0 -28 -10.5 -59.5 t-25 -56t-29 -45t-25.5 -31.5l-10 -11v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447q-4 4 -11 11.5t-24 30.5t-30 46t-24 55t-11 60v450q0 2 0.5 5.5t4 12t8.5 15t14.5 12t22.5 5.5q20 0 32.5 -12.5t14.5 -24.5l3 -13v-350h100v350v5.5t2.5 12 t7 15t15 12t25.5 5.5q23 0 35.5 -12.5t13.5 -24.5l1 -13v-350h100v350q0 2 0.5 5.5t3 12t7 15t15 12t24.5 5.5z" />
|
||||
<glyph unicode="" d="M1200 1100v-56q-4 0 -11 -0.5t-24 -3t-30 -7.5t-24 -15t-11 -24v-888q0 -22 25 -34.5t50 -13.5l25 -2v-56h-400v56q75 0 87.5 6.5t12.5 43.5v394h-500v-394q0 -37 12.5 -43.5t87.5 -6.5v-56h-400v56q4 0 11 0.5t24 3t30 7.5t24 15t11 24v888q0 22 -25 34.5t-50 13.5 l-25 2v56h400v-56q-75 0 -87.5 -6.5t-12.5 -43.5v-394h500v394q0 37 -12.5 43.5t-87.5 6.5v56h400z" />
|
||||
<glyph unicode="" d="M675 1000h375q21 0 35.5 -14.5t14.5 -35.5v-150h-105l-295 -98v98l-200 200h-400l100 100h375zM100 900h300q41 0 70.5 -29.5t29.5 -70.5v-500q0 -41 -29.5 -70.5t-70.5 -29.5h-300q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5zM100 800v-200h300v200 h-300zM1100 535l-400 -133v163l400 133v-163zM100 500v-200h300v200h-300zM1100 398v-248q0 -21 -14.5 -35.5t-35.5 -14.5h-375l-100 -100h-375l-100 100h400l200 200h105z" />
|
||||
<glyph unicode="" d="M17 1007l162 162q17 17 40 14t37 -22l139 -194q14 -20 11 -44.5t-20 -41.5l-119 -118q102 -142 228 -268t267 -227l119 118q17 17 42.5 19t44.5 -12l192 -136q19 -14 22.5 -37.5t-13.5 -40.5l-163 -162q-3 -1 -9.5 -1t-29.5 2t-47.5 6t-62.5 14.5t-77.5 26.5t-90 42.5 t-101.5 60t-111 83t-119 108.5q-74 74 -133.5 150.5t-94.5 138.5t-60 119.5t-34.5 100t-15 74.5t-4.5 48z" />
|
||||
<glyph unicode="" d="M600 1100q92 0 175 -10.5t141.5 -27t108.5 -36.5t81.5 -40t53.5 -37t31 -27l9 -10v-200q0 -21 -14.5 -33t-34.5 -9l-202 34q-20 3 -34.5 20t-14.5 38v146q-141 24 -300 24t-300 -24v-146q0 -21 -14.5 -38t-34.5 -20l-202 -34q-20 -3 -34.5 9t-14.5 33v200q3 4 9.5 10.5 t31 26t54 37.5t80.5 39.5t109 37.5t141 26.5t175 10.5zM600 795q56 0 97 -9.5t60 -23.5t30 -28t12 -24l1 -10v-50l365 -303q14 -15 24.5 -40t10.5 -45v-212q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v212q0 20 10.5 45t24.5 40l365 303v50 q0 4 1 10.5t12 23t30 29t60 22.5t97 10z" />
|
||||
<glyph unicode="" d="M1100 700l-200 -200h-600l-200 200v500h200v-200h200v200h200v-200h200v200h200v-500zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-12l137 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5 t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M700 1100h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-1000h300v1000q0 41 -29.5 70.5t-70.5 29.5zM1100 800h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-700h300v700q0 41 -29.5 70.5t-70.5 29.5zM400 0h-300v400q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-400z " />
|
||||
<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-100h200v-300h-300v100h200v100h-200v300h300v-100zM900 700v-300l-100 -100h-200v500h200z M700 700v-300h100v300h-100z" />
|
||||
<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 300h-100v200h-100v-200h-100v500h100v-200h100v200h100v-500zM900 700v-300l-100 -100h-200v500h200z M700 700v-300h100v300h-100z" />
|
||||
<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-300h200v-100h-300v500h300v-100zM900 700h-200v-300h200v-100h-300v500h300v-100z" />
|
||||
<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 400l-300 150l300 150v-300zM900 550l-300 -150v300z" />
|
||||
<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM900 300h-700v500h700v-500zM800 700h-130q-38 0 -66.5 -43t-28.5 -108t27 -107t68 -42h130v300zM300 700v-300 h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130z" />
|
||||
<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-100h200v-300h-300v100h200v100h-200v300h300v-100zM900 300h-100v400h-100v100h200v-500z M700 300h-100v100h100v-100z" />
|
||||
<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM300 700h200v-400h-300v500h100v-100zM900 300h-100v400h-100v100h200v-500zM300 600v-200h100v200h-100z M700 300h-100v100h100v-100z" />
|
||||
<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 500l-199 -200h-100v50l199 200v150h-200v100h300v-300zM900 300h-100v400h-100v100h200v-500zM701 300h-100 v100h100v-100z" />
|
||||
<glyph unicode="" d="M600 1191q120 0 229.5 -47t188.5 -126t126 -188.5t47 -229.5t-47 -229.5t-126 -188.5t-188.5 -126t-229.5 -47t-229.5 47t-188.5 126t-126 188.5t-47 229.5t47 229.5t126 188.5t188.5 126t229.5 47zM600 1021q-114 0 -211 -56.5t-153.5 -153.5t-56.5 -211t56.5 -211 t153.5 -153.5t211 -56.5t211 56.5t153.5 153.5t56.5 211t-56.5 211t-153.5 153.5t-211 56.5zM800 700h-300v-200h300v-100h-300l-100 100v200l100 100h300v-100z" />
|
||||
<glyph unicode="" d="M600 1191q120 0 229.5 -47t188.5 -126t126 -188.5t47 -229.5t-47 -229.5t-126 -188.5t-188.5 -126t-229.5 -47t-229.5 47t-188.5 126t-126 188.5t-47 229.5t47 229.5t126 188.5t188.5 126t229.5 47zM600 1021q-114 0 -211 -56.5t-153.5 -153.5t-56.5 -211t56.5 -211 t153.5 -153.5t211 -56.5t211 56.5t153.5 153.5t56.5 211t-56.5 211t-153.5 153.5t-211 56.5zM800 700v-100l-50 -50l100 -100v-50h-100l-100 100h-150v-100h-100v400h300zM500 700v-100h200v100h-200z" />
|
||||
<glyph unicode="" d="M503 1089q110 0 200.5 -59.5t134.5 -156.5q44 14 90 14q120 0 205 -86.5t85 -207t-85 -207t-205 -86.5h-128v250q0 21 -14.5 35.5t-35.5 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-250h-222q-80 0 -136 57.5t-56 136.5q0 69 43 122.5t108 67.5q-2 19 -2 37q0 100 49 185 t134 134t185 49zM525 500h150q10 0 17.5 -7.5t7.5 -17.5v-275h137q21 0 26 -11.5t-8 -27.5l-223 -244q-13 -16 -32 -16t-32 16l-223 244q-13 16 -8 27.5t26 11.5h137v275q0 10 7.5 17.5t17.5 7.5z" />
|
||||
<glyph unicode="" d="M502 1089q110 0 201 -59.5t135 -156.5q43 15 89 15q121 0 206 -86.5t86 -206.5q0 -99 -60 -181t-150 -110l-378 360q-13 16 -31.5 16t-31.5 -16l-381 -365h-9q-79 0 -135.5 57.5t-56.5 136.5q0 69 43 122.5t108 67.5q-2 19 -2 38q0 100 49 184.5t133.5 134t184.5 49.5z M632 467l223 -228q13 -16 8 -27.5t-26 -11.5h-137v-275q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v275h-137q-21 0 -26 11.5t8 27.5q199 204 223 228q19 19 31.5 19t32.5 -19z" />
|
||||
<glyph unicode="" d="M700 100v100h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170l-270 -300h400v-100h-50q-21 0 -35.5 -14.5t-14.5 -35.5v-50h400v50q0 21 -14.5 35.5t-35.5 14.5h-50z" />
|
||||
<glyph unicode="" d="M600 1179q94 0 167.5 -56.5t99.5 -145.5q89 -6 150.5 -71.5t61.5 -155.5q0 -61 -29.5 -112.5t-79.5 -82.5q9 -29 9 -55q0 -74 -52.5 -126.5t-126.5 -52.5q-55 0 -100 30v-251q21 0 35.5 -14.5t14.5 -35.5v-50h-300v50q0 21 14.5 35.5t35.5 14.5v251q-45 -30 -100 -30 q-74 0 -126.5 52.5t-52.5 126.5q0 18 4 38q-47 21 -75.5 65t-28.5 97q0 74 52.5 126.5t126.5 52.5q5 0 23 -2q0 2 -1 10t-1 13q0 116 81.5 197.5t197.5 81.5z" />
|
||||
<glyph unicode="" d="M1010 1010q111 -111 150.5 -260.5t0 -299t-150.5 -260.5q-83 -83 -191.5 -126.5t-218.5 -43.5t-218.5 43.5t-191.5 126.5q-111 111 -150.5 260.5t0 299t150.5 260.5q83 83 191.5 126.5t218.5 43.5t218.5 -43.5t191.5 -126.5zM476 1065q-4 0 -8 -1q-121 -34 -209.5 -122.5 t-122.5 -209.5q-4 -12 2.5 -23t18.5 -14l36 -9q3 -1 7 -1q23 0 29 22q27 96 98 166q70 71 166 98q11 3 17.5 13.5t3.5 22.5l-9 35q-3 13 -14 19q-7 4 -15 4zM512 920q-4 0 -9 -2q-80 -24 -138.5 -82.5t-82.5 -138.5q-4 -13 2 -24t19 -14l34 -9q4 -1 8 -1q22 0 28 21 q18 58 58.5 98.5t97.5 58.5q12 3 18 13.5t3 21.5l-9 35q-3 12 -14 19q-7 4 -15 4zM719.5 719.5q-49.5 49.5 -119.5 49.5t-119.5 -49.5t-49.5 -119.5t49.5 -119.5t119.5 -49.5t119.5 49.5t49.5 119.5t-49.5 119.5zM855 551q-22 0 -28 -21q-18 -58 -58.5 -98.5t-98.5 -57.5 q-11 -4 -17 -14.5t-3 -21.5l9 -35q3 -12 14 -19q7 -4 15 -4q4 0 9 2q80 24 138.5 82.5t82.5 138.5q4 13 -2.5 24t-18.5 14l-34 9q-4 1 -8 1zM1000 515q-23 0 -29 -22q-27 -96 -98 -166q-70 -71 -166 -98q-11 -3 -17.5 -13.5t-3.5 -22.5l9 -35q3 -13 14 -19q7 -4 15 -4 q4 0 8 1q121 34 209.5 122.5t122.5 209.5q4 12 -2.5 23t-18.5 14l-36 9q-3 1 -7 1z" />
|
||||
<glyph unicode="" d="M700 800h300v-380h-180v200h-340v-200h-380v755q0 10 7.5 17.5t17.5 7.5h575v-400zM1000 900h-200v200zM700 300h162l-212 -212l-212 212h162v200h100v-200zM520 0h-395q-10 0 -17.5 7.5t-7.5 17.5v395zM1000 220v-195q0 -10 -7.5 -17.5t-17.5 -7.5h-195z" />
|
||||
<glyph unicode="" d="M700 800h300v-520l-350 350l-550 -550v1095q0 10 7.5 17.5t17.5 7.5h575v-400zM1000 900h-200v200zM862 200h-162v-200h-100v200h-162l212 212zM480 0h-355q-10 0 -17.5 7.5t-7.5 17.5v55h380v-80zM1000 80v-55q0 -10 -7.5 -17.5t-17.5 -7.5h-155v80h180z" />
|
||||
<glyph unicode="" d="M1162 800h-162v-200h100l100 -100h-300v300h-162l212 212zM200 800h200q27 0 40 -2t29.5 -10.5t23.5 -30t7 -57.5h300v-100h-600l-200 -350v450h100q0 36 7 57.5t23.5 30t29.5 10.5t40 2zM800 400h240l-240 -400h-800l300 500h500v-100z" />
|
||||
<glyph unicode="" d="M650 1100h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5zM1000 850v150q41 0 70.5 -29.5t29.5 -70.5v-800 q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-1 0 -20 4l246 246l-326 326v324q0 41 29.5 70.5t70.5 29.5v-150q0 -62 44 -106t106 -44h300q62 0 106 44t44 106zM412 250l-212 -212v162h-200v100h200v162z" />
|
||||
<glyph unicode="" d="M450 1100h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5zM800 850v150q41 0 70.5 -29.5t29.5 -70.5v-500 h-200v-300h200q0 -36 -7 -57.5t-23.5 -30t-29.5 -10.5t-40 -2h-600q-41 0 -70.5 29.5t-29.5 70.5v800q0 41 29.5 70.5t70.5 29.5v-150q0 -62 44 -106t106 -44h300q62 0 106 44t44 106zM1212 250l-212 -212v162h-200v100h200v162z" />
|
||||
<glyph unicode="" d="M658 1197l637 -1104q23 -38 7 -65.5t-60 -27.5h-1276q-44 0 -60 27.5t7 65.5l637 1104q22 39 54 39t54 -39zM704 800h-208q-20 0 -32 -14.5t-8 -34.5l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5zM500 300v-100h200 v100h-200z" />
|
||||
<glyph unicode="" d="M425 1100h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM425 800h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5 t17.5 7.5zM825 800h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM25 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150 q0 10 7.5 17.5t17.5 7.5zM425 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM825 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5 v150q0 10 7.5 17.5t17.5 7.5zM25 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM425 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5 t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM825 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
|
||||
<glyph unicode="" d="M700 1200h100v-200h-100v-100h350q62 0 86.5 -39.5t-3.5 -94.5l-66 -132q-41 -83 -81 -134h-772q-40 51 -81 134l-66 132q-28 55 -3.5 94.5t86.5 39.5h350v100h-100v200h100v100h200v-100zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-12l137 -100 h-950l138 100h-13q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M600 1300q40 0 68.5 -29.5t28.5 -70.5h-194q0 41 28.5 70.5t68.5 29.5zM443 1100h314q18 -37 18 -75q0 -8 -3 -25h328q41 0 44.5 -16.5t-30.5 -38.5l-175 -145h-678l-178 145q-34 22 -29 38.5t46 16.5h328q-3 17 -3 25q0 38 18 75zM250 700h700q21 0 35.5 -14.5 t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-150v-200l275 -200h-950l275 200v200h-150q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M600 1181q75 0 128 -53t53 -128t-53 -128t-128 -53t-128 53t-53 128t53 128t128 53zM602 798h46q34 0 55.5 -28.5t21.5 -86.5q0 -76 39 -183h-324q39 107 39 183q0 58 21.5 86.5t56.5 28.5h45zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13 l138 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M600 1300q47 0 92.5 -53.5t71 -123t25.5 -123.5q0 -78 -55.5 -133.5t-133.5 -55.5t-133.5 55.5t-55.5 133.5q0 62 34 143l144 -143l111 111l-163 163q34 26 63 26zM602 798h46q34 0 55.5 -28.5t21.5 -86.5q0 -76 39 -183h-324q39 107 39 183q0 58 21.5 86.5t56.5 28.5h45 zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13l138 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M600 1200l300 -161v-139h-300q0 -57 18.5 -108t50 -91.5t63 -72t70 -67.5t57.5 -61h-530q-60 83 -90.5 177.5t-30.5 178.5t33 164.5t87.5 139.5t126 96.5t145.5 41.5v-98zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13l138 -100h-950l137 100 h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M600 1300q41 0 70.5 -29.5t29.5 -70.5v-78q46 -26 73 -72t27 -100v-50h-400v50q0 54 27 100t73 72v78q0 41 29.5 70.5t70.5 29.5zM400 800h400q54 0 100 -27t72 -73h-172v-100h200v-100h-200v-100h200v-100h-200v-100h200q0 -83 -58.5 -141.5t-141.5 -58.5h-400 q-83 0 -141.5 58.5t-58.5 141.5v400q0 83 58.5 141.5t141.5 58.5z" />
|
||||
<glyph unicode="" d="M150 1100h900q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5zM125 400h950q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-283l224 -224q13 -13 13 -31.5t-13 -32 t-31.5 -13.5t-31.5 13l-88 88h-524l-87 -88q-13 -13 -32 -13t-32 13.5t-13 32t13 31.5l224 224h-289q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM541 300l-100 -100h324l-100 100h-124z" />
|
||||
<glyph unicode="" d="M200 1100h800q83 0 141.5 -58.5t58.5 -141.5v-200h-100q0 41 -29.5 70.5t-70.5 29.5h-250q-41 0 -70.5 -29.5t-29.5 -70.5h-100q0 41 -29.5 70.5t-70.5 29.5h-250q-41 0 -70.5 -29.5t-29.5 -70.5h-100v200q0 83 58.5 141.5t141.5 58.5zM100 600h1000q41 0 70.5 -29.5 t29.5 -70.5v-300h-1200v300q0 41 29.5 70.5t70.5 29.5zM300 100v-50q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v50h200zM1100 100v-50q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v50h200z" />
|
||||
<glyph unicode="" d="M480 1165l682 -683q31 -31 31 -75.5t-31 -75.5l-131 -131h-481l-517 518q-32 31 -32 75.5t32 75.5l295 296q31 31 75.5 31t76.5 -31zM108 794l342 -342l303 304l-341 341zM250 100h800q21 0 35.5 -14.5t14.5 -35.5v-50h-900v50q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M1057 647l-189 506q-8 19 -27.5 33t-40.5 14h-400q-21 0 -40.5 -14t-27.5 -33l-189 -506q-8 -19 1.5 -33t30.5 -14h625v-150q0 -21 14.5 -35.5t35.5 -14.5t35.5 14.5t14.5 35.5v150h125q21 0 30.5 14t1.5 33zM897 0h-595v50q0 21 14.5 35.5t35.5 14.5h50v50 q0 21 14.5 35.5t35.5 14.5h48v300h200v-300h47q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-50z" />
|
||||
<glyph unicode="" d="M900 800h300v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-375v591l-300 300v84q0 10 7.5 17.5t17.5 7.5h375v-400zM1200 900h-200v200zM400 600h300v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-650q-10 0 -17.5 7.5t-7.5 17.5v950q0 10 7.5 17.5t17.5 7.5h375v-400zM700 700h-200v200z " />
|
||||
<glyph unicode="" d="M484 1095h195q75 0 146 -32.5t124 -86t89.5 -122.5t48.5 -142q18 -14 35 -20q31 -10 64.5 6.5t43.5 48.5q10 34 -15 71q-19 27 -9 43q5 8 12.5 11t19 -1t23.5 -16q41 -44 39 -105q-3 -63 -46 -106.5t-104 -43.5h-62q-7 -55 -35 -117t-56 -100l-39 -234q-3 -20 -20 -34.5 t-38 -14.5h-100q-21 0 -33 14.5t-9 34.5l12 70q-49 -14 -91 -14h-195q-24 0 -65 8l-11 -64q-3 -20 -20 -34.5t-38 -14.5h-100q-21 0 -33 14.5t-9 34.5l26 157q-84 74 -128 175l-159 53q-19 7 -33 26t-14 40v50q0 21 14.5 35.5t35.5 14.5h124q11 87 56 166l-111 95 q-16 14 -12.5 23.5t24.5 9.5h203q116 101 250 101zM675 1000h-250q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h250q10 0 17.5 7.5t7.5 17.5v50q0 10 -7.5 17.5t-17.5 7.5z" />
|
||||
<glyph unicode="" d="M641 900l423 247q19 8 42 2.5t37 -21.5l32 -38q14 -15 12.5 -36t-17.5 -34l-139 -120h-390zM50 1100h106q67 0 103 -17t66 -71l102 -212h823q21 0 35.5 -14.5t14.5 -35.5v-50q0 -21 -14 -40t-33 -26l-737 -132q-23 -4 -40 6t-26 25q-42 67 -100 67h-300q-62 0 -106 44 t-44 106v200q0 62 44 106t106 44zM173 928h-80q-19 0 -28 -14t-9 -35v-56q0 -51 42 -51h134q16 0 21.5 8t5.5 24q0 11 -16 45t-27 51q-18 28 -43 28zM550 727q-32 0 -54.5 -22.5t-22.5 -54.5t22.5 -54.5t54.5 -22.5t54.5 22.5t22.5 54.5t-22.5 54.5t-54.5 22.5zM130 389 l152 130q18 19 34 24t31 -3.5t24.5 -17.5t25.5 -28q28 -35 50.5 -51t48.5 -13l63 5l48 -179q13 -61 -3.5 -97.5t-67.5 -79.5l-80 -69q-47 -40 -109 -35.5t-103 51.5l-130 151q-40 47 -35.5 109.5t51.5 102.5zM380 377l-102 -88q-31 -27 2 -65l37 -43q13 -15 27.5 -19.5 t31.5 6.5l61 53q19 16 14 49q-2 20 -12 56t-17 45q-11 12 -19 14t-23 -8z" />
|
||||
<glyph unicode="" d="M625 1200h150q10 0 17.5 -7.5t7.5 -17.5v-109q79 -33 131 -87.5t53 -128.5q1 -46 -15 -84.5t-39 -61t-46 -38t-39 -21.5l-17 -6q6 0 15 -1.5t35 -9t50 -17.5t53 -30t50 -45t35.5 -64t14.5 -84q0 -59 -11.5 -105.5t-28.5 -76.5t-44 -51t-49.5 -31.5t-54.5 -16t-49.5 -6.5 t-43.5 -1v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-100v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-175q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h75v600h-75q-10 0 -17.5 7.5t-7.5 17.5v150 q0 10 7.5 17.5t17.5 7.5h175v75q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-75h100v75q0 10 7.5 17.5t17.5 7.5zM400 900v-200h263q28 0 48.5 10.5t30 25t15 29t5.5 25.5l1 10q0 4 -0.5 11t-6 24t-15 30t-30 24t-48.5 11h-263zM400 500v-200h363q28 0 48.5 10.5 t30 25t15 29t5.5 25.5l1 10q0 4 -0.5 11t-6 24t-15 30t-30 24t-48.5 11h-363z" />
|
||||
<glyph unicode="" d="M212 1198h780q86 0 147 -61t61 -147v-416q0 -51 -18 -142.5t-36 -157.5l-18 -66q-29 -87 -93.5 -146.5t-146.5 -59.5h-572q-82 0 -147 59t-93 147q-8 28 -20 73t-32 143.5t-20 149.5v416q0 86 61 147t147 61zM600 1045q-70 0 -132.5 -11.5t-105.5 -30.5t-78.5 -41.5 t-57 -45t-36 -41t-20.5 -30.5l-6 -12l156 -243h560l156 243q-2 5 -6 12.5t-20 29.5t-36.5 42t-57 44.5t-79 42t-105 29.5t-132.5 12zM762 703h-157l195 261z" />
|
||||
<glyph unicode="" d="M475 1300h150q103 0 189 -86t86 -189v-500q0 -41 -42 -83t-83 -42h-450q-41 0 -83 42t-42 83v500q0 103 86 189t189 86zM700 300v-225q0 -21 -27 -48t-48 -27h-150q-21 0 -48 27t-27 48v225h300z" />
|
||||
<glyph unicode="" d="M475 1300h96q0 -150 89.5 -239.5t239.5 -89.5v-446q0 -41 -42 -83t-83 -42h-450q-41 0 -83 42t-42 83v500q0 103 86 189t189 86zM700 300v-225q0 -21 -27 -48t-48 -27h-150q-21 0 -48 27t-27 48v225h300z" />
|
||||
<glyph unicode="" d="M1294 767l-638 -283l-378 170l-78 -60v-224l100 -150v-199l-150 148l-150 -149v200l100 150v250q0 4 -0.5 10.5t0 9.5t1 8t3 8t6.5 6l47 40l-147 65l642 283zM1000 380l-350 -166l-350 166v147l350 -165l350 165v-147z" />
|
||||
<glyph unicode="" d="M250 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM650 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM1050 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44z" />
|
||||
<glyph unicode="" d="M550 1100q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM550 700q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM550 300q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44z" />
|
||||
<glyph unicode="" d="M125 1100h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM125 700h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5 t17.5 7.5zM125 300h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
|
||||
<glyph unicode="" d="M350 1200h500q162 0 256 -93.5t94 -256.5v-500q0 -165 -93.5 -257.5t-256.5 -92.5h-500q-165 0 -257.5 92.5t-92.5 257.5v500q0 165 92.5 257.5t257.5 92.5zM900 1000h-600q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h600q41 0 70.5 29.5 t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5zM350 900h500q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -14.5 -35.5t-35.5 -14.5h-500q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 14.5 35.5t35.5 14.5zM400 800v-200h400v200h-400z" />
|
||||
<glyph unicode="" d="M150 1100h1000q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5 t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M650 1187q87 -67 118.5 -156t0 -178t-118.5 -155q-87 66 -118.5 155t0 178t118.5 156zM300 800q124 0 212 -88t88 -212q-124 0 -212 88t-88 212zM1000 800q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM300 500q124 0 212 -88t88 -212q-124 0 -212 88t-88 212z M1000 500q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM700 199v-144q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v142q40 -4 43 -4q17 0 57 6z" />
|
||||
<glyph unicode="" d="M745 878l69 19q25 6 45 -12l298 -295q11 -11 15 -26.5t-2 -30.5q-5 -14 -18 -23.5t-28 -9.5h-8q1 0 1 -13q0 -29 -2 -56t-8.5 -62t-20 -63t-33 -53t-51 -39t-72.5 -14h-146q-184 0 -184 288q0 24 10 47q-20 4 -62 4t-63 -4q11 -24 11 -47q0 -288 -184 -288h-142 q-48 0 -84.5 21t-56 51t-32 71.5t-16 75t-3.5 68.5q0 13 2 13h-7q-15 0 -27.5 9.5t-18.5 23.5q-6 15 -2 30.5t15 25.5l298 296q20 18 46 11l76 -19q20 -5 30.5 -22.5t5.5 -37.5t-22.5 -31t-37.5 -5l-51 12l-182 -193h891l-182 193l-44 -12q-20 -5 -37.5 6t-22.5 31t6 37.5 t31 22.5z" />
|
||||
<glyph unicode="" d="M1200 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-850q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v850h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM500 450h-25q0 15 -4 24.5t-9 14.5t-17 7.5t-20 3t-25 0.5h-100v-425q0 -11 12.5 -17.5t25.5 -7.5h12v-50h-200v50q50 0 50 25v425h-100q-17 0 -25 -0.5t-20 -3t-17 -7.5t-9 -14.5t-4 -24.5h-25v150h500v-150z" />
|
||||
<glyph unicode="" d="M1000 300v50q-25 0 -55 32q-14 14 -25 31t-16 27l-4 11l-289 747h-69l-300 -754q-18 -35 -39 -56q-9 -9 -24.5 -18.5t-26.5 -14.5l-11 -5v-50h273v50q-49 0 -78.5 21.5t-11.5 67.5l69 176h293l61 -166q13 -34 -3.5 -66.5t-55.5 -32.5v-50h312zM412 691l134 342l121 -342 h-255zM1100 150v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5z" />
|
||||
<glyph unicode="" d="M50 1200h1100q21 0 35.5 -14.5t14.5 -35.5v-1100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v1100q0 21 14.5 35.5t35.5 14.5zM611 1118h-70q-13 0 -18 -12l-299 -753q-17 -32 -35 -51q-18 -18 -56 -34q-12 -5 -12 -18v-50q0 -8 5.5 -14t14.5 -6 h273q8 0 14 6t6 14v50q0 8 -6 14t-14 6q-55 0 -71 23q-10 14 0 39l63 163h266l57 -153q11 -31 -6 -55q-12 -17 -36 -17q-8 0 -14 -6t-6 -14v-50q0 -8 6 -14t14 -6h313q8 0 14 6t6 14v50q0 7 -5.5 13t-13.5 7q-17 0 -42 25q-25 27 -40 63h-1l-288 748q-5 12 -19 12zM639 611 h-197l103 264z" />
|
||||
<glyph unicode="" d="M1200 1100h-1200v100h1200v-100zM50 1000h400q21 0 35.5 -14.5t14.5 -35.5v-900q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v900q0 21 14.5 35.5t35.5 14.5zM650 1000h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM700 900v-300h300v300h-300z" />
|
||||
<glyph unicode="" d="M50 1200h400q21 0 35.5 -14.5t14.5 -35.5v-900q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v900q0 21 14.5 35.5t35.5 14.5zM650 700h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5zM700 600v-300h300v300h-300zM1200 0h-1200v100h1200v-100z" />
|
||||
<glyph unicode="" d="M50 1000h400q21 0 35.5 -14.5t14.5 -35.5v-350h100v150q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-150h100v-100h-100v-150q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v150h-100v-350q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5zM700 700v-300h300v300h-300z" />
|
||||
<glyph unicode="" d="M100 0h-100v1200h100v-1200zM250 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM300 1000v-300h300v300h-300zM250 500h900q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M600 1100h150q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-100h450q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h350v100h-150q-21 0 -35.5 14.5 t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h150v100h100v-100zM400 1000v-300h300v300h-300z" />
|
||||
<glyph unicode="" d="M1200 0h-100v1200h100v-1200zM550 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM600 1000v-300h300v300h-300zM50 500h900q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
|
||||
<glyph unicode="" d="M865 565l-494 -494q-23 -23 -41 -23q-14 0 -22 13.5t-8 38.5v1000q0 25 8 38.5t22 13.5q18 0 41 -23l494 -494q14 -14 14 -35t-14 -35z" />
|
||||
<glyph unicode="" d="M335 635l494 494q29 29 50 20.5t21 -49.5v-1000q0 -41 -21 -49.5t-50 20.5l-494 494q-14 14 -14 35t14 35z" />
|
||||
<glyph unicode="" d="M100 900h1000q41 0 49.5 -21t-20.5 -50l-494 -494q-14 -14 -35 -14t-35 14l-494 494q-29 29 -20.5 50t49.5 21z" />
|
||||
<glyph unicode="" d="M635 865l494 -494q29 -29 20.5 -50t-49.5 -21h-1000q-41 0 -49.5 21t20.5 50l494 494q14 14 35 14t35 -14z" />
|
||||
<glyph unicode="" d="M700 741v-182l-692 -323v221l413 193l-413 193v221zM1200 0h-800v200h800v-200z" />
|
||||
<glyph unicode="" d="M1200 900h-200v-100h200v-100h-300v300h200v100h-200v100h300v-300zM0 700h50q0 21 4 37t9.5 26.5t18 17.5t22 11t28.5 5.5t31 2t37 0.5h100v-550q0 -22 -25 -34.5t-50 -13.5l-25 -2v-100h400v100q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v550h100q25 0 37 -0.5t31 -2 t28.5 -5.5t22 -11t18 -17.5t9.5 -26.5t4 -37h50v300h-800v-300z" />
|
||||
<glyph unicode="" d="M800 700h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-100v-550q0 -22 25 -34.5t50 -14.5l25 -1v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v550h-100q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h800v-300zM1100 200h-200v-100h200v-100h-300v300h200v100h-200v100h300v-300z" />
|
||||
<glyph unicode="" d="M701 1098h160q16 0 21 -11t-7 -23l-464 -464l464 -464q12 -12 7 -23t-21 -11h-160q-13 0 -23 9l-471 471q-7 8 -7 18t7 18l471 471q10 9 23 9z" />
|
||||
<glyph unicode="" d="M339 1098h160q13 0 23 -9l471 -471q7 -8 7 -18t-7 -18l-471 -471q-10 -9 -23 -9h-160q-16 0 -21 11t7 23l464 464l-464 464q-12 12 -7 23t21 11z" />
|
||||
<glyph unicode="" d="M1087 882q11 -5 11 -21v-160q0 -13 -9 -23l-471 -471q-8 -7 -18 -7t-18 7l-471 471q-9 10 -9 23v160q0 16 11 21t23 -7l464 -464l464 464q12 12 23 7z" />
|
||||
<glyph unicode="" d="M618 993l471 -471q9 -10 9 -23v-160q0 -16 -11 -21t-23 7l-464 464l-464 -464q-12 -12 -23 -7t-11 21v160q0 13 9 23l471 471q8 7 18 7t18 -7z" />
|
||||
<glyph unicode="" d="M1000 1200q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM450 1000h100q21 0 40 -14t26 -33l79 -194q5 1 16 3q34 6 54 9.5t60 7t65.5 1t61 -10t56.5 -23t42.5 -42t29 -64t5 -92t-19.5 -121.5q-1 -7 -3 -19.5t-11 -50t-20.5 -73t-32.5 -81.5t-46.5 -83t-64 -70 t-82.5 -50q-13 -5 -42 -5t-65.5 2.5t-47.5 2.5q-14 0 -49.5 -3.5t-63 -3.5t-43.5 7q-57 25 -104.5 78.5t-75 111.5t-46.5 112t-26 90l-7 35q-15 63 -18 115t4.5 88.5t26 64t39.5 43.5t52 25.5t58.5 13t62.5 2t59.5 -4.5t55.5 -8l-147 192q-12 18 -5.5 30t27.5 12z" />
|
||||
<glyph unicode="🔑" d="M250 1200h600q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-500l-255 -178q-19 -9 -32 -1t-13 29v650h-150q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM400 1100v-100h300v100h-300z" />
|
||||
<glyph unicode="🚪" d="M250 1200h750q39 0 69.5 -40.5t30.5 -84.5v-933l-700 -117v950l600 125h-700v-1000h-100v1025q0 23 15.5 49t34.5 26zM500 525v-100l100 20v100z" />
|
||||
</font>
|
||||
</defs></svg>
|
After Width: | Height: | Size: 106 KiB |
BIN
content/minari/fonts/glyphicons-halflings-regular.ttf
Normal file
BIN
content/minari/fonts/glyphicons-halflings-regular.woff
Normal file
BIN
content/minari/fonts/glyphicons-halflings-regular.woff2
Normal file
BIN
content/minari/images/0.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
content/minari/images/1.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
content/minari/images/10.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
content/minari/images/11.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
content/minari/images/12.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
content/minari/images/13.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
content/minari/images/14.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
content/minari/images/15.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
content/minari/images/16.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
content/minari/images/17.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
content/minari/images/18.png
Normal file
After Width: | Height: | Size: 16 KiB |