読者です 読者をやめる 読者になる 読者になる

福澤テクノロジー

おっさんプログラマーが、主に技術的な話をするブログ。

GMailの迷惑メールに分類されてしまった必要なメールを検出しやすくする方法

GMailは迷惑メールフィルタが優秀なので、契約しているプロバイダのメールも全てGMailに転送してメールは全てGMailで読んでいる人も多いかと思います。
しかしフィルタは100%完璧な訳ではないので、たまに迷惑メールが受信トレイに紛れ込む事もあります。
それだけならいいのですが、普通のメールがたまに迷惑メールと判断されてしまう事があります。
とても重要な国連からのメールが迷惑メールに仕分けされてた!なんて事も実際あるのです!
和尚の2012を振り返る。【国連からのメールは迷惑メールフォルダに!】 | Ninebonz - その和尚IT系

とはいえ、迷惑メールフォルダをいちいちチェックするのも大変。
そこで、迷惑メールに分類されても、普通のメールの可能性のあるものは浮かび上がって見えてくる仕組みを考えました。
f:id:FukuzawaTadashi:20130801024735j:plain
ほぼ確実に迷惑メールと判断出来るものを既読にしてやれば、残ったメールは普通のメールの可能性があります。
迷惑メールフォルダに未読がある時にだけチェックしに行けば良いので、とても楽チンです。
f:id:FukuzawaTadashi:20130801151048p:plain

以下、そのやり方を説明します。

まず、GMailの迷惑メールをよく観察し、特徴をつかみます。
メールアドレスが決まっていたり、文章に特徴があったり、URLに特徴があったりします。
ただ、敵もさるもの、アドレスなどはころころ変えてくる事が多いです。そういった部分に注意しつつ、特徴をつかみましょう。

特徴が見えたら、迷惑メールフォルダを開き、画面上部の「検索オプションを表示」をクリックします。
f:id:FukuzawaTadashi:20130801184855p:plain


検索が「迷惑メール」内であることを確認の上、特徴を入力します。
f:id:FukuzawaTadashi:20130801184856p:plain
ここでは、メール本文の中の文字列に特徴があったので、その文字列を「含む」の箇所に記入しました。
そしてこの条件で検索してみて下さい。((1)の虫メガネボタンを押します。)
期待通りに迷惑メールが検索出来ていればOKです。
f:id:FukuzawaTadashi:20130801184857p:plain
うまく検索できない場合は条件を変えて色々試してみましょう。

検索条件が整ったら、再び「検索オプションを表示」の部分をクリックし、今度は(2)の「この検索条件でフィルタを作成」をクリックします。
確認ダイアログが出ます。
f:id:FukuzawaTadashi:20130801184859p:plain
OKをクリックして先に進みましょう。

f:id:FukuzawaTadashi:20130801184858p:plain
既読にする」にチェックをします。「一致する○件のスレッドにもフィルタを適用する」にもチェックを入れておくと良いでしょう。
一番上の検索条件の中に、「label:spam」が入っていることを確認しておいて下さい。さもないと、受信トレイに届いたメールが読んでいないのに既読になってしまう可能性もあります。
最後に「フィルタを作成」ボタンをクリックします。

これで設定は完了です。
このフィルタにかかった迷惑メールは今後届いたとしても既読になりますので、無視しても良くなるわけです。

この調子でいくつかフィルタを設定しておくと、ほぼ全ての迷惑メールが届いた瞬間に既読になっているという状態に持っていけます。
後は迷惑メールフォルダに未読がある場合にだけチェックしにいけば良いのです。
迷惑メールなどまるで存在していないかのような状態でメールチェックできるようになります。
快適なメールライフを楽しみましょう!

まあ本来はスパムを送ることが出来ないようにメールの仕組みを根本的に変えるべきだと思うんですがね。
新しい規格が世界的に承認されない事には状況は変わりませんね。
LINEなどがデファクトスタンダードを取ることになるのでしょうか?




