Perl スクリプトに assertion code を埋め込む実験中2006年12月05日 21時56分09秒

この記事の続きというか後日談というか。現在製作中の若干大きめのプロジェクトにおいて、自作の assertion code がそれなりに役立っているので、一応現状使っているものとほぼ等価のコードを示しておこうと思う。

sub assert (&) {
    return      unless $debug_mode;
    shift->()   and return;
    
    # assertion 失敗時の処理
    my (undef, $filename, $line) = caller;
    my $main_file = main::__FILE__;
    print STDERR <<ENDLINE;
$main_file: Assertion faild at $filename line $line
** Call stack **
ENDLINE
    my $i = 0;
    while (my ($pkg, $file, $l, $sub, undef, undef, $evaltxt, $is_req) = caller $i++){
        $is_req = $is_req ? 'YES' : 'NO';
        print <<ENDLINE;
    -- stack frame #$i: at $file (package $pkg) line $l --
ENDLINE
        print $file eq '(eval)' ? <<ENDEVALBLOCK : $sub eq '(eval)' ? <<ENDEVALTEXT : <<ENDSUB;
        type        : eval block
        is require  : $is_req
ENDEVALBLOCK
        type        : eval text
        is require  : $is_req
        eval text   :
$evaltxt
ENDEVALTEXT
        type        : subroutine
        subroutine  : $sub
ENDSUB
    }
    die "\n";
}

使い方としては、例えばこんな感じ。

$debug_mode = 1;    # 本来このインターフェースはもうちょっと別の形で用意されるべき

# 最大値を求める
sub maxNumber {
    my $max = shift     or return;
    for my $number (@_){
        assert { $number eq $number + 0 };  # 数値以外の値は渡されないはず
        $max = $number  if $max < $number;
    }
    
    $max
}

my $num1 = maxNumber -2, -70, 6, 4.3;
print "num1: $num1\n";
my $num2 = maxNumber 37, -256, 1.25e+17, 'infinity';    # assertion faild!!
print "num2: $num2\n";

実用的かどうかはまだ検討中。プロジェクトではまだ小さいデータでしか試せてないのよ。もしかしたら実用には耐え難いほどに処理を重くしてしまうかもしれない (しょっちゅう無名関数を生成するし、少なくともデバッグモードか否かの判定は行われるからね)。

ただ、おいらの場合、大き目のプログラムを作る場合において、部品となる部分のプログラムを作って動作を確認しながら、それらを繋ぎ合わせて大きくする、という手順は踏まずに、大まかに設計した枠組みに沿って全体をどかっと書き始め、問題点をフィードバックしつつ実装し、ある程度出来上がったところで試しに走らせてバグ潰しをする、というやり方で作ってしまうことが多いので、assertion code を埋め込む仕組みがあるのと無いのとではバグ潰しのはかどり具合が全然違ってきてしまう。そういう意味では今のところ、かなり重宝していたりします (それだけバグが多いということですが。。。T-T/)。

union って、そーいやあんま使ったことなかったなぁ2006年12月05日 23時34分13秒


プログラミング言語C 第2版 (訳書訂正版) ANSI規格準拠

(B.W.カーニハン / D.M.リッチー / 石田晴久 訳 / 共立出版)

C では union を reinterpret_cast 代わりに使えるよ、というお話。へぇぇ。

個人的には、union 使うと実数値の実装が見えておもろいなぁとか思った。そんだけなので tb はなし。w

しかし K&R おさらいしてみたら、malloc するときの境界の整合のために union を使う例が示されてた。そうか union ってこういう風に使うものだったっけか。(なにをいまさら)

チェーン×××の問題点2006年12月06日 01時03分57秒

まだ話の筋はイマイチ読みきれていないのですが、とりあえず以下の記事にだけ tb 飛ばしておきますね。

本質的な問題

チェーンメールやチェーン日記 (ブログにおける「転載」による情報の拡散) において、最も問題となるのは、情報の拡散が無期限に継続しうることにあります。

大分昔の話ですが、とある友人から、以下のようなメールが届きました。

突然ですが、みなさんの中でもしくは知り合いなどで
血液型がRH(-)AB型の方がおりましたら以下宛てでご一報ください。

