読者です 読者をやめる 読者になる 読者になる

requirements.txt を書いておく

Python

いつも忘れるので。

Python で作ったアプリが依存するライブラリは requirements.txt に記述しておく。

改行区切りで次のように。

requests==2.0.1

pip freeze で出力されるのが Python カレントな環境でインストールされているライブラリとバージョン。

pip install -r requirements.txt でインストールする。

参考

2012.05版 Python開発のお気に入り構成(ポロリもあるよ) - YAMAGUCHI::weblog

似た色を求める

Python

似た色をざっくりともとめる

色の科学といいますが、いろんなものがありますね。 RGBCMYKHSV色空間、HSBとか。

今回は、js の Canvas に画像情報をコピーしてきて、 線形探索で 1 ピクセルずつ色の判定をして一番使われている色を求めるということをするための前身としてどういうロジックにするか考えてみたときのメモです。

いくつか色のサンプル(基準色)を RGB で用意しておき、比較元の色をそれらとつきあわせて最も似た色を求めます。 基準とするのは次。

kijun = {
    '1': [0,0,0],
    '2': [0,0,255],
    '3': [0,255,0],
    '4': [255,0,0],
    '5': [0,255,255],
    '6': [255,0,255],
    '7': [255,255,0],
    '8': [255,255,255],
}

これを次のロジックで。

def main():
    # 比較する色
    mr = 200
    mg = 100
    mb = 100
    # キーに kijun のキー、値に色の2点間の距離
    distant_dict = {}
    for key in kijun:
        r,g,b = kijun[key]
        distance = math.sqrt((mr-r)*(mr-r)+(mg-g)*(mg-g)+(mb-b)*(mb-b))
        print(distance, kijun[key])
        distant_dict[key] = distance
    # 最も距離が近い(値が小さい)順に並べる
    srt_distance_dict = sorted(distant_dict.items(), key=lambda x:x[1])
    key,value = srt_distance_dict[0]
    # kijun[key] が判定された似た色
    print(key, kijun[key])

    # PIL で比較用に画像を作る
    # 画像のサイズ
    screen = (100,100)
    # 画像の背景色(RGB)
    bgcolor = tuple(kijun[key])
    # 保存するファイル名(ファイル形式は、拡張子から自動的に判別する)
    filename = "kijun.png"
    img = Image.new('RGB', screen,bgcolor)
    img.save(filename)
    # 画像の背景色(RGB)
    bgcolor = (mr,mg,mb)
    # 保存するファイル名(ファイル形式は、拡張子から自動的に判別する)
    filename = "original.png"
    img = Image.new('RGB', screen,bgcolor)
    img.save(filename)

基準の色の組み合わせを作る&色のサンプルは次で作る

def main():
    rgb_list = [
        0,64,127,190,255
    ]
    for c in itertools.product(rgb_list, rgb_list, rgb_list):
        print(c)
        # 画像のサイズ
        screen = (100,100)
        # 画像の背景色(RGB)
        bgcolor = c
        # 保存するファイル名(ファイル形式は、拡張子から自動的に判別する)
        filename = "r%d_g%d_b%d.png" % (bgcolor[0],bgcolor[1],bgcolor[2])
        img = Image.new('RGB', screen,bgcolor)
        img.save(filename)

参考サイト ActionScript入門Wiki - 近似色を探す - @ウィキモバイル

おわり。

LOAD DATA INFILE で項目を手動マッピングする

MySQL

LOAD DATA INFILE で手動マッピングする

LOAD DATA INFILE で DBサーバローカルのファイル「@@LOAD_FILE@@」(sed -e "s?@@LOAD_FILE@@?${LOAD_FILE}?" とかで置換します)からロードする。
読み込むデータファイルの項目に変数名をつけて、DB の項目と手動でマッピングすることもできる。

実行コマンド

mysql -u ${MYSQL_USER} -p${MYSQL_PASS} -D ${MYSQL_DB} -h ${MYSQL_HOST} -e"${LOAD_SQL}"

