7百万件のデータから1秒以内に波形表示をする

波形表示のサンプルソフトを作っている途中。

20100926_01.jpg

ちと、自分のメモとして。

  • 周波数 2,000 Hz で、約1時間(3,600秒)ということなので、データ数は、7.2M のデータとなる。
  • チャンネル数は 32ch 程度

このデータを、グラフで描画すると、ひどく大変。

データ数が 700万件なんて、まともに処理しようとすると専用のデータベースでも難しい。

のだが、ちょっとコツがあって、

  • 描画するときには、ディスプレイの解像度が上限になる

というものがある。

つまり、横幅は、たかだか 1000ドット程度で十分な訳で、700万件を1000程度に集約すればよいわけだ。

ただ、

ここにも数学、という物理的なトリックを利用する必要があって(サンプリング理論ともいうけど)、

振動値を、普通にサンプリングしてしまう(間引いてしまう)と、本来必要なデータが欠損してしまう場合がある。

欠損というのは、

  • 振動自体は、200Hz の範囲で変化する。
    → 0.1 秒の単位で注視が必要。

という条件がある。

言い換えれば、調べる目的というものがある。

それに沿っていえば、単純に間引いてしまうのは、ちょっとまずい。

200プロットの範囲で、どのくらいの重要なデータ(検出したい異常値)が現れるか、によってサンプリングの方法を工夫する必要がある。

なので、このような振動を検知する場合には、集約対象の範囲で、

  • 単位範囲内の最大値を抽出してプロット
  • 単位範囲内の最小値を抽出してプロット

というサンプリングをしないと、検出したい異常値が取れない。

そんな訳で、先の画像は、最大値と最小値をプロットしている、というわけ。

また、このような方法をとると、単純サンプリング(間引きの方法)とは異なり、集約範囲を自由に決めることができる。

ただし、これもダメな場合があって、

  • 最小値、最大値で振動する場合、これの範囲で超えて、集約させてはいけない。

のですね。

このあたりは、理論になるので省略(気が向いたら、書きます、メモ的に)。

というわけで、この方法をとると、たかだかプロットするデータは1,000ドットになるので、データを集約する計算だけになります。

な訳で、結構なスピード(1秒以下)で、7.2Mのデータが処理できますね。

という話。

 

 

 

カテゴリー: 開発 | 7百万件のデータから1秒以内に波形表示をする はコメントを受け付けていません

アリスはプラダの中古がお嫌い

プラダの鞄の話の続き。

■プラダの鞄を共有する

いままで、プラダの鞄をポインタとして話してきましたが、クラスとして扱うとちょっと違った形になります。

 Prada *prada = new Prada();
 Alice.Present( prada );

な形で、Present メソッドを使って、アリスにすることを考えてみると、実はプラダの鞄は、ロリータにもプレゼントできることが分かります。

 Prada *prada = new Prada();
 Alice.Present( prada );
 Lolita.Present( prada );

ってな訳ですね。
これは、プラダの鞄をアリスにもロリータにもプレゼントができる、っていう意味でデータを共有します。

20100921_01.jpg

一見、これで十分なような気もしますが、実は微妙なところがあるのです。

■ロリータは中古のプラダなのよ

そうなんです。

 Prada *prada = new Prada();
 Alice.Present( prada );
 Lolita.Present( prada );

こうしたときには、ロリータに渡るプラダは「中古」なんですね。一度、アリスが使っている(というかプレゼントされている)ので、ロリータが貰う prada とアリスが貰う prada とは微妙に違います。

20100921_02.jpg

メモリなので変わらないだろう?という話があるでしょうが、分かり易いように Prada クラスに Used フラグを追加してみましょう。

C++の場合は、こんな感じ。

 class Prada {
  public:
   bool Used ;
 };

C#やJavaの場合は、こんな感じ。

 class Prada {
  public bool Used ;
 }

さて、この状態でアリスの Present メソッドを次のように定義すると。


 
 class Alice {
  public:
   bool Present( Prada *prada ) {
    if ( prada->Used == true ) {
     return false;
    }
    prada->Used = true;
    return true;
   }
 };


ほら、プラダの鞄が「中古(Used)」になりますね。

このあたりが、オブジェクト指向のポリフォリズム(隠蔽化)の利用です。

そんな訳で、ロリータに渡されるプラダの鞄は、中古である可能性がある、ということですねw

20100922_01.jpg

そうすると、

 Prada *prada = new Prada();
 if ( Alice.Present( prada ) == false ) {
  // 激怒ッ!!!
 }
 if ( Lolita.Present( prada ) == false ) {
  // 激怒ッ!!!
 }

という話も作れます。アリスが「激怒ッ!!!」するときは、いきなり中古を私たときです。

例えば、ファクトリークラス「大黒屋」を使うと、
 
 Prada *prada = Daikokuya.Buy();
 if ( Alice.Present( prada ) == false ) {
  // 激怒ッ!!!
 }

