Подборка нетривиальных велосипедных фонарей с Kickstarter и не только

За последнее время совершенно не по сезону на Kickstarter появилось сразу несколько светящихся устройств для велосипеда. С другой стороны — готовь сани летом, а телегу — зимой. Поэтому мы решили подготовить небольшую подборку велофонариков.


Обычные фонари можно найти в любом спортивном магазине, а цены начинаются от 100 рублей и могут доходить до 5 — 7 тысяч. Взять хоть Маркет. При этом выглядит они однообразно и скучно. В связи с этим предлагаем посмотреть на не самые простые решения в этой нише.

Начнем с сабжа

NEO — фонарь без батареек, прототип которого уже залежался на полке, по словам создателей проекта.

За это время тестовые образцы поучаствовали в различных испытаниях, в результате которых количество драматических случаях на дорогах уменьшилось на 35%, а 85% опрошенных заявили, что чувствуют себя в большей безопасности.

Энергия, которой хватает на то, чтобы лампочка зажглась, получается за счет вихревых токов, возникающих при вращении аллюминиевого обода.

Еще один «блестящий» проект — Mstick, волшебная палочка, которая может быть использована тысячей разных способов, и один из них — задний фонарь для велосипеда.

Работает под управлением приложений, где можно подобрать индивидуальную анимацию и выбрать желаемый цвет. Ее можно использовать на концертах, на пикнике, в качестве вспышки или миниатюрного варианта цветомузыки.

Небольшой фонарик, слегка не добравший нужной суммы, FAST «обладал интеллектом», увеличивая яркость в темное время суток, при этом среди функций должен был быть «Анти-вор», и если бы кто-то решил оседлать вашего коня, пока вы заходили за хлебом, вы тут же получили бы тревожный сигнал на смартфон.

Интеллектуальный диодный фонарик TurnCycle управлялся дистанционно с помощью специального браслета, который предлагался в комплекте.

В наборе было несколько запрограммированных жестов, которые различал датчик, и на основании их выводил на дисплей информационный сигнал, который указывал на будущее действие велосипедиста.

В нашем каталоге вы можете найти Fly6 — велосипедный фонарь с HD-камерой. Диодный фонарик пишет видео 1280 x 720 в формате AVI, а угол обзора девайса — 130 градусов.

В настоящее время на официальном сайте собирают предзаказы на Fly12 за $259.

Spokenlights — вариант оформления колес диодными узорами. Кроме того, что велосипедист становится заметнее на дороге, сам велосипед выглядит очень привлекательно как целое произведение искусства.

Monocle — сумка-чехол в паре с приложением, которое превращает Iphone в велофонарь. Необычайно простая конструкция на удивление оказалась привлекательна для пользователей, после того, как про нее не то в шутку, не то в серьез, написали известные СМИ. Кампанию, впрочем, это не спасло.

Aqualight — вполне очевидный проект, так как практически каждый велосипедист имеет при себе бутылку воды, поэтому именно в нее решили вмонтировать диодные фонари безопасности.

Phantom Frames — проект рам для детских велосипедов с подстветкой, который не добрал полутора тысяч, однако все-таки запустившийся, и теперь продукцию можно купить в официальном магазине.

Velodroom — интеллектуальный фонарик, который активируется, как только вы начинаете крутить педали и гаснет через минуту после остановки.

Еще один фонарик, который выступает как информационное табло и указывает на скорость, с которой двигается велосипедист — VeloCityLight. Четыре уровня яркости автоматически подстраиваются под уровень естественного освещения.

Nori Lights — один из способов «украсить» диодными световыми элементами. Впрочем, конечно, не единственный. Есть универсальные накладки на раму или отдельные детали для велосипеда от 4id — PowerWrapz.

А для подсветки колес — симпатичные Mini Monkey Light.

К тому же варианту оформления — BikeGlow.

Несмотря на «замкнутый круг» колеса, именно тут развертывается настоящая битва предложений: Radlicht

Revolights:

и т. п.

Одежда и экипировка

Самым очевидным решением кажется не «наращивать» детали велосипеда, а добавить что-то в костюм или экипировку. Специальная одежда со светоотражающими элементами, накладки или шлемы с диодными фонариками представлены в значительном количестве. Брутально выглядит Trail LED — шлем для велосипедистов и мотоциклистов.

Мы скоро привезем в Россию умный шлем для велосипедистов LIVALL Bling, который оснащен микрофоном, подавляющим шум ветра, 3-х осевым акселерометром, Bluetooth динамиком и яркими светодиодами в верхней и задней части шлема. Дистанционный пульт LIVALL Bling Jet поможет вам управлять шлемом и телефоном во время езды, не отвлекаясь от дороги, а крепится он на руль транспортного средства. Ориентировочная РРЦ — ок. $200.