実行するSQL ${LOAD_SQL}

SET autocommit=0;

BEGIN;

LOAD DATA INFILE "@@LOAD_FILE@@" 
IGNORE
INTO TABLE UserMaster
FIELDS 
    TERMINATED BY ',' 
    ENCLOSED BY '"' 
    ESCAPED BY '\\' 
LINES 
    STARTING BY '' 
    TERMINATED BY '\n' 
(
     @user_id
    ,@user_name
    ,@user_kana
    ,@zip_code
    ,@address1
    ,@address2
    ,@telephone
)
SET
     user_id=@user_cd
    ,user_name=@user_name
    ,zip_code=@zip_code
    ,address=concat(@address1,' ',@address2)
    ,telephone=@telephone
;

SHOW WARNINGS ;

COMMIT;

WebView の DOM 操作

Android

Android の WebView 動作

やりたいことは、Android のネイティブアプリのコンポーネントandroid.webkit.WebView」で読み込んだ HTML のページに対して DOM 操作を行いたい。

動作環境

Device SDK
Nexus S(Android 4.1.2) Android 4.0.3 Google APIs

検証方法

適当なドメインで公開されている単純な HTML で DOM操作をしてみる。

こんな感じの HTML をどこかに公開する。

<h1>TEST PAGE</h1>
<form action="/" method="GET" id="form1">
    <input type="hidden" name="param1" value="hgoehoge">
    <input type="submit">
</form>

AndroidManifest.xml で次の Permission を設定する。

android.permission.INTERNET

layout 配下に適当な名前で次の画面を作る。

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <WebView android:id="@+id/web_view"
             android:layout_width="fill_parent"
             android:layout_height="0dip"
             android:layout_weight="1"
            />
    <Button android:id="@+id/button"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Button"
            android:drawablePadding="10dip"
            />

</LinearLayout>

Activity クラスで画面制御。

package com.example.test_android_ui;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebView;
import android.widget.Toast;

public class MyActivity2 extends Activity implements View.OnClickListener {

    WebView webView = null;

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 上記のレイアウトを設定する
        setContentView(R.layout.webviewtest);

        // 上記の公開している URL を指定する
        webView = (WebView) findViewById(R.id.web_view);
        String url = "http://hogehoge/test.html";
        webView.loadUrl(url);

        // Javascript を有効に
        webView.getSettings().setJavaScriptEnabled(true);

        // DOM 操作を行うネイティブボタンのイベントを登録する
        findViewById(R.id.button).setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {

        int id = v.getId();
        switch (id) {
            case R.id.button:
                // Javascript 実行
                String formAction = "http://yahoo.co.jp/";
                final String script = String.format("javascript:document.getElementById(\"form1\").action = \"%s\"", formAction);
                Toast.makeText(v.getContext(), String.format("Changed form action. %s", formAction), Toast.LENGTH_SHORT).show();
                webView.loadUrl(script);
                break;
            default:
                break;
        }
    }
}

ネイティブボタンを押下せずにサブミットすると自身のドメインのトップに遷移する。
自身のネイティブボタンを押下してからサブミットすると yahoo.co.jp へ遷移する。
異なるドメインへのアクションの変更が可能っぽい。

未検証

  • HTTPS のページで DOM 操作可能かどうか
  • 制限についての詳細(WebKit の許す範囲で制限なしかどうか)

GCM のサンプルを動かしたメモ

Android

■GCM を使うための事前準備

  • GoogleAPI コンソールでプロジェクトに GCM API を使用する設定 このとき、プロジェクトキーAPIキーがわかる。あとで使うので控えておく

■GCM サーバ(Google)を使う

  • <GCM 初期処理>

    • GCMライブラリの登録処理を呼び出す、このときさきほどのプロジェクトキーが必要
    • GCMサーバで登録IDが発行され、Android アプリに通知される
    • 登録IDサードパーティーサーバ(こちらのサーバ)に送信して DB などに永続保存しておく
      (この登録IDGoogleサーバによって定期的にリフレッシュされるので再度呼び出されるように設計しておく!)
  • <GCM 送信処理>

    • APIキー登録IDを以て送信先端末を指定して、PUSH 通知を行う 1,000 程度までなら一斉送信可能?要検証

