月別: 2015年1月

fuelphpでcsvファイルをアップロードして読み込み処理

こんにちは

WEBエンジニアのyuchiです。

前々回の記事に引き続き、開発でfuelphpからCSVファイルをアップロードして読み込みしないといけなかったので、
その時調べた方法を書きたいと思います。

まずはCSVファイルをアップロードします。

// 初期設定
$config = array(
'path' => dirname(DOCROOT).'/uploads/',
'randomize' => true,
'ext_whitelist' => array('csv'),
);
// アップロード基本プロセス実行
Upload::process($config);
// 検証
if (Upload::is_valid())
{
// 設定を元に保存
Upload::save();
// 情報をデータベースに保存する場合
$result = Model_Uploads::deliv_add(Upload::get_files());
}

configでアップロードする場所をpathに指定し、保存するファイルの拡張しを設定し保存します。
randomizeをtrueにすると保存されるファイル名がランダムにつけられます。

次にアップロードしたファイルからcsvの読み込みを行います。

foreach ($files as $file)
{
$data = file_get_contents($file['saved_to'].$file['saved_as']);
$data = mb_convert_encoding($data, 'UTF-8', 'SJIS');
$data = Format::forge($data, 'csv')->to_array();
}

csvファイルの文字コードが分からないため、文字化け防止としてmb_convert_encodingで変換します。
例としまして、ここではSJISからUTF-8に変換。

あとは、読み込んだcsvファイルのデータを表示したりするだけです。

foreach($data as $list)
{
echo $list;
}

fuelphpの機能を使えば簡単にできました。

ちなみにアップロードしたファイルを削除したい場合は、

//ファイルを削除したい場合
File::delete(dirname(DOCROOT).'/uploads/' . ファイル名);
//ディレクトリを削除したい場合
File::delete_dir(dirname(DOCROOT).'/uploads/');

を書けばOKです。

では、今日はこのあたりで!

三山崩しゲーム

名前だけ聞いても分からないかもですが、やったことのある方もたくさんいると思います。
私も授業中とかによくやりました。
最後の1つを取ったら勝ち的なゲームです。
このゲームには必勝法があるので、今回はそれを紹介します。

