WordPress Plugin作成 〜アンケート集計〜

アンケート集計方法を実現するための方法を考え実装に着手します。

アンケート集計

ここ最近は、WordPressプラグインの作成をいやっていて、機能としては下のようなものを考えています。

  1. ダッシュボードにて、アンケートを作成
  2. ブログに挿入
  3. 主計結果をダッシュボードに表示

現状の実装

今までの経緯はこちらのリンクに記載しました。

とりあえずは、作成している(2020-01-25)時点でのプラグインを起動した時の動作です。

現状での実装

・ユースケースについて

  1. WordPressプラグインをインストール
  2. プラグインを有効化
  3. ダッシュボードでアンケートを作成
  4. アンケートの挿入位置の指定(各アンケート)
  5. アンケートのDB登録 ※未実装

現状の悩みどころ

アンケートの挿入位置をWordPressの(HTML)クラス名(wrap, primary, entry-header ...)で指定します。大まかに真ん中らへんとか下の方とか。。。
これに関して、ダッシュボード上で確認する方法を実装していません。そして実装する気も。。。
というのは、使用するテンプレートなどにより挿入いちをコントロールできるように挿入位置を下のように「選択」 or 「指定」できるようになっています。

なので、下手に確認用の実装を入れない方が良いと思いました。。。

アンケート集計について

色々と調査、検討をしてみたところ以下のような方法が良いであろうと思いました。

  1. 各アンケート(質問)をDBに登録
  2. 各アンケートの回答数(ボタンのクリック数)を登録
  3. ボタンが押下された回数をDBに登録
  4. 各質問をクロス集計できるように設定を入力できるフォームを作成する

そしてこの「クロス集計する」ための設定入力が必要です。しかし。。。その実装のイメージが難しく。。。どのように実装するかわからない状態です。

ここはちょっと頭をひねる必要がります。。。

でわでわ。。。



WordPress 処理解析 ~index.phpを眺める~

WordPressにログイン機能を追加して自サイトでのWebサービスを作成しようと考えています。

しかしながら、WordPressの中身に関してほぼ理解していないので調べようと思いました。

WordPress解析

現段階でわかっているのは以下のようなことです。1. 「テーマ」でブログ表示アプリケーションが動いている

  1. テーマフォルダ内のindex.phpがメイン処理を行う
  2. phpはHTMLを出力する
  3. DBはMySQLを使用している

これ以外はわかっていません。

どこから着手?

まずはメイン処理のindex.phpから解析していきます、使用しているのはtwentyseventeenというテーマです。なので以下のフォルダにあるindex.phpを眺めます。フルパスです。
/wp-content/themes/twentyseventeen/index.php

ヘッダ部分の解析

このメソッドで、ヘッダー部分のphpを読み込みます。調査で参照するサイトはWordPressのサイトです。
説明書きには以下のような内容が記載されていました。

現在のテーマディレクトリの header.php テンプレートファイルを読み込みます。名前(name)を指定すると、指定したヘッダー header-{name}.php を読み込みます。

つまり、下のようにファイルを配置した時に、get_header()というコードは「header.php」を読み込みます。
そして、get_header('test')というコードは「header-test.php」を読み込みます。

実際のコード(header.php)

/**
 * The main template file
 *
 * This is the most generic template file in a WordPress theme
 * and one of the two required files for a theme (the other being style.css).
 * It is used to display a page when nothing more specific matches a query.
 * E.g., it puts together the home page when no home.php file exists.
 *
 * @link https://codex.wordpress.org/Template_Hierarchy
 *
 * @package WordPress
 * @subpackage Twenty_Seventeen
 * @since 1.0
 * @version 1.0
 */

get_header('test'); ?>

これはindex.phpの初めの部分で、ヘッダー(header.php)を表示する処理です。

そして、以下のコード(HTML)が続きます。

<div class="wrap">
    <?php if ( is_home() /*&& ! is_front_page()*/ ) : ?>
        <header class="page-header">
            <h1 class="page-title"><?php single_post_title(); ?></h1>
        </header>
    <?php else : ?>
    <header class="page-header">
        <h2 class="page-title"><?php _e( 'Posts', 'twentyseventeen' ); ?></h2>
    </header>
    <?php endif; ?>

このコードは、画面(HTML)のヘッダ<header>部分を出力する処理が混ざったPHPコードで、HTML文書の中(間)にPHPでの処理結果をHTMLとして出力します。
上のコードのif〜esle〜endifの部分は各条件に合う部分をHTMLに出力します。

画面のメインコンテンツ部の解析

