k01ken’s b10g

He110 W0r1d!

Windows10(64bit)にDockerをインストールする

開発環境は、Windows10 Pro(64bit)。

タスクマネージャーを起動して、パフォーマンスタブをクリックして、仮想化が有効になっていることを確認する。

1.公式サイトへアクセスする
Enterprise Container Platform | Docker

2.右上のGet Startボタンをクリック
f:id:k01ken:20190406172912p:plain

3.ちょっとスクロールして、Download for Windowsボタンをクリック
f:id:k01ken:20190406173017p:plain

4. Please Login To Downloadボタンをクリック
f:id:k01ken:20190406173849p:plain

5.Docker IDを作成するために、Create Accountリンクをクリック
f:id:k01ken:20190406174025p:plain

6.Docker IDとEmailとPasswordを入力し、チェックボックスにチェックを入れて、規約に同意し、reCAPCHAを入力して、Continueボタンをクリックする
f:id:k01ken:20190406174938p:plain

7.メールが送信されるので、メールを開く

8.メールを開いたら、Confirm Your Email With Dockerボタンをクリックする
f:id:k01ken:20190406175208p:plain

9.Get Dockerボタンをクリック
f:id:k01ken:20190406175434p:plain

10.ダウンロードが開始されるので、インストーラをダウンロードする

11.ダウンロードしたDocker for Windows Installer.exeを実行する

12.Configurationの2つにチェックを入れて、Okボタンをクリック
f:id:k01ken:20190406182037p:plain

13.インストールが完了したら、Close and log outボタンをクリック
Windows自体が再起動するので、ほかのプログラムはすべて終わらせておくこと
f:id:k01ken:20190406182238p:plain


14.Docker Desktopをクリックして、以下のようなメッセージが表示されたら、OKボタンを再起動する
f:id:k01ken:20191210230910p:plain

再起動した後に、もう一度、Docker Desktopをクリックしたときに、インストールが開始されるので、終了まで待つ。

15.Dockerがうまくインストールされているかチェックするために、コマンドプロンプトにて、以下のコマンドを入力する。
正しくインストールされていれば、Dockerのバージョンが表示される。

docker version

f:id:k01ken:20191210231323p:plain

16.Dockerイメージをインストールして、コンテナを起動してみたいと思います。
ubuntuをコンテナ上で起動して、その上で、bashを動かしてみます。

docker run -it ubuntu bash

f:id:k01ken:20191210232526p:plain


■参考リンク
WindowsでDocker環境を試してみる - Qiita

CakesのUI

CakesへTwitterのリンク経由で個別記事にアクセスした時に、なぜか、タイトルはあるけれど、記事の中身のないページに飛ばされる。
f:id:k01ken:20190320134248p:plain
リロードすると、変わるかな?と思って、リロードしても変わらない。
だから、1回その連載のトップページ(目次ページ)へアクセスしてから、もう一度、個別ページへ飛ぶという手間が増えてしまう。
そうすると、以下のように記事の中身がきちんとあるページが表示される。
f:id:k01ken:20190320134404p:plain
2つのページを見てみると、どちらも、
https://cakes.mu/posts/24970
となっていて、リンクとしては変わらないのに、なぜ、一方は、記事が表示されなくて、もう一方は記事が表示されるのだろうか?

これは、意図的に手間を増やしているのか、それとも、気づいていないだけなのか。

Candy Crash FriendsのUI

Candy Cransh Friendsというゲームをやっていて、ゲームに失敗すると、出現する画面で、自分では、ギブアップを選択しようとしたが、間違えて、アイテムの金塊を10個支払って、続けるボタンを押してしまった。一度、押してしまうと、キャンセルができない。

このゲームで、金塊というアイテムは、初期の段階で、進めると、無料で50個もらうかどうか選択できるものだ。

f:id:k01ken:20190302165316j:plain

そこで、よく見てみると、続けるボタンをギブアップボタンよりも大きいサイズにしていて、かつ、視線の動きを上から下へ動かす段階で、どうしても目に入るように配置していて、さらに、画像だと分からないけれども、アニメーションで、続けるボタン→ギブアップボタンの順番で出現するようになっていて、間違えて押しやすくなっている。

ゲーム上では、金塊が減ると、再び入手するためには、お金を出して、買うしか手段がない。そして、金塊がちょっと減ってしまうと、(最初に与えられたものを取られると)精神的に気持ちが悪くて、初期の満タンの数である50個まで貯めたくなる。そこを狙っている。


