ひまつぶし雑記帖

おひとり様ActivityPubサーバーにブースト実装

2023/9/21 [09:25:34] (木) 天気

twitter(現X)に代表されるSNSの一番の特徴はリツート(ブースト、リポスト)
これがあるおかげで?せいで?SNSへの投稿は拡散力を持つことになった。良い悪いはおいといて、ウチのおひとり様APサーバーにも実装してみた。

考えなきゃいけない一番の優先順位は。
「デマの拡散に加担してはいけない」

なので、ブーストはブースト取り消しの実装と同時。

ブーストはActivityPubだとタイプAnnounceのjson。対象となるNoteのIDをobjectに入れる。
宛先の「cc」には自分のfollowersに、対象となるNoteの投稿者も含めておく。

{"@context": ["https://www.w3.org/ns/activitystreams", {"Hashtag": "as:Hashtag"}],                                                                                                                                           
"type": "Announce",
"id": "https://tokoroten.doncha.net/t2aki/announce/TIMESTAMP",
"actor": "https://tokoroten.doncha.net/t2aki",
"to": ["https://www.w3.org/ns/activitystreams#Public"],
"cc": [DELIVER-LIST],
"object":"NoteID"}



Announceの取り消しはタイプUndoのjsonに、Announceに使ったjsonをobjectにそのまま入れる。

{"@context": ["https://www.w3.org/ns/activitystreams", {"Hashtag": "as:Hashtag"}],
"type": "Undo",
"id": "https://tokoroten.doncha.net/t2aki#UUID",
"actor": "https://tokoroten.doncha.net/t2aki",
"object":ANNOUNCE-OBJECT}


以上のjsonを自分のフォロワーさんのinboxに署名付きpostでリクエストをすれば、ブースト・ブーストの取り消しとなる。

これだけっちゃこれだけなんだけど、ブーストはスクリプトじゃないところに問題があるんだよなあ。

ブーストを実装したいと思ったのは。
いま、フォロワーさんの数が16人ほどで拡散力もなにもないんだけど、それでもイベントのお知らせや、発売の宣伝なんかは、微力ながら協力できればなあ、というのが動機。
せっかくSNSなんだし。

ブーストはヤバイなあと思うのは。
デマの拡散に加担する可能性、というのがもちろん一番で。
それ以外というか、他人の投稿を拡散することで自分が何かを語ったつもりになる、という乗っかりの承認欲求、自己顕示欲を得られるところ。

自分の頭で考えて自分の言葉で語ることをしなくなる、簡単に闇落ちする(自戒をこめて)
実装はしたけど、ブーストするのは基本的にイベントや発売告知だけにする。

また、ウチのおひとり様は、他人のデータを持たない、というのが原則。
なので、Annouceの投稿も期限つき。最長7日間にした。
イベントなんかは終わってたら残念だし、発売関連は初動に少し貢献できれば十分かなあ、と。

