MT4:MTの変数演算をプラグインで拡張
Movable Type4.1以降でよく使用するようになった、変数での演算。この前、乱数が用いたいと思ったんだが、標準のテンプレートタグではできない。JavaScriptでやるにしても、それはクライアントコンピュータ側での処理となり、テンプレートの処理分岐などには使えない。
これを拡張するプラグインを試作してみた。標準のMTSetVarテンプレートタグにop="+"などというモデファイアを付与する標準の方式では、計算時の左辺がnameモデファイア、右辺がvalueモデファイアとなるので、慣れていない方へは直感的にわかりづらい(と思う)し、記述のやり方が(例えば単に乱数や三角関数の結果が欲しいときなどは)面倒くさい。
Movable Type4.1以降で動作する(他の環境ではチェックしていない)。
プラグインソース
以下参照。
package MT::Plugin::CalcExp;
use strict;
use MT;
use MT::Plugin;
use base qw(MT::Plugin);
use POSIX;
my $plugin = new MT::Plugin::CalcExp({
id => "CalcExp",
key => "CalcExp",
name => "CalcExp",
version => '0.1',
description => "<MT_TRANS phrase=\"The Calculation Value(Expand) \">",
author_name => "apstar",
author_link => "http://www.mtde.info/",
});
MT->add_plugin($plugin);
sub init_registry {
my $plugin = shift;
$plugin->registry({
'tags' => {
'function' => {
'CalcExp' => \&_hdlr_getvalue,
},
},
});
}
sub _hdlr_getvalue {
my($ctx, $args) = @_;
my $op = $args->{op};
my $base = $args->{base};
my $palam = $args->{palam};
use constant PI => 3.14159265358979;
if (('+' eq $op) || ('add' eq $op)) {
return $base + $palam if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif (('-' eq $op) || ('sub' eq $op)) {
return $base - $palam if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif (('*' eq $op) || ('mul' eq $op)) {
return $base * $palam if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif (('/' eq $op) || ('div' eq $op)) {
return $base / $palam if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif (('%' eq $op) || ('mod' eq $op)) {
# Perl % is integer only
$base = int($base);
$palam = int($palam);
return $ctx->error(MT->translate('Division by zero.'))
if $palam == 0;
return $base % $palam if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif (('++' eq $op) || ('inc' eq $op)) {
return ++$base if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif (('--' eq $op) || ('dec' eq $op)) {
return --$base if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif (('&' eq $op) || ('join' eq $op)) {
return $base . $palam;
}
elsif ('zero' eq $op) {
return sprintf("%0".$palam."d", $base);
}
elsif ('rand' eq $op) {
return $base + int(rand($palam))+1 if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif ('int' eq $op) {
return int($base) if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif ('round' eq $op) {
return round($base, $palam) if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif ('floor' eq $op) {
return floor($base) if defined $base && $base =~ m/^\-?[\d\.]+$/; #by POSIX
}
elsif ('ceil' eq $op) {
return ceil($base) if defined $base && $base =~ m/^\-?[\d\.]+$/; #by POSIX
}
elsif ('sin' eq $op) {
return sin($base) if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif ('cos' eq $op) {
return cos($base) if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif ('tan' eq $op) {
return sin($base)/cos($base) if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif ('deg2rad' eq $op) {
return ($base / 180) * PI if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif ('rad2deg' eq $op) {
return ($base / PI) * 180 if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif ('log' eq $op) {
return log($base) if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif ('pow' eq $op) {
return ($base ** $palam) if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif ('sqrt' eq $op) {
return sqrt($base) if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
return $base;
}
sub round {
my $val = shift;
my $col = shift;
my $r = 10 ** $col;
my $a = ($val > 0) ? 0.5 : -0.5;
return int($val * $r + $a) / $r;
}
1;
使い方
計算の種類がopモデファイア、元の値がbaseモデファイア、計算用のいじくりパラメータがpalamモデファイアとなる。例えば、乱数がほしいときはbaseが100、palamが10、opが"rand"であれば90-110の範囲で値を返す。
palamパラメータが必要ないものもある。整数丸めとか。それはopモデファイア(int)とbaseモデファイア(12.3456など)のみを渡せばよく、palamモデファイアは不要。
モデファイアについてドキュメントなど書きたいが、いまのとこそういうものはない。
参考になるかどうかアレだが、コードは以下参照。
(足し算)
<MTSetvar name="value1" value="111">
<MTSetvar name="value2" value="21">
<MTCalcExp base="$value1" palam="$value2" op="+">
<br />
(引き算)
<MTSetvar name="value1" value="111">
<MTSetvar name="value2" value="21">
<MTCalcExp base="$value1" palam="$value2" op="-">
<br />
(掛け算)
<MTSetvar name="value1" value="111">
<MTSetvar name="value2" value="21">
<MTCalcExp base="$value1" palam="$value2" op="*">
<br />
(割り算)
<MTSetvar name="value1" value="111">
<MTSetvar name="value2" value="21">
<MTCalcExp base="$value1" palam="$value2" op="/">
<br />
(余剰)
<MTSetvar name="value1" value="111">
<MTSetvar name="value2" value="21">
<MTCalcExp base="$value1" palam="$value2" op="%">
<br />
(文字列連結)
<MTSetvar name="value1" value="週間">
<MTSetvar name="value2" value="秩父伝説">
<MTCalcExp base="$value1" palam="$value2" op="join">
<br />
(乱数)
<MTSetvar name="value1" value="0">
<MTSetvar name="value2" value="100">
<MTCalcExp base="$value1" palam="$value2" op="rand">
<br />
(ゼロ埋め)
<MTSetvar name="value1" value="71">
<MTSetvar name="value2" value="4">
<MTCalcExp base="$value1" palam="$value2" op="zero">
<br />
(四捨五入)
<MTSetvar name="value1" value="123.456789">
<MTSetvar name="value2" value="3">
<MTCalcExp base="$value1" palam="$value2" op="round">
<br />
(整数化)
<MTSetvar name="value1" value="123.456789">
<MTSetvar name="value2" value="">
<MTCalcExp base="$value1" palam="$value2" op="int">
<br />
(切り捨て)
<MTSetvar name="value1" value="123.456789">
<MTSetvar name="value2" value="5">
<MTCalcExp base="$value1" palam="$value2" op="floor">
<br />
(切り上げ)
<MTSetvar name="value1" value="123.456789">
<MTSetvar name="value2" value="5">
<MTCalcExp base="$value1" palam="$value2" op="ceil">
<br />
(べき乗)
<MTSetvar name="value1" value="2">
<MTSetvar name="value2" value="16">
<MTCalcExp base="$value1" palam="$value2" op="pow">
<br />
(平方根)
<MTSetvar name="value1" value="144">
<MTSetvar name="value2" value="">
<MTCalcExp base="$value1" palam="$value2" op="sqrt">
<br />
(sin)
<MTSetvar name="value1" value="30">
<MTSetvar name="value2" value="">
<MTCalcExp base="$value1" palam="$value2" op="sin">
<br />
(cos)
<MTSetvar name="value1" value="30">
<MTSetvar name="value2" value="">
<MTCalcExp base="$value1" palam="$value2" op="cos">
<br />
(tan)
<MTSetvar name="value1" value="30">
<MTSetvar name="value2" value="">
<MTCalcExp base="$value1" palam="$value2" op="tan">
<br />
(角度→rad)
<MTSetvar name="value1" value="30">
<MTSetvar name="value2" value="">
<MTCalcExp base="$value1" palam="$value2" op="angle2rad">
<br />
(rad→角度)
<MTSetvar name="value1" value="0.789">
<MTSetvar name="value2" value="">
<MTCalcExp base="$value1" palam="$value2" op="rad2angle">
<br />
特記事項
参考にしたのはこちら。
Open MagicVox.net | 変数操作を無駄に拡張するMovableTypeプラグイン:MathOperatorExpander# 今の私にはヨダレもんの記事が盛りだくさんで、最近はちょくちょくお邪魔しています。クオリティの高い記事をありがとうございます。
ほか、プラグインを作るために必要になりそうな知識を公開しているサイトをチョコチョコ訪問した。今回作成したのは簡単な練習のためのファンクションタグなので、MTの中の中まで調べることはやっていない。
それと、MT4の/lib/MT/Template内のContextHandlers.pmの8500行目辺り以降に_math_operation関数があるので、そちらが参考になる。
このプラグインは自分で使用する前提であるので、拡張性を持たせたい。まず、使いそうな関数を初めから準備した。Asset画像を拡大・縮小した際の数値の丸め。四捨五入・切捨て・切り上げなどがいるかと思い、初めから実装している。これはperlの標準命令でもいけるんだが、切捨てと切り上げはperlのPOSIXモジュールという便利ライブラリ内に関数が(floor、ceilですな)あったので、それを利用している。将来的にPOSIXから使用したい関数が出てきたとき、最初からプラグインに実装しておくと有利かな...などと考えた。
あと私は、三角関数や角度→ラジアン演算なんかは本職ではよくやるのだ。一応つけてみた。スタイルシートの何かを三角関数を用いて計算...することは、今のところは、...ないだろうけど。
- カテゴリ:212MT4.1実験室
トラックバック(0)
このブログ記事を参照しているブログ一覧: MT4:MTの変数演算をプラグインで拡張
このブログ記事に対するトラックバックURL:
- Categories
- Entries
-
- MT4のテンプレートタグとプラグインでサインカーブを描く
- MT4.1:クマーを色々(MTSetvarTemplate)
- MT4分科会第2回勉強会に参加しました
- MTOS4.2RC1:各ページの拡張子を得る
- MTでAA
- MT4:MTの変数演算をプラグインで拡張
- MT4.1:「MT」という文字をテーブルの背景色で表現
- 「NabeAzzテンプレート問題・パート2」へ乗ってみる
- 作りたいプラグインの覚え書き
- 世界のナベアツをプラグインで表現
- MT4:世界のナベアツをテンプレートタグで表現(2)
- MT4.1:プラグインを書いてみよう
- MT4.1:予約変数の実験
- Movable Type 4.15 テスト中(1)
- mtde.info の、反省点
- mtde.info の、できる経緯
- MT4:前のエントリ・次のエントリのリンクをカテゴリごとに(条件あり)
- MT4:世界のナベアツをテンプレートタグで表現
- MT4.1:カテゴリ並べ替え・表示非表示切り替え(非プラグイン非カスタムフィールド)
- MT4.1:変数参照専用のモジュールの可能性
- MT4:XHTML+CSS素材テンプレート化の不具合修正・要望リスト
- MT4.1:Movable Type 4.1用テンプレート作った
コメントする