Scratchを使ってみた

プログラミング開発環境Scratchをさわってみたので、その記録

どうせなら子供と一緒にやろうかと思ったもののITリテラシーの低い我が子たちはiPhoneでマインクラフトが限界で、PCのマウス操作ができないので今回は見送り

ブラウザさえあればScratchのプログラムは作れるけど最低でもタブレットを要求されるようで、iPhoneでは動かないみたい。iPadかなにかを買ったら再挑戦しよう

Scratchさわってみた感想は、さすが「マサチューセッツ工科大学のメディアラボが作成した初心者の学習用プログラム言語」、非常に洗練されている

特にリファレンスに頼ることもなく適当に作っても動くものができた。それがコチラ

※iPhone/iPadでは動かないです。PCかFlashが動くAndroid推奨

※音を出さないと意味不明かも。ペンとかクリックしてね。

 

Scratchつかってみて感銘を受けた特徴を書き出してみる

  • 変数は宣言しただけで画面に表示される

    例えばマウスクリックで「Score」という変数を作ると、まずは画面に「Score 0」表示される。画面やコンソールに変数の内容を表示するための(初心者にとって)オマジナイのようなコードは不要。簡単に画面から非表示にすることもできるけど「変数を作ると画面に表示される」がディフォルトであるとか、初心者の気持ちわかってる感がステキ。デバッグも楽

  • オブジェクト指向という考え方を身につけられる

コードは背景画像(ステージと呼ぶ)かキャラクターなどの画像(スプライトと呼ぶ)にしか書けない。あるキャラクターを動かしたかったら、そのキャラクター画像のスプライトにコードを書かないといけない。自然とプログラムをステージやスプライトといったオブジェクトごとに書くことになる。また「何を動かすのか」が解決済みなのでコード部分で指定する必要がないのでシンプルにもなる。ちなみにScratchがオブジェクト指向言語であるかどうかの論議があるらしい。怖いね

  • メッセージ駆動を自然と覚えられる

イベントとしての「メッセージを送る」「メッセージを受ける」が、それぞれ1つのブロックで表現されるので非常に使いやすい。他のオブジェクトに影響を与えたい場合はメッセージを使うことになるのでイベントを受け取るということが自然と理解できてくる。メッセージは複数のオブジェクトで並行して受け取れるので、並列プログラムも気が付いたら組んでいたみたいなことが起きる。スゴイ

  • 「もし~なら」の条件には条件判定のブロックしか入れられない

ブロックのピースに形があってブロックの形が違う組み合わせは入れることができない。視覚的にできないことが示されるので、初心者にありがちなシンタックスエラーの洗礼を避けることができる。しあわせ

  • ブロック塊をクリックするだけで、そのブロック全体をテストできる

実行と編集の区別がないのでブロックをクリックしたら作ってる途中でも一連の処理がバンバン走る。実行されるのはブロックの塊単位なので同じスプライト内でも他のブロック群は処理されない。ユニットテストやりやすい。ステキ

  • 作品をソースコードごと世界に向けて公開できる

Scratch公式トップページで、たくさんの作品がソースコードごと公開されていてる。「中身を見る」というボタンを押すだけでソースの編集画面になり改造することができる。改造した作品はリミックスとよばれて公開される。オープンソースソフトウェアという概念を体験する分かりやすい仕組みが整っている言語がほかにあるのだろうか

 

以上

今度は書籍みながら子供とやってみようかな

LINE BotでMiitomoもどきを作ってみた

LINE Bot流行ってますね
ビジネスアカウントの機能制限版なのに、みなさん嬉しそうでなによりです

ということで流行に便乗してLINE Bot作ってみた

Miitomoもどき
line_bot

Botに話しかけた内容を保存しておいて、他人の発言内容をランダムにチラ見せ

ほぼ拾ったコードのツギハギ
発言の保存するのにDB使ったけど、SSL証明書用意する手間に比べたら楽だよね

ソース

<?php