なお、ここで行った設定は、後で見直すことが出来ます。
f:id:FukuzawaTadashi:20130801184900p:plain
右上の「設定」ボタンから、「設定」メニューを開きます。
f:id:FukuzawaTadashi:20130801184901p:plain
フィルタ」タブをクリックすれば、設定したフィルタの一覧が出てきますので、編集するなり削除するなり出来ます。

「お花見ゆうれい」をiBookstoreでリリースしました

Kindleストアから出版した「立体写真集 桜」を改変して、iBookstoreから「お花見ゆうれい」を出しました。
立体写真集 桜 を出版しました - 福澤テクノロジー

どちらも桜の立体写真なのですが、iBooks版はインタラクティブに、平行法、交差法
、ぴくぴく法(正式名称は何だろ?)、鏡を使う方法、をその場で変更する事が出来ます。
また、スワイプで写真を選べたり、ピンチでズームや位置調整などもできます。
さらに新しい遊びを組み入れました。
立体視すると、そこに無かったはずの図形が浮かび上がって見えるというものです。
一時期視力回復トレーニングという事でランダムドットステレオグラムが流行りましたが、この本はランダムドットではなく立体写真を使っている訳です。
これは他では見たことないので、もしや世界初かも?? まあどこかで誰かが既にやってると思いますが。

f:id:FukuzawaTadashi:20130731161550j:plain f:id:FukuzawaTadashi:20130731161817j:plain
iTunes - ブック - 福澤正 & リオ・リーバス「お花見ゆうれい」
iTunes - Books - The Cherry Blossom GHOSTS by Tadashi Fukuzawa & Leo Rivas
ゆうれいの図形を入れたので、タイトルを「お花見ゆうれい」としてみましたが、ゆうれい以外に動物やUFOなども入ってます。

iBooksではKindleストアと違って容量による価格制限などが無いので、価格も100円と安くしました。こちらの方が断然お買い得です。
サンプル版も用意しました。こちらは無料ですので、まずはお試しにダウンロードしてみて下さい。

ただ、iBookstoreなのでiOSデバイスでしか見ることができません。
iPhoneだと画面が小さすぎて、浮き出る図形の判別が難しいです。iPadで見ることをお勧めします。
ePubで作ってあるので、iBooks以外のePub電子書籍マーケットでも出すことができるのですが、そちらの方は調べてないのでわかりません。どこか良い販売プラットフォームがあるようなら検討してみたい。
Kindleストアがインタラクティブコンテンツを許可してjavascriptが動くようになれば一番いいような気がします。

続編も製作して、既に2冊が審査中になっています。近日中にお知らせ出来ると思います。

立体写真集 桜 を出版しました

今まで Finepix REAL 3D W1 で撮り貯めてきた立体写真を、Kindleストアから立体写真集として出版しました。

立体写真集 桜

立体写真集 桜


5/1追記: 英語版も出ました。
Cherry Blossoms / Stereo Photographs

Cherry Blossoms / Stereo Photographs


この本のテーマは桜です。
Kindleのハードを持っていなくても、PCアプリからでもiOSアプリからでもKindleコンテンツを買うことは出来ますので、興味がありましたら買って頂けると幸いです。

写真集だとどうしても容量が大きくなってしまい、Kindleストアの制約から、300円という価格になってしまいました。本当は100円くらいにしたかったんですが。
Kindleのみの独占コンテンツにすれば250円まで下げられるんですが、iBooksでも出してみたいと思っているので、独占コンテンツにはしませんでした。
iBooks版はこれから製作しますが、javascriptが使えるようなので、平行法と交差法を任意に切り替える機能などを盛り込もうと思ってます。
そちらの方が良いと思われましたら、Kindle版は買わずにしばらくお待ち頂ければ良いかと思います。
また、桜以外にも色々と立体写真を撮ってあるので、今後順次出版していきたいと思います。