そして画面(HTML)のメイン部分を出力するのが下のコードです。

   <div id="primary" class="content-area">
        <main id="main" class="site-main" role="main">

            <?php
            if ( have_posts() ) :

                /* Start the Loop */
                while ( have_posts() ) : the_post();

                    /*
                     * Include the Post-Format-specific template for the content.
                     * If you want to override this in a child theme, then include a file
                     * called content-___.php (where ___ is the Post Format name) and that will be used instead.
                     */
                    get_template_part( 'template-parts/post/content', get_post_format() );

                endwhile;

                the_posts_pagination( array(
                    'prev_text' => twentyseventeen_get_svg( array( 'icon' => 'arrow-left' ) ) . '<span class="screen-reader-text">' . __( 'Previous page', 'twentyseventeen' ) . '</span>',
                    'next_text' => '<span class="screen-reader-text">' . __( 'Next page', 'twentyseventeen' ) . '</span>' . twentyseventeen_get_svg( array( 'icon' => 'arrow-right' ) ),
                    'before_page_number' => '<span class="meta-nav screen-reader-text">' . __( 'Page', 'twentyseventeen' ) . ' </span>',
                ) );

            else :

                get_template_part( 'template-parts/post/content', 'none' );

            endif;
            ?>
        </main><!-- #main -->
    </div><!-- #primary -->

そして、曲者になるコードがget_template_partget_post_formatです。

get_template_part

参考サイトには下のような説明があります。

テンプレートパーツ(ヘッダー、サイドバー、フッターを除きます)をテンプレートへ読み込みます。これにより、テーマがコードのセクションを再利用すること、また子テーマが親テーマのセクションを置き換えることが容易になります。
テーマの $slug で指定したテンプレートパーツをインクルードします。$name が指定された場合は、そのパーツの個別版をインクルードします。テーマに {$slug}.php ファイルがなければ何もインクルードしません。
$name パラメータの値は、例えばファイル "{slug}-special.php" をインクルードしたければ "special" にします。

上で呼ばれている処理は以下のような形で呼ばれています。
get_template_part( $slug, $name );
なので、上の説明にある以下の部分がこのコードの説明部分になります。

テーマの $slug で指定したテンプレートパーツをインクルードします。$name が指定された場合は、そのパーツの個別版をインクルードします。テーマに {$slug}.php ファイルがなければ何もインクルードしません。
$name パラメータの値は、例えばファイル "{slug}-special.php" をインクルードしたければ "special" にします。

呼び出し部分はget_template_part( 'template-parts/post/content', get_post_format() );
そして、テーマフォルダ(template-parts/post/content)を見てみると。。。

content.phpというファイルがあります。これが読み込まれているであろう。と目星をつけます。
※はっきりさせるときはこのファイルの中身を見ます。が、これは実装する時に眺めようかと思います。(あてになりませんが(笑))

そして、get_post_format()の部分ですが、これも参考サイトを参照します。

投稿記事の投稿フォーマットを返します。 これは通常ループ内で呼び出されますが、投稿IDが提供されていれば、どこでも使うことができます。

ちなみに、上のこーどでは引数がありませんので、さらに下のある説明

のように引数なし=初期値 →「現在のループ記事」つまりは、「the_post」などで取得できる記事の投稿フォーマットということになります。
フォーマットの種類は以下の通り。

aside
chat
gallery
link
image
quote
status
video
audio

ちょっと長くなったのでここら辺で失礼いたします。

でわでわ。。。



RPi EJDK install 〜ラズパイにJavaSE Embeddedのインストール〜

今回は、JavaSE Embedded(EJDK)をインストールします。

関連記事

EJDKのダウンロード
RPiコマンドメモ -> ラズパイにSSH接続、ファイル送信

参考サイトはオラクルのJavaSE Embeddedインストールです。英語なので翻訳して読みます。

Step1:通常のJDKインストール

参考サイトでは、通常のJDKがインストールされている必要があると書いてあるのでJava8のインストールを行います。
参考サイトはこちらです、ラズパイフォーラムページです。
前提として、今回のJavaSE EmbeddedはJava8です。
jdk-8u231-linux-arm32-vfp-hflt.tar.gz
jdk-8XXXXと書いてあるものはJava8です。

そして、JavaSE Embeddedは8が最新で最後になるらしい。。。です。

なので、通常のJava8をインストールします。OpenJDKを使用します。
なので、ラズパイにログインしてから以下のコマンドを叩きます。
sudo apt-get install -y galternatives openjdk-8-jdk

そして、インストールできたか確認します。
java -version

確認が取れたら、JavaSE Embedded(EJDK)のインストール準備が完了です。(スペックなどは各自で確認してください)

EJDKインストール

今回はラズパイのドキュメント直下にインストールディレクトリを作成します。
~/Javaというディレクトリを作成します。「~/」というのはログインしているユーザーのドキュメント直下という意味になります。
つまりユーザー「pi」でログインしているのであれば「/home/pi/Java」というディレクトリを作成します。

mkdir ~/Javaというコマンドで作成します。
そして、mvコマンドでインストールするファイルを移動します。

そして、インストールファイルを解答します。

gunzip ファイル名(.gzでも良い)とコマンドを叩くと、指定ファイルもしくは(.gz)そのディレクトリにある全てのgzファイルを解凍します。

同様にtarコマンドで解凍します。
tar -xvf ファイル名

環境設定ファイル(環境変数)

参考サイトはこちらです、ラズパイフォーラムページです。

こちらのページには以下のような記述がありました。