他にも、ライフがゼロになった状態で出現する画面を見てみると、
f:id:k01ken:20190302165509j:plain
ライフを追加するボタンが大きく表示されていて、ステージへ戻るための×ボタンを押す過程で、視線が、どうしても、ライフを追加するボタンに目がいってしまうし、それだけじゃなくて、片方は、「ライフを追加する」と、文字で表現している一方で、ステージへ戻る方のボタンは×の絵で表示されているだけで、この違いも、ライフを追加するボタンをクリックする方へ誘導している気がする。
何となく、そっちのほうが、それが何なのかを認知をするための脳への負荷が小さいので、クリックしてしまうのを狙ってるんじゃないか?


最後に紹介したい事例として、このゲームでは、1ステージクリアするたびに、金塊が溜まっていくが、最大30個までしか溜まらず、それ以上は、捨てられるアニメーションを毎回見せられる。これによって、金塊を取り出さなければ、もったいないという心理を植えつけようとする。
f:id:k01ken:20190303132750p:plain

しかし、このゲームでは、金塊を取り出すには、課金しなければならない。
f:id:k01ken:20190303131338p:plain


ステージ画面の右上の金塊ボタンをクリックすると、下は230円から、上は、11700円までの金塊を含めた課金アイテムがずらりと並び、いつでも買えるようになっている。
f:id:k01ken:20190303133829p:plain


他の仕組みとして、ゲーム内では、全プレイヤーの総合ランキングみたいなものは表示されていない。これによって、プレイヤーのやる気が削がれないような仕組みにしているのかもしれない。
ただ、ステージ別のランキングはある。でも、そのランキングは、そのステージの歴代ランキングなのか、それとも、そのステージをクリアした、直近、10名のランキングなのかは不明。ランキングにはメリット/デメリットの両方があって、デメリット(自分と相手の差がありすぎたり、上位の顔ぶれが変わらなくて、やる気が削がれる)を減らして、メリット(競争心を煽り、やる気を出す)を増やす仕組みになっている気がします。


今まで紹介してきたように、Candy Crashのゲーム運営者はいかに、金塊をユーザーに買わせようとしているかという事例でした。

CakePHP3でルーティングを行う

開発環境は、Windows 10 Pro(64bit) + PHP 7.2.12 + CakePHP 3.7.2 + XAMPP Control Panel v3.2.2。

今回は具体的な事例として、トップページを、PostsController内のindexアクションにしたい場合の書き方を説明。

1. /config/routes.phpを開く

2.以下の部分を変更する

<?php

    $routes->connect('/', ['controller' => 'Pages', 'action' => 'display', 'home']);

?>

<?php
    $routes->connect('/', ['controller' => 'Posts', 'action' => 'index']);
?>

に変更する。
また、ユーザーが、/posts/indexや、/postsにアクセスしてきたときもトップページに飛ぶように設定しておくには、

<?php
$routes->redirect('/posts/', '/',['persist' => true]);
?>

を、config/routes.php内のRouter::scope('/', function (RouteBuilder $routes) { ~ });ブロック内に追加する。

名前付きルーティング

名前付きルーティングとは、その名前のコントローラを作っていなくても、好きな名前をURLに設定することができるものです。Togetterの個別記事ページのようなルーティングを実現したい場合(/li/12345678のようなTogetterの個別記事ページのようなルーティングを書く場合)で、それを、PostsControllerのviewアクションで実現したい場合は、

<?php
$routes->connect('/li',['controller' => 'Posts', 'action' => 'view'],['_name' => 'li']);

$routes->connect('/li/:id',['controller' => 'Posts', 'action' => 'view'])
->setPatterns(['id' => '\d+'])
->setPass(['id']);

?>

を、config/routes.php内のRouter::scope('/', function (RouteBuilder $routes) { ~ });ブロック内に追加する。
逆に、/posts/view/234のようなアクセスをリダイレクトするためには、

<?php
$routes->redirect('/posts/view/:id', ['controller' => 'Posts', 'action' => 'view'], ['persist' => true])
->setPatterns(['id' => '\d+'])
->setPass(['id']);
?>

を、config/routes.php内のRouter::scope('/', function (RouteBuilder $routes) { ~ });ブロック内に追加する。

※設定を変更したのに、それが反映されない場合の解決法

この部分で、かなり時間を食ってしまったのでメモ。
解決法としては、
1.ブラウザ側のキャッシュを削除する
2.CakePHP側のキャッシュを削除する
/tmp/cache/myapp_cake_routes_route_collection
を削除する。(削除しても、変更すると、新しく生成されるので大丈夫)

自分のケースでは、1.をしても変わりはなくて、2.をしたら変更が反映されました。できれば、両方やっておいたほうがいいでしょう。


■参考リンク
https://book.cakephp.org/3.0/ja/development/routing.html
CakePHP3でルーティングを設定し、URLをカスタマイズする | (株)シャルーン

Windows10にBlenderを使う

開発環境は、Windows 10 Pro(64bit)。

1.公式サイトへアクセスし、画面をクリック
blender.org - Home of the Blender project - Free and Open 3D Creation Software
f:id:k01ken:20190206220441p:plain

