2012-11-24

【保育士試験】実技試験合格したよ


今日(12年11月24日)、保育士試験事務センターから合格通知が来ました。
去年の実技試験はボロボロで、今年はまぁまぁ出来た気はしてたんだけど、実際結果が来るまで不安でしょうがありませんでしたw

・点数について

今年の実技試験の結果は画像の通り、音楽「32点」言語「36点」でした。
去年の実技試験の結果は、音楽「14点」言語「35点」だったので、ピアノ弾き歌いは上達したと見てよいのではないでしょうか。

・結果通知書について

上の画像のように、今年の合格通知(オレンジ色の方)の裏には「保育士として業務に就く場合、都道府県知事への登録手続きが必要です。」という文言が表示されています。
去年の一部合格通知(の方)にはそれがありません。ということは、結果通知の裏に「保育士として~」という文言があれば「受かっている」ことが一目瞭然となっています。

・都道府県知事への登録手続き
保育士試験に受かっただけでは、いわゆる「保育士となる資格を有する(これも一生有効なのですが)」のみで、「保育士の名前を使って業務に就く」ことが出来ません
なので、保育士となるには都道府県知事に登録して【保育士証】を発行してもらうことが必要です。
保育士の登録を行っている団体は「登録事務センター」と言って、保育士試験を実施する団体とは別のものです。
登録事務センターから「登録の手引き」を取り寄せて、登録申請用紙に必要事項を記入して、登録手数料(4200円です。安いw)の払込証明書と合格通知書を添付して送付。2ヶ月程度で保育士証が送られてくるそうです。

以上です。

2012-10-16

【保育士試験】保育士実技試験の情報やスケジュールなどについて


前回の記事で実技試験の感想を記載したら、かなりいっぱいアクセスが来たのでもうちょっと解説してみます。
実技試験を受験したことが無い人にも分かるように書いたつもりです。


●実技試験受験票について
まず、実技試験を受けるためには「実技試験受験票」が必要です。
学科試験で全ての科目に合格したら学科試験の成績表と一緒になって送られてきます。
この受験票には
 ・試験会場
 ・ガイダンス開始時刻
 ・実技試験の選択科目
 ・最終受験者終了予定時間
 ・受験番号シール(4枚)
 ・筆記試験結果
が記載されています。


「受験番号シール」は実技試験を受験する際に試験監督者に渡したりするものです。
上の実技試験受験票は、昨年(H23年度)に受験したときのものです。
注意としては、「上履き」が必要な会場(私が行ったところも必要だった)では必ず上履きを持参しましょう。


●実技試験の流れ
当日の流れを知っているかいないかで大分精神的な余裕に違いが出ると思うので詳しく書きますね。
基本的には、
1)待機用の待合室で各試験開始20分前まで待つ
2)試験開始20分前になったら「各科目ごとに用意された受験者待機室」へ移動する
3)「各科目ごとに用意された受験者待機室」で係員に受験番号を呼ばれたら、試験室へ案内されるので付いていく
4)試験室前には順番待ち用の椅子が置いてあるので順番に座る
5)順番が来たら試験室へ入室し試験開始
という感じです。


△試験会場へ移動
私個人の行動としては試験会場へは大体20分~30分くらい前に着くように家を出ます。なんというか、場所に慣れるのにそのくらいかかってしまいますw


△ガイダンス(8時45分~)
試験会場に着いたら係員などから、実技試験の「注意事項」と「各受験者ごとの各試験開始時刻」が書かれた冊子(受験者が多い会場)や用紙(受験者が少ない会場)が渡されます。なくさないようにしましょう。
その後「待機用の待合室」に行くよう指示されます。この部屋ではガイダンスを聞いたり、「各科目ごとに用意された受験者待機室」へ移動するまで待つことになります。
ガイダンスでは、係員から渡された注意事項が読み上げられます。注意事項は全部最初に渡される冊子や用紙に書いてありますのでよく読んでおきましょう


△試験開始(9時30分から順次開始)
試験開始前に大きく「絵画の科目を選択している受験者」と「音楽と言語の科目を選択している受験者」に分けられます。

1)絵画の科目を選択している受験者
絵画の試験は全国どこの試験会場でも9時30分~10時15分までが試験時間です。なので、一斉に試験開始ということになるので分けられているのです。
絵画の試験終了後は各受験者が選択した音楽か言語の試験を受けに行きますが、基本的に「音楽と言語の科目を選択している受験者」が先に受験しているので後回しにされます
受験する人数が多い会場(東京の会場など)では絵画の試験後「5時間待ち」などがざらなので暇をつぶせる様に準備しておくと良いかもしれません。

2)音楽と言語の科目を選択している受験者
こちらの受験者は9時30分から順次音楽か言語の試験を受験します。基本的に絵画を選択している受験者より早く終わることが多いです。
個人的な情報ですが、自分が受験した仙台の試験会場では受験者が90人位だったので、音楽・言語を選択した受験者は大体午前中に試験を終えて帰宅することが可能でした。
今回の受験で私は音楽・言語を選択したので、11時くらいに試験が終了しました。


△音楽と言語の試験の注意事項
試験会場で渡される注意事項の冊子(用紙)に書いてありますが、「音楽と言語」の試験では「受験者が試験室に入室後の行動」に順番があります。受験後後悔しないようにしっかり暗記しておきましょう。

・入室前
1)「各科目ごとに用意された受験者待機室」に20分前には移動しておく
2)係員に受験番号を呼ばれたら、その係員に従って試験室前の椅子まで移動し、受験する順番に椅子に座る
3)順番が来たら係員に従い「失礼します」と入室する

入室後
1)入室したら、「手荷物」を「手荷物置き場」に置く。このとき受験票を手に持つのを忘れないようにする
2)受験票に付いてる「受験番号シール」を「2人の試験監督者へ1枚ずつ渡す」
3)「受験票」を「手荷物置き場」に置く
3)試験監督者が「受験番号と氏名を言ってください」というので「受験番号」「氏名」を答える
4)試験開始

というながれになります。
「自己紹介より先」に「受験番号シールを渡す」のがポイントです
試験監督者に「受験番号」を聞かれるときになって「覚えていない」場合、ちょっと「気まずい(笑)」のでちゃんと覚えておきましょう。これも受験して後悔しないためです。


△2科目受験後
試験は終了なので順次帰宅してOKです。


●合格発表
合格発表は、実技試験に合格すれば「合格通知」、実技試験に不合格なら「一部合格通知」が来ます。どちらもハガキサイズのものです。

「合格通知」の裏側には「保育士として業務に付く場合、都道府県知事への登録手続きが必要です」と記載されているので「中を開かなくても結果が分かる」ようになっています


●私の成績
去年の試験の成績表は上の画像の通りです。言語35点、音楽14点で不合格となりました。

1)言語
前回の記事でも書きましたが、言語の試験は後一行程度残しての時間切れでしたが、合格範囲内の点数はいただけるようですね。

2)音楽
音楽の試験では「電子ピアノで練習したから大丈夫だろう」と思い、ピアノで練習しなかったのが失敗の原因です。
そもそも、具合が悪くなるほど緊張しているところに、試験会場のピアノの「鍵盤の重さ」や電子ピアノとの「音の違い、響きの違い」からパニックになり、もう何をしたか覚えていませんw
心の強さがほしいところです。


---
以上、こんな感じです。

2012-10-14