Или еще один, тоже не самый дешевый, велосипедный шлем с подсветкой — Torch, который перекочевал с Kickstarter на официальный сайт и стоит £ 99.

Светящиеся накладки с разной функциональностью от самых простых, типа клипс на плечо от 4id или такой перетяжки на спину или рюкзак — Veglo:

До вполне функциональных. Мне интересным показался замок-лента, который бережет и велосипедиста, и велосипед, который теперь можно оставить на короткое время и отлучиться, за водой, к примеру. Vivid.

Ну и в финале — самый «хулиганский» проект Bikeballs. Тут без комментариев.

Хороших выходных!

ссылка на оригинал статьи http://geektimes.ru/post/265002/

Кадровые перестановки в крупнейших ИТ- и медиакомпаниях России на этой неделе

Прошедшая рабочая неделя (26-30 октября) сопровождалась громкими (и не очень) кадровыми перестановками в крупнейших российских ИТ-компаниях и медиа-ресурсах.

Кто-то покидал компанию со скандалом, кто-то уходил с любовью и ощущением пройденного этапа. А один топ-менеджер, вероятно, всегда говорит только «до свидания» — как в известном произведении про Мэри Поппинс. Он умудрился дважды устроиться и уйти из одной и той же компании.

«Мегамозг» предлагает читателям вспомнить и сделать «коммит» прошедших изменений.

1. Президентом геймдев-компании Game Insight станет её вице-президент по маркетингу и руководитель одной из внутренних студий Road 404 Максим Донских. Нынешний президент Александр Ващенко заявил, что он «искренне рад передать Game Insight в руки Макса» и что покидает команду по семейным обстоятельствам.

2. Директор Price.ru / «Бегун» Алексей Романенков уходит из компании, которая владеет сервисом. Романенков уже второй раз уходит из «Бегуна» — в 2011-2012 годах он руководил компанией в статусе исполняющего обязанности гендиректора. В феврале 2012 года, он ушел из холдинга «Рамблер», который на тот момент владел половиной «Бегуна».

3. Afisha.ru распускает нынешнюю редакцию путеводителей под руководством Дмитрия Беглярова, говорится в сообщении компании. От направления в целом издание не отказывается, но будет пересматривать стратегию его развития.

4. Из «Ведомостей» уходит технический директор Заур Абасмирзоев. Он сообщил об этом на своей странице в Facebook. Абасмирзоев уточнил, что уходит один, команда остается работать: «Решение исключительно моe».

5. Из «Яндекса» ушла Ксения Елкина, вице-президент по развитию Yandex Data Factory и руководитель мастерской стартапов Tolstoy Summer Camp. «Я не успела на раздачу кэша, не собираюсь создавать интернет-компанию, не собираюсь продаваться обратно в Яндекс, но собираюсь повзрослеть», заявила она.

И на десерт – самое громкое увольнение недели за рубежом по версии «Мегамозга»:

Председатель правления норвежского холдинга Telenor Свейн Осер (Svein Aaser) ушел в отставку из-за новой информации о коррупционном скандале, в котором замешан Vimpelcom (бренд «Билайн»). Об этом сообщалось в его заявлении на сайте компании. По данным Bloomberg, его уход с должности инициировало министерство торговли Норвегии.

ссылка на оригинал статьи http://megamozg.ru/post/20798/

Руководство по поиску работы для MDA-специалиста (и немного про метод анализа иерархий, Xcore и Sirius)

Это 4-я статья цикла по разработке, управляемой моделями. В предыдущих статьях мы познакомились с OCL и метамоделями, Eclipse Modeling Framework и Sirius. Сегодня научимся описывать метамодели в текстовой нотации (а не в виде диаграмм как раньше) и познакомимся с табличным представлением моделей в Sirius. Сделаем это на примере кризиса среднего возраста и метода анализа иерархий. Возможно, это пригодится вам при разработке ИИ в играх, при принятии решений или в работе.

Введение

Вообще, я планировал статью про разработку DSL и преобразование моделей. Но мои планы внезапно нарушили мысли о смысле жизни, о том тем ли я вообще занимаюсь.

Самое очевидное, что может при этом сделать специалист по разработке, управляемой моделями, это

  • Выбрать метод, который позволит получить интересующие ответы (раздел 1)
  • Создать метамодель под этот метод (раздел 2)
  • Создать инструмент разработки моделей в соответствии с метамоделью (раздел 3)
  • Создать модель (раздел 4)
  • Profit

Именно этим мы и займемся.

1 Метод анализа иерархий

Меня интересовали следующие вопросы:

  • Чем мне интересно заниматься?
  • Достаточно ли времени я уделяю интересным вещам?
  • Что можно изменить в жизни к лучшему?
  • Не станет ли от этих изменений хуже?

