M.C.P.C.

―むり・くり―プラスコミュニケーション


« 2011年8月 | トップページ | 2011年10月 »

2011.09.30

昔あれだけ“1 User”表記にこだわったはてなが、Androidアプリだと平気で“1 Users”と表記している

むかし、はてなブックマークといえば、ブックマークしたユーザ数が一人の場合は“1 Users”ではなく、“1 User”と表記することにとてもこだわっていたのだと思います。

たとえば、被リンク数を画像で取得するAPIを使ったときに表示に利用される画像などは、

http://cdn.b.st-hatena.com/images/users/gif/normal/00001.gif
http://cdn.b.st-hatena.com/images/users/gif/normal/00002.gif

となっています。

ところが、Android版はてなブックマークアプリや、iOS版はてなブックマークアプリでは、“1 Users”と表示されてしまいます。

Device20110930224433
▲1 Usersと表示

はてなのエンジニアも中身が入れ替わっているのでしょうから、こだわりの部分が変化しているのだと思いました。

[Web] | 固定リンク | コメント (0) | トラックバック (0) | このエントリーをはてなブックマークへ追加 livedoor Clipでこのサイトを登録している人数livedoor Clipでこの記事をクリップ!

2011.09.29

お年寄り相手の印刷物ではミリよりもセンチ

いろいろな移管がありまして高齢者が多い業種の印刷物の営業を行うことになったわけですけれども、実際に担当してみると、今までわからなかったことが見えてきます。

特に、寸法表記では、「ミリ」で表記するとうまく理解していただけないことが多いように感じます。この前、僕の行きつけの飲み屋のハゲとっつぁまが放射線の単位をミリとかマイクロとか言うな、と誰に向かって怒っているのかわかんないことを言っていましたが、要は単純に単位になじみがないのだと思いました。

じゃあ、尺とか寸とかで言え、ていう話ではなくて、僕らがイメージを抱くお年寄り(自分自身の祖父母の年代)よりは若いので、単純にセンチでいえば話は通じるのです。

うちらも印刷業界に入る前はいちいちミリに言い換えるのまんどくせーとか内心思っていたはずなのですが、いつの間にか「印刷業界のルールで提示するのが当たり前」となっていたのですね。

つうわけで、移管した事業のカタログとかは、今度からセンチ表記に書き換えたり、客層に応じてミリとセンチの言い換えをスマートに行うことが必要だなあとか思いました。

[日記・コラム・つぶやき] | 固定リンク | コメント (0) | トラックバック (0) | このエントリーをはてなブックマークへ追加 livedoor Clipでこのサイトを登録している人数livedoor Clipでこの記事をクリップ!

2011.09.28

Android版Firefox7でWebSocket接続

Android版Firefox 7が出たので、最近作っているWebSocketサーバに果たして接続できるかどうかやってみました。

見事接続できました。

ただし、WebSocketオブジェクトではなくて、MozWebSocketオブジェクトを使うことになります。

WS = function(f) {
  if (typeof MozWebSocket != 'undefined' ) return new MozWebSocket(f);
  if (typeof WebSocket != 'undefined' ) return new WebSocket(f);
  return;
}

こんなの作ればいいわけだな。

[Web] | 固定リンク | コメント (0) | トラックバック (0) | このエントリーをはてなブックマークへ追加 livedoor Clipでこのサイトを登録している人数livedoor Clipでこの記事をクリップ!

2011.09.27

⌘キーが書きにくいと言われた

いきなりDTPのトレーニングを担当することになって、僕もMac離れてから2年近くなるので、リハビリということで、「じゃあ、Macの電源の付け方と、Finder操作のキーボードショートカットから行きましょー」とか言いながら教えていたのですが、キーボードのCommandキーが「⌘とリンゴ」になっているタイプ(年代から言うとApple Pro Keyboard?)なので、「コマンドマークが書きにくい」と言われました。

最近のMacだったら、しっかりCommandって書いてあるので楽なんですよね。

コマンドキーについて :Macintosh - Wikipedia [ja.wikipedia.org]

[DTP] | 固定リンク | コメント (0) | トラックバック (0) | このエントリーをはてなブックマークへ追加 livedoor Clipでこのサイトを登録している人数livedoor Clipでこの記事をクリップ!

2011.09.26

