text:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Marat Sharifullin</title>
    <link>//sharifmarat.github.io/</link>
    <description>Recent content on Marat Sharifullin</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Thu, 03 Feb 2022 00:00:00 +0000</lastBuildDate><atom:link href="//sharifmarat.github.io/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Dockerized email</title>
      <link>//sharifmarat.github.io/articles/dockerized_email/</link>
      <pubDate>Thu, 03 Feb 2022 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/dockerized_email/</guid>
      <description>
I&rsquo;ve been running my personal email server for almost 6 years.
The initial setup was on &ldquo;bare metal&rdquo;. Afterwards only little maintenance time was needed.
Recently I decided to reduce number of servers and moved to another provider.
To avoid migrating &ldquo;bare metal&rdquo; setup, I dockerized it. It is still not very easy to use compared to existing solutions, but works for my scale.
</description>
    </item>

    <item>
      <title>Improved way to run cron</title>
      <link>//sharifmarat.github.io/articles/longwarn/</link>
      <pubDate>Thu, 30 Dec 2021 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/longwarn/</guid>
      <description>
Systemd timers is an interesting alternative, but I still prefer crontab over it to run periodic jobs on my servers.
To make it a bit more reliable I just chain a few commands like cronic, longwarn and flock.
</description>
    </item>

    <item>
      <title>Generate gallery from Nextcloud tagged images</title>
      <link>//sharifmarat.github.io/articles/gallery_generator_nextcloud_tags/</link>
      <pubDate>Sat, 03 Jul 2021 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/gallery_generator_nextcloud_tags/</guid>
      <description>
I could not find a way to share or publish tagged Nextcloud images. This seems like a useful feature
in which you can share all images of a person with them. There are a few feature requests on Nextcloud GitHub,
but Nextcloud 21 still does not implement it. I wrote a small shell script to make it possible.
</description>
    </item>

    <item>
      <title>Alternative to Remote Console</title>
      <link>//sharifmarat.github.io/articles/remote_console_alternative/</link>
      <pubDate>Thu, 23 Jul 2020 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/remote_console_alternative/</guid>
      <description>
Not all hosting providers offer a free remote console. It makes it difficult to debug certain issues with grub,
especially when LUKS and/or LVM is used. Rescue mode, on the other hand, is offered. That
removes the need for a remote console in most of the cases.
</description>
    </item>

    <item>
      <title>Using borgbackup with rsync.net</title>
      <link>//sharifmarat.github.io/articles/borgbackup_rsyncnet/</link>
      <pubDate>Thu, 23 Jul 2020 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/borgbackup_rsyncnet/</guid>
      <description>
rsync.net offers cloud backups with ZFS snapshots.
It has very special pricing for borg accounts, as borg takes care of versioning automatically.
</description>
    </item>

    <item>
      <title>Catch of Microsoft Azure Certification</title>
      <link>//sharifmarat.github.io/articles/microsoft_certification/</link>
      <pubDate>Wed, 17 Jun 2020 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/microsoft_certification/</guid>
      <description>
Free vouchers for Azure Certification were offered in our company.
Surprisingly for myself I signed up for the exam. But there is a catch.
</description>
    </item>

    <item>
      <title>Стихи Jan de Bas</title>
      <link>//sharifmarat.github.io/mabsurdation/jan-de-bas/</link>
      <pubDate>Thu, 25 Jul 2019 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/mabsurdation/jan-de-bas/</guid>
      <description>Перевод стихов Jan de Bas c голландского Checkpoint Charlie На боку лежала она
и в кровати вдруг стену
сооружила.
С последним камнем
свет перестал проникать.
Я думал о Берлине
и искал Чекпойнт Чарли.
Когда нашел его я
повернулась ко мне она:
падение стены было окончено.
Спокойной ночи (Welterusten) Он захлопнул книгу.
На тумбу ее положил.
Ночь может наступать.
Она читает чуть дальше
Романы о любви.
Он дышит еще 2 предложения.</description>
    </item>

    <item>
      <title>Хватит писать</title>
      <link>//sharifmarat.github.io/mabsurdation/enough-writing/</link>
      <pubDate>Wed, 08 May 2019 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/mabsurdation/enough-writing/</guid>
      <description></description>
    </item>

    <item>
      <title>Infinite redirect in Firefox</title>
      <link>//sharifmarat.github.io/articles/firefox_redirect/</link>
      <pubDate>Wed, 23 Jan 2019 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/firefox_redirect/</guid>
      <description>
Recently Firefox started to throw an error on some sites that a page was not redirecting properly.
On the internet, people gave recommendations to clear the browser cache and cookies, but it didn&rsquo;t help me.
It turned out that the issue was quite different, but simple.
</description>
    </item>

    <item>
      <title>Большой глаз и Маленький глаз</title>
      <link>//sharifmarat.github.io/mabsurdation/grootoog_en_kleinoog/</link>
      <pubDate>Wed, 23 Jan 2019 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/mabsurdation/grootoog_en_kleinoog/</guid>
      <description>Перевод голландской сказки "Grootoog en Kleinoog" Жили-были два не родных брата. Одного звали Большой глаз, а другого - Маленький глаз. Оба были фермерами. Большой глаз был богат и цедил 12 коров, Маленький глаз был беден и доил только одну корову. Однажды, корова Маленького глаза сорвалась и убежала пастись на участок Большого глаза. Большой глаз пришел к своему брату и сказал: &ldquo;Если твоя корова еще раз придет - я ее зарежу. Можешь в этом не сомневаться&rdquo;.</description>
    </item>

    <item>
      <title>Dual Intel and Nvidia graphics on Void Linux</title>
      <link>//sharifmarat.github.io/articles/void_optimus_nvidia_intel/</link>
      <pubDate>Fri, 11 Jan 2019 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/void_optimus_nvidia_intel/</guid>
      <description>
Nvidia Optimus technology allows seamlessly switch between two graphics cards on a laptop.
An Intel integrated card is used to safe battery life when performance is not needed.
A discrete Nvidia card is turned on for certain applications, like games, mining.
It was a big tricky to setup dual graphics on Void Linux. A few hints below could help you to take advantage
of this technology on Linux.
</description>
    </item>

    <item>
      <title>Нет сну!</title>
      <link>//sharifmarat.github.io/mabsurdation/no-to-sleep/</link>
      <pubDate>Mon, 31 Dec 2018 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/mabsurdation/no-to-sleep/</guid>
      <description>Недавно узнал, что необходимое количество сна для каждого человека определено генами. Есть &ldquo;везунчики&rdquo;, которым можно спать 6 часов вместо 8 (да, обычным людям надо спать по 8 часов). Таких всего где-то 3%.
Если у вас есть raw genetic data, то можно посмотреть на маркер rs121912617. Если у вас (G, G) в положительном направлении, то тогда вы один из 97% людей, которым надо спать по 8 часов. Если есть C, или даже две C, то вам повезло, можете спать меньше и делать больше!</description>
    </item>

    <item>
      <title>Gravity UART CO2 sensor with Raspberry Pi</title>
      <link>//sharifmarat.github.io/articles/co2_gravity_uart_raspberry_pi/</link>
      <pubDate>Sun, 30 Dec 2018 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/co2_gravity_uart_raspberry_pi/</guid>
      <description>
This tutorial explains how to connect Gravity UART MH-Z16 CO2 sensor from DFRobot to Raspberry Pi
and get CO2 readings.
This is a nice NDIR-sensor with a wide range, up to 50000 ppm.
</description>
    </item>

    <item>
      <title>Мусорщикам</title>
      <link>//sharifmarat.github.io/mabsurdation/garbage/</link>
      <pubDate>Sat, 22 Dec 2018 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/mabsurdation/garbage/</guid>
      <description>Хватит обливать людей говном. Договорились на телефонное интервью. Сегодня перед работой. Во время обеда. Забронировал комнату заранее, на другом этаже, подальше от коллег. Перед, осознал, что не успеваю дойти к назначенному времени, как раз буду в лифте. Решил дожидаться звонка на улице. Выбрал место подальше от людей, чтобы не шокировать их своим денежным запросом - не так уж и нужна мне эта новая работа.
В выбранном месте было ветрено, решил поискать место получше.</description>
    </item>

    <item>
      <title>Incorrect user in ACPI script in Void Linux</title>
      <link>//sharifmarat.github.io/articles/void_acpi_user/</link>
      <pubDate>Thu, 20 Dec 2018 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/void_acpi_user/</guid>
      <description>
In previous article Closing laptop lid does not lock screen on Void Linux I
showed how to lock the screen when closing a laptop lid on Void Linux. It required to know a user under which the
mate-session was started. Default ACPI script in Void Linux does not detect correct user.
</description>
    </item>

    <item>
      <title>Fix for touchpad in Void Linux on MacBook Air</title>
      <link>//sharifmarat.github.io/articles/void_mouse_on_mac/</link>
      <pubDate>Wed, 12 Dec 2018 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/void_mouse_on_mac/</guid>
      <description>
Fixing MacBook Air&rsquo;s touchpad (versions 2011-2012) in Void Linux.
</description>
    </item>

    <item>
      <title>История о днях</title>
      <link>//sharifmarat.github.io/mabsurdation/days/</link>
      <pubDate>Thu, 25 Oct 2018 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/mabsurdation/days/</guid>
      <description>По Берлиновским похождениям. Три земных человека прилетели по небу в город, разделенный камнем на две части. С ними было небольшое животное. Это животное постоянно нуждалось в еде. За ним приходилось следить.
В первый день животное умудрилось просочиться в не совсем обычную комнату. Комната эта была под охраной. На входе стоял мелкий Баунс. Несмотря на его размер, не хотелось иметь с ним дело. Три человека позвали 6 других на подмогу. Но похоже, что со входом это не помогло.</description>
    </item>

    <item>
      <title>Опционализация</title>
      <link>//sharifmarat.github.io/mabsurdation/scifi/</link>
      <pubDate>Sat, 01 Sep 2018 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/mabsurdation/scifi/</guid>
      <description>Ответ Алексею на фантастичный вызов I Верхом на велосипеде, быстро кручу педали. Если сбавить темп, то начиню падать с высоты третьего этажа. Люди из домов тянут свои руки ко мне, пытаются схватить. Некоторым не везет и они выпадают из окон. Постоянно слышны хлопки мешков с водой. У меня не получается отлететь от них подальше, дома окружают со всех сторон. Я начинаю уставать, оконные руки все ближе и ближе к моим ногам.</description>
    </item>

    <item>
      <title>Пляжный день</title>
      <link>//sharifmarat.github.io/mabsurdation/day-at-the-beach/</link>
      <pubDate>Sat, 18 Aug 2018 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/mabsurdation/day-at-the-beach/</guid>
      <description>Один глубокий человек пошел на пляж. Это был замечательный пляж с белоснежным песком, удобными креслами в тени зонтов и изумрудной водой.