Когда я учился в вузе, для получения ответов на разные вопросы мы использовали метод анализа иерархий. Суть метода следующая.

  1. Вы определяете
    • цель,
    • критерии достижения цели и
    • возможные альтернативы.
  2. Оцениваете значимость критериев.
  3. Оцениваете альтернативы по каждому из критериев.
  4. Рассчитываете приоритеты альтернатив.
  5. Принимаете решение.

Более подробно этот метод описан в книге Томаса Саати «Принятие решений. Метод анализа иерархий» (она легко гуглится). Кстати, в ней много примеров от психологии до мировой экономики.

1.1 Построение иерархии

Итак, в простейшем случае иерархия должна содержать цель, критерии и альтернативы.

Если суммировать все мои вопросы, то, по большому счету, меня интересует стоит ли мне сменить работу. Поэтому цель: выбрать работу.

При выборе работы меня интересует

  • сколько денег я буду зарабатывать,
  • на сколько интересно мне будет этим заниматься,
  • будет ли у меня время на жизнь,
  • карьерные перспективы,
  • смогу ли я бывать на природе или буду видеть солнце и деревья раз в год,
  • на сколько близка мне культура коллег, соседей и остальных людей.

При этом возможны следующие альтернативы:

  • ничего не менять,
  • переехать в Москву,
  • переехать за границу,
  • заняться фрилансом или каким-нибудь предпринимательством.

В соответствии с методом анализа иерархий строится следующая иерархия:

1.2 Оценка критериев

У разных людей при принятии решений могут быть примерно одинаковые критерии. Однако, их значимость может сильно различаться. Кто-то работает в большей степени ради денег, кто-то ради интереса, кому-то просто нравится общаться с коллегами и т.д.

В соответствии со своими приоритетами один человек не раздумывая выберет более денежную работу, а другой – более интересную. Не существует работы, которая по всем критериям подходит абсолютно всем.

Наверное, при принятии решений большинство людей в явной или неявной форме ранжируют критерии от самого значимого до самого незначительного. Последние отбрасывают, а по первым сравнивают возможные альтернативы. На каждую возможную работу они навешивают ярлычок: вот, эта работа более денежная, но не интересная, а эта интересная и коллектив там хороший, но сомнительные карьерные перспективы и т.д.

Если сходу не получается сделать выбор, то человек начинает переоценивать критерии: может быть интерес пока не так важен и в пробке можно лишние два часа постоять, зато там больше зарплата, вот, выплачу ипотеку и займусь чем-то интересным.

Подобные рассуждения могут продолжаться долго, мучительно и без гарантии, что в итоге действительно будет принято оптимальное решение.

В методе анализа иерархий предлагается формальный алгоритм принятия подобных решений: все критерии попарно сравниваются друг с другом по шкале от 1 до 9.

Например, что для меня важнее: интерес или деньги? Интерес важнее, но не сказать, что очень сильно. Если максимальная оценка 9 к 1, то для себя я оцениваю приоритеты как 5 к 1.

Или, например, что важнее: деньги или наличие времени для жизни, хобби? Готов ли я ради дополнительных денег работать в выходные или стоять по два часа в пробках? Я для себя оцениваю значимость этих критериев как 1 к 7.

В итоге заполняется подобная таблица:

Очевидно, что по диагонали всегда будут единицы. Также очевидно, что все оценки будут обратно-симметричны относительно главной диагонали. Например, если я оцениваю значимость «интерес-деньги» как 5 к 1, то значимость «деньги-интерес» будет 1 к 5. Иногда такие матрицы называют обратно-симметричными.

В общем случае, если мы сравниваем N критериев, то необходимо сделать (N*(N-1))/2 сравнений. Казалось бы, всё только усложнилось. Если изначально было 6 критериев, то сейчас целая матрица каких-то чисел. Чтобы снова вернуться к критериям, рассчитаем собственный вектор матрицы. Элементы этого вектора и будут относительной значимостью каждого критерия.

В книге Томаса Саати предлагается несколько упрощенных методов расчета собственного вектора в уме или на бумаге. Мы воспользуемся более точным итеративным алгоритмом:

N = количество критериев m = матрица оценок размерностью NxN eigenvector = вектор размерностью N, заполненный значениями 1/N Повторяем пока eigenvalue не начнет сходиться к определенному значению или пока не сделаем максимально допустимое количество итераций     x = m * eigenvector     eigenvalue = sum(x)     eigenvector = x / eigenvalue 

В итоге получаем следующий вектор:

[ 0,0592; 0,2323; 0,3846; 0,0555; 0,1220; 0,1462 ] 

Наиболее значимый критерий – время (0,3846), наименее значимый – карьера (0,0555).