$json_string = file_get_contents('php://input');
$jsonObj = json_decode($json_string);
$to = $jsonObj->{"result"}[0]->{"content"}->{"from"};
$text = $jsonObj->{"result"}[0]->{"content"}->{"text"};

$url = "https://trialbot-api.line.me/v1/profiles?mids={$to}";
$headers = array(
	'X-Line-ChannelID: xxxx',
    'X-Line-ChannelSecret: xxxx',
    'X-Line-Trusted-User-With-ACL: xxxx'
);

$curl = curl_init($url);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$profileJson = curl_exec($curl);

//スタンプとか無視するためにtextに値があることをチェック
if($text != ""){

	$profile = json_decode($profileJson);
	$name = $profile->{"contacts"}[0]->{"displayName"};
	$mid = $profile->{"contacts"}[0]->{"mid"};


	$pdo = new PDO();// DB接続的な何か

	$sql = 'select * from log_line_bot order by id desc limit 50';
	$stmt = $pdo->prepare($sql);
	$stmt->execute();

	$arr_res = array();
	while($row = $stmt -> fetch(PDO::FETCH_ASSOC)) {
		if($row['mid'] != $mid){//自分以外 SQLで絞り込まないのはインデックス面倒だから
			$arr_res[] = $row;
		}
	}

	$sql = 'insert into log_line_bot (mid,name,msg) values (?, ?, ?)';
	$stmt = $pdo->prepare($sql);
	$stmt->execute(array($mid,$name, $text));

	if(count($arr_res) > 0){
		$res = $arr_res[array_rand($arr_res,1)];
		$res_text = "{$res['name']}がさっき「{$res['msg']}」って言ってましたよ";

		$response_format_text = array('contentType'=>1,"toType"=>1,"text"=>$res_text);
		$post_data = array("to"=>array($to),"toChannel"=>"1383378250","eventType"=>"138311608800106203","content"=>$response_format_text);

		$ch = curl_init("https://trialbot-api.line.me/v1/events");
		curl_setopt($ch, CURLOPT_POST, true);
		curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data));
		curl_setopt($ch, CURLOPT_HTTPHEADER, array(
		    'Content-Type: application/json; charser=UTF-8',
		    'X-Line-ChannelID: xxx',
		    'X-Line-ChannelSecret: xxx',
		    'X-Line-Trusted-User-With-ACL: xxx'
		    ));
		$result = curl_exec($ch);
		curl_close($ch);
	}
}

テーブル定義