【保育士試験】実技試験を受けてきたよ@2回目

今日(2012/10/14)に保育士実技試験の2回目受験してきたよ。合格発表は11月23日あたりらしいです。 

今回は前回のひどい有様とは違い、少しの失敗だけで何とか乗り切った気がするけど、どうなるかw 

以下、試験の記録です。 

---
追記(2012/10/19):
実技試験の詳しい内容や情報について、新しい記事にしてみましたのであわせてどうぞ。
---

【会場について】 
試験会場は昨年と一緒で「仙台幼児保育専門学校http://www.sendai-yoji.ac.jp/)」というところ。 
音楽・言語とも去年と試験室が同じだったので、「去年と同じか・・・」とイヤな予感がしたけどそんなことは無かったです。 

【試験全般】 
8時45分に会場に集合して、試験の説明を受け、9時30分から順次試験開始。 
今回は自分は受験番号が最後のほうのだったので、やっぱりだいぶ待つのか、と思ったけど午前中に終了しました。

【言語について】 
今回も言語の試験が先だったので、呼ばれたら試験室の前へ移動。 
自分の番がきたら、いわゆる「面接」の要領で試験官に挨拶してから、言語の試験開始。 
去年は後1行程度で終わるところで時間切れだったのだけど、今回は最後の「おしまい!」の「お」で時間切れだった。去年よりいい感じでしたよ。 

【音楽について】 
これも、呼ばれたら試験室の前へ移動。自分の番になったら試験官への挨拶をして試験開始。 
ピアノはカワイのアップライトピアノでした。去年はめちゃくちゃな結果だったからピアノのメーカなんて見る余裕も無かったけど、今回はちゃんと見たよw 
ただ今年もちょっと具合が悪くなるくらい緊張しました。 
「大きなたいこ」の伴奏を少しだけとちっちゃったけど、気にせず無理やり歌いきれました。 
「おんまはみんな」は伴奏もとちらずちゃんと歌えたよ。 
ただ、めちゃくちゃ緊張してたので音程が合ってたか?とかぜんぜん覚えてないですがw 

---
今回は、文化センターでピアノを借りて2時間ぶっ続けで練習したりしたので、何とかなったのかな。 

2012-06-19

【PHP】PC用・スマートフォン用・携帯用のページ振り分けする方法

PC、スマートフォンおよび携帯電話のページを自動的に切り替える方法を考えてみました。
SEO的にどのような影響が出るかはわかりませんw


◆仕様
・(1)切り替え用のプログラムは、公開しているディレクトリ直下に置く
・レスポンスされるHTMLを生成するプログラムは公開されていないディレクトリに、「pc/」、「smart/」および「mobile/」という名前にしておく
・レスポンスされるHTMLを生成するプログラムは、(1)に置いてある切り替え用のプログラムで読み込む(インクルードする)
・PC用ページは「/pc」以下のURLでアクセスする
・スマートフォン用ページは「/smart」以下のURLでアクセスする
・携帯電話用ページは「/mobile」以下のURLでアクセスする
・振り分けのは「ユーザエージェント」を検査して行うものとする



参考)ディレクトリ構成
├─public/ (公開ディレクトリ)
│  │
│  ├foo.php(振り分けプログラム1)
│  └bar.php(振り分けプログラム2)
│
└─template/ (非公開ディレクトリ))
    │
    ├─pc/
    ├─smart/
    └─mobile/
        │
        ├foo.php (携帯HTML生成用プログラム1)
        └bar.php (携帯HTML生成用プログラム2)
          ※この2つのプログラムはpc/、smart/ディレクトリにも存在する。



◆.htaccess
mod_rewriteを使用して、/pc、/smart、/mobileにアクセスしてきたリクエストを仕様の(1)にアクセスさせます。
例として、
---
RewriteRule /pc/([a-zA-Z\.]+)$ /$1
RewriteRule /smart/([a-zA-Z\.]+)$ /$1
RewriteRule /mobile/([a-zA-Z\.]+)$ /$1
---
といった感じでしょうか。

◆振り分けプログラムのすること
振り分けを厳密にするのは大変なので、今回はユーザエージェントを使用して振り分けすることにします。
たとえば、以下のようなプログラムになるでしょう。


  define( 'PC',       0 );
  define( 'SMART',    1 );
  define( 'MOBILE',   2 );
 
  switch( true ) {
    case preg_match( '/DoCoMo/i',    $_SERVER[ 'HTTP_USER_AGENT' ] ):
    case preg_match( '/KDDI/i',    $_SERVER[ 'HTTP_USER_AGENT' ] ):
    case preg_match( '/J\-PHONE|Vodafone|SoftBank/i',  
      $_SERVER[ 'HTTP_USER_AGENT' ] ):
      define( 'USER',   MOBILE );
      break;
    case preg_match( '/Android/i',  $_SERVER[ 'HTTP_USER_AGENT' ] ):
    case preg_match( '/iPhone/i',   $_SERVER[ 'HTTP_USER_AGENT' ] ):
    case preg_match( '/iPod/i',     $_SERVER[ 'HTTP_USER_AGENT' ] ):
    case preg_match( '/iPad/i',     $_SERVER[ 'HTTP_USER_AGENT' ] ):
      define( 'USER',   SMART );
      break;
    default:
      define( 'USER',   PC );
  }


これを振り分けプログラムで判別し、それにあったHTML生成プログラムをインクルードすればOKです。
たとえば、


  switch( USER ) {
    case MOBILE:
      include( '/template/mobile/' . basename( __FILE__ ) );
      break;
    case SMART:
      include( '/template/smart/' . basename( __FILE__ ) );
      break;
    default:
      include( '/template/pc/' . basename( __FILE__ ) );
      break;
  }


というような感じになるでしょう。
HTMLを変更するときは、必要となるtemplate/以下のファイルを修正するだけでOKです。

2012-06-18

【保育士試験】保育実習理論の画材・色の理論のメモ

保育士試験で出る「画材」「表現技法」や「色」のことは音楽理論ほど詳しい人が多くないような気がするので、ちょっと解説します。
実は、高校時代に美術部にいたのでそこら辺のことは結構知っていて学科試験の役に立ちました。

とりあえず今思い出せるものは以下の通りです。また思い出したら追加しておきますね。

◆画材
とりあえず、一覧にしてみます。

・クレヨン
顔料+ワックス(ろうそくのロウのこと)+油脂が材料で、適度に硬く線を引くのに適する。

・クレパス
いわゆる「パス」のこと。顔料+油脂が材料。伸びが良い。

・パステル
顔料を固定剤で固めたもの。削ったりすると顔料が粉になって、指で伸ばしたりできる。
出来上がった作品にはフィキサチーフという固定剤をスプレーして顔料の粉が落ちないようにする。

・アクリル絵の具
アクリルの液体で溶いた絵の具。かなり早く乾き、乾くと表面に耐水性の膜ができて上から重ね塗りしても下の色がにじまない。
いろいろなモノ(布やコンクリート)に塗れて乾くと落ちない。
日本では「リキテックス」という商品名で呼ばれることが多い。ガッシュ(後述)もある。

・ガッシュ
「不透明」な水彩絵の具の総称。
この中には「ポスターカラー」「不透明水彩絵の具」「アクリルガッシュ(アクリル絵の具の不透明版)」がある。
重ね塗りすると下の色は隠れてしまうが、多目の水で絵の具を薄めて使うと透明水彩絵の具のように使える。

