архив | Программирование RSS for this section

Command line calculator on Rails — dentaku

Итак, сегодня в моём блоге наконец появится первая запись по Ruby on Rails.

При разработке системы административного учёта для одного из моих клиентов на Rails я столкнулся с маленькой проблемой. Заказчик изъявил желание самостоятельно создавать новые тарифы, по которым производится расчёт платежей клиентов организации. Это значит что алгоритм работы тарифа не должен являться внутренней частью приложения. Необходимо пользователю дать возможность самостоятельно разрабатывать формулы, по которым и будут производиться расчёты. На самом деле это не проблема, это обычная практика — не обращаться же к программисту каждый раз, когда нужно изменить способ расчёта.

Для решения такой задачи тарифы легче всего хранить в виде:

ID      Name          Formula
1       rate1         var1+var2/var3
2       rate2         var1+var2/var3-100

При расчёте нужно просто извлечь формулу из БД, подставить переменные, рассчитать получившееся выражение и вывести результат пользователю. Самая большая сложность заключается именно на стадии «рассчитать получившееся выражение»…

В ход пошёл Google. Осознав, что найти простую и корректную функцию на Ruby (да и не только на Ruby), способную на входе принять нечто вроде «486+67/2-100», а результатом выдать «419,5», мне не удастся, я взялся за поиски информации на тему разработки простого синтаксического анализатора… И зря потерял время.

В Ruby on Rails не принято изобретать велосипед. Большинство велосипедов уже изобретено в виде гемов. Они хорошо хранятся, легко доступны и успешно причёсываются сообществом. Оказывается и мой велосипед давно изобретён. Называется он Dentaku.

Dentaku — это небольшой гем, позволяющий анализировать арифметические и логические выражения. На вход принимает строку типа «2+2*2», на выходе даёт результат операции «6».

Dentaku поддерживает работу с переменными и следующие операции:

  • Математические: + — * /
  • Логические: < > <= >= <> != = AND OR
  • Функции: IF ROUND

Для начала нужно его установить. На Rails 3 достаточно в Gemfile просто прописать:

gem 'dentaku'

А затем выполнить в директории проекта:

bundle install

После чего увидеть его в списке установленных гемов:

Теперь можно его использовать

def calculate
      calculator = Dentaku::Calculator.new
      calculator.evaluate("2+4") #простое выражение
      calculator.evaluate("2+4/4*8-3*6") #более сложное выражение
      calculator.evaluate("var1+4/4*8-var2*6", 
                           :var1 => 3, :var2 => 6) #выражение с переменными
end

 

Страница на Github — https://github.com/rubysolo/dentaku

GlassFrame в Embarcadero RAD Studio 2010

В Embarcadero RAD Studio 2010 существует возможность создания эффекта полупрозрачности Aero для фона окна. Называется этот эффект GlassFrame, но при его включении появляется проблема, связанная с тем, что надписи на кнопках, расположенных на этом окне становятся нечитабельными, а лейблы с темным шрифтом и вовсе пропадают.

Решается эта проблема путём установки свойства формы «DoubleBuffered» в значение «True».

Delphi. Перевод в универсальный формат даты для SQL Server

SQL Server, начиная с версии 2005 понимает универсальный формат даты, не зависящий от региональных настроек yyymmdd.

Перегнать любую DateTime переменную в этот формат можно с помощью процедуры.

DateTimeToString(str,’yyymmdd’,Now);

Более подробную информацию можно получить здесь

Как изменить стандартный crHandPoint на системный (Delphi)

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

 Screen.Cursors[crHandPoint]:=LoadCursor(0,IDC_HAND);

При изменении размеров TImage размер его Canvas не меняется (Delphi)

Иногда возникает ситуация, когда необходимо в ходе выполнения программы изменить размеры компонента TImage, а потом на его холсте что-то нарисовать. Но все новые рисунки на холсте TImage ограничены старыми габаритами. Как это решить?

Необходимо вместе с размерами TImage изменить размеры его Bitmap.

Image1.Height := 80;
Image1.Width := 33;
Image1.Picture.Bitmap.Height := 80;
Image1.Picture.Bitmap.Width := 33;

Кто вызвал PopupMenu? (Delphi)

Маленькое лирическое отступление

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

Кто вызвал PopupMenu?

Для того, чтобы узнать, к примеру, имя компонента, вызвавшего появление PopupMenu нужно обработать событие клика (или какое вам нужно) следующим образом.

procedure Form.N11Click(Sender: TObject);
  begin
  ShowMessage(PopupMenu1.PopupComponent.Name);
  end;

О наболевшем. Даже IE8 они сделали… они не доделали…

Ну как так? Я конечно не претендую на звание матёрого вёб-программиста, но IE8 почему-то отказался обрабатывать последовательность вида:

<script type="text/javascript">
айлалэлалы
</script>
<form>
<input type="button" value="У" onclick="ajax_loadContent('Texts','Clean.php');" class="but">
<input type="button" value="Ы" onclick="ajax_loadContent('Texts','Go.php');" class="but">
</form>

Он просто наитупейшим образом тупил!! Зато в опере всё норм, как надо… И я полтора часа бился в истериках от мысли: «Неужели я такой тупой, что не смогу просто перепечатать скрипт с исходника??!!» В исходнике последовательность <script> — <form> такая же, и самое главное, что там всё работает. Я чуть ежика не родил, пока ко мне не пришла мысль о том, чтобы переставить конструкции местами и свести вышенаписанное к:

<form>
<input type="button" value="У" onclick="ajax_loadContent('Texts','Clean.php');" class="but">
<input type="button" value="Ы" onclick="ajax_loadContent('Texts','Go.php');" class="but">
</form>
<script type="text/javascript">
айлалэлалы
</script>

От крываю ИЕ и вижу долгожданный результат… 70% меня радовалось от того, что проблема решена, но 30% офигевало от количества затраченных нервов и времени… Вот так вот бывает…

alvisX