2.Download Blender 2.8 Beta(現時点)と書かれたボタンをクリック
f:id:k01ken:20190206220456p:plain

3. 2.80 Beta Windows 64bit(現時点)をクリックし、zipファイルをダウンロード
f:id:k01ken:20190206220514p:plain

4.blender-2.80-8996e26116f0-win64.zipを解凍するだけ

5.解凍したディレクトリ内のblender.exeを実行

6.実行すると、Windows Defenderがストップする可能性があるので、詳細をクリックして、実行ボタンをクリックすると、Blenderが実行される。

7.中央のウィンドウのNextボタンをクリック
f:id:k01ken:20190206221802p:plain

8.New FileのGeneralをクリック
f:id:k01ken:20190206221817p:plain

おすすめリンク
Blender入門 - CGrad Project

PHPでarray_searchを使用する際の注意点

開発環境は、PHP 7.2.12。

条件文の中で使用する際に注意すべき部分

array_search関数は、配列の中に指定の値があれば、その値のキーを、指定の値がなければ、falseを返す関数なのですが、例えば、以下のコードのように、返り値としてインデックス番号の0が返る場合は、指定の要素があるのに、false扱いになってしまいます。

<?php
$arr = ["test", "test2","test3"];

# false
if( array_search("test", $arr) ){
  echo "true";
}else{
  echo "false";
}
?>

そこで、以下のようにコードを書き換えておきます。仮に、!== falseの部分を、!= falseとしてしまうと、同様に、falseと出力されてしまいます。
厳密な型の比較を確実に行い、意図しない動作を防ぐことが求められます。

<?php
$arr = ["test", "test2","test3"];

# true
if( array_search("test", $arr) !== false){
  echo "true";
}else{
  echo "false";
}
?>

条件文を書く際には、注意したい。

条件文内で変数を入れる際の注意点

array_searchを2回呼び出すのが処理的にどうなの?と思ったので、条件文内の変数に入れておこうと考えたが、想定した通りの動きにはならなかった。

<?php

$arr = [1,2,3,4,5];

if($idx = array_search(3,$arr) !== false){
  echo $idx; # 1が入る。
  echo array_search(3,$arr); # 2が入る
}
?>

文字列の値を用いてarray_searchを用いる際の注意点

文字列を値に指定する場合は、第三引数をtrueに指定しないと、きちんと動作しない。

<?php

$arr = [0,1,2,3,4,"str",5,"key" => "value",6,7,8];

print_r( array_search("str",$arr) ); # 5ではなくて0が返ってくる
print_r( array_search("str", $arr, true) ); # 5が返ってくる
print_r( array_search("value",$arr) ); # keyではなく0が返ってくる 
print_r( array_search("value",$arr,true) ); # keyが返ってくる 

?>


参考サイト
PHP: array_search - Manual

ImagicKを使って色々と画像を加工してみる

開発環境は、PHP 7.2.12 + ImageMagicK ImageMagick 7.0.7-11 Q16 x86 2017-11-23 + XAMPP Control Panel v3.2.2。

新しく画像を作成する

新しく画像を作成し、png画像のフォーマットとして、表示させます。

<?php
$image = new Imagick();
$image->newImage(100, 100, new ImagickPixel('red'));
$image->setImageFormat('png');

header('Content-type: image/png');
echo $image;
?>

実行結果
f:id:k01ken:20190125231848p:plain

画像を保存する

<?php
$image = new Imagick();
$image->newImage(100, 100, new ImagickPixel('red'));
$image->setImageFormat('png');

$image->writeImage(realpath("test.png"));
?>

と書く。writeImageのファイル名は絶対パスで指定すること。

参考リンク
http://php.net/manual/ja/imagick.writeimage.php

画像のサイズを変更する

以下のコードは、読み込んだ画像を、幅203px、高さ293pxに変換して表示している。

<?php
$image = new Imagick(realpath('test.jpg'));
$image->thumbnailImage(203,293);

header("Content-type: image/jpeg");
echo $image;
?>

thumbnailImage関数の第1引数か、第2引数を0にすると、指定した幅 or 高さに応じて自動的に、0を指定した幅 or 高さを調節してくれる。もし、高さを知りたければ、Imagick::getImageHeight関数を用いると高さを取得できる。

