RSS

日々のメモ書き

Debian Developerが綴るメモ

ReportLabのPDFの明朝がゴシックで表示される

evinceで日本語の入ったPDFを表示させると明朝がゴシックになるという話があって、それはfont-mangerの設定ファイルを編集しろという話はすぐにみつかって、まあ、dvipdfmxで作ったPDFはそれで表示される。バグ登録もされているようだがなかなか直ってないのはなんでだろうとか思うがまあいい。

がReportaLabで作った場合はCIDフォント(HeiseiMin-W3)を指定しているせいなのかその設定がわからない。Acrobat Readerではきちんと明朝体で表示されるので指定が間違っているわけではない。ごちゃごちゃlocal.confを設定してみたがよくわからない。どうでもいいところで進まねえよ。

Shift JISのHTMLを読む前に

引き続きHXTでスクレイピングの話。対象ファイルがShift JISなのでText Nodeの検索などを考えると素直にはいかない。結局IConvを使って変換することに。以下のようなコードになる。

import Codec.Binary.UTF8.String
import Codec.Text.IConv
import Data.List
import Text.XML.HXT.Core
import qualified Data.ByteString.Lazy as BSL

main = do
  cs <- BSL.readFile "shiftjis.html"
  let u8s  = convert "CP932" "UTF-8" cs
  let html = decode (BSL.unpack  u8s)
  let doc  = readString [withParseHTML yes, withWarnings no] html
  nodes <- runX $ doc //> hasText (isInfixOf  "日")
  mapM_ (putStrLn . show) nodes

GHCのString(=[Char])は内部エンコーディングにUCS-4が使われていらしいがソースコードがutf-8なら認識はしてくれる。

IConvはByteStringを直接扱っているがそのバイト列のエンコーディングをプログラマが意識しなければならない。この点はHaskellの型を使わない実装というのはあまり良くないと思う。UTF-8の入ったByteStringとEUC-JPの入ったByteStringを混ぜることができるなんて恐しい…。

urlopenのバグを追い掛けて

Pythonのurllib.urlopenが一部の HTTPS 接続がタイムアウトする問題を調べていたが、予想していた通りOpenSSLの問題。

openssl s_client -connect sslsite.example.com:443

とエラーが出るサイトがやるとやはり繋がらない。gnutls-cliだと問題なく繋がるからサーバ側の問題ではない。

ごちゃごちゃ探してみたが NetBSD でも同じバグレポートが。TLS1.2をs_clientで無効にするという話が出ている。というかUbuntuでも報告されてパッチ当たってるじゃねえか。Debian側のメンテナがどういう方針かしらんがしばらくすれば直ることは直るんだろう。たしかにopenssl s_client でも -tls1 とか -ssl3 とか付ければ大丈夫な感じだ。でもOpenSSLが直るまでまで自分の開発が止まっちゃうよ。

追記: 当たり前だがRubyのopen-uriでも再現するな。

製品レビュー: サワートレッカー

モンベルの沢靴のサワートレッカーの感想である。買ったのは2011年で去年は使用する機会がなかった。多分あまり2012年もモデルチェンジはしてないと思うのだが一応注意。

今年数回の沢で使ってみた。一応大きな破綻もなく使えている。縫製がいきなりほつれるということもない。ただ靴の幅がひろいのでつま先が下がる場面で親指がつっこんで痛いことがある。これは足型が合わないのでどうしようもない。靴紐をかなりしめても足型の問題でどうにもならない。もっと細い靴をどこか出してくれないかな。

この靴の特徴としてベロの部分が完全に縫い付けられていることが上げられる。足首のホールドまで完全に一体化しているので沢の中を歩いていても靴の中に小石が入ることはほぼ無い。が、着脱がかなり力入れてやらないとできない。そんなことするのは朝晩だけなのであきらめろという話だ。それでも構造的に仕方がないのはわかるけどなんとかならないかと思う。

使用しての1年目としては特に不満もなく使えているというところ。

WordPressをテスト

世間並にWordPressを少しテスト。

Apacheの設定ファイルを設定して、mysqlのデータベースを作成。WordPressの設定ファイルを入れて動かしてみる。まあ動くのはすぐに動く。

