Rss. Наболело.

Сегодня хочу написать о том, как мне наболело читая посты через RSS ходит на сайты источники, и читать их там.

Мне надоело то что в RSS ленту половина сайтов выливает всего лишь начало поста, а чтобы прочитать весь пост нужно идти по ссылке, кликать куда то. И вообще мне рушит моск мысль о том что куда то нужно идти, чтобы прочитать новость которую я читаю в RSS. Я конечно понимаю владельцев сайтов, что они хотят чтобы к ним ходили, баннера, показы, клики, и все такое. Я не вижу ваших баннеров, Adblock рулит.
И кстати, на заметку веб мастерам. При правильных танцах с бубном можно модифицировать код Google Analytics и встраивать его в RSS. Тем самым смотреть посещаемость конкретно для тех кто читает вас через ленту. Плюс можно те же баннеры вставлять в посты, это если кому то уж сильно хочется покрутить баннеры где возможно.
Делаем выводы.


Заметка технарям: Правильно чистим гранат

Как правильно почистить гранат?

Эта заметка будет полезна как технарям, так и кому угодно кто любит гранат :)

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

Читать далее


Алгоритм распознавания текста

Начало.

И так, с чего это все началось и откуда оно взялось?
В одном рабочем проекте потребовалось распознавать тексты(записи) на основе собственной базы. К примеру у нас есть база видео-карт для компьютера соответственно с названиями, и нам нужно сказать что то что нам прислали, это та или иная видео-карта из нашел базы.

Больше техники.

Перепробовав немало подходов и разных алгоритмов, остановился на алгоритме «Левенштейна» (Дистанция Левенштейна). [wiki]
Кому интересно, на вики есть формула и в примерах есть визуализатор алгоритмов.
«Расстояние Левенштейна (также редакционное расстояние или дистанция редактирования) между двумя строками в теории информации и компьютерной лингвистике — это минимальное количество операций вставки одного символа, удаления одного символа и замены одного символа на другой, необходимых для превращения одной строки в другую.» (c) wiki
Т.к. проект на перле, пришлось реализовать и это на перле. Вот что из этого получилось:

#!/usr/bin/perl

# так в книжке написано :)
use strict;

# дебаггер
use Data::Dumper;

# что будем сравнивать
my $word1 = "ASUS NVIDIA PCI-E ENGTX550 TI DI/1GD5 ENGTX550 TI DI/1GD5 (90-C1CR70-L0UAY0YZ) [1137722]";

# наша база для сравнения
my @word2 = (
'ASUS GeForce GTX 550 Ti 1024 MB GDDR5 (ENGTX550 TI DC TOP/DI/1GD5)',
'ASUS GeForce GTX 550 Ti 1024 MB GDDR5 (ENGTX550 TI DC/DI/1GD5)',
'ASUS GeForce GTX 550 Ti 1024 MB GDDR5 (ENGTX550 TI/DI/1GD5)',
'ASUS GeForce GTX 560 Ti 1024 MB GDDR5 (ENGTX560 TI DCII TOP/2DI/1GD5)',
'ASUS GeForce GTX 560 Ti 1024 MB GDDR5 (ENGTX560 TI DCII/2DI/1GD5)',
'ASUS GeForce GTX 560 Ti 1024 MB GDDR5 (ENGTX560 TI DC/2DI/1GD5)',
'ASUS GeForce GTX 460 1024 MB GDDR5 (ENGTX460 DC TOP/2DI/1GD5/V2)',
'ASUS GeForce GTX 560 1024 MB GDDR5 (ENGTX560 DCII OC/2DI/1GD5)',
'ASUS GeForce GTX 560 1024 MB GDDR5 (ENGTX560 DCII TOP/2DI/1GD5)',
'ASUS GeForce GTX 460 1024 MB GDDR5 (ENGTX460 DirectCU TOP/2DI/1GD5)',
'ASUS GeForce GTX 560 1024 MB GDDR5 (ENGTX560 DC/2DI/1GD5)',
'ASUS GeForce GTX 460 1024 MB GDDR5 (ENGTX460 DIRECTCU/2DI/1GD5)',
'MSI GeForce GTX 550 Ti 1024 MB GDDR5 (N550GTX-Ti Cyclone II 1GD5/OC)',
'MSI GeForce GTX 550 Ti 1024 MB GDDR5 (N550GTX-Ti-M2D1GD5/OC)',
'MSI GeForce GTX 550 Ti 1024 MB GDDR5 (N550GTX-Ti Cyclone II 1GD5)',
'ASUS GeForce GTX 580 1536 MB GDDR5 (ENGTX580/2DI/1536MD5)',
'ASUS GeForce GTX 480 1536 MB GDDR5 (ENGTX480/G/2DI/1536MD5)',
'ASUS Eee PC 1015PEM-N550-N1BSAWM (90OA33BB3114987E23ZU)',
'ASUS Eee PC 1015PEM-N550-N1BSAP (90OA33BD3114987E23ZU)',
'ASUS Eee PC 1015PEM-N550-N1BSABL (90OA33B43114987E23ZU)'
);