〔内容〕
○○(私の友人の会社です)社員の奥さんが妊娠されておりますが、
先日入院され ました。 病名は、【全前置胎盤】です。
(全前置胎盤…胎盤が逆になって子宮口を覆っている為、
出産時は帝王切開で胎児を取り出し、胎盤を除去する)
出産予定は、8月初旬でありましたが、この為、7月初旬(第一週位)に帝王
切開 し、胎児の取り出し及び、胎盤の除去を行います。
帝王切開の際、輸血が必要ですが上記血液型の為病院でも輸血用血液が全然
足りなく、また、集まるか否かが問題になっております。

(...中略...)

この件は、絶対自分で止めず、必ず、周りの友達、家族、親戚、
会社関係の人に伝え、情報を収集してください。

その友人は他の多くの友人にも同内容のメールを発信していました。

そこで、おいらは以下のように返信しました。

 標記の件、一応、発信元の方に確認のため連絡のメールを入れさせて
いただきました。
 事実が確認出来次第、ホームページのほうで公表する予定です。

 新しいことがわかり次第、また連絡します。
 協力してメールを発信してしまった以上、責任はとるように(^_^;)。

同時に、連絡先として記述されていたメールアドレス宛に、以下のメールを送信しました。

Subject: 確認させてください

 知人より以下のメールが転送されました。
 あなたから発信されて事実のものであるか確認させてください。
 確認出来次第、拙ホームページにて転載させていただきます。
 不特定多数の人間が着てくれるほど立派なページではありませんが、
私の交友関係にある知人には一通り迅速に広められると思います。

 事実であるならばまどろっこしくて慎重すぎる私の対応はいささか
失礼なものかもしれませんが、なにとぞご回答をよろしくお願い申し
上げます。

(以下、送られてきたメールの内容...)

その対応はどうなのよとかいうモヒカン族の突っ込みはもうちょっと待ってね。当時のおいらのリテラシーではそれが限度だった。

すると、確認メールを送った方の方から、以下のような返信がありました。

Subject: 献血の件、お詫び

初めまして、△△ (当事者のお名前) と申します。
先日、私が献血に関するメールを発信したところ、
多数の御回答を頂きました。
まことに有り難うございました。
しかしながら、結果としてチェーンメールの様な形になってしまい、
皆様に大変な御迷惑をかける結果となってしまいました。
私も確認せずメールを転送しまい反省している次第です。
こころよりお詫び申し上げます。
以後、この件をチェーンメールの様な形で転送するのは控えて頂いた方が
良いのではないかと思っています。

しかしながら、今回私の処に送られてきたメールは事実でありまして、
また、6月3日に緊急手術の末、無事出産されたそうです。
詳細は、病院ホームページにて確認して下さい。

(病院名と URL)

せっかくの皆様の善意が、無駄骨になってしまったかもしれませんが
無事解決したとのことで、お許し願いたいと思います。
よろしくお願い申しあげます。

さて。

この方から発信されたチェーンメールは、紛れもなく善意のものであることが証明されました。

それは目出度いことではあるのですが、当初の問題 (RH(-)AB型の血液不足) が解決したあとに、新たな問題として、伝播し続けるチェーンメールを受け取った方への対応を、取り続けなければならないという問題が発生してしまいました。

チェーンメールやチェーン日記などの問題の本質は、実はここにあります。トラフィックとかは、業者による spam なんかと比較すれば、些細な問題です。つまり、当初の問題はとっくの昔に片付いているのに、古い情報だけが独り歩きして伝播し続けてしまうのです。これは、伝播する情報の内容とは関係なく、必ず存在する問題です。

「善意」の永続性

棒の手紙、というのをご存知でしょうか? 元々は「不幸の手紙」であったものの、変遷を遂げて変化した代物です。これは極端な例であり、なによりコピー&ペーストが可能な電子媒体においては、無関係な問題であるようにも見えるでしょう。

しかし、意図的に内容を改ざんした上で、転載する、という行為は十分有り得ます。善意の問題が絡んでくるのは、恐らくこの領域ということになって来るでしょう。悲しいことですが、情報の伝播において、善意は、必ずしも劣化せず伝播し続けるとは限らないのです。

例えば (これもまた極端な例ですが)、寄付を訴える記事に、寄付をする先の口座番号が記述されていた場合、転載した人間は、その口座番号を自分のものに書き換えてしまうかもしれません。もちろん、詐欺罪が当てはまりますので、法による担保はあるのですが、こういう詐欺行為をする人間は、至って逃げ足も速いものです ;-P