<?php
$image = new Imagick(realpath('test.jpg');
$image->thumbnailImage(220,0); # 例えば、高さは318pxに自動的になる

header("Content-type: image/jpeg");
echo $image;
?>

参考リンク
http://php.net/manual/ja/imagick.thumbnailimage.php
http://php.net/manual/ja/imagick.getimageheight.php
http://php.net/manual/ja/imagick.getimagewidth.php

画像の品質を変更/取得する

スクリプトのある同一ディレクトリにtest.jpgがあったとして、画像の圧縮品質を取得します。品質が高いと画像のファイルサイズが大きくなり、逆に、低いとファイルサイズが小さくなります。
値は1~100のどれかになります。

<?php
$img = new \Imagick(realpath("test.jpg"));
echo "<b>getImageCompressionQuality: </b>".$img->getImageCompressionQuality();

?>

次に画像の圧縮品質を変更してみたいと思います。
設定できる値は、1~100までです。jpeg画像だと、画像の見た目が変わりますが、png画像だと、画像の見た目は、全然変わりません。

<?php
$img = new \Imagick(realpath("test.jpg"));
$img->setImageCompressionQuality(100);
header("Content-Type: image/jpeg");
echo $img;
?>

参考リンク
https://www.php.net/manual/ja/imagick.getimagecompressionquality.php
https://www.php.net/manual/ja/imagick.setimagecompressionquality.php

画像を一部切り取って抜き出す

今回は入力した画像から、画像の中心を基準にして、正方形に切り出すプログラムを書いてみたいと思います。

<?php
$im = new Imagick(realpath('test.jpg'));
$width = $im->getImageWidth();
$height = $im->getImageHeight();

$half_width = $width / 2;
$half_height = $height / 2;

if($width > $height){
  # 縦幅の方が短い横長の画像
  $upper_half_width = $half_width - $half_height;
  $im->cropImage($height,$height, $upper_half_width,0);
}else if($width < $height){
  # 横幅の方が短い縦長の画像
  $upper_half_height = $half_height - $half_width;
  $im->cropImage($width,$width,0,$upper_half_height);
}else{
  # 最初から正方形の場合の画像
  $im->cropImage($width,$height,0,0);
}

$im->setImageFormat('jpg');

header("Content-type: image/jpg");
echo $im;

参考リンク
http://php.net/manual/ja/imagick.cropimage.php

2枚の画像を比較して差分を抽出する

下記の2枚の画像を使用します。
f:id:k01ken:20190125214822p:plain
f:id:k01ken:20190125214839p:plain

下記のプログラムでは、画像のパスは絶対パスで指定しないとエラーになる。

<?php

$image1 = new imagick("C:/xampp/htdocs/image1.png");
$image2 = new imagick("C:/xampp/htdocs/image2.png");

$result = $image1->compareImages($image2, Imagick::METRIC_MEANSQUAREERROR);
$result[0]->setImageFormat("png");

header("Content-Type: image/png");
echo $result[0];

?>

実行結果
f:id:k01ken:20190125215121p:plain

このように差分のみが赤く表示されていることが分かります。
サイトの中でデザインのどこが変更されたのか知るのにちょうどよいでしょう。


参考リンク
http://php.net/manual/ja/imagick.compareimages.php
Imagick::compareImages - ある画像を再構築された画像と比較する


画像のフォーマットを変換する

画像のフォーマットを変更するには、setImageFormat関数を用います。
例えば、以下のコードにて、読み込んだjpeg画像をpng画像に変換して表示します。

<?php

$image = new Imagick(realpath('test.jpg'));
$image->setImageFormat('png');

header("Content-Type: image/png");
echo $image;

?>

参考リンク
PHP Imagick で画像フォーマット変換 – rilakkuma3xjapan's blog

画像を半透明にする

自分の環境ではなぜか、setImageOpacity関数がなかったので代替方法を探して、あったので書いておきます。

<?php
$image = new Imagick();
$image->newImage(300,300,new ImagickPixel('black'));
$image->setImageFormat('png');

$image->transparentPaintImage(new ImagickPixel('black'), 0.8,10,false);

header("Content-Type: image/png");
echo $image;

?>

実行結果
f:id:k01ken:20190131232029p:plain

参考リンク
http://php.net/manual/ja/imagick.transparentpaintimage.php

画像を合成する

<?php
  $image = new Imagick();
  $image->newImage(600,600, new ImagickPixel('#cccccc'));
  $image->setImageFormat('png');

  $image2 = new Imagick();
  $image2->newImage(300,300, new ImagickPixel('#ffffff'));
  $image2->setImageFormat('png');

  $image->setImageVirtualPixelMethod(Imagick::VIRTUALPIXELMETHOD_TRANSPARENT);
  $image->setImageArtifact('compose:args', "1,0,-0.5,0.5");
  $image->compositeImage($image2, Imagick::COMPOSITE_MATHEMATICS, 0, 0); 

  header('Content-Type: image/png');
  echo $image;
?>

実行結果
f:id:k01ken:20190606220543p:plain

上に被せる画像が透過PNGだと、setImageVirtualPixelMethod,setImageArtifactを除いて、表示させると、シルエットとして表示されます。


参考リンク
https://www.php.net/manual/ja/imagick.compositeimage.php