monthly gimite 試験運用中。 2012-01-01T23:02:34+09:00 Gimite Hatena::Blog hatenablog://blog/12704346814673860630 Flexboxとを組み合わせるときはsize="1"が必要 hatenablog://entry/17680117126973992272 2015-12-26T00:50:30+09:00 2019-02-20T22:21:18+09:00 <div style="display: flex;"> <div style="flex: 1 1 auto;">hoge:</div> <input type="text" style="flex: 1 1 auto;"> </div> とした場合のこのinput要素、画面サイズが大きいぶんにはちゃんと伸びてくれるのですが、画面サイズが小さい場合にある程度以上小さくなってくれません。 <div style="display: flex;"> <div style="flex: 1 1 auto;">hoge:</div> <input type="text" size="1" style=… <pre class="code lang-html" data-lang="html" data-unlink><span class="synIdentifier">&lt;</span><span class="synStatement">div</span><span class="synIdentifier"> </span><span class="synType">style</span><span class="synIdentifier">=</span><span class="synConstant">&quot;display: flex;&quot;</span><span class="synIdentifier">&gt;</span> <span class="synIdentifier">&lt;</span><span class="synStatement">div</span><span class="synIdentifier"> </span><span class="synType">style</span><span class="synIdentifier">=</span><span class="synConstant">&quot;flex: 1 1 auto;&quot;</span><span class="synIdentifier">&gt;</span>hoge:<span class="synIdentifier">&lt;/</span><span class="synStatement">div</span><span class="synIdentifier">&gt;</span> <span class="synIdentifier">&lt;</span><span class="synStatement">input</span><span class="synIdentifier"> </span><span class="synType">type</span><span class="synIdentifier">=</span><span class="synConstant">&quot;text&quot;</span><span class="synIdentifier"> </span><span class="synType">style</span><span class="synIdentifier">=</span><span class="synConstant">&quot;flex: 1 1 auto;&quot;</span><span class="synIdentifier">&gt;</span> <span class="synIdentifier">&lt;/</span><span class="synStatement">div</span><span class="synIdentifier">&gt;</span> </pre><p>とした場合のこのinput要素、画面サイズが大きいぶんにはちゃんと伸びてくれるのですが、画面サイズが小さい場合にある程度以<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BE%E5%BE%AE">上小</a>さくなってくれません。</p> <pre class="code lang-html" data-lang="html" data-unlink><span class="synIdentifier">&lt;</span><span class="synStatement">div</span><span class="synIdentifier"> </span><span class="synType">style</span><span class="synIdentifier">=</span><span class="synConstant">&quot;display: flex;&quot;</span><span class="synIdentifier">&gt;</span> <span class="synIdentifier">&lt;</span><span class="synStatement">div</span><span class="synIdentifier"> </span><span class="synType">style</span><span class="synIdentifier">=</span><span class="synConstant">&quot;flex: 1 1 auto;&quot;</span><span class="synIdentifier">&gt;</span>hoge:<span class="synIdentifier">&lt;/</span><span class="synStatement">div</span><span class="synIdentifier">&gt;</span> <span class="synIdentifier">&lt;</span><span class="synStatement">input</span><span class="synIdentifier"> </span><span class="synType">type</span><span class="synIdentifier">=</span><span class="synConstant">&quot;text&quot;</span><span class="synIdentifier"> </span><span class="synType">size</span><span class="synIdentifier">=</span><span class="synConstant">&quot;1&quot;</span><span class="synIdentifier"> </span><span class="synType">style</span><span class="synIdentifier">=</span><span class="synConstant">&quot;flex: 1 1 auto;&quot;</span><span class="synIdentifier">&gt;</span> <span class="synIdentifier">&lt;/</span><span class="synStatement">div</span><span class="synIdentifier">&gt;</span> </pre><p>と <span class="deco" style="font-weight:bold;">size="1"</span> をつければ良いようです。sizeを省略した場合はデフォルトのsizeが適用されるわけですが、その幅以下には縮んでくれないようです。ちなみにsize="0"は不正な値なようで、駄目でした。動作確認は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>。</p> Gimite [programming][mahjong] シャンテン数計算アルゴリズムで各言語をベンチマーク hatenablog://entry/17680117126973992322 2013-09-19T23:30:37+09:00 2019-02-20T22:21:20+09:00 ymatsuxさんのシャンテン数計算アルゴリズムをいろんな言語に移植して速度を比較してみました。結果(所要時間): C++ (GCC 4.4.3): 2.07秒 Java 1.6.0: 3.53秒 C# (Mono 2.10.8): 3.57秒 JavaScript (Node.js 0.10.18): 4.78秒 Scala 2.9.1: 14.51秒 Ruby 1.9.3: 250.65秒 タスクは天鳳牌譜中のランダムな手牌1000個のシャンテン数計算です。同一マシンのtimeコマンドで計測した3回の平均。感想: V8かなり頑張ってる。C++の約2.4倍程度。 Scala意外と遅い。Jav… <p><a href="https://github.com/ymatsux/MjaiClients/blob/master/src/org/ymatsux/mjai/client/ShantensuUtil.java">ymatsux&#x3055;&#x3093;&#x306E;&#x30B7;&#x30E3;&#x30F3;&#x30C6;&#x30F3;&#x6570;&#x8A08;&#x7B97;&#x30A2;&#x30EB;&#x30B4;&#x30EA;&#x30BA;&#x30E0;</a>をいろんな言語に移植して速度を比較してみました。</p><p>結果(所要時間):</p> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/C%2B%2B">C++</a> (<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCC">GCC</a> 4.4.3): 2.07秒</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Java">Java</a> 1.6.0: 3.53秒</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/C%23">C#</a> (Mono 2.10.8): 3.57秒</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a> (Node.js 0.10.18): 4.78秒</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Scala">Scala</a> 2.9.1: 14.51秒</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Ruby%201.9">Ruby 1.9</a>.3: 250.65秒</li> </ul><p>タスクは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%B7%CB%B1">天鳳</a>牌譜中のランダムな手牌1000個のシャンテン数計算です。同一マシンのtimeコマンドで計測した3回の平均。</p><p>感想:</p> <ul> <li>V8かなり頑張ってる。<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%2B%2B">C++</a>の約2.4倍程度。</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Scala">Scala</a>意外と遅い。<a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a>に負けてる。</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Ruby">Ruby</a>めっちゃ遅い。こういうのを書く言語じゃないんでしょうけど。</li> </ul><p>注:</p> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Scala">Scala</a>の数字が<a href="https://plus.google.com/117540889015776612378/posts/LrN9jGkncyt">&#x524D;&#x56DE;</a>と変わってるのは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Hayato">Hayato</a>さんの勧めに従ってforをwhileに書き換えたのと-optimizeオプションを付けたことで合計2倍程度高速化したためです。</li> <li>もちろんこういうのはタスク依存でコードの書き方依存なので色々と一概には言えない。</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0">アルゴリズム</a>自体は色々と改良の余地があると思っている。とりあえず3倍程度に高速化する<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0">アルゴリズム</a>は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BC%C2%C1%F5%BA%D1">実装済</a>み。</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Java">Java</a>版以外は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BC%B7%C2%D0%BB%D2">七対子</a>を考慮してません。どの実装も<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B9%F1%BB%CE%CC%B5%C1%D0">国士無双</a>を考慮していません。計測時は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Java">Java</a>版に手を入れて<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BC%B7%C2%D0%BB%D2">七対子</a>の計算を無効化してます。</li> </ul><p>というわけで<a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a>が意外と速いので麻雀AI <a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a>で書こうかなー。</p><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>:</p> <ul> <li><a href="https://gist.github.com/gimite/6249634">C++, Scala, JavaScript</a></li> <li><a href="https://github.com/ymatsux/MjaiClients/blob/master/src/org/ymatsux/mjai/client/ShantensuUtil.java">Java</a></li> <li><a href="https://github.com/gimite/mjai/blob/master/lib/mjai/ymatsux_shanten_analysis.rb">Ruby</a></li> <li><a href="https://gist.github.com/yuizumi/547960ae83c9b3059b07">C#</a></li> </ul><p>牌は1m, 2m, ..., 9m, 1p, 2p, ..., 9p, 1s, 2s, ..., 9s, 東, 南, 西, 北, 白, 發, 中の順の0-originの通し番号で表現されています。</p><p><span class="deco" style="font-weight:bold;">2013/9/21追記:</span> yuizumiさんに<a href="https://gist.github.com/yuizumi/547960ae83c9b3059b07">C#&#x7248;</a>をもらったので追加。</p> Gimite [mahjong][tenhou] 天鳳牌譜の統計による麻雀危険牌分析 hatenablog://entry/17680117126973992350 2012-10-19T11:34:17+09:00 2019-02-20T22:21:20+09:00 ネット麻雀の天鳳で公開されている、天鳳位の人の牌譜17670ゲームを集計して、牌の危険度を分析しました。詳細はこちら:統計による麻雀危険牌分析得られた主な知見: 大雑把な危険度: 字牌 = 中スジ = ノーチャンス 中スジ(2p, 8pに対する5pなど)は表スジ(4pに対する1pなど)より安全。 生牌の字牌はスジの通った数牌よりやや危険、片スジよりは安全。 序盤の捨て牌の外側はスジと同程度に安全。 暗刻スジはやや危険度が上がる。 裏スジは危険度に影響しない。序盤の裏スジに限っても特に危険ではない。 ただし序盤に5を捨てている場合の1, 9は危険度が上がる。 間四間も危険度に影響しない。 またぎ… <p>ネット麻雀の<a href="http://tenhou.net/">&#x5929;&#x9CF3;</a>で公開されている、<a href="http://tenhou.net/ranking.html">&#x5929;&#x9CF3;&#x4F4D;&#x306E;&#x4EBA;&#x306E;&#x724C;&#x8B5C;</a>17670ゲームを集計して、牌の危険度を分析しました。詳細はこちら:</p><p><a href="http://gimite.net/pukiwiki/index.php?%C5%FD%B7%D7%A4%CB%A4%E8%A4%EB%CB%E3%BF%FD%B4%ED%B8%B1%C7%D7%CA%AC%C0%CF">&#x7D71;&#x8A08;&#x306B;&#x3088;&#x308B;&#x9EBB;&#x96C0;&#x5371;&#x967A;&#x724C;&#x5206;&#x6790;</a></p><p>得られた主な知見:</p> <ul> <li>大雑把な危険度: <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BB%FA%C7%D7">字牌</a> = 中スジ = ノーチャンス < 表スジ << ワンチャンス < 片スジ << 無スジ</li> </ul></li> <li>中スジ(2p, 8pに対する5pなど)は表スジ(4pに対する1pなど)より安全。</li> <li>生牌の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BB%FA%C7%D7">字牌</a>はスジの通った数牌よりやや危険、片スジよりは安全。</li> <li>序盤の捨て牌の外側はスジと同程度に安全。</li> <li>暗刻スジはやや危険度が上がる。</li> <li>裏スジは危険度に影響しない。序盤の裏スジに限っても特に危険ではない。</li> <li>ただし序盤に5を捨てている場合の1, 9は危険度が上がる。</li> <li>間四間も危険度に影響しない。</li> <li>またぎスジは基本的に危険度が下がる。リーチ牌のまたぎスジであってもノーヒントよりはやや安全。</li> <li>ここのブログの放置ぶりがひどい。</li> </ul> Gimite [mahjong] 麻雀AIと麻雀AI対戦サーバを公開 hatenablog://entry/17680117126973992369 2012-04-30T00:09:50+09:00 2019-02-20T22:21:21+09:00 最近麻雀AIを作っています。現状のAI同士を対戦させるとこんな感じです(たぶんChromeでしか見れません)。一応それっぽく動いています。まだまだナイーブで、あまり強くないですが。まだ役やドラの価値を考慮してないので、赤ドラをガンガン切ってますね…。このAIのために対戦サーバを作りました。TCPでこんな感じのJSONを送り合って対戦できます。もし使いたい人がいたらご自由にどうぞ。詳細はこちら:Mjai 麻雀AI対戦サーバソースはこちら: gimite/mjai - Github : 対戦サーバ gimite/mjai-manue - Github : AI <p>最近麻雀AIを作っています。現状のAI同士を対戦させると<a href="http://gimite.net/mjai/samples/manue1.mjson.html">&#x3053;&#x3093;&#x306A;&#x611F;&#x3058;</a>です(たぶん<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>でしか見れません)。一応それっぽく動いています。まだまだナイーブで、あまり強くないですが。まだ役やドラの価値を考慮してないので、赤ドラをガンガン切ってますね…。</p><p>このAIのために対戦サーバを作りました。<a class="keyword" href="http://d.hatena.ne.jp/keyword/TCP">TCP</a>で<a href="http://gimite.net/mjai/samples/sample3.protocol.txt">&#x3053;&#x3093;&#x306A;&#x611F;&#x3058;&#x306E;JSON</a>を送り合って対戦できます。もし使いたい人がいたらご自由にどうぞ。詳細はこちら:</p><p><a href="http://gimite.net/mjai/">Mjai &#x9EBB;&#x96C0;AI&#x5BFE;&#x6226;&#x30B5;&#x30FC;&#x30D0;</a></p><p>ソースはこちら:</p> <ul> <li><a href="https://github.com/gimite/mjai">gimite/mjai - Github</a> : 対戦サーバ</li> <li><a href="https://github.com/gimite/mjai-manue">gimite/mjai-manue - Github</a> : AI</li> </ul> Gimite [ruby][googledrive] Google DriveにアクセスするRubyライブラリを作りました hatenablog://entry/17680117126973992388 2012-04-29T17:28:56+09:00 2019-02-20T22:21:22+09:00 google-drive-ruby - Github作りました、というか、google-spreadsheet-rubyにスプレッドシート以外のファイルをアップロード/ダウンロードする機能を加えて改名しました。Google Drive Appを作るライブラリではありません。Google Driveにアクセスする2種類のライブラリの違いについてはこちら。インストール: $ sudo gem install google_drive使用例: require "rubygems" require "google_drive" # Logs in. # You can also use OAuth. … <p><a href="https://github.com/gimite/google-drive-ruby">google-drive-ruby - Github</a></p><p>作りました、というか、<a class="keyword" href="http://d.hatena.ne.jp/keyword/google">google</a>-spreadsheet-<a class="keyword" href="http://d.hatena.ne.jp/keyword/ruby">ruby</a>に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%D7%A5%EC%A5%C3%A5%C9%A5%B7%A1%BC%A5%C8">スプレッドシート</a>以外のファイルをアップロード/ダウンロードする機能を加えて改名しました。</p><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google%20Drive">Google Drive</a> Appを作るライブラリではありません。<a href="https://plus.google.com/u/0/117540889015776612378/posts/RkMqnNsDHEf">Google Drive&#x306B;&#x30A2;&#x30AF;&#x30BB;&#x30B9;&#x3059;&#x308B;2&#x7A2E;&#x985E;&#x306E;&#x30E9;&#x30A4;&#x30D6;&#x30E9;&#x30EA;&#x306E;&#x9055;&#x3044;&#x306B;&#x3064;&#x3044;&#x3066;&#x306F;&#x3053;&#x3061;&#x3089;</a>。</p><p>インストール:</p> <pre class="code" data-lang="" data-unlink>$ sudo gem install google_drive</pre><p>使用例:</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">require</span> <span class="synSpecial">&quot;</span><span class="synConstant">rubygems</span><span class="synSpecial">&quot;</span> <span class="synPreProc">require</span> <span class="synSpecial">&quot;</span><span class="synConstant">google_drive</span><span class="synSpecial">&quot;</span> <span class="synComment"># Logs in.</span> <span class="synComment"># You can also use OAuth. See document of</span> <span class="synComment"># GoogleDrive.login_with_oauth for details.</span> session = <span class="synType">GoogleDrive</span>.login(<span class="synSpecial">&quot;</span><span class="synConstant">username@gmail.com</span><span class="synSpecial">&quot;</span>, <span class="synSpecial">&quot;</span><span class="synConstant">mypassword</span><span class="synSpecial">&quot;</span>) <span class="synComment"># Gets list of remote files.</span> <span class="synStatement">for</span> file <span class="synStatement">in</span> session.files p file.title <span class="synStatement">end</span> <span class="synComment"># Uploads a local file.</span> session.upload_from_file(<span class="synSpecial">&quot;</span><span class="synConstant">/path/to/hello.txt</span><span class="synSpecial">&quot;</span>, <span class="synSpecial">&quot;</span><span class="synConstant">hello.txt</span><span class="synSpecial">&quot;</span>, <span class="synConstant">:convert</span> =&gt; <span class="synConstant">false</span>) <span class="synComment"># Downloads to a local file.</span> file = session.file_by_title(<span class="synSpecial">&quot;</span><span class="synConstant">hello.txt</span><span class="synSpecial">&quot;</span>) file.download_to_file(<span class="synSpecial">&quot;</span><span class="synConstant">/path/to/hello.txt</span><span class="synSpecial">&quot;</span>) <span class="synComment"># Updates content of the remote file.</span> file.update_from_file(<span class="synSpecial">&quot;</span><span class="synConstant">/path/to/hello.txt</span><span class="synSpecial">&quot;</span>) </pre><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/google">google</a>-spreadsheet-<a class="keyword" href="http://d.hatena.ne.jp/keyword/ruby">ruby</a>は</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">require</span> <span class="synSpecial">&quot;</span><span class="synConstant">google_drive</span><span class="synSpecial">&quot;</span> <span class="synType">GoogleSpreadsheet</span> = <span class="synType">GoogleDrive</span> </pre><p>するだけのライブラリになる予定です。</p> Gimite [android] Androidアプリ「かんたん検索」公開 hatenablog://entry/17680117126973992438 2012-02-14T13:27:20+09:00 2019-02-20T22:21:23+09:00 かんたん検索というAndroidタブレットアプリを公開しました。かんたん検索パソコンや携帯電話が苦手な人でも簡単に使える、ウェブ検索アプリです。とても簡単に使えるので、Androidタブレットを持っていて、まわりに「パソコンは苦手/使わない」というご家族/ご友人がいれば、ぜひ一度試してもらってみてください。使い方:1. 五十音のボタンで調べたい単語を入力して、[検索]ボタンにタッチ。 2. その単語についてのウェブページが表示される。 たったこれだけです。ローマ字入力や漢字変換といった難しい操作は不要です。注: これはオープンソースのプロジェクトであり、現在所属している会社の製品ではありません… <p>かんたん検索という<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%D6%A5%EC%A5%C3%A5%C8">タブレット</a>アプリを公開しました。</p><p><a href="https://market.android.com/details?id=com.googlecode.kantankensaku">&#x304B;&#x3093;&#x305F;&#x3093;&#x691C;&#x7D22;</a></p><p>パソコンや携帯電話が苦手な人でも簡単に使える、ウェブ検索アプリです。とても簡単に使えるので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%D6%A5%EC%A5%C3%A5%C8">タブレット</a>を持っていて、まわりに「パソコンは苦手/使わない」というご家族/ご友人がいれば、ぜひ一度試してもらってみてください。</p><p>使い方:</p><p>1. 五十音のボタンで調べたい単語を入力して、[検索]ボタンにタッチ。<br /> <span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/Gimite/20120214131018" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/G/Gimite/20120214/20120214131018.jpg" alt="f:id:Gimite:20120214131018j:image" title="f:id:Gimite:20120214131018j:image" class="hatena-fotolife" itemprop="image"></a></span></p><p>2. その単語についてのウェブページが表示される。<br /> <span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/Gimite/20120214131019" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/G/Gimite/20120214/20120214131019.jpg" alt="f:id:Gimite:20120214131019j:image" title="f:id:Gimite:20120214131019j:image" class="hatena-fotolife" itemprop="image"></a></span></p><p>たったこれだけです。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%ED%A1%BC%A5%DE%BB%FA%C6%FE%CE%CF">ローマ字入力</a>や漢字変換といった難しい操作は不要です。</p><p>注: これは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D7%A5%F3%A5%BD%A1%BC%A5%B9">オープンソース</a>のプロジェクトであり、現在所属している会社の製品ではありません。</p> Gimite テスト hatenablog://entry/12704346814673860668 2012-01-01T23:02:34+09:00 2012-01-01T23:25:41+09:00 一般公開と聞いて作ってみました。こっちに移ってくるかどうかは未定。 無駄に色々スタイルを使ってみるテスト。 ブログパーツ系は現状無理っぽい?と思ったら出てきた。iframeも使えるのか。プレビューだと出ないんですね…。あと見たまま編集モードで挿入する方法はなさそう? というかJavaScriptが自由に動くっぽいですね。 Click here あと+1ボタンがあるのを発見。 iframe: google gadget: <p>一般公開と聞いて作ってみました。こっちに移ってくるかどうかは未定。</p> <ul> <li><strong>無駄に</strong>色々<a href="http://ja.wikipedia.org/wiki/%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB">スタイル</a>を使ってみる<span style="color: #cc0000;">テスト</span>。&nbsp;</li> </ul> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D6%A5%ED%A5%B0%A5%D1%A1%BC%A5%C4">ブログパーツ</a>系は現状無理っぽい?と思ったら出てきた。iframeも使えるのか。プレビューだと出ないんですね&hellip;。あと見たまま編集モードで挿入する方法はなさそう?</p> <p>というか<a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a>が自由に動くっぽいですね。</p> <p><button onclick="alert('Hello!');">Click here</button></p> <p>あと+1ボタンがあるのを発見。</p> <p>iframe:</p> <p><iframe src="http://docs.google.com/EmbedSlideshow?docid=dc3xhpx3_3cmrbxk" frameborder="0" width="410" height="342"></iframe></p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/google">google</a> gadget:</p> <script type="text/javascript" src="http://gmodules.com/ig/ifr?url=http://gimite.net/rails/iframe_gadget/xml%3Fparams%3Dscrolling%3Dtrue%21url%3Dhttp://docs.google.com/EmbedSlideshow%253Fdocid%253Ddc3xhpx3_3cmrbxk&amp;synd=open&amp;w=410&amp;h=342&amp;title=&amp;border=%23ffffff%7C3px%2C1px+solid+%23999999&amp;output=js"></script> Gimite Twitterの検索結果の1日単位のフィードを作った hatenablog://entry/17680117126973992463 2011-12-17T11:57:46+09:00 2019-02-20T22:21:23+09:00 Twitterの検索結果の1日単位のAtomフィードを作りました:Twitter daily search result Atom feed今までTwitter公式の検索結果フィードをGoogle Readerに登録していたのですが、これだと1 Tweetごとに別のエントリになってしまって、見にくいです。そこで、1日分の検索結果をまとめて1エントリにするAtomフィードを作りました。実験的に作ったもので、配信を停止する場合があります。 <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>の検索結果の1日単位の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Atom%A5%D5%A5%A3%A1%BC%A5%C9">Atomフィード</a>を作りました:</p><p><a href="http://tweet-feed.yuyake-dev.appspot.com/">Twitter daily search result Atom feed</a></p><p>今まで<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>公式の検索結果フィードを<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google%20Reader">Google Reader</a>に登録していたのですが、これだと1 <a class="keyword" href="http://d.hatena.ne.jp/keyword/Tweet">Tweet</a>ごとに別のエントリになってしまって、見にくいです。そこで、1日分の検索結果をまとめて1エントリにする<a class="keyword" href="http://d.hatena.ne.jp/keyword/Atom%A5%D5%A5%A3%A1%BC%A5%C9">Atomフィード</a>を作りました。</p><p>実験的に作ったもので、配信を停止する場合があります。</p> Gimite [web][android] パスワードの代わりにAndroid携帯で認証するサイトのデモを作った hatenablog://entry/17680117126973992488 2011-11-20T20:23:15+09:00 2019-02-20T22:21:24+09:00 Touchauth Demo試すのが若干面倒(Androidアプリのインストールが必要)なので、動画も用意してみました。携帯で撮った低解像度手ぶれ動画ですが…。各PC/ブラウザに対して、 初回はブラウザ上に表示されたQRコードを携帯で撮ることで認証。 2回目以降はログインボタンをクリックすると携帯に自動的にログインボタンが表示されるので、それをクリックして認証。(動画はこっち) という感じになっています。個人的にいい加減パスワードで認証するのは古いよなーと(作るのも覚えるのも面倒、特に数が増えると)思っていて、思いついた方法です。携帯なくしたら終わりなのはどうよ、という説はありますが…。Web… <p><a href="http://touchauth.gimite.net/">Touchauth Demo</a></p><p>試すのが若干面倒(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>アプリのインストールが必要)なので、動画も用意してみました。携帯で撮った低解像度手ぶれ動画ですが…。</p><p><iframe width="420" height="315" src="https://www.youtube.com/embed/of_V0F7nGug?wmode=transparent" frameborder="0" allowfullscreen></iframe></p><p>各PC/ブラウザに対して、</p> <ul> <li>初回はブラウザ上に表示された<a class="keyword" href="http://d.hatena.ne.jp/keyword/QR%A5%B3%A1%BC%A5%C9">QRコード</a>を携帯で撮ることで認証。</li> <li>2回目以降はログインボタンをクリックすると携帯に自動的にログインボタンが表示されるので、それをクリックして認証。(動画はこっち)</li> </ul><p>という感じになっています。</p><p>個人的にいい加減パスワードで認証するのは古いよなーと(作るのも覚えるのも面倒、特に数が増えると)思っていて、思いついた方法です。携帯なくしたら終わりなのはどうよ、という説はありますが…。</p><p>WebSocketと<a href="http://code.google.com/intl/ja/android/c2dm/">C2DM</a>を使ってブラウザと<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>にそれぞれプッシュすることで、両者を連携させています。</p> Gimite Tweet Search Streamでキーワードに関連するハッシュタグを表示 hatenablog://entry/17680117126973992509 2011-08-08T10:36:25+09:00 2019-02-20T22:21:25+09:00 Tweet Search Streamにハッシュタグ以外のキーワードを入れたときに、そのキーワードに関連する(と思われる)ハッシュタグを(あれば)表示するようになりました。「このイベントのハッシュタグは何だろう」という時に便利かもしれません。「関連する」といっても、検索結果のTweetに含まれるハッシュタグを表示しているだけです。なのでゴミが混ざったり、適切なものが出てこない場合も多々あります…。ついでに、複数ハッシュタグのOR検索もできるようになりました。大文字の" OR "でつないでください。 <p><a href="http://tweet-search-stream.gimite.net/">Tweet Search Stream</a>に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CF%A5%C3%A5%B7%A5%E5%A5%BF%A5%B0">ハッシュタグ</a>以外のキーワードを入れたときに、そのキーワードに関連する(と思われる)<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CF%A5%C3%A5%B7%A5%E5%A5%BF%A5%B0">ハッシュタグ</a>を(あれば)表示するようになりました。</p><p><img src="http://gyazo.com/2e4c292d427a425cc0907471ca775fc4.png"></p><p>「このイベントの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CF%A5%C3%A5%B7%A5%E5%A5%BF%A5%B0">ハッシュタグ</a>は何だろう」という時に便利かもしれません。</p><p>「関連する」といっても、検索結果の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Tweet">Tweet</a>に含まれる<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CF%A5%C3%A5%B7%A5%E5%A5%BF%A5%B0">ハッシュタグ</a>を表示しているだけです。なのでゴミが混ざったり、適切なものが出てこない場合も多々あります…。</p><p>ついでに、複数<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CF%A5%C3%A5%B7%A5%E5%A5%BF%A5%B0">ハッシュタグ</a>のOR検索もできるようになりました。大文字の" OR "でつないでください。</p> Gimite Yuyake - ブラウザ上でRubyでWebアプリ開発 hatenablog://entry/17680117126973992531 2011-07-24T20:31:18+09:00 2019-02-20T22:21:25+09:00 色々未完成なのですが、放置気味だったのでとりあえず現状を公開することにしました。Yuyakeブラウザ上でRubyでWebアプリを開発してそのまま実行できる、というものです。フレームワークはSinatraのみをサポートしてます。利用にはGoogleアカウント*1が必要です。 おことわり 実験的なサービスなので、突然落ちたり、サービス終了したり、データが消えたりする可能性があります。また、Yuyake上の全アプリケーションがAppEngineの無料クオータを共有することになるので、誰かが使いすぎるとサービス全体が落ちます :) まあ落ちてもいいのですが、わざと負荷をかけないようにしてください。そん… <p>色々未完成なのですが、放置気味だったのでとりあえず現状を公開することにしました。</p><p><a href="http://admin.yuyake-dev.appspot.com/">Yuyake</a></p><p><img src="http://gyazo.com/dce4421c3f5500ad5296b81641a5d44e.png"></p><p>ブラウザ上で<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ruby">Ruby</a>でWebアプリを開発してそのまま実行できる、というものです。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EC%A1%BC%A5%E0%A5%EF%A1%BC%A5%AF">フレームワーク</a>は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Sinatra">Sinatra</a>のみをサポートしてます。利用には<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a>アカウント<a href="#f-157c74c6" name="fn-157c74c6" title="Google+アカウントではない。">*1</a>が必要です。</p> <div class="section"> <h4>おことわり</h4> <p>実験的なサービスなので、突然落ちたり、サービス終了したり、データが消えたりする可能性があります。また、Yuyake上の全アプリケーションがAppEngineの無料クオータを共有することになるので、誰かが使いすぎるとサービス全体が落ちます :) まあ落ちてもいいのですが、わざと負荷をかけないようにしてください。</p><p>そんな感じでいまいち実用的ではないのですが、AppEngineで動くので、自分のアカウントで自分専用のやつを立ち上げることができます(ソースがあれば。近日公開予定)。その方法なら、使い物になるかもしれません。</p> </div> <div class="section"> <h4>利用可能な<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ruby">Ruby</a>の機能</h4> <p>FileとかSocketとか以外の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ruby">Ruby</a>の組み込みクラス/標準ライブラリは使えるはずですが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B5%A5%F3%A5%C9%A5%DC%A5%C3%A5%AF%A5%B9">サンドボックス</a>のせいでところどころ動きません。データベースは現状使えませんが、Yuyake::SStore, Yuyake::AStoreというkey/<a class="keyword" href="http://d.hatena.ne.jp/keyword/value">value</a>ストアが使えます。自動生成されるソースのコメント参照。</p> </div> <div class="section"> <h4>実装</h4> <p><a href="http://c9.io/">Cloud9 IDE</a>(これはnode.js用)の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ruby">Ruby</a>版(&しょぼい版)みたいな感じです。Herokuが昔<a class="keyword" href="http://d.hatena.ne.jp/keyword/Rails">Rails</a>で似たようなことをやっていた気がするのですが、今見るとローカルで書いてアップロードする方法しか見当たらない…。</p><p>実装は<a href="http://code.google.com/p/appengine-jruby/wiki/GettingStarted">AppEngine+JRuby</a>です。<a href="#f-3305abe4" name="fn-3305abe4" title="たまにやけに反応が遅いのはAppEngine+JRubyの起動が遅いせい。">*2</a>ユーザのコードは<a href="http://flouri.sh/2009/4/4/how-to-set-up-the-jruby-sandbox">javasand</a>という<a class="keyword" href="http://d.hatena.ne.jp/keyword/JRuby">JRuby</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B5%A5%F3%A5%C9%A5%DC%A5%C3%A5%AF%A5%B9">サンドボックス</a>の中に入れて実行しています。</p><p>エディタの部分は<a href="http://ace.ajax.org/">Cloud9 IDE&#x306E;&#x30A8;&#x30C7;&#x30A3;&#x30BF;&#x90E8;&#x5206;</a>が単独で公開されているので、それを使っています。各種言語の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%F3%A5%BF%A5%C3%A5%AF%A5%B9">シンタックス</a>ハイライトとかオートインデントとかしてくれて、いい感じです。</p> </div><div class="footnote"> <p class="footnote"><a href="#fn-157c74c6" name="f-157c74c6" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google%2B">Google+</a>アカウントではない。</span></p> <p class="footnote"><a href="#fn-3305abe4" name="f-3305abe4" class="footnote-number">*2</a><span class="footnote-delimiter">:</span><span class="footnote-text">たまにやけに反応が遅いのはAppEngine+<a class="keyword" href="http://d.hatena.ne.jp/keyword/JRuby">JRuby</a>の起動が遅いせい。</span></p> </div> Gimite Tweet Search Streamが日本語ハッシュタグに対応 hatenablog://entry/17680117126973992557 2011-07-17T23:21:14+09:00 2019-02-20T22:21:26+09:00 Tweet Search Streamを日本語ハッシュタグに対応させました。例: #名言の文末を過去形にすると深みが増す - Tweet Search Streamバリデーションを弱めればいいだけかと思ったら、 Tweet Search StreamはJSONを解釈する前にキーワードでのgrepをかける Twitter APIから来るJSONはマルチバイト文字が\uxxxxの形にエスケープされている ので意外と面倒くさいことに。なんかバグがあるかもしれません。特にTweet中のオートリンクはそもそも仕様がよく分からないのでテキトーです。# 日本語は単語間にスペースを入れる必要がないので、やたら… <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Tweet">Tweet</a> Search Streamを日本語<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CF%A5%C3%A5%B7%A5%E5%A5%BF%A5%B0">ハッシュタグ</a>に対応させました。</p><p>例: <a href="http://tweet-search-stream.gimite.net/search?q=%23%E5%90%8D%E8%A8%80%E3%81%AE%E6%96%87%E6%9C%AB%E3%82%92%E9%81%8E%E5%8E%BB%E5%BD%A2%E3%81%AB%E3%81%99%E3%82%8B%E3%81%A8%E6%B7%B1%E3%81%BF%E3%81%8C%E5%A2%97%E3%81%99&hl=ja">#&#x540D;&#x8A00;&#x306E;&#x6587;&#x672B;&#x3092;&#x904E;&#x53BB;&#x5F62;&#x306B;&#x3059;&#x308B;&#x3068;&#x6DF1;&#x307F;&#x304C;&#x5897;&#x3059; - Tweet Search Stream</a></p><p>バリデーションを弱めればいいだけかと思ったら、</p> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Tweet">Tweet</a> Search Streamは<a class="keyword" href="http://d.hatena.ne.jp/keyword/JSON">JSON</a>を解釈する前にキーワードでの<a class="keyword" href="http://d.hatena.ne.jp/keyword/grep">grep</a>をかける</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>から来る<a class="keyword" href="http://d.hatena.ne.jp/keyword/JSON">JSON</a>はマルチバイト文字が\uxxxxの形に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>ケープされている</li> </ul><p>ので意外と面倒くさいことに。なんかバグがあるかもしれません。特に<a class="keyword" href="http://d.hatena.ne.jp/keyword/Tweet">Tweet</a>中のオートリンクはそもそも仕様がよく分からないのでテキトーです。</p><p># 日本語は単語間にスペースを入れる必要がないので、やたら長い(けど可読な)<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CF%A5%C3%A5%B7%A5%E5%A5%BF%A5%B0">ハッシュタグ</a>が作れるんですね…。</p> Gimite [tss][websocket][js] web-socket-jsとTweet Search Streamのスライド hatenablog://entry/17680117126973992583 2011-06-25T15:01:02+09:00 2019-02-20T22:21:27+09:00 すっかり忘れていたのですが、しばらく前に社内でweb-socket-jsとTweet Search Streamについて発表する機会があったので、そのスライドを置いておきます。内容的にはこのブログに書き散らしたことの詰め合わせみたいな感じだし、文字ばっかりだし、なんか英語だし、あまり面白くはないと思いますが…。 <p>すっかり忘れていたのですが、しばらく前に社内で<a href="https://github.com/gimite/web-socket-js">web-socket-js</a>と<a href="http://tweet-search-stream.gimite.net/">Tweet Search Stream</a>について発表する機会があったので、そのスライドを置いておきます。</p><p><script src="http://gmodules.com/ig/ifr?url=http://gimite.net/rails/iframe_gadget/xml%3Fparams%3Dscrolling%3Dtrue%21url%3Dhttps://docs.google.com/present/embed%253Fid%253Ddc3xhpx3_29c9p95v97&amp;synd=open&amp;w=410&amp;h=342&amp;title=&amp;border=%23ffffff%7C3px%2C1px+solid+%23999999&amp;output=js"></script></p><p>内容的にはこのブログに書き散らしたことの詰め合わせみたいな感じだし、文字ばっかりだし、なんか英語だし、あまり面白くはないと思いますが…。</p> Gimite Fiberを使ってem-http-requestとかを同期的に呼び出す hatenablog://entry/17680117126973992600 2011-05-14T21:09:19+09:00 2019-02-20T22:21:27+09:00 EventMachineの関数(em-http-requestとか)を多用すると、コールバックだらけになって訳が分からなくなるのが欠点です。Ruby 1.9のFiberを使うと、em-http-requestみたいな非同期関数を同期的に呼ぶことができます。em-synchronyというライブラリがそのようなラッパを提供してるのを見つけました。 require "em-synchrony" require "em-synchrony/em-http" p EM::HttpRequest.new("http://www.google.com").get.response p EM::HttpReq… <p>EventMachineの関数(em-http-requestとか)を多用すると、コールバックだらけになって訳が分からなくなるのが欠点です。</p><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Ruby%201.9">Ruby 1.9</a>のFiberを使うと、em-http-requestみたいな非同期関数を同期的に呼ぶことができます。<a href="https://github.com/igrigorik/em-synchrony">em-synchrony</a>というライブラリがそのようなラッパを提供してるのを見つけました。</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">require</span> <span class="synSpecial">&quot;</span><span class="synConstant">em-synchrony</span><span class="synSpecial">&quot;</span> <span class="synPreProc">require</span> <span class="synSpecial">&quot;</span><span class="synConstant">em-synchrony/em-http</span><span class="synSpecial">&quot;</span> p <span class="synType">EM</span>::<span class="synType">HttpRequest</span>.new(<span class="synSpecial">&quot;</span><span class="synConstant">http://www.google.com</span><span class="synSpecial">&quot;</span>).get.response p <span class="synType">EM</span>::<span class="synType">HttpRequest</span>.new(<span class="synSpecial">&quot;</span><span class="synConstant">http://www.yahoo.com</span><span class="synSpecial">&quot;</span>).get.response </pre><p>こうすると<a href="http://www.google.com">http://www.google.com</a>と<a href="http://www.yahoo.com">http://www.yahoo.com</a>を順にロードします(ロード中もちゃんとEventMachineが動きます)。これはFiberの中で実行する必要があります。方法としては、EM.synchronyを使う方法:</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synType">EM</span>.synchrony <span class="synStatement">do</span> p <span class="synType">EM</span>::<span class="synType">HttpRequest</span>.new(<span class="synSpecial">&quot;</span><span class="synConstant">http://www.google.com</span><span class="synSpecial">&quot;</span>).get.response p <span class="synType">EM</span>::<span class="synType">HttpRequest</span>.new(<span class="synSpecial">&quot;</span><span class="synConstant">http://www.yahoo.com</span><span class="synSpecial">&quot;</span>).get.response <span class="synStatement">end</span> </pre><p>と、自分でFiberを作る方法:</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synType">EM</span>.run <span class="synStatement">do</span> ... <span class="synType">Fiber</span>.new { p <span class="synType">EM</span>::<span class="synType">HttpRequest</span>.new(<span class="synSpecial">&quot;</span><span class="synConstant">http://www.google.com</span><span class="synSpecial">&quot;</span>).get.response p <span class="synType">EM</span>::<span class="synType">HttpRequest</span>.new(<span class="synSpecial">&quot;</span><span class="synConstant">http://www.yahoo.com</span><span class="synSpecial">&quot;</span>).get.response }.resume ... <span class="synStatement">end</span> </pre><p>があります。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Sinatra">Sinatra</a>で使う場合は<a href="https://github.com/mperham/rack-fiber_pool">rack-fiber_pool</a>というのを使うと、リク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>ト処理全体をFiberで囲ってくれるようです。</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">require</span> <span class="synSpecial">&quot;</span><span class="synConstant">sinatra</span><span class="synSpecial">&quot;</span> <span class="synPreProc">require</span> <span class="synSpecial">&quot;</span><span class="synConstant">em-synchrony</span><span class="synSpecial">&quot;</span> <span class="synPreProc">require</span> <span class="synSpecial">&quot;</span><span class="synConstant">em-synchrony/em-http</span><span class="synSpecial">&quot;</span> <span class="synPreProc">require</span> <span class="synSpecial">&quot;</span><span class="synConstant">rack/fiber_pool</span><span class="synSpecial">&quot;</span> use(<span class="synType">Rack</span>::<span class="synType">FiberPool</span>) get(<span class="synSpecial">&quot;</span><span class="synConstant">/</span><span class="synSpecial">&quot;</span>) <span class="synStatement">do</span> res1 = <span class="synType">EM</span>::<span class="synType">HttpRequest</span>.new(<span class="synSpecial">&quot;</span><span class="synConstant">http://www.google.com</span><span class="synSpecial">&quot;</span>).get.response res2 = <span class="synType">EM</span>::<span class="synType">HttpRequest</span>.new(<span class="synSpecial">&quot;</span><span class="synConstant">http://www.yahoo.com</span><span class="synSpecial">&quot;</span>).get.response res1 + res2 <span class="synStatement">end</span> </pre><p><a href="http://d.hatena.ne.jp/Gimite/20101017/1287298216">async_sinatra&#x3092;&#x4F7F;&#x3046;</a>のと同じことが、もっと楽に書けるわけですね。<a href="https://github.com/kyledrake/sinatra-synchrony">sinatra-synchrony</a>というのもあるようですが、こっちはちゃんと見てないのでよくわかりません…。</p><p>ちなみに上のような例では(よく分からない例ですが)同時並行でロードするとベターなわけですが、そういう時のためにFiberを使って同時並行で実行するeachを作ってみました。</p><p><a href="https://github.com/gimite/em-fiber-utils">em-fiber-utils</a><br /> </p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">require</span> <span class="synSpecial">&quot;</span><span class="synConstant">em-synchrony</span><span class="synSpecial">&quot;</span> <span class="synPreProc">require</span> <span class="synSpecial">&quot;</span><span class="synConstant">em-synchrony/em-http</span><span class="synSpecial">&quot;</span> <span class="synPreProc">require</span> <span class="synSpecial">&quot;</span><span class="synConstant">em-fiber-utils</span><span class="synSpecial">&quot;</span> <span class="synType">EM</span>.synchrony <span class="synStatement">do</span> urls = [<span class="synSpecial">&quot;</span><span class="synConstant">http://www.google.com</span><span class="synSpecial">&quot;</span>, <span class="synSpecial">&quot;</span><span class="synConstant">http://www.yahoo.com</span><span class="synSpecial">&quot;</span>] <span class="synType">EM</span>::<span class="synType">FiberUtils</span>.concurrent_each(urls) <span class="synStatement">do</span> |<span class="synIdentifier">url</span>| <span class="synComment"># ここが同時並行で実行される。</span> p <span class="synType">EM</span>::<span class="synType">HttpRequest</span>.new(url).get.response <span class="synStatement">end</span> <span class="synComment"># 両方終わるとここに来る。</span> <span class="synStatement">end</span> </pre> Gimite [js] 次世代JavaScriptのawait (Deferred Functions) hatenablog://entry/17680117126973992663 2011-05-09T22:29:40+09:00 2019-02-20T22:21:29+09:00 この記事で知ったのですが、次世代JavaScriptのawaitという機能が楽しそうです。 function sleep(ms) { var deferred = new Deferred(); window.setTimeout(function() { deferred.callback(); }, ms); return deferred; } function foo() { for (var i = 0; i < 10; ++i) { console.log(i); await sleep(1000); } } foo(); これで1秒おきにconsole.logに出力されます。aw… <p><a href="http://www.publickey1.jp/blog/11/javascripttraceur.html">&#x3053;&#x306E;&#x8A18;&#x4E8B;</a>で知ったのですが、次世代<a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a>のawaitという機能が楽しそうです。</p> <pre class="code lang-javascript" data-lang="javascript" data-unlink><span class="synIdentifier">function</span> sleep(ms) <span class="synIdentifier">{</span> <span class="synIdentifier">var</span> deferred = <span class="synStatement">new</span> Deferred(); <span class="synStatement">window</span>.setTimeout(<span class="synIdentifier">function</span>() <span class="synIdentifier">{</span> deferred.callback(); <span class="synIdentifier">}</span>, ms); <span class="synStatement">return</span> deferred; <span class="synIdentifier">}</span> <span class="synIdentifier">function</span> foo() <span class="synIdentifier">{</span> <span class="synStatement">for</span> (<span class="synIdentifier">var</span> i = 0; i &lt; 10; ++i) <span class="synIdentifier">{</span> console.log(i); await sleep(1000); <span class="synIdentifier">}</span> <span class="synIdentifier">}</span> foo(); </pre><p>これで1秒おきにconsole.logに出力されます。awaitというキーワードで非同期関数を同期関数風に呼び出せます。</p><p>実は<a class="keyword" href="http://d.hatena.ne.jp/keyword/CoffeeScript">CoffeeScript</a>でも使える(つまり、<a class="keyword" href="http://d.hatena.ne.jp/keyword/CoffeeScript">CoffeeScript</a>を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>してさらにTraceurで<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>するすれば動く)ことを発見しました。</p> <pre class="code" data-lang="" data-unlink>sleep = (ms)-&gt; deferred = new Deferred() window.setTimeout((-&gt; deferred.callback()), ms) return deferred foo = -&gt; for i in [0...10] console.log(i) await sleep(1000) null foo()</pre><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/CoffeeScript">CoffeeScript</a>はawaitを関数だと思ってawait(sleep(1000))に変換しますが、余計な括弧があっても通るので、ちゃんと動きます。そのあとにnullが必要なのが微妙ですが<a href="#f-c902b9e4" name="fn-c902b9e4" title="nullを入れないと_results.push(await(sleep(1000) ) );が生成されてエラーに。">*1</a>。</p> <div class="footnote"> <p class="footnote"><a href="#fn-c902b9e4" name="f-c902b9e4" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text">nullを入れないと_results.push(await(sleep(1000) ) );が生成されてエラーに。</span></p> </div> Gimite [coffeescript][js] CoffeeScript雑感 hatenablog://entry/17680117126973992690 2011-04-25T10:45:14+09:00 2019-02-20T22:21:30+09:00 なんかCoffeeScriptというのが話題になっていたので試しにちょっとだけ使ってみました。パッと見の印象は「このRubyとPythonとJavaScriptのちゃんぽんみたいな独自文法は無駄に敷居を上げてるような気が…。JavaScriptに最低限の拡張を加えるなり、Mirahみたいにどれか既存の言語を極力真似るとかのほうがとっつきやすいのでは」という感じだったのですが、使ってみると割とすぐ慣れました。ちょっとしたコードを書いてみて便利だったのは functionが->。言われてみればJSはfunctionだらけなのに"function"は長すぎ。特に foo(function() { .… <p>なんか<a href="http://jashkenas.github.com/coffee-script/">CoffeeScript</a>というのが話題になっていたので試しにちょっとだけ使ってみました。</p><p>パッと見の印象は「この<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ruby">Ruby</a>と<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>と<a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a>のちゃんぽんみたいな独自文法は無駄に敷居を上げてるような気が…。<a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a>に最低限の拡張を加えるなり、<a href="http://www.mirah.org/">Mirah</a>みたいにどれか既存の言語を極力真似るとかのほうがとっつきやすいのでは」という感じだったのですが、使ってみると割とすぐ慣れました。</p><p>ちょっとしたコードを書いてみて便利だったのは</p> <ul> <li>functionが->。言われてみればJSはfunctionだらけなのに"function"は長すぎ。特に</li> </ul><pre class="code lang-javascript" data-lang="javascript" data-unlink>foo(<span class="synIdentifier">function</span>() <span class="synIdentifier">{</span> ... <span class="synIdentifier">}</span>); </pre><p>が<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ruby">Ruby</a>のブロック付きメソッドっぽく</p> <pre class="code" data-lang="" data-unlink>foo -&gt; ...</pre><p>と書けるのは便利。</p> <ul> <li>配列に対する<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ruby">Ruby</a>的なfor文。</li> </ul><p>今回は使わなかったですが便利そうなのは</p> <ul> <li>[f(x) for x if x] みたいなやつ。</li> <li>classと=>(thisが変わっちゃう問題をworkaroundしてくれるやつ)。</li> </ul><p>難点としては、誰かが書いてましたがruntime errorがあったときに生成後のJSでの行番号が出てくることですね…。比較的綺麗なJSが吐かれるので、逆にたどることは難しくないのですが。</p> Gimite jruby-jars-*.gem のビルド方法 hatenablog://entry/17680117126973992725 2011-04-17T16:11:49+09:00 2019-02-20T22:21:31+09:00 jruby-jars-*.gem をビルドする方法のメモ。 $ git clone git://jruby.org/jruby.git jruby $ cd jruby $ ant $ ./bin/jruby bin/gem install rake rspec $ ant gem $ ls dist jruby-complete-1.6.1.jar jruby-jars-1.6.1.gem jruby-complete-1.6.1.jar.md5 jruby-jars-1.6.1.gem.md5 jruby-complete-1.6.1.jar.sha1 jruby-jars-1.6.1.g… <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/jruby">jruby</a>-jars-*.gem をビルドする方法のメモ。</p> <pre class="code" data-lang="" data-unlink>$ git clone git://jruby.org/jruby.git jruby $ cd jruby $ ant $ ./bin/jruby bin/gem install rake rspec $ ant gem $ ls dist jruby-complete-1.6.1.jar jruby-jars-1.6.1.gem jruby-complete-1.6.1.jar.md5 jruby-jars-1.6.1.gem.md5 jruby-complete-1.6.1.jar.sha1 jruby-jars-1.6.1.gem.sha1</pre> Gimite [ruby] rubygemsのダウングレード hatenablog://entry/17680117126973992748 2011-04-09T14:53:52+09:00 2019-02-20T22:21:32+09:00 諸事情でrubygemsをダウングレードする必要があったのですが、 $ sudo gem install -v 1.3.7 rubygems-update $ sudo update_rubygemsでいけたっぽい。 <p>諸事情で<a class="keyword" href="http://d.hatena.ne.jp/keyword/rubygems">rubygems</a>をダウングレードする必要があったのですが、</p> <pre class="code" data-lang="" data-unlink>$ sudo gem install -v 1.3.7 rubygems-update $ sudo update_rubygems</pre><p>でいけたっぽい。</p> Gimite [priv] gimite.net, irc.gimite.net, tweet-search-stream.gimite.netは3/14に一時停止します hatenablog://entry/17680117126973992768 2011-03-13T22:57:37+09:00 2019-02-20T22:21:32+09:00 輪番停電のため、gimite.net, irc.gimite.net, tweet-search-stream.gimite.netは3/14 8:30〜22:30頃にサービスを停止します。実際の停電は9:20〜13:00、18:20〜22:00らしいのですが、途中で電源を入れられる人がいないので、ずっと止めます。停電の予定についてはまだ情報が混乱しているようなので、サービス停止の予定も変わるかもしれません。 <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%CE%D8%C8%D6%C4%E4%C5%C5">輪番停電</a>のため、gimite.net, <a class="keyword" href="http://d.hatena.ne.jp/keyword/irc">irc</a>.gimite.net, <a class="keyword" href="http://d.hatena.ne.jp/keyword/tweet">tweet</a>-search-stream.gimite.netは3/14 8:30〜22:30頃にサービスを停止します。</p><p>実際の停電は9:20〜13:00、18:20〜22:00らしいのですが、途中で電源を入れられる人がいないので、ずっと止めます。</p><p>停電の予定についてはまだ情報が混乱しているようなので、サービス停止の予定も変わるかもしれません。</p> Gimite [web][priv] iframe → Google Gadget コンバータの不具合 hatenablog://entry/17680117126973992787 2011-03-02T21:33:18+09:00 2019-02-20T22:21:33+09:00 201/4/18追記: 現在は(以前に変換されたものについても)直っています。Google Gadget側のバグが修正されたようです。iframe → Google Gadget コンバータで変換して貼りつけたガジェットが正しく表示されないという不具合が起きています。以前は http://gimite.net/ の内容、現在はエラーメッセージが表示されるようになっています。これはどうやらGoogle Gadget側のバグのようです。とりあえずの対策としては、iframe → Google Gadget コンバータでもう一度変換したものを貼りつけなおしてください。バグの対策が入っています。以前の… <p><span style="font-weight:bold;">201/4/18追記</span>: 現在は(以前に変換されたものについても)直っています。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Gadget側のバグが修正されたようです。</p><p><a href="http://gimite.net/rails/iframe_gadget">iframe &rarr; Google Gadget &#x30B3;&#x30F3;&#x30D0;&#x30FC;&#x30BF;</a>で変換して貼りつけたガジェットが正しく表示されないという不具合が起きています。以前は <a href="http://gimite.net/">http://gimite.net/</a> の内容、現在はエラーメッセージが表示されるようになっています。</p><p>これはどうやら<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Gadget側のバグのようです。とりあえずの対策としては、<a href="http://gimite.net/rails/iframe_gadget">iframe &rarr; Google Gadget &#x30B3;&#x30F3;&#x30D0;&#x30FC;&#x30BF;</a>でもう一度変換したものを貼りつけなおしてください。バグの対策が入っています。</p><p>以前のコンバータで変換されたものについては、残念ながら現状、こちらではエラーを表示する以上の修正ができません。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Gadgetのバグについては報告済みなので、そちらが修正されるのをお待ちください。</p><p>ちなみに<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Gadgetのバグというのは、ガジェットの<a class="keyword" href="http://d.hatena.ne.jp/keyword/XML">XML</a>のURLの"&"以降が落ちてしまうというものです。</p><p>ご迷惑をおかけします。報告をいただいた<a href="http://twitter.com/#!/risupunk">@risupunk</a>さん、ありがとうございました。</p> Gimite [tss][mobile] Tweet Search StreamのAndroid/iPhone対応 hatenablog://entry/17680117126973992840 2011-01-08T23:53:23+09:00 2019-02-20T22:21:34+09:00 Tweet Search Stream元々動作はしていたんですが、ちょっと見にくかったので、Android/iPhone向けに見た目をいじりました。実際に確認したのはAndroidだけですが…。Tweet Search Streamの動作には、AndroidならAndroid 2.2以上 & Flash Player、iPhoneならiOS 4以上が必要です。アニメーションが携帯ブラウザには重すぎる気がしますが、それは後で直す。予定。 <p><a href="http://tweet-search-stream.gimite.net/">Tweet Search Stream</a></p><p>元々動作はしていたんですが、ちょっと見にくかったので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>/<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>向けに見た目をいじりました。実際に確認したのは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>だけですが…。</p><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Tweet">Tweet</a> Search Streamの動作には、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>なら<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a> 2.2以上 & <a class="keyword" href="http://d.hatena.ne.jp/keyword/Flash">Flash</a> Player、<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>なら<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS%204">iOS 4</a>以上が必要です。</p><p>アニメーションが携帯ブラウザには重すぎる気がしますが、それは後で直す。予定。</p> Gimite [css] CSSのmax-widthを指定しつつ中央寄せする方法のメモ hatenablog://entry/17680117126973992812 2011-01-08T23:11:03+09:00 2019-02-20T22:21:33+09:00 .hoge { width: 80%; max-width: 800px; margin-left: auto; margin-right: auto; } で 幅をウィンドウの80%に ただしそれが800pxを越える場合は800pxに 余った余白は左右均等に(中央寄せ) max-widthはIE6だと使えないらしい。IE7以降と他の最近のブラウザなら大丈夫そうです。margin-left: auto, margin-right: 0pxで右寄せ。 <pre class="code lang-css" data-lang="css" data-unlink><span class="synIdentifier">.hoge</span> <span class="synIdentifier">{</span> <span class="synType">width</span>: <span class="synConstant">80%</span>; <span class="synType">max-width</span>: <span class="synConstant">800px</span>; <span class="synType">margin-left</span>: <span class="synConstant">auto</span>; <span class="synType">margin-right</span>: <span class="synConstant">auto</span>; <span class="synIdentifier">}</span> </pre><p>で</p> <ul> <li>幅をウィンドウの80%に</li> <li>ただしそれが800pxを越える場合は800pxに</li> <li>余った余白は左右均等に(中央寄せ)</li> </ul><p>max-widthはIE6だと使えないらしい。<a class="keyword" href="http://d.hatena.ne.jp/keyword/IE7">IE7</a>以降と他の最近のブラウザなら大丈夫そうです。</p><p>margin-left: auto, margin-right: 0pxで右寄せ。</p> Gimite Amazon EC2の無料ティアを試す hatenablog://entry/17680117126973992859 2010-11-06T11:21:08+09:00 2019-02-20T22:21:35+09:00 Amazon EC2が1年間無料というので、試してみました。とりあえずUnbuntuが立ち上がってSSHでログインできるようになりました。セットアップの仕方はしげふみメモ : 無料でAWS(Amazon EC2,S3等)を使ってみたとかに説明があります。なんか時々罠があって、うっかりしてるとすぐに課金されますね…。自分が不注意なだけのような気もしますが。今のところ Instance Typeにlargeを選んだら$0.75取られる。無料なのはmicroだけでした…。 インスタンスをStopしておけば課金されなくなるだろうと思って、Stopして会社に行って帰って来たら普通に課金され続けていて、追… <p><a href="http://aws.typepad.com/aws_japan/2010/11/%E3%82%A2%E3%83%9E%E3%82%BE%E3%83%B3%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%81%AE%E7%84%A1%E6%96%99%E3%83%86%E3%82%A3%E3%82%A2%E3%82%92%E7%99%BA%E8%A1%A8.html">Amazon EC2&#x304C;1&#x5E74;&#x9593;&#x7121;&#x6599;</a>というので、試してみました。とりあえずUnbuntuが立ち上がって<a class="keyword" href="http://d.hatena.ne.jp/keyword/SSH">SSH</a>でログインできるようになりました。</p><p>セットアップの仕方は<a href="http://blog.livedoor.jp/hakin/archives/51875780.html">&#x3057;&#x3052;&#x3075;&#x307F;&#x30E1;&#x30E2; : &#x7121;&#x6599;&#x3067;AWS&#xFF08;Amazon EC2,S3&#x7B49;&#xFF09;&#x3092;&#x4F7F;&#x3063;&#x3066;&#x307F;&#x305F;</a>とかに説明があります。</p><p>なんか時々罠があって、<span style="font-weight:bold;">うっかりしてるとすぐに課金されます</span>ね…。自分が不注意なだけのような気もしますが。今のところ</p> <ul> <li>Instance Typeにlargeを選んだら$0.75取られる。無料なのはmicroだけでした…。</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>をStopしておけば課金されなくなるだろうと思って、Stopして会社に行って帰って来たら普通に課金され続けていて、追加で$4.25ほど取られる。Terminateしないと駄目なようです。</li> <li>regional data transferという名目で$0.02取られる。これがなんで発生したのかはっきりしないのですが、どうもapt-getの時に発生している気がします。sources.listにデフォルトで<a href="http://us-east-1.ec2.archive.ubuntu.com/ubuntu/">http://us-east-1.ec2.archive.ubuntu.com/ubuntu/</a>と書いてあるので、これがEC2内の別のゾーンにあるということかもしれません。<a href="#f-10a506d8" name="fn-10a506d8" title="インターネットでの通信が(一定量まで)無料で、EC2内の通信が有料なのはちょっと妙な気がしますが、1GB $0.01とかなので気にしなくていいかも。">*1</a></li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Ubuntu">Ubuntu</a>を入れる場合は<a href="http://alestic.com/">alestic.com</a>に書いてあるイメージを使うのが普通っぽいのですが、ここでEBS boot<a href="#f-0426c464" name="fn-0426c464" title="ディスクとしてEBSを使うバージョン。instance-storeの方だとマシンを再起動するとディスクが初期化されてしまうが、EBSなら普通に保存される、らしい。">*2</a>を選ぶと15GBのEBSができます。しかし無料なのは10GBまでなので、このままだと課金されます。10GB*月を超えると課金なので、これはまだ課金されてないですが…。</li> </ul><p>という感じで合計$5ほど課金されました :)App Engineみたいに、自動では課金されない(無料quotaを超えたらサービスが止まる)オプションがほしいですね…。</p><p>適当に使い方をググッたときは、管理ツールとして<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%DE%A5%F3%A5%C9%A5%E9%A5%A4%A5%F3">コマンドライン</a>版とか<a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>アドオンを使う説明が多かったんですが、今は<a href="https://console.aws.amazon.com/ec2/home#s=Home">AWS Management Console</a>というWebインタフェースがあるので、これを使っています。</p><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Ubuntu">Ubuntu</a>については<a href="http://guru.gg/aether/ubuntu-10-4-amazon-aws-free-tier/">10GB EBS&#x7248;&#x306E;&#x30A4;&#x30E1;&#x30FC;&#x30B8;&#x3092;&#x4F5C;&#x3063;&#x3066;&#x304F;&#x308C;&#x305F;&#x4EBA;</a>がいるので、これを指定すれば課金されずに済みます。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>を作るときに、AMIを選ぶところでCommunity AMIsでami-c2a255abを検索して選べばOK。ただし、US Eastにしか置いてないので、RegionをUS Eastにする必要があります。<a href="http://ubuntu-smoser.blogspot.com/2010/11/using-ubunt-images-on-aws-free-tier.html">&#x3053;&#x306E;&#x3078;&#x3093;&#x306E;&#x8AAC;&#x660E;</a>に従ってAMIを自作すればいAsiaでもできそうなんですが、面倒そうなのでやめました。</p><p><span style="font-weight:bold;">2010/11/6追記</span>: regional data transferについて追記。</p> <div class="footnote"> <p class="footnote"><a href="#fn-10a506d8" name="f-10a506d8" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text">インターネットでの通信が(一<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C4%EA%CE%CC">定量</a>まで)無料で、EC2内の通信が有料なのはちょっと妙な気がしますが、1GB $0.01とかなので気にしなくていいかも。</span></p> <p class="footnote"><a href="#fn-0426c464" name="f-0426c464" class="footnote-number">*2</a><span class="footnote-delimiter">:</span><span class="footnote-text">ディスクとしてEBSを使うバージョン。instance-storeの方だとマシンを再起動するとディスクが初期化されてしまうが、EBSなら普通に保存される、らしい。</span></p> </div> Gimite Tweet Search Stream上でtweetできるようになりました hatenablog://entry/17680117126973992954 2010-10-17T23:46:05+09:00 2019-02-20T22:21:37+09:00 Tweet Search Stream上でtweetできるようになりました。[Tweet here]というところをクリックしてください。Twitterアカウントでのログインが必要です。導入後1分でこの機能を使っている人がいたのでびっくり :) <p><a href="http://tweet-search-stream.gimite.net">Tweet Search Stream</a>上で<a class="keyword" href="http://d.hatena.ne.jp/keyword/tweet">tweet</a>できるようになりました。[<a class="keyword" href="http://d.hatena.ne.jp/keyword/Tweet">Tweet</a> here]というところをクリックしてください。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>アカウントでのログインが必要です。</p><p>導入後1分でこの機能を使っている人がいたのでびっくり :)</p> Gimite [ruby][sinatra] Sinatraのハンドラ内でem-http-requestを使う hatenablog://entry/17680117126973992902 2010-10-17T15:50:16+09:00 2019-02-20T22:21:36+09:00 Sinatra+Thinで、どこかからHTTPで取得した結果を加工して出力したい、という場合、 require "open-uri" get("/") do open("http://example.com/"){ |f| f.read() } end でもいいのですが、これだとexample.comからの返答待ちの間、EventMachineが完全に止まってしまうのがいまいちです。そこでem-http-requestを使おうとしたのですが、それにはハンドラのレスポンスを非同期に返す必要があります。どうするんだろうと思ったのですが、async_sinatraというものがあるようです。 $ su… <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Sinatra">Sinatra</a>+Thinで、どこかからHTTPで取得した結果を加工して出力したい、という場合、</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">require</span> <span class="synSpecial">&quot;</span><span class="synConstant">open-uri</span><span class="synSpecial">&quot;</span> get(<span class="synSpecial">&quot;</span><span class="synConstant">/</span><span class="synSpecial">&quot;</span>) <span class="synStatement">do</span> open(<span class="synSpecial">&quot;</span><span class="synConstant">http://example.com/</span><span class="synSpecial">&quot;</span>){ |<span class="synIdentifier">f</span>| f.read() } <span class="synStatement">end</span> </pre><p>でもいいのですが、これだと<a class="keyword" href="http://d.hatena.ne.jp/keyword/example.com">example.com</a>からの返答待ちの間、EventMachineが完全に止まってしまうのがいまいちです。そこでem-http-requestを使おうとしたのですが、それにはハンドラのレスポンスを非同期に返す必要があります。どうするんだろうと思ったのですが、<a href="http://github.com/raggi/async_sinatra">async_sinatra</a>というものがあるようです。</p> <pre class="code" data-lang="" data-unlink>$ sudo gem install async_sinatra em-http-request</pre><pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">require</span> <span class="synSpecial">&quot;</span><span class="synConstant">sinatra/async</span><span class="synSpecial">&quot;</span> <span class="synPreProc">require</span> <span class="synSpecial">&quot;</span><span class="synConstant">em-http</span><span class="synSpecial">&quot;</span> register(<span class="synType">Sinatra</span>::<span class="synType">Async</span>) aget(<span class="synSpecial">&quot;</span><span class="synConstant">/</span><span class="synSpecial">&quot;</span>) <span class="synStatement">do</span> http = <span class="synType">EventMachine</span>::<span class="synType">HttpRequest</span>.new(<span class="synSpecial">&quot;</span><span class="synConstant">http://example.com/</span><span class="synSpecial">&quot;</span>).get() http.callback() <span class="synStatement">do</span> body(http.response) <span class="synStatement">end</span> http.errback() <span class="synStatement">do</span> status(<span class="synConstant">500</span>) body(<span class="synSpecial">&quot;</span><span class="synConstant">error</span><span class="synSpecial">&quot;</span>) <span class="synStatement">end</span> <span class="synStatement">end</span> </pre> Gimite [tss][ruby] Tweet Search Streamの実装をem-websocketとem-http-requestに hatenablog://entry/17680117126973992978 2010-10-11T11:36:52+09:00 2019-02-20T22:21:37+09:00 Tweet Search StreamでTwitter Streaming APIの結果をWebSocketに流す部分は、元々web-socket-rubyとnet/httpを使って1コネクション1スレッドという実装だったのですが、em-websocketとem-http-requestを使うように変更しました。Webサーバもthinなので、これで全てEventMachineの上に乗って、ほぼ1スレッドで全部動くようになりました。余計な排他処理が要らなくなったのはいいですね。パフォーマンスも良くなったことに期待ですが、測ってはいないです。まあ元々今ぐらいのアクセス数だと負荷は問題なかったんです… <p><a href="http://tweet-search-stream.gimite.net/">Tweet Search Stream</a>で<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a> Streaming <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>の結果をWebSocketに流す部分は、元々web-socket-<a class="keyword" href="http://d.hatena.ne.jp/keyword/ruby">ruby</a>とnet/httpを使って1コネクション1スレッドという実装だったのですが、<a href="http://github.com/igrigorik/em-websocket">em-websocket</a>と<a href="http://github.com/igrigorik/em-http-request">em-http-request</a>を使うように変更しました。Webサーバもthinなので、これで全てEventMachineの上に乗って、ほぼ1スレッドで全部動くようになりました。余計な排他処理が要らなくなったのはいいですね。パフォーマンスも良くなったことに期待ですが、測ってはいないです。まあ元々今ぐらいのアクセス数だと負荷は問題なかったんですが。</p><p>実装には<a href="http://japan.cnet.com/blog/kenn/2010/03/20/entry_27038355/">kenn&#x3055;&#x3093;&#x306E;&#x8A18;&#x4E8B;</a>が参考になりました。1点変更が必要だったのが</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink>http = <span class="synType">EM</span>::<span class="synType">HttpRequest</span>.new(<span class="synType">STREAMING_URL</span>).get <span class="synConstant">:head</span> =&gt; { <span class="synSpecial">'</span><span class="synConstant">Authorization</span><span class="synSpecial">'</span> =&gt; [ <span class="synSpecial">'</span><span class="synConstant">USERNAME</span><span class="synSpecial">'</span>, <span class="synSpecial">'</span><span class="synConstant">PASSWORD</span><span class="synSpecial">'</span> ] } </pre><p>という部分で、</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink>http = <span class="synType">EM</span>::<span class="synType">HttpRequest</span>.new(<span class="synType">STREAMING_URL</span>).get <span class="synConstant">:head</span> =&gt; { <span class="synSpecial">'</span><span class="synConstant">Authorization</span><span class="synSpecial">'</span> =&gt; [ <span class="synSpecial">'</span><span class="synConstant">USERNAME</span><span class="synSpecial">'</span>, <span class="synSpecial">'</span><span class="synConstant">PASSWORD</span><span class="synSpecial">'</span> ] }, <span class="synConstant">:timeout</span> =&gt; <span class="synConstant">0</span> </pre><p>としないと、ストリームが10秒以上止まるとそこで接続が切れてしまいます(:timeoutのデフォルトが10なので)。この記事が書かれた当時は要らなかったのかもしれませんが。</p><p>ちなみに<a href="http://github.com/voloko/twitter-stream">twitter-stream</a>というのも見つけたのですが、なぜかOAuthの認証に失敗します。OAuthを深追いするのが面倒だったので、使うのを諦めました。</p><p><a href="http://github.com/gimite/tweet-search-stream/blob/master/lib/tss_em_web_socket_server.rb">&#x30BD;&#x30FC;&#x30B9;&#x306F;&#x3053;&#x3061;&#x3089;</a>です。</p> Gimite [tss][twitter] Tweet Search StreamがTwitterからアクセス禁止された経緯と復活した経緯 hatenablog://entry/17680117126973993023 2010-10-10T11:46:13+09:00 2019-02-20T22:21:39+09:00 10/3-10/5ぐらいにかけてTweet Search Streamが落ちていたのですが、これはTwitterからアクセス禁止をくらってました :) その後Twitter Streaming APIの使い方を変えることで制限に引っかからないようにして復活しました。以下はその経緯です。まずアクセス禁止を食らった理由ですが、たぶんこれです。Access and Rate Limiting - Streaming API: Concepts Excessive connection attempts, regardless of success, will result in an automat… <p>10/3-10/5ぐらいにかけて<a href="http://tweet-search-stream.gimite.net/">Tweet Search Stream</a>が落ちていたのですが、これは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>からアクセス禁止をくらってました :) その後<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a> Streaming <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>の使い方を変えることで制限に引っかからないようにして復活しました。以下はその経緯です。</p><p>まずアクセス禁止を食らった理由ですが、たぶんこれです。</p><p><a href="http://dev.twitter.com/pages/streaming_api_concepts#access-rate-limiting">Access and Rate Limiting - Streaming API: Concepts</a></p> <blockquote> <p>Excessive connection attempts, regardless of success, will result in an automatic ban of the client's IP address.</p> </blockquote> <p>元の実装では<a class="keyword" href="http://d.hatena.ne.jp/keyword/Tweet">Tweet</a> Search Streamを開いているユーザの数だけStreaming <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>のコネクションを張っていました。最初の頃は平気だったのですが、徐々にユーザが増えて、同時接続数がしょっちゅう20以上、ピーク時は50〜80ぐらいになったところで<a class="keyword" href="http://d.hatena.ne.jp/keyword/IP%A5%A2%A5%C9%A5%EC%A5%B9">IPアドレス</a>単位のアクセス禁止を食らいました。</p><p>当初からこれには引っかかるかも、と思っていました。ただ、excessive connection attemptsというのが一体10なのか100なのか1000なのか分からなかったので、見切り発車していたのです。</p><p>で、これはもう<a class="keyword" href="http://d.hatena.ne.jp/keyword/Tweet">Tweet</a> Search Stream終了のお知らせかな、と思ったのですが、<a href="http://dev.twitter.com/pages/streaming_api_methods#statuses-filter">API&#x306E;&#x30C9;&#x30AD;&#x30E5;&#x30E1;&#x30F3;&#x30C8;</a>をよく見ると検索キーワードはORで400個まで同時に指定できると書いてあります。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Tweet">Tweet</a> Search Streamは同じキーワードにアクセスが集中する傾向にあるので、キーワードの数は接続者数よりかなり少なくなります。なのでStreaming <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>の接続を全体で1本にして、接続中の全ユーザのキーワードをOR(Streaming <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>では",")でつないで投げれば、今ぐらいのアクセス数なら余裕なのでは、ということに気づきました。で、そのように実装しなおして10/5に投入しました。</p><p>が、実はその後1度問題が起きました。10/8にちょっとしたバグ修正のために<a class="keyword" href="http://d.hatena.ne.jp/keyword/Tweet">Tweet</a> Search Streamのサーバを再起動したのですが…。再起動によってWebSocketの接続が切れると、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Tweet">Tweet</a> Search Streamのページには"Disconnected. Retry"とか表示されるので、当然みなさんすぐにそれをクリックします。そうすると再起動直後にアクセスが集中することになります。新しい実装ではキーワードが増えるたびにStreaming <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>のコネクションを切断→新しいキーワードを追加して接続しなおし、ということをやります。なので再起動直後は短期間でこの切断→接続が繰り返されることになり、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>側から「おちつけ」というエラーをもらって繋がらなくなってしまいました。そこで短期間で切断→接続を繰り返そうとしたときは、ちょっと待つ、という仕組みを入れて回避しました。</p><p>もうちょっと様子を見ないと分からないですが、これで今のところは安定しているようです。</p><p>ちなみに新方式ではさりげなく<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>アカウントでのログインが不要になっています。これはコネクションが1本しかないので、僕のアカウントで認証すれば済むからです。<a href="#f-fdeb38e8" name="fn-fdeb38e8" title="Streaming APIのコネクションは1ユーザ1本しか張れないので、旧方式では各ユーザに認証してもらう必要がありました。">*1</a></p><p>新しい実装は<a href="http://github.com/gimite/tweet-search-stream">Guthub</a>に上がってるので、興味のある人はどうぞ。<a href="http://github.com/gimite/tweet-search-stream">Guthub</a>のバージョンはさらにem-http-requestとem-websocketを使って完全にEM化されています。これについては後述。</p> <div class="footnote"> <p class="footnote"><a href="#fn-fdeb38e8" name="f-fdeb38e8" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text">Streaming <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>のコネクションは1ユーザ1本しか張れないので、旧方式では各ユーザに認証してもらう必要がありました。</span></p> </div> Gimite Devas, G Launchなど開発終了のお知らせ hatenablog://entry/17680117126973993055 2010-09-26T16:37:06+09:00 2019-02-20T22:21:39+09:00 namespace gimiteやVectorなどで公開している、以下のソフトの開発を終了します。 Devas G Launch 助さん G Check 大貧民 Guppy Pound X 今後のバージョンアップはおそらくないですが、どれも(記憶によれば)致命的なバグは見つかっていないと思うので、今のバージョンを使い続ける&ダウンロードして使う分には問題ありません。ものによってはWindows Vista/7でうまく動かないかもしれませんが…。DevasはWindows 7でも動作します*1。今後も「エラーが出る」とか「こういう事をする方法がわからない」とかは掲示板などで訊いて下さい。今のバー… <p><a href="http://gimite.net/">namespace gimite</a>や<a class="keyword" href="http://d.hatena.ne.jp/keyword/Vector">Vector</a>などで公開している、以下のソフトの開発を終了します。</p> <ul> <li>Devas</li> <li>G Launch</li> <li>助さん</li> <li>G Check</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C2%E7%C9%CF%CC%B1">大貧民</a></li> <li>Guppy</li> <li>Pound X</li> </ul><p>今後のバージョンアップはおそらくないですが、どれも(記憶によれば)致命的なバグは見つかっていないと思うので、今のバージョンを使い続ける&ダウンロードして使う分には問題ありません。ものによっては<a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows%20Vista">Windows Vista</a>/7でうまく動かないかもしれませんが…。Devasは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows%207">Windows 7</a>でも動作します<a href="#f-f64731fe" name="fn-f64731fe" title="動かないという報告もあったのですが、少なくとも自分の環境では動いています。">*1</a>。</p><p>今後も「エラーが出る」とか「こういう事をする方法がわからない」とかは<a href="http://gimite.net/bbs/tnote.cgi?book=gbbs">&#x63B2;&#x793A;&#x677F;</a>などで訊いて下さい。今のバージョンの使い方次第でどうにかなる場合は、教えます。ただ、「こうして欲しい」という要望には、残念ながら応えられません。</p><p>どれも数年以上放置されているもので、非常に今更なのですが…。特にDevasは最近でも<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B7%C7%BC%A8">掲示</a>板で時々要望をくれる人がいて、「あーそれは確かにそうですねぇ。今後バージョンアップすることがあれば入れるかも」みたいな曖昧なことを毎回書いて結局放置してるのも申し訳なかったので、きちんと宣言しておこうと思った次第です。</p><p>Devasについては最後にVer.3.5βをそのままVer.3.5としておきました。経験上少なくとも3.4と同程度には安定していたので。インストールすると3.5βと表示されるのがあれですが…。<a href="#f-09084621" name="fn-09084621" title="そこを直すだけでも開発環境のセットアップから始めないといけないのでかなり面倒なのです…。">*2</a></p><p>あと<a href="http://gimite.net/pukiwiki/index.php?Devas">Devas&#x306E;&#x30DA;&#x30FC;&#x30B8;</a>では微妙にバージョンが古いのですが<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>も公開されています。BCB(有料)が必要(しかも最新のBCBで動くのかは不明)だしとてもソースが汚いのでかなり敷居が高いですが、どうしてもいじりたいという人はどうぞ。</p> <div class="footnote"> <p class="footnote"><a href="#fn-f64731fe" name="f-f64731fe" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text">動かないという報告もあったのですが、少なくとも自分の環境では動いています。</span></p> <p class="footnote"><a href="#fn-09084621" name="f-09084621" class="footnote-number">*2</a><span class="footnote-delimiter">:</span><span class="footnote-text">そこを直すだけでも開発環境のセットアップから始めないといけないのでかなり面倒なのです…。</span></p> </div> Gimite [tss][twitter] Tweet Search Streamのソースを公開 hatenablog://entry/17680117126973993077 2010-09-13T23:37:24+09:00 2019-02-20T22:21:40+09:00 Twitterをリアルタイム検索するTweet Search Streamのソースを公開しました。tweet-search-stream - GitHubサーバ側がSinatra + Thin + web-socket-ruby + Ruby Twitter Gem、クライアント側がweb-socket-js + jQuery、という感じです。Ruby Twitter GemはStreaming APIには対応してないっぽかったので、OAuthで認証する部分だけ借りて、残りは自作しました。Tweet Search Streamの紹介記事はこちら。 <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>をリアルタイム検索する<a href="http://tweet-search-stream.gimite.net/">Tweet Search Stream</a>のソースを公開しました。</p><p><a href="http://github.com/gimite/tweet-search-stream">tweet-search-stream - GitHub</a></p><p>サーバ側が<a class="keyword" href="http://d.hatena.ne.jp/keyword/Sinatra">Sinatra</a> + Thin + <a href="http://github.com/gimite/web-socket-ruby">web-socket-ruby</a> + <a href="http://twitter.rubyforge.org/">Ruby Twitter Gem</a>、クライアント側が<a href="http://github.com/gimite/web-socket-js">web-socket-js</a> + <a class="keyword" href="http://d.hatena.ne.jp/keyword/jQuery">jQuery</a>、という感じです。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ruby">Ruby</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a> GemはStreaming <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>には対応してないっぽかったので、OAuthで認証する部分だけ借りて、残りは自作しました。</p><p><a href="http://d.hatena.ne.jp/Gimite/20100909/1284038001">Tweet Search Stream&#x306E;&#x7D39;&#x4ECB;&#x8A18;&#x4E8B;&#x306F;&#x3053;&#x3061;&#x3089;</a>。</p> Gimite [tss][twitter] 秒単位で更新されるTwitterリアルタイム検索 hatenablog://entry/17680117126973993094 2010-09-09T22:13:21+09:00 2019-02-20T22:21:41+09:00 Twitter Streaming APIとWebSocketを使って、Twitterのリアルタイム検索を作ってみました。Twitter Search Stream英語、日本語のHot hash tags(あれば)を適当にクリックしてみてください。英語の盛り上がってるハッシュタグとかだと大変なことになります。読めません。クリックもほぼ無理です。Retweetされた発言は上がります。 日本語での検索結果は自動更新されません。ハッシュタグは大丈夫です。これはTwitter Streaming APIが日本語に未対応だからです。 安定して動くのかはよく分かりません。*1落ちたらごめんなさい。 自作の… <p><a href="http://dev.twitter.com/pages/streaming_api">Twitter Streaming API</a>とWebSocketを使って、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>のリアルタイム検索を作ってみました。</p><p><a href="http://tweet-search-stream.gimite.net/">Twitter Search Stream</a></p><p>英語、日本語のHot hash tags(あれば)を適当にクリックしてみてください。英語の盛り上がってる<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CF%A5%C3%A5%B7%A5%E5%A5%BF%A5%B0">ハッシュタグ</a>とかだと大変なことになります。読めません。クリックもほぼ無理です。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Retweet">Retweet</a>された発言は上がります。</p> <ul> <li>日本語での検索結果は自動更新されません。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CF%A5%C3%A5%B7%A5%E5%A5%BF%A5%B0">ハッシュタグ</a>は大丈夫です。これは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a> Streaming <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>が日本語に未対応だからです。</li> <li>安定して動くのかはよく分かりません。<a href="#f-ce3182c9" name="fn-ce3182c9" title="Twitter Streaming APIのコネクションをどれぐらい同時に張っても怒られないのかが分からないのと、あまりスケールするような実装ではないというあたりが懸念材料です。まあその辺の実験も兼ねているので、遠慮無く使ってみてください。">*1</a>落ちたらごめんなさい。</li> <li>自作の<a href="http://github.com/gimite/web-socket-js">web-socket-js</a>を使っているので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/IE">IE</a>や<a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a>などWebSocket未実装のブラウザでも動きます。ただ、これらのブラウザでは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Flash">Flash</a> Playerが必要です。</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a> 7(開発版), <a class="keyword" href="http://d.hatena.ne.jp/keyword/Firefox">Firefox</a> 3.6, <a class="keyword" href="http://d.hatena.ne.jp/keyword/IE">IE</a> 8で動作確認しました。それ以外のブラウザでは動かないかもしれません。</li> <li>Hot wordsの部分は<a href="http://buzztter.com/">buzztter</a>のフィードからお借りしています。</li> </ul><p>この組み合わせの実装はいくつか見かけたのですが、手軽に試せるサービスとして上がっているものが一見見当たらなかったのと、楽しそうだったので自作してみました。Streaming <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>速いですね。投稿後ほぼ即座(1秒以内)に反映されるみたいです。</p><p><span style="font-weight:bold;">2010/9/13追記</span>: <a href="http://github.com/gimite/tweet-search-stream">&#x30BD;&#x30FC;&#x30B9;</a>公開しました。<br /> <span style="font-weight:bold;">2010/10/10追記</span>: <a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>アカウントでのログインが不要になりました。</p> <div class="footnote"> <p class="footnote"><a href="#fn-ce3182c9" name="f-ce3182c9" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a> Streaming <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>のコネクションをどれぐらい同時に張っても怒られないのかが分からないのと、あまりスケールするような実装ではないというあたりが懸念材料です。まあその辺の実験も兼ねているので、遠慮無く使ってみてください。</span></p> </div> Gimite