クイックガイド
ただシステムを実行する必要がある性急な人のために、ここであなたができることがあります:
すべてのグローバル環境変数、つまりすべてのユーザーに影響する変数を/ etc / environmentに入れます
このファイルはシェルではなく PAMによって読み取られることに注意してください。ここではシェル拡張を使用できません。たとえば、MAIL = $ HOME / Maildir /は機能しません!
PAMが処理できる些細なケース以外に、すべてのユーザーの環境を構成する方法の問題に対する、シェルに依存しない、ログインに依存しないソリューションはありません。
すべての一時的なシェル設定(エイリアス、関数、シェルオプション)を〜/ .bashrcに入れます
すべての環境変数を〜/ .profileに入れます
ファイル〜/ .bash_profileを作成または編集し、コマンドを含めます。

なので、「evironment」ファイルにEJDKのパスを設定します。
sudo nano /etc/environment
EJDK_HOME=/home/pi/Java/ejdk1.8.0_211/bin

そして、上記でインストールしたJDK(EJDKではない)を参照するように環境変数のJAVA_HOMEを設定します。
</etc/environment>

JJAVA_HOME=/usr/lib/jvm/java-8-openjdk-armhf/bin
EJDK_HOME=/home/pi/Java/ejdk1.8.0_211/bin

jrecreate.sh --help実行結果

JREの生成

参考ページ(サイト)はオラクルのJRE生成ページです。

そして、JREの生成で実行するコマンドはExample3のコマンドを実行します。

JavaFX controls and Java SE locales added to server JVM and compact3 profile.

% installDir/ejdk<version>/bin/jrecreate.sh \
    --dest /tmp/exampleJRE2 \
    --profile compact3 \
    --vm server \
    --extension fx:controls \
    --extension locales 

インストールしたいのはJavaFXのコントロールとJVMサーバーなので。。。
<実際に実行したコマンド>
※「(バックスラッシュ)」は改行しても改行したこと(Enterキーを押したこと)にしない(エスケープする)ためにつけています。

cd $EJDK_HOME
bin/jrecreate.sh --dest /tmp/exampleJRE2 \
    --profile compact3 \
    --vm server \
    --extension fx:controls \
    --extension locales

そして、実行して見た所以下のようなエラーが出ました。

JREの作成に失敗しました。ターゲットlinux_arm_sfltはVM serverをサポートしていません。

改めてヘルプを見ると色々と修正する必要がありました。。。

使用方法: jrecreate --help | --dest  [options]
オプションは次のとおりです:
  -?, -h, --help             このヘルプ・メッセージを表示します。
  -d, --dest           Javaランタイムのターゲット・ディレクトリを指定します。
  --ejdk-home          ejdkディストリビューションのルートのパスを指定します。
  -g, --debug                Javaレベルのデバッグ・サポートを組み込みます。
  -k, --keep-debug-info      JRE生成中にクラス/jarファイルからデバッグ属性を除去しません。
                               署名付きjarファイルには適用されません。
  -n, --dry-run              リクエストされた操作を試験的に実行します。
  --no-compression           jarファイルを圧縮しません。署名付きjarファイルには適用されません。
  -p, --profile        オプション。プロファイルのいずれかを生成対象として指定します。
                               有効なプロファイル名: compact1、compact2、compact3。
                               指定しない場合、完全なJREが作成されます。
  -v, --verbose              詳細な出力を有効にします。
  --vm               ターゲット・ランタイムで使用するVMを指定します。
                               有効なオプション: minimal、client、server、all。
                               デフォルトは、compact1とcompact2に対してはminimal、compact3に対してはclient、JREに対してはallです。
  -x, --extension      生成されるランタイムに含めるオプション・コンポーネントを1つ以上選択します。
                               複数のコンポーネントを選択するために、このオプションには単独の値だけで
                               なく、カンマ区切りリスト(スペースなし)も指定できます。
                               有効な拡張機能:
                                   sunpkcs11 - Cryptographic Token Interface Standard (PKCS 11)プロバイダ
                                   gcf - 汎用接続フレームワーク・オプション・パッケージ(JSR-197)
                                   locales - すべてのJava SEロケール
                                   charsets - 拡張文字エンコーディング
                                   sunec - 楕円曲線暗号方式プロバイダ
                                   nashorn - Nashorn JavaScriptエンジン

結局のところは以下のようなコマンドになりました。

% installDir/ejdk<version>/bin/jrecreate.sh  --dest /tmp/ejre8 --extension locales 

生成したJREは/tmp/ejre8というフォルダに出力されるようにコマンドを実行しました。

どうやらJREの生成ができたようです。(Fullversion)

でわでわ。。。



数学への挑戦 第二弾〜まとめ1:数理モデルxプログラミング〜

前回は確率変数の足し算を行いました。しかし、イマイチな感じです。。。
なので、これらをまとめるために「樹形図」を使用して今までの学習したものをまとめようと思います。

今までのまとめ

  1. 傘を持っていくべきか、持っていかないべきか?
  2. 数理モデルをJavaで表現する
  3. 喫煙率を求めるモデル
  4. コインの表裏(確率変数)
  5. コインの表裏(期待値と分散)
  6. 卒業までに彼氏ができる確率
  7. 確率変数の足し算

使用する書籍は下のものです。