・透明水彩絵の具
ウォーターカラーともいう。
不透明じゃない絵の具のこと。顔料とアラビアガムという材料で作られている。
これらの絵の具は「重ね塗り」が基本で赤を塗って乾かし、その後「青」を塗る。結果的に下の赤が透けて見え「紫」に見えるように彩色する。

・カラーインク
色のついたインクのこと。ものすごく発色がいい。

・色鉛筆
混色ができないので、色をそろえなければいけないけど、重ね塗りをすると混色っぽいこともできる。


◆表現技法
上の画材を使った表現技法のうち、横文字で耳慣れない技法の一覧です。

・フロッタージュ
100円玉や10円玉の上に紙を置いて、上から鉛筆でこするとしたのデコボコが写し取れる。
この技法のこと。

・デカルコマニー
紙に絵の具を載せて適当に筆や指で混ぜた後、二つ折りにし、開くとできる。
ロールシャッハテストに使われるやつ。

・ドリッピング
筆から絵の具を紙の上にたらして絵を作る。アクション・ペインティングともいう。
例としては「ジャクソン・ポロック」という画家が行っていた。
http://ja.wikipedia.org/wiki/%E3%82%B8%E3%83%A3%E3%82%AF%E3%82%BD%E3%83%B3%E3%83%BB%E3%83%9D%E3%83%AD%E3%83%83%E3%82%AF

・マーブリング
容器に張った水のうえに「水に浮くタイプ」の絵の具を流し、そっとかき混ぜ「マーブル模様」を作っておく。
その上にそっと紙を浮かべてマーブル模様を写し取る技法のこと。


◆色
色の理論はそれほど難しくないので覚えておけば何問か正解できるでしょう。

・色相環
順番に色を並べて輪にしたもの。
http://ja.wikipedia.org/wiki/%E8%89%B2%E7%9B%B8
この輪にある色の関係から、後述の「補色」などがわかる。

・色相
色自体のこと。青とか赤とかのこと。

・彩度
色の鮮やかさ。白や黒が他の色に混ざると「彩度」が減少する。
純色に近ければ彩度が上昇する。

・明度
色の明るさ。白が混ざれば明度はあがって明るく、黒が混ざれば明度が下がって暗くなる。
ちなみに、白と黒および灰色は彩度は無く明度のみ存在する。

・無彩色
「白」「灰色」「黒」のこと。明度のみ存在し、彩度が無い。
これ以外の色は「有彩色」といい、彩度というものがある。

・純色
混ぜていない色のこと。保育士試験ではおそらく「無彩色を混ぜていない色」のことだと思われる。

・補色
色相環上で中心点をはさみ向こう側の色のこと。
たとえば「青」の補色は「オレンジ」、「黄色」なら「紫」など。
1つの絵に補色だけ使うと目がチカチカするほど目立つものになる。

・色の三原色
シアン・マゼンタ・イエローのこと。全部混ぜると「黒」っぽい色になる。減算混合ともいう。

・光の三原色
青・赤・緑のこと。全部混ぜると「白(というか透明)」になる。加算混合ともいう。

・暖色
色相環上の「黄色」~「赤」~「ピンク」あたりの色のこと。あったかい色。

・寒色
色相環上の「水色」~「青」あたりの色のこと。寒い色。


以上です。

2012-05-27

【資格勉強法】丸暗記で乗り切る資格取得

3年前くらいから「合格率10%弱~20%未満」程度の資格試験を受験しています。
そこで自分なりの方法論を述べてみたいと思います。

この丸暗記で何とかなった資格試験は以下の通りです。
・宅建(1度で合格)
・マンション管理士(2度で合格)
・管理業務主任者(1度で合格)
・消防設備士(4類、6類とも1度に合格)
・2種電気工事士(1度で合格)
・保育士(1度で学科試験全て合格、実技試験は2回で合格)

まず、この勉強法を行う前提条件は以下の通りです

●前提条件
1)文系の資格であること(または、公式を覚えれば解けるくらいの計算以外出題されないこと)
2)極端に難しい試験ではないこと
3)マークシートや選択式の試験であること(4の一問一答問題集が出版されやすいため)
4)目標とする資格試験の一問一答問題集が販売されていること

1)は自分が文系であることと、そもそも「丸暗記」でやるので「応用問題」とかできない為です。
2)については、丸暗記では厳しすぎる内容ということならば腰をすえて勉強するものだ、ということですね。
4)は、後で詳しく述べますが「繰り返し問題を解く」のに非常に手軽だからです。


●教材について
自分が使う教材は「参考書(テキスト)」、「一問一答問題集」および「過去問題集」です。
テキストは下の「手順1」でも述べますが「重要なところが赤字や太字になっている」ものを選ぶのがいいです。
問題集は2種類で「一問一答」と「過去問」です。
一問一答問題集は学習のはじめから試験直前までずっと使います。なるべく過去問題を一問一答問題集にしたものを使ってください
過去問題集は試験直前2週間になったら過去5年分を1~2回くらい解いて一問一答問題集ではわからない「出題のされ方」を確認します。

なぜ、「一問一答問題集」なのか、という点について説明しますね。箇条書きにすると以下のとおりになります。

1)大抵の一問一答問題集は「過去問の選択肢をバラバラにして○×」という形式なので、網羅性が高く、読み飛ばしができないため
2)「過去問の選択肢をバラバラにして○×」という形式と、分野別に並べてあるものが多いので、取り組むときに比較的敷居が低いため
3)配点という概念が無く、学習進捗度を集計しやすい

3)の学習進捗度というのは「一問一答問題集の正答率」のことです。
自分がやっている集計方法としては、Excelで成績表を作り、問題番号を列に並べ、問題番号の隣の行にはその問題番号の問題が正答なら「1」誤答なら「0」を入力して集計します。
その集計を問題数で割れば「正答率」がでます。
分野別に分かれている問題集なら「分野別の正答率」も出せますから苦手分野もわかりやすくなります。


では、具体的な丸暗記勉強法について。


◆手順1:テキストの本文の「太字、色分け」部分のみ「ノートに抜き出す」作業を行う
参考書やテキストは、だいたい重要な部分は赤字だったり、太字になっていたりします。または枠で囲ってあったりもします。
その「重要な部分周辺の文章」を読み取って、「自分でまとめ」て、そのまとめをノートに書きます
そのほかの文章は全て無視でOKです。これをテキストの最後まで行います。

この作業は結構時間がかかるものなので、試験日から2ヶ月前くらい前までには終えるようにスケジュールを組んでください。
最初に受ける試験の時は、試験日の6ヶ月前くらいから始めるとかなり余裕を持ってできると思います。
慣れてきたら、試験日の3ヶ月~4ヶ月前からでも余裕で間に合います。

はっきりいいますがテキストはここで御役御免です。この後は問題集の解説を読んでもわからないところだけ確認のために読むくらいしか出番がありませんw

◆手順2:一問一答問題集を平日5日間かけて全て回答
手順1が終了したら、次は一問一答問題集で問題演習です。
この勉強の問題演習は基本的に1週間単位です。1週間で行う量としてはそれほど多くなく、しかも効果がテキメンです。
大体の一問一答問題集は1冊で1000問前後です。これを平日5日間でやるとすると1日200問です。1日200問もか…、と思われるでしょうが、大丈夫です。ここで一問一答問題集なのが効いてくるのです。
一問一答問題集の問題1つは大体1行から多くても5行くらいのものです。解くのに1分もかかりません。200問でも1時間はかからないものです。しかもやっていくうちに丸暗記が出来てきますので、解くのに10秒かからないこともあります。

