OmniAICreator/Qiita-1.07M huggingface dataset:
Cocos2d-x 2.2.6 のサンプルアプリを起動する（iOS）

# はじめに
cocos2d-x 2.2.6 を C++API の利用を前提にセットアップして画像のようなサンプルアプリを Android Emulator & iOS Simulator 上で起動させることをこの記事のゴールとします。
v3系は[Cocos2d-x 3.17.2 のサンプルアプリを起動する（iOS / Android）](https://qiita.com/tikidunpon/items/3e3a825852393f4017a0)をご確認ください。

![Simulator Screen Shot - iPhone SE (2nd generation) - 2020-08-06 at 00.46.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9628/b30cdcb7-e96e-c57a-e38f-eb52c909847b.png)

# 環境
- cocos2d-x 2.2.6
- Xcode 12.4 (12D4e)
- Python 2.7.17

# 導入手順

## Cocos2d-x本体と依存関係のダウンロード

### 1. リポジトリをcloneする
```sh
$ git clone git@github.com:cocos2d/cocos2d-x.git
```
### 2. cocos2d-x-2.2.6をcheckout

```sh
$ cd cocos2d-x
$ git checkout -b feature/cocos2d-x-2.2.6 tags/cocos2d-x-2.2.6
```

### 3. 依存関係をダウンロードする
依存関係を[cocos2d-x-3rd-party-libs-bin](https://github.com/cocos2d/cocos2d-x-3rd-party-libs-bin)からダウンロードします。（python）

```sh
$ python download-deps.py
```

## 動作確認用のプロジェクトを作成する

cocosのv2ではcocosコマンドはありません、`create_project.py` でプロジェクトを作成します。（python2系が必要です。）

```sh
$ cd tools/project-creator
$ python create_project.py -project MyGame -package com.MyCompany.SampleGame -language cpp
```

## iOSプロジェクトを実機でビルドする

### 1. iOSプロジェクトを開く

```sh
$ cd projects/MyGame/proj.ios
$ open MyGame.xcodeproj
```


### 2. Bundle version stringが空になっているので設定します。

```info.plist
<key>CFBundleShortVersionString</key>
<string>0.0.1</string>
```

### 3. C++ Standard Libraryを `libc++` に変更する

アプリケーションのターゲットと、cocos2d-x本体両方変更してください。
また、c++ language dialect を c++11 [-std=c++11]に変更しないと文字列リテラルが使えません。
必要に応じてそれも設定してください。
![スクリーンショット 2021-03-31 22.04.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9628/0ac3f3f6-04a8-d889-2d78-b6a108a4f471.png)

![スクリーンショット 2021-03-31 22.04.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9628/02899905-eb9e-1858-2c58-bdaec4ad45fb.png)

### 4. Enable Bitcode を NO に変更

アプリケーションのターゲットと、cocos2d-x本体両方変更してください。

### 5. Deployment Target を 9に変更

アプリケーションのターゲットのみ5.1.1->9に変更します。

Signingを修正すればここまでで実機で実行できます。

## iOS Simulatorで実行する

### 1. EXCLUDED_ARCHSでiOS Simulatorの時にarm64を除外する。
参考:https://zenn.dev/yimajo/articles/7e275bc23999fe7d8b87
![スクリーンショット 2021-04-07 16.05.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9628/a44dc901-3de5-a27f-b38f-53d8d3d45bba.png)

### 2. User-DefinedのVALID_ARCHSを削除する

VALID_ARCHSは、x86_64が入ってないかつ非推奨なのでプロジェクト側のBuild Settingsから項目ごと削除します。
https://developer.apple.com/documentation/xcode-release-notes/xcode-12-release-notes

これでシミュレーターでも実行できるはずです、以上。
rails saveとsave!の違い

#はじめに
rails学習中に`XXX.save!`と記載されたコードを確認し、
普段書いている`XXX.save`との違いが気になったためまとめました。

#結論
`XXX.save`：通常のメソッド　成功時⇒保存　失敗時⇒falseを返す
`XXX.save!`：破壊的メソッド　成功時⇒保存　失敗時⇒例外を返す

例えばOrderモデルのtotal_priceに0円より大きい値のみ許可を与えている場合
以下の挙動を示す

```
[3] pry(main)> order=Order.new
   (0.6ms)  SELECT sqlite_version(*)
  TRANSACTION (0.0ms)  begin transaction
=> #<Order:0x000000012ee09aa0 id: nil, total_price: 0, created_at: nil, updated_at: nil>
[4] pry(main)> order.save
=> false
[5] pry(main)> order.save!
ActiveRecord::RecordInvalid: Validation failed: Total price must be greater than 0
```
#save!のメリット
* 失敗時にエラーが発生し、原因が追求しやすい
* 例外が発生することで、処理が止まる
Textfieldの枠線の色を変える

## 環境
- Swift 5.3.2
- Xcode 12.4

## これだけじゃ変わらなかった

```swift
textField.layer.borderColor = UIColor.lightGray.cgColor
```

## これも一緒に書く
```swift
textField.layer.borderWidth = 1.0
```

備忘録でした。

## 参考
[stack overflow](https://stackoverflow.com/questions/38460327/how-set-swift-3-uitextfield-border-color/38460383)
いろんなDBをDockerで雑に起動する私的ワンライナー集

# この記事の目的

「DBMSで何かしら確認したり作業したいが、サーバは構築するのは面倒」ということがよくあって、そういう場合によく使うDB起動ワンライナーをまとめたものです。

なおセキュリティなどの考慮はしていないので、本番環境などでは絶対に利用してはいけません。ローカル環境で使い捨てる程度の利用にとどめてください。

# 私的ワンライナー集

## PostgreSQL (db: testdb, user: testdb, password: passw0rd)

```
docker run --rm -d \
  -p 5432:5432 \
  -e POSTGRES_USER=testuser \
  -e POSTGRES_PASSWORD=passw0rd \
  -e POSTGRES_DB=testdb \
  postgres:13
```

## MySQL (db: testdb, user: testdb, password: passw0rd)

```
docker run --rm -d \
  -p 3306:3306 \
  -e MYSQL_ROOT_PASSWORD=passw0rd \
  -e MYSQL_USER=testuser \
  -e MYSQL_PASSWORD=passw0rd  \
  -e MYSQL_DATABASE=testdb \
  mysql:8 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci 
```

## SQLServer (user: sa, password: 1234@Hoge)

```
docker run --rm -d \
  -p 1433:1433 \
  -e ACCEPT_EULA=Y \
  -e SA_PASSWORD=1234@Hoge \
  mcr.microsoft.com/mssql/server:2019-latest
```

## Oracle Database (db: testdb, user: system, passowrd: passw0rd)

- 前提: 以下の手順に従って、環境を構築していること
    - https://github.com/oracle/docker-images/blob/main/OracleDatabase/SingleInstance/README.md
- OracleのDockerイメージは起動が重たいので、作成したコンテナを使いまわす

```
docker run -d \
  -p 1521:1521 \
  -p 5500:5500 \
  -e ORACLE_PWD=passw0rd \
  -e ORACLE_PDB=testdb \
  oracle/database:19.3.0-se2
```

## Db2 (db: testdb, user: db2inst1, password: passw0rd)

- Db2のDockerイメージは起動が重たいので、作成したコンテナを使いまわす
- 自分が利用しているGUIツールがDb2に対応していないので、以下のコマンドを実行して、CLIで接続する
    1. `docker exec -it <containerid> su - db2inst1 -c db2`
    2. `connect to testdb user db2inst1 using passw0rd`

```
docker run -d \
  --privileged=true \
  -p 50000:50000 \
  -e LICENSE=accept \
  -e DB2INST1_PASSWORD=passw0rd \
  -e DBNAME=testdb \
  ibmcom/db2:11.5.5.1
```
【Salesforce】PDFの一括出力時はInternal Salesforce.com Errorに注意

「getContentAsPDF」メソッドというPDFを出力する機能があります。
このメソッドをバッチ処理で実行時にエラーが発生するとどうなるのか試してみました。

## 検証対象のVisualforce
今回は以下のVisualforceをバッチ処理で出力してみます。
なお、検証用としてコントローラで必ずエラーが発生するようにしています。

``` html
<apex:page controller="PdfCtrl" renderAs="pdf">
  <h1>Hello PDF</h1>
</apex:page>
```

``` java
public class PdfCtrl {
    public PdfCtrl() {
        Date date1 = Date.newInstance(2021, 1, 1);
        Boolean result = date1.isSameDay(null);
    }
}
```

## バッチ処理
検証対象のVisualforceを以下のバッチ処理でPDF出力してみます。

``` java
public class PdfBatch implements Database.Batchable<sObject>, Database.Stateful {
    public Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator(
            'SELECT Id FROM Account LIMIT 1'
        );
    }

    public void execute(Database.BatchableContext bc, List<Account> scope) {
        PageReference pageRef = Page.PdfTest;
        Blob content = pageRef.getContentAsPDF(); 
    }

    public void finish(Database.BatchableContext bc) {
    }
}
```

## バッチ実行結果
バッチの実行ログを確認すると「Internal Salesforce.com Error」が出力されていました。

``` java
FATAL_ERROR Internal Salesforce.com Error
```

## まとめ
バッチの実行ログが「Internal Salesforce.com Error」なので原因が非常に分かりにくいです。
このような場合には、Visualforceのコントローラのログにエラーの原因が出力されていることが多いです。
諦めずに他のログを解析するようにしましょう。

## 参考
■getContentAsPDF

https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_System_PageReference_getContentAsPDF.htm
Railsアプリ内にVue.jsのエントリーポイントを複数作る方法

# RailsにVue.jsを導入したい
モダンなUI/UXを実現するために、RailsアプリにVue.jsを導入してフロントエンドを整えるパターンが多くなっていると聞きます。

私もオリジナルアプリを作成する際、ランディングページだけでもモダンに仕上げたい！という思いと、純粋に流行っている技術を身に付けたいという思いで、かなり初歩的ではあるもののRailsにVue.jsを導入しました。

# RailsへのVue導入方法
ここは他の方の記事で散々紹介されており、私があえて説明する必要もないかと思いますので、参考にさせていただいたリンクを載せるにとどめます。
(下記記事の方はRailsにDocker環境にてVue.jsを導入するという初学者からするとかなり助けになる内容を執筆されています。)
https://qiita.com/rh_taro/items/21bc9a98e501b8d7de71

# Railsアプリ内でVue.jsのエントリーポイントを複数作る方法
ここからエントリーポイントを複数作る方法の説明に入ります。

Vueをrailsに導入すると`app/javascript`下に`/packs/hello_vue.js`と`App.vue`ファイルが生成されます。
この単一のvueであれば上記で紹介した記事を参考にしていただければ表示までできると思います。

では本題の2つめのエントリーポイントはどうやって作るの？の方法を説明していきます。

とは言っても、`/packs/hello_vue.js`と`App.vue`のような組み合わせを新たに作るだけです。

ここでは仮に`details`というエントリーポイントを作る前提で、行うべきことを書いていきます。
まずはjavascriptファイルの作成です。

```javascript
// details.js
import Vue from 'vue'
import App from '../details.vue'

document.addEventListener('DOMContentLoaded', () => {
  const el = document.body.appendChild(document.createElement('details'))
  const app = new Vue({
    el,
    render: h => h(App)
  })

  console.log(app)
})

```

続いてvueファイルの作成です。

``` vue
<!--details.vue-->
<template>
  <div id="details">
  </div>
</template>

<script>
export default {
  name: 'Details',
}
</script>

<style scoped>
</style>

<!--必要最低限のコードのみ書いています-->
```

最後に上記Vueを表示するHTMLの作成です。

``` html
<%= javascript_pack_tag 'details' %>
<%= stylesheet_pack_tag 'details' %>

<div id="details"></div>

```

これで二つ目のエントリーポイントが完成です！

具体例というよりも方法にフォーカスした内容となっておりますので、実際のコンテンツの部分はご自身のものを当てはめていただければ良いと思います。

コメント、ご指摘等ございましたらご連絡お願いします。
初心者とCommand PhaseScriptExecution failed with a nonzero exit code

初めてCommand PhaseScriptExecution failed with a nonzero exit codeが起きました。

ただし自分の場合は単純な原因でした。
一つの例として共有します。

# 状況
### 環境
・xcode 12.4
・CocoaPods 1.10.1
podで導入したライブラリ
・R.swift・Realm

ビルド実行時に「Command PhaseScriptExecution failed with a nonzero exit code」が発生しビルドが止まってしまう。

# 原因
プロジェクト名.xcodeprojを開いていた。

# 解決策
プロジェクト名.xcworkspaceを開き、ビルドが成功しました。

みたことがないエラーが起きると焦ってしまいますが落ち着いて対応していきたいです。
開発をする際に気をつけること

# 開発をする際に気をつけること
（会社による）

自分のメモがてらに残しておきます。
　
# 作業管理
・Redmineなど、プロジェクト管理をするソフトウェアを使う。
・イシュー　＝　問題　＝　チケットに起こす。
・チケットは誰でも上げて良い。
・チケットはいるいらないに関わらず、どんどん上げる。
（いるいらないは上げてから判断する）
・自分の振られたチケットの内容を確認する。
・チケットの作業者は、管理する側が振る。
・プロジェクトごとに管理者は違うので、
誰が管理する方か、確認すること。
・チケットは勝手に判断して閉じない。
・進行し始めたら、ステータスを進行中にする。
・終わった作業は、解決、ステータスにする。
・チケットに、関連する項目や、関連するURL、作業の変更箇所、確認が必要な箇所、なども書くと、他の方が助かるのと、進捗を把握しやすくなるので、なるべくする。（自分が休んだ場合なども分かりやすい。）
・プロジェクトのお客さんとやりとりすることがある。
お客さんの名前など、把握しておくこと。
（文面など、心配なら、slackに投げて確認していただくと良い。）
・プルリクエストしたら、Redmineのチケットに
そのURLを貼ること。（プルリクされる方は忙しいので）
・プルリクエストが返ってきたら、またURLを貼り直し、レビューしてくれる方から、OKが出るまで修正するの繰り返し。



# Git
・masterブランチと、developブランチと、
作業するブランチは、
それぞれ違うブランチである。
・作業するブランチ名は決まっているので
確認すること。
（作業するブランチはチケット名を使うことが多い）
・作業のチケットを行うごとに、
developブランチから生やす。
・コンフリクトしたら相談する。
・日本語でコミットのメッセージを書かない。
（誰が読むか分からないから。）
【戒め】Gitに誤ってPushした時の対処法 

2021-04-02追記
自身の理解不足で誤解を招きやすい記事になってしまっていたため、内容を一部訂正しました。

#概要
最近、個人開発でGit hubへPushを行なった後にミスが発覚し、どうしていいかわからず混乱する一幕がありました。自分への戒め　兼　今後万が一起きてしまった時の備忘録として残します。

#結論

ローカル環境でrevertコマンドを使用し、変更内容をリモートへ反映する

```
#取り消したいCommit識別番号を確認（以下のabcde...の部分）
$git log 

commit abcdefghijklmnopqrstuvwxy
 Author: 有吉　貴紀 <>
Date:   Wed Mar 31 12:20:05 2021 +0900

#取り消したいCommitをrevertする
$git revert <Commit識別番号(abcde...)>


#変更内容をリモート環境へpushする
$git push
```

#git revert コマンドとは

既存のCommit履歴を取り消すためのコマンド。
私のような個人の失敗だけでなく、特定のCommitが原因で不具合が出てしまった場合の修正手段として使われるコマンドです。
Commitを取り消したという事実や変更内容を記録するため、リモートにpushしたCommitに対しても安全に使うことができます。
指定した識別番号のCommitが取消対象となり、その前後にあるCommitには影響が出ません。
複数取り消したい場合はそれぞれに対して処理を行う必要があります。

また、「既存のコミットを元に戻す」という点について、同じような機能を持つコマンドにresetがあります。
resetコマンドは、指定したCommitまで巻き戻し、過去の作業内容をなかったことにする処理です。
「Commitを取り消した」という事実や変更内容が残らないため、リモートにpush済みで公開されているCommitに使ってはいけません。理由として、他の開発者が公開されたCommitからブランチを切って開発を進めている可能性があるからです。そこでresetを実行してしまうとpush不能になってしまうため、共同開発の場合は基本的にrevertを使いましょう。

また、revertを使う上で重要なポイントがもう一点あります。
それは、機密性の高い情報(個人情報やセキュリティデータ等)を誤ってpushした場合に使用すべきでないということです。
上で説明した通り、revertはファイルの変更内容をCommitし直す性質を持っているため、すぐ気づいてリモート環境からファイルを削除しても、Commit履歴からファイルの中身を確認出来てしまいます。


それでは実例を見てみましょう。

環境変数.envファイルを作成し『ログインパスワード』を書き込んで保存

```
$vi .env

$cat .env
ログインパスワード
```

.envをpushし、リモート環境に上げてからやらかしに気づく...

```
$git add .env
$git commit -m "うっかりミス"
$git push
```
![0a812b85736554698c2f9e8a9dfa0ef1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/746705/01008e5f-72d8-b26c-dfd5-9e9be5c1b4a4.png)


最初に書いた通り、"うっかりミス"Commitをrevert、pushする

```
$git revert Commit識別番号(abcde...)
(コメント編集のためviが開かれますが i→:wqで閉じる)

Revert "うっかりミス"
 1 file changed, 1 deletion(-)
 delete mode 100644 .env


$git push

Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.![e035b4af6f7200bccbc417c327e2f165.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/746705/55cc3a74-f45b-9943-4fdb-ffcd6f5b3351.png)

Writing objects: 100% (2/2), 267 bytes | 267.00 KiB/s, done.
Total 2 (delta 1), reused 0 (delta 0)

```

![e035b4af6f7200bccbc417c327e2f165.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/746705/53fec3ae-ac38-e275-1a61-0f87ebdc78ae.png)

リモート環境上はファイルが削除されていますが

```
$git log -p -1 (-pは差分表示 -1は出力するログの件数を指定)

diff --git a/.env b/.env
deleted file mode 100644
index 2da2f36..0000000
--- a/.env
+++ /dev/null
@@ -1 +0,0 @@

-ログインパスワード

```
logでは差分として表示されてしまい、ここから情報漏洩する可能性も...
revertでのCommit取消はCommitが再度記録されるため、機密性の高い情報(個人情報やセキュリティデータ等)を上げてしまった場合、完全に取り消せないことがわかりました。
じゃあどうするの?という点については、まだまだ学習不足で正確なことがわかっていないため省きます。今後の学習でわかり次第追記していきます。


#最後に
revert,resetどちらにも言えることは、開発上あまり好ましくない行為だということ。
開発メンバーやユーザーに多大なる迷惑をかけてしまわないよう
①branch、プルリクでの確認というフローを常に意識すること
②branchをリモートへpushする前の確認を徹底すること
以上２点を行なっていきます。
続・長年の疑問だった「Lightmap Bakingで何が原因で重くなるのか」問題、いい加減決着をつける

前記事→[長年の疑問だった「Lightmap Bakingで何が原因で重くなるのか」問題、いい加減決着をつける](https://qiita.com/warapuri/items/88ae7cd1e89fda63d3ad "長年の疑問だった「Lightmap Bakingで何が原因で重くなるのか」問題、いい加減決着をつける")の続き


## 検証１２：ライトの種類でベイク時間が変わるのか

DirectLightを大量に置くことはないと思われるが（太陽が何個もないという意味）、他のライトは大量に置くことがある。
そういったわけで、Spot Light、Point Light、Area Light の3種類の比較を行った。

| ライトの数 | Spotベイク時間 | Pointベイク時間 | Areaベイク時間 |
|:-:|:-:|:-:|:-:|
|1 | 0:00:17 | 0:00:18 | 0:00:18 |
|16 | 0:00:17 | 0:00:20 | 0:00:20 |
|64 | 0:00:20 | 0:00:29 | 0:00:28 |
|100 | 0:00:20 | 0:00:33 | 0:00:32 |
|150 | 0:00:20 | 0:00:40 | 0:00:41 |
|200 | 0:00:21 | 0:00:48 | 0:00:47 |
|256 | 0:00:21 | 0:00:58 | 0:00:54 |

![2021-03-30_13h55_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72960/81100441-3541-29c0-5ac0-47c1433a361f.png)

### 検証結果

驚くべきことに、Spot Lightはいくら増やしてもベイク時間が増えないという結果となった。
流石に何かの間違いだろうと思って、500個1000個とやってみたが、それぞれ24秒、32秒という結果であり、ほぼ増えないという結果となった。

その後、Spot Lightの「Outer Spot Angle」（影響の範囲）を179度ぐらいの広角にすると、ベイク時間が伸びた。

つまり**Spot Lightのベイクは影響範囲を考慮されており、限定して利用すればベイク時間が短縮できる**という結論となった。
Point LightもArea Lightも影響範囲を限定すればベイクに支障はないと推察できる。

## 疑問：Progressive GPUでやっていたはずなのにいつの間にかCPUに戻ってることがある

「Progressive GPU」を選択してベイクしていたつもりがなかなか終わらなくて、もう一回見てみると「Progressive **CPU**」になってしまっている時がある。バグか？と思ったが、どうやら仕様らしい。

> Note: If the baking process uses more than the available GPU memory, the process might fall back to the CPU Lightmapper. Some graphics drivers with virtual memory support swap to CPU memory instead, which makes the baking process slower.
> (翻訳)注：ベーキング処理で使用可能なGPUメモリーを超える量を使用した場合、処理がCPUライトマッパーにフォールバックすることがあります。仮想メモリをサポートしているグラフィックスドライバーの中には、代わりにCPUメモリにスワップするものがあり、その場合、ベーキング処理が遅くなります。

https://docs.unity3d.com/ja/current/Manual/GPUProgressiveLightmapper.html

**VRAMを確保するために余計なアプリケーションを閉じて、Progressive GPUを使ってベイクする**ようにしよう。

# まとめ

以上の検証結果から、広域マップのライトベイク設定は以下のようにしていく。

1. ベイクの前に余計なアプリケーションを閉じておく
1. 影を落とす側（例えば樹木）はStatic、Cast shadows: On、Receive Global Illumination:Light Probesにする
　![2021-03-30_15h31_27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72960/760b19a6-d392-fb96-96dc-ed52c6a54104.png)

1. 影を落される側（例えば道路、地面）はStatic、Cast shadows: Off、Receive Global Illumination:Lightmapsにする
　![2021-03-30_15h31_50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72960/da7445dc-2338-d12d-7280-46ff04832b03.png)

1. 大量にライトを配置する際はSpot light を利用する。または影響範囲を小さめのライトを使う
1. Progressive GPU LightmapperをON
1. SceneビューではBaked Lightmapを表示させる
1. Max Lightmap Sizeを妥当なサイズに（512~2048あたり）する
1. Lightmap Resolutionを小さい値にして、Baked Lightmapビューで十分な解像度が出ているか確認しながら調整する
![2021-03-30_14h53_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72960/a34d656d-5f9b-5aba-683f-e2826374787a.png)
【Laravel8】npm run dev (sh: mix: command not found)

#経緯
laravelでsassを使うためにnpmをいじっている際にエラーに遭遇しました。

#環境
Laravel Framework 8.34.0

#エラーの内容
以下がエラーの内容です。（抜粋）

```
$ npm run dev

> @ dev /folder/foo
> npm run development


> @ development /folder/foo
> mix

sh: mix: command not found
npm ERR! code ELIFECYCLE
npm ERR! syscall spawn
npm ERR! file sh
npm ERR! errno ENOENT
npm ERR! @ development: `mix`
npm ERR! spawn ENOENT
npm ERR! 
npm ERR! Failed at the @ development script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
```

mixのコマンドがないと言われてしまいました。これは参りました。

#検証
以前は動いていたため、とりあえずlaravelのバージョンを7系に下げてもう一度実行。すると、今度はちゃんと動きました!

ということはバージョンが低いのでしょうか。

#解決方法
バージョンを上げてみましょう。以下のコマンドを入力して実行します。

```
npm i --save-dev laravel-mix@latest && 
npm i --save-dev sass-loader@latest && 
npm i --save-dev postcss@latest && 
npm i --save-dev webpack@latest
```

さて、この状態でもう一度 `npm run dev`を実行します。

```
$ npm run dev

> @ dev /folder/foo
> npm run development


> @ development /folder/foo
> mix


● Mix █████████████████████████ emitting (95%)  
 emit




● Mix █████████████████████████ done (99%) plugins 
 WebpackBar:done

```

今度はちゃんと実行できました！

#おわりに
バージョンは最新に！そして古い記事には注意！

#参考
[Laravel, NPM: Command “mix” not found](https://stackoverflow.com/questions/65718391/laravel-npm-command-mix-not-found)
kubernetesを超手軽に作って触れるサイトで効率的に学ぼう

ここを見ている方はkubernetesは知ってるけど触る環境を用意する方法がわからない/めんどくさいという方が多いかと思います。
なのでk8sとは？という話は省きます。


今回ご紹介したいのは下記のサイトです。
https://labs.play-with-k8s.com/

ここではgithubまたはDockerhubアカウント持っていれば、
ブラウザ上から簡単にk8sを試すことが出来ます。


# 使ってみる。
こちらの画面からログインしていきます。

![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181554/520abb5b-f792-28aa-e7e9-9e30d4fcbdab.png)

ログインするとこんな画面が出てきます。
+ASS NEW INSTANCEをクリックしてk8s用のインスタンスを作成します。
マスターとワーカーの２ノードを用意しましょう。

![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181554/918422c6-7d46-6096-f93c-bfbaa9b474a5.png)

コンソールが開いたら片方(マスターノード)で画面に表示されているコマンドを入力していきます。
まずは1.のkubeadm init~というコマンドをコピペして実行します。

![3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181554/b04c38d3-d4ba-0e5e-6bd6-267e40466264.png)

するとインスタンス上にK8Sが構築されます。

コンソールの最後らへんに表示される kubeadm join～のコマンドをコピーし
もう片方(ワーカーノード)のインスタンスのコンソールを開いて入力します。

![4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181554/a34f5735-b0d8-5c5b-d2b2-261de43b7d2f.png)

完了したら、マスターノードのコンソールに戻り、
最初に表示されていた2. kubeadm apply~をコピーして実行します。


![5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181554/e38cb15b-8832-386f-0380-4766984a0dcf.png)

これで環境の作成は完了です！

最後にワーカーノードを認識できているか確認します。

```
[node1 ~]$ kubectl get node
NAME    STATUS   ROLES                  AGE     VERSION
node1   Ready    control-plane,master   4m12s   v1.20.1
node2   Ready    <none>                 2m4s    v1.20.1
```

出来てますね！
kubectlコマンドも正常に動作します。

# まとめ
制限時間はありますが、ブラウザ上で簡単にk8sを構築し試すことが出来ます！
K8Sを触りたいけど環境を用意するのが大変という方や、まずはコマンドを触ってみたい！という方はぜひ活用してみてください！
【Salesforce】半角カナ文字の文字数を調べてみた

Stringクラスの「length」メソッドを使ってカナ文字の文字数を調べてみました。
全角と半角で文字数に違いはあるのでしょうか？

## 全角カナ文字の文字数は？
まず、全角カナ文字の文字数を確認してみます。
濁点ありでも試してみましたが、いずれの文字数も1文字でした。

``` java
// 全角「カ」の文字数は: 1
System.debug('全角「カ」の文字数は: ' + 'カ'.length());

// 全角「ガ」の文字数は: 1
System.debug('全角「ガ」の文字数は: ' + 'ガ'.length());
```

## 半角カナ文字の文字数は？
続いて、半角カナ文字の文字数を確認してみます。
全角カナ文字と結果は異なり、濁点ありの文字数は2文字でした。

``` java
// 半角「ｶ」の文字数は: 1
System.debug('半角「ｶ」の文字数は: ' + 'ｶ'.length());

// 半角「ｶﾞ」の文字数は: 2
System.debug('半角「ｶﾞ」の文字数は: ' + 'ｶﾞ'.length());
```

## まとめ
全角カナ文字は期待値通り、文字数は1文字となりました。
しかし、半角カナ文字については濁点の有無で文字数が変化するため注意が必要そうです。

## 参考
■String クラス

https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_methods_system_string.htm
【Python】Worksheet.freeze_panes属性を使って、ウィンドウ枠の固定を行う。

pythonを使用してExcelファイルの操作を勉強しています。
本日の気づき(復習)は、ウィンドウ枠の固定に関してです。
pythonでExcelを操作するため、openpyxlというパッケージを使用しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927441/4e3a5f98-db09-8eee-30dd-7b26cf6fda89.png)

上記のようなブック「表」の見出しを見やすくするためウィンドウ枠の固定を行います。

固定方法はWorksheet.freeze_panes属性に、固定するセル番地を設定するだけで

ウィンドウ枠の固定には
「行」「列」「行・列」の3通りあります。

# ウィンドウ枠の固定(行)
表の4行目以降をスクロールするようにしたい場合は・・・

```python
from openpyxl import load_workbook

wb = load_workbook('表.xlsx')
ws = wb.active

ws.freeze_panes = 'A4'

wb.save('表_行固定.xlsx')
```

上記のようにＡ列のセル番地を指定します。

# ウィンドウ枠の固定(列)
表のＥ列目以降をスクロールするようにしたい場合は・・・

```python
from openpyxl import load_workbook

wb = load_workbook('表.xlsx')
ws = wb.active

ws.freeze_panes = 'E1'

wb.save('表_列固定.xlsx')
```

上記のようにＡ列以外で１行目のセル番地を指定します。

# ウィンドウ枠の固定(行・列)
表の１～３行とＡ～Ｄ列を固定して
４行、Ｅ以降をスクロールするようにしたい場合は・・・

```python
from openpyxl import load_workbook

wb = load_workbook('表.xlsx')
ws = wb.active

ws.freeze_panes = 'E4'

wb.save('表_行列固定.xlsx')
```

上記のようにＡ列以外、２行目以降のセル番地を指定します。

意外とお手軽に実装できました。
【備忘録】Pythonのライブラリ名とプログラムのファイル名が同じだとAttributeErrorが出る【Python】

## 概要
ふと「csvファイルにあるn行1列のデータをリスト型で読み込んで、指定された数だけランダムに要素を表示しよう」と思ったのでPythonで実装することに。
「データの読み込み」と「ランダムに要素を取り出す」という処理の練習になればいいな～というふんわりした理由で書き始めること10分、PowerShellで実行するとAttributeErrorが出現したのでその原因と解決策を書き散らしておきたいと思います。

というわけでテキトウに書いているので間違いがあるかもしれません。予めご理解よろしくお願いします。

## 実行環境
- OS: Windows 10 Home
- Python: ver. 3.9.0
- エディター: Visual Studio Code(ver. 1.54.3)
- CUI: Windows PowerShell

Pythonは公式サイトからDLしたexeファイルを使ってインストールしたものを使っています。
ライブラリはpipを使ってインストールしています。
VScodeには適当な拡張機能を入れてあります。

## 原因と解決策
実際に書いていたプログラムは以下の通り。

```python:random.py
import random


def main():
    '''
    dataset.csvからデータをリスト型で読み込み、要素をランダムで表示する
    表示する要素数はキーボードから入力する
    '''
    # データの読み込み
    # データ以外の文字(「"」「,」「\n」の3つ)は削除する
    with open('dataset.csv', mode = 'r', encoding = 'utf-8') as f:
        data = list(map(lambda x: x.replace('"', '').strip().rstrip(','), list(f.readlines())))
    n = int(input('n = '))
    print(type(data))
    print(len(data))
    print(random.choice(data))


if __name__ == '__main__':
    main()
```

上記のプログラムをPowerShell上で実行すると

```:PowerShell
$ python random.py
n = 1
<class 'list'>
20
Traceback (most recent call last):
  File "長ったらしいので省略\random.py", line 21, in <mo
    main()
  File "長ったらしいので省略\random.py", line 17, in mai
    print(random.choice(data))
AttributeError: module 'random' has no attribute 'choice'
```

といった感じでエラーが出ます。
アトリビュートエラー、randomモジュールはchoiceという属性を持っていません。

おかしいなぁ、randomライブラリにはchoice関数があるはずなのに。

というわけでAttributeErrorについてググって見ると原因が判明。
それは......

**ファイル名とモジュール名が一緒** だから。

はい。君、予約語って知ってるぅ？←
気づいてしまえばしょーもないミスでした。

そりゃモジュールとファイル、同じ名前のものがあればごちゃごちゃにもなります。
というわけで解決策はファイル名を`random.py`から`rand.py`に変えるというものでした。

ファイル名を変えた状態でプログラムを実行すると以下のようになります。

```:PowerShell
$ python rand.py
n = 1
<class 'list'>
20
re
```

はい。実行できました(変数nについては触れないでください)。

## 結論
ファイル名はプログラム内で登場する関数や変数と被らないようにしましょう(あたりまえ)。

## おまけ
ちなみに、dataset.csvの中身は以下の通りです(Pythonの標準ライブラリの名前を適当に抜粋したものです)。

```:dataset.csv
"string",
"re",
"difflib",
"textwrap",
"unicodedata",
"stringprep",
"readline",
"rlcompleter",
"struct",
"codecs",
"datatime",
"zoneinfo",
"calendar",
"collections",
"collections.abc",
"heapq",
"bisect",
"array",
"weakref",
"types"
```
WindowManagerで追加したviewをアニメーションで移動させる。

オーバーレイアプリで詰まったのでメモ
全画面にViewを配置してその上で動かすとイベントが取られて操作ができなくなる。
しかし、今度は動かしたいViewを配置すると、アニメーションで範囲外に出ると表示できなくなる状態だった。
なので、windowManagerへ追加したView自体を移動させたかった

```Kotlin
// windowManager でViewを追加
val params = WindowManager.LayoutParams(
            100, 100,
            WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
            or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
            PixelFormat.TRANSLUCENT)

view = inflater.inflate(R.layout.hoge_view, null)
windowManager.addView(view, params)


//横へ移動するアニメーションを準備
val animatorX = ValueAnimator.ofInt(params.x, params.x + 100).apply {
                duration = animateDuration
            }
animatorX.addUpdateListener {
                val x = it.animatedValue as Int
                if (view.isAttachedToWindow) {
                    //windowManagerでViewを更新させる。
                    params.x = x
                    windowManager.updateViewLayout(view, params)
                }
            }
AnimatorSet().apply {
                play(animatorX)
                start()
            }


```
【CakePHP2】EmailComponent.phpでのメールヘッダ設定メモ

# はじめに
cakePHP2でメール送信処理にて、メールヘッダを付与する際にハマりかけた部分の注意点になります。

# 環境
cakePHP:2.4

# ことのはじまり
メールのヘッダにパラメータを設定するときに、追加したパラメータが正しく設定できなかった事例がありました。
ざっくり説明すると、メールヘッダに以下のユーザ定義パラメータを用意して、trueを指定すると設定が有効化されるという内容になります。
（パラメータの詳細は割愛します）


 `X-USE-HOGEHOGE = true;`

そしてコントローラ側で、以下のようにパラメータ設定しました。

```php:コントローラの設定部分（修正前）
   class myEmailSendClass extends EmailComponent {
       // ・・・（省略）・・・
       // ヘッダを有効化する
       $this->headers['X-USE-HOGEHOGE'] = 'true';
   }
```

このときに、実際に送信されたパラメータをチェックすると、`X-`が余分についてる状態でした。

 `X-X-USE-HOGEHOGE = true;`


#原因など 

もとの処理を見てみると、`EmailComponent.php`では、
`X-`をヘッダに付加してから、`CakeEmail.php`を利用する仕様でした。
そのため、ヘッダに余分が`X-`がついてしまいました。

そこで、以下のようにコントローラの設定部分を見直して正しくヘッダ設定できるようにしました。

```php:コントローラの設定部分（修正後）
   class myEmailSendClass extends EmailComponent {
       // ・・・（省略）・・・
       // ヘッダを有効化する
       $this->headers['USE-HOGEHOGE'] = 'true';
   }
```

```php:scripts/lib/Cake/Controller/Component/EmailComponent.php

/**
 * Associative array of a user defined headers
 * Keys will be prefixed 'X-' as per RFC2822 Section 4.7.5
 *
 * @var array
 */
   public $headers = array();

   // ・・・（省略）・・・

/**
 * Send an email using the specified content, template and layout
 *
 * @param string|array $content Either an array of text lines, or a string with contents
 *  If you are rendering a template this variable will be sent to the templates as `$content`
 * @param string $template Template to use when sending email
 * @param string $layout Layout to use to enclose email body
 * @return boolean Success
 */
	public function send($content = null, $template = null, $layout = null) {

        $lib = new CakeEmail();

        // ・・・（省略）・・・

        // ここで、接頭語として "X-"を付与しています。
        foreach ($this->headers as $key => $value) {
           $headers['X-' . $key] = $value;
        }
		   
        $lib->setHeaders($headers);

        // ・・・（省略）・・・

        $sent = $lib->send($content);

    }

```

#所感 
使用しているクラス（Component）によって、メールヘッダのユーザ定義（`X-`）を補完する場合があるみたいなので、
気をつけねばなと思いました。

元々、Cake自体のメール送信処理では、標準のメール送信処理が入ってるので、特別な理由がない場合は、
こちらを使用した方が良いのかもと思いました。

ちなみに、2021年時点で[Cake4の標準Mailer](https://github.com/cakephp/cakephp/tree/master/src/Mailer)の[仕様](https://book.cakephp.org/4/ja/core-libraries/email.html)を見ると、自分で設定する必要があるみたいです。

> ヘッダーの設定
> Mailer の中に、自由にヘッダーをセットできます。Email を使用する際、 独自のヘッダーにプレフィックスの X- をつけることを忘れないでください。
Gitの基本（リポジトリとは）

日々の学習で新しく学んだことを共有します。プログラミング初学者なので、至らぬ点がありましたら指摘していただけると助かります。

#Gitの基本

リポジトリとは「ファイルやディレクトリの状態を記録する場所」らしいです。（引用：サル先生のGit入門）

ゲームに例えると、セーブデータを保存できる場所のようなものと考えると良いでしょう。ゲーム内でのプレイヤーがどこまで進んだかなどの情報が、データとしてリポジトリに記録されるというわけです。

また、リポジトリ内に保存することで、そのセーブデータの保存履歴は記録として残り、いつでも昔のデータをロードすることができるらしいです。この仕組みは「バージョン管理」と呼ばれています。

---

この記事は以下の情報を参考にして執筆しました。
サル先生のGit入門：https://backlog.com/ja/git-tutorial
テストに関する基礎の基礎

# はじめに
テスト is 何？　何にもわからんという方向けのものになっています。
解説する内容はこちらになります。

- 基本用語（ブラックボックステスト、ホワイトボックステスト、単体テスト、結合テスト、総合テスト）
- 同値分割
- 境界値テスト
- 分岐網羅
- 条件網羅

# 基本用語
## ブラックボックステスト
システムの内部構造を考慮せずに仕様を満たしているかどうかのみを確認するテスト手法です。
「プログラムが正常に動作しているか」ではなく、「望んだ機能ができているか」を見るテストになります。
内部的なものを考慮せず、機能だけを見るため、ユーザ目線でのテストです。

ちなみに、エンジニアのような内部をよく知る人がやるブラックボックステストを<b>グレーボックステスト</b>といいます。

## ホワイトボックステスト
全てのプログラムが意図した通りに動作しているかを確認するテスト手法です。
プログラムの構造、ロジック、制御の流れなどが正常かを見るテストになります。
内部をガッツリと考慮しているため、エンジニア（作り手）目線でのテストです。

# 同値分析
ブラックボックステスト技法の一つです。テスト手法というよりも、入力データの分析手法になります。
同じ影響を及ぼす入力値のグループ（同値クラス）に分け、その中から代表値を定めてテストに使用します。

<b>ex) 自分の誕生月を入力する画面でのテスト</b>
有効同値クラスになると推測される入力値

　　1, 2 , 3, 4, 5, 6, 7, 8, 9, 10, 11, 12   =>  1以上12以下なら有効

無効同値クラスになると推測される入力値

　　-1, 13, 100, 1.2 etc...   =>  1未満、12より大きいなら無効

同じクラスの入力値ならば得られる結果は同じであると考えて、クラスから１つ代表値を選んで入力値とする

<b>いいところ</b>

- 仕様上のエラーの確認ができる
- テスト項目を省略できる（全部の値を入れる必要がないため）

#境界値テスト
ブラックボックステスト技法の一つです。上の同値分割と併用して使われることが多いものになります（境界値を判定するのに同値分析が使われたりします）
同値クラスの境界値にはバグが潜みやすいという経験則に基づいたテストになります。

<b>ex) 自分の誕生月を入力する場所でのテスト</b>

　正常な結果が返る条件は「1以上12以下」であるため、境界値は1、12になる

このように、コーディングにおける「<=」と「<」、「>=」と「>」の記述ミス、読解ミスを起こしやすいという前提の元行われるものになります。

<b>いいところ</b>

- 条件分岐でのありがちなミスを検証できる
- あるあるなバグを見つけやすい

# 分岐網羅
ホワイトボックステスト技法の一つです。
条件分岐処理（if文, switch文）の true or false を少なくとも一度は実行するテストになります。
<b>ex)</b>
if (A or B) {
処理1;
} else {
処理2;
}

この時のテストケースは、

A = True, B = False　処理1が実行
A = False, B = False　処理2が実行
これで分岐網羅達成

（B = Trueのケースがなくても条件分岐処理のtrue, falseのパターンを通っているのでOK）

# 条件網羅
条件分岐処理が複数ある場合、それぞれの条件がtrue, falseの場合を組み合わせたテストのこと

<b>ex)</b>
if (A or B) {
処理1;
} else {
処理2;
}

この時のテストケースは

A = True, B = False　　 処理1が実行
A = False, B = True　　 処理1が実行
A = False, B = False　　処理2が実行
これで条件網羅達成
【エラー備忘録】[Vue warn]: Invalid prop: type check failed for propのエラー

##原因

コンソールに出ているエラー内容は以下の通り。

```
[Vue warn]: Invalid prop: type check failed for prop "taskId". 
Expected String with value "1", got Number with value 1.
```

##原因
APIから取得したtaskIdはNumber型.
それに対してTaskShowComponentのpropsのtaskIdはString型。
データ型が一致していない。

関連するコードは以下の部分。

```vue:TaskListComponent.vue
<router-link v-bind:to="{name: 'task.show', params: {taskId: task.id}}">

<script>
export default {
  methods: {
    getTasks(){
      axios.get('/api/tasks')
        .then((res) => {
          this.tasks = res.data;
        });
    },
</script>
```

```js:app.js
{
   path: '/tasks/:taskId',
   name: 'task.show',
   component: TaskShowComponent,
   props: true
},
```



TaskListComponentのrouter-linkのparamsをString型に変換してみる。

```vue:TaskListComponent.vue
 <router-link v-bind:to="{name: 'task.show', params: {taskId: task.id.toString()}}">
```

これでエラーが解消した。
AWS SDK for PHP を EC2Roleを通して利用する

AWSのリソースをプログラム上から操作するためにはSDKを活用します。
AWS SDKを使ってリソースを操作するためにはAWSの認証情報を持っている必要がありますが、
サーバやコード内に認証情報を入れるのはセキュリティ上あまり推奨できません。

そこで利用するのが、EC2Roleです。
EC2インスタンスにRoleを適用することで認証情報をサーバ内に置くことなくAWSのリソースを操作できます。

SDK自体の導入は他の記事をご参照ください。

# コード
今回はS3とRekognitionを例にコードをご紹介します。

S3へ画像をアップロードするPHPコードです。

``` s3-upload.php
<?php

require 'vendor/autoload.php';

use Aws\S3\S3Client;  
use Aws\Exception\AwsException;

$bucket = "test-bucket";
$file_Path = "/home/centos/img/test.png";
$key = "20210315_101046-3374.png";

try {
    //Create a S3Client
    $s3Client = new S3Client([
        'region' => 'ap-northeast-1',
        'version' => '2006-03-01'
    ]);
    $result = $s3Client->putObject([
        'Bucket' => $bucket,
        'Key' => $key,
        'SourceFile' => $file_Path,
    ]);
    echo $result['@metadata']['statusCode'];
} catch (S3Exception $e) {
    echo $e->getMessage() . "\n";
}

?>
```

AWSRekognitionのコレクションに対して類似画像があるか検索するコードです。

``` rekognition.php
<?php
require 'vendor/autoload.php';

use Aws\Rekognition\RekognitionClient;
use Aws\Exception\AwsException;

try {
    //Create a rekognitionClient
    $rekognitionClient = new RekognitionClient([
        'region' => 'ap-northeast-1',
        'version' => 'latest'
    ]);
    $result = $rekognitionClient->searchFacesByImage([
        'CollectionId' => 'hogehoge',
        'Image' => [
            'Bytes' => file_get_contents(hogehoge.png),            
        ],
        'MaxFaces' => 1,
    ]);
    $Auth_Name = $result['FaceMatches'][0]['Face']['ExternalImageId'];
    if($Auth_Name != ""){
        echo "この写真は" . $Auth_Name . "さんです。";
    }else{
        echo "この写真に写っている方は登録されておりません";
    }

} catch (RekognitionException $e) {
    echo $e->getMessage() . "\n";
}

}

?>
```

# まとめ
EC2RoleとSDKを組み合わせることで、セキュアにAWSを活用したコードを書くことが出来ます！
Python でスニペットの実行時間が気になったときに使える timeit

突然ですが、あなたは 0 以上の隣り合った整数の積を改行区切りでコンソールに表示したいとします。
どのように書いたらいいでしょうか？
いろいろな書き方があると思います・・・(print は省略)

```python
"\n".join(str(i * (i + 1)) for i in range(100))
```

や

```python
"\n".join([str(i * (i + 1)) for i in range(100)])
```

だったり

```python
"\n".join(map(lambda x: str(x * (x + 1)), range(100)))
```

その他、こんなパターンもあると思います。

```python
"\n".join([f"{i * (i + 1)}" for i in range(100)])
```

これは改行が 1 個多いですが print するときに `end=""` を指定すれば同じ結果が得られるのでﾖｼ!

```python
for i in range(100): str(i * (i + 1)) + "\n"
```

## timeit ライブラリ

Python ではこういった断片的なコードの実行時間を、timeit というライブラリを用いてお手軽に調べることができます。
https://docs.python.org/ja/3/library/timeit.html

### コマンドラインから利用する

次のようなコマンドで調べることができます。

```sh
python -m timeit '"\n".join(str(i * (i + 1)) for i in range(100))'
```

1 万ループ回して一番速かったのが 20.9 マイクロ秒だったそう。

```html
$ python -m timeit '"\n".join(str(i * (i + 1)) for i in range(100))'
10000 loops, best of 5: 20.9 usec per loop
```

他のコードでもやってみました。

```html
$ python -m timeit '"\n".join([str(i * (i + 1)) for i in range(100)])'
20000 loops, best of 5: 18.4 usec per loop

$ python -m timeit '"\n".join(map(lambda x: str(x * (x + 1)), range(100)))'
10000 loops, best of 5: 22.7 usec per loop

$ python -m timeit '"\n".join([f"{i * (i + 1)}" for i in range(100)])'
20000 loops, best of 5: 12.3 usec per loop

$ python -m timeit 'for i in range(100): str(i * (i + 1)) + "\n"'
10000 loops, best of 5: 20.7 usec per loop
```

格段に速いのがありますね。

### Python インタプリタで利用する

改行区切りにしたら `SyntaxError: EOL while scanning string literal` になったのでカンマ区切りに変えてます :cry:

```python
>>> import timeit
>>> timeit.timeit('",".join(str(i * (i + 1)) for i in range(100))', number=10000)
0.21407770000000426
```

### まとめ

Python で実装していて、大量データの処理とかで実行時間がシビアだよー、という状況では非常に役に立つライブラリだと思いました。
みなさんもお近くのコードで是非お試しください。
8.3ログアウト

ユーザーが明示的にログアウトするまではログイン状態を保てなくてはならない

ログアウトリンクはあるのでユーザーセッションを破棄するための有効なアクションをコントローラで作成するだけで済む



ログアウトの処理では、log_inメソッドの実行結果を取り消す
→セッションからユーザーIDを削除、deleteメソッドを実行

```
session.delete(:user_id)
```
上のコードで、現在のユーザーをnilに設定できる


log_outメソッド

```app/helpers/sessions_helper.rb
module SessionsHelper

  # 渡されたユーザーでログインする
  def log_in(user)
    session[:user_id] = user.id
  end
  .
  .
  .
  # 現在のユーザーをログアウトする
  def log_out
    session.delete(:user_id)
    @current_user = nil
  end
end
```
log_outメソッドは、Sessionsコントローラのdestroyアクションでも同様に使う
セッションを破棄する（ユーザーのログアウト）

```app/controllers/sessions_controller.rb
class SessionsController < ApplicationController

  def new
  end

  def create
    user = User.find_by(email: params[:session][:email].downcase)
    if user && user.authenticate(params[:session][:password])
      log_in user
      redirect_to user
    else
      flash.now[:danger] = 'Invalid email/password combination'
      render 'new'
    end
  end

  def destroy
    log_out
    redirect_to root_url
  end
end
```


ログイン後、
deleteメソッドでDELETEリクエストをログアウト用パスに発行し、
ユーザーがログアウトして
ルートURLにリダイレクトされたことを確認します。
ログイン用リンクが再度表示されること、
ログアウト用リンクとプロフィール用リンクが非表示になることを確認

そのテスト
ユーザーログアウトのテスト（無効なログインテストも1箇所改良

```test/integration/users_login_test.rb
require 'test_helper'

class UsersLoginTest < ActionDispatch::IntegrationTest

  def setup
    @user = users(:michael)
  end

  test "login with valid email/invalid password" do
    get login_path
    assert_template 'sessions/new'
    post login_path, params: { session: { email:    @user.email,
                                          password: "invalid" } }
    assert_not is_logged_in?
    assert_template 'sessions/new'
    assert_not flash.empty?
    get root_path
    assert flash.empty?
  end

  test "login with valid information followed by logout" do
    get login_path
    post login_path, params: { session: { email:    @user.email,
                                          password: 'password' } }
    assert is_logged_in?
    assert_redirected_to @user
    follow_redirect!
    assert_template 'users/show'
    assert_select "a[href=?]", login_path, count: 0
    assert_select "a[href=?]", logout_path
    assert_select "a[href=?]", user_path(@user)
    delete logout_path
    assert_not is_logged_in?
    assert_redirected_to root_url
    follow_redirect!
    assert_select "a[href=?]", login_path
    assert_select "a[href=?]", logout_path,      count: 0
    assert_select "a[href=?]", user_path(@user), count: 0
  end
end
```

##まとめ
・Railsのsessionメソッドを使うと、あるページから別のページに移動するときの状態を保持できる。
・一時的な状態の保存にはcookiesも使える
・ログインフォームでは、ユーザーがログインするための新しいセッションが作成できる
・flash.nowメソッドを使うと、描画済みのページにもフラッシュメッセージを表示できる
・テスト駆動開発は、回帰バグを防ぐときに便利
・sessionメソッドを使うと、ユーザーIDなどをブラウザに一時的に保存できる
・ログインの状態に応じて、ページ内で表示するリンクを切り替えることができる
・統合テストでは、ルーティング、データベースの更新、レイアウトの変更が正しく行われているかを確認できる
7.5 プロのデプロイ

デプロイの下準備として、まずはこの時点までの変更をmasterブランチにマージ

```
$ git add -A
$ git commit -m "Finish user signup"
$ git checkout master
$ git merge sign-up
```

SSLを有効化

本番環境ではSSLを使うように修正する

```config/environments/production.rb
Rails.application.configure do
  .
  .
  .
  # Force all access to the app over SSL, use Strict-Transport-Security,
  # and use secure cookies.
  config.force_ssl = true
  .
  .
  .
end
```
config.force_sslをtrueに設定するだけ

次に、遠隔にあるサーバーのSSLをセットアップします。本番用のWebサイトでSSLを使えるようにするためには、ドメイン毎にSSL証明書を購入し、セットアップする必要がある
それは、Heroku上でサンプルアプリケーションを動かし、HerokuのSSL証明書に便乗する方法
ただし、この方法はHerokuのサブドメインでのみ有効です。独自ドメインを使う場合はSSL証明書を購入する必要がある


###7.5.2 本番環境用のWebサーバー

番環境のWebサーバー設定ファイル

```config/puma.rb
# Pumaの設定ファイル
max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
threads min_threads_count, max_threads_count
port        ENV.fetch("PORT") { 3000 }
environment ENV.fetch("RAILS_ENV") { ENV['RACK_ENV'] || "production" }
pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }
workers ENV.fetch("WEB_CONCURRENCY") { 2 }
preload_app!
plugin :tmp_restart
```


umaが使うようにProcfileで定義する

```./Procfile
web: bundle exec puma -C config/puma.rb
```

##7.5.3 本番データベースを設定する

更新が必要なのは、データベース設定ファイルconfig/database.ymlのproductionセクションだけ

データベースを本番向けに設定する

```config/database.yml
# SQLite version 3.x
#   gem install sqlite3
#
#   Ensure the SQLite 3 gem is defined in your Gemfile
#   gem 'sqlite3'
#
default: &default
  adapter: sqlite3
  pool: 5
  timeout: 5000

development:
  <<: *default
  database: db/development.sqlite3

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: db/test.sqlite3

production:
  adapter: postgresql
  encoding: unicode
  # For details on connection pooling, see Rails configuration guide
  # https://railsguides.jp/configuring.html#データベース接続をプールする
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  database: sample_app_production
  username: sample_app
  password: <%= ENV['SAMPLE_APP_DATABASE_PASSWORD'] %>
```

###7.5.4 本番環境へのデプロイ
$ rails test
$ git add -A
$ git commit -m "Use SSL and the Puma webserver in production"
$ git push && git push heroku


##最後に
・今後
認証（authentication）システムを導入し、ユーザーがログインとログアウトをできるようにします
ユーザーも自分のアカウント情報を更新できるようにし、Webサイトの管理者がユーザーを削除できるようにします

##まとめ
・debugメソッドを使うことで、役立つデバッグ情報を表示できる

・Sassのmixin機能を使うと、CSSのルールをまとめたり他の場所で再利用できるようになる

・Railsには標準で3つ環境が備わっており、それぞれ開発環境（development）、テスト環境（test）、本番環境（production）と呼ぶ

・標準的なRESTfulなURLを通して、ユーザー情報をリソースとして扱えるようになった

・Gravatarを使うと、ユーザーのプロフィール画像を簡単に表示できるようになる

・form_withヘルパーは、Active Recordのオブジェクトに対応したフォームを生成する

・ユーザー登録に失敗した場合はnewビューを再描画するようにした。その際、Active Recordが自動的に検知したエラーメッセージを表示できるようにした

・flash変数を使うと、一時的なメッセージを表示できるようになる

・ユーザー登録に成功すると、データベース上にユーザーが追加、プロフィールページにリダイレクト、ウェルカムメッセージの表示といった順で処理が進む

・統合テストを使うことで送信フォームの振る舞いを検証したり、バグの発生を検知したりできる
セキュアな通信と高いパフォーマンスを確保するために、本番環境ではSSLとPumaを導入した
7.4 ユーザー登録成功

ユーザーを保存できるようにします。
保存に成功すると、ユーザー情報は自動的にデータベースに登録されます。
次にブラウザの表示をリダイレクトして、登録されたユーザーのプロフィールを表示します。
ついでにウェルカムメッセージも表示しましょう


 保存とリダイレクトを行う、userのcreateアクション

```app/controllers/users_controller.rb
class UsersController < ApplicationController
  .
  .
  .
  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to @user
    else
      render 'new'
    end
  end

  private

    def user_params
      params.require(:user).permit(:name, :email, :password,
                                   :password_confirmation)
    end
end
```
redirect_to メソッドに注目
redirect_to user_url(@user)と等価

###7.4.2 flash
ウェルカムメッセージ表示
二度目は表示しないように

ユーザー登録ページにフラッシュメッセージを追加する

```app/controllers/users_controller.rb
class UsersController < ApplicationController
  .
  .
  .
  def create
    @user = User.new(user_params)
    if @user.save
      flash[:success] = "Welcome to the Sample App!"
      redirect_to @user
    else
      render 'new'
    end
  end

  private

    def user_params
      params.require(:user).permit(:name, :email, :password,
                                   :password_confirmation)
    end
end
```

flash変数の内容をWebサイトのレイアウトに追加する


```app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  .
  .
  .
  <body>
    <%= render 'layouts/header' %>
    <div class="container">
      <% flash.each do |message_type, message| %>
        <div class="alert alert-<%= message_type %>"><%= message %></div>
      <% end %>
      <%= yield %>
      <%= render 'layouts/footer' %>
      <%= debug(params) if Rails.env.development? %>
    </div>
    .
    .
    .
  </body>
</html>
```

Bootstrap CSSは、このようなflashのクラス用に4つのスタイルを持っています（success、info、warning、danger）
sucess dengerの場合

```
flash = { success: "It worked!", danger: "It failed." }
```

###7.4.3 実際のユーザー登録
ここまでの変更がうまくいったかどうか確認するため、実際にサンプルアプリケーションでユーザー登録を試す


まずはデータベースの内容を一旦リセット

```
rails db:migrate:reset
```

##7.4.4 成功時のテスト
ここで一旦、有効な送信に対するテストを書く
これにより今後バグが埋め込まれたらそれを検知できるようになる

assert_differenceというメソッドを使ってテストを書く


content_tagを使ってレイアウトの中にflashを埋め込む

```app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
      .
      .
      .
      <% flash.each do |message_type, message| %>
        <%= content_tag(:div, message, class: "alert alert-#{message_type}") %>
      <% end %>
      .
      .
      .
</html>
```
Railsのcontent_tagというヘルパーを使ってる
#content_tag（出力したいタグ,表示させたい内容 , クラス名（変数展開も出来る））
Next.jsでTypescript導入するとき特に何もしなくていいよって話

# 概要
Next.jsマジで親切、Typescript導入に何か特にすること無いよって話です

# Next.jsでTypescript導入するとき
`create-next-app`でNext.jsのプロジェクトを作ってみます

```
> npx create-next-app
```

その時生成されたプロジェクトにはTypescriptは入っていません。

```json:package.json
{
  "name": "hoge",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  },
  "dependencies": {
    "next": "10.1.2",
    "react": "17.0.2",
    "react-dom": "17.0.2"
  }
}
```

Typescriptをインストールします。

```
> yarn add --dev typescript @types/react @types/node
```

これで`yarn run dev`を走らせてみます。
すると下記のようなログが表示されます。

```
$ next dev
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
info  - Using webpack 4. Reason: future.webpack5 option not enabled https://nextjs.org/docs/messages/webpack5
We detected TypeScript in your project and created a tsconfig.json file for you.
```

>We detected TypeScript in your project and created a tsconfig.json file for you.

Typescriptがあるの見つけたから、tsconfig.json作っておいたよ、ってことですね。
マジで親切。

これでデフォルトの`index.js`を`index.tsx`に変更してもちゃんと動きます。
![スクリーンショット 2021-03-31 20.10.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202053/3c971dec-cda6-8c51-2ec3-408b28c41979.png)
AWS Rekognitionで簡単に顔認証ができた

AWS Rekognitionは画像分析が簡単にできるサービスです。
今回はCliを利用して顔認証をしていきます。

# コレクションを作成
まずは顔の情報を保存するためのコレクションを作成します。

``` 
$ aws rekognition create-collection  --collection-id "Face"
CollectionArn: aws:rekognition:ap-northeast-1:000000000:collection/Face
FaceModelVersion: '5.0'
StatusCode: 200
```

# コレクションへ顔を登録
作成したコレクションに顔画像を登録します。
画像はS3にあげてから、それを指定して登録します。
external-image-idを画像に写っている人の名前とかにすると認識時にわかりやすくなります。

```
$ aws rekognition index-faces \
       --image '{"S3Object":{"Bucket":"hogehoge-bucket","Name":"hogehoge.jpg"}}' \
       --collection-id "Face" \
       --max-faces 1 \
       --quality-filter "AUTO" \
       --detection-attributes "ALL" \
       --external-image-id "kaotesuto"
```

コレクションに登録されたか確認します。

```
 $ aws rekognition list-faces --collection-id "Face"
FaceModelVersion: '5.0'
Faces:
・・・・・・・
 ExternalImageId: kaotesuto
```

# コレクションの画像と比較
コレクションに登録された画像の中に、同じ人の顔があるか検索します。
CLIですとこちらもS3の画像を指定する必要があります。
S3を経由したくない場合はAWS SDKを利用してPHPなどから画像を直接AWS Rekognitionへ送ることが可能です。


```
$ aws rekognition search-faces-by-image \
     --image '{"S3Object":{"Bucket":"hogehoge-bucket","Name":"hogehoge.jpg"}}' \
     --collection-id "Face"
FaceMatches:
- Face:
    BoundingBox:
      Height: 0.5754799842834473
      Left: 0.31725001335144043
      Top: 0.16239699721336365
      Width: 0.4426969885826111
    Confidence: 99.98900604248047
    ExternalImageId: kaotesuto
  Similarity: 100.0

```

今回は同じ画像を使ったのでSimilarityが100で完全一致しました。
試して見る際は別の写真などを試してみてください！


# まとめ
コレクションを作って登録するだけで簡単に顔認証が可能になります。
表情が変わっていてもかなりの精度で認識をしてくれます。
これを使って顔認証システムなど作るのも面白いと思います！
自社サイトのwordpressをマルチサイト化した話

## 概要
自社サイトをマルチサイト化する機会があったので、その時の内容をまとめてみました。
マルチサイトにはサブドメイン方式とサブディレクトリ方式の二つがありますが、今回はサブドメイン方式で作成しています。

## 手順
#### 1. サイトネットワーク設置できるようにする
wordpressディレクトリ直下の`wp-config.php`に以下の行を追加します。

```wp-config.php
define('WP_ALLOW_MULTISITE', true); <-追加

/* 編集が必要なのはここまでです ! WordPress でブログをお楽しみください。 */
```

追加する場所は、
`/* 編集が必要なのはここまでです ! WordPress でブログをお楽しみください。 */`
と書いてある行の一つ上になります。
また、`wp-config.php`はホームページの設定が書いてある重要なファイルであるため、編集前にバックアップを取ることをお勧めします。

#### 2. すべてのプラグインを無効化する。
これを行わないと次の手順に進めません。
また、マルチサイト化完了後に再度必要なプラグインを有効化する必要があるため、現在有効にしているプラグインをメモしておくとよいです。

#### 3. サイトネットワークを設定する
管理画面左メニューの「ツール」→「サイトネットワーク設置」を選んでサイトネットワークの設定を行います。
なお、「サイトネットワーク設置」の項目は手順１を行わないと表示されません。

「サイトネットワーク設置」をクリックし、遷移した先の画面でサイトネットワーク名、管理者のメールアドレスを入力します。
初期値として現在のサイト名、メールアドレスが入力されていますので、適宜変更して「インストール」を押してください。

#### 4. wp-config.phpと.htaccessを編集
インストールが終わり、以下のような画面が表示されたら画面の指示に従ってwordpressディレクトリ直下の`wp-config.php`と`.htaccess`にコードを追加します。
追加するコードの内容は環境によって変わるようです。
また、両ファイルともに編集前にバックアップを取っておいてください。

![スクリーンショット 2021-03-31 150819.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1261074/ef0b170a-1c9b-618f-5683-1e3514abc3a1.png)


#### 5. 画面をリロード
ファイルの編集が終わったら管理画面に戻り、画面を再読み込みしてください。(再ログインが求められます)
以下の画面のように、画面上部に「参加サイト」「サイトネットワークの管理」が表示されればマルチサイト化完了です。(白塗りの場所にはサイトネットワーク名が入ります)

![スクリーンショット 2021-03-31 154226-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1261074/287ca24d-71c2-703b-9ba0-f4d43d8df502.png)


「参加サイト」にカーソルを当てるとサイトネットワークの管理画面と、個別サイトの管理画面を選択することができます。
個別サイトの管理画面に戻り、無効化したプラグインを有効化してください。
「サイトネットワークのみ」とあるプラグインはサイトネットワークの管理画面から有効にしてください。
Ruby 文字列と数値


##文字列
文字列は、文字を扱うための値です。
文字を"(ダブルクォーテーション)または'(シングルクォーテーション)で
囲むことで文字列を生成することができます。

```ruby
"Hello World"
'Hello World'
```

+を使うことで、文字同士を繋げることもできます。

```ruby
"Hello " + "world" 
=> "Hello world"
```
また、メソッドを使用することで、様々な処理を行うことができます。
例えば、lengthメソッドを使用すると文字数をカウントすることができます。

```ruby
"Hello World".length
=> 11
```

##数値
数値は数を表現する値です。文字列のように"や'で囲む必要はありません。

```ruby
# 整数
10

# 負の値
-10

# 小数
3.14
```

数値は演算子が使えます。

```ruby
1 + 1
=> 2

10 - 5
=> 5

1 > 0
=> true
```

数値は、to_sメソッドで文字列に、to_iメソッドで数値に変換することができます。

```ruby
1.to_s
=> "1"

"1".to_i
=> 1
```

式展開を使うことで、文字列の中に数値を入れることができます。

```ruby
"年齢は#{20}歳です"
=> "年齢は20歳です"

"年齢は#{20 + 1}歳です"
=> "年齢は21歳です"
```
PHP 8.0 を使ってベンチ結果もとってみた

PHP 8.0 の評判が良いようなので、自分の開発環境も PHP 8.0 にバージョンアップしてみました

## PHP 8.0 のインストール

具体的な手順はネットにたくさん出てるので省略

	$ rpm -qa | grep php
	php-pecl-msgpack-2.1.2-1.el7.remi.8.0.x86_64
	php-pecl-mongodb-1.9.0-1.el7.remi.8.0.x86_64
	php-pecl-memcached-3.1.5-4.el7.remi.8.0.x86_64
	php-cli-8.0.3-1.el7.remi.x86_64
	php-pecl-apcu-5.1.20-1.el7.remi.8.0.x86_64
	php-common-8.0.3-1.el7.remi.x86_64
	oniguruma5php-6.9.6-1.el7.remi.x86_64
	php-mysqlnd-8.0.3-1.el7.remi.x86_64
	php-mbstring-8.0.3-1.el7.remi.x86_64
	php-pecl-igbinary-3.2.1-1.el7.remi.8.0.x86_64
	php-sodium-8.0.3-1.el7.remi.x86_64
	php-8.0.3-1.el7.remi.x86_64
	php-opcache-8.0.3-1.el7.remi.x86_64
	php-pdo-8.0.3-1.el7.remi.x86_64
	php-process-8.0.3-1.el7.remi.x86_64

## PHP 設定関連

JIT関連の設定を行った。
/etc/php.d/10-opcache.ini

	opcache.enable=1
	opcache.enable_cli=1
	opcache.jit=on
	opcache.jit_buffer_size=100M

## JIT ベンチ

JIT の有無でベンチ結果
単純にループするだけのスクリプトで比較してみました。

sample.php

	<?php
	$start_time = microtime(true);
	$count = 0;
	for ($i=0; $i<1000; $i++) {
		for ($k=0; $k<1000; $k++) {
        		$count += 1;
    		}
	} 
	$end_time = microtime(true);
	echo "Exec time: " . ($end_time - $start_time) * 1000 . " ms" . PHP_EOL;

### opcache.jit=off 実行結果

	$ time php sample.php
	Exec time: 860.44096946716 ms
	
	real	0m0.907s
	user	0m0.883s
	sys	0m0.022s

### opcache.jit=on 実行結果

	$ time php sample.php
	Exec time: 291.85199737549 ms
	
	real	0m0.336s
	user	0m0.312s
	sys	0m0.023

### ベンチ結果考察

JITをonにするだけで３倍弱高速化してます。
JITを有効にするだけでここまで高速化するのは驚きです。

高速化は処理時間が短くなるだけでなく、CPUの使用時間も短くなってます。
timeコマンドだとphpの起動時間も入ってますが、それでもCPU使用時間が短くなることが確認出来ました。

ただしJITで高速化されるのは PHP の実行時のみ。実際のWebだとここまでの高速化はされません。

それじゃあまり意味がないようにも思えますが、高速化されることは正義ですw

特に今時のクラウドでWebサーバをオートスケールしている場合は、高速化よりも軽くなるメリットの方が大きいかも。
レスポンスタイムの改善は少なくても、Webサーバの台数が減ることはコストメリットになりますからね。
Nutanix ClustersのREST APIを試してみる

マルチクラウドを実現する仕掛けとして、Nutanix Clustersが使えるようになったので、REST API経由で操作してみようと思います。

# 使える構文を確認してみる

とりあえずログインをしてREAT API エクスプローラから見ていきます。

![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181554/6f600753-4c08-113e-60e4-c25e2b05730e.png)

v2のページがうまく動かないときはurlを書き換えてv3に入ってみましょう。
:9440/api/nutanix/v3/api_explorer/index.html


エクスプローラ画面が開きました。
操作ができるように上部のユーザ名とパスワードを入力してExploreしておきましょう。

![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181554/21f3c1b3-e08b-4e56-c627-85eb76b9ba0c.png)



# REST API エクスプローラから使ってみる
Centos8のイメージを入れたくらいしかしていない環境なので、一旦イメージを確認してみます。

imagesの項目の /images/list を開いてみます。

![3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181554/1b22ad04-fe09-0a51-4721-1015acdcf311.png)

Parametersは一旦{}だけ加えて Try it out!をクリックします。

![4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181554/9fef61a8-570c-44dc-b623-18bfa2cfbb4e.png)

レスポンスでcentos8の情報が返ってきましたね。

# 外部から使ってみる
Try it outを実行するとCurlコマンドが出力されるので、それを活用してPostmanから操作してみましょう。
PostmanにてURLとheadersなどを入力をしていきます。

![5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181554/122b59f2-64cf-0150-e208-02a8f4f20317.png)

準備が出来たら送ってみます。

![6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181554/ec86fd3d-2470-ea6c-b7a3-5acae534fe0a.png)


REST API エクスプローラと同様の結果が出ましたね！
あとは同じ方法でREST APIでの操作ができるので、自動化が捗りますね！

 
# まとめ
REST APIを活用して、積極的に運用の自動化をしていきましょう！