ルール

  1. いくつかの石を3つの山に分けます。
  2. 2人のプレイヤーは交互に1つの山から1つ以上の好きな数の石をとる。
  3. 最後の1つを取った方の勝ちヽ(´∀`。)ノ゚イェイ

必勝法

説明がちょっと難しいのですが、
それぞれの山の石の数を2進法展開して同じ基底の係数の和が全て偶数になるように石をとります。
文章で書かれてもよく分からないと思うので、PHPのコードにしてみました。

function saikyou($input) {
$order = ceil(log(max($input), 2)) + 1;
arsort($input);
foreach ($input as $k => $v) {
$binary[$k] = str_split(str_pad(decbin($v), $order, "0", STR_PAD_LEFT));
}
$key = null;
for ($i = 0; $i < $order; $i++) {
$sum = 0;
foreach ($binary as $v) {
$sum += (int)$v[$i];
}
if ($sum % 2 == 1) {
if ($key === null) {
foreach ($binary as $k => $v) {
if ($v[$i] === "1") {
$key = $k;
$binary[$key][$i] = "0";
break;
}
}
} else {
$binary[$key][$i] = (string)(1 - (int)$binary[$key][$i]);
}
}
}
ksort($binary);
foreach ($binary as $k => $v) {
$output[$k] = bindec(implode("", $v));
}
return $output;
}

$inputには配列でそれぞれの山の石の数を入れます。
↓こんな感じになります。

$input  = array(9, 2, 5);
$output = saikyou($input);  // array(7, 2, 5)

$outputは最強の石の取り方でできたそれぞれの山の石の数です。
上の例では(7,2,5)なので、9の山から石を2つ取るのが最強です。
ちゃんと2進法展開の同じ基底の係数の和が全て偶数になっているのが分かります。
山の数は3つでなくても同じですし、石の数もいくつあっても考え方は一緒です。

便利な関数がたくさんあって短いコードでスッキリ書けました。
説明の難しいこともコードにするとスッキリですね。

◯参考
三山崩しゲーム

HubotでSlackのボットを作成する

Hubotとは

Hubotは、Github社が開発したBot作成フレームワークです。
今回は、Hubotを使用してSlackボットを作成する方法をご紹介します。

Slack https://slack.com/
Hubot https://github.com/github/hubot

HubotはNode.jsのモジュールですので、Node.jsのインストールから始めます。

Node.jsのインストール

複数のNode.jsを管理するnvmコマンド経由で、Node.jsをインストールします。

nvmコマンドのインストール。

git clone git://github.com/creationix/nvm.git ~/.nvm

nvmのコマンドを使えるように、.bashrcにスクリプトを追記します。

if [[ -s ~/.nvm/nvm.sh ]]; then
source ~/.nvm/nvm.sh
fi

以上で、nvmコマンドが使えるようになります。

次にNode.jsをインストールします。
今回の例では、バージョン0.11.13をインストールします。

npm install 0.11.13
npm use v0.11.13

以上で、Node.js関連のコマンドが使えるようになります。

nvmの他の機能が気になる方は、
nvm単体で実行するとヘルプが表示されるので、そちらをご参照ください。

Hubotのインストール

npmコマンドでHubotをインストールします。
また、必要なモジュールもインストールします。

npm install -g hubot hubot-slack yo generator-hubot coffee-script

上記のコマンドでインストールしたモジュールの情報は以下のとおりになっています。

モジュール名 説明
hubot Hubot本体。hubotコマンドが使用できるようになる。
hubot-slack HubotのSlack用アダプタ。HubotをSlackに対応させるために使用する。
yo ひな形生成ツール。
generator-hubot yoでHubotプロジェクトのひな形を生成するために使用する。
coffee-script CoffeeScript。HubotのスクリプトはCoffeeScriptで記述する。

HubotでHello World

「Hello」と呼びかけたら「World」と返すボットを作成します。

まずはHubotのひな形作成します。

$ mkdir hellobot
$ cd hellobot
$ yo hubot
_____________________________
/                             \
//\              |      Extracting input for    |
////\    _____    |   self-replication process   |
//////\  /_____\   \                             /
======= |[^_/\_]|   /----------------------------
|   | _|___@@__|__
+===+/  ///     \_\
| |_\ /// HUBOT/\\
|___/\//      /  \\
\      /   +---+
\____/    |   |
| //|    +===+
\//      |xx|
? Owner: Uchiyama
? Bot name: hellobot
? Description: (A simple helpful robot for your Company)
? Bot adapter: (campfire) slack
? Bot adapter: slack

ひな形ができたら、scriptsディレクトリ下にスクリプトを作成します。
今回はscripts/helloworld.coffeeとしました。

# scripts/helloworld.coffee
module.exports = (robot) ->
robot.respond /HELLO$/i, (msg) ->
msg.send "world"

ざっくり説明すると、
robot.respond /HELLO$/i」で、正規表現で反応する文字列をマッチさせ、
msg.send “world”」で、レスポンスを返しています。

チャットからのメッセージを受信したり返信したりする処理は、Hubot側で行ってくれています。

Hubotのコンソールを立ち上げて、このスクリプトの動作確認をしてみます。
以下のコマンドを実行します。

$ bin/hubot

Heroku関連の環境変数の設定に関するエラーが出てきますが、
現状は問題ないのでエンターを押して、コマンドプロンプトを復活させます。

以下のようにHubotにメッセージを送信すると、メッセージが返ってきます。

Hubot> Hubot hello
Hubot> world!
Hubot>

このように、実際にSlack上で実行する前に、コンソールで動作確認することができます。

Slackと連携するBotを作成

SlackのIntegrationページでHubotと連携するための設定を行います。

「Hubot URL」は、Hubot設置予定のURLを設定します。

あとで参照するので、「HUBOT_SLACK_TOKEN」などの環境変数は覚えておきます。

今回のSlackボットは、Slack上で挨拶された場合に挨拶を返す仕様にします。
コードは以下のようになります。

# scripts/slack-hello.coffee
module.exports = (robot) ->
robot.hear /@hubot Hello/i, (msg) ->
username = msg.message.user.name
msg.send "Hello, " + username

robot.hear /@hubot Hello/i, (msg) ->」で、反応するメッセージを検出し、
username = msg.message.user.name」で、ユーザー名を取得し、
msg.send “Hello, ” + username」で、レスポンスしています。

このスクリプトをコンソール上で動作確認してみます。

$ bin/hubot
Hubot> hubot @hubot hello
Hubot> Hello, Shell
Hubot>

ということで、挨拶を返してくれました。

Slackと連携するBotを実行

本番でSlackと連携する場合は、実行時のオプション指定などが必要になってきます。
結論から言いますと、コマンドは以下のようになります。

HUBOT_SLACK_TOKEN=xxxxxxxxxxxxxxx \
HUBOT_SLACK_TEAM=xxxx \
HUBOT_SLACK_BOTNAME=hubot \
bin/hubot --adapter slack

HUBOT_SLACK_TOKEN」「HUBOT_SLACK_TEAM」「HUBOT_SLACK_BOTNAME」といった環境変数を設定しています。
これらはSlackのIntegration画面にありましたね。

また、–adapterオプションでアダプタ(slack)を指定しています。

これで、Hubotが立ち上がったと思います。
この状態で、Slack上に「@hubot hello」と打ち込めば返信が返ってくるはずです。

まとめ

Hubotでボットを作成する方法をご紹介しました。
scriptsディレクトリ下にスクリプトを追加していけば、
ボットの機能を増やしていけます。
慣れてくると気軽に開発できるので、ボットづくりが捗ります。
色々連携させて効率化していきましょう。

chef12になって今までのcookbookが動かなくなった

chefでサーバーの初期構築をする時、以下のコマンドでchefをインストールして

curl -L https://www.opscode.com/chef/install.sh | bash

その後、ソースをgitから持ってきてchef-soloを実行してました

chef-solo -c solo.rb -j localhost.json

ある時、chefをインストールしたらバージョン12になって、以下のようなエラーが出るようになりました。

ERROR: Cookbook loaded at path(s) [/tmp/vagrant-chef-1/chef-solo-1/cookbooks/xxxxxx] has invalid metadata: The `name' attribute is required in cookbook metadata

とか

ERROR: Cookbook hogehoge not found. If you're loading hogehoge from another cookbook, make sure you configure the dependency in your metadata

とか。。

どうやらchef 12 から cookbookのmetadata.rb内のname attributeの記述が必須になったり、重要視されるようになったようです。
具体的に上側のエラーはmetadata.rbにnameの記述がない、というエラー。
下側のエラーはmetadata.rbのnameに書かれてる名前が実際のレシピと異なる場合に出てるみたいです。
(例えばディレクトリ名がhogeなのに name が fuga と設定されていてrecipe[hoge]と呼び出した場合に上記のエラーになります)

上記のようなエラーが出た場合は
cookbookディレクトリ内にあるmetadata.rbのname部分を見直してみてください。

name             'hoge'  ←ここが重要!
maintainer       'YOUR_COMPANY_NAME'
maintainer_email 'YOUR_EMAIL'
license          'All rights reserved'
description      'Installs/Configures hoge'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version          '0.1.0'

ソフトウェア開発生産性の向上に向けて

個人的な話ですが、昨年は職場がかわり、その環境に慣れるための1年だったような気がします。同僚に、またよいお客様に支えられなんとか1年無事?に過ごすことができました。ありがとうございます!!感謝感謝(笑)

さて、本年は自分のことだけでなく、本題のとおり、会社全体の課題である「ソフトウェア開発生産性の向上」について考えていきたいと思っています。具体的なディテイルには落とし込めていないですが思っていることをつらつらと書き留めておきます。

私自身、いままで、様々なソフトウェア開発プロジェクトに参画させていただきました。その中で正直、このプロジェクトはうまくいった!!と実感したプロジェクトは少なかった気がします。やはり何かしら問題があって、最悪、プロジェクト崩れを起こしてしまう場合もあったと記憶しています。

では、プロジェクトを円滑に進め、生産性を向上させるためにはどうしたらよいか?・・ですが、大きく分けると以下の点に集約され、それぞれを改善することで生産性の向上が可能であると考えます。

エンジニアスキル向上

IT業界の人材不足が社会問題となっていますが、現場を見てますと個人の自己啓発や興味?に頼っている部分が大きいと思っています。簡単にいうとできる人はできるし、それなりの人はそれなりなんですね。ちなみに私はまだそれなりの部類ですが(涙)
ここを会社として底上げする必要があると考えます。基礎知識をつけたうえで、各自得意分野を身につけていく。。といった流れが望ましいと思っています。具体的には資格取得によって基礎知識を身につけて実務と勉強会で応用力を身につけるような流れになればよいです。ここは独断では実行できないので、会社と要相談です。

PDCAサイクルの徹底

PDCAの詳細についてはググってください(笑)
昨今のソフトウェア開発の短納期・低コストでのプロジェクトを回すことを優先するあまり「D」の部分ばかりがフォーカスにあたり、特に「P」「A」が疎かになっているプロジェクトが多いと思われます。
気が付けば、赤字プロジェクト・・・なんてこともあったりするので、ここを是正することで、生産性の向上を考えます。具体的には「P]「A」を主題とした会議や体制を設けることで対応できればよいと考えています。
エンジニアへの意識づけも大切です。