create table log_line_bot(
id INT NOT NULL AUTO_INCREMENT,
mid CHAR(64) NOT NULL,
name VARCHAR(255) NOT NULL,
msg VARCHAR(255) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;

新入社員の皆さんへ

今日から社会人となった新入社員の皆さん、おめでとう

私も15年前、入社式を経験し社会の一員となりました

皆さんよりもほんの少し(15年だけ)先輩の私から、入社式での挨拶代わりに
伝えたいことをここに残します

これから皆さんは、会社の先輩や上司からいろいろ学び成長をしていくでしょうが
どうか目指す先を目の前の先輩や上司にしないでください

皆さんの目指す先は、もっとはるか遠くにあります

今はまだ自分に実力がなかったとしても、隣の先輩がいかに優秀に見えたとしても
自分自身の可能性を信じてください
先輩を目標にしてしまったら、きっとその先輩を超えることは一生できません

自分には世界を変える力があると本気で信じてください

皆さんが新入社員研修を終えて私たちのチームの一員として最初に行う仕事は
「先輩から与えられた課題」でも、「誰にでもできる仕事」でもなく、いつか
皆さん自身が世界を変えるための「最初の1歩」なのです

そして、始めのうちは先輩や上司が先導してくれるであろう歩みを、なるべく早く
自分のものとしてください

そうでなければ、皆さんに待っているのは「先輩の劣化コピー」です

先輩や上司の意見を真正面から否定し、恐れることなく自論を展開できる
ようになってください
ダイバーシティ(多様性)は歓迎すべきもので、私たちのチームは
先輩や上司の意見を否定することを好ましいことであるとの価値観を
もっています。安心してください

そしていつの日か私たちを老害と呼び、自分たちこそが世界を変えることが
できるんだということを示してください

私は皆さんなら、それができると信じています

入社おめでとう

1日の中のトラフィックの変動に合わせてEC2の起動台数を増減させる方法

JAWS-UG Advent Calendar 2013 4日目の投稿です
昨日は@j3tm0t0さんのg2インスタンスを使って宇宙へ行こう!です

11/2の第9回JAWS-UG大阪で発表したときにはManualScalingとして紹介した方法の解説

ゲームに限らず、アクセス数の多いブログやニュースサイトなんかでは、例えばお昼の12時からの1時間のほうが、その前後の1時間に比べて数倍のトラフィックがくることがよくありますよね

1日のピーク値にあわせてサーバを用意しておくというのはイマイチ「クラウド」っぽくありません
そこで、毎日のトラフィックの増減の予想から、指定時間でサーバを起動させる仕組みを作ってみました

なお、指定時刻でサーバを増減させる仕組みを、AWSのドキュメントではScheduled Scalingっていうらしいです。AutoScalingのコマンドで実現可能です。
詳しくはこちら

この公式のScheduled Scalingは、既に運用面も含めてAutoScaling構成になっている環境では簡単に使えるのですが、今回はあえてAutoScalingを使わない方法をご紹介します

今回ご紹介する方法には、コチラのようなメリットがあります

・サーバ減少時にTerminateではなくStop状態でサーバを保存しておける。ログ消えない
・サーバ増加時にはStop状態のサーバをStartさせる。インスタンスの作成時間を短縮
・最新プログラムをサーバへダウンロードするときは前回Stop時からの差分のみなのでわりと高速
・最新プログラムの反映を待ってからELBにサーバを組み込む

ということで、まずは全サーバに次のような起動スクリプトを仕掛けます

#!/bin/bash
#
# Auto associate Elastic IP , rsync and register ELB
#
# chkconfig: 345 98 6
# description: rsync and register ELB
# processname: rsync-elb
#
export JAVA_HOME=/usr/lib/jvm/jre
export EC2_HOME=/opt/aws/apitools/ec2
export AWS_ELB_HOME=/opt/aws/apitools/elb

# 初期化
RSYNC_SERVER=""
ELB_SERVER=""

# 自分のインスタンスIDを取得
INSTANCE_ID=$(/usr/bin/curl http://169.254.169.254/latest/meta-data/instance-id)

# インスタンスIDを元にtagを取得
TAGS=`/opt/aws/apitools/ec2/bin/ec2-describe-tags -O アクセスキー -W シークレットキー --filter "resource-id=${INSTANCE_ID}"  --region ap-northeast-1|/usr/bin/awk '{print $4,$5}'`

# スペース区切りでtagが返ってくるので配列へ
ARR_TAGS=(`echo $TAGS`)

# tagのキーとバリューが交互に入っているのでループ
for i in `seq 1 ${#ARR_TAGS[@]}`
do
  if [[ 'rsync' == ${ARR_TAGS[$i-1]} ]];then
    RSYNC_SERVER=${ARR_TAGS[$i]}
  fi
  if [[ 'elb' == ${ARR_TAGS[$i-1]} ]];then
    ELB_SERVER=${ARR_TAGS[$i]}
  fi
#  キーとバリューが交互なので1つ飛ばす
  i=`expr $i + 1`
done

if [[ $RSYNC_SERVER != "" && $ELB_SERVER != "" ]]; then
#   rsync実行
  /usr/bin/sudo -u ユーザー /usr/bin/rsync -av --update -e "/usr/bin/ssh -i /home/ユーザー/.ssh/秘密鍵 -o \"StrictHostKeyChecking no\"" --include="いろいろ" --exclude="*"  "${RSYNC_SERVER}:/コピー元ディレクトリ"  /コピー先ディレクトリ
  if [ $? -eq 0 ]; then
#   rsync成功 ELB登録
    /opt/aws/apitools/elb/bin/elb-register-instances-with-lb  ${ELB_SERVER} --instances ${INSTANCE_ID} -O アクセスキー -W シークレットキー  --region ap-northeast-1
    if [ $? -eq 0 ]; then
#      ELB登録成功 Apache起動
      /etc/init.d/httpd start
    fi
  else
#   失敗はシャットダウン
    /sbin/shutdown -h now
  fi
else
# 失敗はシャットダウン
  /sbin/shutdown -h now
fi

ttyがない状態でもsudoが使えるように下記の修正


# visudo
コメントアウト
#Defaults    requiretty

そして、次のようなマネージメントコンソールからタグを仕掛けます
scaling

rsync:rsync先のサーバのPublicDNS
elb:elbのLoad Balancer Name

次に指定時間に増減させたいインスタンスIDを指定した起動・停止用スクリプトを作成します

起動用スクリプト

vi /home/ec2-user/EC2-server-start.sh 
------------------------------------------------------------------------------
#!/bin/sh
/opt/aws/bin/ec2-start-instances  -O アクセスキー -W シークレットキー  --region ap-northeast-1 i-XXXXXXXX i-YYYYYYYY
------------------------------------------------------------------------------
chmod +x  EC2-server-start.sh

停止用スクリプト

vi /home/ec2-user/EC2-server-stop.sh
------------------------------------------------------------------------------
#!/bin/sh
# ELB切り離し
elb-deregister-instances-from-lb ELBの名前 --instances  i-XXXXXXXX,i-YYYYYYYY  -O アクセスキー -W シークレットキー   --region ap-northeast-1

# ELB切り離し後、30秒ほど時間を空ける
sleep 30

# インスタンス停止
/opt/aws/bin/ec2-stop-instances -O アクセスキー -W シークレットキー  --region ap-northeast-1 i-XXXXXXXX i-YYYYYYYY
------------------------------------------------------------------------------
chmod +x  EC2-server-stop.sh

最後にお好みの起動・停止時間をcronで設定して終わり

明日は@ar1さんです。

新人ソフトウェアエンジニアが知るべき13のこと

今年の新入社員に向けて、つらつらと書いてみた。

 

1.学び続ける覚悟を持とう

日々テクノロジーは進歩している。
エンジニアとして生きていくなら一生学び続ける覚悟が必要だ。

2.基礎を学ぼう

ここでいう基礎とは、TCP/IPやOSのファイルシステムなんかだ
基礎は新しいことを学ぶときに、きっと役に立つ。

3.リファレンスを読もう

googleで検索してblogに書かれたプログラムを無条件に信じてはいけない。
たまたま見たblogの内容が良くない方法(アンチパターン)かもしれない。
信じていいのは公式のリファレンスだけだ。

4.ソースも読もう

リファレンスが不十分だったり理解できないときは、躊躇せずソースを読もう。
たとえばPHPはC言語で書かれているが意外と読めるものだ。
ソースを読んで理解することは一人前になる通過儀礼みたいなものだと覚悟しよう。

5.「動けばいい」とは決して考えないようにしよう

君たちが作るプログラムは、必ず利用者がいる。
利用者に使ってもらえるものを作ろう。「動く」だけでは駄目なんだ。
誰にも観てもらえない映画を作る映画監督になりたいかい?

6.バグに遭遇したら、まずは冷静になろう

よく言われているが、「プログラムは思ったようには動かない。書いたとおりに動く。」は真実だ。
99%は目の前に原因がある。原因が目の前にないことは1%くらいだ。
99:1が決して逆ではないと肝に銘じよう。

7.思想を理解しよう

他人のソースを読むとき処理の内容を追うだけでなく「何故そのように作ったのか」を理解することは大切だ。
計算量を減らして負荷軽減を狙っている/不正な値が入らないようにしている/キャッシュ化することで高速化を狙っている等
コードから学ぶというのは思想を理解することに等しい。

8.良書を探そう

この本いいなと思ったらamazonで検索してみよう。
今は便利な世の中で「この商品を買った人は~」と良書っぽものが芋づる式に見つかる。

9.モチベーションを意識しよう

エンジニアとして学び続けるのは時として大変だ。
行動を起こそうとする源、すなわちモチベーションを意識しよう
朝、鏡を見るときに「自分はなぜエンジニアになったのか?」と問いかけるのもいい
君たちのモチベーションを手っ取り早く上げてくれるはずだ

10.勉強会やコミュニティに参加しよう

会社だけでなく外の風に触れることも時には必要だ。
新しい刺激はモチベーションの維持にもつながる。

11.アウトプットしよう

勉強会でLTをするのでもblogを書くのでもなんでもいい。
なにかをアプトプットするだけで世界は大きく変わる。

12.コミュニティ疲れ・勉強会疲れを感じだたら距離を置こう

「疲れ」の意味がわからないうちは気にしなくていい。
これがそうかな?と思ったら立ち止まろう。もう君は大丈夫だ。
また気が向いたり考え方が変わったら参加してみるといい。

13.趣味や夢中になれるものを持とう

できたら技術以外のものが望ましい。
どんなものであれ君たちの人生を豊かにしてくれる。

CentOSでTimeMachineサーバを作る

Macを何台か買ったのを機に、その辺に余っていたハード使ってTimeMachineサーバを立てたメモ

環境

CentOS6.3(Minimalでインストール)

必要なパッケージを入れる


yum -y update
yum -y install wget cracklib-devel openssl-devel quota-devel libtool automake autoconf db4-devel pam-devel tcp_wrappers-devel libgcrypt-devel avahi-dnsconfd avahi-devel libacl-devel openldap-devel make lynx

nss-mdnsのインストール

avahiで使うので導入する


cd /usr/local/src
wget http://0pointer.de/lennart/projects/nss-mdns/nss-mdns-0.10.tar.gz
tar xzvf nss-mdns-0.10.tar.gz
cd nss-mdns-0.10
./configure
make
make install

vi /etc/nsswitch.conf
hostsの行を下記の用に書き換え
hosts:      files mdns4_minimal [NOTFOUND=return] dns mdns4

netatalkのインストール


cd /usr/local/src
wget http://prdownloads.sourceforge.net/netatalk/netatalk-3.0.2.tar.gz
tar xzvf netatalk-3.0.2.tar.gz
cd netatalk-3.0.2
./configure --with-init-style=redhat-sysv
make
make install

バックアップを取りたいmacごとのアカウントの作成


useradd user1
passwd user1
su user1
mkdir ~/TM
exit

useradd user2
passwd user2
su user2
mkdir ~/TM
exit

以下、必要な台数分繰り返し

netatalkの設定


vi /usr/local/etc/afp.conf

[Global]
; Global server settings
vol preset = default_for_all_vol

[default_for_all_vol]
file perm = 0600
directory perm = 0700

[user1TimeMachine]
path = /home/user1/TM
valid users = user1
time machine = yes
vol size limit = 100000

[user2TimeMachine]
path = /home/user2/TM
valid users = user2
time machine = yes
vol size limit = 100000

以下、必要な台数分繰り返し

iptablesの設定


vi /etc/sysconfig/iptables
-A INPUT -m state --state NEW -m tcp -p tcp --dport 548 -j ACCEPT
-A INPUT -m state --state NEW -m udp -p udp --dport 548 -j ACCEPT
-A INPUT -m state --state NEW -m udp -p udp --dport 5353 -j ACCEPT
service iptables restart

netatalkの自動起動


chkconfig netatalk on
service messagebus start
service avahi-daemon start
service netatalk start

これでmac側のTimeMachineのディスク選択に表示されるはず
mac側で見えるようになるまで時間がかかることもあるかも
vol size limitはHDDの容量と相談