だいたい、問題演習を始めて3週目以降は1日の勉強時間は大体1時間以内で終わります。
これくらいの勉強時間なら忙しい社会人の方でも、昼休みや帰宅後でも大丈夫じゃないでしょうか。また、複数の試験勉強の同時進行も比較的楽に実行可能ですね。


◆手順3:週末に手順1で作ったノートを読む
一問一答問題集を平日5日間で終わらせたら、週末です。週末になったら復習のために手順1で作ったノートを読みます。
当然テキストの全てを書き写していないので、問題演習中に「習ってない」部分が出てきたはずです
そこは一問一答問題集の解説、自分の記憶、テキスト確認でノートに補足しておきます


◆手順4:手順2と手順3を試験前2週間まで繰り返す
繰り返すのは丸暗記のためです。最低でも3回は繰り返してください3回繰り返すと解答正答率が全体で85%~95%程度になります。ならなくてももう1回か2回繰り返せばなります。
うそじゃありません。面倒なのを3回我慢すれば試験には本当に合格します。

注意としては、手順2をはじめるのは最低でも試験前5週間前くらいにしてください。多分暗記が間に合いません。
最低でも3回は手順2と手順3を繰り返してもらえれば、自分が言ってることがわかってもらえると思いますw


◆手順5:過去問題を1~2回解いて、実際の出題のされ方に慣れる
手順4が終了すれば後は仕上げのみです。
一問一答問題集ではわからない「実際の出題形式」に「慣れる」ために過去問題集を1回か2回解きます。
そうすれば出題の形式もわかるし、実際に時間を計って本番さながらの状況にもなれることができます。


以上が、「丸暗記で乗り切る資格試験」という駄文でしたw

自分の中では実績のある方法なのですが、これを読んで下さっている皆さんには会わない方もいると思います。
なぜ、こんな方法で勉強しているかといえば、「資格試験では100%の得点は必要ないから」であります。
つまり、「資格取得だけ」が目標になっているためですね。資格を使って就職、転職しようという方ならば、もっとちゃんと理解を進めるような勉強法をお勧めしますw

以上です。それでは。

2012-05-23

【サービス】家計簿システム作ってみた。

久しぶりに専門である「お金計算」のプログラム作ってみました。

今回は慣らしということで簡単な「家計簿」のシステムにしてみました。
開発期間は設計から賞味2日位です。
以前にも同じようなシステムを作っていたのですが、そちらはすでに古いバージョンのデータベースやPHPを使っていたので保守性も悪く、長いプログラムになっていました。
ですので、全面的にプログラムを書き直したうえでデータベースのバージョンもあげています。
あと、プライバシーとセキュリティを考えると、「名前」や「住所」は入力してもらわないほうが良いと判断して、ユーザ登録の際の入力には「メールアドレス」「パスワード」「ニックネーム」のみお願いしています

「TagajoTown Household Account Book System (TgagajoTown家計簿システム)」
紹介サイトURL  : http://kakei.tagajo.tv/
システムの使い方: http://kakei.tagajo.tv/how_to_use.php

というわけで、以下システムの目的と特徴紹介です。

■システムの目的
この家計簿システムは「現金出納」に利用するための物です(世間一般の家計簿はみな現金出納だと思いますが)。
基本的に、
1)預金からお金を引き出し
2)買い物をし
3)あまったら預金へ戻す
という流れを記録することで、現金の流れ(キャッシュフロー)を把握します。
つまり、無駄なお金を使ってないか確認するのが目的のひとつです。

あと重要なのが3)の「あまったら預金へ戻す」ことです。
これは「貯蓄を増やす」こととイコールなので「ヘソクリを増やしたい」という方にもお勧めの方法です。
このシステムでは、摘要が自由に設定できるので「預金預入」の摘要を追加して、その金額が増えるように家計を管理していけば、このシステムの目的達成、ということになります。

■特徴1.加算式家計簿
自分が家計簿(お小遣い帳でもいいですが)をつけるときに気になることがあります。
それは、家計簿をつけるとき「摘要」に合致する出納を「事前に集計して」からでないと家計簿に記載できないのがイヤだったということです。
たとえば、「食費」の摘要にはその日買った「昼食代」や「おやつ代」などを一旦「集計」するというひと手間です。

今回、それをなくすために以下のような方針で入力画面を設計しました。
1)1日の出納入力は「摘要」ごとに行う。つまりある日の出納データ数は設定した摘要の数までとなる。
2)摘要に入力した出納の数値は、すでにデータがあるときは「データに加算」、無いときは「その数値のデータを作成」とする。
3)摘要のデータは削除できないようにする(このシステムでの「出納データ削除」とは「摘要の削除」を意味するため)
4)削除できないため、出納の数値から「減算」もできるように「マイナスの数値」を受け入れるようにする。
という感じにしました。
このような設計にすると、「買った金額」ごとに入力できます
買い物の後レシートをもらったとして「その商品ごと」に金額を入力(しかも同じ摘要へ何度も)を行えるようになります。

こうしたおかげで「日毎に増えるデータ数」が限定され、ディスクの容量も節約できるようになり、集計演算もまぁまぁのスピードで行えるようになりました。

■特徴2.摘要のカテゴリ分類
摘要を「カテゴリ分け」できるようになっています。
カテゴリ分けすると、システムトップの集計一覧表に「小計」が表示されるようになります。
たとえば「収入」カテゴリに「預金引出」と「給与(手渡)」の摘要があったとして、2つの摘要の合計が「小計」欄に表示されるようになります。

また、これら「カテゴリ」「摘要」ともに「登録、変更、削除」ができるようになっています。
ただし、出納データが登録された摘要やカテゴリを削除すると同時に出納データも削除されてしまうので注意が必要です。

■特徴3.グラフ表示
システムのトップページには、「カテゴリ・摘要の集計一覧表」が表示されますが、そのほかに「摘要ごと」の折れ線グラフが表示されます。
このグラフ自体はGoogle Chart APIを使用しています。

以上です。

2012-04-29

【電脳卸】全てのカテゴリをパースする。

電脳卸のWebAPIで「全てのカテゴリを返す」XMLファイルがあるので、それをパースしてみたよ。
PHPの組み込み関数にもXMLをパースする関数があるけど、自分で実装したくなったので自分で書いてみたよ。

APIから返されるXMLの構造が微妙に難しかったので、再帰関数とスタックでやってみた。

APIのURLは→「http://webservice.d-064.com/3.x/category.xml」です。