image
ひとつ何かを実装するのに、やっぱりけっこういろいろ考慮しなきゃいけないことってあるもんだなあ(今さら
自分のとこだけのことならどうでもいいんだけど、ActiviyPubで繋がるわけだから、そりゃそうかという話。

»電子書籍制作代行についてはこちら

iPhone13ProMAXに機種変更

2023/9/15 [13:22:16] (金) 天気

今日はiPhone15の予約開始の日。
そして、わたしのところには整備品で買ったiPhone13ProMAXが届いた。これまで使ってたXSでそれほど問題も感じてなかったんだけど、バッテリーの持続時間が倍違う、という家人のプッシュに乗ってしまった。
アップルケア(2年保証)や、ケース、カバーもろもろで17万円ぐらい。ビンボ世帯にとっては安い買い物じゃないんだけど、正規で買うよりは安かったし、などなどモゴモゴ。

iPhoneに限らず。スマホで最優先されるべきはバッテリーの持続時間。ネットに繋がって、たまには電話できればそれで十分で、それ以外はすべてオマケ。

機種変更でハマったのが。
データ通信は問題なかったんだけど、ネットワークが繋がらない。IPアドレス取得のあたりが怪しい?と思ってキレちらかしてたら、家人がVPSをインストールしてあっさり接続、解決。
iOSとmineoの問題なのか、よくわからないんだけど、mineoのページに行って、VPSをインストールする必要があったらしい。

それ以外は問題なく、XSの環境がそのまま13に移行して、今まで通りに使える。
横に並べておいておくだけで移行できるのって、未来だよなあ、と感心するばかりだった。
image
これはXSで撮った13の写真。13はカメラが売りらしいんで、それっぽい対象を見つけたら撮ってみてみよう。

»電子書籍制作代行についてはこちら

iPhoneで撮った写真の向きが逆

2023/9/14 [22:03:58] (木) 天気

iPhoneで撮った写真が、タテのはずがヨコになったり、ヨコのはずがタテになったり。iPhoneを縦に構えて撮ってるのに、写真では横になる。
前からちょっと気になってた。

「写真」アプリだと意図通り縦で表示されている。
WEBにアップすると横に転んでしまう。意味がわからない。なんでやねん。
image
検索してみるとiPhoneのジャイロセンサーで縦横が決められるという話が出てくるんだけど、なんか違う。

identify -verbose
してみたら。
Geometry: 4032x3024+0+0
Orientation: RightTop
て、思いっきり横位置で保存されていた。それをExifのOrientationで縦に起こしている。
RightTop
「Right」は横向きで保存されている上側を右側にする
「Top」は横向きで保存されている左側を上側にする
という指示。この通りに表示すれば時計回りに90度回転して縦位置となる。Exif情報を読んで表示できる環境(アプリ)であれば。

とはいえ、そもそも横位置で保存されてしまってるんで、そのままjpgファイルをpngファイルに変換したら横写真になる。

しょうがないんで、画像の回転指示(Orientation)を確認して、指示が入っていたらRotateして縦位置で保存するようにした。
image
Image::ExifToolというexif情報を取得できるモジュールがlolipopにはインストールされていたので実装はすんなり。

my $is_rotate;
my $exif = new Image::ExifTool;                                                                                                                          
my $pinfo = $exif->ImageInfo($ofile);
$is_rotate = $1 if( $pinfo->{'Orientation'} =~ m!Rotate *90 *(CW|CCW)! )


iPhoneで縦位置で写真を撮る=デジカメを縦に構えて写真を撮るということらしい。
ということなら、写真を横で保存するのは正しい動作。てことで回転は90度決め打ち。

だけど、Exif情報にカメラ位置補正を入れるぐらいなら、保存する時に補正してくれ。

てのはともかく、上野の科学博物館で開催の「海展」は、ほんと語彙をなくすほどの凄さだった。どの展示も目を奪われて立ち尽くす時間が長くなる。はやぶさがリュウグウから持ち帰った砂を見られるとは思わなった。ほんとスゲー。
まじオススメ!
「国立科学博物館」
「海 ―生命のみなもと―」

»電子書籍制作代行についてはこちら

おひとり様ActivityPubサーバー自作実装メモ

2023/9/8 [15:45:34] (金) 天気

ActivityPubを通じてMastodonなどFediverseと呼ばれるネット連合からアカウントとして認識されるように最低限のサーバー構成を作ったのが7/12。その後、秘密鍵・公開鍵を使えるperlのモジュールをlolipopレンタルサーバーにインストールできたことで、それっぽいものにしあがって、実際に運用して今日に至る。

「ため池」
↑perlで自作実装したおひとり様ActivityPubサーバー

そもそもMastodonやMisskeyなどのサーバーを立てるスキルがない。わたしには難易度が高すぎる。
自分のわかる範囲で自作実装したので、間違ってる・勘違いしてるところもあるかも知れないけど、今のところ意図通り。
この雑記帖と同じレンタルサーバーに展開して追加の費用なども必要ない。

自作とはいえ、スグ忘れるのでまとめてメモしておこう、というのがこのエントリ。
5分以上前の自分はアカの他人。

Fediverseからアカウントとして認識されるために必要なもの
1)nodeinfo(json)
 サーバー情報。
2)host-meta(xml)
 webfingerのURL。