ええ、アリスは激怒するかもしれません。

■ Used フラグを隠蔽化してプロパティっぽく

ここで、使用済みフラグ(Used)は、public にして直接変更できるようにしましたが、ここの仕組みを「フィールド」とか「プロパティ」とか「属性」とか言います。
使用済みフラグだとイメージがしづらいので、メソッドに変えると、いわゆるC#のプロパティの例になります。


 class Prada {
  private:
   bool used ;
  public:
   void Used() {
    used = true;
   }
 };

ってな感じで、Used メソッドってのを作ります。
先の例だと、used = false って設定すると、「中古」から「新品」に勝手に変えることができるから、こんな風に「新品」→「中古」の一方通行の制限ができるといいですよね。
いわゆる、書き込み専用のプロパティ(あるいはメソッド)ってことです。

この場合も同じで、

 class Alice {
  public:
   bool Present( Prada *prada ) {
    prada->Used();
    …
    return true;
   }
 };

となって、

 Prada *prada = new Prada();
 if ( Alice.Present( prada ) == false ) {
  // 激怒ッ!!!
 }
 if ( Lolita.Present( prada ) == false ) {
  // 激怒ッ!!!
 }

こうすると、ロリータが「激怒ッ!!!」するようにしたい。

bool used は非公開(private)だから、使いづらいのでは?と思いますが、さにあらず。例外なんかを使うと結構シンプルに書けます。

 class Prada {
  private:
   bool used ;
  public:
   Prada() {
    used = false;
   }
   void Used() throw Gekido {
    if ( used == true ) {
     throw new Gekido();
    }
   }
 };

こんな風に、Used メソッドを使うときは最初の1回だけにしておきます。
このパターンは結構多くて、データベースを Close した後、ファイルハンドルを閉じた後に呼び出されないようにガードする時に便利ですね。

例外をとらえるために、Present メソッドはこうなります。

 class Alice {
 public:
  bool Present( Prada *prada ) {
   try {
    prada->Used();
   } catch {
    return false;
   }
   return true;
  }
 };

used フラグ、Used メソッドの使い方が異なりますね。

「激怒ッ!!!」を例外でも良いのであれば、シンプルに

 class Alice {
 public:
  void Present( Prada *prada ) throw Gekido {
   prada->Used();
  }
 };

と書いてしまって、

 Prada *prada = new Prada();
 try {
  Alice.Present( prada );
  Lolita.Present( prada );
 } catch {
  // 激怒ッ!!!
 }

な風にしても良いです。
この違いは、例外すると、アリスとロリータのどちらが激怒したか分かりません。

■「激怒ッ!!!」例外の位置を変えるのがベターかなと。

ちと、書いてしまってから思ったのですが、この例外の仕方は状況にそぐわないのです。というのも、例外を発生させているのが Prada クラスの Used メソッド内ってのが変ですよね。
プラダの鞄が「激怒ッ!!!」するのは変です(苦笑)。

というのも、

・アリスは中古のプラダを貰ったら、激怒する。
・ロリータは中古のプラダでも我慢する。

っていうパターンができません。

