エンジニアのソフトウェア的愛情

または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか

Retriable gem の使い方のめも

インストー

$ gem install retriable

実装例

require 'retriable'

class SampleError < RuntimeError
end

puts <<~EOS
  | exception       | try | elapsed_time | time         |
  |-----------------|-----|--------------|--------------|
EOS

Retriable.configure do |c|
  c.tries = 5
  c.base_interval = 1
  c.rand_factor = 0
  c.on = SampleError
  c.on_retry = -> (exception, try, elapsed_time, next_interval) {
    puts format('| %-15s | %3d | %12f | %-12s |', exception, try, elapsed_time, Time.now.strftime('%H:%M:%S.%L'))
  }
end

begin
  Retriable.retriable do |try|
    raise SampleError if try < 5
  end
  puts format('| %-15s | --- | ------------ | %-12s |', 'done', Time.now.strftime('%H:%M:%S.%L'))
rescue SampleError => e
  puts format('| %-15s | --- | ------------ | %-12s |', e, Time.now.strftime('%H:%M:%S.%L'))
end


実行。

$ ruby samle.rb
| exception       | try | elapsed_time | time         |
|-----------------|-----|--------------|--------------|
| SampleError     |   1 |     0.000040 | 13:29:53.806 |
| SampleError     |   2 |     1.005182 | 13:29:54.811 |
| SampleError     |   3 |     2.508871 | 13:29:56.315 |
| SampleError     |   4 |     4.764138 | 13:29:58.570 |
| done            | --- | ------------ | 13:30:01.948 |


リトライ回数を 3 回にしてみます。

# 略

Retriable.configure do |c|
  c.tries = 3
  # 略
end

# 略


実行。

$ ruby sample.rb 
| exception       | try | elapsed_time | time         |
|-----------------|-----|--------------|--------------|
| SampleError     |   1 |     0.000041 | 13:35:22.001 |
| SampleError     |   2 |     1.000827 | 13:35:23.002 |
| SampleError     |   3 |     2.501092 | 13:35:24.502 |
| SampleError     | --- | ------------ | 13:35:24.502 |

抵抗器のカラーコードは虹の色

会社で「抵抗器のカラーコードは虹の順番だよ」という話をしたら。
「いや、そもそも虹の色の順番覚えてないから」と返されてしまいました。


そんなわけなので、Ruby の gem にしてみました。
gem は書き慣れていないので、雑です。

虹の色

「せき とう おう りょく せい らん し」と覚えます。「赤 橙 黄 緑 青 藍 紫」。
ただしカラーコードには「藍」は使われず「赤 橙 黄 緑 青 紫」の 6 つを使います。
前に「黒 茶」、後ろに「灰 白」を加えた「黒 茶 赤 橙 黄 緑 青 紫 灰 白」を 0 から 9 に割り当てます。

gem にしてみた

まず。Gemfile を書きます。

source "https://rubygems.org"

gem 'color_code', github: 'mattsan/color_code'


インストールします。

$ bundle install


irb で動作確認。

color_code_sample $ bundle exec irb
irb(main):001:0> require 'color_code'
=> true
irb(main):002:0> resister = '青緑赤金'.to_resister
=> 65 * 10**2 ± 5.0%
irb(main):003:0> resister.to_f
=> 6500.0
irb(main):004:0> resister.significant_digits
=> 65
irb(main):005:0> resister.multiplier
=> 2
irb(main):006:0> resister.tolerance
=> 0.05
irb(main):007:0> resister.lower_bound
=> 6175.0
irb(main):008:0> resister.upper_bound
=> 6825.0


誤差の範囲の上限下限も計算します。

いつか読むはずっと読まない:半世紀前の作品

原著 “ Way Station” が著されたのが 1963 年。サイエンス・フィクションというカテゴリにあると、科学や技術の発展に伴って陳腐化するのではないか、古くさくなるのではないか、という感覚を抱いてしまいますが。物語の面白さはそんなこととは無縁でした。


どう書くのたのしみ

横浜へなちょこプログラミング勉強会 オフラインリアルタイムどう書く が神田に移ってきてやがて半年になります。
場所が住んでいるところから近くに移ったということもあって、ようやくオフラインで参加できるようになりました。

ふりかえってみるとオンラインながら どう書く のコードを書き始めたのが4年前。

気がつくと長いおつきあいになっていました。

ようやくオフラインで参加できるようになって、感じたことを少し。

当日

頭が真っ白になる、あの感じ