じゃあ、どうすればいいの?

緊急を要する事態において、多くの人に情報を伝播しなければならない。そんな場合、実際にはどのような手段を取るべきでしょうか。

昔も今も変わらぬこととして、そのようなケースにおいては、少なからず、コストを払う必要があるということを、まずは肝に銘じておくべきです。たとえば、自分の足と時間を使ってたくさんの街を訪問して回る、といった作業を、かつては要していたわけです。

それに変わるものとして、効果的な代案を提案するならば。。。例えば、Google AdWords を利用する、というのはどうでしょうか? Google の広告システムは、Google の検索結果のみならず、たとえば当サイトにおいても利用している Google AdSense 広告などにも広がっており、多くのサイトにおいて、関連する記述があれば広告が表示される可能性があります。例えば、最初に示した実例のような、輸血を求める SOS の場合、病名や「輸血」などのキーワードを盛り込むことによって、医療・福祉系のサイトや、慈善団体関連のサイトなどにおいて表示される可能性があり、輸血に関してより関心の高い方々への情報の伝播が期待できます。

あるいは、もっと良い方法を提供しているサービスはあるかもしれません。また、情報の伝播を手助けするためのサイト「呼びかけ.com」のようなものが登場してくれても良いような気もします。誰かやらないですかね? ;-)

おいおい。。。2006年12月06日 10時52分22秒

こうして地方の IT 関連企業はますます廃れていくわけだな。ビバ無責任マスゴミ。

  • 地元には、大規模で最新技術を用いるような案件が(少)ない
  • 地域性もあるのか、プロジェクトマネジメントが“ゆるゆる”である。東京に行って、最先端の高度なプロジェクトマネジメントに触れたい

地方で案件が少ない点についてはまぁそうかもしれんが、プロジェクトマネジメントの地域間における格差を語る根拠は何? 「なんとなくそんな気がする」とかじゃないよね?

そもそもこの国の IT 関連企業に、プロジェクトマネジメントがまともな職場って、いったいどれくらい存在するものなんだろう。。。

富山の某社もがんがってたぜ! (←ヤメレ)

若年生活者の労働意識と成果主義・年功序列…つーかむしろおいらの昔話w2006年12月06日 16時24分54秒

業界にもよりますが、かつては会社の昼休みにビールを飲むという風景はそう珍しいことではなかったように思います。それも今は昔。この数年、日本人の労働意識は、ものすごく真面目な方向に向かっているようです。読者のみなさんの中で、昼休みにビールを飲んだことのある方は、ご注意下さい。調査結果によれば、あなたはかなりの少数派のようですから。

背広着て働いていたうちに、一度はやってみたかったと思っていたのは内緒w 春日町で働いていた頃、近くの「庄や」によく昼飯を食いに行っていたのですが、昼まっぱらから背広姿や作業服姿でビールやら焼酎やらを飲むおっちゃんというのは少なからずいたから、その辺は世代を隔てて常識が異なるんだろうなということはなんとなく知っていました。

結局それをやる勇気は (かつての職場では) 無かったのですが、その割には、夜、焼き肉屋に繰り出して散々飲んでから、職場に戻ってきて作業の続き、なんてことは何度かやっていたりもしますw。

例えば“努力”に対する意識。「世の中、運やツキよりも努力だと思う」と答える生活者は少しずつではありますが増加傾向にあり、今年の調査では前回調査から2.7ポイント増加して66.0%になりました(図2)。

そしてそれに比例してうつ病患者も増加傾向にあるわけだ。。。

「年功序列は守るべきだと思う」と回答する人は、2000年の14.9%から上昇を続け、今年は21.8%に達しました(図3)。これは、行き過ぎた能力主義、成果主義への反動でしょう。

不治痛の例が印象悪すぎただけです。成果や能力を評価できる能力を持った人間がいないのに、成果主義・実力主義が成り立つわけがありません。

つか、「成果主義」か「年功序列」かの二者択一なのね。「成果と年功の併用」とか答える人はおらんかったのかしら。基本給は年功で、成果手当ては別支給、みたいな。ポジション? そもそも管理職が他より上位って考え方自体が古いんじゃね?

