ФЭНДОМ


На досуге нарисовал парсер CSV данных на текщий момент и сегодняшний день с worldwheateronline с превращением их в текстовый и приятный для festival формат. 

Это первая версия. Возможно буду продолжать улучшение. 

Имеется:

  • 16 русских направлений ветра
  • Склонение чисел
  • Машинный перевод состояний погоды полученных по API

Особеннности: 

  • Скрипт только генерирует текст. Для воспроизведения можно использовать конструкцию на bash ./saytext_ru.sh "`./wheater.pl`"
  • Весь текст формируется в виде одного принта в конце файла.
  • Все переменные для принта описываются чуть выше.

Благодарности:

Текущие проблемы:

  • Отсутствие адекватного перевода для состояний погоды
  • Неявное конструирование текста.


ИнструкцияПравить

Аналогично статье Получение актуальной погоды требуется получить API-key и ввести его в скрипт. Так же необходимо указать координаты своего города до четвёртого знака.

Для использования склонятора есть 2 функции 

  1. litnum($num, $pad, $gen) .  - преобразование числа в текст с учётом падежа и пола. возвращает число
  1. [" $one "," $two "," $three "]->[numdecl($num)]; - выбор версии текста в зависимости от числа. возвращает слово
  2. rus_int_word(ceil($temp),'i','m',"градус","градуса","градусов"); - комбинированная версия 2х вышеописанных функций. Возвращает число слово.
  • Весь текст формируется в виде одного принта в конце файла.
  • Все переменные для принта описываются чуть выше.

СкриптПравить

#!/usr/bin/perl
# Free License 
# Nikita I Shapovalov
# n.shapovalov@immap.ru
# Thanks for: 
# http://mail.pm.org/pipermail/moscow-pm/2010-October/009101.html - For dig2text function
# http://developer.worldweatheronline.com - for Free wheater API
# https://translate.yandex.net/api/v1.5/tr.json/translate - For Translate API for wheater strings
#


	use POSIX;
	use LWP::Simple;
	use Time::Piece;

### PUT HERE YOU API KEY FROM developer.worldweatheronline.com ###
$api_key="developer.worldweatheronline";                       ###
###       А сюда координаты                                    ###
###         Нижний Новгород                                    ###
$shir = '56.1937';                                             ###
$dolg = '44.0027';                                             ###
##################################################################