制限時間内にコードを書き上げなければならないのに、問題を見た瞬間に一行も書けないんじゃないか、という気がするあの感じ。
学生の頃はよく経験したこの感覚ですが(ォィ)、それが懐かしくもあり新鮮でもあり。

その状態から解法を閃いて書ける! と感じた時のあの安堵感もなんとも言えません。

脇目も振らずコードを書く、あの感じ

仕事で書くコードは、慎重に書くようにしています。何かと早とちりする性格なので、小さく手を進めるようにしています。
そいうのをかなぐり捨てて、閃いた解法をコードに変換する行為に没頭する、あの感じ。
入力データがどのように流れて出力データになるのか見えていて、途中の動作確認もそこそこにコードを書く。コードの最終形態に頭から突っ込む。

…そしてだいたいはテストが通らず焦りながらデバッグする後半になるのですが、それはまた別のお話。

他の参加者のアイディアを知る、書き方を知る

当日参加された方の多くは、書いたコードをネット上に公開してくださっていますが、そこに至った経緯の解説はどうしても少なくなります。また解けたアイディアの解説はあっても、失敗したアイディアや、つまずいたところは、あまり表に出てきません。
当日は、その人が、その場所で、その問題を考えた、生のアイディアを伺う機会がえられます。勘違いだったり、遠回りだったり、明後日の方向を向いていたりすることもありますが、それを思いついた背景を聴ける機会はとても貴重。
加えてコーディングの技法もいろいろと知ることができます。

飲む

コードを書いて、互いにコードを読んで、そのあとは懇親会です。


…。

そんなことも、あります。

後日

深く深く考える

気になる問題に遭遇すると、何日も考える癖があります。二日も三日も考え続けると、ふと新しいアイディアが降りてくる瞬間があります。
そんなアイディアが降りてきたときは、言葉で定義し文章に書き出すことをしています。そうすると一段高いところから問題が見えるようになった気がします。


こうすることでコードを書くときの視野が高く遠く広くなってゆく感じがしています。

いつか読むはずっと読まない:ハッカーのたのしみ

すでに何回も紹介していますが。良書です。現在入手は困難なようですが、見つけたらぜひ手にとって読んでみてください。


ハッカーのたのしみ―本物のプログラマはいかにして問題を解くか

ハッカーのたのしみ―本物のプログラマはいかにして問題を解くか

  • 作者: ジュニア,ヘンリー・S.ウォーレン,Jr.,Henry S. Warren,滝沢徹,玉井浩,鈴木貢,赤池英夫,葛毅,藤波順久
  • 出版社/メーカー: エスアイビーアクセス
  • 発売日: 2004/09
  • メディア: 単行本
  • 購入: 35人 クリック: 732回
  • この商品を含むブログ (128件) を見る

Ruby/RSVG と Cairo を使って SVG から PDF を生成しためも

前回C++ で書いたのですが、調べたら Ruby でも同じように書くことができることがわかりました。

今回は libRSVG を Ruby から利用する Ruby/RSVG (rsvg2 gem) を利用。

require 'rsvg2'

source = <<~EOS
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg
   xmlns='http://www.w3.org/2000/svg'
   version='1.1'
   width='210mm'
   height='297mm'
>
  <rect x='100' y='100' width='100' height='100' fill='red' />
  <text
    font-family='sans-serif'
    font-size='18'
    x='200'
    y='200'>エンジニアのソフトウェア的愛情</text>
  <text
    font-size='12'
    x='200'
    y='220'>または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか</text>
</svg>
EOS

svg = RSVG::Handle.new_from_data(source)

dim = svg.dimensions

puts "document size = #{dim.width}x#{dim.height}"

surface = Cairo::PDFSurface.new('sample.pdf', dim.width, dim.height)

cairo = Cairo::Context.new(surface)

cairo.render_rsvg_handle(svg)


結果は前回と同じです。

Cairo::PDFSurface.new の第一引数に文字列を渡すと出力先のファイルのファイル名と解釈します。第一引数に write メソッドを持つオブジェクトを渡すと、そのメソッドを使って結果を書き出します。

詳しくはこちら: http://cairo.rubyforge.org/doc/ja/cairo-pdf-surface.html



SVG をベタに書くのがになったので、 Haml で描き直してみました。
ついでに Cairo::PDFSurface.new の第一引数に Fileインスタンスwrite メソッドを持つオブジェクト)を渡しています。
HamlSVG を書く話は 以前の記事 なんかもご参照ください。

require 'haml'
require 'rsvg2'