なので、利用フラグのsetter/getterを用意して(C#ならばプロパティ)にしておいて、アリスやロリータがそれぞれ getter を使って中古かどうかをチェックする(あるいはチェックしない)ってのがベターです。

 class Prada {
  private:
   bool used ;
  public:
   Prada() {
    used = false;
   }
   void setUsed() {
    // 利用設定のみ
    used = true;
   }
   bool getUsed() {
    return used ;
   }
 };

という形にしておいて、

 class Alice {
  public:
   bool Present( Prada *prada ) throw Gekido {
    if ( prada->getUsed() == true ) {
     throw new Gekido();
    }
    return true;
   }
 };

こんな風に、getUsed メソッドでチェックします。

 Prada *prada = new Prada();
 try {
  Alice.Present( prada );
  Lolita.Present( prada );
 } catch {
  // 激怒ッ!!!
 }

そうすると、例外を catch できますね。

カテゴリー: 開発, C++ | アリスはプラダの中古がお嫌い はコメントを受け付けていません

プラダの鞄をおねだりするのが参照

プラダの鞄をおねだりするのが参照

プラダの鞄の続きです。
元ネタは、深読みのし過ぎだった訳ですが、ネタとして引き続き。

プラダの鞄をおねだりするときには、いくつかパターンがあるので、書き上げてみます。

■この箱にプラダの鞄を入れてパターン

<001>

 Prada *prada = NULL;
 Lewis.Onedari( &prada );

この prada ポインタは、アリスが用意する箱です。
ルイス君に「この箱にプラダの鞄を入れてね」とお願いするわけで、後で箱の中身を確認するのが、

 Prada *prada = NULL;
 Lewis.Onedari( &prada );
 if ( prada == null ) {
  // 激怒ッ!!!
 }

な訳ですね。

ここの部分、プラダの箱を直接チェックするのが「アリス」。
ルイス君が自己申告(プラダの鞄を入れたか、いれなかったか)をするパターンは次の書き方。

 Prada *prada = NULL;
 if ( Lewis.Onedari( &prada ) != true ) {
  // 激怒ッ!!!
 }

この違いは大きいですよね。

  • prada をチェックするのが、アリスの場合
  • prada をチェックするのが、ルイスの場合(自己申告)

という具合です。
前者の場合は、ルイスに責任はありません、というかアリスはルイスの振る舞いに疑いを持っています。
後者の場合は、ルイスの自己申告なので、実際は箱の中にプラダの鞄が入っているか分かりません。

ええ、そうなんです。
アリスが、ルイスに対してどれだけ疑いを持っているか(あるいは信じているか)にかかっています。

ちなみに、プログラマは疑い深いのでw、後者の場合でも

 Prada *prada = NULL;
 if ( Lewis.Onedari( &prada ) != true ) {
  // 激怒ッ!!!
 }
 if ( prada == null ) {
  // 激怒ッ!!!
 }

なことをやりますねw

■プラダの箱ごと頂戴ねパターン

先のアリスは、ご丁寧にプラダの箱に鞄を入れてくれることを期待しましたが、プラダの箱ごともらうパターンもあります。

 Prada *prada = Lewis.Onedari();

ルイスにおねだりをすると、プラダを箱ごとくれますね。
# 「箱」ってのはポインタなのか、メモリなのか、ってのがありますけど、この場合はメモリってことで。

これよく見ると Factory Pattern ですよね。Lewis がファクトリーで、Ondeari が Create メソッドって訳です。
Java の場合は、このファクトリパターンが多くって、C++の世界では、new演算子が多いです。ただし、この比較は正確ではなくて、

  • Factory.Create の場合は、ファクトリクラスにより Create を制御できる。
  • new 演算子の場合は、取得するクラスそのものだけになる。

ってことです。

具体的には、

 Prada *prada1 = Lewis.Onedari();
 Prada *prada2 = Nabokov.Onedari();

なところで、ルイスとナボコフにおねだりをすると、くれるのは同じプラダであっても、別のものです(あるいはプラダですらなかったりw)。

new 演算子を使う場合は、

 Prada *prada = new Prada();

になるので、おねだりをするというよりも、プラダ工場から直接購入って感じになります。

というわけで、

プラダの鞄の利用許可を与える件(委譲)のパターンは、また後日ということで。

カテゴリー: 開発, C++ | 2件のコメント

プラダの鞄を直接あげるのが値渡し

プラダの鞄を手渡しするのが、「値渡し」なのはOKとして、

新作プラダが売っていたら、と教えるのが「参照渡し」なのは、納得がいか~んッ!!!

ということで、図解。

話題にしたのは、PHP なんだろうけど、ちょっと C++ で図解。

PHP 版、C# 版も後ほど、作ります?

■直接、手渡せば「値渡し」

値渡しってのは、実は、コピーが発生するので、あまり正確ではないのだが、

こんな感じ。

20100917_02.jpg

struct Prada prada ;

Alice.Plesent( prada );

な感じですね。

実は、C++ の場合は、変数のコピーがスタック上で渡されるので、下図のようになるのが本当です。

20100917_03.jpg

■予約券渡して、参照渡し

そんなもののだから、一度、こっちで購入して(newして)、ポインタだけ渡します。

これが参照渡し。C#やJavaだと、これがデフォルトですね。

20100917_04.jpg

Prada *prada = new Prada();

Alice.Plesent( prada );

こんな感じ。ルイスは、鞄を買うわけですね。後で、取りに来て具合。

後に取りに来るにしても、new した場合は、アリスは百貨店に取りに行くわけですが、ルイスとしては自分の処に取りに来て欲しいわけで、

Prada prada;

Alice.Plesent( &prada );

とすると、自分のところに取りに来てくれます。

■レンタル品も、参照渡しで

ところで、高級品はレンタルでもいいんじゃないか、とか。

皆で共有すればいいんじゃない?ってな考え方もありますよね。

20100917_05.jpg

Prada *prada = new Prada();

Alice1.Plesent( prada );

Alice2.Plesent( prada );

Alice3.Plesent( prada );

確保した鞄を、それぞれのアリスに予約券で配ります。

いらなくなったら、ってな話は、C++の場合大変なのですが、C#やJavaの場合はGC(ガベージコレクション)ですね。

逆に言えば、誰かが使っている間はプラダは確保されます。

■おねだりは、参照渡しで

参照渡しのもうひとつの使い方が、おねだりパターンです。

ええ、訳が分かりませんね。図解します。

20100917_06.jpg

これが欲しい、とルイス君に言うと買ってくれます。

コードにすれば、

Prada *prada ;

Lewis.Onedari( &praga );

こんな風になります。

Onedari メソッドを呼ぶと、prada の中身をくれます。

たまに買ってくれないとき(nullのとき)があるので、注意が必要ですが。

■空箱を渡すと例外が発生する

ちなみに、参照渡しをするときに、nullポインタを渡すとエラーになりますね。

20100917_07.jpg

Prada *prada = null;

Alice.Plesent( prada );

箱を開けて見れば、空っぽッ!!、Alice は大激怒です。

そんな訳で、呼び出された側でも null チェックは必要ですよね。

ええ、元ネタは、これということでw

20100917_08.jpg

カテゴリー: 開発, C++ | 1件のコメント

wordpressで、はてなブックマークへのリンクを表示

WordPress ではてなブックマーク数を表示 | Sun Limited Mt.
http://www.syuhari.jp/blog/archives/152

こちらを参考にして、タイトルにはてなブックマークを入れてみました。

20100917_01.jpg

簡単なプラグインみたいなのがあればいんですが、直接 php を変更。

loop.php 140行目あたり

  <div id=”post-<?php the_ID(); ?>” <?php post_class(); ?>>
   <h2 class=”entry-title”><a href=”<?php the_permalink(); ?>” title=”<?php printf( esc_attr__( ‘Permalink to %s’, ‘twentyten’ ), the_title_attribute( ‘echo=0’ ) ); ?>” rel=”bookmark”><?php the_title(); ?></a><a href=’http://b.hatena.ne.jp/entry/<?php the_permalink(); ?>’>
  <img src=”/images/b_entry.gif”></a>
</h2>

single.php 24行目あたり

    <div id=”post-<?php the_ID(); ?>” <?php post_class(); ?>>
     <h1 class=”entry-title”><?php the_title(); ?>
     <a href=’http://b.hatena.ne.jp/entry/<?php the_permalink(); ?>’><img src=”/images/b_entry.gif”></a></h1>

loop.php は、「HOME」をクリックしたときの、最新記事のところ。

single.php は、記事のタイトルをクリックしたときの、単独の記事を表示しているところです。

記事の URL は、the_permalink 関数を使います。

はてな自体は、あまり活用してない(kidtwi.jp用にひとつキープしているけど)のですが、たまに

[TopHatenar] www.moonmile.net さんの順位
http://tophatenar.com/entry/210750/BTS+Develop(%E4%BB%AE)

なんかを見ると、あったほうがいいのかな?と思ったりします。

個人的には、このブログが自分の情報の中心になっているので、「はてなブックマーク風に、wordpress でブックマークを管理できる」と良いかなと。

ちょっと、妄想すると、

  1. wordpress に、はてなブックマーク風の、ページを用意する。
  2. ブラウザに、wordpress ブックマーク(仮)へのブックマーレットを付けておく。
    → はてなブックマークと同じで、URL経由で、wordpress api を呼び出す。
  3. wordpress api で受けたブックマークを、ページに書き込む。
    → この時、一言コメントを付ける。

はてなと違って、wordpress は個別になるので、あくまで個人メモ用になりますね。

他の人のブックマークと共有できればいいんだけど、それだと「はてなブックマーク」を使えばいいわけで、あまり意味がないし。

最近は、twitter に、「【メモ】」というヘッダを付けて流すようにしています。これは、

Google の検索で、「【メモ】 site:twitter.com/moonmile」とすると、自分のメモが一発でわかるので便利なんです。

こんな風にできたらよいかなと。

 

カテゴリー: Wordpress | 5件のコメント

wordpresssで対応しているxml-rpc api

wordpress の xml-rpc は、

XML-RPC wp « WordPress Codex
http://codex.wordpress.org/XML-RPC_wp

にあるのですが、ところどころ間違っています。blogid のところが、int 型と string 型が混在していて、xml-rpc のクライアントを実装してくとエラーになります、ってな具合です。

さて、ブログ系の xml-rpc は、種類が色々あって、

[WordPress] XML-RPC を使用する方法 | Sun Limited Mt.
http://www.syuhari.jp/blog/archives/1373

を参考にすると、

  • mt.* で始まる Movable Type
  • metaWeblog.* で始まる MetaWeblog
  • blogger.* で始まる Blogger
  • wp.* で始まる wordpress

と様々です。

一体、どれが対応しているのか?良くわからないので、結局は、ソースを見ることになります。

# まぁ、原点/原典に戻るというこでw

xmlrpc.php をそのまま見ると、133行目あたりから、 以下のように一覧が見れます。

 function wp_xmlrpc_server() {
        $this->methods = array(
            // WordPress API
            'wp.getUsersBlogs'      => 'this:wp_getUsersBlogs',
            'wp.getPage'            => 'this:wp_getPage',
            'wp.getPages'           => 'this:wp_getPages',
            'wp.newPage'            => 'this:wp_newPage',
            'wp.deletePage'         => 'this:wp_deletePage',
            'wp.editPage'           => 'this:wp_editPage',
            'wp.getPageList'        => 'this:wp_getPageList',
            'wp.getAuthors'         => 'this:wp_getAuthors',
            'wp.getCategories'      => 'this:mw_getCategories',      // Alias
            'wp.getTags'            => 'this:wp_getTags',
            'wp.newCategory'        => 'this:wp_newCategory',
            'wp.deleteCategory'     => 'this:wp_deleteCategory',
            'wp.suggestCategories'  => 'this:wp_suggestCategories',
            'wp.uploadFile'         => 'this:mw_newMediaObject', // Alias
            'wp.getCommentCount'    => 'this:wp_getCommentCount',
            'wp.getPostStatusList'  => 'this:wp_getPostStatusList',
            'wp.getPageStatusList'  => 'this:wp_getPageStatusList',
            'wp.getPageTemplates'   => 'this:wp_getPageTemplates',
            'wp.getOptions'         => 'this:wp_getOptions',
            'wp.setOptions'         => 'this:wp_setOptions',
            'wp.getComment'         => 'this:wp_getComment',
            'wp.getComments'        => 'this:wp_getComments',
            'wp.deleteComment'      => 'this:wp_deleteComment',
            'wp.editComment'        => 'this:wp_editComment',
            'wp.newComment'         => 'this:wp_newComment',
            'wp.getCommentStatusList' => 'this:wp_getCommentStatusList',

            // Blogger API
            'blogger.getUsersBlogs' => 'this:blogger_getUsersBlogs',
            'blogger.getUserInfo' => 'this:blogger_getUserInfo',
            'blogger.getPost' => 'this:blogger_getPost',
            'blogger.getRecentPosts' => 'this:blogger_getRecentPosts',
            'blogger.getTemplate' => 'this:blogger_getTemplate',
            'blogger.setTemplate' => 'this:blogger_setTemplate',
            'blogger.newPost' => 'this:blogger_newPost',
            'blogger.editPost' => 'this:blogger_editPost',
            'blogger.deletePost' => 'this:blogger_deletePost',

            // MetaWeblog API (with MT extensions to structs)
            'metaWeblog.newPost' => 'this:mw_newPost',
            'metaWeblog.editPost' => 'this:mw_editPost',
            'metaWeblog.getPost' => 'this:mw_getPost',
            'metaWeblog.getRecentPosts' => 'this:mw_getRecentPosts',
            'metaWeblog.getCategories' => 'this:mw_getCategories',
            'metaWeblog.newMediaObject' => 'this:mw_newMediaObject',

            // MetaWeblog API aliases for Blogger API
            // see http://www.xmlrpc.com/stories/storyReader$2460
            'metaWeblog.deletePost' => 'this:blogger_deletePost',
            'metaWeblog.getTemplate' => 'this:blogger_getTemplate',
            'metaWeblog.setTemplate' => 'this:blogger_setTemplate',
            'metaWeblog.getUsersBlogs' => 'this:blogger_getUsersBlogs',

            // MovableType API
            'mt.getCategoryList' => 'this:mt_getCategoryList',
            'mt.getRecentPostTitles' => 'this:mt_getRecentPostTitles',
            'mt.getPostCategories' => 'this:mt_getPostCategories',
            'mt.setPostCategories' => 'this:mt_setPostCategories',
            'mt.supportedMethods' => 'this:mt_supportedMethods',
            'mt.supportedTextFilters' => 'this:mt_supportedTextFilters',
            'mt.getTrackbackPings' => 'this:mt_getTrackbackPings',
            'mt.publishPost' => 'this:mt_publishPost',

            // PingBack
            'pingback.ping' => 'this:pingback_ping',
            'pingback.extensions.getPingbacks' => 'this:pingback_extensions_getPingbacks',

            'demo.sayHello' => 'this:sayHello',
            'demo.addTwoNumbers' => 'this:addTwoNumbers'
        );

例えば、wordpress の記事を取得するための API は、metaWeblog.getPost なので、mw_getPost メソッドを見ると、

入力値がこんな感じ

 /**
     * Retrieve post.
     *
     * @since 1.5.0
     *
     * @param array $args Method parameters.
     * @return array
     */
    function mw_getPost($args) {

        $this->escape($args);

        $post_ID     = (int) $args[0];
        $username  = $args[1];
        $password   = $args[2];

出力値がこんな感じ

         $resp = array(
                'dateCreated' => new IXR_Date($post_date),
                'userid' => $postdata['post_author'],
                'postid' => $postdata['ID'],
                'description' => $post['main'],
                'title' => $postdata['post_title'],
                'link' => $link,
                'permaLink' => $link,
                // commented out because no other tool seems to use this
                //        'content' => $entry['post_content'],
                'categories' => $categories,
                'mt_excerpt' => $postdata['post_excerpt'],
                'mt_text_more' => $post['extended'],
                'mt_allow_comments' => $allow_comments,
                'mt_allow_pings' => $allow_pings,
                'mt_keywords' => $tagnames,
                'wp_slug' => $postdata['post_name'],
                'wp_password' => $postdata['post_password'],
                'wp_author_id' => $author->ID,
                'wp_author_display_name'    => $author->display_name,
                'date_created_gmt' => new IXR_Date($post_date_gmt),
                'post_status' => $postdata['post_status'],
                'custom_fields' => $this->get_custom_fields($post_ID),
                'sticky' => $sticky
            );

            if ( !empty($enclosure) ) $resp['enclosure'] = $enclosure;

            return $resp;

ってな感じで分かります。

現在は、コマンドライン版を作成中。

 

 

カテゴリー: Wordpress | 1件のコメント

XML-RPC.NETを使ってカスタムフィールドを設定

.NET(C#)でXML-RPCを使ってブログに投稿する | Moonmile Solutions Blog

http://www.moonmile.net/blog/archives/1284 

の続きです。 

xml-rpc.net を使って、wordpress のカスタムフィールドを設定します。 

カスタムフィードってのは、記事に付随する情報で、WEB上でブログを書くときに追加できます。 

20100915_02.jpg 

カスタムなので、文字列ならば何でも入る(BASE64を使えばバイナリも入る)のですが、私がこれを使う理由は、書籍サイトを作る時のページ数とセクション名を入れるんですね。 

これを手作業でWEB上で、ぽちぽち入れるのは非常に面倒くさい。というか、間違えます。 

なので、クライアントツールを使って、一気に落とし込みます。 

xml-rpc.net を使って、カスタムフィールドを送信する場合は、 

    public interface IBlogger : IXmlRpcProxy
    {
        [XmlRpcMethod("metaWeblog.newPost")]
        string newPost(
            string blogid,
            string username,
            string password,
            Content content,
            bool publish);
    } 

    public struct Fields
    {
        public string key;
        public string value;
    }
    public struct Content
    {
        public string title;
        public string description;
        public DateTime dateCreated;
        public Fields[] custom_fields;
    }

な風に、metaWeblog.newPost メソッドを使います。 

カスタムフィールドは配列になっています。 

# List<Fileds> だと駄目だったので、配列しか駄目な模様。 

送信する時は、 

        public void BllogerNewPostWP(string title, string desc )
        {
            //プロキシクラスのインスタンスを作成
            IBlogger proxy = (IBlogger)
                CookComputing.XmlRpc.XmlRpcProxyGen.Create(
                typeof(IBlogger));
            //URLを指定
            proxy.Url = url;
            Console.WriteLine("url: " + url);

            string id = "";
            // content を生成
            Content cont;
            cont.title = title;
            cont.description = desc;
            cont.dateCreated = DateTime.Now;
            cont.custom_fields = new Fields[2];
            cont.custom_fields[0].key = "page";
            cont.custom_fields[0].value = "10";
            cont.custom_fields[1].key = "section";
            cont.custom_fields[1].value = "1.1.1";
            try
            {
                Console.WriteLine("title: " + title);
                //blogger.getRecentPostsを呼び出す
                id = proxy.newPost(
                    "1",            // 念のため1にしておく
                    username,
                    password,
                    cont,
                   true);
            }
            catch (Exception ex)
            {
                Console.WriteLine("エラー:" + ex.Message);
                return;
            }

            //結果を表示する
            Console.WriteLine("id: " + id);
        }

という感じです。 

フィールドの生成が、ちょっと不様ですが、まあ、所詮ツールなので。 

これを実行すると、無事カスタムフィールドが設定されます。 

20100915_03.jpg 

次は、これらを使ってコマンドラインから記事の投稿ができるようにします。 

方法としては、 

  1. テキストエディタで編集する。
  2. 適当なツールを通して、HTML形式へ変換する。
  3. 適当なツールを通して、ヘッダ部を付ける。
  4. 投稿ツールで、wordpress へ投稿。

みたいな感じです。 

投稿するときのフォーマットは、俗にいう mail フォーマットで、ヘッダ部とボディ部に分けます。 

ID:   <記事のID> ... 編集時に使う
Date:   <投稿日時>
Title:  タイトル
Page:   <該当ページ>
Section:  <章番号>

本文が続く
...

のような感じ。 

ID:   100
Date:  2010/09/15 12:00:00
Title:  Linux初心者の基礎知識
Page:   2
Section: 1.2

<H3>ハードディスクのデバイスファイル名</H3>
<p>
ハードディスクには、SCSI、IDE、SATAなどがありますね。
Linuxからみると、デバイスファイル名といいまして、
</p>
<pre>
IDEは「/dev/hda」など
SCSI,SATAは「/dev/sda」など
</pre>
となります。

のようなフォーマットで送れるようにする予定です。

カテゴリー: Wordpress | XML-RPC.NETを使ってカスタムフィールドを設定 はコメントを受け付けていません

wordpressのXML-RPCレスポンスが欠ける

ちと、メモ的に。

IIS 7.0 上に WordPress 3.0 を入れた状態で、XML-RPC を使って投稿しようとすると、レスポンスが2バイト欠けます。

故に、

Response from server does not contain valid XML.

なるエラーが出ます。

XML-RPC.NET ライブラリを試しても、BlogWrite を試しても駄目なので、おそらく、IIS + PHP + wordpress の組み合わせが駄目です。


<?xml version=”1.0″?>
<methodResponse>
  <params>
    <param>
      <value>
        <array><data>
  <value><struct>
  <member><name>isAdmin</name><value><boolean>1</boolean></value></member>
  <member><name>url</name><value><string>http://localhost/wp/</string></value></member>
  <member><name>blogid</name><value><string>1</string></value></member>
  <member><name>blogName</name><value><string>local blog</string></value></member>
  <member><name>xmlrpc</name><value><string>http://localhost/wp/xmlrpc.php</string></value></member>
</struct></value>
</data></array>
      </value>
    </param>
  </params>
</methodRespons

こんな風に最後の2バイトが欠けます。おそらく、UTF-8 BOM の分だけ加算し忘れて、content-length が間違っているかと。

同じソースを動かしても、linux 上の wordpress は ok です。

ソース自体は、

.NET(C#)でXML-RPCを使ってブログに投稿する | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/1284

を参照。

エラーの回避方法は分からず。

環境としては、

  • windows 7
  • PHP 本家(MSのPHPではない)
  • WordPress 本家(MSのPHPではない)
  • IIS 7.0

ですね。他の組み合わせでは未定です。

追記 2010/09/14

解決法を見つけました。

wp-includes/class-IXR.php の 339 行目あたりに、XML-RPCのレスポンスを返しているので、


        // Create the XML
        $xml = <<<EOD
<methodResponse>
  <params>
    <param>
      <value>
        $resultxml
      </value>
    </param>
  </params>
</methodResponse>



EOD;
        // Send it
        $this->output($xml);
    }

のように、</methodResponse> の後ろに2バイト分、改行を増やしてやります。

本来はlengthを変えるところなのですが、乱暴ですが、これでIISでも動きます。

カテゴリー: Wordpress | 4件のコメント

wordpress のカテゴリ一覧をアメブロ風にする

wordpress を使って独自サイトを作ろうと思って、いくつか調べ。

どうやら、wordpress 3.0 からは、いくつかテンプレートが違っている模様で、と言いますか、PHP 初心者なものだから、何処から始めても良いということで。

Main Page – WordPress Codex 日本語版
http://wpdocs.sourceforge.jp/

カスタマイズするには、上記のサイトから始めればいいらしいです。

まぁ、この手のカスタムはコードを読んで諸々を進める訳ですが(他人様のコードのデバッグと同じですね…デバッグとは違うけど)、wordpress 3.0 から、ちょっと面白い仕組みが備わっているので紹介。

投稿したい記事を表示したり、一覧を表示したりするページをカスタムする場合、大抵はテーマのphpを直接編集すると思います。と言いますか、修正しちゃうのが「テーマ」ですよね。

けれど、wordpress 3.0 の標準で付いてくるテーマはこんな仕組みになっています。

cotegory.php を見ると

<001>


<?php
/**
 * The template for displaying Category Archive pages.
 *
 * @package WordPress
 * @subpackage Twenty_Ten
 * @since Twenty Ten 1.0
 */

get_header(); ?>

  <div id=&quot;container&quot;>
   <div id=&quot;content&quot; role=&quot;main&quot;>

    <h1><?php
     printf( __( 'Category Archives: %s', 'twentyten' ), '<span>' . single_cat_title( '', false ) . '</span>' );
    ?></h1>
    <?php
     $category_description = category_description();
     if ( ! empty( $category_description ) )
      echo '<div>' . $category_description . '</div>';

    /* Run the loop for the category page to output the posts.
     * If you want to overload this in a child theme then include a file
     * called loop-category.php and that will be used instead.
     */
    get_template_part( 'loop', 'category' );
    ?>

   </div><!-- #content -->
  </div><!-- #container -->

<?php get_sidebar(); ?>
<?php get_footer(); ?>

な風に、get_template_part 関数なるものが用意されています。

これ、通常は、loop.php を呼び出すのですが、loop-category.php を用意すると、そっちの php ファイルを呼び出す、なかなか面白い仕組みです。

C# を知っていると、デリゲートに似ていると言えます。

ループの中身を後から、インジェクション(挿入)する仕組みですね。

これによって、便利なのは、

  • このテンプレートをバージョンアップしても、loop-category.php は上書きされない(自作だから)ので、そのままテンプレートをバージョンアップできる。
  • 他のテンプレートを適用しても、同じ仕組みであれば、loop-category.php を使い廻しできる。

という再利用性の問題がクリアできる点です。

PHP の場合、手軽にソースを書き換えられる分、それぞれのユーザー(プログラマ)がカスタムしているところを、どうやってバージョンアップするのか?という回答になっていますね。

C# な話だと、

  • インターフェースを作っておいて、DLLを動的にロード

な形になります。

さて、

この category-loop.php に至ったのは、カテゴリの一覧をカスタムしたかったからで、通常のカテゴリ一覧だと本文の一部とかが出て、ちょっと閲覧性が悪いんですよね。どうせならば、アメブロ風に一覧で出て欲しい(そのほうがクリックしやすいし)。

という訳で、作ってみたのがこれ。

<002>


<?php
 $cat_name = single_cat_title( '', false );
 $cat_id = get_cat_ID( $cat_name );
 $posts = get_posts(&quot;numberposts=1000&order=DESC&orderby=post_date&category=$cat_id&quot;);

 if ( $posts ) : ?>
 <table width=&quot;100%&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; border=&quot;0&quot;>
  <?php 
   $i = 1;
   foreach ( $posts as $post ) :  setup_postdata( $post );
  ?>
   <tr>
    <td><?php echo $i ?></td>
    <td>
     <a href=&quot;<?php the_permalink(); ?>&quot;><?php the_title(); ?></a></td>
    <td><?php echo $post->post_date; ?></td>
    <td>コメント(<?php echo $post->comment_count; ?>)</td>
   </tr>
  <?php
   $i++;
   endforeach; ?>
 </table>
<?php endif; ?>

ページ送りが無いので、いまいちですが、ひとまずPHP初心者としてはOKかな、と

出来上がりは、こんな感じ。

20100912_01.jpg

スタイルシートを変えれば、もうちょっとマシになるかなと。

同様に、カレンダーで月を選択した場合は loop-archive.php を作ります。

<003>


<?php
 global $wpdb;

 $date = get_the_date();
 $year = intval(get_the_date('Y'));
 $month = intval(get_the_date('m'));
 $day = intval(get_the_date('d'));

if ( is_month() ) {

 $sdate = $year . &quot;/&quot; . $month . &quot;/01&quot;;
 if ( $month < 12 ) {
  $edate = $year . &quot;/&quot; . ($month+1) . &quot;/01&quot;;
 } else {
  $edate = $year+1 . &quot;/&quot; . 1 . &quot;/01&quot;;
 }
 $sql = <<< HERE
select
  *
FROM
 $wpdb->posts  
WHERE
    post_status = 'publish'
and post_type = 'post'
and '$sdate' <= post_date and post_date < '$edate'
order by post_date desc
HERE;
} else {
 $sdate = $year . &quot;/&quot; . $month . &quot;/&quot; . $day;
 $sql = <<< HERE
select
  *
FROM
 $wpdb->posts  
WHERE
    post_status = 'publish'
and post_type = 'post'
and '$sdate' = cast(post_date as date)
HERE;

}

?>
<?php
  $posts = $wpdb->get_results( $sql );
 if ( $posts ) : ?>
 <table width=&quot;100%&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; border=&quot;0&quot;>
  <?php 
   $i = 1;
   foreach ( $posts as $post ) :  setup_postdata( $post );
  ?>
   <tr>
    <td><?php echo $i ?></td>
    <td>
     <a href=&quot;<?php the_permalink(); ?>&quot;><?php the_title(); ?></a></td>
    <td><?php echo $post->post_date; ?></td>
    <td>コメント(<?php echo $post->comment_count; ?>)</td>
   </tr>
  <?php
   $i++;
   endforeach; ?>
 </table>
<?php endif; ?>

データベースを直接弄っているのは、それらしい関数がなかったので。

デザイナさんが改修すると、さすがに SQL 周りは触れないのでは?と思うので、プログラマが wordpress を弄るとこんな風に、という例として。

という訳で、table タグを使っているのは、ご愛嬌ということで。

カテゴリー: Wordpress | 2件のコメント

年賀状ソフトができましたよ

ここ1週間ほど、乃木坂に来ていますが、やっとこさ、年賀状ソフトが完成しました。

いえ、完成とは言っても、デザイナさんの画像の差し替えなんですけどね。

付属のCD-ROM/DVDに、年賀状ソフトがついています。

20100910_01.jpg

来年は、うさぎ年という訳で、うさぎな画像が満載です。

CD-ROMに入っている、背景の画像を選択して、自前の写真を差し込みすると、この通り

20100910_03.jpg

そのまま、はがきの裏面に印刷できます。

でもって、住所録も装備。簡易版ではありますが。

20100910_04.jpg

パソコンにあるフォントを使って、書き換えることもできます。

20100910_05.jpg

秀和システムさんから、9月末ごろに、

  • デジカメ年賀状
  • 世界一おしゃれな年賀状
  • そのまま使えるスペシャル年賀状
  • そのまま使える年賀状データ大全10000

で書店に並びます。

不具合、要望なんてのがある場合は、秀和システムさんにメールにて、あるいは、直接メールなどでどうぞ。

カテゴリー: ツール | 年賀状ソフトができましたよ はコメントを受け付けていません