3)webfinger(json)
 ユーザー情報のURL。
4)actor.json(json)
 ユーザー情報。type:Personのjson。
上から順番にアクセスされて4のユーザー情報にたどり着けばActivityPubサーバーのアカウントとして認識される。
1と2はなくても大丈夫らしいけど、webfingerのURLは「/」だったり「/.well-known/」だったりするので、2の「/host-meta」で教えてあげる。

「ActivityPubを使ってFediverseにたどり着く」
↑各ファイルの詳細。


おひとり様サーバーとして動作しているスクリプトは2つだけ。
・飛んでくるリクエストをさばく門番的スクリプト
・タイムラインを表示、投稿、管理するスクリプト


【飛んでくるリクエストをさばく門番スクリプト】

ActivityPubでの会話を求めて飛んでくるリクエストはいろいろ。
アカウント情報を取得するためにactor.jsonをリクエストされるし、ActivityとしてCreate(投稿)Follow(フォロー)などのリクエストが飛んでくる。

まず「.htaccess」を設置
rewrite ruleでパラメータをつけて門番スクリプトにリダイレクトするところからスタート。

リダイレクトされてリクエストを受けつける門番スクリプトの仕事は以下。

サーバー情報やユーザー情報はGETでリクエストが飛んでくる。
リクエストされたURLに応じて、門番は用意してある静的ファイル、jsonやxmlファイルを返す。
ActivityPubのjsonファイルは「Content-Type: application/activity+json; charset=utf-8」をヘッダにつけるのが必須。

followerやfollowingにアクセスされた時はfollower、followingを記載したテキストファイルを読んで、静的ファイルにそのリスト情報をくっつけて返すようにした。

Activityリクエストは「ユーザー名/inbox」にPOSTでリクエストが飛んでくる。
これはまとめて門番で受け取って。
・HTTPヘッダ類
・content(ボディ)
これをひとつのログファイルとして、所定のディレクトリに保存する。
ボディ=jsonを読んで、CreateだのFollowだのUndoだのログファイル名の一部にしておく。
門番スクリプトの仕事はここまで。

ヘッダ類もログファイルに収録するのは。
公開鍵とhttp signatureで、飛んできたリクエストが正しく署名されているか検証する必要がある。
Mastodonなんかはたぶんリクエストが来たらその場で検証までしてるはずで、ログファイルなど必要ないと思う。
わたしの場合、まだよくわかってないことが多くて、ログファイルで確認したいことがあるので、そのためにログファイルを残している。

ActivityのPOSTリクエストのうちいくつかは今時点スルーしている。
仕様的にはMUSTとかSHOULDだったりするものもあって、対応が必要と思われるけど、ウチの運用的にそれ必要?と微妙なもの…要検討。


【タイムラインを表示、投稿、管理するスクリプト】
あまり考えず「ため池」という名前にした。

Mastodonでいうところの「ローカルタイムライン」のために投稿用のデータベースを用意。

といっても、テーブル2つだけ。それも1つはログインに使うだけのもの。投稿用のテーブルはテキストと、画像のURLや幅・高さぐらいを記録するメモ帳。
投稿するには重複しない一意のIDが必要で、それにはデータベースが便利に使える…ほぼそのため。

おひとり様サーバー、ユーザーはわたしだけ。サーバーに登録しているユーザーの投稿を表示する「ローカルタイムライン」は、わたしの壁打ちとなる。


フォローしたひとの投稿を表示する「ホームタイムライン」はファイル管理。

自分以外、ひと様のデータを持たないのが原則。ひと様のデータを溜め込むといろいろ考えなきゃいけないことが出てくるから。

ため池にアクセスすると、門番スクリプトが保存したログファイルを開いて。
まずはHTTP SignatureのVerify。
actor情報をリクエストして、公開鍵を取得。公開鍵を使ってログファイルのヘッダ情報にあるSignatureを検証する。
Signatureに問題がなければ、Activityに応じた所定のフォルダに、所定の命名規則で名前をつけたjsonファイルを保存。元のログファイルを削除。