ニンテンドーDSのカートリッジ収納ケースに3DSのカートリッジが収納できん……カートリッジに出っ張りをつけよった……

あんまり時間がないもののせっかく買ったニンテンドー3DSで遊んだりすることもあるのですけれども、3DS用カートリッジを抜いて昔のDS用カートリッジが収納されている入れ物に入れようとしたのですが、3DSカートリッジには、DSカートリッジから比べると突起物が付いており、収納ができなくなっていました……

DS本体に3DSカートリッジ誤挿入を防止するための出っ張りなんだと思いますが、デザイン的にも醜いし、ギミックとして工夫されているとも言いにくいので、おそらくDS開発時は次世代機はDS互換になるとは思っていなかったのかなーとか感じました。

実際、オンラインでゲームが購入できたりしますしね。今カートリッジで売っているソフトがダウンロード販売になってくれたら、カートリッジでのゲーム交換せずに3DSのGUIで選択できるようになるのでしょうから、よっぽどいいんですけれどもね。

[ゲーム] | 固定リンク | コメント (0) | トラックバック (0) | このエントリーをはてなブックマークへ追加 livedoor Clipでこのサイトを登録している人数livedoor Clipでこの記事をクリップ!

2011.09.25

Google ChromeウェブブラウザにMojolicious::LiteサーバからWebSocketで接続しリアルタイムでTwitterのストリームをニコニコ動画風に表示する

Twitter Streaming APIからの出力をリアルタイムにWebブラウザに表示する実装を作るにあたり、Mojolicious::LiteサーバとGoogle ChromeブラウザをWebSocketで接続すればいいと考え、実際にできるかどうか試したのは昨日のエントリでやりましたが、表示のさせ方を変えてみました。

声の高さやアクセントをちょっといじってみた。

どう見てもニコニコ動画です。本当にありがとうございました

コメントの当り判定がすごい甘いのでコメント同士が重なってしまっているのです。

これは少しずつ直していかなくてはならないなあ。

#!/usr/bin/perl
 
use AnyEvent::Twitter::Stream;
use Config::Pit;
use DateTime;
use Encode;
use EV;
use File::Spec;
use FindBin::Real;
use HTML::Entities;
use Mojolicious::Lite;
use Mojo::JSON;
use URI::Escape;
use utf8;
use YAML;
 
my $keys = YAML::LoadFile(
  File::Spec->catdir( FindBin::Real::Bin(), '..', 'consumer_keys.yaml' )
);
my $pit = pit_get( 'twitter.com@CLCLCL' );
 
my $clients = {};
my $done = AnyEvent->condvar;
 