При парных сравнениях некоторые оценки могут получиться несогласованными. Например, для меня интерес важнее денег, а деньги важнее карьеры. Очевидно, что интерес должен быть существенно важнее карьеры. В данной таблице так и есть. Но если бы оценка для «интерес-карьера» была меньшей или вообще обратной, то мои оценки были бы не согласованы между собой.

Оценить меру этой несогласованности поможет собственное значение матрицы сравнений. Оно равно 6,7048.

Очевидно, что собственное значение пропорционально количеству критериев. Чтобы оценка согласованности не зависела от количества критериев, рассчитывается так называемый индекс согласованности = (собственное значение — N) / (N — 1).

Наконец, чтобы оценка была совсем объективной необходимо разделить данный индекс на усредненный индекс согласованности для случайных матриц. Если полученная величина (отношение согласованности) меньше 0,1000, то парные сравнения можно считать более-менее согласованными. В нашем примере оно равно 0,1137, это значит, что рассчитанным приоритетам можно более-менее доверять.

1.3 Оценка альтернатив

Теперь необходимо сравнить все альтернативы по каждому из критериев.

Например, при переезде в Москву я существенно выиграю в зарплате. Но работа, скорее всего, будет менее интересная, а также будет оставаться меньше времени для жизни. Или при переезде за границу мне придется отказаться от своего языка, подстраиваться под чужие культурные ценности.

По каждому критерию рассчитывается собственный вектор и отношение согласованности.

Полученные собственные векторы записаны в столбцах:

Отношения согласованности по каждому критерию записаны в следующем векторе:

[ 0,0337; 0,0211; 0,1012; 0,1399; 0,1270; 0,9507 ] 

Большинство значений меньше или незначительно превышают 0,1000. Однако для критерия «культура» отношение согласованности получилось очень большое. Это связано с тем, что я неправильно расставил часть оценок. Хотел поставить 7 для «ничего не менять – переехать за границу», потому что жить в родном городе гораздо комфортнее. Но по ошибке поставил 1/7.

1.4 Определение приоритетов альтернатив

Итак, мы оценили критерии, навесили на каждую альтернативу ярлычок: какой вариант более денежный, какой более интересный и т.д. Теперь необходимо оценить альтернативы по всем критериям в сумме. Для этого достаточно умножить матрицу

на вектор

[ 0,0592; 0,2323; 0,3846; 0,0555; 0,1220; 0,1462 ] 

В итоге мы получим следующий вектор:

[ 0,3184; 0,1227; 0,2049; 0,3540 ] 

Это и есть значимости альтернатив относительно достижения цели.

1.5 Принятие решения

Теперь изобразим все рассчитанные значения на следующем рисунке:

В скобках указано отношение согласованности оценок.

Толщина линий пропорциональна приоритетам. Наиболее интересна и перспективна в плане карьеры текущая работа. Фриланс позволил бы больше бывать на природе и больше времени тратить на жизнь. Более денежная работа в Москве и заграницей.

Видно, что Москва совсем отпадает. Заграница чуть лучше, но тоже не очень. Ничего не менять и фриланс примерно на одном уровне.

2 Создание метамодели

Теперь опишем как всё это рисуется и считается.

Сначала необходимо описать метамодель: виды сущностей, которые используются в методе анализа иерархий. Причем, в отличие от предыдущей статьи мы не будем рисовать метамодель в виде диаграммы, а опишем её в текстовой нотации Xcore.

Как и раньше понадобится Eclipse Modeling Tools. Установите Xcore и Sirius.

Вы можете взять либо готовый проект, либо сделать всё самостоятельно. Если самостоятельно, то создайте Xcore-проект. В папке model создайте файл ahp.xcore со следующим содержимым:

@Ecore(nsURI="http://www.example.org/ahp") @GenModel( 	modelName="AHP", 	prefix="AHP", 	editDirectory="/xctest.edit/src-gen", 	editorDirectory="/xctest.editor/src-gen", 	testsDirectory="/xctest.tests/src-gen") package ahp  class Hierarchy { 	contains Goal[1] goal 	contains Criterion[+] criteria 	contains Alternative[2..*] alternatives }  interface Named { 	String[1] name }  class Goal extends Named { }  class Criterion extends Named { }  class Alternative extends Named { } 

Смысл должен быть интуитивно понятен. Мы описали иерархию, которая содержит одну цель, хотя бы один критерий, две или более альтернативы. У всех трёх сущностей есть имя.

После сохранения файла автоматически сформируется Java API для работы с иерархиями в папке src-gen. А также будут созданы 3 дополнительных проекта. Нечто подобное мы уже делали в статье про EMF. Только там было две модели (ecore и genmodel), и генерацию кода мы запускали вручную. Xcore делает это автоматически.