コミュニケーション力

当たり前のことですが、この当たり前のことが疎かになりがちです。
お客様からしたらプロジェクトの進捗状況は気になるところでしょうし、できあがったソフトウェアを動かしてみて、「こんなイメージではなかった」といった認識の相違をなくすためにはコミュニケーションは不可欠です。
プロジェクトごとの状況チェックを強化することで、疎かになっているプロジェクトがあれば是正する方向で対応できれば。と考えています。

全体的にぼんやりしていますが、今年は上記3点をよりいっそう意識してソフトウェア開発を進めていき、お客様によりよい製品を納入して喜んでいただけるようにしたいと思います。
よりディテイルなアクションプランについてもブログ上で報告できれば。と思います。(予定)

Gmailにおける便利なショートカットキー自己ランキングNo1の発表!

書きたくない内容であったが、ネタの枯渇から書かざる得ない状況になった。

 

Gmailは、仕事をする私にとって非常に重要なツールである。

一日で一番利用率が高いツールだった。ので、

 

そこで、「Gmailで便利だったショートカットキーNo1!」をご紹介したい。

それは、

 

「?」

 

だ。

このショートカットキーを押すと、下記のようなショートカットキー一覧が表示されるので

それをひと通り覚えると、手足のごとくGmailが使えるようになる。