Человек пошел вдоль берега рассматривая людей, которые наслаждались кто солнцем, а кто морем. На пути ему встретился песочный замок. Человек, не очень долго думая, пнул по замку. &ldquo;Как можно сидеть и играть в песочек, когда проблемы метафизики не решены?!&rdquo; - подумал он.
Пройдя глубже ему встретилась группа детей, играющих с мячом.</description>
    </item>

    <item>
      <title>Откладыватель</title>
      <link>//sharifmarat.github.io/mabsurdation/delay/</link>
      <pubDate>Wed, 18 Jul 2018 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/mabsurdation/delay/</guid>
      <description>Один не очень старый житель города был профессионалом по откладыванию дел, особенно таких, от которых не зависел завтрашний день.
- Почитать скучную книгу? Можно отложить. - Заплатить за газ летом? Отложить. - Приготовить белую еду? Перейти на разноцветную.
Когда этот человек отложил вдох воздуха, то от него остался только гештальт размером с ближлежащий пятиэтажный дом, в котором жил хирург, отложивший операцию этого человека.</description>
    </item>

    <item>
      <title>Чужая станция</title>
      <link>//sharifmarat.github.io/mabsurdation/foreign-station/</link>
      <pubDate>Fri, 29 Jun 2018 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/mabsurdation/foreign-station/</guid>
      <description>Один человек во время поездок в соседний город всегда садился с одной и той же стороны вагона. На промежуточной станции жила его знакомая мышь. Человек регулярно покупал с собой бутерброд в дорогу. Даже не из-за голода, а чтобы бросить крошки своей знакомой.
В один из дней мышки не оказалось на привычном месте. Это так шокировало человека, что он отправился на ее поиски.
Побродив по станции он нашёл хвостик, ушко, лапки, а потом и целую кошку.</description>
    </item>

    <item>
      <title>Утро</title>
      <link>//sharifmarat.github.io/mabsurdation/morning/</link>
      <pubDate>Thu, 21 Jun 2018 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/mabsurdation/morning/</guid>
      <description>Один современный человек каждый будний день ходил на работу. Там ему приходилось работать головой.
Сегодня был особый день, когда работы было на две головы, и он решил прийти пораньше. Проснулся как обычно, но не остался со своими мыслями в кровати - встал сразу же. Покушал, оделся и вышел на улицу.
&ldquo;Начинается дождь, а я без куртки - замерзну. Зайду быстро домой и переоденусь&rdquo;, подумал он. Так и сделал.
Дорога до офиса состяла из нескольких частей: сначала велосипедом, поездом а потом ногами.</description>
    </item>

    <item>
      <title>Ген</title>
      <link>//sharifmarat.github.io/mabsurdation/genes/</link>
      <pubDate>Mon, 18 Jun 2018 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/mabsurdation/genes/</guid>
      <description>Была у меня давняя мечта - поплевать в пробирку и узнать о своих генах. Ровно месяц назад я получил такую пробирку на день рождения. Все больше и больше сервисов, которые предлагают такие услуги. Я воспользовался одним из самых известных - 23andme. На дня получил сообщение, что расшифровка и анализ закончены. Можно погружаться в отчеты.
Один из отчетов рассказывает о неандертальской наследственности. Как раз недавно, был закончен проект расшифровки генома неандертальца. 23andme проверяют насколько гены, каждого из нас, наследуются от неандертальцев.</description>
    </item>

    <item>
      <title>Власть</title>
      <link>//sharifmarat.github.io/mabsurdation/power/</link>
      <pubDate>Fri, 01 Jun 2018 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/mabsurdation/power/</guid>
      <description>Ленина любили все и продолжают полюбовать Сталина очень любили, а потом сильно перестали Маленкова не успели полюбить
Хрущева тепло полюбили, а потом немного забыли К Брежневу любовь застоялась Горбачева почти сразу невзлюбили Ельцина полюбили сразу, а потом с ним танцевали Путина любили все, а потом Трамп.</description>
    </item>

    <item>
      <title>Хватит белой еды</title>
      <link>//sharifmarat.github.io/mabsurdation/no-white-food/</link>
      <pubDate>Thu, 31 May 2018 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/mabsurdation/no-white-food/</guid>
      <description>В честь Сати устроили диету белую Белую капусту ели неспелую Творог утром На обед треску Вечером грудку куриную Редис очищенный Козьего сыра долю львиную Соль Сахар И бурату моцарелой закусывали
Эксперимент показал, что стул белым не стал Да и по всем пунктам невыгоден Желтки выкидывать надо Времени и пакетов расход сильный Да и несладка жизнь без кожуры нектарина
Надоел мне этот спор, пошёл ты Сати к черту со своей однопальцевой игрой.</description>
    </item>

    <item>
      <title>Белая диета</title>
      <link>//sharifmarat.github.io/mabsurdation/white-food/</link>
      <pubDate>Wed, 30 May 2018 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/mabsurdation/white-food/</guid>
      <description>Посвящено Сати Свою жизнь Сати описывал так: &ldquo;Жизнь артиста (в широком смысле этого слова) должна быть упорядоченной.
Мои ежедневные действия: Просыпаюсь в 7:18. Вдохновляюсь с 10:23 до 11:47. Обедаю в 12:11 и выхожу из-за стола в 12:14. Живительная прогулка верхом с 13:19 до 14:53. Следующий приступ вдохновения с 15:12 до 16:07. С 17 до 18:47 все остальное (фехтование, созерцание, неподвижность, посещения, разработка рук, плавание,&hellip;). Ужин накрывают в 19:16 и кончают в 19:20.</description>
    </item>

    <item>
      <title>Closing laptop lid does not lock screen on Void Linux</title>
      <link>//sharifmarat.github.io/articles/void_lock_screen_on_suspend/</link>
      <pubDate>Sat, 10 Feb 2018 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/void_lock_screen_on_suspend/</guid>
      <description>
Void Linux is an amazing operating system which reminded me FreeBSD in Linux world. Many parts were built from scratch,
like runit for init scripts, xbps for package management. And they are minimalistic which makes it
even better. Void uses rolling release to delivers fresh packages on regular basis.
</description>
    </item>

    <item>
      <title>Homework</title>
      <link>//sharifmarat.github.io/articles/homework/</link>
      <pubDate>Sat, 03 Feb 2018 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/homework/</guid>
      <description>
A good friend of mine (let&rsquo;s call him D.) asked if I could help his nephew V. with English essay. He studies in middle school in Russia.
It&rsquo;s not the first time V. did not do his homework. I recommended to copy some examples from google.
It would be at least more useful for him rather than doing nothing. But he said that schoold checks homework for plagiarism. What?!
</description>
    </item>

    <item>
      <title>Map matching 101 - part 1</title>
      <link>//sharifmarat.github.io/articles/mapmatching_101_part_1/</link>
      <pubDate>Thu, 31 Aug 2017 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/mapmatching_101_part_1/</guid>
      <description>
Map matching is an interesting problem which is used in car navigation,
self-driving cars, traffic analysis, map correction and more.
Let&rsquo;s write a simple map matching algorithm in Julia.
</description>
    </item>

    <item>
      <title>Dialogues on size_type vs size_t</title>
      <link>//sharifmarat.github.io/articles/dialogue_on_size_type/</link>
      <pubDate>Thu, 24 Aug 2017 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/dialogue_on_size_type/</guid>
      <description>
It all began, as usual, with a simple yes or no question on how to loop in C++.
Which led to size_type vs size_t discussion and ended with a joke and a bit of assembly.
</description>
    </item>

    <item>
      <title>Eneco or an example of terrible service</title>
      <link>//sharifmarat.github.io/articles/eneco/</link>
      <pubDate>Thu, 03 Aug 2017 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/eneco/</guid>
      <description>
Eneco is one of the biggest energy company in the Netherlands. I&rsquo;ve been using their services
for quite some time. It was alright except phone calls from private numbers with offers to
renew a contract (I bet there is a better way to do it). But recently they sent me a bill
which questions competency of their workers and the company in general.
</description>
    </item>

    <item>
      <title>What will probably kill you</title>
      <link>//sharifmarat.github.io/articles/what_will_probably_kill_you/</link>
      <pubDate>Mon, 31 Jul 2017 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/what_will_probably_kill_you/</guid>
      <description>
Have you ever wondered what is probably going to kill you if you die at certiange age?
Based on data from Statistics Netherlands (or Centraal Bureau voor de Statistiek)
we could try to figure out main cause of death for different age groups.
</description>
    </item>

    <item>
      <title>Flickr Roulette</title>
      <link>//sharifmarat.github.io/articles/flickr_roulette/</link>
      <pubDate>Mon, 24 Jul 2017 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/flickr_roulette/</guid>
      <description>
If you like to browse through random Flickr photos then Flickr Roulette is
the thing you are looking for.
</description>
    </item>

    <item>
      <title>Percolation</title>
      <link>//sharifmarat.github.io/articles/percolation/</link>
      <pubDate>Mon, 17 Jul 2017 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/percolation/</guid>
      <description>
From wikipedia: In physics, chemistry and materials science, percolation
refers to the movement and filtering of fluids through porous materials.
Original problem was described by Broadbent and Hammersley in 1957:
Will the water reach the center of the porous rock when it is submerged under water?
</description>
    </item>

    <item>
      <title>Blocked by Hotmail/Outlook</title>
      <link>//sharifmarat.github.io/articles/blocked_by_hotmail/</link>
      <pubDate>Thu, 22 Jun 2017 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/blocked_by_hotmail/</guid>
      <description>
Today I discovered that Hotmail/Outlook (live.com) does not want to receive my emails.
Outgoing email bounced with error:
host mx1.hotmail.com[65.55.92.168] said: 550 SC-001 (SNT004-MC3F4) Unfortunately, messages from 163.172.218.53 weren&rsquo;t sent.
</description>
    </item>

    <item>
      <title>Real-time Dutch train traffic</title>
      <link>//sharifmarat.github.io/articles/realtime_trains/</link>
      <pubDate>Tue, 23 May 2017 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/realtime_trains/</guid>
      <description>
Following the previous article I reconstructed a &ldquo;real-time&rdquo; train traffic through a single day.
</description>
    </item>

    <item>
      <title>Train data in the Netherlands</title>
      <link>//sharifmarat.github.io/articles/netherlands_trainstations/</link>
      <pubDate>Mon, 22 May 2017 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/netherlands_trainstations/</guid>
      <description>
NS (Nederlandse Spoorwege) is the biggest railway operator in the Netherlands.
Recently I&rsquo;ve found out that that they provide API to share data on trains and
prices. API is very simple but quite limited.
</description>
    </item>

    <item>
      <title>TMUX config</title>
      <link>//sharifmarat.github.io/articles/tmux_config/</link>
      <pubDate>Sun, 21 May 2017 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/tmux_config/</guid>
      <description>
Config of tmux (&ldquo;terminal multiplexer&rdquo; if it makes it easier for you&hellip;) to allow
switching between windows using Alt+number:
</description>
    </item>

    <item>
      <title>MX backup with a friend</title>
      <link>//sharifmarat.github.io/articles/mx_backup_with_friend/</link>
      <pubDate>Fri, 23 Dec 2016 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/mx_backup_with_friend/</guid>
      <description>