/**
  電脳卸用全てのカテゴリをパースして配列して、シリアライズ後保存する。
  パース結果の配列は以下のような仕様で出力される
  
  結果配列仕様:
    array( 'カテゴリID 1' => array( 'name' => 'カテゴリ名', 'parent' => '親カテゴリID' ) );
    array( 'カテゴリID 2' => array( 'name' => 'カテゴリ名', 'parent' => '親カテゴリID' ) );
    array( 'カテゴリID 3' => array( 'name' => 'カテゴリ名', 'parent' => '親カテゴリID' ) );
    ...
    array( 'カテゴリID n' => array( 'name' => 'カテゴリ名', 'parent' => '親カテゴリID' ) );
    ※一番上のカテゴリは親カテゴリIDが「-1」となっている。
  
  商品のカテゴリIDから親カテゴリ全てを取得するには、    
    function get_category_tree( $category_id, &$category_tree )
    {
      global $global_category_array;
      
      $id = $category_id;
      $name   = $global_category_array[ $id ][ 'name' ];
      $parent = $global_category_array[ $id ][ 'parent' ];
      
      $category_tree[ $id ] = 
        array( 'name'   => $name, 'parent' => $parent );
      
      if( $parent == '-1' ) {
        return ;
      } else {
        get_category_tree( $parent, $category_tree );
      }
    }
    
    $global_category_array = unserialize( file_get_contents( './category_array.dat' ) );
    $tree = array();
    get_category_tree( '1269', $tree );
    var_dump( $tree );
  といったプログラムで返せる。
*/
define( 'CATEGORY_XML_URL',         'http://webservice.d-064.com/3.x/category.xml' );
define( 'CATEGORY_XML_FILENAME',    dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'category.xml' );
define( 'CATEGORY_ARRAY_FILENAME',  dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'category_array.dat' );
define( 'CATEGORY_SRC_ENCODING',    'UTF-8' );
define( 'CATEGORY_DIST_ENCODING',   'SJIS' );
date_default_timezone_set( 'Asia/Tokyo' );

/*
  個々のカテゴリデータを取得する
  @return array [ 'category_id', 'category_depth', 'category_name' ]
*/
function get_id_depth_name()
{
  global $xmlp;
  return array(
    preg_replace( '/<[^>]+>(.*?)<\/[^>]+>/', '$1', trim( fgets( $xmlp ) ) ),        // カテゴリID
    preg_replace( '/<[^>]+>(.*?)<\/[^>]+>/', '$1', trim( fgets( $xmlp ) ) ),        // カテゴリ深さ
    preg_replace( '/<[^>]+>(.*?)<\/[^>]+>/', '$1', trim( fgets( $xmlp ) ) ) );      // カテゴリ名
}
 /**
  カテゴリXMLをパースする。再帰関数。
  @param $parent 親カテゴリID
*/
function parse( $parent = -1 ) 
{
  global $xmlp;
  global $global_category_array;
  global $global_parent_ids;        // 親IDのスタック
  
  $line = trim( fgets( $xmlp ) );
  switch( true ) {
    // 空行
    case ($line == ''):
      parse( $parent );
      break;
    
    // XML定義
    case preg_match( '/<\?xml(?:[^>]+)>/', $line ):
      parse( $parent );
      break;
    
    // 一番外側のタグ
    case ($line == ''):
      parse( $parent );
      break;
    case ($line == ''):
      fclose( $xmlp );
      return;
    
    // 1つのカテゴリ
    case ($line == ''):
      list( $id, $depth, $name ) = get_id_depth_name();
      $name = mb_convert_encoding( $name, CATEGORY_DIST_ENCODING, CATEGORY_SRC_ENCODING );
      // 親IDを退避
      $parent = $global_parent_ids[ 0 ];
      // スタックに自分を積む
      array_unshift( $global_parent_ids, $id );
      
      $global_category_array[ $id ][ 'name' ]    = $name;
      $global_category_array[ $id ][ 'parent' ]  = $parent;
      
      parse( $parent );
      break;
    case ($line == ''):
      // 自分のIDを捨てる
      array_shift( $global_parent_ids );
      parse( $global_parent_ids[ 0 ] );
      break;
      
    // サブカテゴリ
    case ($line == ''):
      parse( $global_parent_ids[ 0 ] );
      break;
    case ($line == ''):
      parse( $global_parent_ids[ 0 ] );
      break;
    
    // ファイルが終わる前に「/Categorys」が来るはずなので使わないかも。
    case feof( $xmlp ):
      fclose( $xmlp );
      return;
      
    // 何かあったときのための保険。そのまま終了。
    default:
      die( '[' . $line . '] Exception.' );
  }
}


// XMLファイルダウンロードと保存
file_put_contents( CATEGORY_XML_FILENAME, file_get_contents( CATEGORY_XML_URL ) );

// XMLファイルのポインタ取得
$xmlp = fopen( CATEGORY_XML_FILENAME, 'r' );
if( !$xmlp ) {
  die( 'XML File Dont Open.' );
}

// 親IDスタックと結果配列準備
$global_parent_ids      = array( -1 );
$global_category_array  = array();

// パース本体
parse();

// 結果配列をシリアライズして保存
file_put_contents( CATEGORY_ARRAY_FILENAME, serialize( $global_category_array ) );

exit( 0 );

こんな感じ。

2012-04-25

【Scheme】ForthをSchemeで実装してみた。


はい。今度はScheme(処理系はGaucheを使用)でForthを実装してみました。

プログラムは5つの部分に分かれていて、
1)スタック管理
2)標準入力からプログラムを読むリーダ
3)ForthプログラムをSchemeプログラムに変換するトランスレータ
4)ワードが登録される辞書
5)実行制御
という構成になっています。

とりあえず、各部分の説明をしていきます。

1)スタック管理
;;; スタック管理

(define *data-stack* '())

(define (push val)
  (set! *data-stack* (cons val *data-stack*)))

(define (pop)
  (cond
   ((null? *data-stack*)
    (raise "Stack UnderFlow."))
   (else 
    (let ((val (car *data-stack*)))
      (set! *data-stack* (cdr *data-stack*))
      val))))

スタック管理は面倒くさくないグローバル変数を使ったものにしました。
関数もPUSHとPOPのみです。POPにはスタックアンダーフローがでたら例外が投げられるようになっています。

2)標準入力からプログラムを読むリーダ
;;; 標準入力から読み込み、トークンに分割する。

