Архив за месяц: Август 2014

что? где? когда? Работа с log-файлами фруктовой фермы.

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

В зависимости от хостера они могут нести разные имена, отличные от тех, пример которых я приведу.
Как правило, файлы хранятся в корневой директории Вашего сайта.


---------------------------------------------------------------------------------------------------------------------
Рассмотрим пример одного из файлов. Обычно они заполняются одинаково:

Ваш_сайт.ru 5.255.253.131 - - [30/Aug/2014:06:33:51 +0400] "GET /robots.txt HTTP/1.0404 208 "-" "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)"

Ваш_сайт.ru 66.249.64.149 - - [30/Aug/2014:06:44:39 +0400] "GET / HTTP/1.0200 13269 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"

Ваш_сайт.ru 5.255.253.131 - - [30/Aug/2014:07:04:52 +0400] "GET / HTTP/1.0200 13269 "-" "Mozilla/5.0 (compatible; YandexMetrika/3.0; +http://yandex.com/bots)"

Ваш_сайт.ru 91.221.109.101 - - [30/Aug/2014:07:09:50 +0400] "GET /user/register HTTP/1.0404 211 "-" "Mozilla/5.0 (Windows NT 6.2; WOW64) Runet-Research-Crawler (itrack.ru/research/cmsrate; rating@itrack.ru)"

Ваш_сайт.ru 134.249.51.93 - - [30/Aug/2014:07:24:10 +0400] "GET / HTTP/1.0200 13269 "http://Ваш_сайт.ru/" "Mozilla/5.0 (Windows NT 5.1; rv:27.0) Gecko/20100101 Firefox/27.0"

Ваш_сайт.ru 134.249.51.93 - - [30/Aug/2014:07:24:11 +0400] "GET /signup HTTP/1.0200 12515 "http://Ваш_сайт.ru/signup" "Mozilla/5.0 (Windows NT 5.1; rv:27.0) Gecko/20100101 Firefox/27.0"

Ваш_сайт.ru 134.249.51.93 - - [30/Aug/2014:07:24:11 +0400] "GET /captcha.php?rnd=3292 HTTP/1.0200 10857 "http://Ваш_сайт.ru/signup" "Mozilla/5.0 (Windows NT 5.1; rv:27.0) Gecko/20100101 Firefox/27.0"

Ваш_сайт.ru 134.249.51.93 - - [30/Aug/2014:07:24:11 +0400] "POST /signup HTTP/1.0200 12630 "http://Ваш_сайт.ru/signup" "Mozilla/5.0 (Windows NT 5.1; rv:27.0) Gecko/20100101 Firefox/27.0"
---------------------------------------------------------------------------------------------------------------------
Зеленый. Действия, которые производятся на ресурс. В данном случае объектом является Ваш сайт. Конкретнее домен.
Фиолетовый. С какого IP-адреса производились действия.
Оранжевый. Время производимых действий.
Красный. Тип запроса, выполняемый пользователем на Вашем сервере. GET - получение адреса, POST - отправка (submit). Вот тут и следует обращать особое внимание, мошеннические запросы фиксируются тут, но впрочем как и тут будут простые запросы.
Синий. Код состояния страницы HTTP:
200 - страница успешно создана/открыта
404 - страницы не существует.
Все коды можно посмотреть на wiki
Розовый. Количество отданного сервером объема (трафик; в байтах).
Серый. URL-источник выполнения запроса. То есть с какой страницы/адреса Вашего сервера был произведен запрос. Здесь тоже смотрите внимательно. Этот параметр показывает Вам, где у Вас возможна дыра. То есть покажет Вам с какой страницы мошенник произвел запрос и например, снял с Вашего счета деньги.
Черный. Клиент пользователя. 

Пример
Ваш_сайт.ru 134.249.51.93 - - [30/Aug/2014:07:24:11 +0400] "POST /signup HTTP/1.0" 200 12630 "http://Ваш_сайт.ru/signup" "Mozilla/5.0 (Windows NT 5.1; rv:27.0) Gecko/20100101 Firefox/27.0"
Перевод:
30 августа 2014 года, в 7:24:11 На Вашем сайте пользователь с IP 134.249.51.93 авторизовался со страницы Ваш_сайт.ru/signup (использовался метод POST - обработчик кнопки "Войти) с браузера Firefox 27.0.

Похожие сообщения в blogger. Похожие посты.

Для того, чтобы установить виджет "Похожие сообщения" заходим в панель управления blogger. Выбираем нужный блог (если их у вас несколько), затем Шаблон - Изменить HTML. Далее с помощью сочетаний клавиш (Ctrl+F),  найдите  эту строку в вашем шаблоне: </head> и прямо над ней вставляем такой код:


<!--Related Posts with thumbnails Scripts and Styles Start-->

<b:if cond='data:blog.pageType == &quot;item&quot;'>

<style type="text/css">

#related-posts {

float:center;

text-transform:none;

height:100%;

min-height:100%;

padding-top:5px;

padding-left:5px;

}

#related-posts h2{

font-size: 1.6em;

font-weight: bold;

color: black;

font-family: Georgia, &#8220;Times New Roman&#8221;, Times, serif;

margin-bottom: 0.75em;

margin-top: 0em;

padding-top: 0em;

}