###
my %lit = (
	'i' => {
		lit100 => [undef, 'сто', 'двести', 'триста', 'четыреста', 'пятьсот', 'шестьсот', 'семьсот', 'восемьсот', 'девятьсот'],
		lit10 => [undef, undef, 'двадцать', 'тридцать', 'сорок', 'пятьдесят', 'шестьдесят', 'семьдесят', 'восемьдесят', 'девяносто'],
		zero => 'ноль',
		ths => ['тысяча', 'тысячи', 'тысяч'],
		mln => ['миллион', 'миллиона', 'миллионов'],
		bln => ['миллиард', 'миллиарда', 'миллиардов'],
	},
	'r' => {
		lit100 => [undef, 'ста', 'двухсот', 'трёхсот', 'четырёхсот', 'пятисот', 'шестисот', 'семисот', 'восьмисот', 'девятисот'],
		lit10 => [undef, undef, 'двадцати', 'тридцати', 'сорока', 'пятидесяти', 'шестидесяти', 'семидесяти', 'восьмидесяти', 'девяноста'],
		zero => 'нуля',
		ths => ['тысячи', 'тысяч', 'тысяч'],
		mln => ['миллиона', 'миллионов', 'миллионов'],
		bln => ['миллиарда', 'миллиардов', 'миллиардов'],
	},
	'd' => {
		lit100 => [undef, 'ста', 'двумстам', 'трёмстам', 'четырёмстам', 'пятистам', 'шестистам', 'семистам', 'восьмистам', 'девятистам'],
		lit10 => [undef, undef, 'двадцати', 'тридцати', 'сорока', 'пятидесяти', 'шестидесяти', 'семидесяти', 'восьмидесяти', 'девяноста'],
		zero => 'нулю',
		ths => ['тысяче', 'тысячам', 'тысячам'],
		mln => ['миллиону', 'миллионам', 'миллионам'],
		bln => ['миллиарду', 'миллиардам', 'миллиардам'],
	},
	'v' => {
		lit100 => [undef, 'сто', 'двести', 'триста', 'четыреста', 'пятьсот', 'шестьсот', 'семьсот', 'восемьсот', 'девятьсот'],
		lit10 => [undef, undef, 'двадцать', 'тридцать', 'сорок', 'пятьдесят', 'шестьдесят', 'семьдесят', 'восемьдесят', 'девяносто'],
		zero => 'ноль',
		ths => ['тысячу', 'тысячи', 'тысяч'],
		mln => ['миллион', 'миллиона', 'миллионов'],
		bln => ['миллиард', 'миллиарда', 'миллиардов'],
	},
	't' => {
		lit100 => [undef, 'ста', 'двумястами', 'тремястами', 'четыремястами', 'пятистами', 'шестистами', 'семистами', 'восемьюстами', 'девятьюстами'],
		lit10 => [undef, undef, 'двадцатью', 'тридцатью', 'сорока', 'пятидесятью', 'шестидесятью', 'семидесятью', 'восьмидесятью', 'девяноста'],
		zero => 'нулём',
		ths => ['тысячью', 'тысячами', 'тысячами'],
		mln => ['миллионом', 'миллионами', 'миллионами'],
		bln => ['миллиардом', 'миллиардами', 'миллиардами'],
	},
	'p' => {
		lit100 => [undef, 'ста', 'двухстах', 'трёхстах', 'четырёхстах', 'пятистах', 'шестистах', 'семистах', 'восьмистах', 'девятистах'],
		lit10 => [undef, undef, 'двадцати', 'тридцати', 'сорока', 'пятидесяти', 'шестидесяти', 'семидесяти', 'восьмидесяти', 'девяноста'],
		zero => 'нуле',
		ths => ['тысяче', 'тысячах', 'тысячах'],
		mln => ['миллионе', 'миллионах', 'миллионах'],
		bln => ['миллиарде', 'миллиардах', 'миллиардах'],
	},
	'im' => {
		lit1 => [undef, 'один', 'два', 'три', 'четыре', 'пять', 'шесть', 'семь', 'восемь', 'девять', 'десять', 'одиннадцать', 'двенадцать', 'тринадцать', 'четырнадцать', 'пятнадцать', 'шестнадцать', 'семнадцать', 'восемнадцать', 'девятнадцать'],
	},
	'if' => {
		lit1 => [undef, 'одна', 'две', 'три', 'четыре', 'пять', 'шесть', 'семь', 'восемь', 'девять', 'десять', 'одиннадцать', 'двенадцать', 'тринадцать', 'четырнадцать', 'пятнадцать', 'шестнадцать', 'семнадцать', 'восемнадцать', 'девятнадцать'],
	},
	'rm' => {
		lit1 => [undef, 'одного', 'двух', 'трёх', 'четырёх', 'пяти', 'шести', 'семи', 'восьми', 'девяти', 'десяти', 'одиннадцати', 'двенадцати', 'тринадцати', 'четырнадцати', 'пятнадцати', 'шестнадцати', 'семнадцати', 'восемнадцати', 'девятнадцати'],
	},
	'rf' => {
		lit1 => [undef, 'одной', 'двух', 'трёх', 'четырёх', 'пяти', 'шести', 'семи', 'восьми', 'девяти', 'десяти', 'одиннадцати', 'двенадцати', 'тринадцати', 'четырнадцати', 'пятнадцати', 'шестнадцати', 'семнадцати', 'восемнадцати', 'девятнадцати'],
	},
	'dm' => {
		lit1 => [undef, 'одному', 'двум', 'трём', 'четырём', 'пяти', 'шести', 'семи', 'восьми', 'девяти', 'десяти', 'одиннадцати', 'двенадцати', 'тринадцати', 'четырнадцати', 'пятнадцати', 'шестнадцати', 'семнадцати', 'восемнадцати', 'девятнадцати'],
	},
	'df' => {
		lit1 => [undef, 'одной', 'двум', 'трём', 'четырём', 'пяти', 'шести', 'семи', 'восьми', 'девяти', 'десяти', 'одиннадцати', 'двенадцати', 'тринадцати', 'четырнадцати', 'пятнадцати', 'шестнадцати', 'семнадцати', 'восемнадцати', 'девятнадцати'],
	},
	'vm' => {
		lit1 => [undef, 'один', 'два', 'три', 'четыре', 'пять', 'шесть', 'семь', 'восемь', 'девять', 'десять', 'одиннадцать', 'двенадцать', 'тринадцать', 'четырнадцать', 'пятнадцать', 'шестнадцать', 'семнадцать', 'восемнадцать', 'девятнадцать'],
	},
	'vf' => {
		lit1 => [undef, 'одну', 'две', 'три', 'четыре', 'пять', 'шесть', 'семь', 'восемь', 'девять', 'десять', 'одиннадцать', 'двенадцать', 'тринадцать', 'четырнадцать', 'пятнадцать', 'шестнадцать', 'семнадцать', 'восемнадцать', 'девятнадцать'],
	},
	'tm' => {
		lit1 => [undef, 'одним', 'двумя', 'тремя', 'четырьмя', 'пятью', 'шестью', 'семью', 'восемью', 'девятью', 'десятью', 'одиннадцатью', 'двенадцатью', 'тринадцатью', 'четырнадцатью', 'пятнадцатью', 'шестнадцатью', 'семнадцатью', 'восемнадцатью', 'девятнадцатью'],
	},
	'tf' => {
		lit1 => [undef, 'одной', 'двумя', 'тремя', 'четырьмя', 'пятью', 'шестью', 'семью', 'восемью', 'девятью', 'десятью', 'одиннадцатью', 'двенадцатью', 'тринадцатью', 'четырнадцатью', 'пятнадцатью', 'шестнадцатью', 'семнадцатью', 'восемнадцатью', 'девятнадцатью'],
	},
	'pm' => {
		lit1 => [undef, 'одном', 'двух', 'трёх', 'четырёх', 'пяти', 'шести', 'семи', 'восьми', 'девяти', 'десяти', 'одиннадцати', 'двенадцати', 'тринадцати', 'четырнадцати', 'пятнадцати', 'шестнадцати', 'семнадцати', 'восемнадцати', 'девятнадцати'],
	},
	'pf' => {
		lit1 => [undef, 'одной', 'двух', 'трёх', 'четырёх', 'пяти', 'шести', 'семи', 'восьми', 'девяти', 'десяти', 'одиннадцати', 'двенадцати', 'тринадцати', 'четырнадцати', 'пятнадцати', 'шестнадцати', 'семнадцати', 'восемнадцати', 'девятнадцати'],
	},
);