source = Haml::Engine.new(<<EOS).to_html
!!! XML
%svg{xmlns: 'http://www.w3.org/2000/svg', version: '1.1', width: '210mm', height: '297mm'}
  %rect{x: 100, y: 100, width: 100, height: 100, fill: 'red'}
  %text{font: {family: 'sans-serif', size: 18}, x: 200, y: 200} エンジニアのソフトウェア的愛情
  %text{font: {size: 12}, x: 200, y: 220} または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか
EOS

svg = RSVG::Handle.new_from_data(source)

dim = svg.dimensions

puts "document size = #{dim.width}x#{dim.height}"

surface = Cairo::PDFSurface.new(File.new('sample.pdf', 'w'), dim.width, dim.height)

cairo = Cairo::Context.new(surface)

cairo.render_rsvg_handle(svg)

いつか読むはずっと読まない:バチガルピ短篇

イーガンをまとめて読んでいた時期があったせいか、第一篇を読んでてイーガンを読んでいるような錯覚をしてしまいました。設定が。
作風が似ているかどうか判断できるほど、わたしの SF 脳は肥えていない。

第六ポンプ (ハヤカワ文庫SF)

第六ポンプ (ハヤカワ文庫SF)

libRSVG と Cairo を使って SVG から PDF を生成しためも

それぞれのサイト。


今回参照したドキュメント。

#if 0
# このファイルを Ruby で実行すると、このファイルを C++ のソースとしてコンパイルします。
# $ ruby minimum-svg2pdf.cpp
system('g++ --std=c++11 `pkg-config --cflags --libs cairo librsvg-2.0` -o minimum-svg2pdf minimum-svg2pdf.cpp')
__END__
#endif

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>

#include <librsvg/rsvg.h>

#include <cairo/cairo.h>
#include <cairo/cairo-pdf.h>

static const std::string source =
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"
"<svg"
"   xmlns=\"http://www.w3.org/2000/svg\""
"   version=\"1.1\""
"   width=\"210mm\""
"   height=\"297mm\""
">"
"  <rect x=\"100\" y=\"100\" width=\"100\" height=\"100\" fill=\"red\" />"
"  <text"
"    font-family=\"sans-serif\""
"    font-size=\"18\""
"    x=\"200\""
"    y=\"200\">エンジニアのソフトウェア的愛情</text>"
"  <text"
"    font-size=\"12\""
"    x=\"200\""
"    y=\"220\">または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか</text>"
"</svg>";

int main(int argc, char* argv[])
{
    GError* error = 0; 
    RsvgHandle* svg = rsvg_handle_new_from_data(reinterpret_cast<const guint8*>(source.c_str()), source.length() , &error);

    if(error != 0)
    {
        std::cout << error->message << std::endl;
        return 0;
    }

    if(svg == 0)
    {
        std::cout << "no handle" << std::endl;
        return 0;
    }

    RsvgDimensionData dim;
    rsvg_handle_get_dimensions(svg, &dim);

    std::cout << "document size = " << dim.width << "x" << dim.height << std::endl;

    cairo_surface_t* surface = cairo_pdf_surface_create("sample.pdf", dim.width, dim.height);
    cairo_t* cairo = cairo_create(surface);
    cairo_set_source_rgb(cairo, 1.0, 1.0, 1.0);
    rsvg_handle_render_cairo(svg, cairo);
    cairo_surface_flush(surface);

    cairo_destroy(cairo);
    cairo_surface_destroy(surface);

    rsvg_handle_close(svg, &error);

    if(error != 0)
    {
        std::cout << error->message << std::endl;
    }

    g_object_unref(svg);

    return 0;
}


コンパイルと実行*1

$ ruby minimum-svg2pdf.cpp
$ ./minimum-svg2pdf 
document size = 744x1052


こんなイメージの PDF ファイルが作成されます。

いつか読むはずっと読まない:今ここにある世界のSF

フィクションであり、フィクションでない。


遠隔機動歩兵 -ティン・メン- (ハヤカワ文庫SF)

遠隔機動歩兵 -ティン・メン- (ハヤカワ文庫SF)

*1:C/C++ のソースに Rubyスクリプトを埋め込んで自分に自分をコンパイルさせるやり方は横へなの鍋谷さんから教わりました。

SVG から PDF

PDF を生成する prawn と、PrawnSVG を解釈する prawn-svg を使って、haml で書いた SVG を PDF にした時のメモ。

prawn-svg の利用例として書かれているコードhaml で書き直したものです。

require 'prawn-svg'
require 'haml'

Prawn::Document.generate("test.pdf") do
  svg Haml::Engine.new(<<~EOS).to_html
    %svg
      %rect{width: 100, height: 100, fill: 'red'}
  EOS
end