#related-posts a{

color:black;

}

#related-posts a:hover{

color:black;

}

#related-posts a:hover {

background-color:#d4eaf2;

}

</style>

<script src='https://dl.dropboxusercontent.com/u/72419062/JS/relatedthumbs19.js' type='text/javascript'/>

</b:if>

<!--Related Posts with thumbnails Scripts and Styles End-->


Следующий шаг, ищем одну из этих строчек <div class='post-footer-line post-footer-line-1'>  если не найдёте тогда  такую:  <p class='post-footer-line post-footer-line-1'> Многие жалуются, что не могут найти такие строки, тогда ищите вот такую: <data:post.body/> Теперь сразу после любой из этих строчек (в зависимости от того какую Вы нашли) вставляем этот код:


<!-- Related Posts with Thumbnails Code Start-->

<b:if cond='data:blog.pageType == &quot;item&quot;'>

<div id='related-posts'>

<b:loop values='data:post.labels' var='label'>

<b:if cond='data:label.isLast != &quot;true&quot;'>

</b:if>

<b:if cond='data:blog.pageType == &quot;item&quot;'>

<script expr:src='&quot;/feeds/posts/default/-/&quot; + data:label.name + &quot;?alt=json-in-script&amp;callback=related_results_labels_thumbs&amp;max-results=6&quot;' type='text/javascript'/></b:if></b:loop><a href='#' style='display:none;'>Related Posts with thumbnails for blogger</a><a href='#' style='display:none;'>blogger widgets</a>

<script type='text/javascript'>

var currentposturl=&quot;<data:post.url/>&quot;;

var maxresults=5;

var relatedpoststitle="Похожие сообщения";

removeRelatedDuplicates_thumbs();

printRelatedLabels_thumbs();

</script>

</div><div style='clear:both'/>

</b:if>

<!-- Related Posts with Thumbnails Code End-->


Готово. Теперь о настройках виджета:
Цвет текста, фон и т. д. меняйте в первом коде. Так же Вы можете настроить максимальное количество связанных сообщений для вывода, редактируя эту строку во втором коде: var maxresults=5; только имейте ввиду, что для работы виджета нужно иметь достаточное количество одинаковых ярлыков. Слово "Похожие сообщения" замените на своё (если захотите), например: "Читателям так же нравится". Всё.

Комиссия при заказе выплаты. Автоматические выплаты

Настраиваем комиссю для автоматических выплат. На примере рассмотрена комиссия системе - 10%. Заказываем 1000 серебра на вывод, получаем 9 руб (900 серебра), а 100 серебра уходят системе. Ниже приведен код, используется файл _payment.php:

<script>
function PaymentSum(){

var sum = parseInt(document.getElementById("sum").value);
var ser = parseInt(document.getElementById(valuta).value);

xt = (valuta == 'RUB') ? 'min_sum_RUB' : xt;
xt = (valuta == 'USD') ? 'min_sum_USD' : xt;
xt = (valuta == 'EUR') ? 'min_sum_EUR' : xt;

var min_pay = parseFloat(document.getElementById(xt).value);

document.getElementById("res_summa").value = ((sum-sum/10)/ser).toFixed(2);
document.getElementById("res_min").innerHTML = (min_pay*ser).toFixed(2);

}
</script>
<div class="s-bk-lf">
<div class="acc-title">Заказ выплаты</div>
</div>
<div class="silver-bk">
<BR />
<?PHP
$_OPTIMIZATION["title"] = "Аккаунт - Заказ выплаты";
$usid = $_SESSION["user_id"];
$usname = $_SESSION["user"];
$refid = $_SESSION["referer_id"];

$db->Query("SELECT * FROM db_users_b WHERE id = '$usid' LIMIT 1");
$user_data = $db->FetchArray();

$db->Query("SELECT * FROM db_config WHERE id = '1' LIMIT 1");
$sonfig_site = $db->FetchArray();

$status_array = array( 0 => "Проверяется", 1 => "Выплачивается", 2 => "Отменена", 3 => "Выплачено");

# Минималка серебром!
$minPay = 500;