いずれにせよ、悪しき日本の風習として、1990年代に最も槍玉に挙げられがちだった「年功序列制度」ですが、生活者はフラットな目で「日本の会社の良さはチームワークと経験主義だ」と思い始め、従来の日本企業の長所へも再び目を向けているようです。

待ってくれ。経験主義というのは認めるとしても、チームワークってのは無いだろう。業務における各ポジションがなすべき仕事をこなすことによって全体の業務がうまく推進するという鳥の目の視点で自分の役どころを理解し、他者と手を取り合って仕事を進めてゆくという意味では欧米企業の人間の方がよっぽど良く理解している。日本は良く語られる営業と技術者 (開発者) との対立構造だの研究者に対する軽視だの、とにかくポジション間の連携の悪さが目立つ。それを差し置いて何がチームワークだ。

きっとここでいう「チームワーク」というのはよーするに仲良しごっこのことだろう。仲良くなっておかなければ仕事に溶け込めないとかいうアレだ。だから異動だなんだで人が替われば再び緊張状態から関係を作りなおさなきゃならない。日本代表のサッカーチームが強くなれないのと理由は同じだ。人が入れ替わったからチームワークが取れなくなりました、なんてのはチームワークとは言わないんだよ。そもそもポジション間の連携が論理的に把握できていない証拠。

年を取っても働き続けたい人も増えています。

これはとてもよいことだと思う。

で、後半からはまったく違う記事になるわけですが。。。

年功序列の会社は人を大切にしているというのは大きな誤解です。もともと日本企業が本当の意味で年功序列だったかにも疑問が残ります。昔から年齢が上がって社内の出世競争に敗れて肩をたたかれたり、左遷されたりして、処遇に恵まれない人は少なくなかった。生き残った一握りの年寄りが役員となって偉そうにしているというだけの年功序列だったのです。問題なのは、「年功」ではなく、「序列」で物事を決めてしまう企業の体質。相手のポストが自分より上か下かということが行動を決める理由になっているという状況を脱しない限り、日本企業はなかなか変われないでしょう。

御意。後半の記事は視点がとても鋭く、読み応えのあるものとなっております。是非ご一読を。

「君のおかげだ。部署の目標も君の頑張りのおかげで大きく超えた。ありがとう。で、今年のボーナスの査定だけど、君はこれを最初にやらせてくださいと言ったよね。それはお金欲しさで言ったの?」

「いえ、違います」

「よかった。それじゃあボーナスはほかの人と同じでいいね」

自分の話になるのだが、とある派遣君が事実上逃げるような形になった替わりに出向となった職場にて、まぁそれなりの仕事を継続することができたおいらは、その年の賞与面談にて 5 段階評価で 4 (よーするに、今の役職相当よりも良い仕事ができている) という評価を頂いた。これは昇給に関係するので、嬉しかったわけだが、それに伴って翌年に「補助プログラマー」から「専門職担当」に格上げになると、次の面談時には評価は 3 (よーするに、今の役職相当程度の仕事はできてる) という評価になった (つまり、昇給の幅は落ちる)。そのとき課長に念を押されたのだ、「だってリーダーの仕事はできていないもんね」と。

おいらはその職場では一人だった。もちろん、出向先の会社の方々には懇意にさせていただいていたし、その方々とは円滑に仕事ができていたとは思う。そういう意味ではなくて、受託業務という形で仕事を受け取っていると考えた場合に、その仕事はおいら一人で片付けるものであった。自分とこの会社から、部下となる人間があてがわれることは無かったし、数年間はおいらに別の職場を選ぶ権限は事実上無かったように思う。もっとも、当のおいらもその職場においてはいろんな技術分野への経験を得やすかったという意味でありがたく思っていたし、一方で社に戻って仕事をするとなれば技術文書を作るツールはどーせ Excel だろうとかその辺の事情も心得ていたこともあって、あんまり積極的に社に戻る気が沸かなかったのも事実だ。