1.傘を持っていくべきか、持っていかないべきか?

ここでは、傘を持っていくことの嫌度(損失)を-2とし、雨に濡れることの嫌度(損失)を-10として計算式(数理モデル)を作成しました。
ポイントは「全てのケースに対する結果を数値化する」と言うところでした。
具体的には以下のようになります。

<前提>
行動の選択肢は「傘を持ってくる」 or 「持ってこない」の2つ
<嫌度>
雨に濡れることの嫌度 = -10(濡れないとき = 0)
傘を持ってくることの嫌度 = -2
<確率>
雨の確率: 60% = 0.6
晴れの確率: 40% = 0.4

上記のようになります。

平均的な損失を求める

上でまとめたものを表にすると下のようになります。
<天気(確率 : 嫌度)>

傘を持ってくる 持ってこない
Ⅰ 晴れ(0.4 : -2) Ⅲ 晴れ(0.4 : 0)
Ⅱ 雨(0.6 : -2) Ⅳ 晴れ(0.6 : -10)

これらの結果(Ⅰ -> Ⅳ)から平均を求めると

<傘を持ってきた場合の損失>
Ⅰ + Ⅱ + Ⅲ + Ⅳ = (0.4 - 2) + (0.6 - 2) = -0.8 - 1.2 = -2のようになります。
<傘を持ってこない場合>
Ⅰ + Ⅱ + Ⅲ + Ⅳ = (0.4 0) + (0.6 -10) = 0 - 6 = -6

2.数理モデルをJavaで表現する

そして、変数にできるものを変数化(一般化)してやるとしたのようになる。

降水確率60% = 0.6 = p : 晴れの確率40% = 1 - p
雨に濡れる嫌度 = -10 = -c : 傘を持ってくる嫌度 = -c/5

雨の場合
(0.4 x -2) + (0.6 x -2) = -2 => ((1-p) x -2) + (p x -2) = (-2 + 2p) + (-2p) => 平均は「-2」
晴れの場合
(0.4 x 0) + (0.6 x -10) = -6 => ((1-p) x 0) + (p x -10) = 0 + -10p = 平均は「-10p」

ここで「雨に濡れる嫌度が1/5」になっているのでこれも変数化します。変数名は「a」にします、そして割合なので0 < a < 1」になります。まとめると以下のようになります。

雨の確率 = p : 晴れの確率 = 1 - p
雨に濡れる嫌度 = -c : 傘を持ってくる嫌度 = -ac

これを式にすると。。。

傘を持って来た時
((1-p) x -ac) + (p x -ac) = (-ac + pac) + (-pac) = -ac
傘を持ってこなかった時
((1-p) x 0) + (p x -c) = (0 - pc) = -pc

結果として、

a > p

なので、「雨の確率がa(傘を持ってくる嫌度の割合)より大きい時」ということになります。

3. 喫煙率を求めるモデル

回答のランダム化で、出た結果のグループ分けを行う
1.Aグループ = コインで表が出た人
2.Bグループ = コインで裏が出た人
3.Cグループ = Aの中でタバコを吸った人
4.Dグループ = Bグループでタバコを吸った人

実際に行ってはいないけれど「仮に」喫煙者が400人いたとするのであれば、喫煙率は「400 / 1000 = 40%」になるので「コイントスでA, Bグループ(500人ずつ)にいる喫煙者社の割合(確率)も40%で200人ずついることになる。

求めるべき値の喫煙者数=400は下のようにして求めることができる。

|B U C| = |B| + |C|
|B U C| - |B|=  |C| 両辺から|B|を引く

下の値を使用して計算すると。。。
|B U C|=600, |A|=500, |B|=500
次のような計算式で求めることができる
|B U C| - |B| = |C| = 100
|C| / |A| = 100 / 500 = 0.2 = 40%
となる。。。つまり喫煙者の割合は「40%」になり「仮定」で示した「400」と言う数値も正しいものであると言える。

と言うような感じで、集合を使った時の考え方を学びました。

4. コインの表裏(確率変数)

確率変数

前回の話では、コインの表裏を使ったので下のような確率が存在します。

出来事 確率
裏が出る 0 0.5(1/2)
表が出る 1 0.5(1/2)

そして、出来事の集合をΩ={裏, 表}のように表現します。
さらに、(わかりやすいように)コインがちょっと曲がっていて上の確率が変わり下のようになったとします。(仮定)

出来事 確率
裏が出る 0 0.4
表が出る 1 0.6

ここでの「0」「1」が確率変数というものになります。

サイコロの場合
目の数 1 2 3 4 5 6
確率 1/6 1/6 1/6 1/6 1/6 1/6

1〜6が確率変数で下のように数式で表します。
1(実現値) x 1/6(確率)

そして一般化するとE[X] = xi pi
のように表現できる。

5. コインの表裏(期待値と分散)

目の数 1 2 3 4 5 6
確率 1/6 1/6 1/6 1/6 1/6 1/6

1〜6が確率変数で下のように数式で表します。
1(実現値) x 1/6(確率)

そして一般化するとE[X] = xi pi
のように表現できる。

期待値