You just finished setting up your MX server and everything works fine.
And now you are wondering whether you need a secondary MX server for backups.
Some would say that these days you actually don&rsquo;t need a secondary MX server,
because MTAs (mail transfer agent) queue mail if MX server is down.
In addition a secondary MX server might be abused by spammers.
But just for fun, let&rsquo;s assume you want to have a backup MX server.
And you are lucky enough to have a friend who also runs an MX server which he is willing
to configure as your backup server.
</description>
    </item>

    <item>
      <title>Transmission status from Raspberry Pi 3</title>
      <link>//sharifmarat.github.io/articles/transmission_status_raspberry_pi/</link>
      <pubDate>Sun, 04 Dec 2016 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/transmission_status_raspberry_pi/</guid>
      <description>
I have a transmission client running on Raspberry Pi 3. But what I also wanted is to have
a simple way to check the status of this client with a simple glance.
Raspberry Pi 3 has multiple LEDs on-board.
Luckily, one of them can be easily controlled from a user space.
</description>
    </item>

    <item>
      <title>Dutch with ease</title>
      <link>//sharifmarat.github.io/articles/dutch_with_ease/</link>
      <pubDate>Sun, 18 Sep 2016 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/dutch_with_ease/</guid>
      <description>
I&rsquo;ve just started Dutch With Ease self-study course made by Assimil.
It is a language course designed in France that uses a language known to you to teach you a target language.
Creators claim that you can acquire an average vocabulary of a few thousands words,
gain a command of everyday conversation and reach B2 level in a few months.
I am going to try it.
</description>
    </item>

    <item>
      <title>Dutch challenge</title>
      <link>//sharifmarat.github.io/articles/dutch_challenge/</link>
      <pubDate>Sun, 11 Sep 2016 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/dutch_challenge/</guid>
      <description>
Tomorrow I am starting another challenge with a friend to study Dutch.
Actually it is happening exactly after I invited friends and paid for their luch today,
because I had lost my previous challenge which was to exercise French every day.
</description>
    </item>

    <item>
      <title>Proxemics</title>
      <link>//sharifmarat.github.io/articles/proxemics/</link>
      <pubDate>Sun, 04 Sep 2016 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/proxemics/</guid>
      <description>
It is interesting how personal, intimate, social and public spaces vary depending
on cultural differences. If you experienced living with people from different backgrounds
(for example living in another country) then you probably noticed how different in size these spaces can be.
</description>
    </item>

    <item>
      <title>Italy or NOT whatever works</title>
      <link>//sharifmarat.github.io/articles/italy_or_not_whatever_works/</link>
      <pubDate>Sun, 28 Aug 2016 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/italy_or_not_whatever_works/</guid>
      <description>
Italy is an excellent country to visit.
This time it was a short trip in the Northen Italy including Venice, Bologna, Imola and San-Marino.
Everything is great about this country, except a few things.
</description>
    </item>

    <item>
      <title>Trip to Russia or Uber VS Yandex Taxi</title>
      <link>//sharifmarat.github.io/articles/trip_to_russia/</link>
      <pubDate>Sun, 21 Aug 2016 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/trip_to_russia/</guid>
      <description>
Currently I am traveling in Italy, but I have to post something, because of the yet another challenge where I have to make a post every week.
So I am writing 200 meaningless words from a car.
</description>
    </item>

    <item>
      <title>Duolingo challenge</title>
      <link>//sharifmarat.github.io/articles/duolingo_challenge/</link>
      <pubDate>Sun, 07 Aug 2016 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/duolingo_challenge/</guid>
      <description>
Duolingo is a fun way to learn a langugage. To insipre learning even further we introduced a challenge with friends. The idea is simple. A person who loses a streak on a language fails the challenge. But Duolingo keeps track of global streak only.
</description>
    </item>

    <item>
      <title>Why you should avoid unsigned types in C++</title>
      <link>//sharifmarat.github.io/articles/signed_unsigned_in_cpp/</link>
      <pubDate>Tue, 15 Mar 2016 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/signed_unsigned_in_cpp/</guid>
      <description>
C++ offers signed and unsigned integer types.
This article explains why you should avoid using unsigned types in C++.
</description>
    </item>

    <item>
      <title>Switching from Drupal and Wordpress to Wintersmith</title>
      <link>//sharifmarat.github.io/articles/drupal_wordpress_to_wintersmith/</link>
      <pubDate>Sun, 13 Mar 2016 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/drupal_wordpress_to_wintersmith/</guid>
      <description>
I have been using WordPress and Drupal for a while. It worked well, but recently I have decided to switch to
Wintersmith, static site generator.
</description>
    </item>

    <item>
      <title>Setting up Raspberry Pi 3</title>
      <link>//sharifmarat.github.io/articles/setting_up_raspberry_pi/</link>
      <pubDate>Mon, 07 Mar 2016 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/setting_up_raspberry_pi/</guid>
      <description>
Recently Raspberry Pi Foundation released new version of thier product: Raspberry Pi 3.
It has 64-bit quad-core ARM CPU and integerated wireless LAN. It is great thing to play with and I got it for myself.
</description>
    </item>

    <item>
      <title>Getting admin access for Comtrend VI-3223u router</title>
      <link>//sharifmarat.github.io/articles/router_full_access/</link>
      <pubDate>Wed, 02 Mar 2016 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/articles/router_full_access/</guid>
      <description>