問題はプラグインを入れようとしたとき。/var/lib/wordpress/wp-content/plugins に入れているはずなのに表示されない。おかしいなと /usr/share/wordpress/wp-content/plugins に入れたら表示される。WP_CONTENT_DIR の設定が /var/lib/wordpress に向いていない。/usr/share/wordpress/wp-config.php にはきちんと設定されているようなんだが…。また考えよう。

GtkStatusIcon に文字を表示させる

Pythonでやったがどの言語でも似たような話。

GtkStatusIcon に画像は表示できるが直接文字を表示させられない。GtkWidget なら Cairo を使って文字を表示させるが GtkStatusIcon は GtkWidget のサブクラスではない。

ということで貼り付ける画像に文字を書き込んで画像を更新するということになる。ただ GtkStatusIconは Cairo で描いたものを渡すことはできない。受け取るのは Pixbuf。流れとしては背景となるPNGファイルから ImageSurface を作り CairoContext を使って文字を書き込む。そのあと ImageSurface を Pixbuf に変換して GtkStatusIcon に渡す。次のようなコードとなる。

        image = cairo.ImageSurface.create_from_png(ICON_PATH)
        width = pngimage.get_width()
        height = pngimage.get_height()
        cr = cairo.Context(image)
        cr.set_font_size(128)
        cr.move_to(0,128 )
        cr.show_text("1234")
        cr.move_to(0,256 )
        cr.show_text("ABC")
        pixbuf = Gdk.pixbuf_get_from_surface(pngimage,0,0,width,height)

        statusicon.set_from_pixbuf(pixbuf)

GtkStatusIcon は直接PNGファイルを渡すことができるので Cairo.ImageSurface.write_to_png ファイルに書き出してできないこともないがそんなことはやりたくなかった。StringIO を使ってできないかと思ったが Gtk.StatusIcon.set_from_file はファイルハンドラは受け取らずパスのみだったのでできず。

queryのparse

Haskellで低レベルなGETによるクエリのパースの処理について。

Network.HTTP.Types にある parseQuery か parseSimpleQuery を使う。この二つの違いは、例えば "?a=b&c"とあったときに parseQueryだと [("a", Just "b"),("c", Nothing)] となるが parseSimpleQuery だと [("a", "b"), ("c","")] となる。ちなちみに両方ともStringではなくてByteStringを受け取るのでpackするなり注意。

必要なパラメータだけ取り出す場合は Data.Map.fromList を使って Map に変換して扱うのががわかりやすいが(追記: Data.List.lookupを使うのもいいが)、同じパラメータ名が二つ以上あったときにどうするかというのがあるなあ…。

HXTでスクレイピング

ほんとはHaskellでスクレイピングを書きたかったので頑張ってみる。TagSoupは使い方がまだよく理解してないのでHXTで。HXTはStringしか受け付けないのが面倒だな。Data.ByteString.Char でファイルを読み込んでからunpackするのが必要だ。

同じくリンク先にfooが含まれるものの一覧を作成する。

import Text.XML.HXT.Core
import Data.List
import qualified Data.ByteString.Char8 as BSC

main = do
  html <- BSC.readFile "index.html"
  let doc = readString [withParseHTML yes, withWarnings no] (BSC.unpack html)
  links <- runX $ doc //> hasName "a"  >>>  
           hasAttrValue "href" (isInfixOf "foo") >>> 
           getAttrValue "href"
mapM_ putStrLn links 

BeautifulSoupでスクレイピング

少しだけテスト。

from bs4 import BeautifulSoup
import re
import urlparse

soup = BeautifulSoup(file('index.html'))

tags_a = soup.findAll('a', href=re.compile('.*foo.*'))

for i in tags_a:
    print i.get('href')
    print i.get_text().encode('utf-8')

これでURLにfooが含まれるリンク先の取得して一覧にして表示。

ワールドカップ予選突破まで勝ち点はあと何点?

ちょっと怪しいながらもイラクに勝ってほっと安心。前のイラクの試合を見たときはジーコらしいぐだぐだな試合をしていたので楽勝かと思ったらちゃんとしたサッカーになっていたので何が起こったんでしょうか?日本はボランチとCBの補強が課題。今は大丈夫でも2年後を考えるとなんとしても次が来てもらわないと困ります。