my @dist = &distance($word1, @word2);

print Dumper(\@dist);

sub distance
{
        my ($s,@t)=@_;

        my $n=length($s);
        my @result;

        foreach my $t (@t) {
                if ($s eq $t) {
                        push @result, 0;
                        next;
                }
                my @d;
                my $cost=0;

                my $m=length($t);
                push @result,$m and next unless $n;
                push @result,$n and next unless $m;

                $d[0][0]=0;
                foreach my $i (1 .. $n) {
                        if ($i != $n && substr($s,$i) eq substr($t,$i)) {
                                push @result,$i;next;
                        }
                        $d[$i][0]=$i;
                }
                foreach my $j (1 .. $m) {
                        if ($j != $m && substr($s,$j) eq substr($t,$j)) {
                                push @result,$j;next;
                        }
                        $d[0][$j]=$j;
                }

                for my $i (1 .. $n) {
                        my $s_i=substr($s,$i-1,1);
                        for my $j (1 .. $m) {
                                $d[$i][$j]=&_min($d[$i-1][$j]+1,
                                         $d[$i][$j-1]+1,
                                         $d[$i-1][$j-1]+($s_i eq substr($t,$j-1,1) ? 0 : 1) )
                        }
                }

                push @result,$d[$n][$m];
        }

        return @result;
}

sub _min
{
        return $_[0] < $_[1]
                ? $_[0] < $_[2] ? $_[0] : $_[2]
                : $_[1] < $_[2] ? $_[1] : $_[2];
}

На выходе получим что то такого вида:

$VAR1 = [
          62,
          60,
          58,
          64,
          63,
          62,
          67,
          65,
          66,
          67,
          62,
          65,
          69,
          68,
          69,
          64,
          66,
          67,
          67,
          67
        ];

Как мы видим из примера, 3-я в списке видеокарта, та которая нам нужна, и дистанция Левенштейна у нее будет минимальная (58) по отношению к другим видео-картам.

Наши выводы или что мы получили?

Алгоритм работает при небольших базах хорошо, как только начинаешь увеличивать количество слов(фраз) для сравнения, начинает определять не точно. При базе в 20 фраз, определяет с точностью до 90 процентов. Есть еще одна проблема, когда дистанция у двух или более фраз будет равна, пока еще не придумал решение для это ситуации. Думаю в скором времени мы увидим новые алгоритмы.


Автоматический обзвон на Asterisk PBX

Недавно задался идеей сделать автоматический обзвон абонентской базы, было принято решение делать это на Asterisk.

В общем ничего сложно в этом нет, вот рабочее решение из двух файлов.

extensions_custom.conf

[obzvon]
exten => s,1,Playback(demo)
exten => s,n,Hangup

call.pl:

#!/usr/bin/perl

$file = "/var/spool/asterisk/tmp_call.call";
$phone = $ARGV[0];
$context = $ARGV[1];
unless ($ARGV[1]){
$context = "obzvon";
}
open(FILE, "> $file");
print FILE "Channel: SIP/trunk_name/".$phone."\n";
print FILE "CallerID: 5555555\n";
print FILE "MaxRetries: 2\n";
print FILE "RetryTime: 300\n";
print FILE "WaitTime: 45\n";
print FILE "Context: ".$context."\n";
print FILE "Extension: s\n";
print FILE "Priority: 1\n";
close(FILE);

call.sh:

#!/bin/bash
call.pl $1 $2
chown asterisk:asterisk /var/spool/asterisk/tmp_call.call
mv /var/spool/asterisk/tmp_call.call /var/spool/asterisk/outgoing/$1.call

Использовать нужно так:
./call.sh 3211223
./call.sh 3211223 custom_context


Настройка SNMP на Cisco 3560

В этой статье я раскажу как сделать первоначальную настройку SNMP на оборудовании Cisco.
За пример был взят коммутатор Cisco 3560. Для ограничения доступа к SNMP возьмем “standart” access-list.
Для того чтобы создать access-list нужно ввести следующие команды:
router#configure terminal
router(config)#access-list 60 permit 1.1.1.1
router(config)#access-list 60 permit 1.1.1.2
Этим мы разрешим доступ IP-адресам 1.1.1.1 и 1.1.1.2 к SNMP.
Дальше команды для настройки SNMP:
router#configure terminal
router(config)#snmp-server community public RO 60
router(config)#snmp-server location Kiev, Ukraine
router(config)#snmp-server contact router.ru, Kiev
Это всего лишь базовая настройка, более подробную информацию Вы можете прочитать на сайте производителя.