そんなこんなで元々無かった出世意欲がますます萎えてしまったおいらは技術職のままどうにかその職場にすがりつき続けようとしていたわけだが、辞める 1 年前に若い営業の人がやってきて面談をしてくれたので、「他の若手でここで働きたいという方がいればそういう方にお譲りしたい」と告げたわけだが、いつまで経ってもその話はまったく進展せず (たぶん当時の課長の怠慢だったんだと思うんだが)。そして軽いうつを煩ったときにブログで会社を辞めることをほのめかしたのを職場の人に見られたらしく (今でも見てます? ドキドキw)、まぁその前に既に課長には辞意を表明していたんだが (この課長にはいろいろとはぐらかされたナ…#-_-)、職場の人との面談で心のうちを明かして、そういうことなら年度末で穏便に契約終了としませう本当にお疲れ様でしたということになって本格的に辞意を固めるに至ったわけなのですが。。。

まぁ、なんつーか、一度でも会社に対して、挑戦意欲がはぐらかされる場なんだなと絶望されてしまったら、その社員にとってはもうオシマイよね。そういう意味ではおいらの会社員生活は始めの 1 年と 9 ヶ月で終わってた。で、自分はどちらかと言うと出向先の会社の社員なんだという意識で働くことにしていた。ふつーに生活はできてたし貯金もそれなりに溜まってはいたからお金のことにはまったく頓着していなかった。でも、それでもやっぱり。。。抜け出せないことが解っていながら、「だってリーダーの仕事はできていないもんね」のあの一言は、ショックだった。ああ、ここはそういう会社なんですね、って思ったよ。

それでも当時は自分の仕事がそれなりに楽しかったから、救いだったわけではあるんだけれども。

辞める間際、そのとき新しく課長になった人に、別の仕事の話を持ちかけられたときは、実は正直嬉しかったのよ。でも、後悔はしません。もう少しの間、自分のやりたいことに、力を注いでみようと思う。

超簡易 MIDI キーボード for cygwin Perl2006年12月07日 02時03分16秒

実行画面

概要

PC のキーボードを MIDI キーボードにしてしまうという、激しくありがちなプログラムです。MIDI マッパーが正しく設定されていればふつーに音が鳴ります。

操作方法

画面の表示に合わせてキーを押すと音が鳴り、放せば止まります。

また、カーソルキーの上下でオクターブを移動することができます。

動作環境

  • 本プログラムは cygwin 上の Perl にて動作確認していますが、Win32API::MIDI をビルドして動かすことができるようであれば、ActivePerl 上でも動かせるかもしれません。
  • Windows 以外の OS では動作しません。
  • Win32API::MIDI モジュールを追加インストールする必要があります。
  • Win32::Console のバージョンが古いと、定義済み変数であるはずの変数が定義されていない為に例外が発生するかもしれません。その場合は、最新のモジュールに差し替えてください。

制限事項

音色の差し替えやベロシティの変更など、その他のいろんなことは一切できません。

また、キーリピートが発生するぐらい押しっぱなしにしていると、何故か和音が 3 つぐらいまでしか鳴らせなくなっちゃったりします。

免責事項

Artistic License (参考: 日本語訳) に準じます。ご自由にどうぞ。また、一切の保証はありません。ご利用は自己責任で。

ソースコード

#!/usr/bin/perl

package Keybord;

use strict;

use Win32::Console;

# 鍵盤のキー割り当て
use constant    KEYBORD_MAP_WHITE_LOW       => [qw(z x c v b n m , . / \\)];
use constant    KEYBORD_MAP_BLACK_LOW       => [qw(s d), '', qw(g h j), '', qw(l ;)];
use constant    KEYBORD_MAP_WHITE_HIGH      => [qw(q w e r t y u i o p @ [)];
use constant    KEYBORD_MAP_BLACK_HIGH      => [qw(2 3 4), '', qw(6 7), '', qw(9 0 -)];

# 鍵盤の垂直表示位置
use constant    KEYBORD_POS_Y_WHITE_LOW     => [ 12, 20 ];
use constant    KEYBORD_POS_Y_BLACK_LOW     => [ 12, 16 ];
use constant    KEYBORD_POS_Y_WHITE_HIGH    => [  2, 10 ];
use constant    KEYBORD_POS_Y_BLACK_HIGH    => [  2,  6 ];

# 鍵盤の水平表示位置
use constant    KEYBORD_POS_X_LOW           => 10;
use constant    KEYBORD_POS_X_HIGH          => 8;

# 鍵盤の幅
use constant    KEY_WIDTH_WHITE             => 4;
use constant    KEY_WIDTH_BLACK             => 2;

# 鍵盤の色
use constant    KEY_COLOR_WHITE             => $FG_BLACK | $BG_LIGHTGRAY;
use constant    KEY_COLOR_BLACK             => $FG_LIGHTGRAY | $BG_BLACK;
use constant    KEY_COLOR_HIGHLIGHT         => $FG_BLACK | $BG_YELLOW;

# 鍵盤の最初のキーに割り当てられるノート値 (デフォルト値)
use constant    FIRST_NOTE_LOW              => 48;
use constant    FIRST_NOTE_HIGH             => 65;

# オクターブシフトで変化するノート値
use constant    OCTAVE                      => 12;

# オクターブシフトの閾値
use constant    NOTE_UNDER_LIMIT            => 0;
use constant    NOTE_UPPER_LIMIT            => 127 - scalar(@{&KEYBORD_MAP_WHITE_HIGH}) * 2;

# 鍵盤のキーに対する各種情報 (ノート値差分、インデクス、白鍵 or 黒鍵、押下中か否か)
my %keybord_info_low;
my %keybord_info_high;
{
    my $setNoteDiff = sub {
        my ($note_diff, $white, $black) = @_;
        for (my $i = 0, my $note = 0; $i < @$white; $i++){
            $note_diff->{$white->[$i]} = {
                'note' => $note++,
                'index' => $i,
                'type' => 'white',
                'is down' => 0,
            };
            $note_diff->{$black->[$i]} = {
                'note' => $note++,
                'index' => $i,
                'type' => 'black',
                'is down' => 0
            }                               if $black->[$i] ne '';
        }
    };
    $setNoteDiff->(\%keybord_info_low, KEYBORD_MAP_WHITE_LOW, KEYBORD_MAP_BLACK_LOW);
    $setNoteDiff->(\%keybord_info_high, KEYBORD_MAP_WHITE_HIGH, KEYBORD_MAP_BLACK_HIGH);
}

# コンソール出力オブジェクト
our $console_out = new Win32::Console(STD_OUTPUT_HANDLE);

# パッケージローカル関数
my ($displayKeybord);

# オブジェクト生成 - 画面作り
sub new {
    my $invocant = shift;
    my $class = ref $invocant || $invocant;
    
    $console_out->Cls($FG_BLACK | $BG_BLUE);
    $displayKeybord->(KEYBORD_MAP_WHITE_LOW, KEYBORD_POS_X_LOW, 'white', KEYBORD_POS_Y_WHITE_LOW);
    $displayKeybord->(KEYBORD_MAP_WHITE_HIGH, KEYBORD_POS_X_HIGH, 'white', KEYBORD_POS_Y_WHITE_HIGH);
    $displayKeybord->(KEYBORD_MAP_BLACK_LOW, KEYBORD_POS_X_LOW, 'black', KEYBORD_POS_Y_BLACK_LOW);
    $displayKeybord->(KEYBORD_MAP_BLACK_HIGH, KEYBORD_POS_X_HIGH, 'black', KEYBORD_POS_Y_BLACK_HIGH);
    
    my $self = {
        'first note low'    => FIRST_NOTE_LOW,      # 下鍵盤の最初のキーのノート値
        'first note high'   => FIRST_NOTE_HIGH,     # 上鍵盤の (以下略)
    };
    
    bless $self, $class
}

# デストラクタ - 画面消去
sub DESTROY {
    $console_out->Cls($ATTR_NORMAL);
}

# キー on/off 切り替え - 対応するノート値を返す
sub keyTurn {
    my ($self, $key, $is_down) = @_;
    my $high_or_low =     $keybord_info_low{$key}   ? 'low'
                        : $keybord_info_high{$key}  ? 'high'
                        :                             undef;
    return  unless $high_or_low;
    
    my $keybord = $high_or_low eq 'low' ? \%keybord_info_low : \%keybord_info_high;
    # リピート防止の為、押し続けている間はノート値を返さない
    return  if $keybord->{$key}{'is down'} && $is_down;
    
    $keybord->{$key}{'is down'} = $is_down;
    my ($note, $index, $type) = @{$keybord->{$key}}{qw(note index type)};
    my $y = $high_or_low eq 'low'   ? ($type eq 'white' ? KEYBORD_POS_Y_WHITE_LOW->[1]
                                                        : KEYBORD_POS_Y_BLACK_LOW->[1])
                                    : ($type eq 'white' ? KEYBORD_POS_Y_WHITE_HIGH->[1]
                                                        : KEYBORD_POS_Y_BLACK_HIGH->[1]);
    # ハイライトの切り替え
    $console_out->FillAttr(
        $is_down    ? KEY_COLOR_HIGHLIGHT
                    : $type eq 'white' ? KEY_COLOR_WHITE : KEY_COLOR_BLACK,
        $type eq 'white' ? KEY_WIDTH_WHITE : KEY_WIDTH_BLACK,
        ($high_or_low eq 'low' ? KEYBORD_POS_X_LOW : KEYBORD_POS_X_HIGH) +
            ($type eq 'white' ? 0 : KEY_WIDTH_WHITE - int(KEY_WIDTH_BLACK / 2)) +
            KEY_WIDTH_WHITE * $index,
        $y);
    
    $note + $self->{"first note $high_or_low"}
}

# オクターブを上げる / 下げる
sub moveOctave {
    my ($self, $updown) = @_;
    return  if $updown eq 'down' && $self->{'first note low'} - OCTAVE < NOTE_UNDER_LIMIT;
    return  if $updown eq 'up' && $self->{'first note high'} + OCTAVE > NOTE_UPPER_LIMIT;
    
    $self->{'first note low'} += $updown eq 'up' ? OCTAVE : - OCTAVE;
    $self->{'first note high'} += $updown eq 'up' ? OCTAVE : - OCTAVE;
}

# 画面作り - キーボード描画
$displayKeybord = sub {
    my ($keymap, $x, $type) = (shift, shift, shift);
    my ($y1, $y2) = @{shift()};
    $x += $type eq 'white' ? 0 : KEY_WIDTH_WHITE - int(KEY_WIDTH_BLACK / 2);
    local $_;
    for my $key (@$keymap){
        next    if $key eq '';
        $console_out->FillAttr(
            $type eq 'white'    ? (KEY_COLOR_WHITE, KEY_WIDTH_WHITE, $x, $_)
                                : (KEY_COLOR_BLACK, KEY_WIDTH_BLACK, $x, $_)
            )   for ($y1 .. $y2);
        $console_out->WriteChar($key, $x, $y2);
    }
    continue {
        $x += KEY_WIDTH_WHITE;
    }
};

package main;

use strict;

use Win32::Console;
use Win32API::MIDI;

# 仮想キー
use constant    VKEY_END                => 27;  # 終了キー : [ESC]
use constant    VKEY_OCTAVE_UP          => 38;  # オクターブを上げる : カーソルキー [↑]
use constant    VKEY_OCTAVE_DOWN        => 40;  # オクターブを下げる : カーソルキー [↓]


# MIDI イベント
use constant    MIDI_STATUS_NOTE_ON     => 0x90;    # ステータスコード: note on
use constant    MIDI_VELOCITY           => 100;     # ベロシティ

my $console_in = new Win32::Console(STD_INPUT_HANDLE);

my $midi = new Win32API::MIDI;
my $midi_out = new Win32API::MIDI::Out      or die $midi->OutGetErrorText;

my $keybord = new Keybord;

while (1){
    my ($type, $is_down, undef, $vkey, undef, $char) = $console_in->Input;
    next    if $type != 1;          # キー入力以外のイベントの場合
    last    if $vkey == VKEY_END;   # 終了キーが押された場合
    
    # オクターブ移動
    $keybord->moveOctave('up'), next    if $vkey == VKEY_OCTAVE_UP && $is_down;
    $keybord->moveOctave('down'), next  if $vkey == VKEY_OCTAVE_DOWN && $is_down;
    
    my $key = $keybord->keyTurn(chr $char, $is_down);
    next    unless defined $key;
    $midi_out->ShortMsg(
        (($is_down ? 100 : 0) << 16) |
        ($key << 8) |
        MIDI_STATUS_NOTE_ON)
            or die $midi_out->GetErrorText;
}

$midi_out->Close;

__END__

Yahoo! ブログの転載機能2006年12月07日 03時04分37秒

TB どもです。やっと話が見えてきました。

なるほど。Yahoo! ブログには、Yahoo! ブログシステムローカルで機能する「転載」機能が存在し、転載したい記事の「転載」ボタンを押すだけで、自分の Yahoo! ブログに記事を転載できるようになっている。この機能を中心とした話題だったわけですね。

昔、試しに使っていてそのままにしていた Yahoo! ブログがあったので、自分のブログだけで転載機能を試してみました。

自分で試して見て解った点を以下に列挙します。

  • 転載機能を用いてコピーした記事は、編集できない。転載時の内容がそのまま保たれる。
  • 上記で転載元と転載先の内容が異なるのは、転載を行ってから転載元を編集しなおした為。この場合、現時点では、転載元と転載先の記事は同期しない模様 (つまり、ハードリンクのようなものではなく、あくまでコピーであるということ)。
  • オリジナルの記事を作成もしくは編集時に、転載機能を許可するか拒否するかを設定可能。
  • 転載機能によってコピーした記事は編集できないため、転載を拒否する設定に変更することはできないっぽい。転載元の記事がコメント・トラックバックを受け付ける設定の場合は、これらも拒否する設定には変更できないっぽい。

この機能を実装した Yahoo! は、サーバーのキャパシティによほどの自身があるのでしょう。。。

個人的な見解を申し上げます。

Yahoo! ブログが機能として提供している以上、Yahoo! ブログシステム内の仲間同士で、この機能を用いて記事の転載を行いあうこと自体は、多くの場合、それほど問題は無いように思います。

ただ、「転載」という用語自体はごく一般的なものですので、「ご自由に転載してください」のような記述をした場合、Yahoo! ブログ以外のブログ等をもつ人が、手動で記事をコピーし、転載する行為も認めることになるという点には、注意する必要があるかもしれません (Yahoo! ブログが SNS だったならば、問題にはならないのですが)。

あとは、まぁ、各自の良識の範囲内で使われればよろしいのではないかと思います。

経営情報2006年12月07日 11時00分42秒

経営情報学についてはあんまり興味のないおいらなのですが、上記記事が結構面白かったので、著者の方のサイトを覗いてみました。

経営と情報に関する私の主張の中で、ERPパッケージ批判という記事があり、まだこれぐらいしか目を通していないのですが、これがまた面白い。要チェックです。

何この妄想。2006年12月07日 11時44分22秒

小飼氏による記事経由。

                            この記事を読む前に言っておくッ!
                        おれは今この記事を流し読みだが読んできた
                  い…いや…読んだというよりはまったく理解を超えていたのだが……
         ,. -‐'''''""¨¨¨ヽ
         (.___,,,... -ァァフ|          あ…ありのまま 今 起こった事を話すぜ!
          |i i|    }! }} //|
         |l、{   j} /,,ィ//|       『部下を教育する話だと思ったら
        i|:!ヾ、_ノ/ u {:}//ヘ        実は馴れ合いごっこによる部下いびりの話だった』
        |リ u' }  ,ノ _,!V,ハ |
       /´fト、_{ル{,ィ'eラ , タ人        な… 何を言ってるのか わからねーと思うが
     /'   ヾ|宀| {´,)⌒`/ |<ヽトiゝ        おれも何が「ひとつ上」なのかわからなかった…
    ,゙  / )ヽ iLレ  u' | | ヾlトハ〉
     |/_/  ハ !ニ⊇ '/:}  V:::::ヽ        頭がどうにかなりそうだった…
    // 二二二7'T'' /u' __ /:::::::/`ヽ
   /'´r -―一ァ‐゙T´ '"´ /::::/-‐  \    勘違いだとか作り話だとか
   / //   广¨´  /'   /:::::/´ ̄`ヽ ⌒ヽ    そんなチャチなもんじゃあ 断じてねえ
  ノ ' /  ノ:::::`ー-、___/::::://       ヽ  }
_/`丶 /:::::::::::::::::::::::::: ̄`ー-{:::...       イ  もっと恐ろしいものの片鱗を味わったぜ…

つか、こういうことが本当に行われて、上司を疑えないようじゃ、単なる馬鹿だと思うわけだが。おいらがこの「坂本君」だったら、この時点でもう辞めることを前提に出力 10% ぐらいでしか仕事しなくなっちゃうけどね。

ただまぁ、こういう形で、上司と結託して部下をいびるどーしよーも無い人間は結構いるよーというケーススタディとしてはそれなりに参考になった。現場の上司がこういうことになっちゃっているような会社はまず間違いなく古き悪しき序列社会を強いる会社であり、あなたの実力がまともに評価されて反映されることは有り得ないので、心の距離を物凄く長めにとることにするか、若しくはさっさと辞めることを考えた方がよろしいかと思われ。