ほんの少し前には、自分が本を出すなんて考えもしなかったのですが、リオさん (@StudioLoupe)のブログ記事
【新刊】『誰でもKindle出版〜電子マンガ・絵本・画集・写真集の作り方!〜』をKindleストアで販売開始!
を読んで、「あ、写真集を作って出版する事も出来るんだな」と気づいた事がきっかけです。

リオさんには、説明イラストも描いて頂きました。
この本が出せたのは、ほんとにリオさんのおかげです。ありがとうございました!


3D画像は僕は以前から好きで、Nintendo 3DSが出る前から、
「いずれ3Dゲーム機が出るから、その前からゲームの企画を出してメーカーにプレゼンしに行けば、セカンドパーティーになれるかもしれないよ!」
と言っていたんですが、周りの誰も興味を示しませんでした…。
3Dテレビも売れてないし、あまり人気のない分野みたいですね。
メガネが不要で、見る角度の制限がなく、横になっても見え、装置も安く、コンテンツが沢山出るまでは、一般的にはならないのかも。こりゃ絶望的か。

でも好きな人は一定数いるとは思うので、そういう人に楽しんで頂ければ良いかと。

ニコニコ超会議2でやってた、手作りプラネタリウムの中での3D影絵も面白かったなあ。
赤と青の並んだ光源に、立体物をかざした時、その影を赤青メガネで見ると立体的に見えるんですよ。

ALCS(仮) 仕様まとめ

ALCS(仮)

新しいリテラルのアイデア。
文字列とクロージャの配列を生成する表記法。
Array Literal of Closures and Strings の略。
(もっと良いネーミングは無いものか)