Думаю, что описывать всю метамодель в статье нет смысла, вы можете посмотреть её самостоятельно.

Остановимся только на самых интересных вещах. Xcore в отличие от Ecore позволяет описывать не только структуру модели, но и некоторую логику на Java-подобном языке. Опишем, например, тип данных для хранения оценок. Положительные оценки будем хранить в виде положительных целых чисел. А обратные оценки вида 1/n будем хранить как -n. Мы могли бы хранить оценки в виде строк или в виде действительных чисел, но, наверное, это плохая идея.

При этом нам нужны две функции для преобразования оценок из или в строковое представление. На Xcore это будет выглядеть так:

type Weight wraps int create { 	if (it.matches("\\d+")) { 		Integer.parseInt(it) 	} 	else if (it.matches("1\\s*/\\s*\\d+")) { 		val result = Integer.parseInt(it.replaceFirst("1\\s*/\\s*", "")) 		if (result <= 1) 1 else -result 	} 	else { 		throw new NumberFormatException("The weight must be either n or 1/n") 	} } convert { 	if (it >= 1) { 		it.toString 	} 	else if (it >= -1) { 		"1" 	} 	else { 		"1/" + (-it).toString 	} } 

Xcore позволяет описывать также и относительно сложную логику.

Вот, например, операция расчета приоритетов в иерархии.

class Hierarchy { 	op void updatePriorities() 	{ 		priorities.clear 		inconsistencies.clear  		val mat = new JudgmentMatrix<Criterion>(criteria) 		val criteriaJudgments = judgments.filter(typeof(CriterionJudgment)).filter(cj | cj.goal == goal) 		for (judgment : criteriaJudgments) { 			mat.set(judgment.first, judgment.second, judgment.weight) 		} 		for (criterion : criteria) { 			val GoalCriterionPriority priority = AHPFactory.eINSTANCE.createGoalCriterionPriority 			priority.goal = goal 			priority.criterion = criterion 			priority.value = mat.findEigenvectorElement(criterion) 			priorities.add(priority) 		} 		val goalInconsistency = AHPFactory.eINSTANCE.createGoalInconsistency 		goalInconsistency.goal = goal 		goalInconsistency.value = mat.inconsistency 		inconsistencies.add(goalInconsistency)  		val mat2 = new Matrix(alternatives.size, criteria.size)  		criteria.forEach[criterion, j| 			val mat3 = new JudgmentMatrix<Alternative>(alternatives) 			val alternativeJudgments = judgments.filter(typeof(AlternativeJudgment)).filter(aj | aj.criterion == criterion) 			for (judgment : alternativeJudgments) { 				mat3.set(judgment.first, judgment.second, judgment.weight) 			} 			val criterionInconsistency = AHPFactory.eINSTANCE.createCriterionInconsistency 			criterionInconsistency.criterion = criterion 			criterionInconsistency.value = mat3.inconsistency 			inconsistencies.add(criterionInconsistency)  			alternatives.forEach[alternative, i| 				val CriterionAlternativePriority priority = AHPFactory.eINSTANCE.createCriterionAlternativePriority 				priority.criterion = criterion 				priority.alternative = alternative 				priority.value = mat3.findEigenvectorElement(alternative) 				priorities.add(priority) 				mat2.set(i, j, priority.value) 			] 		] 		 		val mat4 = mat2.multiply(mat.eigenvector) 		alternatives.forEach[alternative, i| 			val GoalAlternativePriority priority = AHPFactory.eINSTANCE.createGoalAlternativePriority 			priority.goal = goal 			priority.alternative = alternative 			priority.value = mat4.get(i) 			priorities.add(priority) 		] 	} } 

Наконец, для Xcore-модели (как и для Ecore-модели) вы можете создать диаграмму классов.

Так выглядит метамодель для метода анализа иерархий. Это максимально упрощенный вариант. А в общем случае, иерархия может содержать более трех уровней (например, у критериев могут быть подкритерии). Матрицы связей между уровнями могут быть разреженными. Оценки могут ставить несколько экспертов, а не один.

3 Разработка инструмента для работы с моделями

Метамодель готова, теперь нужен редактор иерархий и матриц. Наверное, нет смысла подробно описывать как всё это сделано. Если вам это интересно, то можете прочитать предыдущую статью про Sirius и посмотреть готовый проект.

Так выглядит спецификация редактора диаграмм и таблиц:

Так выглядит результирующий редактор:

Совсем декларативно описать редактор иерархий не получилось, пришлось писать расширения на Java. Думаю, стоит остановиться на этом немного подробней. В Sirius есть по крайней мере два варианта расширений: службы (service) и действия (action).