期待値=<確率変数の実現値> x <実現値の確率>の合計

つまり、サイコロの期待値は・・・

(1 x 1/6) + (2 x 1/6) + (3 x 1/6) + (4 x 1/6) + (5 x 1/6) + (6 x 1/6) = 3.5となる。

6. 卒業までに彼氏ができる確率

「出会った男性が青葉のことを好きになる or ならない」で考えます。

好きになる 好きにならない
1 0

そして、確率変数の時と同じように表にすると下のようになります。

出来事 確率
好きにならない 0 1 - p
好きになる 1 p

P(X1 = 1) = p
P(X2 = 0) = 1-p

これが、ベルヌーイ分布というもだと書いてありました。

確率変数Xが、「確率pでX=1」となり、「確率1-pでX=0」となる時、確率変数Xはベルヌーイ分布に従う、という

男性1(X1) 男性2(X2) 男性3(X3) 合計
No No No 0
Yes No No 1
No Yes No 1
No No Yes 1
Yes Yes No 2
Yes No Yes 2
No Yes Yes 3
Yes Yes Yes 3

上の表が起こりうるパターンを一覧化したものです。
これらの期待値を算出するためにはどう考えたら良いかを学習しました。

7. 確率変数の足し算

上の表にあるもので実際に同時には起きない事象があります。

X1, X2の独立下確率変数を1つの塊としてみる

と言うことが「確率変数の足し算」と言う意味です。
これはどう言うことかと言うと

「男性1が好きになり、男性2が好きにならない」という事象と「男性2が好きになり、男性1が好きにならない」という事象は「同時に起きない」

と言うことなので、

パターン数が1のもの(合計が0 or 3)

① P(X1 + X2 + X3 = 0) = P(X1=0, X2=0, X3=0) = P(X1=0)P(X2=0)P(X3=0) = 1/2 x 1/2 x 1/2 = 1/8

②P(X1 + X2 + X3 = 3) = P(X1=1, X2=1, X3=1) = P(X1=1)P(X2=1)P(X3=1) = 1/2 x 1/2 x 1/2 = 1/8

パターン数が2のものは合計が(2になるもの)

③ P(X1 + X2 + X3 = 2) = P(X1=1, X2=1, X3=0) 
+ P(X1=0, X2=1, X3=1)
+ P(X1=1, X2=0, X3=1)

= P(X1=1)P(X2=1)P(X3=0) 
+ P(X1=0)P(X2=1)P(X3=1)
+ P(X1=1)P(X2=0)P(X3=1)
= 1/8 + 1/8 + 1/8 = 3/8

パターン数が3のもの(合計が1)

④P(X1 + X2 + X3 = 1) = P(X1=1, X2=0, X3=0) 
+ P(X1=0, X2=1, X3=0)
+ P(X1=0, X2=0, X3=1)

= P(X1=1)P(X2=0)P(X3=0)
+ P(X1=0)P(X2=1)P(X3=0)
+ P(X1=0)P(X2=0)P(X3=1)
= 1/8 + 1/8 + 1/8 = 3/8

これらを表にすると
<X1 + X2 + X3>

実現値 0 1 2 3
確率 1/8 3/8 3/8 1/8

とちょっと長くなりましたが、こんな感じで学習してきました。

これから、ちょいと学習レベルを上げていく感じです。
つまり、実際に数理モデルを扱うための学習になって行きます。

でわでわ。。。



数学への挑戦 第二弾〜卒業までに彼氏ができる確率:数理モデルxプログラミング〜

始めに断っておきますが、参考にしている書籍のタイトルです。自分の話ではございません(笑)

余談

世間にはオープンデータを始め色々な情報(統計データ)が落ちています。
図書館やインターネットには国、市が作成したという系データというものがWebAPIという形で使用することができます。
例えば、Macユーザーの方だったらターミナルを立ち上げて
下のようなコマンドを叩いてみてください。
curl -s https://api.ipify.org?format=jsonこれをターミナルから叩くと、自分の端末が使用しているグローバルIPがわかるらしいです。

こんな感じで、たくさんの情報がインターネット上にあるのでそれを有効利用するために「統計」「人工知能」。。。などと騒がれる昨今ですが、基本を理解しないと「なんとなく動いた。。。」で終わってしまうんで基本を理解つまりは数学的にどういう意味なのか?を理解するために数理モデルを学習します。

学習中の本は以下のものです。

彼氏ができる確率

この本に出てくる「青葉」は女子大生です。やはり女の子は結婚などがきになるようです。
そして、結婚できるか不安になったようです。。。

その不安を解消するために「数理モデル」をしようしようというのが今回のお話です。。。

ベルヌーイ分布

「なぜ?分布が?」と思った方、自分もそう思ったのでよく本を読んでみます。
とりあえずは「確率」でものを考えるようです。
コインと時と同じように考えますので。。。
「出会った男性が青葉のことを好きになる or ならない」で考えます。

好きになる 好きにならない
1 0

そして、確率変数の時と同じように表にすると下のようになります。

出来事 確率
好きにならない 0 1 - p
好きになる 1 p

P(X1 = 1) = p
P(X2 = 0) = 1-p