sub litnum
{
	my $n = int(shift);
	my $p = shift || 'i';
	my $g = shift || 'm';
	return 'минус ' . litnum(abs($n), $p) if $n < 0;
	$lit{$p} or die "Invalid parameter: p=$p";
	$lit{"$p$g"} or die "Invalid parameter: g=$g";
	my $res = ;
	if ($n >= 1000000000) {
		$res .= ' ' if $res;
		my $int = int($n / 1000000000);
		$res .= litnum($int, $p, 'm') . ' ' . $lit{($int % 1000) ? $p : 'r'}->{bln}->[numdecl($int)];
		$n -= $int * 1000000000;
	}
	if ($n >= 1000000) {
		$res .= ' ' if $res;
		my $int = int($n / 1000000);
		$res .= litnum($int, $p, 'm') . ' ' . $lit{($int % 1000) ? $p : 'r'}->{mln}->[numdecl($int)];
		$n -= $int * 1000000;
	}
	if ($n >= 1000) {
		$res .= ' ' if $res;
		my $int = int($n / 1000);
		$res .= litnum($int, $p, 'f') . ' ' . $lit{$p}->{ths}->[numdecl($int)];
		$n -= $int * 1000;
	}
	if ($n >= 100) {
		$res .= ' ' if $res;
		my $int = int($n / 100);
		$res .= $lit{$p}->{lit100}->[$int];
		$n -= $int * 100;
	}
	if ($n >= 20) {
		$res .= ' ' if $res;
		my $int = int($n / 10);
		$res .= $lit{$p}->{lit10}->[$int];
		$n -= $int * 10;
	}
	if ($n > 0) {
		$res .= ' ' if $res;
		$res .= $lit{"$p$g"}->{lit1}->[$n];
	}
	return $res || $lit{$p}->{zero};
}