「RSAモジュールで公開鍵と秘密鍵」
「HTTP Signatureをlolipopレンタルサーバーで作成」
↑秘密鍵、公開鍵について

タイムライン用に保存するjsonファイルはCreateかAnnounceのNote
・上限20個
・期間1日
ディレクトリのファイルを読んで制限以上になっていたら削除。
フォローイングが増えてくると、読まないまま削除される方が多いし、さらにフォローは増やすつもりなので、読む・目にする投稿の方が圧倒的に少なくなる。知らない間に流れてきて知らないうちに削除されている。

でも、SNSはそのぐらいで適正だと思う。
その時その場で見たものがすべて。「袖すり合うも他生の縁」だ。

「ホームタイムライン」用に保存するjsonファイルは「to」か「cc」に「Publish」(全公開)が指定されているもの限定(サークル投稿を除く)
この「ホームタイムライン」を表示するにはログインが前提。つまり、見ることができるのはわたしだけだ。

ホームタイムラインの投稿にフォローしたひとのアイコンや名前を表示させるために、actor.jsonをリクエストしてpersonを取得してそこからアイコンのURLや名前を取ることになる。
これだけのためにリクエストが生じるんで、ホームタイムラインの表示が重い。

[10/24 09:27:53]
さすがに重すぎでキレた…ので、不本意ながら、表示名とアイコンURLに限っては、キャッシュすることにした。
当然、表示は劇的に早くなった。
キャッシュの期間は30日(要検討)。
Updateのリクエストがpersonだったら確認してキャッシュに反映。

本当だったら非同期で情報を更新したいところだけど、Javascriptとか面倒くさいし、メンテやエラーの特定にあっちもこっちもになってコスト高なので却下。手動更新。

見るのが自分ひとり、一般公開はしないということから、表示が重いのは我慢、また、同じ理由でいくつかのリクエストはスルーしてもいいかな、と。

[10/04 12:53:50]
というのが、ログファイルが貯まるとさすがに重すぎるので、このフェーズだけ抜き出したスクリプトを作ってcronで5分間隔で回すようにした。


MentionとFollowは別扱い。
両方とも確認してから返事するなりフォロー返しするなりしてから手動で削除することにした。

FollowをAcceptしたら、Followのjsonを保存して、followersのリストに登録する。
Following、こちらからフォローする場合も同じ。Followingに使ったjsonを保存して、followingのリストに登録する。Followingのjsonを保存するのは、フォロー解除するUndoのために、元になったjsonが必要だから。uuidでIDを作ることにしてしまって、残しておかないと元のjsonを再現できないというオチ。

Mention
連絡先としてサイトや名刺など今まではtwitterのアカウントを入れたんだけど、twitterがなくなったんで、こっちを「連絡先はこちら」にしたい。Mentionを見落としちゃまずいんで、これも確認からの手動にした。

[09/21 10:05:12]
リクエストとして飛んでくるブーストは対応済みで、こちらからブーストのリクエストを飛ばすのも実装してみた。
「おひとり様ActivityPubサーバーにブースト実装」
いろいろ考えなきゃいけないことあった(改めて)

[10/03 10:57:44]
「おひとり様ActivityPubサーバーのjsonの実例」
投稿するのに実際に使ってるActivityPubのJSONの実例をメモした。

[10/06 10:26:14]
「おひとり様ActivityPubサーバーにLike実装」
Likeされる方じゃなくて、する方の実装。
WEB拍手みたい感じで使うのがいいかな、と。

[12/22 07:40:43]
「ActivityPubサーバーのGETリクエストに署名」
GETリクエストでactor情報などを取得する時にHTTP Signatureが必要なサーバーもあった。
GETにも署名することにした。

[12/27 10:01:38]
「おひとり様ActivityPubサーバーにBlock実装」
レアケースだけどBlockも対応した。

[2024/01/23 09:08:36]
「おひとり様サーバーの改修」
Fedibird.comやkmy.blueなど一部のサーバーが実装しているサークル機能に対応…といっても読むだけ。サークル作成やサークル投稿に対する返信は未対応。

■以上、雑なまとめでした■
ディテールというか無駄の多いエントリはカテゴリからどうぞ。
「ActivitiyPub::ひまつぶし雑記帖」