I have got Comtrend VI-3223u router from my ISP. Unfortunaly they do not give you full access to this router.
Recently I have discovered that with limited access you cannot do even simple things like configuring static IP address
in DHCP or setting up parental control. If you are interested how to get full access for this router then this article is for you.
</description>
    </item>

    <item>
      <title>Contact</title>
      <link>//sharifmarat.github.io/contact/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/contact/</guid>
      <description>var lower_bound = 32; //including var upper_bound = 126; //excluding var count = upper_bound - lower_bound; function scramble(str, key, scramble = true) { if (key.length == 0) return str; var scrambled = []; for (var i = 0; i = upper_bound) && it = upper_bound) { c = Math.abs(c) % count + lower_bound; } scrambled.push(String.fromCharCode(c)); } } return scrambled.join(""); } function unscramble(str, key) { return scramble(str, key, false); } var origValues = []; function updateInfo(event) { var key = document.</description>
    </item>

    <item>
      <title>Flickr Roulette</title>
      <link>//sharifmarat.github.io/projects/flickr_roulette/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/projects/flickr_roulette/</guid>
      <description>function jsonFlickrApi(obj) { var p = obj.photos.photo[Math.floor(Math.random() * obj.photos.total)]; var raw_url = "https://farm" + p.farm + ".static.flickr.com/" + p.server + "/"+ p.id + "_" + p.secret + "_b.jpg"; var flickr_url = "https://www.flickr.com/photos/" + p.owner + "/" + p.id; document.getElementById("pic").src = raw_url; document.getElementById("source").innerText = "Check the license " + flickr_url + " before using this photo"; } function reload() { var head = document.getElementsByTagName('head')[0]; var script = document.</description>
    </item>

    <item>
      <title>Percolation</title>
      <link>//sharifmarat.github.io/projects/percolation/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/projects/percolation/</guid>
      <description>Imagine the grid where every pixel is open with some probability p. What is the probability to get from left side of the grid to right via open pixels (site percolation)?

**Result**:  Probability to enable a pixel (0 to 100):  Pixel size: 1 2 4 8 10 20 40  Note: If you want to get an idea of critical percolation threshold (high probability that long-range connectivity occurs), it is possible to run multiple iterations for all probabilities (0 to 100) and calculate how many times long-range connectivity occured.</description>
    </item>

    <item>
      <title>Projects</title>
      <link>//sharifmarat.github.io/projects/all/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>

      <guid>//sharifmarat.github.io/projects/all/</guid>
      <description>Dockerized email Managing my own email server with the following setup. Read here for more details.
Source of the docker image is on GitHub.
Web 1.0 version of Wordle/Lingo Web 1.0 (no react and fancy stuff) clone of wordle/lingo supporting 4 languages:
 English Dutch Russian Tatar  Play here or here.
Sources are on GitHub.
Auto solver is part of the game:
 When the field is empty, click 3 times on DEL, followed by 3 clicks on ENTER.</description>
    </item>

  </channel>
</rss>


text:
package org.apache.jackrabbit.oak.security.authentication.token;

import javax.jcr.AccessDeniedException;

import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.oak.AbstractSecurityTest;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import org.apache.jackrabbit.oak.spi.security.authentication.token.TokenConstants;
import org.apache.jackrabbit.oak.spi.security.authentication.token.TokenInfo;
import org.apache.jackrabbit.oak.util.NodeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.Before;

/**
 * AbstractTokenTest...
 */
public abstract class AbstractTokenTest extends AbstractSecurityTest implements TokenConstants {

    TokenProviderImpl tokenProvider;

    @Before
    public void before() throws Exception {
        super.before();

        root = adminSession.getLatestRoot();
        tokenProvider = new TokenProviderImpl(root,
                getTokenConfig(),
                getUserConfiguration());
    }

    @Override
    public void after() throws Exception {
        try {
            root.refresh();
        } finally {
            super.after();
        }
    }

    ConfigurationParameters getTokenConfig() {
        return ConfigurationParameters.EMPTY;
    }

    @Nullable
    Tree getTokenTree(@NotNull TokenInfo info) {
        String token = info.getToken();
        int pos = token.indexOf('_');
        String nodeId = (pos == -1) ? token : token.substring(0, pos);
        return new IdentifierManager(root).getTree(nodeId);
    }

    @NotNull
    Tree createTokenTree(@NotNull TokenInfo base, @NotNull NodeUtil parent,
                         @NotNull String ntName) throws AccessDeniedException {
        Tree tokenTree = getTokenTree(base);
        Tree tree = parent.addChild("token", ntName).getTree();
        tree.setProperty(tokenTree.getProperty(JcrConstants.JCR_UUID));
        tree.setProperty(tokenTree.getProperty(TOKEN_ATTRIBUTE_KEY));
        tree.setProperty(tokenTree.getProperty(TOKEN_ATTRIBUTE_EXPIRY));
        return tree;
    }
}

redpajama_set_name: RedPajamaGithub


text:
/**
 * @fileoverview 'POJO' for all HTML elements that are required by the ProfileWidget.
 * @author Lukas Vlcek (lvlcek@redhat.com)
 */

goog.provide('org.jboss.profile.widget.ProfileWidgetElements');

goog.require('goog.Disposable');

/**
 * @param {!HTMLDivElement}   avatar_div
 * @param {!HTMLDivElement}   name_div
 * @param {!HTMLDivElement}   contributions_div
 * @param {!HTMLDivElement}   top_collaborators_div
 * @param {!HTMLDivElement}   top_projects_div
 * @constructor
 * @extends {goog.Disposable}
 */
org.jboss.profile.widget.ProfileWidgetElements = function(
	avatar_div, name_div, contributions_div,
	top_collaborators_div, top_projects_div
	) {

	goog.Disposable.call(this);

	/**
	 * @type {!HTMLDivElement}
	 * @private
	 */
	this.avatar_div_ = avatar_div;

	/**
	 * @type {!HTMLDivElement}
	 * @private
	 */
	this.name_div_ = name_div;

	/**
	 * @type {!HTMLDivElement}
	 * @private
	 */
	this.contributions_div_ = contributions_div;

	/**
	 * @type {!HTMLDivElement}
	 * @private
	 */
	this.top_collaborators_div_ = top_collaborators_div;

	/**
	 * @type {!HTMLDivElement}
	 * @private
	 */
	this.top_projects_div_ = top_projects_div;
};
goog.inherits(org.jboss.profile.widget.ProfileWidgetElements, goog.Disposable);

/** @inheritDoc */
org.jboss.profile.widget.ProfileWidgetElements.prototype.disposeInternal = function() {
	org.jboss.profile.widget.ProfileWidgetElements.superClass_.disposeInternal.call(this);
	delete this.avatar_div_;
	delete this.name_div_;
	delete this.contributions_div_;
	delete this.top_collaborators_div_;
	delete this.top_projects_div_;
};

/**
 * Object is valid if all the html elements are defined and not null.
 * @return {boolean}
 */
org.jboss.profile.widget.ProfileWidgetElements.prototype.isValid = function() {
	return goog.isDefAndNotNull(this.avatar_div_)
		&& goog.isDefAndNotNull(this.name_div_)
		&& goog.isDefAndNotNull(this.contributions_div_)
		&& goog.isDefAndNotNull(this.top_collaborators_div_)
		&& goog.isDefAndNotNull(this.top_projects_div_);
};

/** @return {!HTMLDivElement} */
org.jboss.profile.widget.ProfileWidgetElements.prototype.getAvatar_div = function() {
	return this.avatar_div_;
};

/** @return {!HTMLDivElement} */
org.jboss.profile.widget.ProfileWidgetElements.prototype.getName_div = function() {
	return this.name_div_;
};

/** @return {!HTMLDivElement} */
org.jboss.profile.widget.ProfileWidgetElements.prototype.getContributions_div = function() {
	return this.contributions_div_;
};

/** @return {!HTMLDivElement} */
org.jboss.profile.widget.ProfileWidgetElements.prototype.getTop_collaborators_div = function() {
	return this.top_collaborators_div_;
};

/** @return {!HTMLDivElement} */
org.jboss.profile.widget.ProfileWidgetElements.prototype.getTop_projects_div = function() {
	return this.top_projects_div_;
};


text:
package org.jboss.weld.util.bytecode;

import org.jboss.classfilewriter.code.CodeAttribute;

/**
 * utility class for common bytecode operations
 *
 * @author Stuart Douglas
 */
public class BytecodeUtils {

    public static final String VOID_CLASS_DESCRIPTOR = "V";
    public static final String BYTE_CLASS_DESCRIPTOR = "B";
    public static final String CHAR_CLASS_DESCRIPTOR = "C";
    public static final String DOUBLE_CLASS_DESCRIPTOR = "D";
    public static final String FLOAT_CLASS_DESCRIPTOR = "F";
    public static final String INT_CLASS_DESCRIPTOR = "I";
    public static final String LONG_CLASS_DESCRIPTOR = "J";
    public static final String SHORT_CLASS_DESCRIPTOR = "S";
    public static final String BOOLEAN_CLASS_DESCRIPTOR = "Z";

    private static final String TYPE = "TYPE";
    private static final String LJAVA_LANG_CLASS = "Ljava/lang/Class;";

    public static final int ENUM = 0x00004000;
    public static final int ANNOTATION = 0x00002000;

    private BytecodeUtils() {
    }

    /**
     * Adds the correct load instruction based on the type descriptor
     *
     * @param code     the bytecode to add the instruction to
     * @param type     the type of the variable
     * @param variable the variable number
     */
    public static void addLoadInstruction(CodeAttribute code, String type, int variable) {
        char tp = type.charAt(0);
        if (tp != 'L' && tp != '[') {
            // we have a primitive type
            switch (tp) {
                case 'J':
                    code.lload(variable);
                    break;
                case 'D':
                    code.dload(variable);
                    break;
                case 'F':
                    code.fload(variable);
                    break;
                default:
                    code.iload(variable);
            }
        } else {
            code.aload(variable);
        }
    }

    /**
     * Pushes a class type onto the stack from the string representation This can
     * also handle primitives
     *
     * @param b         the bytecode
     * @param classType the type descriptor for the class or primitive to push.
     *                  This will accept both the java.lang.Object form and the
     *                  Ljava/lang/Object; form
     */
    public static void pushClassType(CodeAttribute b, String classType) {
        if (classType.length() != 1) {
            if (classType.startsWith("L") && classType.endsWith(";")) {
                classType = classType.substring(1, classType.length() - 1);
            }
            b.loadClass(classType);
        } else {
            char type = classType.charAt(0);
            switch (type) {
                case 'I':
                    b.getstatic(Integer.class.getName(), TYPE, LJAVA_LANG_CLASS);
                    break;
                case 'J':
                    b.getstatic(Long.class.getName(), TYPE, LJAVA_LANG_CLASS);
                    break;
                case 'S':
                    b.getstatic(Short.class.getName(), TYPE, LJAVA_LANG_CLASS);
                    break;
                case 'F':
                    b.getstatic(Float.class.getName(), TYPE, LJAVA_LANG_CLASS);
                    break;
                case 'D':
                    b.getstatic(Double.class.getName(), TYPE, LJAVA_LANG_CLASS);
                    break;
                case 'B':
                    b.getstatic(Byte.class.getName(), TYPE, LJAVA_LANG_CLASS);
                    break;
                case 'C':
                    b.getstatic(Character.class.getName(), TYPE, LJAVA_LANG_CLASS);
                    break;
                case 'Z':
                    b.getstatic(Boolean.class.getName(), TYPE, LJAVA_LANG_CLASS);
                    break;
                default:
                    throw new RuntimeException("Cannot handle primitive type: " + type);
            }
        }
    }

    public static String getName(String descriptor) {
        if (!descriptor.startsWith("[")) {
            return descriptor.substring(1).substring(0, descriptor.length() - 2);
        }
        return descriptor;
    }

}


text:
package com.socrata.tileserver
package util

import java.nio.charset.StandardCharsets.UTF_8
import java.util.Base64

import com.rojoma.json.v3.io.JsonReader
import com.rojoma.simplearm.v2.ResourceScope
import org.apache.commons.io.IOUtils
import org.velvia.MsgPack

import com.socrata.http.client.{exceptions => _, _}
import com.socrata.testcommon

import RenderProvider.MapTile
import exceptions.FailedRenderException

// scalastyle:off import.grouping, no.whitespace.before.left.bracket
class RenderProviderTest extends TestBase with UnusedSugar {
  val styleInfo = new RequestInfo(Unused, Unused, Unused, Unused, Unused) {
    override val style = Some(Unused: String)
  }

  test("handleResponse unpacks payload") {
    forAll { payload: String =>
      val expected = payload
      val resp = mocks.StringResponse(payload)
      val client = testcommon.mocks.StaticHttpClient(resp)
      val actual = IOUtils.toString(
        RenderProvider(client, Unused).renderPng(Unused, styleInfo), UTF_8)

      actual must equal (expected)
    }
  }

  test("handleResponse fails on non-200 responses") {
    import gen.StatusCodes._

    forAll { (payload: String, sc: NotOkStatusCode) =>
      val expected = FailedRenderException(payload)

      val resp = mocks.StringResponse(payload, sc)
      val client = testcommon.mocks.StaticHttpClient(resp)
      val renderer = RenderProvider(client, Unused)
      val actual =
        the [FailedRenderException] thrownBy renderer.renderPng(Unused, styleInfo)
      actual must equal (expected)
    }
  }

  test("renderPng throws on error") {
    forAll { (tile: MapTile, z: Int, css: String, message: String) =>
      val resp = mocks.ThrowsResponse(message)
      val client = testcommon.mocks.StaticHttpClient(resp)
      val renderer = RenderProvider(client, Unused)

      val info = new RequestInfo(Unused, Unused, Unused, Unused, Unused) {
        override val style = Some(css)
        override val zoom = z
      }

      val actual =
        the [Exception] thrownBy renderer.renderPng(tile, info) // scalastyle:ignore
      actual.getMessage must equal (message)
    }
  }

  test("renderPng passes x-socrata-federation to renderer") {
    def requireFederationHeader(): (SimpleHttpRequest => Response) = { req =>
      val headers = req.builder.headers.map { pair =>
        val (k, v) = pair
        k.toLowerCase -> v
      }.toMap

      headers("x-socrata-federation") must equal ("Honey Badger")
      mocks.StringResponse(Unused)
    }

    val client = testcommon.mocks.StaticHttpClient()
    val info = new RequestInfo(Unused, Unused, Unused, Unused, Unused) {
      override val style = Some(Unused: String)
    }

    val renderer = RenderProvider(client, Unused)
    renderer.renderPng(Unused, info): Unit
  }

  test("renderPng passes x-socrata-requestid to renderer") {
    def requireRequestId(reqId: String): (SimpleHttpRequest => Response) = { req =>
      val headers = req.builder.headers.map { pair =>
        val (k, v) = pair
        k.toLowerCase -> v
      }.toMap

      headers("x-socrata-requestid") must equal (reqId)
      mocks.StringResponse(Unused)
    }

    forAll { reqId: String =>
      val client = testcommon.mocks.StaticHttpClient(requireRequestId(reqId))
      val info = new RequestInfo(Unused, Unused, Unused, Unused, Unused) {
        override val style = Some(Unused: String)
        override val requestId = reqId
      }

      val renderer = RenderProvider(client, Unused)
      renderer.renderPng(Unused, info): Unit
    }
  }
}


text:
import findCountryCode from './findCountryCode';
import findType from './findType';

function getBestHighlightedForm(highlightedValues) {
  const defaultValue = highlightedValues[0].value;
  // collect all other matches
  const bestAttributes = [];
  for (let i = 1; i < highlightedValues.length; ++i) {
    if (highlightedValues[i].matchLevel !== 'none') {
      bestAttributes.push({
        index: i,
        words: highlightedValues[i].matchedWords,
      });
    }
  }
  // no matches in this attribute, retrieve first value
  if (bestAttributes.length === 0) {
    return defaultValue;
  }
  // sort the matches by `desc(words), asc(index)`
  bestAttributes.sort((a, b) => {
    if (a.words > b.words) {
      return -1;
    } else if (a.words < b.words) {
      return 1;
    }
    return a.index - b.index;
  });
  // and append the best match to the first value
  return bestAttributes[0].index === 0
    ? `${defaultValue} (${highlightedValues[bestAttributes[1].index].value})`
    : `${highlightedValues[bestAttributes[0].index].value} (${defaultValue})`;
}

function getBestPostcode(postcodes, highlightedPostcodes) {
  const defaultValue = highlightedPostcodes[0].value;
  // collect all other matches
  const bestAttributes = [];
  for (let i = 1; i < highlightedPostcodes.length; ++i) {
    if (highlightedPostcodes[i].matchLevel !== 'none') {
      bestAttributes.push({
        index: i,
        words: highlightedPostcodes[i].matchedWords,
      });
    }
  }
  // no matches in this attribute, retrieve first value
  if (bestAttributes.length === 0) {
    return { postcode: postcodes[0], highlightedPostcode: defaultValue };
  }
  // sort the matches by `desc(words)`
  bestAttributes.sort((a, b) => {
    if (a.words > b.words) {
      return -1;
    } else if (a.words < b.words) {
      return 1;
    }
    return a.index - b.index;
  });

  const postcode = postcodes[bestAttributes[0].index];
  return {
    postcode,
    highlightedPostcode: highlightedPostcodes[bestAttributes[0].index].value,
  };
}

export default function formatHit({
  formatInputValue,
  hit,
  hitIndex,
  query,
  rawAnswer,
}) {
  try {
    const name = hit.locale_names[0];
    const country = hit.country;
    const administrative =
      hit.administrative && hit.administrative[0] !== name
        ? hit.administrative[0]
        : undefined;
    const city = hit.city && hit.city[0] !== name ? hit.city[0] : undefined;
    const suburb =
      hit.suburb && hit.suburb[0] !== name ? hit.suburb[0] : undefined;

    const county =
      hit.county && hit.county[0] !== name ? hit.county[0] : undefined;

    const { postcode, highlightedPostcode } =
      hit.postcode && hit.postcode.length
        ? getBestPostcode(hit.postcode, hit._highlightResult.postcode)
        : { postcode: undefined, highlightedPostcode: undefined };

    const highlight = {
      name: getBestHighlightedForm(hit._highlightResult.locale_names),
      city: city
        ? getBestHighlightedForm(hit._highlightResult.city)
        : undefined,
      administrative: administrative
        ? getBestHighlightedForm(hit._highlightResult.administrative)
        : undefined,
      country: country ? hit._highlightResult.country.value : undefined,
      suburb: suburb
        ? getBestHighlightedForm(hit._highlightResult.suburb)
        : undefined,
      county: county
        ? getBestHighlightedForm(hit._highlightResult.county)
        : undefined,
      postcode: highlightedPostcode,
    };

    const suggestion = {
      name,
      administrative,
      county,
      city,
      suburb,
      country,
      countryCode: findCountryCode(hit._tags),
      type: findType(hit._tags),
      latlng: {
        lat: hit._geoloc.lat,
        lng: hit._geoloc.lng,
      },
      postcode,
      postcodes: hit.postcode && hit.postcode.length ? hit.postcode : undefined,
    };

    // this is the value to put inside the <input value=
    const value = formatInputValue(suggestion);

    return {
      ...suggestion,
      highlight,
      hit,
      hitIndex,
      query,
      rawAnswer,
      value,
    };
  } catch (e) {
    /* eslint-disable no-console */
    console.error('Could not parse object', hit);
    console.error(e);
    /* eslint-enable no-console */
    return {
      value: 'Could not parse object',
    };
  }
}


text:
<?php
// TODO make person details more secure and integrate with WP user data
class EM_Person extends WP_User{

	function __construct( $person_id = 0, $username = '', $blog_id='' ){
		if( is_array($person_id) ){
			if( array_key_exists('person_id',$person_id) ){
				$person_id = $person_id['person_id'];
			}elseif ( array_key_exists('user_id',$person_id) ){
				$person_id = $person_id['user_id'];
			}else{
				$person_id = $person_id['ID'];
			}
		}elseif( is_object($person_id) && get_class($person_id) == 'WP_User'){
			$person_id = $person_id->ID; //create new object if passed a wp_user
		}
		if($username){
			parent::__construct($person_id, $username);
		}elseif( is_numeric($person_id) && ($person_id <= 0) ){
			$this->data = new stdClass();
			$this->ID = 0;
			$this->display_name = 'Non-Registered User';
			$this->user_email = '';
		}else{
			parent::__construct($person_id);
		}
		$this->phone = wp_kses_data(get_metadata('user', $this->ID, 'dbem_phone', true)); //extra field for EM
		do_action('em_person',$this, $person_id, $username);
	}

	function get_bookings($ids_only = false, $status= false){
		global $wpdb;
		$status_condition = $blog_condition = '';
		if( is_multisite() ){
			if( !is_main_site() ){
				//not the main blog, force single blog search
				$blog_condition = "AND e.blog_id=".get_current_blog_id();
			}elseif(is_main_site() && !get_option('dbem_ms_global_events')){
				$blog_condition = "AND (e.blog_id=".get_current_blog_id().' OR e.blog_id IS NULL)';
			}
		}
		if( is_numeric($status) ){
			$status_condition = " AND booking_status=$status";
		}elseif( EM_Object::array_is_numeric($status) ){
			$status_condition = " AND booking_status IN (".implode(',', $status).")";
		}
		$EM_Booking = em_get_booking(); //empty booking for fields
		$results = $wpdb->get_results("SELECT b.".implode(', b.', array_keys($EM_Booking->fields))." FROM ".EM_BOOKINGS_TABLE." b, ".EM_EVENTS_TABLE." e WHERE e.event_id=b.event_id AND person_id={$this->ID} {$blog_condition} {$status_condition} ORDER BY ".get_option('dbem_bookings_default_orderby','event_start_date')." ".get_option('dbem_bookings_default_order','ASC'),ARRAY_A);
		$bookings = array();
		if($ids_only){
			foreach($results as $booking_data){
				$bookings[] = $booking_data['booking_id'];
			}
			return apply_filters('em_person_get_bookings', $bookings, $this);
		}else{
			foreach($results as $booking_data){
				$bookings[] = em_get_booking($booking_data);
			}
			return apply_filters('em_person_get_bookings', new EM_Bookings($bookings), $this);
		}
	}

	/**
	 * @return EM_Events
	 */
	function get_events(){
		global $wpdb;
		$events = array();
		foreach( $this->get_bookings()->get_bookings() as $EM_Booking ){
			$events[$EM_Booking->event_id] = $EM_Booking->get_event();
		}
		return apply_filters('em_person_get_events', $events);
	}

	function get_bookings_url(){
		if( get_option('dbem_edit_bookings_page') && (!is_admin() || !empty($_REQUEST['is_public'])) ){
			$my_bookings_page = get_permalink(get_option('dbem_edit_bookings_page'));
			$bookings_link = em_add_get_params($my_bookings_page, array('person_id'=>$this->ID, 'event_id'=>null, 'ticket_id'=>null, 'booking_id'=>null), false);
		}else{
			$bookings_link = EM_ADMIN_URL. "&page=events-manager-bookings&person_id=".$this->ID;
		}
		return apply_filters('em_person_get_bookings_url', $bookings_link, $this);
	}

	function display_summary(){
		ob_start();
		$no_user = get_option('dbem_bookings_registration_disable') && $this->ID == get_option('dbem_bookings_registration_user');
		?>

				<?php echo get_avatar($this->ID); ?>

						<?php if( $no_user ): ?>

<?php _e('Name','dbem'); ?> : 	<?php echo $this->get_name(); ?>

						<?php else: ?>

<?php _e('Name','dbem'); ?> : 	<a href="<?php echo $this->get_bookings_url(); ?>"><?php echo $this->get_name(); ?>

						<?php endif; ?>

<?php _e('Email','dbem'); ?> : 	<?php echo $this->user_email; ?>

<?php _e('Phone','dbem'); ?> : 	<?php echo esc_html($this->phone); ?>

		<?php
		return apply_filters('em_person_display_summary', ob_get_clean(), $this);
	}

	function get_name(){
		$full_name = $this->first_name  . " " . $this->last_name ;
		$full_name = wp_kses_data(trim($full_name));
		$name = !empty($full_name) ? $full_name : $this->display_name;
		return apply_filters('em_person_get_name', $name, $this);
	}
}
?>


text:
class ViewType(object):
    """Supports processing files by passing them and supplied attributes
    to a special template processor or a custom implementation (format
    keywords from a dictionary, etc.)
    """
    def __init__(self):
        self.attributes = {}

    def process(self, resource, attributes):
        raise NotImplementedError('Should have implemented a view processor')


text:
<?php

use Gems\Date\Period;
use Gems\Tracker\Engine\FieldsDefinition;
use Gems\Tracker\Model\FieldMaintenanceModel;

/**
 * Parent class for all engines that calculate dates using information
 * from other rounds.
 *
 * @package    Gems
 * @subpackage Tracker
 * @copyright  Copyright (c) 2011 Erasmus MC
 * @license    New BSD License
 * @since      Class available since version 1.4
 */
abstract class Gems_Tracker_Engine_StepEngineAbstract extends \Gems_Tracker_Engine_TrackEngineAbstract
{
    /**
     * Database stored constant value for using an answer in a survey as date source
     */
    const ANSWER_TABLE = 'ans';

    /**
     * Database stored constant value for using an appointment as date source
     */
    const APPOINTMENT_TABLE = 'app';

    /**
     * Database stored constant value for using nothing as a date source
     */
    const NO_TABLE = 'nul';

    /**
     * Database stored constant value for using a track field as date source
     */
    const RESPONDENT_TRACK_TABLE = 'rtr';

    /**
     * Database stored constant value for using a respondent as date source
     */
    const RESPONDENT_TABLE = 'res';

    /**
     * Database stored constant value for using a token as date source
     */
    const TOKEN_TABLE = 'tok';

    /**
     *
     * @var string Class name for creating the round model.
     */
    protected $_roundModelClass = 'MUtil_Model_TableModel';

    /**
     *
     * @var \Gems_User_User
     */
    protected $currentUser;

    /**
     *
     * @var \Zend_Locale
     */
    protected $locale;

    /**
     *
     * @var \Gems_Project_ProjectSettings
     */
    protected $project;

    /**
     * Helper function for default handling of multi options value sets
     *
     * @param \MUtil_Model_ModelAbstract $model
     * @param string $fieldName
     * @param array $options
     * @param array $itemData    The current items data
     * @param boolean True if the update changed values (usually by changed selection lists).
     */
    protected function _applyOptions(\MUtil_Model_ModelAbstract $model, $fieldName, array $options, array &$itemData)
    {
        if ($options) {
            $model->set($fieldName, 'multiOptions', $options);

            if (! array_key_exists($itemData[$fieldName], $options)) {
                // Set the value to the first possible value
                reset($options);
                $itemData[$fieldName] = key($options);

                return true;
            }
        } else {
            $model->del($fieldName, 'label');
        }
        return false;
    }

    /**
     * Returns true if the source uses values from another token.
     *
     * @param string $source The current source
     * @return boolean
     */
    protected function _sourceUsesSurvey($source)
    {
        switch ($source) {
            case self::APPOINTMENT_TABLE:
            case self::NO_TABLE:
            case self::RESPONDENT_TRACK_TABLE:
            case self::RESPONDENT_TABLE:
                return false;

            default:
                return true;
        }
    }

    /**
     * Set the after dates to be listed for this item and the way they are displayed (if at all)
     *
     * @param \MUtil_Model_ModelAbstract $model The round model
     * @param array $itemData    The current items data
     * @param string $language   (ISO) language string
     * @param boolean True if the update changed values (usually by changed selection lists).
     */
    protected function applyDatesValidAfter(\MUtil_Model_ModelAbstract $model, array &$itemData, $language)
    {
        // Set the after date fields that can be chosen for the current values
        $dateOptions = $this->getDateOptionsFor($itemData['gro_valid_after_source'], $itemData['gro_valid_after_id'], $language, true);

        return $this->_applyOptions($model, 'gro_valid_after_field', $dateOptions, $itemData);
    }

    /**
     * Set the for dates to be listed for this item and the way they are displayed (if at all)
     *
     * @param \MUtil_Model_ModelAbstract $model The round model
     * @param array $itemData    The current items data
     * @param string $language   (ISO) language string
     * @param boolean True if the update changed values (usually by changed selection lists).
     */
    protected function applyDatesValidFor(\MUtil_Model_ModelAbstract $model, array &$itemData, $language)
    {
        $dateOptions = $this->getDateOptionsFor($itemData['gro_valid_for_source'], $itemData['gro_valid_for_id'], $language, true);

        if ($itemData['gro_id_round'] == $itemData['gro_valid_for_id']) {
            // Cannot use the valid until of the same round to calculate that valid until
            unset($dateOptions['gto_valid_until']);
        }

        if ($itemData['gro_valid_for_source'] == self::NO_TABLE) {
            $model->del('gro_valid_for_unit', 'label');
            $model->del('gro_valid_for_length', 'label');
        }
        return $this->_applyOptions($model, 'gro_valid_for_field', $dateOptions, $itemData);
    }

    /**
     * Apply respondent relation settings to the round model
     *
     * For respondent surveys, we allow to set a relation, with possible choices:
     *
     *  null => the respondent
     *  0    => undefined (specifiy when assigning)
     *  >0   => the id of the track field of type relation to use
     *
     * @param \MUtil_Model_ModelAbstract $model The round model
     * @param array $itemData    The current items data
     *
     * @return boolean True if the update changed values (usually by changed selection lists).
     */
    protected function applyRespondentRelation(\MUtil_Model_ModelAbstract $model, array &$itemData)
    {
        $model->set('gro_id_survey', 'onchange', 'this.form.submit();');
        if (!empty($itemData['gro_id_survey']) && $model->has('gro_id_relationfield')) {
            $forStaff = $this->tracker->getSurvey($itemData['gro_id_survey'])->isTakenByStaff();
            if (!$forStaff) {
                $empty = array('-1' => $this->_('Patient'));

                $relations = $this->getRespondentRelationFields();
                if (!empty($relations)) {
                    $relations = $empty + $relations;
                    $model->set('gro_id_relationfield', 'label', $this->_('Assigned to'), 'multiOptions', $relations, 'order', 25);
                }
                $model->del('ggp_name');
            } else {
                $model->set('ggp_name', 'label', $this->translateAdapter->_('Assigned to'), 'elementClass', 'Exhibitor', 'order', 25);
                $model->set('gro_id_relationfield', 'elementClass', 'hidden');

                $itemData['ggp_name'] = $this->db->fetchOne('select ggp_name from gems__groups join gems__surveys on ggp_id_group = gsu_id_primary_group and gsu_id_survey = ?', $itemData['gro_id_survey']);
                if (!is_null($itemData['gro_id_relationfield'])) {
                    $itemData['gro_id_relationfield'] = null;
                }
            }
        } else {
            $model->del('gro_id_relationfield', 'label');
            $model->del('ggp_name');
            if ($model->has('gro_id_relationfield')) {
                $itemData['gro_id_relationfield'] = null;
            }
        }
    }

    /**
     * Set the surveys to be listed as valid after choices for this item and the way they are displayed (if at all)
     *
     * @param \MUtil_Model_ModelAbstract $model The round model
     * @param array $itemData    The current items data
     * @param boolean True if the update changed values (usually by changed selection lists).
     */
    abstract protected function applySurveyListValidAfter(\MUtil_Model_ModelAbstract $model, array &$itemData);

    /**
     * Set the surveys to be listed as valid for choices for this item and the way they are displayed (if at all)
     *
     * @param \MUtil_Model_ModelAbstract $model The round model
     * @param array $itemData    The current items data
     * @param boolean True if the update changed values (usually by changed selection lists).
     */
    abstract protected function applySurveyListValidFor(\MUtil_Model_ModelAbstract $model, array &$itemData);

    /**
     *
     * @param \MUtil_Date $startDate
     * @param string $type
     * @param int $period
     * @return \MUtil_Date
     */
    protected function calculateFromDate($startDate, $type, $period)
    {
        return Period::applyPeriod($startDate, $type, $period);
    }

    /**
     *
     * @param \MUtil_Date $startDate
     * @param string $type
     * @param int $period
     * @return \MUtil_Date
     */
    protected function calculateUntilDate($startDate, $type, $period)
    {
        $date = $this->calculateFromDate($startDate, $type, $period);

        if ($date instanceof \MUtil_Date) {
            if (Period::isDateType($type)) {
                // Make sure day based units are valid until the end of the day.
                $date->setTimeToDayEnd();
            }
            return $date;
        }
    }

    /**
     * Check if the token should be enabled / disabled due to conditions
     *
     * @param \Gems_Tracker_Token $token
     * @param array $round
     * @param int   $userId Id of the user who takes the action (for logging)
     * @param \Gems_Tracker_RespondentTrack Current respondent track
     * @return int The number of tokens changed by this code
     */
    protected function checkTokenCondition(\Gems_Tracker_Token $token, $round, $userId, \Gems_Tracker_RespondentTrack $respTrack)
    {
        $skipCode = $this->util->getReceptionCodeLibrary()->getSkipString();

        // Only if we have a condition, the token is not yet completed and
        // receptioncode is ok or skip we evaluate the condition
        if (empty($round['gro_condition']) ||
            $token->isCompleted() ||
            !($token->getReceptionCode()->isSuccess() || $token->getReceptionCode()->getCode() == $skipCode)) {

            return 0;
        }

        $changed   = 0;
        $condition = $this->loader->getConditions()->loadCondition($round['gro_condition']);
        $newStatus = $condition->isRoundValid($token);
        $oldStatus = $token->getReceptionCode()->isSuccess();

        if ($newStatus !== $oldStatus) {
            $changed = 1;
            if ($newStatus == false) {
                $message = $this->_('Skipped by condition %s: %s');
                $newCode = $skipCode;
            } else {
                $message = $this->_('Activated by condition %s: %s');
                $newCode = $this->util->getReceptionCodeLibrary()->getOKString();
            }

            $token->setReceptionCode($newCode,
                    sprintf($message, $condition->getName(), $condition->getRoundDisplay($token->getTrackId(), $token->getRoundId())),
                    $userId);
        }

        return $changed;
    }

    /**
     * Check the valid from and until dates for this token
     *
     * @param \GemS_Tracker_Token $token
     * @param array $round
     * @param int   $userId Id of the user who takes the action (for logging)
     * @param \Gems_Tracker_RespondentTrack Current respondent track
     * @return int 1 if the token has changed
     */
    protected function checkTokenDates($token, $round, $userId, \Gems_Tracker_RespondentTrack $respTrack)
    {
        $skipCode = $this->util->getReceptionCodeLibrary()->getSkipString();

        // Change only not-completed tokens with a positive successcode where at least one date
        // is not set by user input
        if ($token->isCompleted() || !$token->getReceptionCode()->isSuccess() || ($token->isValidFromManual() && $token->isValidUntilManual())) {
            // When a token has a skipcode, due to age being out of limits, changing the date might change the condition
            // For this reason we recalculate the date when it was skipped due to a condition
            if ($token->getReceptionCode()->getCode() == $skipCode && !empty($round['gro_condition'])) {
                // Just continue, code was split for readabitily
            } else {
                return 0;
            }
        }

        if ($token->isValidFromManual()) {
            $validFrom = $token->getValidFrom();
        } else {
            $fromDate  = $this->getValidFromDate(
                    $round['gro_valid_after_source'], $round['gro_valid_after_field'], $round['gro_valid_after_id'], $token, $respTrack
            );
            $validFrom = $this->calculateFromDate(
                    $fromDate, $round['gro_valid_after_unit'], $round['gro_valid_after_length']
            );
        }

        if ($token->isValidUntilManual()) {
            $validUntil = $token->getValidUntil();
        } else {
            $untilDate  = $this->getValidUntilDate(
                    $round['gro_valid_for_source'], $round['gro_valid_for_field'], $round['gro_valid_for_id'], $token, $respTrack, $validFrom
            );
            $validUntil = $this->calculateUntilDate(
                    $untilDate, $round['gro_valid_for_unit'], $round['gro_valid_for_length']
            );
        }

        return $token->setValidFrom($validFrom, $validUntil, $userId);
    }

    /**
     * Check the valid from and until dates in the track starting at a specified token
     *
     * @param \Gems_Tracker_RespondentTrack $respTrack The respondent track to check
     * @param \Gems_Tracker_Token $startToken The token to start at
     * @param int $userId Id of the user who takes the action (for logging)
     * @param \Gems_Tracker_Token $skipToken Optional token to skip in the recalculation
     * @return int The number of tokens changed by this code
     */
    public function checkTokensFrom(\Gems_Tracker_RespondentTrack $respTrack, \Gems_Tracker_Token $startToken, $userId, \Gems_Tracker_Token $skipToken = null)
    {
        // Make sure the rounds are loaded
        $this->_ensureRounds();

        // Make sure the tokens are loaded and linked.
        $respTrack->getTokens();

        // Go
        $changed = 0;
        $token = $startToken;
        while ($token) {
            // \MUtil_Echo::track($token->getTokenId());
            //Only process the token when linked to a round
            $round   = false;
            $changes = 0;
            if (array_key_exists($token->getRoundId(), $this->_rounds)) {
                $round = $this->_rounds[$token->getRoundId()];
            }

            if ($round && $token !== $skipToken) {
                $changes = $this->checkTokenCondition($token, $round, $userId, $respTrack);
                $changes += $this->checkTokenDates($token, $round, $userId, $respTrack);
            }

            // If condition changed and dates changed, we only signal one change
            $changed += min($changes, 1);
            $token = $token->getNextToken();
        }

        return $changed;
    }

    /**
     * Check the valid from and until dates in the track
     *
     * @param \Gems_Tracker_RespondentTrack $respTrack The respondent track to check
     * @param int $userId Id of the user who takes the action (for logging)
     * @return int The number of tokens changed by this code
     */
    public function checkTokensFromStart(\Gems_Tracker_RespondentTrack $respTrack, $userId)
    {
        $token = $respTrack->getFirstToken();
        if ($token instanceof \Gems_Tracker_Token) {
            return $this->checkTokensFrom($respTrack, $respTrack->getFirstToken(), $userId);
        } else {
            return 0;
        }
    }

    /**
     * Changes the display of gro_valid_[after|for]_field into something readable
     *
     * @param mixed $value The value being saved
     * @param boolean $isNew True when a new item is being saved
     * @param string $name The name of the current field
     * @param array $context Optional, the other values being saved
     * @return string The value to use
     */
    public function displayDateCalculation($value, $new, $name, array $context = array())
    {
        $fieldBase = substr($name, 0, -5);  // Strip field
        $validAfter = (bool) strpos($fieldBase, 'after');

        // When always valid, just return nothing
        if ($context[$fieldBase . 'source'] == self::NO_TABLE) return '';

        $fields = $this->getDateOptionsFor(
                $context[$fieldBase . 'source'],
                $context[$fieldBase . 'id'],
                $this->locale->getLanguage(),
                $validAfter
                );

        if (isset($fields[$context[$fieldBase . 'field']])) {
            $field = $fields[$context[$fieldBase . 'field']];
        } else {
            $field = $context[$fieldBase . 'field'];
        }

        if ($context[$fieldBase . 'length'] > 0) {
            $format = $this->_('%s plus %s %s');
        } elseif($context[$fieldBase . 'length'] < 0) {
            $format = $this->_('%s minus %s %s');
        } else {
            $format = $this->_('%s');
        }

        $units = $this->util->getTranslated()->getPeriodUnits();
        if (isset($units[$context[$fieldBase . 'unit']])) {
            $unit = $units[$context[$fieldBase . 'unit']];
        } else {
            $unit = $context[$fieldBase . 'unit'];
        }

        // \MUtil_Echo::track(func_get_args());
        return sprintf($format, $field, abs($context[$fieldBase . 'length']), $unit);
    }

    /**
     * Changes the display of gro_valid_[for|after]_id into something readable
     *
     * Makes it empty when not applicable
     *
     * @param mixed $value The value being saved
     * @param boolean $isNew True when a new item is being saved
     * @param string $name The name of the current field
     * @param array $context Optional, the other values being saved
     * @return string The value to use
     */
    public function displayRoundId($value, $new, $name, array $context = array())
    {
        $fieldSource = substr($name, 0, -2) . 'source';

        if ($this->_sourceUsesSurvey($context[$fieldSource])) {
            return $value;
        }

        return '';
    }

    /**
     * An array of snippet names for displaying the answers to a survey.
     *
     * @return array if string snippet names
     */
    public function getAnswerSnippetNames()
    {
        return array('Tracker_Answers_TrackAnswersModelSnippet');
    }

    /**
     * Returns the date fields selectable using the current source
     *
     * @param string $source The date list source as defined by this object
     * @param int $roundId  Gems round id
     * @param string $language   (ISO) language string
     * @param boolean $validAfter True if it concenrs _valid_after_ dates
     * @return type
     */
    protected function getDateOptionsFor($sourceType, $roundId, $language, $validAfter)
    {
        switch ($sourceType) {
            case self::NO_TABLE:
                return array();

            case self::ANSWER_TABLE:
                if (! isset($this->_rounds[$roundId], $this->_rounds[$roundId]['gro_id_survey'])) {
                    return array();
                }
                $surveyId = $this->_rounds[$roundId]['gro_id_survey'];
                $survey = $this->tracker->getSurvey($surveyId);
                return $survey->getDatesList($language);

            case self::APPOINTMENT_TABLE:
                return $this->_fieldsDefinition->getFieldLabelsOfType(FieldsDefinition::TYPE_APPOINTMENT);

            case self::RESPONDENT_TRACK_TABLE:
                $results = array(
                    'gr2t_start_date' => $this->_('Track start'),
                    'gr2t_end_date'   => $this->_('Track end'),
                    // 'gr2t_created'    => $this->_('Track created'),
                );

                return $results + $this->_fieldsDefinition->getFieldLabelsOfType(array(
                    FieldsDefinition::TYPE_DATE,
                    FieldsDefinition::TYPE_DATETIME,
                    ));

            case self::RESPONDENT_TABLE:
                return [
                    'grs_birthday' => $this->_('Birthday'),
                    'gr2o_created' => $this->_('Respondent created'),
                    /*'gr2o_changed' => $this->_('Respondent changed'),*/
                    ];

            case self::TOKEN_TABLE:
                return array(
                    'gto_valid_from'      => $this->_('Valid from'),
                    'gto_valid_until'     => $this->_('Valid until'),
                    'gto_start_time'      => $this->_('Start time'),
                    'gto_completion_time' => $this->_('Completion date'),
                    );

        }
    }

    /**
     * Get all respondent relation fields
     *
     * Returns an array of field id => field name
     *
     * @return array
     */
    public function getRespondentRelationFields() {
        $fields = array();
        $relationFields = $this->getFieldsOfType('relation');

        if (!empty($relationFields)) {
            $fieldNames = $this->getFieldNames();
            $fieldPrefix = FieldMaintenanceModel::FIELDS_NAME . FieldsDefinition::FIELD_KEY_SEPARATOR;
            foreach ($this->getFieldsOfType('relation') as $key => $field)
            {
                $id = str_replace($fieldPrefix, '', $key);
                $fields[$id] = $fieldNames[$key];
            }
        }

        return $fields;
    }

    /**
     * Returns a model that can be used to retrieve or save the data.
     *
     * @param boolean $detailed Create a model for the display of detailed item data or just a browse table
     * @param string $action The current action
     * @return \MUtil_Model_ModelAbstract
     */
    public function getRoundModel($detailed, $action)
    {
        $model = parent::getRoundModel($detailed, $action);

        // Add information about surveys and groups
        $model->addLeftTable('gems__surveys', array('gro_id_survey' => 'gsu_id_survey'));
        $model->addLeftTable('gems__groups', array('gsu_id_primary_group' => 'ggp_id_group'));
        $model->addLeftTable('gems__track_fields', array('gro_id_relationfield = gtf_id_field'), 'gtf', false);

        $model->addColumn(new \Zend_Db_Expr('COALESCE(gtf_field_name, ggp_name)'), 'ggp_name');
        $model->set('ggp_name', 'label', $this->_('Assigned to'));

        // Reset display order to class specific order
        $model->resetOrder();
        if (! $detailed) {
            $model->set('gro_id_order');
        }
        $model->set('gro_id_track');
        $model->set('gro_id_survey');
        $model->set('gro_round_description');
        if ($detailed) {
            $model->set('gro_id_order');
        }
        $model->set('gro_icon_file');

        // Calculate valid from
        if ($detailed) {
            $html = \MUtil_Html::create()->h4($this->_('Valid from calculation'));
            $model->set('valid_after',
                    'default', $html,
                    'label', ' ',
                    'elementClass', 'html',
                    'value', $html
                    );
        }
        $model->set('gro_valid_after_source',
                'label', $this->_('Date source'),
                'default', self::TOKEN_TABLE,
                'elementClass', 'Radio',
                'escape', false,
                'required', true,
                'onchange', 'this.form.submit();',
                'multiOptions', $this->getSourceList(true, false, false)
                );
        $model->set('gro_valid_after_id',
                'label', $this->_('Round used'),
                'onchange', 'this.form.submit();'
                );

        if ($detailed) {
            $periodUnits = $this->util->getTranslated()->getPeriodUnits();

            $model->set('gro_valid_after_field',
                    'label', $this->_('Date used'),
                    'default', 'gto_valid_from',
                    'onchange', 'this.form.submit();'
                    );
            $model->set('gro_valid_after_length',
                    'label', $this->_('Add to date'),
                    'description', $this->_('Can be negative'),
                    'required', false,
                    'filter', 'Int'
                    );
            $model->set('gro_valid_after_unit',
                    'label', $this->_('Add to date unit'),
                    'multiOptions', $periodUnits
                    );
        } else {
            $model->set('gro_valid_after_source',
                    'label', $this->_('Source'),
                    'tableDisplay', 'small'
                    );
            $model->set('gro_valid_after_id', 'label', $this->_('Round'),
                    'multiOptions', $this->getRoundTranslations(),
                    'tableDisplay', 'small'
                    );
            $model->setOnLoad('gro_valid_after_id', array($this, 'displayRoundId'));
            $model->set('gro_valid_after_field',
                    'label', $this->_('Date calculation'),
                    'tableHeaderDisplay', 'small'
                    );
            $model->setOnLoad('gro_valid_after_field', array($this, 'displayDateCalculation'));
            $model->set('gro_valid_after_length');
            $model->set('gro_valid_after_unit');
        }

        if ($detailed) {
            // Calculate valid until
            $html = \MUtil_Html::create()->h4($this->_('Valid for calculation'));
            $model->set('valid_for',
                    'label', ' ',
                    'default', $html,
                    'elementClass', 'html',
                    'value', $html
                    );
        }

        $model->set('gro_valid_for_source',
                'label', $this->_('Date source'),
                'default', self::TOKEN_TABLE,
                'elementClass', 'Radio',
                'escape', false,
                'required', true,
                'onchange', 'this.form.submit();',
                'multiOptions', $this->getSourceList(false, false, false)
                );
        $model->set('gro_valid_for_id',
                'label', $this->_('Round used'),
                'default', '',
                'onchange', 'this.form.submit();'
                );

        if ($detailed) {
            $model->set('gro_valid_for_field',
                    'label', $this->_('Date used'),
                    'default', 'gto_valid_from',
                    'onchange', 'this.form.submit();'
                    );
            $model->set('gro_valid_for_length',
                    'label', $this->_('Add to date'),
                    'description', $this->_('Can be negative'),
                    'required', false,
                    'default', 2,
                    'filter', 'Int'
                    );
            $model->set('gro_valid_for_unit',
                    'label', $this->_('Add to date unit'),
                    'multiOptions', $periodUnits
                    );

            // Calculate valid until
            $html = \MUtil_Html::create()->h4($this->_('Validity calculation'));
            $model->set('valid_cond',
                        'label', ' ',
                        'default', $html,
                        'elementClass', 'html',
                        'value', $html
            );

            // Continue with last round level items
            $model->set('gro_condition');
            $model->set('condition_display');
            $model->set('gro_active');
            $model->set('gro_changed_event');
        } else {
            $model->set('gro_valid_for_source',
                    'label', $this->_('Source'),
                    'tableDisplay', 'small'
                    );
            $model->set('gro_valid_for_id',
                    'label', $this->_('Round'),
                    'multiOptions', $this->getRoundTranslations(),
                    'tableDisplay', 'small'
                    );
            $model->setOnLoad('gro_valid_for_id', array($this, 'displayRoundId'));
            $model->set('gro_valid_for_field',
                    'label', $this->_('Date calculation'),
                    'tableHeaderDisplay', 'small'
                    );
            $model->setOnLoad('gro_valid_for_field', array($this, 'displayDateCalculation'));
            $model->set('gro_valid_for_length');
            $model->set('gro_valid_for_unit');
        }

        return $model;
    }

    /**
     * Get the display values for rounds
     *
     * @return array roundId => display string
     */
    protected function getRoundTranslations()
    {
        $this->_ensureRounds();

        return \MUtil_Ra::column('gro_id_order', $this->_rounds);
    }

    /**
     * Returns the source choices in an array.
     *
     * @param boolean $validAfter True if it concerns _valid_after_ dates
     * @param boolean $firstRound List for first round
     * @param boolean $detailed   Return extended info
     * @return array source_name => label
     */
    protected function getSourceList($validAfter, $firstRound, $detailed = true)
    {
        if (! ($validAfter || $this->project->isValidUntilRequired())) {
            $results[self::NO_TABLE] = array($this->_('Does not expire'));
        }
        if (! ($validAfter && $firstRound)) {
            $results[self::ANSWER_TABLE] = array($this->_('Answers'), $this->_('Use an answer from a survey.'));
        }
        if ($this->_fieldsDefinition->hasAppointmentFields()) {
            $results[self::APPOINTMENT_TABLE] = array(
                $this->_('Appointment'),
                $this->_('Use an appointment linked to this track.'),
                );
        }
        if (! ($validAfter && $firstRound)) {
            $results[self::TOKEN_TABLE]  = array($this->_('Token'), $this->_('Use a standard token date.'));
        }
        $results[self::RESPONDENT_TRACK_TABLE] = array($this->_('Track'), $this->_('Use a track level date.'));
        $results[self::RESPONDENT_TABLE] = array($this->_('Respondent'), $this->_('Use a respondent level date.'));

        if ($detailed) {
            foreach ($results as $key => $value) {
                if (is_array($value)) {
                    $results[$key] = \MUtil_Html::raw(sprintf('<strong>%s</strong> %s', reset($value), next($value)));
                }
            }
        } else {
            foreach ($results as $key => $value) {
                if (is_array($value)) {
                    $results[$key] = reset($value);
                }
            }
        }

        return $results;
    }

    /**
     * Look up the survey id associated with a round
     *
     * @param int $roundId  Gems round id
     * @return int Gems survey id
     */
    protected function getSurveyId($roundId)
    {
       $this->_ensureRounds();
       if (isset($this->_rounds[$roundId]['gro_id_survey'])) {
           return $this->_rounds[$roundId]['gro_id_survey'];
       }

       throw new \Gems_Exception_Coding("Requested non existing survey id for round $roundId.");
    }

    /**
     * An array of snippet names for deleting a token.
     *
     * @param \Gems_Tracker_Token $token Allows token status dependent delete snippets
     * @return array of string snippet names
     */
    public function getTokenDeleteSnippetNames(\Gems_Tracker_Token $token)
    {
        return array('Token\\DeleteTrackTokenSnippet');
    }

    /**
     * An array of snippet names for editing a token.
     *
     * @param \Gems_Tracker_Token $token Allows token status dependent edit snippets
     * @return array of string snippet names
     */
    public function getTokenEditSnippetNames(\Gems_Tracker_Token $token)
    {
        return array('Token\\EditTrackTokenSnippet');
    }

    /**
     * An array of snippet names for displaying a token
     *
     * @param \Gems_Tracker_Token $token Allows token status dependent show snippets
     * @return array of string snippet names
     */
    public function getTokenShowSnippetNames(\Gems_Tracker_Token $token)
    {
        $output[] = 'Token\\ShowTrackTokenSnippet';

        if ($token->isCompleted() && $this->currentUser->hasPrivilege('pr.token.answers')) {
            $output[] = 'Tracker_Answers_SingleTokenAnswerModelSnippet';
        } elseif ($this->currentUser->hasPrivilege('pr.project.questions')) {
            $output[] = 'Survey\\SurveyQuestionsSnippet';
        }
        return $output;
    }

    /**
     * An array of snippet names for deleting a track.
     *
     * @param \Gems_Tracker_RespondentTrack $respTrack Allows track status dependent edit snippets
     * @return array of string snippet names
     * @deprecated since version 1.7.1 Snippets defined TrackAction
     */
    public function getTrackDeleteSnippetNames(\Gems_Tracker_RespondentTrack $respTrack)
    {
        return array('Tracker\\DeleteTrackSnippet', 'Tracker\\TrackTokenOverviewSnippet');
    }

    /**
     * An array of snippet names for editing a track.
     *
     * @return array of string snippet names
     * @deprecated since version 1.7.1 Snippets defined TrackAction
     */
    public function getTrackCreateSnippetNames()
    {
        return array(
            'Tracker\\ShowTrackUsageSnippet',
            'Tracker\\EditTrackSnippet',
            'Tracker\\TrackUsageTextDetailsSnippet',
            'Tracker\\TrackSurveyOverviewSnippet',
            );
    }

    /**
     * An array of snippet names for editing a track.
     *
     * @param \Gems_Tracker_RespondentTrack $respTrack Allows track status dependent edit snippets
     * @return array of string snippet names
     * @deprecated since version 1.7.1 Snippets defined TrackAction
     */
    public function getTrackEditSnippetNames(\Gems_Tracker_RespondentTrack $respTrack)
    {
        return array(
            'Tracker\\ShowTrackUsageSnippet',
            'Tracker\\EditTrackSnippet',
            'Tracker\\TrackUsageTextDetailsSnippet',
            'Tracker\\TrackSurveyOverviewSnippet',
            );
    }

    /**
     * The track type of this engine
     *
     * @return string 'T' or 'S'
     */
    public function getTrackType()
    {
        return 'T';
    }

    /**
     * Returns the date to use to calculate the ValidFrom if any
     *
     * @param string $fieldSource Source for field from round
     * @param string $fieldName Name from round
     * @param int $prevRoundId Id from round
     * @param \Gems_Tracker_Token $token
     * @param \Gems_Tracker_RespondentTrack $respTrack
     * @return \MUtil_Date date time or null
     */
    abstract protected function getValidFromDate($fieldSource, $fieldName, $prevRoundId, \Gems_Tracker_Token $token, \Gems_Tracker_RespondentTrack $respTrack);

    /**
     * Returns the date to use to calculate the ValidUntil if any
     *
     * @param string $fieldSource Source for field from round
     * @param string $fieldName Name from round
     * @param int $prevRoundId Id from round
     * @param \Gems_Tracker_Token $token
     * @param \Gems_Tracker_RespondentTrack $respTrack
     * @param \MUtil_Date $validFrom The calculated new valid from value
     * @return \MUtil_Date date time or null
     */
    abstract protected function getValidUntilDate($fieldSource, $fieldName, $prevRoundId, \Gems_Tracker_Token $token, \Gems_Tracker_RespondentTrack $respTrack, $validFrom);

    /**
     * True if the user can create this kind of track in TrackMaintenanceAction.
     * False if this type of track is created by specialized user interface actions.
     *
     * Engine level function, should be the same for each class instance.
     *
     * @return boolean
     */
    public function isUserCreatable()
    {
        return true;
    }

    /**
     * The logic to set the display of the valid_X_field date list field.
     *
     * @param \MUtil_Model_ModelAbstract $model The round model
     * @param string $fieldName The valid_X_field to set
     * @param string $source The date list source as defined by this object
     * @param int $roundId Optional a round id
     * @param string $language   (ISO) language string
     * @param boolean $validAfter True if it concerns _valid_after_ dates
     */
    protected function setDateListFor(\MUtil_Model_ModelAbstract $model, $fieldName, $source, $roundId, $language, $validAfter)
    {
        $dateOptions = $this->getDateOptionsFor($source, $roundId, $language, $validAfter);

        switch (count($dateOptions)) {
            case 0:
                $model->del($fieldName, 'label');
                break;
            case 1:
                $model->set($fieldName, 'elementClass', 'exhibitor');
                // Intentional fall through
            default:
                $model->set($fieldName, 'multiOptions', $dateOptions);
                break;
        }
    }

    /**
     * Updates the model to reflect the values for the current item data
     *
     * @param \MUtil_Model_ModelAbstract $model The round model
     * @param array $itemData    The current items data
     * @param string $language   (ISO) language string
     * @param boolean True if the update changed values (usually by changed selection lists).
     */
    public function updateRoundModelToItem(\MUtil_Model_ModelAbstract $model, array &$itemData, $language)
    {
        $this->_ensureRounds();

        // Is this the first token?
        $first  = ! $this->getPreviousRoundId($itemData['gro_id_round'], $itemData['gro_id_order']);

        // Update the current round data
        if (isset($this->_rounds[$itemData['gro_id_round']])) {
            $this->_rounds[$itemData['gro_id_round']] = $itemData + $this->_rounds[$itemData['gro_id_round']];
        } else {
            $this->_rounds[$itemData['gro_id_round']] = $itemData;
        }

        // Default result
        $result = false;

        // VALID AFTER DATE

        if (! $this->_sourceUsesSurvey($itemData['gro_valid_after_source'])) {
            $model->del('gro_valid_after_id', 'label');
        } else {
            // Survey list is independent of the actual chosen source, but not
            // vice versa. So we have to set it now.
            $result = $this->applySurveyListValidAfter($model, $itemData) || $result;
        }

        // Set allowed after sources
        $result = $this->_applyOptions($model, 'gro_valid_after_source', $this->getSourceList(true, $first), $itemData) || $result;

        // Set the after date fields that can be chosen for the current values
        $result = $this->applyDatesValidAfter($model, $itemData, $language) || $result;

        // VALID FOR DATE

        // Display used survey only when appropriate
        if (! $this->_sourceUsesSurvey($itemData['gro_valid_for_source'])) {
            $model->del('gro_valid_for_id', 'label');
        } else {
            // Survey list is indepedent of the actual chosen source, but not
            // vice versa. So we have to set it now.
            $result = $this->applySurveyListValidFor($model, $itemData) || $result;
        }

        // Set allowed for sources
        $result = $this->_applyOptions($model, 'gro_valid_for_source', $this->getSourceList(false, $first), $itemData) || $result;

        // Set the for date fields that can be chosen for the current values
        $result = $this->applyDatesValidFor($model, $itemData, $language) || $result;

        // Apply respondent relation settings
        $result = $this->applyRespondentRelation($model, $itemData) || $result;

        return $result;
    }
}


text:
package org.pentaho.di.core.row.value;

import org.pentaho.di.core.exception.KettleValueException;
import org.pentaho.di.core.row.ValueMetaInterface;

public class ValueMetaBinary extends ValueMetaBase implements ValueMetaInterface {

  public ValueMetaBinary() {
    this( null );
  }

  public ValueMetaBinary( String name ) {
    super( name, ValueMetaInterface.TYPE_BINARY );
  }

  @Override
  public Object getNativeDataType( Object object ) throws KettleValueException {
    return getBinary( object );
  }

  @Override
  public Class<?> getNativeDataTypeClass() throws KettleValueException {
    return byte[].class;
  }
}