sub numdecl
{
$_[0] = abs($_[0]);
	return
		(($_[0] % 100) >= 10 && ($_[0] % 100) <= 20) ? 2 :
		(($_[0] % 10) >= 2 && ($_[0] % 10) <= 4) ? 1 :
		(($_[0] % 10) == 1) ? 0 :
		2;
}

sub rus_int_word{
	($num,$pad,$gen,$one,$two,$three) = @_;
	return litnum($num, $pad, $gen) . [" $one "," $two "," $three "]->[numdecl($num)];
}


$url = "http://api.worldweatheronline.com/free/v1/weather.ashx?q=$shir%2C$dolg&format=csv&show_comments=no&extra=localObsTime&key=$api_key";
$Hour = localtime->strftime('%-H');
$day = localtime->strftime('%-d');
$month = localtime->strftime('%-m');
$year = litnum(localtime->strftime('%Y'),'i','m');
$minute = localtime->strftime('%-M');

if(($Hour >= 6) && ($Hour < 10)){$grettings = "Доброе утро!"}
if(($Hour >= 10) && ($Hour < 17)){$grettings = "Добрый день!"}
if(($Hour >= 17) && ($Hour < 23)){$grettings = "Добрый вечер!"}
if(($Hour < 6) || ($Hour >= 23)){$grettings = "Доброй ночи!"}

@days = ("Дни месяца","первое","второе","третье","четвёртое","пятое","шестое","седьмое","восьмое","девятое","десятое","одинадцатое","двенадцатое","тринадцатое","четырнадцатое","пятнадцатое","шестнадцатое","семнадцатое","восемнадцатое","девятнадцатое","двадцатое","двадцать первое","двадцать второе","двадцать третье","двадцать четвёртое","двадцать пятое","двадцать шестое","двадцать седьмое","двадцать восьмое","двадцать девятое","тридцатое","тридцать первое");
@months = ("Месяца","января","февраля","марта","апреля","мая","июня","июля","августа","сентября","октября","ноября","декабря");
%windTo = ("N" => "Северный","NNE" => "Северо Северо Восточный","NE" => "Северо Восточный","ENE" => "востоко северо восточный","E" => "восточный","ESE" => "востоко юго восточный","SE" => "юго восточный","SSE" => "юго юго восточный","S" => "южный","SSW" => "юго юго западный","SW" => "юго западный","WSW" => "западо юго западный","W" => "западный","WNW" => "западо северо западный","NW" => "северо западный","NNW" => "северо северо западный");
# Тут весьма плохой перевод погод согласно кода возвращаемого апи / возможно в будущем будет доработано, а пока поржём.
%rusDesk = ("395" => "Умеренный или сильный снегопад в районе с громом","392" => "Пятнистый свет снега в районе с громом","389" => "Умеренный или сильный дождь с громом курения","386" => "Пятнистый небольшой дождь с громом курения","377" => "Умеренные или сильные ливни частиц льда","374" => "Свет души гранулы льда","371" => "Умеренный или сильный снег","368" => "Свет снег","365" => "Умеренный или сильный мокрый снег душевые","362" => "Местами небольшой мокрый снег душевые","359" => "Проливной дождь Душ","356" => "Умеренный или сильный дождь Душ","353" => "Небольшой дождь Душ","350" => "Гроза","338" => "Сильный снег","335" => "Пятнистый снег","332" => "Умеренный снег","329" => "Пятнистый умеренный снег","326" => "Легкий снег","323" => "Пятнистый свет снег","320" => "Умеренный или сильный мокрый снег","317" => "Небольшой мокрый снег","314" => "Умеренный или сильный дождь","311" => "Свет ледяной дождь","308" => "Проливной дождь","305" => "Сильный дождь порой","302" => "Умеренный дождь","299" => "Умеренный дождь порой","296" => "Небольшой дождь","293" => "Пятнистый небольшой дождь","284" => "Тяжелые замораживания полить","281" => "Замораживание полить","266" => "Морось","263" => "Пятнистый морось","260" => "Холодный туман","248" => "Туман","230" => "Метель","227" => "Метель","200" => "Грозовой вспышек в ближайших","185" => "Пятнистый замораживания полить поблизости","182" => "Пятнистый мокрый снег рядом","179" => "Пятнистый снег неподалеку","176" => "Пятнистый среди дождя","143" => "Туман","122" => "Сплошная облачность","119" => "Облачно","116" => "Небольшая Облачность","113" => "Ясно");