これが、ベルヌーイ分布というもだと書いてありました。

確率変数Xが、「確率pでX=1」となり、「確率1-pでX=0」となる時、確率変数Xはベルヌーイ分布に従う、という

これをベースにして

n人の異性と出会いx人から好かれる確率を計算する

ここで人数を「n」とか「x」のように<変数>にしておくとこの変数に10とか100とか入れ替えて計算できる、ということです。
プログラマからして見ると「いつも使ってるものと同じ」です。
データ型はintとかlongになるのかな?いや、小数点も扱うからdoubleかもしれない(笑)

そして、上の値は○○%の確率で「好きになる」 or 「好きにならない」の2択であることに注意が必要です。
さらに、「確率」と記載していますが、これは「割合」を示す数値で例えば『「確率p=0.01」で男性に好かれる』というのは100人と出会った場合男性が一人好きになるという意味なので確率というよりも「割合」という意味になります。

実際に考える

男性3人に出会いそれぞれが青葉を好きになる結果のパターン数を出してみる

表にして見ると下のようになります。あくまで人数に注目しています。

男性1(X1) 男性2(X2) 男性3(X3) 合計
No No No 0
Yes No No 1
No Yes No 1
No No Yes 1
Yes Yes No 2
Yes No Yes 2
No Yes Yes 3
Yes Yes Yes 3

このようになります。「Yes」は好きになる、「No」は好きにならないことを示しています。

そして「青葉」が気がついたことは下のようなことです。

好きになる人の合計は常に「X1 + X2 + X3」になる

なるほど、「男性1〜3」を変数として考えればそーなるな。。。

独立な確率変数

当然の話ではあるが、男性1〜男性3に関連性は、ありません。このような状態を「独立」していると言いいます。

確率変数が独立であるというのは、どんな実験値x1, x2についてもP(X1 = x1, X2 = x2) = P(X1 = x1)P(X2 = x2)が成り立つ

つまり、上のベルヌーイ分布に照らし合わせ流と下のようになります。

P(X1 = 0, X2 = 0) = P(X1 = 0)P(X2 = 0)
P(X1 = 0, X2 = 1) = P(X1 = 0)P(X2 = 1)
P(X1 = 0, X2 = 1) = P(X1 = 0)P(X2 = 1)
P(X1 = 1, X2 = 0) = P(X1 = 1)P(X2 = 0)
P(X1 = 1, X2 = 1) = P(X1 = 1)P(X2 = 1)

そして、実験値と確率を表にすると下のようになります。

X1 X2
0 1 0 1 実験値
1/2 1/2 1/2 1/2 確率

X1の期待値は

(0 x 1/2) + (1 x 1/2) = 0.5

X2の期待値は

(0 x 1/2) + (1 x 1/2) = 0.5

両方とも同じになります。

今日はここら辺にしておきます。次回は「確率変数の足し算」をやります。

でわでわ。。。



JavaME 開発方法 〜JavaMEの開発環境構築〜

前回(JavaME SDK)、前々回(Codename one)とJavaMEでの開発環境構築に失敗していますが、今回はうまくいくであろうと思っています。(やって見ないとわからないのが世の常。。。)

目的

Microbit〜ラズパイ〜MIDI音源と通信をしてMicrobitから音を鳴らそうというものです。

EclipseME

このプラグインを試してみたいと思います。
しかし、古い情報しか見当たらず。。。断念

NetBeansを使用する

Net Beansを見ると行けそうな感じがしました。
細かい説明のあるページも見つけました。が、NetBeansでやるのは嫌なので他を探すことにします。

開発方法を見直す

本当は、PC上でソースコードを書いて、テスト実行して、ラズパイにデプロイ。。。というように作業をしたかったのですが、色々探しても、適当なものが見つからないので諦めることにしました。

PCでコーディング→ラズパイでテスト

諦めて上のような実装方法にしようと思います。
ポイントは以下のようになります。

  1. JDKのバージョンをPCとラズパイで揃える(Java1.8で後に続く_XXX-XX)というのは無視
  2. Eclipseで通常通りに実装、PC上(のコンパイラ)で実行およびテスト
  3. ラズパイで作成したコードをGit経由でダウンロード、ビルドして実行(テスト)

このようにやって行こうと思います。
色々調べたけれど、結局はこの方法に落ち着きました。。。

というわけで、PC上でJavaMEを実行することを考えて環境構築を行います。

色々と調べて、Eclpse Kuraを使用するとか、あるのですがいまいちしっくりきていないのでもう少し調査します。

今回は、ここまでにしておきます。。。



Javaスキル36房〜第35房: はじめの一歩〜

Javaの布教を企んでいます。そしてシンプルにゴールが見える形で学習を進める方法がないか考えていました。

少林寺36房をモデルにする

少林寺拳法など、中国の古い文化は「教育」という部分でとても優れたシステムを持っているように思います。
その中で注目したのがこの「少林寺36房」です

正直のところ、内容は知りませんがポイントとしては以下のようなことです。