■GCM で気をつけておくこと

  • セキュリティ的な懸念は、登録IDが定期的にリフレッシュされる、ということろが Google が想定している一つの回避方法?(セッションのリフレッシュのような)

  • プロジェクトキーAndroid アプリの逆コンパイルでハックされるが、それだけでは勝手にPUSH 通知はできない。APIキーもあわせて必要。APIキーを知り得るためには、Google アカウントでログインが必要。

  • サードパーティーAPPサーバで簡単にブロードキャストしまくる API を作るとダメ
    悪意をもった第三者が API を呼ぶだけで PUSH 通知されてしまう

  • ロジック的には、Android アプリとサードパーティーAPPサーバでの登録IDの同期がちゃんととれるかが設計のキモ

  • サンプルを動かしてソースをみると単純なのですぐわかる。SDK Manager マネージャから Extras > Google Cloud Messaging for Android Library をインストール。次のようなパスにサンプルコードがあるので、設定だけ変更するとすぐ動作する。

      /Users/user/sdks/adt-bundle-mac/sdk/extras/google/gcm/samples/gcm-demo-appengine
      /Users/user/sdks/adt-bundle-mac/sdk/extras/google/gcm/samples/gcm-demo-client
      /Users/user/sdks/adt-bundle-mac/sdk/extras/google/gcm/samples/gcm-demo-server
    

    gcm-demo-appengine は GAE でのサンプルっぽい。まだためしていないけどそんな難しくはないと思う。

    gcm-demo-serverサーブレット。オンメモリなのでサーバ停止したりすると GCM にはデバイス登録しているのにこっちのサーバにはデバイス登録していない状態とかなって、Androidアプリとサードパーティーサーバの間でデータの同期がとれていない状態とかなっちゃうので注意。

    gcm-demo-clientAndroidアプリ。すごくシンプル。

■参考サイトとか

1. GCM をはじめよう - ソフトウェア技術ドキュメントを勝手に翻訳

2. GCM アーキテクチャの概要 - ソフトウェア技術ドキュメントを勝手に翻訳

3. GCM デモ アプリケーション - ソフトウェア技術ドキュメントを勝手に翻訳

4. GCM 上級者向けトピックス - ソフトウェア技術ドキュメントを勝手に翻訳

5. C2DM から GCM へのマイグレーション - ソフトウェア技術ドキュメントを勝手に翻訳

MySQL コマンドメモ

MySQL

□DBログイン

mysql -u ${MYSQL_USER} -p${MYSQL_PASS} -D ${MYSQL_DB} -h ${MYSQL_HOST} -e"show tables;"

→パスワードはかかんほうがいい。history にパス残るからね。

□DB作成

create database [db] default character set utf8;

□ユーザ作成

MySQLのユーザ管理

CREATE USER [user]@[host] IDENTIFIED BY '[PASSWORD]';

grant [create, alter, drop, index, select, update, insert, delete] on [db].[table] to '[user]'@'[host]';

□ユーザ確認

select user,host from mysql.user;

□ユーザ権限確認

SHOW GRANTS FOR [user];

□ユーザ権限削除

revoke create on [db].[table] from '[user]'@'[host]';

□ダンプ エクスポート/インポート

mysqldumpでバックアップ&復元 - phpspot

mysqldump -u[user] -p -h [host]

source [dump_path]

□コマンド例

create database devdb default character set utf8;

CREATE USER devuser@'%' IDENTIFIED BY 'devuser';

grant create, alter, drop, index, select, update, insert, delete on devdb.* to 'devuser'@'%';

git コマンドメモ