以下のサイトを参考にさせてもらっておひとり様ActivityPubサーバーを実装することができた。感謝深謝。
「NetlifyとSupabaseでほぼ静的なActivityPubサーバ」
「Fediverse入門―非中央集権型SNSサーバを作ろう!」
「田舎の昼のサイレンbotをActivityPubで実装する(マストドンにアカウントを認識してもらう編)」
「ActivityPubの実装についてのメモ」

ActivitiPub本家本元。
「ActivityPub」
「ActivityPubの仕様(和訳)」

image
[12/13 08:30:17]追記。
Activityなどの実装・対応状況

[済]Create
noteを投げ込むのに使用
[済]Follow
followしたらfollowingリストに追加。json保存。
followされたらfollowersリストに追加
[済]Accept
followされたら許可
[未]Reject
followされたら拒絶
[済]Update
noteやpersonなどオブジェクトの更新…だけど、personだけ対応
[済]Delete
自分がポストしたNoteの削除。
ポストされて流れてきたNoteの削除(20個しか保存しないので、すでに削除済みのことが多いけど念のため)
[未]Add
オブジェクトの追加
[未]Remove
オブジェクトの削除
[済]Block
ブロックされたらリストに登録。間違えてFollowするといけないので、Followリクエストを飛ばす時にブロックリストも確認する。
[済]Like
いいね。
したらjson保存。14日間。
されたら1日だけ表示。jsonは3日間だけ保存。
[済]Announce
ブースト。
したら、7日間ため池データベースに保存。期限がすぎたら削除、undo
されたものは削除
ブーストされたらLikeと同じ対応にした
[済]Undo
やり直し。
ブーストの取り消しとフォロー解除は対応済み。Likeは未対応。


[済]Mention
DMみたいなものだからJSON保存。確認して手動で対応。
[済]Hashtag
お一人さまだと意味はないけどとりあえず
[未]Replies
リプライは実装しない方向で

Json-LDの署名について不明。手がかりにできそうなURL
jsonの日本語訳PP版
MastodonのJSON-LD署名と検証
MastodonのJSON-LD署名の実装rubyのコード
JSON-LD関連のコード
graph rdfとかよくわからんけど、関係しそうなところ
LDのAPI

»電子書籍制作代行についてはこちら

思考ツールの構築

2023/9/1 [00:04:05] (金) 天気

うわ。なんか、虫唾の走る啓発系本のタイトルみたいで、自分でムカつく。
…のはともかく、還暦を過ぎて、明らかに脳みそが劣化してるんでそのサポートにいいかも、と思ったんでメモ。

この雑記帖以外のナニかを最近作ったんだけど、これらがけっこう使いものになってる。

1)思いつきを垂れ流すひとり言掲示板。
ところてんx10
2)ネットに放流するのに使うおひとり様ActivityPubサーバー。
ため池
3)そして、1998年から続けてる雑記帖。

思考はまさにこの番号順。

1)ひとり言掲示板という、ただのメモ。
スマホで手軽気軽に入力できるので思いついたらその場でちゃっちゃと記入。
そんな思いつきみたいなものをネットで公開?…てのは、公開する意味は意外にもあって、こんな辺境でアクセスログを確認してもほとんど見られていない場所だけど、それでも見られてしまうかもしれないとか考えると、思いつきとはいえ迂闊なことは書けない。ひと目をそれなりに意識したものになる。
保持するのは100個だけ。100個以上はところてん式に古いものを削除。表示させないのではなく、データベースから文字通り削除している。思いつきが流れて消えてしまう前になんらかのカタチにしようと思うことが増えた。つまり、自分で自分を急かしてる。
この2点だけでもこのひとり言掲示板は、わたし的にめちゃくちゃポイントが高い。生産性が上がったとかクソ啓発系ビジネス書みたいなこというけど、自画自讃。

とにかく。思いつきをテキストにして入力するのが楽しいんだわ。

スクリプト的には手抜きもいいとこで、今まで作ってきたスクリプトの中でも難易度は最低レベル。データベースもリレーションなんてないただのメモ帳。