仕様

  1. %P
  2. %W と似ている。 %W では #{} による式展開をその場で実行して文字列化してしまうのに対して、 %P ではProcオブジェクトとして配列の1要素とする。

    %W(foo asd#{1+2}qwe bar)   # => ['foo', 'asd3qwe', 'bar']
    %P(foo asd#{1+2}qwe bar)   # => ['foo', 'asd', Proc.new{1+2}, 'qwe', 'bar']

  3. %p

  4. %Pでは空白文字を要素の区切りとするが、%pでは改行文字を区切りとして、改行文字自身もデータに含む。
    行頭、行末の空白文字は削除される。

    %P(foo
        asd#{1+2}  qwe
        bar)
    # => ["foo", "asd", Proc.new{1+2}, "qwe", "bar"]
    %p(foo
        asd#{1+2}  qwe
        bar)
    # => ["foo\n", "asd", Proc.new{1+2}, "  qwe\n", "bar"]

  5. <<<

  6. ヒアドキュメント形式。
    改行文字を区切りとして、改行文字自身もデータに含む。
    空白文字も全部含む。

    <<<EOH
    foo
       asd#{1+2}qwe
       bar
    EOH
    # => ["foo\n", "   asd", Proc.new{1+2}, "qwe\n", "   bar\n"]
    <<<'EOH'
    foo
       asd#{1+2}qwe
       bar
    EOH
    # => ["foo\n", "   asd\#{1+2}qwe\n", "   bar\n"]

関連エントリ

(追記:2013/3/23)
pull request してみましたが、mrubyコアには実験的新機能は入れないとの事で、リジェクトされました。
使ってみたい人は、僕のブランチから取って行って下さい。

(追記:2013/9/28)
ALCSを Lazy Expression Expansion に改名しました。
Lazy Expression Expansion - 福澤テクノロジー

gotoとクロージャ

goto文の要請

数年前の話。
スクリプト言語Hayatを使ったノベル系のゲームを開発していた。
シナリオ担当者から、「goto文を追加してよ」というリクエストが来た。
えー、goto文なんてプログラムの構造を複雑にしてバグの温床になる機能じゃん。
BASIC言語でよく見られるgotoが複雑に入り組んだプログラムは、実行の順番がよくわからなくなり、プログラムを読んでも構造が把握しきれず、スパゲッティプログラムと呼ばれた。
gotoを使わなくても、ループと条件分岐さえあればプログラムは作れる! として「構造化プログラミング」の流れが起きてプログラミング言語からgotoが追放されていったのは、もう数十年前の話しだ。
そんな機能はつけたくないなあ、と思っていたのだが、


goto文を入れろと言ったら
入・れ・ろ・ッ!

と怒鳴られた。
というのはウソだが、goto文が必要だというのは本当だった。

このゲームではイベントシーンで選択肢が山ほど現れ、分岐しまくったり合流したり前に戻ったり、かなりカオスな状況になるのだった。
フローチャートで書くと、線があちこちにネットワーク状に入り乱れていて、複雑怪奇なものになっていた。
これをループと条件分岐のみで制御するのはかなり難しい。何とか作れることは作れるが、シナリオに変更があればまた頭を悩ませてスクリプトをカット&ペーストして、新たな構造を作る必要がある。
しかもシナリオ変更など日常茶飯事だ。むしろプロジェクトの終わり間際まで最も変更の多くかかる部分だ。
これはgotoで制御する方がわかりやすいし、変更にもむしろ強い。

という事でHayat言語にgoto文を追加する事にした。

クロージャ

Hayatは、ゲーム機でRubyのようなスクリプトを使いたいという動機もあって設計していたので、Rubyのブロックのように、メソッドにクロージャを渡す機能を持っていた。

def method_a (p)
{
  p.call()    # クロージャの呼び出し
}

method_a {
  # クロージャ本体
}

クロージャは単に中括弧 { } で括るだけで書けるので、これがクロージャだと意識する必要もほとんど無い。
こういう言語で goto を入れるにはどうするか。

label :label_x

method_a {
   ...
   method_b {
      ...
      goto :label_x
   }
}

このgotoを期待通りに動かしたい。
同じスコープ内にあるのなら話は簡単だ。単純にジャンプ命令にコンパイルすればいい。
しかし、goto文は2つのメソッドと2つのクロージャの内側にある。ジャンプ先のラベルはその外側にあるのだ。

例外処理との組み合わせ

これを解決するため、gotoは同じスコープ内にラベルが無い場合は、「goto例外」を発行する事にした。
例外はキャッチされなければ、コールスタックを遡ってルーチンの呼び出し元に戻る。
そこでまたジャンプ先ラベルをサーチして、無ければさらにコールスタックを遡る。
コールスタックを深い所に入っていく方向のgotoは実行できない事にした。さすがにこれはどう考えても実装できない。
これで解決した。

この方法を取ることで、面白い事が出来た。

def onGoto (n, *labels) {
  goto labels[n]
}

onGoto(x, :label1, :label2, :label3)

x の値が 0なら :label1 へ、1なら :label2 へ、2なら :label3 へジャンプする。
goto文自体はonGotoメソッドの中にあるのに、これでジャンプが出来るのだ。
あれ、あまり面白くないですか?

必要性

この機能は必要だろうか?
正直、あまり必要ない気がする。
あんな複雑怪奇なフローチャートが必要なゲームなど、めったに出るものではない。
ただ、gotoというのは直感的にかなりわかりやすい。初心者には特に。
ゲームスクリプトを書く人は、プログラマではなく企画や演出の人だったりする。
そういう人達にとって、わかりやすさというのは大きなメリットとなりそうだ。

一方で、これを実装するのに例外処理機構に手を入れる事になった。
僕の設計がまずかったせいもありそうだが、例外処理が重くなった。
例外処理用のデータに、goto用のラベルリストが入り込む事になってしまった。
それと同時にルーチンからのリターン処理にも負荷がかかった。例外がコールスタックを遡る所で共通の処理が走るからだ。
Hayat言語の遅い原因の1つになっている気がする。プロファイリングしてないのでよくわからないけど。

まあ、他の言語で goto を入れようという事になった時には参考にして下さい。
ありえなさそうだけど。

ALCS(仮) の使いどころ

ゲームでは、登場人物がしゃべったり、ナレーションを流すようなシーンがあるが、文字の色やサイズを変えたりメッセージの表示速度を動的に変えたりする演出をよくする。
スクリプトレベルでは、メッセージを全角文字、コマンドを半角文字で表現したり、
HTMLのタグのようにコマンドを埋め込んでおき、コンバータによりコマンド解析を行なう場合が多いんじゃなかろうか。もしくは、スクリプトが実行時に構文解析を行なうとか。

こんな表示をしたいとする。フォントを大きくした所では、メッセージ表示速度も遅くしたい。


霞の目ネペンテス液を入れろと言ったら
入・れ・ろ・ッ!

これを実現させる架空スクリプト:

name(霞の目)
「color(RED)ネペンテス液color(BLACK)を入れろと言ったら
font(BIG);delay(1000)入・れ・ろ・delay(200)ッ!」

この架空スクリプトは、文章を出力する事を主眼としたゲーム専用言語を想定している。
全角文字列は文字出力コマンドであり、半角文字列は機能を実行するコマンドである、と考えればいい。
スクリプト言語としては、汎用性に乏しすぎる。
メッセージ出力に特化しすぎていないで、もっと汎用的な機能を持った言語で、かつメッセージを主体としたゲームでも書きやすい言語がいい。


Rubyのような汎用的なスクリプト言語でそれを実現させるにはどうするか。
せっかくのスクリプト言語なのだから、文字列中のコマンドはその場で直接スクリプトに実行させればいいじゃん! という発想で作ったのがHayat言語のsayCommand機能だ。

霞の目「{赤}ネペンテス液{黒}を入れろと言ったら
      {大}{delay(1000)}入・れ・ろ・{delay(200)}ッ!」

"「" がsayCommand機能開始で、 "」" までがデータの列として扱われ、sayCommand()メソッドに次々と送られていく。
sayCommand()メソッドは、送られてきたデータに従って文字を出力したりサイズ変更や色変更などの機能を実行する。


ALCSは、言語仕様に影響を与えずに、リテラルだけで同様の事を実現できる。

霞の目.say %p[#{赤}ネペンテス液#{黒}を入れろと言ったら
  #{大}#{delay(1000)}入・れ・ろ・#{delay(200)}ッ!]

%pリテラルは、%Wとは異なり #{...} を展開して文字列化したりしないで、Procオブジェクトとして配列の1要素とする。だから受け取った側で実行タイミングをコントロールできる。

これを実働させるスクリプトは、例えばこんな感じになる。

黒 = ""
赤 = ""
青 = ""

小 = ""
中 = ""
大 = ""

$char_wait = 200

def color(x)
  # change font color
  print "[#{x}]"
end

def size(x)
  # change font size
  print "(#{x})"
end

def delay(x)
  $char_wait = x
  print "<#{x}>"
  nil
end

def dispStr(str)
  str.each_char do |c|
    # sleep($char_wait / 1000)
    print c
  end
end

class Person
  def initialize(name)
    @name = name
  end

  def say(alcs)
    print "#{@name}"
    alcs.each do |m|
      case m
      when Proc
        x = m.call
        case x
        when "", "", ""
          size(x)
        when "", "", ""
          color(x)
        else
          # other function
        end
      else
        dispStr m
      end
    end
    print "\n"
  end
end


霞の目 = Person.new("霞の目")

霞の目.say %p[#{赤}ネペンテス液#{黒}を入れろと言ったら
  #{大}#{delay(1000)}入・れ・ろ・#{delay(200)}ッ!]

実行結果:

霞の目「[赤]ネペンテス液[黒]を入れろと言ったら
(大)<1000>入・れ・ろ・<200>ッ!」

文字色やサイズなどを実際に変えるのは大変なのでprintでごまかしているけど、どう動作するのかは十分把握できると思う。

上記スクリプトは、ALCSを実装した魔改造バージョンのmrubyで実際に動きます。

git clone -b alcs git://github.com/FUKUZAWA-Tadashi/mruby.git

%pリテラルではなく、ALCS Here-document を使う場合はこうなる。

霞の目.say <<<EOH
#{赤}ネペンテス液#{黒}を入れろと言ったら
#{大}#{delay(1000)}入・れ・ろ・#{delay(200)}ッ!
EOH

長文のナレーションのような所で使いやすいかと思う。

ALCS(仮): Array Literal of Closures and Strings

Lazy Here-document (仮) をmrubyに実装してみた - 福澤テクノロジー を作ってみたものの、まだ使いにくい。
行頭や行末の空白文字がそのまま残ってしまうのが、文章を主としたスクリプトを書く時にインデントが出来ない原因になっている。
そこで思いついたのが、 %W リテラル類似の機能。
%W だと、 #{...} を展開して文字列化してしまうが、これを Proc オブジェクトにすればいい!
%P として実装しよう。
それだけだと、文章中の空白文字がなくなってしまう。ワードの区切りになってしまうから。
文章書きの人が使った時、「せっかく入れた空白が消された!」と思ってしまいそう。
自由なインデントをしつつ、空白文字も残すにはどんなルールがいいか。

方針:

  • 自由にインデントしたいので、行頭の空白文字は消そう。あえて入れたければエスケープすればいい。
  • 行末に空白文字があっても見えない(エディタにもよるが)。見えないものは無いことにしよう。
  • 改行がどこで行われたかは知る必要がある。行末の空白文字は消すが、改行コードは残す。
  • 改行で一旦ワードが終わるようにしておきたい。

これを %p として実装しよう。

これで、Hayat言語の特殊機能 sayCommand - 福澤テクノロジーで使ったスクリプト記法とほぼ同じく書けるようになった。

白 = 0
青 = 1
赤 = 2
class Person
  def say(a)
    a.each do |x|
      case x
      when Proc
        mySetColor(x.call)
      else
        myPrintStr(x)
      end
    end
  end
end
アインシュタイン = Person.new

アインシュタイン.say %p[人生は#{青}退屈すれば長く#{白}、
           #{赤}充実すれば短い#{白}。]


Lazy Here-document(仮) は、この %P %p リテラルとほぼ同じような機能なので、両者を合わせて新しい呼び方にしてみた。
ALCS(仮): Array Literal of Closures and Strings
うーん、いまいち。



テストコードはこんな感じ。これで現状の仕様がわかると思う。

def concat_m(arr)
  arr.map{|x| x.class == Proc ?  x.call().to_s : x }.join('-')
end

answer = 42
a = %P(aa#{1+1}bb)
b = %P[ aa #{1+2} bb ]
c = %P{aa
  #{1+3}
  bb}
d = %P/ aa
  #{1+4}
  bb
  /
e = %P(#{1+5}#{answer})
f = %P{aa bb}
test1 = (concat_m(a) == 'aa-2-bb' and
         concat_m(b) == 'aa-3-bb' and
         concat_m(c) == 'aa-4-bb' and
         concat_m(d) == 'aa-5-bb' and
         concat_m(e) == '6-42' and
         concat_m(f) == 'aa-bb'
        )

a = %p(aa#{1+1}bb)
b = %p[ aa #{1+2} bb ]
c = %p{aa 
  #{1+3} 
  bb}
d = %p/ aa   
  #{1+4}        
  bb     
  /
e = %p(#{1+5}#{answer})
f = %p{aa bb}
test2 = (concat_m(a) == 'aa-2-bb' and
         concat_m(b) == ' aa -3- bb ' and
         concat_m(c) == "aa\n-4-\n-bb" and
         concat_m(d) == " aa\n-5-\n-bb\n" and
         concat_m(e) == '6-42' and
         concat_m(f) == 'aa bb'
        )

ソースコードは、github上に alcs ブランチとしてコミットしました。
以下のコマンドで取れます。

git clone -b alcs git://github.com/FUKUZAWA-Tadashi/mruby.git


Here document の方は、課題を2つ解決しときました。

  • <<<'EOH' で式展開をしないようにした
  • <<<- で終端文字列がインデント出来るようにした

heredoc ブランチは、alcs ブランチに統合しました。