オススメだ。

 

 

 

 

linux‘find‘コマンドのご紹介

こんにちは、サーバーインフラエンジニアの葉です。
遅くなりましたが、明けましておめでとうございます。
本年も何卒よろしくお願いいたします。

今日は、findをご紹介します。
条件を指定してファイルやディレクトリを検索するコマンドで、検索結果を別のコマンドの引数として実行することが出来ます。

find基本的使い方

[code]
find 検索開始ディレクトリ 検索条件 コマンド
[/code]

検索条件

-name

  検索するファイルを指定。

[code]
find /home/yo -name “test
[/code]
というコマンドを実行するとき
カレントディレクトリ以下に
[code]
/home/yo/test3.txt.gz
/home/yo/test6.txt
/home/yo/test1.txt.gz
/home/yo/test5.txt
/home/yo/test2.txt.gz
/home/yo/test4.txt
[/code]
-iname file

  検索するファイル名を指定。大文字小文字を区別しない以外は -name と同じ。

-atime [+-]n
n日前にアクセスされたファイル。

-atime 2 2日前にアクセスされたファイル
-atime +2 3日以前にアクセスされたファイル
-atime -2 1日以内にアクセスされたファイル

-ctime [+-]n
n日前にファイルステータスが変更されたファイル

-ctime 2 ちょうど2日前にファイルステータスが変更されたファイル
-ctime +2 3日以前にファイルステータスが変更されたファイル
-ctime -2 1日以内にファイルステータスが変更されたファイル

-mtime [+-]n
n日前に修正されたファイル

-mtime 2 ちょうど2日前に修正されたファイル
-mtime +2 3日以前に修正されたファイル
-mtime -2 1日以内に修正されたファイル

アクション

次に検索結果を引数にして実行するのに -exec というアクションを使います。使い方は、
[code]
-exec [command] {} \;
[/code]

過去n日を除き削除してみる

ホームディレクトリ以下に yo ディレクトリで過去90日ごとのファイルを作ります。

  このディレクトリの中の 90日前より古いファイルを削除してみます。いきなり 削除するのは危険なのでまずは検索だけして、目的の結果が得られたことを確認してから削除しましょう。

[code]
find /home/yo -name “test” -exec ls –axl {} \;
[/code]
[code]
-rw-r–r– 1 root root 0 9月 1 12:00 /home/yo/test1.txt
-rw-r–r– 1 root root 0 10月 1 12:00 /home/yo/test3.txt
-rw-r–r– 1 root root 11 1月 6 17:22 /home/yo/test6.txt
-rw-r–r– 1 root root 0 12月 1 12:00 /home/yo/test5.txt
-rw-r–r– 1 root root 0 11月 1 12:00 /home/yo/test4.txt
-rw-r–r– 1 root root 0 8月 1 12:00 /home/yo/test2.txt
[/code]
今日は 1月6日なので 90日前の 11月よりも古いファイル、つまり 8、9、10月のファイルが出力されたので目的の結果が得られたことが確認できたので -exec で繋げて削除します。※-okで繋げたら削除前、削除確認あります。

[code]
find /home/yo -name “test” -exec rm -f {} \;
[/code]
もう一回検索だけして、
[code]
find /home/yo -name “test” -exec ls –axl {} \;
[/code]
[code]
-rw-r–r– 1 root root 11 1月 6 17:22 /home/yo/test6.txt
-rw-r–r– 1 root root 0 12月 1 12:00 /home/yo/test5.txt
-rw-r–r– 1 root root 0 11月 1 12:00 /home/yo/test4.txt
[/code]
成功しました。

まとめ

find コマンドは本当に便利です。特に大量ファイルを削除とか圧縮するときに、めっちゃ使いやすいです。
ぜひ使いこなしてください。

© SEEDS Co.,Ltd.