さて、いつになったら安心できるのかということでちょっと勝ち点を計算してみました。単純に残りの12試合の全ての勝敗パターン(3^12=531441)を計算してみただけです。3位でもプレーオフはありますが考慮せず、勝敗がランダムに発生し得失点差は日本が不利だと仮定して計算すると日本が勝ち抜けできないパターンは40969パターンあり、つまり7.7%になります。よほどのことがないかぎり問題がないということですね。

あと何勝すれば勝ち抜けなのか?ちなみにオーストラリア残り5連勝などということが起これば勝ち点16でも敗退するパターンが6あります。つまり理論的には勝ち抜けには17点が必要になります。逆に言えば一敗は問題ありません。現実問題として二敗しても大丈夫ということがわかります。

早く確定するといいですね。10/16の試合が終わったらまた計算結果を出します。

あと計算につかったプログラムを残しておきます。

import Control.Monad
import Data.List 

data Country = Japan | Jordan | Australia | Oman | Iraq deriving (Eq,Show)
data Result  = HomeWin | Draw | AwayWin deriving (Eq,Show)

countries = [Japan, Jordan , Australia, Oman, Iraq]

countryPriority :: Country -> Int
countryPriority x 
  | x == Japan = 0
  | otherwise = 5
    
matchDone = 
  [ ((Japan,3),(Oman,0))
  , ((Jordan,1),(Iraq,1))
  , ((Japan,3),(Jordan,0))
  , ((Oman,1),(Australia,1))
  , ((Australia,1),(Japan,1))
  , ((Iraq,1),(Oman,1))
  , ((Japan,3),(Iraq,0))
  , ((Jordan,3),(Australia,0)) 
  ]

matchLeft = 
  [ (Oman, Jordan)
  , (Iraq,    Australia)
  , (Iraq,    Jordan)
  , (Oman,    Japan)
  , (Australia,   Oman)
  , (Jordan,    Japan)
  , (Japan,    Australia)
  , (Oman,    Iraq)
  , (Iraq,    Japan)
  , (Australia,   Jordan)
  , (Jordan,    Oman)
  , (Australia,   Iraq) ]

leftPattern = replicateM leftMatchNum [HomeWin, Draw, AwayWin]
leftMatchNum = length matchLeft
  
resultToPoint :: ((Country, Country), Result) -> ((Country, Int),(Country, Int))
resultToPoint ((x,y), r) 
  | r == HomeWin = ((x,3),(y,0))
  | r == AwayWin = ((x,0),(y,3))
  | r == Draw    = ((x,1),(y,1))
  
resultToPointPattern :: [Result] -> [((Country, Int), (Country, Int))]
resultToPointPattern result= map resultToPoint (zip matchLeft result)

calcPoint :: [((Country, Int), (Country, Int))] -> Country -> (Country, Int)
calcPoint pp c = (c,
    sum $ (map (snd . fst) $ filter (\x@(h,a) -> fst h == c ) pp)
    ++    (map (snd . snd) $ filter (\x@(h,a) -> fst a == c ) pp))

resultCompare :: (Country, Int) -> (Country, Int) -> Ordering
resultCompare (c1,r1) (c2,r2) 
  | r1 > r2 = LT
  | r1 < r2 = GT
  | r1 == r2 = compare (countryPriority c2) (countryPriority c1)
  
orderByJapan :: [(Country,Int)] -> [(Country,Int)] -> Ordering
orderByJapan x y = 
  compare 
  (fmap snd $ find (\a@(c,r) -> c == Japan) x)
  (fmap snd $ find (\a@(c,r) -> c == Japan) y)


main = do
  let pointPattern = 
        map (\pt -> 
                sortBy resultCompare 
                 (map (calcPoint (matchDone ++ (resultToPointPattern pt))) 
                  countries)
              ) leftPattern
  let lossPattern = filter  (\x -> not (elem Japan (map (\y@(c,r)->c) 
                                                    (take 2 x))))
                   pointPattern
  mapM_ print $ sortBy orderByJapan lossPattern
  print $ length lossPattern
  print $ (3 ^ leftMatchNum)
  print $ (fromIntegral (length lossPattern))/(3 ^ leftMatchNum)

< 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 >