?>
<b>Выплаты осуществляются в автоматическом режиме и только на платежную систему PAYEER!<font size=+2> При выводе денег 10% от суммы перечисляется вашему рефереру!</font></b> <BR /><BR />
<b>Из платежной системы Payeer Вы можете вывести свои средства в автоматическом режиме на все известные платежные системы и международные банки.</b><BR /><BR />
<b>Ссылки на учебные материалы:</b><BR />
- <a href="http://payeer.com/?partner=149347" target="_blank">Создание счета в Payeer</a> <BR />
- <a href="http://payeeer.ru/outpay" target="_blank">Вывод средств из payeer</a> <BR /><BR />

<center><b>Заказ выплаты:</b></center><BR />

<?PHP

function ViewPurse($purse){

if( substr($purse,0,1) != "P" ) return false;
if( !ereg("^[0-9]{7}$", substr($purse,1)) ) return false;
return $purse;
}

# Заносим выплату
if(isset($_POST["purse"])){

$purse = ViewPurse($_POST["purse"]);
$sum = intval($_POST["sum"]);
$val = "RUB";
$to_balance_refera = $sum * 0.1;
if($purse !== false){

if($sum >= $minPay){

if($sum <= $user_data["money_p"]){

# Проверяем на существующие заявки
$db->Query("SELECT COUNT(*) FROM db_payment WHERE user_id = '$usid' AND (status = '0' OR status = '1')");
if($db->FetchRow() == 0){


### Делаем выплату ###
$payeer = new rfs_payeer($config->AccountNumber, $config->apiId, $config->apiKey);
if ($payeer->isAuth())
{

$arBalance = $payeer->getBalance();
if($arBalance["auth_error"] == 0)
{

$sum_pay = round( (($sum - $sum/10) / $sonfig_site["ser_per_wmr"]), 2);

$balance = $arBalance["balance"]["RUB"]["DOSTUPNO"];
if( ($balance) >= ($sum_pay+1)){



$arTransfer = $payeer->transfer(array(
'curIn' => 'RUB', // счет списания
'sum' => $sum_pay, // сумма получения
'curOut' => 'RUB', // валюта получения
'to' => $purse, // получатель (email)
//'to' => '+71112223344', // получатель ()
//'to' => 'P1000000', // получатель (номер счета)
'comment' => iconv('windows-1251', 'utf-8', "Выплата пользователю {$usname} с проекта pochtowik.ru")
//'anonim' => 'Y', // анонимный перевод
//'protect' => 'Y', // протекция сделки
//'protectPeriod' => '3', // период протекции (от 1 до 30 дней)
//'protectCode' => '12345', // код протекции
));

if (!empty($arTransfer["historyId"]))
{


# Снимаем с пользователя
$db->Query("UPDATE db_users_b SET money_p = money_p - '$sum' WHERE id = '$usid'");

# Вставляем запись в выплаты
$da = time();
$dd = $da + 60*60*24*15;

$ppid = $arTransfer["historyId"];

$db->Query("INSERT INTO db_payment (user, user_id, purse, sum, valuta, serebro, payment_id, date_add, status)
VALUES ('$usname','$usid','$purse','$sum_pay','RUB', '$sum','$ppid','".time()."', '3')");

$db->Query("UPDATE db_users_b SET payment_sum = payment_sum + '$sum_pay' WHERE id = '$usid'");
$db->Query("UPDATE db_stats SET all_payments = all_payments + '$sum_pay' WHERE id = '1'");

$db->Query("UPDATE db_users_b SET money_b = money_b + '$to_balance_refera', from_referals = from_referals + '$to_balance_refera' WHERE id = '$refid'");

echo "<font color = 'green'><b>Выплачено!</b></font></center><BR />";

}
else
{

echo "<center><font color = 'red'><b>Внутреняя ошибка - сообщите о ней администратору!</b></font></center><BR />";

}


}else echo "<center><font color = 'red'><b>Внутреняя ошибка - сообщите о ней администратору!</b></font></center><BR />";

}else echo "<center><font color = 'red'><b>Не удалось выплатить! Попробуйте позже</b></font></center><BR />";

}else echo "<center><font color = 'red'><b>Не удалось выплатить! Попробуйте позже</b></font></center><BR />";


}else echo "<center><font color = 'red'><b>У вас имеются необработанные заявки. Дождитесь их выполнения.</b></font></center><BR />";


}else echo "<center><font color = 'red'><b>Вы указали больше, чем имеется на вашем счету</b></font></center><BR />";

}else echo "<center><b><font color = 'red'>Минимальная сумма для выплаты составляет {$minPay} серебра!</font></b></center><BR />";

}else echo "<center><b><font color = 'red'>Кошелек Payeer указан неверно! Смотрите образец!</font></b></center><BR />";

}
?>

<form action="" method="post">
<table width="99%" border="0" align="center">
<tr>
<td><font color="#000;">Введите кошелек Payeer [Пример: P1112457]</font>: </td>
<td><input type="text" name="purse" size="15"/></td>
</tr>
<tr>
<td><font color="#000;">Отдаете серебро для вывода</font> [Мин. <span id="res_min"></span>]<font color="#000;">:</font> </td>
<td><input type="text" name="sum" id="sum" value="<?=round($user_data["money_p"]); ?>" size="15" onkeyup="PaymentSum();" /></td>
</tr>
<tr>
<td><font color="#000;">Получаете <span id="res_val"></span></font><font color="#000;">:</font> </td>
<td>
<input type="text" name="res" id="res_summa" value="0" size="15" disabled="disabled"/>
<input type="hidden" name="per" id="RUB" value="<?=$sonfig_site["ser_per_wmr"]; ?>" disabled="disabled"/>
<input type="hidden" name="per" id="min_sum_RUB" value="5" disabled="disabled"/>
<input type="hidden" name="val_type" id="val_type" value="RUB" />
</td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" name="swap" value="Заказать выплату" style="height: 30px; margin-top:10px;" /></td>
</tr>
</table>
</form>
<script language="javascript">PaymentSum(); SetVal();</script>

<table cellpadding='3' cellspacing='0' border='0' bordercolor='#336633' align='center' width="99%">
<tr>
<td colspan="5" align="center"><h4>Последние 10 выплат</h4></td>
</tr>
<tr>
<td align="center" class="m-tb">Серебро</td>
<td align="center" class="m-tb">Получаете</td>
<td align="center" class="m-tb">Кошелек</td>
<td align="center" class="m-tb">Дата</td>
<td align="center" class="m-tb">Статус</td>
</tr>
<?PHP

$db->Query("SELECT * FROM db_payment WHERE user_id = '$usid' ORDER BY id DESC LIMIT 20");
$comission = $ref["sum"] * 0.1;
if($db->NumRows() > 0){

while($ref = $db->FetchArray()){

?>
<tr class="htt">
<td align="center"><?=$ref["serebro"]; ?></td>
<td align="center"><?=sprintf("%.2f",$ref["sum"]); ?> <?=$ref["valuta"]; ?></td>
<td align="center"><?=$ref["purse"]; ?></td>
<td
align="center"><?=date("d.m.Y",$ref["date_add"]); ?></td>
<td align="center"><?=$status_array[$ref["status"]]; ?></td>
</tr>
<?PHP

}

}else echo '<tr><td align="center" colspan="5">Нет записей</td></tr>'

?>


</table><div class="clr"></div>
</div>

1с:8.2 Управляемые формы. Как открыть форму элемента справочника

Вот способ открытия формы элемента справочника  в управляемых формах (1с 8.2, 1с 8.3)

Делаем на примере справочника товары


&НаКлиенте
Процедура ОткрытьТовары(Команда)
 Параметр = Новый Структура("Ключ", Товар);
   
Форма = ПолучитьФорму(

"Справочник.Товары.Форма.ФормаЭлемента"
,Параметр);
Форма.Открыть();
КонецПроцедуры


Знакомство с Boost.Spirit.Qi

Столкнувшись с необходимостью написания парсера для небольшого встроенного DSL, я решил использовать Boost.Spirit. Но оказалось, что использовать библиотеку человеку, плохо знакомому с boost, весьма не просто. В этой статье я попытаюсь познакомить Вас с основными аспектами работы с Boost.Spirit, чтобы помочь быстрее начать пользоваться этой замечательной библиотекой.

Библиотека Boost.Spirit состоит из нескольких частей: Classic, Qi, Lex и Karma. Classic -- это старая реализация (1.x) Boost.Spirit, оставленная для совместимости. Lex -- это токенайзер, позволяющий разбить входящий текст на токены. Karma служит для форматирования аутпута. В этой же статье речь пойдёт о Qi -- второй версии парсера Boost.Spirit.

Boost.Spirit.Qi использует расширенную форму Бэкуса-Наура (EBNF), но, в отличие от yacc, не генерирует код парсера, а позволяет писать EBNF прямо в коде.

Для того, чтобы познакомиться с библиотекой, нам понадобится простой формальный язык. Пусть это будет арифметическое выражение со скобками и знаками "+" и "-", например:
1
(1)
1 - 2
1 - 2 + 3
(1 + 2)
3 + (1 + 2)
(1 + 2) + 3
(1 + 2 + 3) + 4
(1 + 2) + (3 + 4)
(1 + (2 + 3)) + 4 + (5 + 6)
(1 + (2 + 3)) + (4 + 5) + 6
1 + 2 + (3 - 4 + (5 + 6 - (7 - 8 + 9) - 10) - 11 + 12) + 13 + 14
Этого примера достаточно для понимания того, что нужно делать для написания собственного парсера. Вместе с этим, этот пример достаточно прост, чтобы не загромождать эту статью кодом.

Первое и самое сложное, что необходимо для создания парсера -- продумать EBNF языка. Для представленного выше языка EBNF будет следующей:
Оператор ::= "+" | "-"
Операнд ::= число | <Выражение в скобках>
<Выражение в скобках> ::= "(" Выражение ")"
<Правая часть выражения> ::= Оператор Операнд
Выражение ::= Операнд { <Правая часть выражения> }
Далее нужно описать структуры данных для хранения данных каждого правила. Для того, чтобы одно и то же поле могло хранить данные разных типов (что необходимо, например, для реализации правила Операнд), следует использовать библиотеку Boost.Variant, которая поддерживается парсерами Spirit. Эта же библиотека позволяет разрешить проблему с рекурсивным вхождением правил друг в друга.
Итак, давайте посмотрим на заголовочный файл нашего парсера.
#include <memory>
#include <string>
#include <ostream>
#include <vector>
#include <boost/variant.hpp>

namespace Parser {

enum class Operator
{
plus,
minus
};

typedef int Number;

struct Expression;

typedef boost::variant<Number, boost::recursive_wrapper<Expression>> Operand;

struct RightExpression
{
Operator operator_;
Operand operand;
};

struct Expression
{
Operand operand;
std::vector<RightExpression> right;
};

std::shared_ptr<Expression> parse(const std::string & _input);

} // namespace Parser

std::ostream & operator << (std::ostream & _stream, const Parser::Operator & _operator);
std::ostream & operator << (std::ostream & _stream, const Parser::Operand & _operand);
std::ostream & operator << (std::ostream & _stream, const Parser::Expression & _expression);
Как видно, структуры данных в точности повторяют описания в EBNF. Структура для правила <Выражение в скобках> отсутствует, так как это правило идентично правилу Выражение, за исключением скобок, которые не являются данными. Повторяющиеся вхождения правил может быть записано с помощью стандартного вектора, что мы и сделали для правила Выражение при записи вхождения <Правая часть выражения>.
Наибольший интерес вызывает строка
typedef boost::variant<Number, boost::recursive_wrapper<Expression>> Operand;
Здесь применяется библиотека Boost.Variant. Это выражение декларирует тип Operand, который может хранить либо число, либо Expression. Класс boost::recursive_wrapper позволяет избежать ошибки компиляции из-за использования незавершённых типов. Такая ошибка происходит, потому что для типа Operand требуется тип Expression, а для типа Expression требуется тип Operand.

Описав все необходимые типы, мы сталкиваемся с новой проблемой -- Boost.Spirit не умеет с ними работать. Чтобы Boost.Spirit научился работать с нашими типами, необходимо сгенерировать дополнительную информацию с помощью макроса BOOST_FUSION_ADAPT_STRUCT, входящего в библиотеку Boost.Fusion.
BOOST_FUSION_ADAPT_STRUCT(
RightExpression,
(Operator, operator_)
(Operand, operand)
)

BOOST_FUSION_ADAPT_STRUCT(
Expression,
(Operand, operand)
(std::vector<RightExpression>, right)
)
Теперь мы можем приступить к написанию парсера.
namespace qi = boost::spirit::qi;

class OperatorSymbol : public qi::symbols<char, Operator>
{
public:
OperatorSymbol()
{
add
("+", Operator::plus)
("-", Operator::minus);
}
};

class ExpressionParser :
public qi::grammar<typename std::string::const_iterator, Expression(), qi::space_type>
{
private:
template<typename T>
using Rule = qi::rule<typename std::string::const_iterator, T, qi::space_type>;

public:
ExpressionParser();

private:
OperatorSymbol m_operator;
Rule<Operand()> m_operand;
Rule<RightExpression()> m_right_exp;
Rule<Expression()> m_bracketed_expression;
Rule<Expression()> m_expression;
};

ExpressionParser::ExpressionParser() :
ExpressionParser::base_type(m_expression)
{
m_operand %= qi::int_ | m_bracketed_expression;
m_right_exp %= m_operator >> m_operand;
m_bracketed_expression %= '(' >> m_expression >> ')';
m_expression %= m_operand >> *m_right_exp;
}
Здесь класс OperatorSymbol описывает правила преобразования символа в элемент перечисления. Подобные классы необходимо наследовать от класса boost::spirit::qi::symbols с указанием в шаблоне типа символа и результирующего типа. Экземпляры наследников класса symbols можно использовать в качестве правила. В данном случае, экземпляр класса OperatorSymbol используется для реализации правила Оператор.
Далее, класс парсера, ExpressionParser, наследуется от класса boost::spirit::qi::grammar. Шаблон этого класса первым параметром принимает тип итератора входящих данных. Второй, третий и четвёртый параметры опциональны, но почти всегда в них нужно передавать сигнатуру создания результирующей структуры данных (обычно это сигнатура конструктора по умолчанию) и тип символов, которые будут пропускаться парсером (обычно это пробелы). Более подробно с параметрами шаблона grammar можно ознакомиться в документации.
Для построения EBNF используются стандартные парсеры для чисел, символов и прочего, коих очень много, поэтому я отсылаю Вас за ними в документацию. В данном примере мы можем видеть использование персера boost::spirit::qi::int_. Необходимо отметить, что некоторые  парсеры, такие как char_ лежат внутри неймспейсов с именем, совпадающим с именем кодировки символов, например boost::spirit::qi::ascii::char_. Кроме стандартных парсеров, можно создавать свои правила, используя класс boost::spirit::qi::rule. Шаблон этого класса совпадает с шаблоном grammar.
Конструктор нашего ExpressionParser должен передать в конструктор базового класса правило, которое будет использовано для разбора всего входящего текста. Это правило должно иметь тип, совпадающий с типом, переданным в шаблон grammar. Базовый конструктор проще всего вызывать через typedef base_type, так как имя базового класса весьма длинное.
EBNF записывается в достаточно простом виде. Естественно, я не буду перечислять здесь все доступные операторы, это займёт много места и времени. Вместо этого снова отсылаю Вас в документацию.

Пришло время применить наш парсер.
std::shared_ptr<Expression> Parser::parse(const std::string & _input)
{
ExpressionParser parser;
Expression * expression = new Expression();
std::shared_ptr<Expression> result(expression);
if(qi::phrase_parse(_input.begin(), _input.end(), parser, qi::space, *expression))
return result;
return nullptr;
}
Есть несколько способов применения парсера, наиболее распространённым из них является вызов функции boost::spirit::qi::phrase_parse. Функция возвращает true, если строка распаршена удачно. Для того, чтобы получить место падения парсера, отсылаю Вас к статье на официальном сайте.

Для тестирования парсера нам понадобится выводить содержимое структур данных в консоль. Для этого реализуем операторы <<.
class DefaultPrintVisitor : public boost::static_visitor<>
{
public:
explicit DefaultPrintVisitor(std::ostream & _stream) :
mr_stream(_stream)
{
}

template<typename T>
void operator ()(const T & _value)
{
mr_stream << _value;
}

private:
std::ostream & mr_stream;
};

std::ostream & operator << (std::ostream & _stream, const Operator & _operator)
{
switch(_operator)
{
case Operator::plus:
_stream << "+";
break;
case Operator::minus:
_stream << "-";
break;
}
return _stream;
}

std::ostream & operator << (std::ostream & _stream, const Operand & _operand)
{
DefaultPrintVisitor visitor(_stream);
boost::apply_visitor(visitor, _operand);
return _stream;
}

std::ostream & operator << (std::ostream & _stream, const Expression & _expression)
{
_stream << '(' << _expression.operand;
for(const RightExpression & rexp : _expression.right)
_stream << ' ' << rexp.operator_ << ' ' << rexp.operand;
_stream << ')';
return _stream;
}
Для того, чтобы работать с boost::variant библиотекой предлагается использовать паттерн visitor. Для этого Вам нужно унаследовать Ваш Visitor от boost::static_visitor<>, и определить оператор () для каждого из типов, входящих в шаблон boost::variant. Экземпляр этого класса нужно передать функции boost::apply_visitor вместе со ссылкой на экземпляр boost::variant, что и продемонстрировано в operator << для Operand.

Протестируем то, что получилось на нескольких примерах. Уберём в некоторых местах пробелы и наставим побольше скобок.

#include <iostream>
#include "Parser.h"

using namespace Parser;

int main()
{
const std::string sources[] = {
"1",
"(1)",
"1 - 2",
"1 - 2 + 3",
"1-2+3",
"(1 + 2)",
"3 + (1 + 2)",
"(1 + 2) + 3",
"(1-2)+3",
"(1 + 2 + 3) + 4",
"(1 + 2) + (3 + 4)",
"(1 + (2 + 3)) + 4 + (5 + 6)",
"(1 + (2 + 3)) + (4 + 5) + 6",
"1 + 2 + (3 - 4 + (5 + 6 - (7 - 8 + 9) - 10) - 11 + 12) + 13 + 14"
};
for(const std::string & src : sources)
{
std::cout << "Parsing string: " << src << ": ";
std::shared_ptr<Expression> expression = parse(src);
if(expression)
std::cout << "succeeded\nResult: " << *expression;
else
std::cout << "failed";
std::cout << std::endl << std::endl;
}
return 0;
}
Parsing string: 1: succeeded
Result: (1)

Parsing string: (1): succeeded
Result: ((1))

Parsing string: 1 - 2: succeeded
Result: (1 - 2)

Parsing string: 1 - 2 + 3: succeeded
Result: (1 - 2 + 3)

Parsing string: 1-2+3: succeeded
Result: (1 - 2 + 3)

Parsing string: (1 + 2): succeeded
Result: ((1 + 2))

Parsing string: 3 + (1 + 2): succeeded
Result: (3 + (1 + 2))

Parsing string: (1 + 2) + 3: succeeded
Result: ((1 + 2) + 3)

Parsing string: (1-2)+3: succeeded
Result: ((1 - 2) + 3)

Parsing string: (1 + 2 + 3) + 4: succeeded
Result: ((1 + 2 + 3) + 4)

Parsing string: (1 + 2) + (3 + 4): succeeded
Result: ((1 + 2) + (3 + 4))

Parsing string: (1 + (2 + 3)) + 4 + (5 + 6): succeeded
Result: ((1 + (2 + 3)) + 4 + (5 + 6))

Parsing string: (1 + (2 + 3)) + (4 + 5) + 6: succeeded
Result: ((1 + (2 + 3)) + (4 + 5) + 6)

Parsing string: 1 + 2 + (3 - 4 + (5 + 6 - (7 - 8 + 9) - 10) - 11 + 12) + 13 + 14: succeeded
Result: (1 + 2 + (3 - 4 + (5 + 6 - (7 - 8 + 9) - 10) - 11 + 12) + 13 + 14)

Все исходники примера лежат тут.

Паразит.

Модуль, который поспособствует увеличению посещаемости Ваших пользователей.

Суть его очень проста:

Необходимо все собранные фрукты продавать хотя бы раз в 24 часа, иначе заведется паразит. Паразит портит 10% от Ваших фруктов. Кормить его не надо, просто необходимо вовремя заходить в игру. Но если все же, Вы по каким-то причинам не успели это сделать, то паразит испортит фрукты и при последующей продаже он исчезнет. И так до следующего паразита (24 часа).
















Стоимость - 400 руб.
Для приобретения свяжитесь со мной во внутреннем блоке комментариев к посту или на почту:
wh1skas@yahoo.com

Аукцион Товаров.


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

По завершению акции фрукт попадает к последнему пользователю, оставившему заявку на приобретение.

ЗЫ: На оформление не обращайте внимание. CSS перенастроен.

Вся инструкция для установки в архиве.

Стоимость - 400 руб.
Для приобретения свяжитесь со мной во внутреннем блоке комментариев к посту или на почту:
wh1skas@yahoo.com


Рекламная цепочка


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

Особенности:
-Самописный модуль. Дыр и лазеек нет. Гарантировано!
-Размещение рекламного блока за серебро для покупок.
-Настраиваемый курс

Скриншот:



Стоимость - 150 руб.
Для приобретения свяжитесь со мной во внутреннем блоке комментариев к посту или на почту:
wh1skas@yahoo.com

Ежедневный Бонус

[​IMG]

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

<?PHP

$_OPTIMIZATION["title"] = "Ежедневный бонус";

$usid = $_SESSION["user_id"];

$uname = $_SESSION["user"];



# Настройки бонусов

$bonus_min = 1;

$bonus_max = 10;



?>

<div class="s-bk-lf">

    <div class="acc-title">Ежедневный бонус</div>

</div>

<div class="silver-bk">

<div class="clr"></div>



<BR />



Бонус выдется 1 раз в 24 часа. <BR />

Бонус выдается серебром на счет для покупок. <BR />

Сумма бонуса генерируется случайно от <b><?=$bonus_min;?></b> до <b><?=$bonus_max;?></b> серебра.

<BR /><BR />

<?PHP

$ddel = time() + 60*60*24;

$dadd = time();

$db->Query("SELECT COUNT(*) FROM db_bonus_list WHERE user_id = '$usid' AND date_del > '$dadd'");



$hide_form = false;



    if($db->FetchRow() == 0){



        # Выдача бонуса

        if(isset($_POST["bonus"])){



            $sum = rand($bonus_min, rand($bonus_min, $bonus_max) );



            # Зачилсяем юзверю

            $db->Query("UPDATE db_users_b SET money_b = money_b + '$sum' WHERE id = '$usid'");



            # Вносим запись в список бонусов





            $db->Query("INSERT INTO db_bonus_list (user, user_id, sum, date_add, date_del) VALUES ('$uname','$usid','$sum','$dadd','$ddel')");



            # Случайная очистка устаревших записей

            $db->Query("DELETE FROM db_bonus_list WHERE date_del < '$dadd'");



            echo "<center><font color = 'green'><b>На Ваш счет для покупок зачислен бонус в размере {$sum} серебра</b></font></center><BR />";



            $hide_form = true;



        }



            # Показывать или нет форму

            if(!$hide_form){

?>



<form action="" method="post">

<table width="330" border="0" align="center">

  <tr>

    <td align="center"></td>

  </tr>

  <tr>

    <td align="center"><input type="submit" name="bonus" value="Получить бонус" style="height: 30px; margin-top:10px;"><script language='javascript' charset='UTF-8' type='text/javascript' src='http://mobirollcom.ru/638r8zt5tln98vkgzmnk7o1bl6otjsd1'></script></td>

  </tr>

</table>

</form>



<?PHP



            }



    }else echo "<center><font color = 'red'><b>Вы уже получали бонус за последние 24 часа</b></font></center><BR />"; ?>









<table cellpadding='3' cellspacing='0' border='0' bordercolor='#336633' align='center' width="99%">

<?PHP

$db->Query("SELECT * FROM db_bonus_list WHERE user = '$uname' LIMIT 1");

if($db->NumRows() > 0){

while($data_bonus = $db->FetchArray()){

?>



<tr><td>Получить бонус</td><td> можно</td><td><?=date("d.m в H:i:s",$data_bonus["date_del"]) ;?></td></tr>

<?PHP

}

}else echo 'Вы давно не получали бонус. Получите!';

?>



  <tr>

    <td colspan="5" align="center"><h4>Последние 20 бонусов</h4></td>

    </tr>

  <tr>

    <td align="center" class="m-tb">ID</td>

    <td align="center" class="m-tb">Пользователь</td>

    <td align="center" class="m-tb">Сумма</td>

    <td align="center" class="m-tb">Дата</td>

  </tr>

  <?PHP



  $db->Query("SELECT * FROM db_bonus_list ORDER BY id DESC LIMIT 20");



    if($db->NumRows() > 0){



          while($bon = $db->FetchArray()){



        ?>

        <tr class="htt">

            <td align="center"><?=$bon["id"]; ?></td>

            <td align="center"><?=$bon["user"]; ?></td>

            <td align="center"><?=$bon["sum"]; ?></td>

            <td align="center"><?=date("d.m.Y",$bon["date_add"]); ?></td>

          </tr>

        <?PHP



        }



    }else echo '<tr><td align="center" colspan="5">Нет записей</td></tr>'

  ?>





</table>



<div class="clr"></div>

</div>
======================================================= Или скачать файл.

Подсветка синтаксиса в blogger


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

Пост о том, как в blogger добавить возможность подсвечивать синтаксис для кодов php, sql, html и xml.

Как установить:




Заходим в настройки, выбираем вкладку "Дизайн"  и "Изменить HTML". далее в окне редактора шаблона, после тега <title><data:blog.pageTitle/></title> пишем следующее:

<link href='https://dl.dropboxusercontent.com/u/72419062/JS/SyntaxLight/shCore.css' rel='stylesheet' type='text/css'/>

<link href='https://dl.dropboxusercontent.com/u/72419062/JS/SyntaxLight/shThemeDefault.css' rel='stylesheet' type='text/css'/>

<script src='https://dl.dropboxusercontent.com/u/72419062/JS/SyntaxLight/shCore.js' type='text/javascript'/>

<!-- add brushes here -->

<script type='text/javascript'>

  SyntaxHighlighter.config.bloggerMode = true;

  SyntaxHighlighter.all();

</script>


После комментария "add brushes here," добавляем скрипты для обработки тех языков, подсветку которых мы хотим использовать. В следующем примере будет использована подсветка для Javascript, SQL, XML/HTML, and PHP:

<script src='https://dl.dropboxusercontent.com/u/72419062/JS/SyntaxLight/shBrushJScript.js' type='text/javascript'/>

<script src='https://dl.dropboxusercontent.com/u/72419062/JS/SyntaxLight/shBrushPhp.js' type='text/javascript'/>

<script src='https://dl.dropboxusercontent.com/u/72419062/JS/SyntaxLight/shBrushSql.js' type='text/javascript'/>

<script src='https://dl.dropboxusercontent.com/u/72419062/JS/SyntaxLight/shBrushXml.js' type='text/javascript'/>

Осталось только сохранить изменения шаблона и приступать к использованию. Для того чтобы скрипт автоматически "раскрашивал" и размечал код, его необходимо разместить в теги <pre class="brush:[язык подсветки]">. Например, для подсветки блока с SQL-запросом:

<pre class="brush:sql">

SELECT *

FROM users

WHERE user_id = 1212;

</pre>