ていうか、これ、間違いなく還暦を過ぎた老化現象。こうしてテキストに落とし込んでおかないとすぐに忘れてしまう。若い頃ならこんなの必要はなかったと思う。

2)おひとり様APサーバー
ひとり言掲示板でネタをためて、この雑記帖のエントリにする、というのが元々の発想だったんだけど、twitterがなくなったこともあって、あれこれ調べて作ったりして面白かったので、こいつも使うようにした。
こっちはひとり言掲示板と違って、Fediverseというネット空間に意図をもって投稿する、ことになるので、わたしの知らないサーバーに表示されるかも知れないし残るかもしれない。自分のコントロールがきかないので、かなり「よそいき」を意識する。
元ネタとしてひとり言掲示板に書いたものから拾うようにする、とりあえずひとり言掲示板に書いてみるのが前提。
twitterなんかのSNSはつい何か言いたくなってしまうことがあって、それは承認欲求だったりマウントだったり、我ながら、動機がロクでもない。
ひとり言掲示板を起点、発火点にすることで、ひと呼吸おけるようになった。

てのはともかく、twitterやfacebookみたいな中央集権型のSNSには愛想が尽きたんで、おひとり様APサーバーをSNSの窓口にしていく。
こいつの発想や仕様をちゃんとメモしておかないと忘れるので、もう少し枯れてきたら雑記帖のエントリにしよう。

3)雑記帖
1998年からなにか書いてる日記で、25年ほど続けてるんで、そこにはなにか狂気を孕んでたりしてのちのち評価されたり…なんてことは1mmもなく、ただただ凡庸でくだらない事象心象についてつまらない文章で書かれてるだけ。
とはいえ、ここまで続けてきたので、レンサバの契約切れとかわたしの健康面金銭面での都合でやむなく終了するまでは書き散らすつもり。
これを作った頃はまだスマホじゃなくてPCだったんで、入力フォームやもろもろPC前提。増改築の継ぎ足し継ぎ足しでスクリプトはこんがらがってるなあ。今となっては無駄なIE対応のCSSなんか読み込んでるし。

現状、ひとり言掲示板の大勝利。
image
2023年も、もう9月。還暦を過ぎると月日の流れがいっそう早くなるなあ。

»電子書籍制作代行についてはこちら

profile

profile

 
doncha.net
contact:
»運営者
@t2aki@tokoroten.doncha.net

ため池

[2024/10/09 23:24]
ActivityPub Implementations
https://syobon.notion.site/a5e9e010575f499fb9f1520436ac2d75
ActivityPubサーバーもいろいろあるんだ。てか、こんなにいろいろあるのはいいなあ。

以前も投稿したEpicyonのスクショはなかなか衝撃的なので再掲。
No timeline algorithms.
No javascript.
No database. Data stored as o ...

[2024/10/09 17:58]
「ちっこい」「オモチャみたいな」
ノパソがほんと欲しいんだけど、需要がないのかなあ。大艦巨砲主義的なゲーミングPCは、わたしは必要ない。

[2024/10/09 17:51]
縦軸:弱い↓↑強い
横軸:馬鹿←→賢い

…ううう、どうやら左下っぽいなあ。せめて左上になりたい人生だった。

@t2aki@tokoroten.doncha.net

検索
<<2023/09>>
     12
3456789
10111213141516
17181920212223
24252627282930

リンク

WINDOWS版サウンドノベル
おかえりください PC WINDOWS版サウンドノベル
『おかえりください』体験版

[1 Page]

TOTAL:2991