Git
  • 今いるブランチを確認(* がついているもの)

    git branch
    
  • 今いるローカルブランチからローカルに別ブランチを作る

    git branch [local_branch]
    
  • ローカルの別ブランチへ移動

    git checkout [local_branch]
    
  • ローカルにブランチを作ってリモートリポジトリをチェックアウト

    git checkout -b [local_branch] [remote_alias]/[remote_branch]
    
  • ローカルブランチからリモートブランチを作成して push

    git push origin hogefuga
    
  • git の変更一時保存

    git statsh save "message"
    
  • git の一時保存一覧参照

    git stash list
    
  • git の一時保存から戻す

    git stash pop stash@{0}
    
  • commit 済みのファイルをリポジトリから消す

    git rm --cached file
    
    git rm -fr --cached /path/to/folder
    
    ※.gitignore にフォルダ、ファイルを追加すれば次からは git 管理外にできる
    
  • リビジョンを1個前に戻す。working directoryは無変更

    git reset HEAD^ --soft
    
  • リビジョンを3個前に戻す。working directoryも戻す

    git reset HEAD~3 --hard
    
  • 特定リビジョンに戻す

    git reset [revision] --hard
    

指定したリビジョンまで戻す。 指定したリビジョンは消えない。

  • 2個前のコミットのみをなかった事にする

    git revert HEAD~2
    
  • git add を取り消すのにも使える。git add の取り消しはアンステージという

    git reset file_name
    
  • First Commit を rebase する

    git rebase -i --root
    
    fixup してコミットを1つにまとめたり
    
  • Git で不要になったローカルブランチの削除

    git branch -d hoge
    
  • Git で不要になったリモートブランチの削除

    git push origin :hoge
    
  • リモートブランチの一覧をみる

    git remote -v
    
  • リモートブランチ追加

    git remote add remote-name url
    
    git remote add -f remote-name url
    
    こっちはフェッチする
    
  • リモートリポジトリから変更を取り込むときに比較する

    git fetch origin mater
    git diff FETCH_HEAD
    
    git difftool FETCH_HEAD #もできる
    
  • ローカルブランチ間のdiff

    git diff [local_branch]
    
  • ローカルの merge で diff

    これのやりかたがわからない・・・
    やり方教えください。。。
    
    git merge --no-commit --no-ff [local_branch]
    これでコミットなしでマージして比較するくらい
    git diff HEAD で確認できました。
    
    そもそもこれがなぜやりたいかというと、
    開発用ブランチ(ローカル、リモート)で開発用の設定を
    コミットしたものを取り込みたくなくて、
    それをスマートにやる方法が分からずに、
    diff みて手動修正しようとしています。
    
    →git merge のときに、--no-commit --no-ff で手動でマージして
    コミットすれば次からは差分としては認識されなくなるので
    この方法であれば開発用ブランチの設定を取り込まず、
    一度だけ手動でマージすれば次からは意識しなくてよくなります。
    ただし、該当箇所を開発用ブランチで修正するとコンフリクトするので注意。
    あと、履歴に残らないので激しく非推奨ですね。
    正しくはどういうフローでやるべきことなんだろうか・・・。
    
  • git リモートリポジトリ作成

    git init --bare --shared=true
    
  • git を ssh で使用

    git remote add <alias> ssh://<username>@<hostname>/path/to/
    
    注意としては、ssh config に使用する鍵ファイルを指定しておくこと
    
    Host 127.0.0.1
        HostName        127.0.0.1
        IdentityFile    ~/.ssh/hogehoge.pem
        User            sshuser
    

変更を一時的に退避!キメろgit stash - Qiita [キータ]

git addの取り消しと、コミット済みのファイルを除外する方法 - kanonjiの日記

git reset と git revert についてメモ - u16suzuの blog

Git で不要になったローカルブランチ・リモートブランチの削除 - sotarokのお勉強

gitでマージとかdiffとかコミットまとめてpushするとか - ikeike443のブログ

transitive.info - git merge 使い方

図で分かるgit-mergeの--ff, --no-ff, --squashの違い - アジャイルSEを目指すブログ