Магия с сенсором освещения
Помимо сенсора внезапного движения многие новые «Макбуки» оборудованы сенсором освещённости, он едва заметно располагается рядом с видеокамерой.
Мне интересно стало попробовать поработать и с ним тоже. На этот раз цель была — научиться эффектным жестом блокировать свой ноут. Конечно, ложных срабатываний масса —

Код на Си получился чуть более ста строк и на этот раз я распознаю шаблон поведения, он задаётся в подстановке
При сканировании чисел с датчика я всегда рассматриваю десять значений от которых считаю среднее и каждое значение рассматриваю как отклонение от этого среднего, собственно, вот код:
// Магические пассы, улавливаемые через датчик освещённости
// Written by Evgeny Stepanischev Jun 2013
// gcc lightlock.c -framework IOKit -framework ApplicationServices -O3 -o lightlock
#include <IOKit/IOKitLib.h>
#include <CoreFoundation/CoreFoundation.h>
#include <ApplicationServices/ApplicationServices.h>
#include <unistd.h>
#define WINDOWSIZE 10
#define GESTURES "+vvv000-^^^"
#define UPDATEINTERVAL .01
const kGetSensorReadingID = 0;
int makeReaction(uint64_t current);
static io_connect_t port = 0;
void macLock () {
CGSCreateLoginSession(NULL);
}
void updateTimerCallBack(CFRunLoopTimerRef timer, void *info) {
IOItemCount osize = 2;
uint64_t values[osize];
kern_return_t ret = IOConnectCallMethod(port, kGetSensorReadingID,
NULL, 0, NULL, 0, values, &osize, NULL, 0);
if (ret == KERN_SUCCESS) {
if (makeReaction(values[0])) {
macLock();
}
}
else if (ret != kIOReturnBusy) {
mach_error("IOConnectCallMethod: ", ret);
exit(-3);
}
}
int main() {
io_service_t service = IOServiceGetMatchingService(
kIOMasterPortDefault, IOServiceMatching("AppleLMUController")
);
if (service == kIOReturnNoDevice) {
fprintf(stderr, "Cannot find Ambient Light Sensor\n");
exit(-1);
}
kern_return_t ret = IOServiceOpen(service, mach_task_self(), 0, &port);
IOObjectRelease(service);
if (ret != KERN_SUCCESS) {
mach_error("IOServiceOpen:", ret);
exit(-2);
}
CFRunLoopTimerRef timer = CFRunLoopTimerCreate(
kCFAllocatorDefault,
CFAbsoluteTimeGetCurrent() + UPDATEINTERVAL,
UPDATEINTERVAL, 0, 0, updateTimerCallBack, NULL
);
CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode);
CFRunLoopRun();
exit(0);
}
int checkMask(char mask, const int64_t diff, const int64_t prevdiff) {
switch (mask) {
case '+': return diff > 0;
case '-': return diff < 0;
case '0': return diff == 0;
case 'v': return prevdiff > diff;
case '^': return diff > prevdiff;
}
return 0;
}
int makeReaction(uint64_t current) {
static uint64_t window[WINDOWSIZE];
static uint64_t prevdiff = 0;
static gesturepos = 0;
uint64_t average = current;
int i, notzerocnt = 1;
for (i = WINDOWSIZE-1; i > 0; i--) {
if (window[i] = window[i-1]) {
average += window[i];
notzerocnt++;
}
}
window[0] = current;
average /= notzerocnt;
int64_t diff = average - current;
if (checkMask(GESTURES[gesturepos], diff, prevdiff)) {
gesturepos++;
} else {
if (!gesturepos || !checkMask(GESTURES[gesturepos-1], diff, prevdiff)) {
gesturepos = 0;
}
}
prevdiff = diff;
return gesturepos == sizeof GESTURES - 1;
}В функции main, в конце стоит магический код, который нужен для того, чтобы вызываемые мною внутренние шестерёнки «Мака» благополучно крутились, иначе функция CGSCreateLoginSession будет ждать когда ей перепадёт процессорного времени.
Ну и традиционно, если
Malbolge

В десятой серии сериала «Элементарно» внезапно для меня в сюжете используется эзотерический язык программирования «Малболж». Я им немного интересовался, но программировать на нём так тяжело, что даже простые программы, в основном, сгенерированы компьютером.
Когда я увидел текст этой программы, конечно, сразу загорелся посмотреть что там выводится, но оказалось, что это даже не программа, а просто фрагмент «Hello, world.», да ещё и с несколькими опечатками (первые две ошибки — символы №№ 9 и 15):
('&%:9]!-}|z2Vzwv-,POqponl$Hjig%eB@@>}=<M:9wv^WsU2T|nm-
,jcl(I&%$#"^CB]V?Tx<uVtT^Rpo3Nlf.Jh++Fdbc=CBA9?!Жаль, можно было бы