С помощью служб вы можете добавить классам из метамодели некоторые дополнительные операции. Например, следующие две операции соответственно форматируют приоритет и рассчитывают толщину связей между критериями и альтернативами.

public class Service {  	public String toString(Priority priority) { 		return String.format("%.4f", priority.getValue()); 	}  	public int getEdgeWidth(Alternative alternative, EdgeTarget targetView) { 		DSemanticDecorator targetNode = (DSemanticDecorator)targetView; 		Criterion criterion = (Criterion)targetNode.getTarget(); 		Priority priority = alternative.getPriority(criterion); 		return (int) (priority.getValue() * 7); 	} } 

Удобно то, что эти операции вы можете использовать прямо в AQL-выражениях. Однако, вы не можете с их помощью изменять модель.

Для изменения модели нужно использовать Java-действия. Действия в отличие от служб уже не могут вызываться в AQL-выражениях. Их можно запускать, например, через контекстное меню или по нажатию кнопки. Действия можно откатывать с помощью команды Undo.

Пример действия, которое пересчитывает приоритеты в иерархии.

package ahp.design;  import java.util.Collection; import java.util.Iterator; import java.util.Map;  import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.transaction.RecordingCommand; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.sirius.business.api.action.AbstractExternalJavaAction; import org.eclipse.sirius.business.api.session.Session; import org.eclipse.sirius.business.api.session.SessionManager; import org.eclipse.sirius.diagram.DSemanticDiagram;  import ahp.Hierarchy;  public class UpdatePrioritiesAction extends AbstractExternalJavaAction {  	public UpdatePrioritiesAction() { 	}  	@Override 	public boolean canExecute(Collection<? extends EObject> arg0) { 		return true; 	}  	@Override 	public void execute(Collection<? extends EObject> selections, Map<String, Object> parameters) { 		Iterator<? extends EObject> iter = selections.iterator(); 		if (!iter.hasNext()) { 			System.out.println("Selections is empty"); 			return; 		} 		EObject obj = selections.iterator().next(); 		if (!(obj instanceof DSemanticDiagram)) { 			System.out.println("DSemanticDiagram is expected"); 		} 		DSemanticDiagram diagram = (DSemanticDiagram)obj; 		EObject target = diagram.getTarget(); 		if (!(target instanceof Hierarchy)) { 			System.out.println("Hierarchy is expected"); 		} 		Hierarchy hierarchy = (Hierarchy)target;  		Session session = SessionManager.INSTANCE.getSession(target); 		TransactionalEditingDomain ted = session.getTransactionalEditingDomain(); 		RecordingCommand cmd = new RecordingCommand(ted) { 			@Override 			protected void doExecute() { 				hierarchy.updatePriorities(); 			} 		}; 		ted.getCommandStack().execute(cmd); 	}  } 

4 Создание модели

Ну, собственно, свою модель я уже создал и показал выше. Попробуйте взять этот проект и построить свою иерархию.

Profit

После прочтения данной статьи вы должны

  • получить общее представление о методе анализа иерархий,
  • научиться описывать метамодели на языке Xcore,
  • научиться создавать сводные таблицы с помощью Sirius,
  • научиться писать расширения для Sirius на Java.

ссылка на оригинал статьи http://habrahabr.ru/post/269291/

Как выжить рынку веб-студий, повысить продажи и что нового предложить клиенту?

Мое выступление на конференции 1С-Битрикс зимой 2015 года.
Тогда я сделал предположение, что компаниям, которые занимаются веб-разработкой нужно предлагать клиенту нечто большее.
Сам по себе сайт или интернет-магазин уже никому не нужен.
Компаниям нужны лиды, продажи, лояльные клиенты, повышение LTV и NPS.

И тогда на конференции я предложил решение — добавить в спектр услуг веб-разработки услуги консалтинга и интеграции с отделом продаж клиента.
Это означает не просто продать сайт, а сделать исследование, аудит, определить «узкие места» системы продаж и предложить комплексное решение под реальные потребности и проблемы Клиента.

Зачастую решение может лежать вообще не области нового сайта.
Хотя клиент стойко уверен, что ему нужен новый сайт.
А как же часто клиенты ошибаются в своих потребностях и принимают не верные решения.

Клиент может прийти за сайтом, а на самом деле ему нужен Landing Page плюс e-mail маркетинг.
Или у клиента может быть не оптимальная организационная структура отдела продаж и система мотивации и сколько не сгенерируй ему лидов, его продажи от этого не вырастут и он будет винить вас, что вы сделали плохой сайт.

Прошел уже почти год и мое предположение начинает сбываться.
Клиент все меньше и меньше идет просто за сайтом и все больше и больше за конечным результатом в виде лидов, продаж, повторных продаж, повышения LTV и NPS.

ссылка на оригинал статьи http://megamozg.ru/post/20796/