(define (trim str)
  (begin
    (set! str (regexp-replace #/^\s+/ str ""))
    (set! str (regexp-replace #/\s+$/ str ""))
    str))

;; シンボルに使えない文字を変換する
(define (def-word-translate str)
  (begin
    (set! str (regexp-replace-all #/\;/ str "edef"))
    (set! str (regexp-replace-all #/\:/ str "sdef"))
    (set! str (regexp-replace-all #/\./ str "dot"))
    (set! str (regexp-replace-all #/\.([a-zA-Z])/ str "dot\\1"))
    (set! str (regexp-replace-all #/\s+/ str " "))
    str))

;; 半角スペースで分割
(define (tokenizer str)
  (token->symbol (string-split (def-word-translate str) " ")))

;; トークンをシンボルと数値のリストにする
(define (token->symbol tokens)
  (cond
   ((null? tokens) '())
   ((rxmatch #/[0-9\.]+/ (car tokens))
    (cons (string->number (car tokens))
   (token->symbol (cdr tokens))))
   (else
    (cons (string->symbol (car tokens))
   (token->symbol (cdr tokens))))))

;; 標準入力からプログラムを読み取り、トークンにして返す
(define (reader)
  (let ((line (read-line)))
    (cond
     ((eof-object? line) '())
     ((string=? "" (trim line))
      (reader))
     (else
      (tokenizer (trim line))))))

基本的には標準入力から入ってきた文字列をトークンに分割するだけなのですが、「;」や「.」がSchemeでは特別な意味を持っているので、変換してからトークンに分割しています。

3)ForthプログラムをSchemeプログラムに変換するトランスレータ
;;; ForthプログラムをSchemeに変換する
(define *program* '())

(define (translate-token token)
  (cond
   ((number? token)
    (list 'push token))
   ((search-dict token)
    (list (get-dict token)))
   (else
    (raise (format #f "Undefined [~A]." token)))))

(define (define-word tokens)
  (cond
   ((null? tokens)
    (raise "Syntax Error: [;] is missing."))
   ((eq? 'edef (car tokens)) '())
   (else
    (cons (translate-token (car tokens))
   (define-word (cdr tokens))))))

(define (translate tokens define-flag)
  (cond
   ((null? tokens) '())
   ((and define-flag)
    (if (eq? (car tokens) 'edef)
 (translate (cdr tokens) #f)
 (translate (cdr tokens) #t)))
   ((eq? (car tokens) 'sdef)
    (add-dict (cadr tokens) 
       (append '(lambda ()) (define-word (cddr tokens))))
    (translate (cdr tokens) #t))
   (else
    (cons (translate-token (car tokens))
   (translate (cdr tokens) #f)))))

トランスレータは今はこれだけです。これに「ループ処理」や「ローカル変数」などを実装するともっと長くなりそうです。
ワード定義もここでやっていて、
(append '(lambda ()) '(define-word ...))
とやれば、手軽にワードを生成することができますね。

4)ワードが登録される辞書
;;; 辞書用プログラム
(define *dictionaly* (make-hash-table 'equal?))

;; 辞書初期化
(define (init-dict)
  (begin
    (hash-table-put! *dictionaly* '+ 
       (lambda () (push (+ (pop) (pop)))))
    (hash-table-put! *dictionaly* '- 
       (lambda () (let ((a (pop))) (push (- (pop) a)))))
    (hash-table-put! *dictionaly* '* 
       (lambda () (let ((a (pop))) (push (* (pop) a)))))
    (hash-table-put! *dictionaly* '/ 
       (lambda () (let ((a (pop))) (push (/ (pop) a)))))
    (hash-table-put! *dictionaly* 'mod 
       (lambda () (let ((a (pop))) (push (mod (pop) a)))))
    (hash-table-put! *dictionaly* 'dot 
       (lambda () (print (pop))))
    (hash-table-put! *dictionaly* 'dots
       (lambda () (print (reverse *data-stack*))))
    (hash-table-put! *dictionaly* 'exit
       (lambda () (exit)))
    ))

;; 辞書に追加
(define (add-dict key val)
  (hash-table-put! *dictionaly* key val))

;; 辞書検索
(define (search-dict key)
  (hash-table-exists? *dictionaly* key))

;; 辞書から取得
(define (get-dict key)
  (if (search-dict key)
      (hash-table-get *dictionaly* key)
      (raise (format #f "Undefined [~A]" key))))

ワード辞書もグローバル変数としました。辞書からワードを取得するとき、ワードが存在しなければ例外が投げられます。
ワードは「init-dict」関数に追加していけば使える組み込みワードが増えます。今は四則演算と表示くらいしかないですがw

5)実行制御
;;; Forthエントリポイント

;; 処理系初期化
(define (init-forth)
  (begin
    (load "./dictionaly")
    (load "./reader")
    (load "./stack")
    (load "./translate")
    (init-dict)))

;; ForthプログラムをSchemeに変換した結果を実行する
(define (exec-forth prog ret)
  (cond
   ((null? prog) ret)
   (else
    (exec-forth (cdr prog)
  (eval (car prog) (interaction-environment))))))


(init-forth)
(let loop ()
  (display "> ")
  (flush)
  (display (exec-forth (translate (reader) #f) #f))
  (newline)
  (loop))

これは特に説明することもないです。
処理系の初期化関数とトランスレートしたForthプログラムの実行くらいです。
トランスレートしたプログラムはただevalしてるだけですね。

こんな感じです。

2012-04-20

【Forth】JavaScriptでForthっぽいの作ってみた。

ちょっと前から、簡単な言語構造をしているプログラミング言語を他の言語で実装することにはまっています。
今回挑戦したのはForth言語です。
今回はJavascriptで作ったので、整数も浮動小数点数も同じ1つのスタックで処理できます。つまり、「1.2 2 + sqrt」とか書くことが可能です。
この言語の特徴は「スタック志向」と「逆ポーランド記法(後置記法)」につきます。他の言語で言う「関数」は「ワード」といいます。ワードは辞書に登録されています。
と、突然言われても良くわからないのと思うので、早速サンプルプログラムをいくつか列挙して解説していきたいと思います。
Forthは(というより後置記法がですが)偶然にも日本語の並びにとても似ているので日本語で説明するのが実は簡単です。

04-21追記:個別サイトを作ってみました。JS Forth

●インタプリタデモ
1.下の入力欄にプログラムを入力して、エンターキーを押します。
2.自動的に計算結果が入力欄の下にたまります。
※このページをリロードすると定義したワードが消えてしまいますので注意してください。




●20000円を3人で割り勘にする
 → 20000 3 /mod floor . .
解説:
上のプログラムは以下の通り処理が進みます。
1)20000をスタックに積む。3をスタックに積む。(20000 3)
2)スタックから2つ値を取り出して、除算をし、剰余をスタックに積む。商をスタックに積む。(/mod)
3)スタックからひとつ取り出して小数点以下を切り捨てる。(floor)
4)スタックから1つ取り出して表示する。(.)
5)スタックから1つ取り出して表示する。(.)
ね、簡単でしょ?
日本語で説明するときは、「20000円と3万円で割り算して商と余りを出す。商の小数点以下を切り捨てて結果を出す」といったところでしょうか。

●割り勘ワード定義
上のプログラムをワード(関数)にしてみます。
 → : warikan ( n1 n2 -- n n ) /mod floor ;
解説:
1)「:(以下コロン)」はワード定義が始まるときに書きます。コロンがないとForthインタプリタは解釈モードとして動作し、結果を出そうとします。それをやめさせるにはこのコロンが必要です。コロンが見つかったときインタプリタは「コンパイルモード」になってプログラムがワード定義だとわかり、結果を出すのではなく定義されたワードを辞書に登録します。
2)「warikan」はワード名です。
3)「(」~「)」はコメントです。この場合のコメント「( n1 n2 -- n n )」はスタックから2つ取り出し、処理結果を2つ積む。という内容のコメントです。
4)「/mod floor」はwarikanワードのプログラム本体でこれらに引数の記述は必要なく、ワードの中でスタックからポップする処理やプッシュ処理が記述されているので「引数を本当に」とりません。
5)「;」はコロン定義の終了マークです。

Forth言語のプログラムは以上のような感じです。

●組み込みワード
今のところ組み込みワードは以下の通りです。
注意としては、制御構造ワードは「コンパイルモード」でしか使用できないところでしょうか。
詳しいワードの説明は「GForthマニュアル」がいいと思います。

・算術演算(整数・小数の区別なし)
+ 1+ - 1- * / mod /mod negate abs min max

・ビット演算
and or xor invert lshift rshift 2* 2/

・比較演算
< <= <> = > >= 0< 0<= 0<> 0> 0>=

・算術関数
floor round ** sqrt exp log cos sin tan acos asin atan atan2 pi

・制御構造
if else then endif begin agein repeat while until ?do loop +loop -loop unloop leave exit recurse

・スタック操作
drop nip dup over tuck swap rot -rot pick clearstacks

・表示
. .s

2012-04-07

【Lisp/Scheme】Pythonで実装されたSchemeインタプリタをPHPにコンバートしてみた。

関数型言語勉強の一環として、比較的簡単なSchemeのインタプリタをいつも使ってるPHPで実装してみることを考えたのですが、参考になる書籍がなかったのでネットで探したところ以下のページを見つけました。
((Pythonで) 書く (Lisp) インタプリタ) http://www.aoky.net/articles/peter_norvig/lispy.htm

このページのプログラムはPythonで書かれています。PythonとPHPはかなり違う言語なので、なぜかPythonの勉強もしてしまいましたw

評価器以外には特に苦労しなかったので、評価器以外を直接見たい場合はこの記事一番下からダウンロードしてください。

■評価器(Evaluator)
評価器は標準入力から入力されたS式(Lisp系言語のプログラムのこと)を読取り器から得るシンボルや定数の列を受け取って解釈しプログラムを実行するものです。
以下具体的に見ていきます。実際のPythonプログラムは上のページを見てください。
評価器は再帰関数になってて、Schemeのスペシャルフォーム(評価器が式の内容全てを評価しない式のこと)の処理と、普通の式を処理するかなり簡単なプログラムです。
が、これをPHPにコンバートするのに苦労しました。以下が自分の書いた評価器プログラムです。

・コンバートしたPHPプログラム
/**
  定数、シンボルまたはシンボルの配列を評価する。再帰関数。
  @param $symbols 定数、シンボル、またはシンボルの配列
  @param $env     環境オブジェクト。指定されない場合はトップレベル環境。
*/
public static function lisp_eval( $symbols, $env = null )
{
  // 環境が指定されていないときはトップレベルの環境を指定
  if( $env == null ) {
    global $global_environment;
    $env = $global_environment;
  }
  
  // シンボルの場合
  if( is_a( $symbols, 'Symbol' ) ) {
    return $env->get( $symbols->value );
  
  // 定数の場合
  } elseif( is_scalar( $symbols ) ) {
    return $symbols;
  
  // 以降リストの場合
  } elseif( $symbols[ 0 ]->value == 'quote' ) {     // (quote exp)
    list( $quote, $exp ) = $symbols;
    return $exp;
    
  } elseif( $symbols[ 0 ]->value == 'if' ) {        // (if test conseq alt)
    list( $if, $test, $conseq, $alt ) = $symbols;
    if( self::lisp_eval( $test, $env ) ) {
      return self::lisp_eval( $conseq, $env );
    } else {
      return self::lisp_eval( $alt, $env );
    }
    
  } elseif( $symbols[ 0 ]->value == 'define' ) {      // (define var (lambda exp))
    list( $define, $var, $exp ) = $symbols;
    $env->add( $var->value, self::lisp_eval( $exp, $env ) );
    
  } elseif( $symbols[ 0 ]->value == 'lambda' ) {      // (lambda vars exp)
    list( $lambda, $vars, $exp ) = $symbols;
    $str_lambda  = '$args = func_get_args();' . "\n";
    $str_lambda .= '$env  = array_pop( $args );' . "\n";
    $str_lambda .= '$vars = unserialize( stripslashes( ' . "'" . addslashes( serialize( $vars ) ) . "'" . ' ) ); ' . "\n";
    $str_lambda .= '$exp  = unserialize( stripslashes( ' . "'" . addslashes( serialize( $exp ) ) . "'" . ' ) ); ' . "\n";
    $str_lambda .= '$new_env = new Environment( &$env );' . "\n";
    $str_lambda .= '$new_env->zip( $vars, $args );' . "\n";
    $str_lambda .= 'return Evaluator::lisp_eval( $exp, $new_env );' . "\n";
    $lambda_function = create_function( '', $str_lambda );
    return $lambda_function;
  
  } elseif( $symbols[ 0 ]->value == 'begin' ) {       // (begin exps)
    each( $symbols );
    foreach( $symbols AS $symbol ) {
      $val = self::lisp_eval( $symbol->value, $env );
    }
    return $val;
    
  } else {                                            // 関数評価
    $exps = array();
    
    foreach( $symbols AS $symbol ) {
      $exps[] = self::lisp_eval( $symbol, $env );
    }
    $proc = array_shift( $exps );
    
    /*
      小細工
      関数が使う環境オブジェクトを関数の引数として渡す。
    */
    array_push( $exps, $env );
    $ret  = call_user_func_array( $proc, $exps );
    return $ret;
  }
}


Pythonの評価器には「S式をリスト構造に直した」リストと、環境オブジェクト(後述)が渡されるようですが、PHPにはリストのように扱える組み込みデータ構造が用意されていません。
この関数のためにいちいちリスト構造を実装するのも面倒なので、配列をリストの代わりにしました。
引数の「$symbols」がその配列です。この配列に対して「each」「array_shift」「list」などを使えば、案外簡単に配列をリストのように扱えます。

・環境オブジェクトのこと
環境オブジェクト(以下環境)はトップレベルやレキシカルな環境を実現するためにあります。評価器に渡される環境オブジェクトには現在自分がいる階層の変数、関数が見えています。
また、環境には1つ外側の環境のポインタを持っていて、「あるシンボルを参照したいときに自分のいる環境に無い場合はひとつ外側の環境を参照する」という再帰メソッドが定義されています。
自分のいる階層の環境には自由に関数やシンボルを登録することができますが、自分より下(よりレキシカルな)環境にはアクセスできません。

・関数定義と環境オブジェクトに関する小細工
評価器にはS式のリストと環境が渡されます。リスト内に関数定義があると、評価する際微妙な問題を起こしました。
Pythonのプログラムは普通にクロージャ内に直接実行時の環境を渡せるのですが、自分が使っているPHP(Ver5.1.4)のクロージャには現在の環境をそのままでは渡せません。
なので、関数実行時に「関数の引数とともに現在の環境を押し込む」というなんともチカラ技なプログラムになってしまいました。
そんな感じなので、クロージャでは「引数のチェック」なんてものはしてませんw

こんな感じです。


Pythonのプログラムページに載っている以下のプログラムも「遅い」ですけど、一応動作します。
lis.py> (define area (lambda (r) (* 3.141592653 (* r r))))
lis.py> (define fact (lambda (n) (if (<= n 1) 1 (* n (fact (- n 1)))))) lis.py> (define first car)
lis.py> (define rest cdr)
lis.py> (define count (lambda (item L) (if L (+ (equal? item (first L)) (count item (rest L))) 0)))


PHPのソース全部は以下からダウンロード可能です。
http://www.tagajo.tv/lisphp_1.0.zip

■使い方
シェルに以下のように入力してください。
$ php -f lisphp.php

2012-03-14

【Androidアプリ】微速度撮影カメラ作ってみた。

Androidスマートフォン(Infobar A01)を買いました。
このスマートフォンにはカメラもついています。そこで、Androidアプリ開発になれるためにほしかった「微速度カメラ」を作ることにしました。

この「微速度撮影機能(インターバル撮影ともいいます)」とは、設定した間隔で自動でシャッターを切ってくれる機能のことで撮影した画像ファイルをぱらぱら漫画の要領で映像に変換すると早回し編集をしなくても面白い映像を作ることができます。
テストで撮影した動画は以下の通りです。



・仕様
対応機種  :Infobar A01 (他にテストできる実機がないため)
対応OSVer :2.3.3(他にテストできる実機がないため)
画面の向き:横のみ
画像保存場所:SDカード内、「DCIM/lapse」以下に保存
画像ファイル名:「yyyymmdd_hhmmss.jpg」

・使い方
1)「設定変更」ボタンをクリック
2)「画像解像度」、「シャッター間隔」、「撮影時間」を設定して「設定する」ボタンをクリック。設定は保存され、次回起動時には前回起動時の設定に自動的に変更されます。
3)「設定する」ボタンをクリックすると、自動的に前の画面に戻りますので「撮影開始」ボタンクリックで撮影開始します。
4)撮影を途中でやめるときは「撮影終了」ボタンをクリックします。


・スクリーンショット
撮影画面:
 設定画面:

・機能
1)スマートフォンのカメラに対応した画像サイズを設定可能
2)シャッター間隔は5、10、15、30、45、60、90、120秒に設定可能
3)撮影時間は1、5、10、15、30、45、60、90、120、180、240分に設定可能

・ダウンロード
Gumroad 微速度撮影カメラアプリ
Androidマーケット 微速度撮影カメラアプリ

・プログラム作成時に躓いたところ
1)ActivityクラスがJavaアプレットのようにライフサイクルによりイベントが発生する形式なので、Cameraクラスのメソッドreleaseを実行した後にtakePictureを実行してしまったりした。
2)Activityクラスは画面の傾きにより縦と横に向きが変わるが、そのたびに「onDestroy」と「onCreate」が発生しめんどくさい。
3)「メソッドの引数」と「クラスのメンバ」が「同じ名前」のときに、無名クラスからその名前を使うときは、引数にfinal修飾子が必要なこと
4)無名クラスから、その無名クラスを定義しているクラスの参照したいときには「無名クラスを定義しているクラス名.this」と書くこと
5)ぱっと見、スタックトレースやエラーメッセージの見方がわからないこと
6)実装の都合からActivityが1つしかないので、AlertDialogすら出すのに苦労すること。
7)TableLayoutで使うTableRowには「行の結合」ができないこと。

2012-02-22

【Gumroad】プログラム販売をしてみることにした

Gunroadというサービスがあります。
このサービスは「ファイルをアップロードする」あるいは自分のサーバ上にファイルを置いてその「URLを登録するだけ」でプログラムを販売するページが作成できる、というものです。
サービスへ払う必要がある手数料は「商品金額の5%+$0.30」ということになっています。
詳細はインプレスのInternet Watchの記事↓を参照してみてください。
http://internet.watch.impress.co.jp/docs/special/20120215_512149.html

とりあえず、自分が作ったPHPの自作ライブラリを販売していってみることにしました。
使い方はファイルの最初に「コメント」として記載しておきました。ちょっとしたサンプルプログラムも載っています。

1つ目:PHPのMySQL接続&結果セットクラス
2つ目:PHPカレンダー作成クラス
3つ目:Linuxサーバで自動的にFTPダウンロードするシェルスクリプト

2つ目は使い方がわからなくて「2ドル」の価格設定としてしまいましたが、1つ目の方は「200円」にしています。
さて、どのくらい売れるでしょうか。

それでは。

2012-02-10

【Apache】Rewriteの設定方法

タイトルの通りなんですが、いわゆる「静的ページ(この言い方どうもしっくり来ないのは自分だけなのでしょうか?)」でWebページを構成したいときにも使います。
その設定方法についての説明です。

例としてAmazonのAPIを使用した商品紹介ページを考えます。

■仕様
・「本」カテゴリの「TIGER&BUNNY(タイガー&バニー) ~桂正和原画&ラフ画集成~」という商品のページ
・「本」カテゴリのSearchIndexは「Books」とする。
・「TIGER&BUNNY(タイガー&バニー) ~桂正和原画&ラフ画集成~」当商品のASINは「408908153X」とします。






■設計
仕様から、以下のようなURLを考えます。

1)パラメータつきのURL
  http://www.foo.com/item.php?s=books&a=408908153X

2)パラメータなしのURL
  http://www.foo.com/item/books/408908153X

今流行のURL形態にしようと思います。

■実装
実装は以下のような感じです。
1)「item.php」上のAタグ、HREF属性を上のパラメータなしURLに変更する。
2)www.foo.comドメインのトップディレクトリにある「.htaccess」にRewriteの設定を記述する。

■Rewriteの設定
やっと本番です。今の例の場合「.htaccess」は以下のようになるでしょう。

RewriteEngine on                                     // Rewrite設定有効化
RewriteCond %{REQUEST_FILENAME} !-f                  // リクエストに「実体」がある場合それを優先する
RewriteCond %{REQUEST_FILENAME} !-d                  // リクエストに「実体」がある場合それを優先する
RewriteRule /item/([a-zA-Z]+)/([0-9a-zA-Z]+)$ /item.php?s=$1&a=$2 [L]  // 実際の動作

RewriteRuleの「[a-zA-Z]」や「[0-9a-zA-Z]」、「()」「+」「$」は正規表現というものです。
意味は
・[a-zA-Z] → 「小文字のa~zまでと大文字のA~Zまでのどれか1文字」を表す
・[0-9a-zA-Z] → 「数字0~9、小文字のa~zまでと大文字のA~Zまでのどれか1文字」を表す
・() → 括弧で括られた部分をキャプチャして左から順に$1、$2という風に後から使えるようにする。
・+ → 直前のパターンが1文字以上続く、という条件
・$ → 行末の意味
などです。これらは「メタ文字」といいますが、詳しくは専門書でも見てください。説明が大変なんですw


これで多分、動くようになると思いますが実際はよくテストを行い確認をして使ってください。

2012-01-13

【マンション管理士】合格発表と模範解答についての感想

2011年度のマンション管理士試験合格発表と模範解答の発表が今日(2012年01月13日)にありました。
合格点は36点(50点満点、5問免除者は31点)合格率は9.3%となりました。そこで、感じたことをつらつら書いてます。

■雑感
今回のマンション管理士試験は簡単だった前回の試験と比べかなり難しかった、というコンセンサスが取れていたように思われます。
ですが、その割には合格率が「9.3%」と史上初めて9%を超えるという現象が起きました。
これは、今年度のマンション管理士試験受験生のレベルが相当に高かった、ということなのではないかと思います。

■解答速報と資格学校について
前のブログエントリである、「【マンション管理士】試験の感想など」でも記載していたとおり、解答の意見が割れておりました。
掲示板やmixiのコミュニティでも活発な予想合戦が繰り広げられていたようです。そして、結果的には「大手資格学校(LEC、TAC)の失態」と「住宅新報社の一人勝ち」ということに落ち着いたようです。
住宅新報社は1番目の解答速報では、模範解答と異なるものを発表していたようですが、すぐに修正され模範解答と同じものを発表しなおしました。
ほかの大手資格学校が模範解答と異なる解答速報を出す中、孤高だったと言っていいでしょうw

■tagajoの試験結果について
さて、今回の私の成績ですが、模範解答で採点しなおした結果、

32点(免除分を加算すると37点)

というわけで、合格いたしました!
なんとかマンション管理士試験を卒業できました。前年度の試験は簡単だっただけに気持ちの切り替えには苦労しましたが報われた気がしてます。
ちなみに自分の問3、問29、問33の解答は「3-4-2」です。わからなかったのは問3のみだったようです。

それでは。

ZenBack

WebMoney ぷちカンパ