$contents = get $url or die;
@strings = split "\n" , $contents;
@params = split "," , $strings[0];
@dayparams = split "," , $strings[1];
($utctime, $temp, $wheaterCode, $image, $desk, $windSpeedmh, $windSpeedkmph, $winddigr, $winddir16, $precip, $humidity, $visibility, $pressure, $clousure) = @params;
($utcdate, $maxTempC, $maxTempF, $minTempC, $minTempF, $windSpeedmhDay, $windSpeedkmphDay, $winddigrDay, $winddigr16, $wheaterCodeDay, $imageDay, $wheaterDeskDay, $precipDay) = @dayparams;
$windSpeed = $windSpeedkmph*1000/3600;
$windSpeedDay = $windSpeedkmphDay*1000/3600;
$hours = rus_int_word($Hour,'i','m',"час","часа","часов");
$minutes = rus_int_word($minute,'i','m',"минута","минуты","минут");
$metres = rus_int_word(ceil($windSpeed),'i','m',"метр","метра","метров");
$vypalo = [" выпал "," выпало "," выпало "]->[numdecl(ceil($precip))];
$milimetres = rus_int_word(ceil($precip),'i','m',"милиметр","милиметра","милиметров");
$graduses = rus_int_word(ceil($temp),'i','m',"градус","градуса","градусов");
$procents = rus_int_word(ceil($humidity),'i','m',"процент","процента","процентов");
$metresDay = rus_int_word(ceil($windSpeedDay),'r','m',"метров","метров","метров");
$milimetresDay = rus_int_word(ceil($precipDay),'i','m',"милиметр","милиметра","милиметров");
$gradusesDayMin = rus_int_word(ceil($minTempC),'r','m',"градусов","градусов","градусов");
$gradusesDayMax = rus_int_word(ceil($maxTempC),'r','m',"градусов","градусов","градусов");
$procentsDay = rus_int_word(ceil($humidityDay),'i','m',"процент","процента","процентов");

if($minTempC < 0){
	$fromto = "от $gradusesDayMax до $gradusesDayMin";
}else{
	$fromto = "от $gradusesDayMin до $gradusesDayMax";
}

### You generated message here.
print "
$grettings Сегодня $days[$day] $months[$month] год $year 
 cейчас $hours $minutes 
 За бортом $graduses по цельсию $rusDesk{$wheaterCode} 
 Ветер $windTo{$winddir16} $metres в секунду 
 Влажность  $procents На данный момент $vypalo $milimetres осадков
 В течении дня ожидается температура $fromto по цельсию $rusDesk{$wheaterCodeDay}
 Ветер $windTo{$winddigr16} до $metresDay в секунду Ожидаемое количество осадков $milimetresDay \n";

 

Обнаружено использование расширения AdBlock.


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

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

Также на ФЭНДОМЕ

Случайная вики