2024 (14)
1 (2)
2 (2)
3 (1)
5 (1)
7 (2)
8 (2)
9 (3)
10 (1)
2023 (53)
1 (1)
2 (5)
3 (1)
4 (1)
5 (3)
6 (9)
7 (9)
8 (6)
9 (5)
10 (3)
11 (2)
12 (8)
2022 (16)
1 (1)
3 (2)
6 (2)
7 (1)
8 (4)
9 (2)
10 (1)
11 (2)
12 (1)
2021 (12)
1 (3)
2 (1)
6 (1)
8 (2)
9 (1)
10 (1)
11 (2)
12 (1)
2020 (18)
1 (2)
2 (6)
4 (1)
6 (1)
7 (2)
8 (2)
12 (4)
2019 (17)
1 (3)
2 (4)
3 (2)
4 (2)
5 (1)
6 (1)
8 (1)
10 (1)
12 (2)
2018 (21)
1 (3)
2 (2)
3 (2)
4 (1)
5 (1)
6 (6)
8 (1)
9 (1)
10 (2)
12 (2)
2017 (32)
1 (2)
2 (1)
4 (2)
5 (1)
6 (6)
7 (3)
8 (5)
9 (3)
10 (2)
11 (2)
12 (5)
2016 (41)
1 (5)
2 (5)
3 (2)
4 (3)
5 (4)
6 (6)
7 (2)
8 (2)
9 (3)
10 (1)
11 (4)
12 (4)
2015 (99)
1 (11)
2 (12)
3 (9)
4 (6)
5 (8)
6 (8)
7 (3)
8 (5)
9 (16)
10 (6)
11 (1)
12 (14)
2014 (112)
1 (16)
2 (5)
3 (6)
4 (12)
5 (16)
6 (19)
7 (9)
8 (6)
9 (4)
10 (8)
11 (6)
12 (5)
2013 (145)
1 (24)
2 (15)
3 (18)
4 (23)
5 (14)
6 (11)
7 (7)
8 (11)
9 (5)
10 (4)
11 (6)
12 (7)
2012 (103)
1 (1)
2 (1)
3 (4)
4 (3)
5 (7)
6 (26)
7 (17)
8 (5)
9 (8)
10 (10)
11 (11)
12 (10)
2011 (54)
1 (4)
3 (7)
4 (4)
5 (14)
6 (6)
7 (3)
8 (3)
9 (1)
10 (4)
11 (2)
12 (6)
2010 (70)
1 (12)
2 (7)
3 (6)
4 (6)
5 (3)
6 (10)
7 (6)
8 (4)
9 (3)
10 (4)
11 (3)
12 (6)
2009 (144)
1 (15)
2 (12)
3 (12)
4 (6)
5 (15)
6 (6)
7 (10)
8 (9)
9 (17)
10 (12)
11 (14)
12 (16)
2008 (148)
1 (10)
2 (6)
3 (10)
4 (11)
5 (13)
6 (10)
7 (13)
8 (19)
9 (18)
10 (12)
11 (13)
12 (13)
2007 (106)
1 (7)
2 (5)
3 (3)
4 (7)
5 (5)
6 (9)
7 (8)
8 (13)
9 (18)
10 (11)
11 (8)
12 (12)
2006 (158)
1 (28)
2 (28)
3 (25)
4 (7)
5 (9)
6 (7)
7 (12)
8 (13)
9 (10)
10 (7)
11 (6)
12 (6)
2005 (350)
1 (31)
2 (26)
3 (26)
4 (27)
5 (29)
6 (30)
7 (32)
8 (30)
9 (30)
10 (32)
11 (29)
12 (28)
2004 (292)
1 (24)
2 (24)
3 (29)
4 (27)
5 (28)
6 (25)
7 (26)
8 (24)
9 (12)
10 (19)
11 (26)
12 (28)
2003 (318)
1 (22)
2 (25)
3 (21)
4 (28)
5 (28)
6 (28)
7 (28)
8 (29)
9 (26)
10 (29)
11 (28)
12 (26)
2002 (317)
1 (29)
2 (26)
3 (26)
4 (25)
5 (28)
6 (30)
7 (27)
8 (21)
9 (25)
10 (27)
11 (28)
12 (25)
2001 (277)
1 (17)
2 (21)
3 (23)
4 (20)
5 (31)
6 (18)
7 (26)
8 (25)
9 (29)
10 (19)
11 (24)
12 (24)
2000 (53)
6 (9)
7 (4)
8 (2)
9 (3)
10 (1)
11 (15)
12 (19)
1999 (3)
7 (1)
10 (2)
1998 (18)
9 (9)
10 (7)
11 (2)