Генерация кода в Go

Перевод статьи Роба Пайка из официального блога Go о автоматической кодогенерации с помощью go generate. Статья немного устарела (была написана перед выходом Go 1.4, в котором и появился go generate), но хорошо объясняет суть работы go generate.

Одно из свойств теории вычислимости — полнота по Тьюрингу — заключается в том, что программа может написать другую программу. Это мощная идея, которая не настолько оценена, как того заслуживает, хотя и встречается достаточно часто. Это достаточно весомая часть определения того, что делают компиляторы, например. Также, команда go test работает тоже по такому же принципу: она сканирует пакеты, которые нужно тестировать, создаёт новую Go программу, в которой дописан необходимый обвес для тестов, затем компилирует и запускает её. Современные компьютеры настолько быстры, что такая, казалось бы, дорогая последовательность действий исполняется за доли секунды.

Вокруг есть масса других примеров, когда программы пишут программы. Yacc, к примеру, читает описание грамматики и выдаёт программу, которая парсит эту грамматику. «Компилятор» Protocol Buffers читает описание интерфейса и выдает определения структур, методов и прочего кода. Разнообразные утилиты конфигурации работают похожим образом тоже, извлекая метаданные из среды окружения и создавая кастомные команды запуска.

Таким образом, программы, пишущие программы являются важным элементом в разработке ПО, но программы вроде Yacc, которые создают исходный код, должны быть интегрированы в процесс сборки, чтобы их вывод мог быть передан компилятору. Когда используется внешняя система сборки, вроде Make, это обычно просто сделать. Но в Go, в котором утилита go получает всю необходимую информацию о билде из исходных кодов, это проблема. В нём просто нет механизма, чтобы запустить Yacc с помощью go tool.

До этого момента, в смысле.

Последний релиз Go, 1.4, включает в себя новую команду, go generate, которая позволяет запускать подобные утилиты. Она называется go generate, и при запуске сканирует код на наличие специальных комментариев, которые указывают, какие команды нужно запускать. Важно понимать, что go generate не является частью go build. Она не анализирует зависимости и должна быть запущена до go build. Она предназначена для автора Go пакета, а не для его пользователей.

Команда go generate очень проста в использовании. Для разминки, вот как её использовать, чтобы сгенерировать Yacc грамматику. Скажем, у вас есть входной Yacc-файл, называющийся gopher.y, который определяет грамматику вашего нового языка. Чтобы сгенерировать код на Go, который будет парсить эту грамматику, вы обычно запустили бы стандартную Go-версию yacc, как-нибудь так:

go tool yacc -o gopher.go -p parser gopher.y

Опция -o тут указывает имя результирующего файла, а -p — имя пакета.

Чтобы переложить этот процесс на go generate, нужно в любом обычном (не автосгенерированном) .go файле в этой директории добавить вот такой комментарий:
//go:generate go tool yacc -o gopher.go -p parser gopher.y

Этот текст это та же самая команда, но с добавленным вначале комментарием, который распознает go generate. Комментарий должен начинаться в начале строки и не иметь пробелов между // и go:generate. После этого маркера, оставшаяся часть указывает, какую команду go generate должен запускать.

А теперь запустите её. Перейдите в исходную директорию и запустите go generate, затем go build и так далее:

$ cd $GOPATH/myrepo/gopher $ go generate $ go build $ go test

И это всё, что нужно. Если нет никаких ошибок, то go generate вызовет yacc, который создаст gopher.go, на этом моменте директория будет содержать все необходимые go-файлы, которые мы можем собирать, тестировать и нормально с ними работать. Каждый раз, когда gopher.y меняется, просто перезапустите go generate, чтобы пересоздать парсер.

Если вам интересно больше деталей о том, как go generate работает внутри, включая параметры, переменные окружения и так далее, смотрите документ с описанием дизайна.

Go generate не делает ничего, что не могло бы быть сделано с помощью Make или другого механизма сборки, но он идёт из коробки в команде go — не нужно ничего устанавливать дополнительно — и он хорошо вписывается в экосистему Go. Главное, помните, что это для авторов пакета, не для пользователей, хотя бы из соображений того, что программа, которая будет вызываться, может отсутствовать на машине пользователя. Также, если пакет предполагается использоваться с go get, не забывайте внести сгенерированные файлы в систему контроля версий, сделав доступными для пользователей.

Теперь, давайте посмотрим, как можно использовать это для чего-то нового. В качестве радикально иного примера, где go generate может помочь, в репозитории golang.org/x/tools есть новая программа stringer. Она автоматически генерирует строковые методы String() для наборов числовых констант. Она не входит в стандартный набор Go, но её легко установить:

$ go get golang.org/x/tools/cmd/stringer