my $listener = AnyEvent::Twitter::Stream->new(
  consumer_key    => $keys->{consumer_key},
  consumer_secret => $keys->{consumer_key_secret},
  token           => $pit->{access_token},
  token_secret    => $pit->{access_token_secret},
  method => 'sample',
  #method => 'filter',
  #track  => 'dtp',
  on_tweet => sub {
    my $tweet = shift;
    my $user = $tweet->{user}{screen_name};
    my $text = $tweet->{text} || '';
    my $lang = $tweet->{user}{lang} || '';
    return if $lang ne 'ja';
    return unless $user && $text;
    $user =~ s/./*/g;
    $text =~ s/\@[^\s:]+/@****/g;
    $text =~ s/[^\s]+さん/****ちゃん/g;
    $text =~ s/[^\s]+ちゃん/****さん/g;
    $text =~ s/[^\s]+くん/****クン/g;
    $text =~ s{http://t.co/[\w\-]+}{http://t.co/******}g;
    print $user." : ".encode_utf8($text)."\n";
    my $send_datetime;
    $send_datetime = sub {
      my $json = Mojo::JSON->new;
      my $dt   = DateTime->now( time_zone => 'Asia/Tokyo');
      my $str = $json->encode({
        hms  => $dt->hms,
        user => $user,
        text => $text,
      });
      utf8::decode( $str );
      for (keys %$clients) {
        $clients->{$_}->send_message( $str );
      }
    };
    $send_datetime->();
  },
  on_error => sub {
    my $error = shift;
    warn "ERROR: $error";
    $done->send;
  },
  on_eof   => sub {
    $done->send;
  },
);
 
get '/' => 'index';
 
 
websocket '/echo' => sub {
  my $self = shift;
 
  app->log->debug(sprintf 'Client connected: %s', $self->tx);
  my $id = sprintf "%s", $self->tx;
  $clients->{$id} = $self->tx;
 
  $self->on_message();
 
  $self->on_finish(
    sub {
      app->log->debug('Client disconnected');
      delete $clients->{$id};
    }
  );
};
 
app->start;
 
__DATA__
@@ index.html.ep
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Mojolicious + WebSocket + Twitter Streaming API</title>
    %= javascript '/js/jquery.js';
    <script type="text/javascript">
    var Ji = function( msg ) {
      this.msg = msg;
      this.screen = {};
      this.screen.width = $('#stage').width() || 100;
      this.position = {};
      this.position.x = this.screen.width;
      this.position.y = 0;
      this.id = 0;
      this.create();
      this.speed = 0;
      this.start();
      this.number = 0;
    };
    Ji.objects = [];
    Ji.prototype = {
      slice: 66,
      time: 5000,
      height: 40,
      move : function() {
        // console.log( this.position.x );
        this.position.x -= this.speed;
        this.show();
        if ( this.position.x < this.width * -1 ) {
          clearInterval( this.id );
          this.destroy();
        }
      },
      start : function() {
        var self = this;
        this.speed = ( this.screen.width + this.width )  / (this.time / this.slice );
        this.id = setInterval( function(){ self.move(); }, this.slice);
      },
      create : function() {
        this.object = $('<span>').html(this.msg).css('visiblity','hidden').appendTo('#stage');
        if (Ji.objects.length) {
          var item = Ji.objects[Ji.objects.length - 1];
          if (item.position.x + item.width > this.screen.width ) {
            this.position.y = item.position.y + this.height;
          }
        }
        this.width = this.object.width() + 1;
        this.object.css({
          visiblity: 'visible',
          display  : 'block',
          width    : this.width + 'px',
          left     : this.position.x + 'px',
          top      : this.position.y + 'px'
        });
        Ji.objects.push(this);
      },
      show: function() {
        $(this.object).css('left', this.position.x + 'px');
      },
      destroy : function() {
        $(this.object).remove();
        Ji.objects.pop();
      }
    };
    $(function () {
      var show = function (text) {
        var sel = 'textarea';
        $(sel).val( text + "\n" + $(sel).val() );
      };
      var ws = new WebSocket('ws://' + location.host + '/echo');
      ws.onopen = function () {
        console.log('Connection opened');
      };
      ws.onmessage = function (msg) {
        var res = JSON.parse(msg.data);
        var d = new Ji(res.text); 
      };
    });
    </script>
    <style type="text/css">
      html, body { height: 98%; }
      h1 { font-size: 14px; }
      span {
        position: absolute;
        font-size: 36px;
        font-family: 'A-OTF 新ゴ Pro M';
      }
      body {
        overflow: hidden;
      }
    </style>
  </head>
  
  <body>
    <header>
      <h1>Mojolicious + WebSocket + Twitter Streaming API</h1>
    </header>
    <article id="stage">
    </article>
  </body>
</html>

実は、横に流れるオブジェクト一つ一つがタイマーを持っているという無駄な作りでありまして、すごい重いので、スタックに積んでおいて、タイマー1つでスタックにあるオブジェクトを一つ一つ動かす、など言う実装のほうがいいのかもしれません。


(2011-10-10 15:50追記)

このままだと、素の状態から構築したときEVモジュールが入っていないと動かないことが判明したので、use EV;を追加しました。

[Web] | 固定リンク | コメント (0) | トラックバック (0) | このエントリーをはてなブックマークへ追加 livedoor Clipでこのサイトを登録している人数livedoor Clipでこの記事をクリップ!

2011.09.24

Google ChromeウェブブラウザにMojolicious::LiteサーバからWebSocketで接続しリアルタイムでTwitterのストリームを表示する

Twitter Streaming APIからの出力をリアルタイムにWebブラウザに表示する実装を作るにあたり、Mojolicious::LiteサーバとGoogle ChromeブラウザをWebSocketで接続すればいいと考え、実際にできるかどうか試してみました。

動画でイメージを見たほうが早いので、下記をどうぞ。

Mojoliciousの発音がこれでいいかは知らない。

Filename: test4-anony.pl

#!/usr/bin/perl
 
use AnyEvent::Twitter::Stream;
use Config::Pit;
use DateTime;
use Encode;
use EV;
use File::Spec;
use FindBin::Real;
use HTML::Entities;
use Mojolicious::Lite;
use Mojo::JSON;
use URI::Escape;
use utf8;
use YAML;
 
# consumer_keyが書かれたYAMLファイルを用意しておく
my $keys = YAML::LoadFile(
  File::Spec->catdir( FindBin::Real::Bin(), '..', 'consumer_keys.yaml' )
);
# Config::Pit あらかじめ自分のディレクトリにtokenが書かれたYAML用意しておく
my $pit = pit_get( 'twitter.com@CLCLCL' );
 
my $clients = {};
my $done = AnyEvent->condvar;
 
my $listener = AnyEvent::Twitter::Stream->new(
  consumer_key    => $keys->{consumer_key},
  consumer_secret => $keys->{consumer_key_secret},
  token           => $pit->{access_token},
  token_secret    => $pit->{access_token_secret},
  method => 'sample',
  #method => 'filter',
  #track  => 'dtpstudy',
  on_tweet => sub {
    my $tweet = shift;
    my $user = $tweet->{user}{screen_name};
    my $text = decode_entities($tweet->{text} || '');
    my $lang = $tweet->{user}{lang} || '';
    return if $lang ne 'ja'; # 日本語メッセージのみ選ぶ
    return unless $user && $text;
    $user =~ s/./*/g;
    $text =~ s/\@[^\s:]+/@****/g;
    $text =~ s/[^\s]+さん/****ちゃん/g;
    $text =~ s/[^\s]+ちゃん/****さん/g;
    $text =~ s/[^\s]+くん/****クン/g;
    $text =~ s{http://t.co/[\w\-]+}{http://t.co/******}g;
    print $user." : ".encode_utf8($text)."\n";
    my $json = Mojo::JSON->new;
    my $dt   = DateTime->now( time_zone => 'Asia/Tokyo');
    my $str = $json->encode({
      hms  => $dt->hms,
      user => $user,
      text => $text,
    }); # utf8フラグが落ちる
    utf8::decode( $str ); # utf8フラグ付きに戻す
    for (keys %$clients) {
      $clients->{$_}->send_message( $str );
    }
  },
  on_error => sub {
    my $error = shift;
    warn "ERROR: $error";
    $done->send;
  },
  on_eof   => sub {
    $done->send;
  },
);
 
get '/' => 'index';
 
 
websocket '/echo' => sub {
  my $self = shift;
 
  app->log->debug(sprintf 'Client connected: %s', $self->tx);
  my $id = sprintf "%s", $self->tx;
  $clients->{$id} = $self->tx;
 
  $self->on_message();
 
  $self->on_finish(
    sub {
      app->log->debug('Client disconnected');
      delete $clients->{$id};
    }
  );
};
 
app->start;
 
__DATA__
@@ index.html.ep
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Mojolicious + WebSocket + Twitter Streaming API</title>
    %= javascript '/js/jquery.js';
    <script type="text/javascript">
    $(function() {
      $('textarea').height(
        $('body').innerHeight() - $('article').position().top
      );
    });
    $(function () {
      var show = function (text) {
        var sel = 'textarea';
        $(sel).val( text + "\n" + $(sel).val() );
      };
      var ws = new WebSocket('ws://' + location.host + '/echo');
      ws.onopen = function () {
        console.log('Connection opened');
      };
      ws.onmessage = function (msg) {
        var res = JSON.parse(msg.data);
        show(res.user + ': ' + res.text); 
      };
    });
    </script>
    <style type="text/css">
      html, body { height: 98%; }
      h1 { font-size: 14px; }
      textarea { width: 100%; }
    </style>
  </head>
  
  <body>
    <header>
      <h1>Mojolicious + WebSocket + Twitter Streaming API</h1>
    </header>
    <article>
      <textarea></textarea>
    </article>
  </body>
</html>

サーバを立ち上げるあたりが大変なのかもしれませんが、これでいろんなものが作れそうな気がしてきますよね。

参考にした:
Mojolicious::Lite で WebSocket を使ったチャットを作る - naoyaのはてなダイアリー [d.hatena.ne.jp]
M.C.P.C.: AnyEvent::Twitterなるものを知ったがSearch APIは使えないのかな←Search APIはないけれども、methodをFilterにして、trackにひっかけたい文字列を設定するんですね。


(2011-10-10 15:50追記)

このままだと、素の状態から構築したときEVモジュールが入っていないと動かないことが判明したので、use EV;を追加しました。

[Web] | 固定リンク | コメント (0) | トラックバック (0) | このエントリーをはてなブックマークへ追加 livedoor Clipでこのサイトを登録している人数livedoor Clipでこの記事をクリップ!

2011.09.23

Android版radiko.jpで谷川岳地下を超えると関東ではなくてもradikoが聞こえた

Android版radiko.jpをインストールしていたのですが、関東や関西ではないので、地域制限のせいで放送がきくことができない全く意味のないアプリになっていたのですが、先日東京に行った時の帰り、新幹線に乗って、radiko.jpで野球中継を聞いていたのですが、そのまま群馬と新潟の境にある谷川岳地下の大清水トンネルの長い長い電波不通区間を乗り越えて新潟県側に出たら、ふたたびradiko.jpの野球中継が聞こえました。

radiko.jpアプリは、起動時にGPSで現在地を確認して、放送取得可能地域を判断したため、高速移動したらそのまま聞くことができたみたいです。

個人的には、radiko.jpよりも、AGQRのAndroid版アプリがあってほしいところです。

[パソコン・インターネット] | 固定リンク | コメント (0) | トラックバック (0) | このエントリーをはてなブックマークへ追加 livedoor Clipでこのサイトを登録している人数livedoor Clipでこの記事をクリップ!

2011.09.22

シャープのFAX複合機UX-MF50CLがWindows7で使い勝手が悪かった

とある事情で、名刺を家庭用プリンタとエレコムのなっとく。名刺を使ってプリントアウトをする必要がありまして(おまえは印刷屋だろ!)、急遽Windows 7 64bitマシンに、僕のうちにあるFAXプリンタ複合機UX-MF50CLをセットアップする必要が発生したのですが、メーカーのサイトに行くと、Windows Vistaまでのドライバしかないわけです。

UX-MF50CL自体は、LAN接続してあったので、メーカーサイトのWindows Vista 64bit用LAN接続用ドライバをダウンロードして、インストールしてみたのですが、ドライバのインストーラーが異常終了します。

よく調べたら、同じサイトにあるWindows Vista 64bit用USB接続用ドライバであれば、Windows 7 64bitでも何とか使えるらしいということが分かり、事なきを得ました。

そうやって苦労して作った名刺をIGASで渡したら、「こういう名刺見たことない」とDISられてへこみました。IGASに来る人間全員がまともに名刺を持っている人間ばかりだとは思うなよ!

[日記・コラム・つぶやき] | 固定リンク | コメント (0) | トラックバック (0) | このエントリーをはてなブックマークへ追加 livedoor Clipでこのサイトを登録している人数livedoor Clipでこの記事をクリップ!

2011.09.21

入念に準備してきた健康診断対策が一瞬の不注意でパーに

今日健康診断だったんですけれども、健康診断で胃のレントゲン撮影する人の場合、前日の夜8時から断食をするのですが、昨日は新幹線に乗っていてちょうど夜8時になる前までにカロリーメイトとお茶を食い終わって、万全の態勢で東京から戻ってきたのです。

そんで、今朝は、昨日東京に行ってきたかせいかすごく眠かったので、フリスクのすごーい辛いやつを食って目を覚ました。

……あ。くっちまった……

健康診断の時に素直に申請したら、「じゃあ今回は胃のレントゲン撮影なしですねーくしゃくしゃぽい」と胃カメラ用問診票を捨てられてしまった……

みんなが胃のレントゲン撮影している中、僕だけ撮影しない状態になり、撮影した人には「うんこしなくてすんで楽だのう」とか、「おめー、ぽんつくなんか?」とか言われてかえって針の筵でした。

来年は、気を抜かず胃カメラ撮影までたどりつけるよう頑張る所存でございます……

[日記・コラム・つぶやき] | 固定リンク | コメント (0) | トラックバック (0) | このエントリーをはてなブックマークへ追加 livedoor Clipでこのサイトを登録している人数livedoor Clipでこの記事をクリップ!

< 最後 « これより前10ä»¶ | 全件