学習する時のポイント

  1. 段階的に学習(修行)レベルを上げていく
  2. 基本の理解を進める中で「奥義」の片鱗を見つけられる
  3. やる気(やって面白い)

実際に学習をするのに「コード」を書かないと始まらないのでソースをコンパイルしたりなんだりと必要なことが多いのですが、ここら辺の問題をクリアするのが「ウェブコンパイラ」だと思いました。

上のキャプチャをクリックするとコードをコンパイルできるページに遷移することができます。

第35房

【問題】
上記のリンク(キャプチャ)から画面遷移してコードを書き下の文言を出力するプログラムを書いてください。
"こんにちは、世界"

ポイント

  1. 「ハローワールドを起動する。」(初めにあるプログラム)
  2. 「"」(ダブルクォーテーション)を表示する

参考ページ
はじめの一歩〜ハローワールド〜

実際に上のキャプチャをクリックするとそのページへ移動できますが、コードを書いて起動するのは自分自身です。
ハローワールドのコードが書いてあります。

注意点

Java以外の言語でも共通して必要なコードがあります。
import文です。
例えば、Listとか、Fileなどの操作を行いたいときにはそれぞれの使用するためのAPIが用意されているのでそれらを使用しますが、使用するときには以下のようにインポートする必要があります。
import java.util.List;

この35房をクリアできたら次は第34房です。



Java はじめて29 〜JUnitでのテスト駆動型開発6: ファイル読み込みのテスト〜

今回は、今迄作成した「ファイル存在チェック」と「ファイル作成、更新」処理を繋げてテストします。

この段階で、ようやくテストらしいテストになります。ちなみにこのテストケースも実装前に作成出来ますが、小さなレベルで、テスト仕様を考える→実装→テスト実施…とやった方が早い気がします。

口座作成処理

ようやく、仕様レベルの話に戻って来ました。このテストケースはコーダー銀行に口座を開設する処理に当たりますので、実際に動かす時と同じような入力(テストなのでデータ)を渡して実行します。テストコードは下のようになります。

このテストケースが通ったらとりあえずは、製造完了です。お疲れ様でした。

ひと段落したので、一旦休むも良し、このまま突走るのも良し。

他の事に着手してみるも良し!

動く事が大事

何が言いたいかと言うと、プログラムは何かを作る、仕組みを作るなどに使用する。若しくは単純に触りたいだけ…など色々あると思いますが、ちゃんと動くモノを作った方が、実力もつくし、作ったもので遊べるし、良い事ずくめだと思うので、色々と作ってみるのが良いと思います。

今迄やって来ているのは、サンプルなので…主な目的は「Javaの学習」になっています、あまり作りたいものには届かないと思います。しかし、基礎を学べる様になっているのと、コンソールアプリなので応用はいくらでも出来ます。早い話が、コンソールアプリが作れれば、あとは環境が違うだけなので大まかな流れは理解できるずです。。。

続き

前置きは、このくらいにして、続きをやります。

早い話が、今迄作成したメソッドを続けて呼び出し、それらが想定通りに動くか?の確認を行います。

作成したメソッドは以下のものです。

そして、上のメソッドを結合してやる場合のテストケースから考えます。

データの読み込み

仕様

  • ファイル存在チェックを行いファイルが存在すれば読み込む
  • 存在しなければファイル作成を行う

仕様に関してはこの部分のみをみていましたが、ファイルの読み込みをした後に、データが入っているはずなので、これを取得する必要があります。

この部分は実装していないので、実装が必要です。とりあえずは、目の前のテストを片付けてしまいます。テストコードは下の様になりました。テストを実施しながら実装するので手直しをするからこうなりました。と言う表現を使いました。

テストが通ったので、次の事を考えます。つまり、ここまでは想定通りに行ったという事です。

データの取得

次は、読み込んだファイルのデータをクラスに設定してやる事を考えます。

ファイルに保存してあるデータを読み込んで、プログラムで使いやすい様にデータクラスを使ってデータを保持します。「保持」と言うのは、プログラムが止まると消えてしまう情報なので「保持」と言う言葉を使いました。

ちなみに、ファイルに保存すれば、プログラムが止まっても情報は残しておけます。

現状では、Dataクラスを使用してファイルにデータを書き込んでいます。
ちなみにデータクラスは下の様なコードになります。

public class Data {
    /** ユーザー名 */
    private String name;
    /** パスワード */
    private String password;

    /** 
     * コンストラクタ。口座情報を保持するクラスのインスタンスを生成。
     * 
     * @param name 口座のユーザー名
     * @param password 口座のパスワード
     */
    public Data(String name, String password) {
        this.name = name;
        this.password = password;
    }
    /**
     * @return the name
     */
    public String getName() {
        return name;
    }
    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }
    /**
     * @return the password
     */
    public String getPassword() {
        return password;
    }
    /**
     * @param password the password to set
     */
    public void setPassword(String password) {
        this.password = password;
    }
}

データクラスは、フィールドとGetter, Setterのみのクラスです。

読み込み時にも同じクラスが使えます。
まとめると以下の様な手順でファイルを読み込みます。
1. ファイルを開く(コンストラクタで実装ぞ済み)
2. ファイルを1行ずつ読み込みDataクラスへ設定
3. データクラスをリストにして返却する