Вот пример из документации к stringer. Представьте, что у нас есть некоторый код, с набором числовых констант, определяющих разные типы лекарств:

package painkiller  type Pill int  const (     Placebo Pill = iota     Aspirin     Ibuprofen     Paracetamol     Acetaminophen = Paracetamol )

Для отладочных целей, мы хотели бы, чтобы эти константы могли красиво отдавать своё название, другими словами, мы хотим метод со следующей сигнатурой:

func (p Pill) String() string

Его легко написать вручную, например как-то так:

func (p Pill) String() string {     switch p {     case Placebo:         return "Placebo"     case Aspirin:         return "Aspirin"     case Ibuprofen:         return "Ibuprofen"     case Paracetamol: // == Acetaminophen         return "Paracetamol"     }     return fmt.Sprintf("Pill(%d)", p) }

Есть несколько способов написать эту функцию, разумеется. Мы можем использовать слайс строк, индексированный по Pill, или map, или какую-нибудь другую технику. Так или иначе, мы должны поддерживать его каждый раз, когда мы меняем набор лекарств, и мы должны проверять, что код правильный. (Два разных названия для парацетамола, к примеру, делают этот код чуть более мудрёным, чем он мог бы быть). Плюс, сам вопрос выбора способа реализации зависит от типов значений: знаковое или беззнаковое, плотное и разбросанное, начинающиеся с нуля или нет и так далее.

Программа stringer берёт эти заботы на себя. Хотя она может запускаться и вручную, но она предназначена для запуска через go generate. Чтобы использовать её, добавьте комментарий в исходник, скорее всего, в коде с определением типа:
//go:generate stringer -type=Pill
Это правило указывает, что go generate должна запустить команду stringer, чтобы сгенерировать метод String для типа Pill. Вывод автоматически будет записан в файл pill_string.go (вывод может быть переопределён с помощью флага -output).

Давайте запустим её:

$ go generate $ cat pill_string.go // generated by stringer -type Pill pill.go; DO NOT EDIT  package pill  import "fmt"  const _Pill_name = "PlaceboAspirinIbuprofenParacetamol"  var _Pill_index = [...]uint8{0, 7, 14, 23, 34}  func (i Pill) String() string {     if i < 0 || i+1 >= Pill(len(_Pill_index)) {         return fmt.Sprintf("Pill(%d)", i)     }     return _Pill_name[_Pill_index[i]:_Pill_index[i+1]] } $

Каждый раз, когда мы меняем определение Pill или констант, всё что мы должны сделать, это запустить

$ go generate

чтобы обновить String метод. И конечно, если у нас есть несколько типов в одном пакете, которые нужно обновить, go generate обновит их всех.

Само собой разумеется, что сгенерированный код уродлив. Это OK, впрочем, так как люди не будут работать с этим кодом; автосгенерированный код очень часто уродлив. Он старается быть максимально эффективным. Все имена объединены вместе в одну строку, которая экономит память (всего одна строка на все имена, даже их тут несметное количество). Затем массив, _Pill_index, находит соответствие типа с именем используя простую и очень эффективную технику. Обратите внимание, что _Pill_index это массив (не слайс; одним заголовком меньше) значений типа uint8, наимейший возможный целочисленный тип, способный вместить в себя нужные значения. Если значений будет больше, или будут отрицательные, тип сгенерированного массива _Pill_index может поменяться на uint16 или int8, смотря что будет работать лучше.

Подход, используемый в методах, сгенерированных с помощью stringer меняется, в зависимости от свойств набора констант. К примеру, если константы разряженные, он может использовать map. Вот простой пример, основанный на наборе констант, представляющих степени двойки:

 const _Power_name = "p0p1p2p3p4p5..."  var _Power_map = map[Power]string{     1:    _Power_name[0:2],     2:    _Power_name[2:4],     4:    _Power_name[4:6],     8:    _Power_name[6:8],     16:   _Power_name[8:10],     32:   _Power_name[10:12],     ..., }  func (i Power) String() string {     if str, ok := _Power_map[i]; ok {         return str     }     return fmt.Sprintf("Power(%d)", i) }

Резюмируя, автоматическая генерация метода позволяет нам решать задачу лучше, чем это сделал бы человек.

В исходных кодах Go есть масса других примеров использования go generate. Сюда входят генерация таблиц Unicode в пакете unicode, создание эффективных методов для кодирования и декодирования массивов в encoding/gob, создания набора данных таймзон в пакете time, и тому подобное.

Пожалуйста, используйте go generate креативно. Он тут для того, чтобы поощрять эксперименты.

И даже если нет, используйте stringer, чтобы добавлять String методы к вашим числовым константам. Позвольте компьютеру делать работу за вас.

ссылка на оригинал статьи http://habrahabr.ru/post/269887/