以上の様な手順でファイルからデータを取得します。
そして、これをテストケースにします。
## テスト仕様
上の手順そのままですがこれを確認するためのテストケースを作成します。そしてこれもとりあえずは「スタブメソッド」を作成します。

/**
 * ファイルを読み込みデータをリストにして返却する
 * @return List CSVファイルのデータリスト
 */
public List readFile() {
    return null;
}

このメソッドはJavaDocコメントにある様に、リストにしてデータを返しますので、java.util.Listインターフェースを使用してデータを返却します。
Listインターフェースの配列型リスト=ArrayListクラスを生成してデータをセットする様に実装します。コードは以下の様になります。

public void testFileRead() {
    List dataList = target.readFile();
    // データは1件
    assertEquals(1, dataList.size());
    // ファイルにあるデータ
    Data data = dataList.get(0);
    assertEquals("test", data.getName());
    assertEquals("passwd", data.getPassword());
}

このテストケースを実行しエラーが出ない様なコードを作成します。一応、CSVファイルはファイル作成時に出力したデータが設定されていることを確認しています。

Java はじめて17 〜設計後の部品を実装する1〜

今回は、役割分担を行なった後にクラス(部品)をどのように組み合わせてアプリを作成するか?について記載したいと思います。
【補足】
アプリの規模がとても小さく、処理内容も少ないのでちゃんとした「設計書」の類は作成しません。

<ユースケース>
【前提】
コンソール画面のATMとします。
ユーザー認証は行いません。
単純に金額を入金、引き出しができるものを作ります。

【仕様】
アプリを起動してコンソールから「引き出す」「入金」を選択する
それぞれの処理に対して「預金額」から足し算、引き算を行いその結果を表示する

<部品候補>

  1. メインメソッドを持ち、入力の受付も行うクラス
  2. 入金、引き出しを行う計算処理クラス

部品を作る

<部品候補>からクラスを2つ作成します。クラス名はアルファベットで作成する必要がある(全角の文字でも作成できますが、なんとなく嫌なので。。。)

  1. MainBankクラス(メインメソッドを持つ)
  2. Calcurationクラス(引出し、入金を管理する)

上のように名前をつけます。このように「役割分担」をしてやれば、いざ修正するときにどちらかのクラスの一部を修正してやれば、デグレート(修正したらおかしな事になる)する事もないように作ることができます。

ここのポイントとしては、書く処理の依存度をなるべく低くしてやることです。依存度が高いと下のようなコードになります。

public static void main(String[] args) {
   MainBank main = new MainBank();
   Scanner input = new Scanner(System.in);
   String inStr = input.nextLine();
   if ("in".equals(inStr)) {
       // 入金処理を行う
   }
      ・
      ・
      ・
}

入力を受けたあとに入金処理を同じクラスの中に書き始めると、結局のところは全部の処理をMainBankクラスに書くことになります。
ソースを読む時は全部読まないといけないし、修正するときも、あちこち直さなくてはいけません。。。
残業パラダイス必至のコードです。平和のためにこのような作成方法はやめましょう。。。

依存度を下げるために

クラスを複数作成し、役割分担をしてやります。
今回のコンソールアプリを作るのには以下のような2つの処理が必要です。

  1. コーダー銀行の受付(入金、引出し)を行う(判定)する処理
  2. 入金処理、引出し処理のそれぞれを行う。

ポイント

  1. 受付部分は共通なので、MainBankで行う
  2. 入金処理、引出し処理は独立させることができるので分割する

そんなわけで

  1. MainBankクラス
  2. Calcurationクラス

上記のクラスを作成することにしました。

MainBankクラス

アプリケーションの起動とコーダー銀行の受付処理を行います。
処理の詳細に関しては、以下の通りになります。

  1. コーダー銀行の受付文言をコンソールに表示
  2. デフォルトの預金金額¥1000-を表示する
  3. 入金(in)、引出し(out)の判定を行い、処理終了する時は「bye」の入力で処理を終了する
  4. そのほかの入力はエラーメッセージを表示してサイド入力を促す表示を行う

Calcurationクラス

入金、引出し処理を担当するクラスです。このクラスには預金額を管理するためのフィールド変数が必要になります。
そして、入金処理、引出し処理では以下のような処理が必要になります。

  1. 入金・引出し処理を行う旨を表示する。
  2. それぞれの処理を行った後の預金額を表示する。
  3. 受付〜各処理への状態が変化していることをプログラム的に区別する必要がある。

上の3番に関して、「プログラム的に〜」と記載している部分は「状態」を管理することにより処理クラスを変更、管理しやすいのです。この設計手法に関してはGOFのデザインパターンなどを読んでみるととても参考になります。
良いデザイン(設計)をできるようになると、色々と楽ができます。

でわでわ。。。



PGボックス 記事一覧

PGボックス記事一覧

Java Basic Lv1-10

Java Basic Step1-3

目標達成プロジェクト (サンプル2)

ND4J

Twitter API

Google Maps

JS Google Maps API 〜オリジナル・データマップを作ろう〜