OmniAICreator/Qiita-1.07M huggingface dataset:
オブジェクト指向プログラミング (object-oriented programming)   -Python- 

# オブジェクト指向プログラミングとは
「モノ」を組み立てるように表現して，コンピュータに動作をさせる

## 例を交えて，各用語を説明する．
オブジェクト，インスタンス：
各々の家(現実に存在する)
			伊藤君の家，佐藤君の家，...
クラス：それぞれの家の設計図(実在しない)
		家の設計図

クラスから実態を作成されたもの．
→オブジェクト-object-(インスタンス-instance-)
クラスから実態を作成すること．
→インスタンス化-instantiation-

## 実際にクラスを作成していこう．

家は，各々同じ構造で，違うのは表札だけであるとする．
すると，次のように期待できる．

|クラス|House|
|:---:|:---:|
|属性|name_plate|

これを，Pythonで実装すると次のようになる．

```py

class House:
	def __init__(self, name):
		self.name_plate = name
```
		
ここで，いろいろと期待していなかった文字列が登場している．
これらは，次のようである．
`def`:
関数の宣言時に必要な接頭語
`__init__`:
関数名は，任意の名前を付けることが可能だが，`__init__`とすると特別な意味を持つ
それは，インスタンス化する際に，自動的にこの関数が呼ばれるということである．
`self`:
クラスを呼び出して，新しいインスタンスが作成されたときのインスタンス名が何なのか，クラスの定義時(プログラム作成時)にはわからない．
そのため，実際にユーザがクラスを呼び出したときに用いた名前を得るために'self'を用いている．
慣例的に"self"とすると，自分自身のインスタンス名を表すことになっているが，別の文字列でもよい．
`name`:
実際にname_plateに代入したい名前を疑似的に"name"としている．
***
具体例：
**satoHouse** = class(**"佐藤"**)
                

##メソッド

先ほどは，クラスからインスタンスを作成したときに自動的に行われる処理を定義しただけであるので，具体的にメソッドは定義していなかった．

そこで，クラス Houseにメソッド helloを追加して，次のようにしたい．

|クラス	|House|
|:---:|:---:|
|属性	|name_plate|
|メソッド	|hello|

Pythonで書くと，次のようになる．

```py

class House:
	def __init__(self, name):
		self.name_plate = name
	def hello():
		print("{}の家です．".format(self.name_plate))
```

ここで，**format関数**をさりげなく使っている．

###format関数
**"**任意の文字列{}任意の文字列**"**.format( {}の部分に挿入したい文字列 )


このように書ける．

このように，インデックス指定もできる．
"任意の文字列{0}任意の文字列{1},...".format({0}の部分に挿入したい文字列, {1}の部分に挿入したい文字列)
***

## 継承-inheritance-
クラスを定義した後で，
「あのメソッド便利だったなー．今定義したクラスでも使いたいなー．再定義面倒だなー．」
という場合に継承が便利である．

次のようなクラスを用意し，

|クラス名|Link|
|:---:|:---:|
|属性|a|
||b|

新しく作った次のクラス，

|クラス名	|Chain|
|:--:|:--:|
|メソッド	|sum|
に継承させる．
つまり，次のような構造にする．

|クラス名	|Chain|
|:--:|:--:|
|属性	|a|
|	|b|
|メソッド	|sum|


Pythonでは，次のように実装できる．

```py
class Link:
	def __init__(self):
		self.a = 1
		self.b = 2
```

いざ，継承

```py
class Chain(Link):
	def sum(self):
		return self.a + self.b
```

classの定義時に，次のようにすると良い．

```py
class クラス名(継承したいクラス名):
```
		
これでうまくいくはずである．

次に，継承した子クラスのほうを今編集しているはずなので，
子クラスのほうで，新しく属性を定義してみたいと思う．
つまり，こうしたい

|クラス名	|Chain|
|:--:|:--:|
|属性	|a(Link由来)|
|	|b(Link由来)|
|	|c(Chain内部で定義)|
|メソッド	|sum|

こうするとよさそう．

```py
class Chain(Link):
	def __init__(self):
		self.c = 5
	def sum(self):
		return self.a + self.b + self.c
C = Chain()
C.sum()
```

しかし，これを実行すると，次のようなエラーが出る．
><font color='Red'>AttributeError: 'Chain' object has no attribute 'a'</font>

理由は，親クラスでも，**\_\_init\_\_**が定義されており，
子クラスの**\_\_init\_\_**が優先的に呼び出され，属性a,bは定義されていないことになるからである．

これは，**super関数**を使うことで回避できる．

このようにする．

```py

class Chain(Link):
	def __init__(self):
		super().__init__()
		self.c = 5
	def sum(self):
		return self.a + self.b + self.c
C = Chain()
C.sum()
```

super()は，親クラスを参照する関数である．
.(ドット)以下に，呼び出したい関数を書く
こうすることで，親クラスの関数を呼び出している．

# おわりに
拙い文章で申し訳ないです．
役に立ってくれたら幸いです．

>引用
2. Python 入門 — ディープラーニング入門：Chainer チュートリアル
https://tutorials.chainer.org/ja/02_Basics_of_Python.html#%E3%82%AF%E3%83%A9%E3%82%B9
DockerでMySQLクライアントを動かしRDS(MySQL)に接続する

### 構成イメージ
![スクリーンショット 2019-08-07 8月7日.57.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258803/59008252-9d38-ff8f-78dd-ee5ed5f27411.png)

MySQL(RDS)のDBへ、K8sコンテナ上のMySQLクライアントから接続確認する方法、SQLを流す際のメモです。
同じVPC内のプライベートサブネットに配置してあるRDSインスタンスへ、パブリックサブネットに配置してあるK8sクラスタノードからアクセスします。
既にRDSのDBインスタンスを作成しセキュリティグループの設定なども完了している事が前提です。

### DockerでMySQLクライアントを起動してコンテナからMySQLに接続

```
sudo docker run -it --rm mysql mysql -h{RDSインスタンスのエンドポイント} -u{ユーザー名} -p
```
・K8sのワーカーノードにsshログインし、コンテナ上で上記を実行します。
・ここでパスワードを聞かれるのでRDSインスタンス構築時に入力したパスワードを入力するとMySQLに接続できます。


### DockerでMySQLクライアントを起動してコンテナからMySQLに接続(ファイルを指定してSQL実行する場合)
```
sudo docker run -v /{マウント元ファイルパス}:/work -it --rm mysql mysql -h{RDSインスタンスのエンドポイント} -u{ユーザー名} -p
```
・-vでボリュームをマウントします。
・マウント元ファイルパスにはK8sワーカーノード上のファイルを配置しているディレクトリパスを指定します。
・ここではマウント先ディレクトリを/workとしていますが任意のものを設定します。

### ファイルを指定してSQL実行
```
source /{マウント先パス}/{ファイル名}
```
・source /{マウント先のパス}/{ファイル名}となるように指定する事でファイルに記載したSQLを実行できます。
・ボリュームをマウントしていないと、sourceコマンドでファイルを指定してSQLを流そうとした際に以下のようなエラーとなるためご注意ください。
　ERROR: 
　Failed to open file 'ファイル名', error: 2
秀丸エディタ > 保存時 > 空白行のタブを消す + 行末のタブを消す > オフにする

```txt:動作環境
Windows 10 Pro v1903
秀丸エディタ Version 8.77
```

### コミットする時の違和感

VCSにコミットしようとすると、自分が触っていない行に修正が入っていた。
調べていくと、秀丸エディタが変更していたようだ。

下記の変更が見つかった。

- A. 空白行のタブを消す
- B. 行末のタブを消す

これらは本来は不要なものであるのだが、VCSのコミットにこれらの変更も含まれると「コミットがよごれる」。

自動的な変更は抑止したい。

### 自動変更のオフ

- [37　秀丸の「共通」ファイルタイプの設定3：その他](http://www.miraisha.co.jp/tips/2011/06/373.html)
    - @ 著者･編集者のためのパソコンTIPS集
    - > 「保存するときの変換」では「タブ･空白の変換」は「変換なし」が通常だが、「保存するときに行末の空白を除去する」にはチェックを入れておいたほうがいい。

情報感謝です。

上記ではチェックを入れる説明だが、こちらでは反対にチェックをはずす。

1. cファイルやhファイルを秀丸エディタで開く
2. メニュー「その他 > ファイルタイプ別の設定」選択
3. ファイルタイプは「共通」や「C言語ソースファイル」など対象にしたいものにする
4. 設定の対象: 「その他 > 保存・読込み」選択
5. 保存する時の変換: 「保存するときに行末の空白を除去する」のチェックをはずす

### 不要な空白

そもそもコードに不要な空白があることがおかしいのだが、チームで開発すると誰かがそういうものを入れてしまう。

それを消すだけのrefactorコミットをすればいいが、それはチームの同意が必要。
Nexus 7(2012) Wi-Fi版にAndroid 7.1.2 AOSPをインストールしてみた

研究室と家に転がっているNexus7(2012)Wifi版．
転がっている理由は動作が重いから．
Android5.1.1が重すぎて，どの作業をするにも向いていない．
文鎮と化していたNexusを復活させることは出来ないのかを探してみたら，Android7.1.2をインストールしている[記事](https://ameblo.jp/nattolecats/entry-12307126801.html)を発見．

動作が劇的に早くなるかはわからないが試して見る価値がある！

ということで試してみました．
参考にしたのは上記でも紹介している以下の記事．

https://ameblo.jp/nattolecats/entry-12307126801

# 準備するもの

- Nexus 7 2012 WiFi版（Grouper）

- [twrp-3.1.1-0-grouper.img](https://redirect.viglink.com/?format=go&jsonp=vglnk_150435990091313&key=f0a7f91912ae2b52e0700f73990eb321&libId=j73d1ikt01000n4o000DL1x8c3xbk9qx06&loc=https%3A%2F%2Fforum.xda-developers.com%2Fnexus-7%2Fdevelopment%2From-android-7-aosp-grouper-t3467514&v=1&out=https%3A%2F%2Feu.dl.twrp.me%2Fgrouper%2Ftwrp-3.1.1-0-grouper.img.html&title=%5BROM%5D%5B7.1.2_r33%5D%5BNZH54D%5D%5BGrouper%7CTilapia%5D%5BF2%E2%80%A6%20%7C%20Nexus%207&txt=TWRP%203.1.1)

- [aosp_grouper-7.1.2-ota-eng-20170811.ds.zip](https://redirect.viglink.com/?format=go&jsonp=vglnk_150435994882114&key=f0a7f91912ae2b52e0700f73990eb321&libId=j73d1ikt01000n4o000DL1x8c3xbk9qx06&loc=https%3A%2F%2Fforum.xda-developers.com%2Fnexus-7%2Fdevelopment%2From-android-7-aosp-grouper-t3467514&v=1&out=https%3A%2F%2Fwww.androidfilehost.com%2F%3Ffid%3D745425885120754981&title=%5BROM%5D%5B7.1.2_r33%5D%5BNZH54D%5D%5BGrouper%7CTilapia%5D%5BF2%E2%80%A6%20%7C%20Nexus%207&txt=(Build%202017811))
- [BeansGapps-Mini-7.1.x-20170725.zip](https://redirect.viglink.com/?format=go&jsonp=vglnk_150435996177315&key=f0a7f91912ae2b52e0700f73990eb321&libId=j73d1ikt01000n4o000DL1x8c3xbk9qx06&loc=https%3A%2F%2Fforum.xda-developers.com%2Fnexus-7%2Fdevelopment%2From-android-7-aosp-grouper-t3467514&v=1&out=https%3A%2F%2Fwww.androidfilehost.com%2F%3Ffid%3D889764386195918677&title=%5BROM%5D%5B7.1.2_r33%5D%5BNZH54D%5D%5BGrouper%7CTilapia%5D%5BF2%E2%80%A6%20%7C%20Nexus%207&txt=BeansGapps-Mini-7.1.x-20170725.zip)

# 導入手順
最初の手順として，bootloaderがunlockしているか確認します（lockされていると作業ができないため）．unlock手順を行うとストレージのデータが消えるため，いろいろとやったあとにlockになっていたことに気づくと泣けます．

1. Nexus7をfastbootモードで起動．（電源を切り，音量-ボタンと電源ボタンを同時押しで起動．もしくはADBコマンドで「adb reboot bootloader」）
2. 左下にfastbootという文字とその下にいろいろな情報が記述されています．そこにlockedとされている場合は，lockされているということなのでunlockする必要があります．ターミナルで「fastboot oem unlock」を実行．
3. その後，もう一度fastbootモードで起動し，「fastboot flash recovery twrp-3.1.1-0-grouper.img」を実行し，リカバリにTWRP3.1.1を導入
4. 右上が「Start」の表示になっているのを確認し，音量ボタンで操作して「Recovery Mode」に切り替えて，電源ボタンで決定．
5. TWRPが起動したら，ホーム画面から「Wipe」を選択し，Factory Resetの画面になるのでスワイプ．
6. ここでADBを使って，用意していたzipファイルをタブレットへコピー．「adb push aosp_grouper-7.1.2-ota-eng-20170811.ds.zip /sdcard」
7. ホーム画面に戻り，「Install」を選択，各ディレクトリが表示されるので「sdcard」を選択するとコピーしたzipファイルが表示されているので，それを選択し，インストール．
8. 成功したらホーム画面に戻り，「Reboot」を選択し，「Recovery」をタップ．
9. TWRPが再起動したら，次のzipファイルを「adb push BeansGapps-Mini-7.1.x-20170725.zip /sdcard」でコピー．
10. コピー終了後，ホーム画面の「Install」を選択し，先程と同じようにインストールする．
11. 成功したら「Reboot System」で再起動．
12. Androidロゴがしばらく表示された後に，初期設定を行う．
後置返り値型のconstの場所

C++11導入の後置返り値型がなかなか便利なので、よく使っています。
そこでメソッドにおける`const`の付け方で　？　となったので
備忘録として

# 結論

```c++

class Person {
    int age;

    auto cfunc() const -> const int {
        
       return age;
    }
...


```

# メソッドの`const`
メソッドの`const` は 2(3)種類あります。
1つは返り値が`const`であることを示すもの
2つはクラスの内容に変更を与えないことを保証するもの


これが普通のメソッドだとそれぞれこうなります。

```c++

class Person {
    int age;

     (1)               (2)
    const int cfunc() const {
        
       return age;
    }
...

```

これを後置文法に直したときどうするかにしばらく悩みました。


```c++
auto cfunc() -> const int const {
        
   return age;
}
```
とか、多分（2）の`const`は最後に置くという思い込みがあったのかと
結局こうでした。



```c++

class Person {
    int age;

    auto cfunc() const -> const int {
        
       return age;
    }
...


```
heatmap を使ってみるぞ！！

# heatmap の出力！！

``` python
"""
相関係数行列のヒートマップを作り、相関係数の高い関係を見つける。
はじめに相関係数行列を算出。＞.corrで相関係数行列を作成する。
その後、算出した相関係数行列のヒートマップを出力する。
ヒートマップを見て、相関係数の高いものを探す。
YearBuiltとGarageYrbltの相関係数が高そう！！

# 相関係数行列を出力する
https://note.nkmk.me/python-pandas-corr/

# heatmap の日本語リファレンスっぽいやつ
https://pythondatascience.plavox.info/seaborn/heatmap

# heatmap のオプション
https://stats.biopapyrus.jp/python/heatmap.html

# heatmap の大きくする方法
https://codeday.me/jp/qa/20190323/465958.html
"""
plt.figure(figsize=(20, 20)) # heatmap の大きさを変更出来る！！すげー！！
Xsoukan = X.corr(method='pearson')
sns.heatmap(Xsoukan, # データをセット
            vmax=1, # 
            vmin=-1,
            center=0,
#             annot=True, # 数値が出るけど小さ過ぎて良く分からない。。
            square=True, # 正方形になる
            cmap='RdYlGn_r', # 色の指定をする（他のは未調査）
            linewidths=0.5, # 感覚の余白ラインの太さ
           )
```
Bitbucket から gitHubへ移行する。


プライベートのBitbucketリポジトリ
から
プライベートのGitHubへ移行する。

以下にアクセスして、

https://github.com/new/import


Your old repository’s clone URL
で、bitbucketのソースのURLを入力


Your new repository details
でGitHubでのリポジトリ名を入力


パスワード聞かれたら、Bitbucketのアカウント情報入力


5分くらいで終了
CentOS7 SELinuxを一時的/永続的に無効化/有効化する

## SELinuxとは

Security Enhanced Linuxの略称。
SELinuxを利用するとサービス毎に最小限の権限を与えて管理するなど細かいアクセス制御が可能になる。

nginx等で権限設定できてるのに `Permission denied` とかなるとSELinuxが原因であることが多いです。セキュリティポリシーを個別に設定もできますが今回は無効化する方法をご紹介します。

## SELinuxの設定確認

```
# getenforce
Enforcing
```

- `Enforcing` SELinuxは有効で、アクセス制限も有効
- `Permissive` SELinuxは有効だが、アクセス制限は行わず警告を出力
- `Disabled` SELinux機能は無効

デフォルトは `Enforcing` となっている

## 一時的な変更

OSを再起動すると設定は元に戻ります。

### 一時的に無効化する

```
# setenforce 0
```

`Permissive` になる。 `Disabled` にはできない。

### 一時的に有効化する

```
# setenforce 1
```

`Enforcing` になる。

## 永続的な変更

設定ファイルを `/etc/selinux/config` 書き換えます。
OSを再起動すると設定が反映されます。

### 永続的に無効化する

```
# sed -i 's/SELINUX=.*/SELINUX=enforcing/' /etc/selinux/config
# reboot
```

### 永続的に有効化する

```
# sed -i 's/SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
# reboot
```
開発環境をコピーして本番環境を作ったのに挙動が異なる時

開発環境をコピーして本番環境を作ったのに挙動が異なる…なぜ？？という時に確認したいチェックポイントをまとめてみました。

# はじめに
とにかくエラーを気合で読み解いてみる！！

500エラーが出てエラーの内容が確認できない場合は、display_errorsをOnにする。php.iniは修正せずにphpファイルに

```php:index.php
ini_set( 'display_errors', 1 );
```
を追記する。
※エラー確認後に必ず消す

# apache
- DocumentRootは適切か
- AllowOverrideの設定は適切か
- 何か変更を加えた場合はrestartを忘れていないか

# php
- PHPのバージョンは一致しているか
- 拡張モジュールは足りているか
- php.iniの疑わしい値を比較してみる

# DB
- DBの接続設定は適切か※ホスト名、ユーザー名、パスワード、DB名
- DBのコピーを忘れていないか
- DBの種類(MySQLとかPostgreSQLとか)は一致しているか

# SVNからcheckoutした場合

- 開発と本番のリビジョンが一致しているか
- 開発、本番共に`svn diff `で差分が出ていないか

# ssl
- 開発がhttpsなら本番もhttpsになっているか
- 開発がhttpなら本番もhttpになっているか

# cakephp
- Security.saltとSecurity.cipherSeedは一致しているか

# その他
- パーミッションは適切か
- ドメインやサブドメインの登録は済んでいるか
- emailやftpが使える状態になっているか

---
私が過去に出くわした問題はこの辺を確認したら解決できました(^^)
【Python】 リストの扱い方もろもろ

競プロを始めてみて、頻出そうなリストの扱い方を自分用に整理しました。

#文字列を一文字ずつ取って、リストにする。
コード

```python
input_str = "101"
box = [num for num in input_str] #　ここで、文字列をfor文で用いると、一文字ずつ取り出される。
print(box)
```

出力

```python
['1', '0', '1']
```

※もう少し詳しく。
もう少し丁寧に書くと。

コード

```python
for num in input_str:
    print(num)
```

出力

```python
1
0
1

```
こうなる。要は文字列をforで取ると、一文字ずつ取り出される。


#リスト中の、特定の要素数を求める。
コード

```python
box = ['1', '0', '1']
one_count = box.count("1")
print(one_count)
```

出力

```python
2
```

#リストの順序を並び替える。
コード

```python
numbers = [2, 5, 6, 1, 7, 23, 15, 19, 30, -4]
asce_numbers = sorted(numbers)
desc_numbers = sorted(numbers, reverse=True)

print(asce_numbers) #昇順
print(desc_numbers) #降順
```

出力

```python
[-4, 1, 2, 5, 6, 7, 15, 19, 23, 30] #昇順
[30, 23, 19, 15, 7, 6, 5, 2, 1, -4] #降順
```
JIRAフィールド：必須設定は要注意

###JIRAのフィールド必須化方法
JIRAのフィールド必須にする場合、管理画面の課題→フィールド構成からフィールド設定表示画面を出し、アクションの「必須」を選択すればよい。元に戻すのは「オプション」を選択する。
常に必須化する必要がない場合は、ワークフローの「必須フィールドの検証」機能を使うと良いです。

###JIRAフィールド必須化の注意事項と対処方法
フィールド構成からフィールド設定する際、フィールド構成「Default Field Configuration」に対して変更することは避けるべきです。
「Default Field Configuration」を使っている他のプロジェクトに思わぬ影響を与えることがあります。
画面に設定されていない項目にもかかわらず、必須項目に値がないエラーが出て先に進めなくなるトラブルに見舞われます。

対処方法として、変更したいプロジェクト用のフィールド構成スキームおよびフィールド構成を作成するようにしてください。
フィールド構成スキームは各課題タイプ別に使い分けが可能なので必要に応じて作成すると良いでしょう。

*JIRA Softwareバージョンは7.12.1*
CudaのバージョンアップをしたらVisualStudioが起動しなくなった件

CUDA Toolkit 10.1をインストールしてVisualStudio(2015/2017/2019)で既存のCUDAプロジェクトを開くとVisualStudioが異常終了する現象に見舞われた。解決に至るまでの手順を以下に示す。

#原因調査
##手順1 VisualStudioを/safemodeで起動
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\devenv.exe" /safemode
->CUDA拡張を読み込まないため起動に成功
やはりCUDAが原因か？
##手順2 VisualStudioを通常起動
起動途中でエラーダイアログが現れる。
##手順3 [Debug]ボタン押下
手順1で起動したVisualStudioのインスタンスをデバッガに選択
##手順4 VisualStudioのデバッグ画面で停止箇所を確認
> 例外がスローされました
0x14DFC5D5 (ig9icd32.dll) で例外がスローされました (devenv.exe 内): 0xC0000005: 場所 0x00000000 の読み取り中にアクセス違反が発生しました
ig9icd32.pdbは読み込まれていません
モジュールig9icd32.dllのソースを見つけるために必要なデバッグ情報がig9icd32.pdbに含まれています
モジュール情報
バージョン: 25.20.100.6323
元の場所: C:\Windows\System32\DriverStore\FileRepository\igdlh64.inf_amd64_8a9535cd18c90bc3\ig9icd32.dll

##手順5 逆アセンブル
> 14DFC5BB  mov         edx,dword ptr [esi]
14DFC5BD  add         esp,8
14DFC5C0  mov         dword ptr [ebp-8],edx
14DFC5C3  mov         ecx,dword ptr [ebp+18h]
14DFC5C6  mov         eax,dword ptr [ecx+1D0h]
14DFC5CC  mov         dword ptr [ebp-0Ch],eax
14DFC5CF  mov         eax,dword ptr [ecx+1E4h]
14DFC5D5  mov         esi,dword ptr [eax]  <--- ここでeaxがゼロになっている
14DFC5D7  mov         eax,dword ptr [eax+4]
14DFC5DA  mov         ecx,dword ptr [ecx+1D0h]
14DFC5E0  mov         dword ptr [ebp-18h],esi
14DFC5E3  mov         esi,dword ptr [ebp+8]
14DFC5E6  mov         dword ptr [ebp-14h],eax

#推測
ig9icd32.dllのバージョンに問題があり、関数の引数に矛盾が生じているように見える。
ig9icd32.dllというのはIntel(R) HD Graphics 530のドライバ
#対処
Intel Graphics 530 driverのバージョンを古いものに戻した。
デバイスマネージャでIntel(R) HD Graphics 530の「ドライバーを元に戻す」を実行。
25.20.100.6323 -> 20.19.15.4312 (20.19.15.4835でもOK)
#結果
Visual Studioで無事CUDAプロジェクトを開くことに成功！
【FileMaker】勝手に拡大縮小しないで - ズーム禁止

FileMaker Goのアプリを利用している時、何気なく指が当たって勝手に拡大・縮小してしまったことはありませんか？
結構焦りますよね。
ピンチして拡大できるのは老眼にとてもありがたいのですが、意図しない拡大・縮小はミスをしてしまう可能性があります。
そういう時は、ズームを選択できるようにしておくのも考えておきましょう。

#動き
FileMakerには「[ズームの設定](https://fmhelp.filemaker.com/help/18/fmp/ja/index.html#page/FMP_Help/set-zoom-level.html)」という関数があります。
今回はこれを使って、ズームのコントロールをします。
この関数はFileMaker Pro 6.0よりも古いバージョンからずっと提供されてきているようですので、現在稼働しているFileMakerの大抵のバージョンで稼働可能と思います。
今回は、FileMaker Pro Advanced 18及びFileMaker Go 18で作成・テストをしています。

まずは、原寸表示。
![zoom1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/6f3da616-11a6-b278-8f04-bee9a8efd23d.png)

「縮小」ボタンで表示が小さくなります。
![zoom2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/07a99de4-be4e-c64d-c58c-a446157ca85c.png)

さらに小さくな〜れ〜。
![zoom3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/150b406d-c29f-8cc5-a89b-f15fd37decb7.png)

次は、再度原寸に戻してから「拡大」ボタンをタップします。
![zoom4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/713fa13b-a1d9-c564-fb77-0284b3083b82.png)

さらに大きくな〜れ〜。
![zoom5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/957b734c-9e04-5c3f-31a1-286e09be71fb.png)

こんな感じの動きです。
ウェブサイトでは「小さく表示」「大きく表示」などのような文字やアイコンを設置していたりしますが、そういう感じの機能になります。

#実装
では、どんな実装か見ていきます。
使っているのはボタンバーとズームの設定関数です。
ボタンバーはサンプルですので、目的にあったボタンや文字列、アイコンなどで実装してください。
<img width="919" alt="zoom6.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/3081a32d-760c-041d-ec2e-e20dfd438ace.png">
ズームの設定をそれぞれ押されたボタンにしたがって切り替えています。
この関数は、FileMaker Pro Advanced,FileMaker Go,Runtimeソリューションでしか利用できませんので、ご注意ください。
また、FileMaker Goでは、すべてのズーム設定が行えるわけではなく、最大倍率が200%までとなっています。
詳しくは、「[ズームの設定](https://fmhelp.filemaker.com/help/18/fmp/ja/index.html#page/FMP_Help/set-zoom-level.html)」ページで確認してください。

ここで重要なのは、ズーム設定のロックを「オン」にする部分です。
これがオフになっていると、間違えてダブルタップしてしまったりピンチをした時に拡大・縮小が可能になります。
ロックをオンにすることで、指定された拡大・縮小サイズで表示できます。

#時と場合による
この機能は使うユーザ対象によってはうっとおしいと感じるかもしれません。
ピンチやダブルタップでの拡大・縮小に慣れたユーザであれば全く必要のない機能です。
ただ、ユーザビリティを考えた時、どの年齢層やアプリの慣れ度の差が激しい場合は設定した方がいい機能だと思います。

では、楽しいFileMaker Lifeを。
起動時のInsufficient PCI Resources Detected

#起動時のInsufficient PCI Resources Detected

System:Supermicro SYS-1028U-TNRT+
CPU:Xeon E52600 v4 x2
Memory:32GB x4
GPU:NVIDIA Tesla V100 x1

起動時にBIOSで下記メッセージが出る。
PCI Out of resources condition:
ERROR: Insufficient PCI Resources Detected!!!

でそのまま続行する事も出来るけど、たぶんOS起動しないよ。
というメッセージ。

解決方法は
BIOSのAdvanced>PCI/PnP Configuration設定で
Abobe 4G DecodingをEnableにする事で回避できました。
![GPUerror.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478729/e18f4e29-a44e-1257-bb5e-b543a1a5ff51.png)
![Abobe 4G.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478729/c3fc1d33-a3d1-5de3-ead5-80835c51567c.png)
Linux で swiotlb buffer is full が出てしまったら…

Linuxにおいて、バグっていて使用メモリを解放しないドライバを使ったりや超大量の入出力を行うと `swiotlb buffer is full` が出てシステムがうまく使えなくなることがありますが、その場合Linuxのブートオプション (`/etc/default/grub` 等に書かれている) に以下を加えると解決することが多いです。

1. `iommu=force,merge,nopanic,nopt intel_iommu=on amd_iommu=on` をカーネルの起動パラメーターに付けて様子をみる
2. それでうまくいかなかったら、 `swiotlb=65536` を追加して様子を見る。うまくいくまで`swiotlb`の値を2倍ずつ増やして再起動する。

`swiotlb buffer is full`のエラーメッセージがでる原因はDMA用のカーネル内メモリの割り当て失敗で`swiotlb=65536` は取り敢えず64目がバイトDMA用にとっておくように指示します。ハードウェアによるIOMMUを使えばそのようなメモリーの使用を大幅に削減できます。



### 参考文献
* [IOMMU SWIOTLB Gentoo Wiki](https://wiki.gentoo.org/wiki/IOMMU_SWIOTLB#SWIOTLB_for_high_input_output_.28such_as_graphics.29)
MySQLの文字列比較で末尾に空白があったら注意な件

MySQLの文字列比較で初めて知ったことがあったのでメモ。

## 文字列比較

文字列比較は

- LIKE ： 単純なパターン一致
- NOT LIKE ： 単純なパターン一致の否定
- STRCMP() ： 2つの文字列を比較

などがあるが、"="演算子で実行される文字列の末尾に空白があった場合は無視される。

### "="もしくはLIKEの場合

~~~
select 'a' = 'a', 'a' = 'a  ', 'a' like 'a', 'a' like 'a  ';
~~~

| 'a' = 'a'|	'a' = 'a  '(空白あり)|	'a' like 'a'|	'a' like 'a  '(空白あり)|
|-----------:|------------:|------------:|------------:|
|1|1|1|0|

LIKEの場合は正常に文字列比較するよう。

### STRCMP()の場合 

> STRCMP() は、文字列が同じ場合は 0 を返し、現在のソート順に従って 1 番目の引数が 2 番目よりも小さい場合は -1、それ以外の場合は 1 を返します。

STRCMPの場合も、末尾の空白は無視して同一値として判別するよう。

~~~
select STRCMP('a', 'a'), STRCMP('a', 'a  ');
~~~

|STRCMP('a', 'a')|	STRCMP('a', 'a  ')（空白あり）|
|---:|---:|
|0|0|

### 参照
https://dev.mysql.com/doc/refman/5.6/ja/string-comparison-functions.html#function_strcmp
python3 初めての、postgresql (psycopg2)

```insert-example.sql
NSERT INTO unicorn VALUES(4, 'VgBh54+pXLs9aduJ4+YQ97Ra43CnmCjuqSzLFmvir8c=', :request, 1);
```

```
INSERT INTO unicorn VALUES(4, 'VgBh54+pXLs9aduJ4+YQ97Ra43CnmCjuqSzLFmvir8c=', :request, 1);
```

```
select * FROM unicorn;

 id |                  requestid                   |             requestvalue              | hits 
----+----------------------------------------------+---------------------------------------+------
  4 | VgBh54+pXLs9aduJ4+YQ97Ra43CnmCjuqSzLFmvir8c= | dedb15ad-5b3c-55d1-15f3-6b0899b82828  |    1
(1 rows)

select last_value from unicorn_id_seq;
 last_value 
------------
          3
(1 row)

```

#環境変数を入れえるとパスワードなしでInsertできる

```
 export PGPASS=pass
```

#PythonでPostgreSQLを利用する

[Python から PostgreSQL へ接続](https://qiita.com/dirty_hero/items/f025d781a9769ec40c3a)
↑テーブル削除、作成、レコード挿入、読み込みと一連の処理を確認することができます。


[PostgreSQL Python: Connect To PostgreSQL Database Server](http://www.postgresqltutorial.com/postgresql-python/connect/)
↑設定ファイルから変数を読み込みスマートにPostgreへ接続することができます。
pythonでのDB操作の一連を確認でき、かなりわかりやすかったです。
上記のチュートリアルを通じて、ストアドプロシージャというものを知りました。
[PostgreSQLでストアドプロシージャを使用する](https://www.fujitsu.com/jp/products/software/resources/feature-stories/stored-procedure/?article-index)
予め、DBにクエリテンプレートを作成しておき、クライアントとの通信回数を省略し、レスポンスを早めることができるわけですね。
![postgresq;.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/347413/038d1769-9baf-45ae-0028-0fdd79f2caf0.png)

初めて、PythonでSQL文を扱ってみましたが、これだけサンプルがあれば応用していきやすそうです。


#Updateで更新されるtimestampを使う
Updateの際にトリガ－される関数を作成しておかなければならないようですね

[PostgreSQLで更新日時を記録する「update_at」カラムを実現させる](http://to-c.hatenablog.com/entry/2017/04/17/225826)
[PostgreSQLで更新時のtimestampをアップデートするには](https://open-groove.net/postgresql/update-timestamp-function/)

```
db=> create function set_update_time() returns opaque as '
  begin
    new.<timestamp column>:= ''now'';
    return new;
  end;
' language 'plpgsql';

db=> create trigger update_tri<trigger_name> before update on <database_name>for each row                                                                                                                       
  execute procedure set_update_time();
```

[DROP TRIGGER](https://www.postgresql.jp/document/9.4/html/sql-droptrigger.html)
[DROP FUNCTION](https://www.postgresql.jp/document/8.4/html/sql-dropfunction.html)


#参考
[PostgreSQLシェルスクリプトでSQLに引数を渡して実行](https://qiita.com/A-Kira/items/dde43e0e0aa7cec51938)
[【PostgreSQL】psqlにてパスワードを省略する方法](https://kaede.jp/2015/10/27002723.html)
AWS CDKで「No stack could be identified for the construct at path」ってエラーでハマるなど

AWS CDKを利用していて下記のエラーが発生してハマっていました。

`No stack could be identified for the construct at path`
`pathのコンストラクトに対してスタックを識別できませんでした(Google翻訳)` だそうです。

```console
> cdk synth -v
(略)
No stack could be identified for the construct at path
Subprocess exited with error 1
Error: Subprocess exited with error 1
    at ChildProcess.proc.on.code (/Users/xxx/.anyenv/envs/ndenv/versions/v10.11.0/lib/node_modules/aws-cdk/lib/api/cxapp/exec.ts:110:23)
    at ChildProcess.emit (events.js:182:13)
    at ChildProcess.EventEmitter.emit (domain.js:442:20)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:240:12)
```


## エラー再現

環境構築は以下のような感じ。AWS CDKは利用できる前提で。

```console
> cdk --version
1.2.0 (build 6b763b7)


> mkdir cdk-error-test
> cd cdk-error-test

> cdk init app --language=typescript
```

実装は以下となります。`Outputs` の定義のみ。

```ts:lib/cdk-error-test-stack.ts
import cdk = require('@aws-cdk/core');

export class UseCdkEc2Stack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    new cdk.CfnOutput(scope, 'hoge', { value: 'hoge' });
  }
}
```

そしてエラーとなります。

```console
> cdk synth -v
(略)
No stack could be identified for the construct at path
Subprocess exited with error 1
Error: Subprocess exited with error 1
    at ChildProcess.proc.on.code (/Users/xxx/.anyenv/envs/ndenv/versions/v10.11.0/lib/node_modules/aws-cdk/lib/api/cxapp/exec.ts:110:23)
    at ChildProcess.emit (events.js:182:13)
    at ChildProcess.EventEmitter.emit (domain.js:442:20)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:240:12)
```

## 原因

`new cdk.CfnOutput(scope, 'hoge', { value: 'hoge' });` と第一パラメータを`scope` としてたのですが、`this` じゃないとだめでした・・・圧倒的・・・ケアレスミス・・・

```ts:lib/cdk-error-test-stack.ts
import cdk = require('@aws-cdk/core');

export class UseCdkEc2Stack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    new cdk.CfnOutput(this, 'hoge', { value: 'hoge' });
  }
}
```

tsファイルを修正後`npm run build` コマンドを実行しないとさらにハマりますのでご注意ください。

```console
> npm run build


> cdk synth -v
(略)
Outputs:
  hoge:
    Value: hoge
Resources:
  CDKMetadata:
    Type: AWS::CDK::Metadata
    Properties:
      Modules: aws-cdk=1.2.0,@aws-cdk/core=1.2.0,@aws-cdk/cx-api=1.2.0,jsii-runtime=node.js/v10.11.0
```

`constructor` や`super` のパラメータ指定に引きづられて気がつくのに相当時間がかかりました。
エラーメッセージからだとさっぱりみえてこなかったので、皆さまお気をつけください。

## 参考

AWS CDK - неопределенная ошибка при создании службы AWS ECS - amazon-web-services | Qaru
http://qaru.site/questions/17927695/aws-cdk-vague-error-while-creating-an-aws-ecs-service
初投稿

#初めて投稿

自分の学んだことを、アウトプットするために、Qiitaを初めてみました。
今後色々書いていきます。

##タイトル
###

| 表テスト     |      表テスト  |
|-----------------|------------------------------------|
|これ|あれ|
|あれ|これ|
【C#】【WPF】リモートデスクトップ接続時の再描画について

以前、WPFでWindowsアプリケーションを開発していた時に、
『リモートデスクトップ接続するとアプリケーションが異常終了する』というバグに遭遇した。

アプリケーションを起動した状態のマシンにリモートで繋ぐと、
異常終了してしまう。
実際の運用環境ではリモートデスクトップで繋ぐことは無いので
割と優先度は低かったけど
100%再現するので何かしら明確な原因はあるだろうと思っていた。

で、結局原因は何だったのかというと、
『**Win8以降では、リモートデスクトップ接続すると
WPFのControlでUnloaded～Loadedイベントが発生する**』
（リモートデスクトップでの画面サイズ変更に対応するため）
ということだった。

当該アプリではLoadedイベント内で
内部データを色々と初期化していたが
当然起動時のみ実行される前提で作っていたので
2回実行された影響で例外が発生していた、と。
＃具体的にはDictionaryに重複登録してエラー

Loadedイベント内で初期化するのはよくやるので
注意しておきたい。
＃初期化処理をまとめて1回だけ実行されるようにするとか
　複数回実行されても問題無いようにするとか対策は容易な筈
AWS 資料集メモ

# 学習資料
[AWSサービス別資料（BlackBelt）](https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-service-cut/)
[よくある質問（FAQ）](https://aws.amazon.com/jp/faqs/)

# ワークショップ
[AWSのユースケース）](https://aws.amazon.com/jp/getting-started/use-cases/)

>10分間チュートリアルなら無料枠で可能
 
[セルプペースラボ](https://run.qwiklabs.com/catalog?keywords=introduction&locale=ja&cloud%5B%5D=any&format%5B%5D=any&level%5B%5D=any&duration%5B%5D=any&price%5B%5D=free&modality%5B%5D=any&language%5B%5D=any)

> 一部、無料

# 構成パターン資料

[クラウド推奨構成とお見積り例](https://aws.amazon.com/jp/cdp/)
[AWSアーキテクチャセンター](https://aws.amazon.com/jp/architecture/?awsf.quickstart-architecture-page-filter=highlight%23new)
[形で考えるサーバレス設計](https://aws.amazon.com/jp/serverless/patterns/serverless-pattern/)
[システム設計、運用のべスプラ集](https://d1.awsstatic.com/International/ja_JP/Whitepapers/AWS_Well-Architected_Framework_2018_JA_final.pdf)

# 便利ツール

[AWS CLI BUILDER](https://awsclibuilder.com/home)
[Console Recorder for AWS](https://chrome.google.com/webstore/detail/console-recorder-for-aws/ganlhgooidfbijjidcpkeaohjnkeicba)

# 最新情報

[AWS最新情報](https://aws.amazon.com/jp/new/?whats-new-content-all.sort-by=item.additionalFields.postDateTime&whats-new-content-all.sort-order=desc&wn-featured-announcements.sort-by=item.additionalFields.numericSort&wn-featured-announcements.sort-order=asc)
[AWS ブログ](https://aws.amazon.com/jp/blogs/news/)
[AWS Twitter](https://twitter.com/awscloud_jp)
LaravelでConfigファイルをサブディレクトリに作成する

##やりたいこと

test.phpという設定ファイルをconfig/Sampleディレクトリ配下に配置する。

config
├Sample-test.php
のようにconfigファイルをサブディレクトリに配置した時の利用方法

##環境

```
$ php --version
PHP 7.1.30 (cli) (built: May 28 2019 15:32:26) ( ZTS MSVC14 (Visual C++ 2015) x64 )

$ php artisan --version
Laravel Framework 5.8.30
```

##コード
利用したい場所で下記コードを書くだけ。

```
Config::get(('Sample.test.***);
***には通常通りキーを指定
GraphQLにおけるエラーハンドリングの仕方

### ZOZO TECH BLOG

GraphQLにおけるエラーハンドリングの仕方
https://techblog.zozo.com/entry/graphql_error_handling

とても良い記事

### Adding Errors to the Array

https://graphql-ruby.org/errors/execution_errors.html#adding-errors-to-the-array
Amazon DynamoDBへのインポート処理を書いた

# はじめに

最近、個人開発でもAWSを使い始めたものの、ちょっと難しそうだなぁ…と思って敬遠していたDynamoDB。
「ちょっと試しに使ってみようかな」と思い、まずテスト用にデータをインポートしてみよう、と思ったものの、結局、簡単なツールを作って対応することになったので、経緯などを記事に起こしておきます。

# 経緯

## こんなデータをインポートしたいんだけど…

いつものごとく競馬系の個人開発をしていたので、以下のようなデータをDynamoDBにインポートしよう…と思いました。
ここでは4レコードだけの記載ですが、実際は約290個くらいのレコードを対象としていました。

```json
[
    {
        "Date": "20190105",
        "Course": "京都",
        "GradedRaces": [
            "スポーツニッポン賞京都金杯"
        ]
    },
    {
        "Date": "20190105",
        "Course": "中山",
        "GradedRaces": [
            "日刊スポーツ賞中山金杯"
        ]
    },
    {
        "Date": "20190106",
        "Course": "京都",
        "GradedRaces": [
            "日刊スポーツ賞シンザン記念"
        ]
    },
    {
        "Date": "20190106",
        "Course": "中山",
        "GradedRaces": []
    }
]
```

## 当然バッチ登録するツールあるよね…

ということで「当然バッチ登録するツールはあるよね」ということでgoogle先生に調べてもらいました。

「aws dynamodb batch-write-item」ってのが使えそう…ということで、[Amazonさんのドキュメント](https://docs.aws.amazon.com/cli/latest/reference/dynamodb/batch-write-item.html)を確認…

> If one or more of the following is true, DynamoDB rejects the entire batch write operation:
> * There are more than 25 requests in the batch.

う〜ん、バッチ内に25件以上あるとバッチ書き込みはできないのか…

[ここ](https://docs.aws.amazon.com/cli/latest/reference/dynamodb/batch-write-item.html#options)を見ると、仮に25件以上のデータに対して使えたとしてもjsonのフォーマット変換しないと使えなさそうだ…

## いいやツール作っちゃえ

他にも方法ありそうだけど、大したコーディング量でもないからツール作ってしまえ、となりました。

# 実装

同じことをやっている人はたくさんいそうなので、まぁありがちな内容ですが…
参考にしたのはこの[Boto3のドキュメント](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/dynamodb.html#batch-writing)です。

```python:dynamoimport.py

"""jsonファイルの内容をDynamoDBにインポートする."""
import json
from argparse import ArgumentParser, FileType

import boto3
from tqdm import tqdm


def main():
    """メイン関数."""
    p = ArgumentParser(description='jsonファイルの内容をDynamoDBにインポートする')
    p.add_argument('table', help='テーブル名')
    p.add_argument('json', type=FileType('r'), help='インポート内容記載したjsonファイル')
    args = p.parse_args()

    dynamodb = boto3.resource('dynamodb')
    table = dynamodb.Table(args.table)
    items = json.load(args.json)

    with table.batch_writer() as batch:
        for item in tqdm(items):
            batch.put_item(Item=item)


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

使い方としては

```
python dynamoimport.py テーブル名 jsonファイル
```
です。
異常系の処理は何も書いてないので、実際使う際にはそのへんケアしてあげてくださいませ。

なお、[github](https://github.com/masaminh/dynamoimport)にもソースあげてあります。

# おわりに

DynamoDBは癖が強いなあ…と思いつつ、AWSで個人開発していく上では必要なサービスだと思っているので、これを機に(?)、仲良くやっていきたいなぁと思ってます。
SlackでCircleCIからカバレッジレポート通知を受け取る設定手順

# はじめに
SlackとCircleCIを連携させて、カバレッジレポートをslackから簡単に見えるようにする設定手順をまとめました。
単にCircleCIのArtifacts上にカバレッジレポートをあげるだけでは誰も見てくれないので、誰かがpushするたびに、Slackでカバレッジレポートのリンクが通知されます。

ちなみに、単にGitHubリポジトリの平均的なカバレッジ数だけを見れるようにしたいなら、Codecovとかを使ってバッジを付けるとかでもいいと思います。

# 前提
既にCircleCIのArtifacts上で下記のようにcoverage.htmlを出せている前提です。
![スクリーンショット 2019-08-02 14.49.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221948/5c7444a7-16fd-4473-e572-3778ee301cf1.png)

動作確認したCircleCIのバージョンは2.0です。

# 設定手順
## ①SlackのWebhook URLを取得する
[こちらの記事](https://qiita.com/vmmhypervisor/items/18c99624a84df8b31008#webhook-url%E5%8F%96%E5%BE%97)を参考に取得してください。
基本的には、「設定を追加→対象のチャンネルを選択→Webhook URLを控える→設定を保存」という流れです。
画像とか変えるとかっこいいです。

## ②CircleCIとSlackを連携する
![スクリーンショット 2019-08-02 15.22.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221948/bad2e3f9-1146-f079-6fab-a0144ee1724c.png)

CircleCIの管理画面で NOTIFICATIONS > Chat Notifications に進み、先ほど取得したWebhook URLを貼り付けてSaveします。

これでGitHubにpushされたら、ビルド結果などが自動で通知されるようになります。（カバレッジレポートはまだ）

## ③CircleCIの環境変数を追加する
![スクリーンショット 2019-08-02 15.56.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221948/abf2544c-31f0-9915-0265-402988758650.png)

CircleCIの管理画面で BUILD SETTINGS > Environment Variables に進み、以下の環境変数を追加します。

```
Key: SLACK_NOTICE_HOOK
Value: 先ほど取得したWebhook URL
```

## ④config.yamlを編集する
例えばこんな感じで `store_artifacts` されているとします。

```yaml
- store_artifacts:
    path: coverage.html
    destination: coverage.html
```

その直後に、POSTリクエストするタスクを追加してください。

```yaml
- run:
    name: coverage report
    command: |
      curl -s -S -X POST \
            -d "{'channel': '#your_channel', 'username': 'coverage-report', 'text': ':circleci: coverage report: <https://$CIRCLE_BUILD_NUM-000000000-gh.circle-artifacts.com/0/coverage.html|open report :earth_asia: >(build $CIRCLE_BUILD_NUM)' }" \
            $SLACK_NOTICE_HOOK >/dev/null
```

- channelは任意のチャンネル名を指定してください。
- usernameは分かればなんでもよいです。
- `:circleci:` はslack側でemoji登録されている必要があります。emojiはなくてもよいですがあるとかっこいいです。
- `$CIRCLE_BUILD_NUM` はCircleCIの定義済み環境変数です。特に設定する必要はありません。
- `000000000` はプロジェクトごとのIDです。カバレッジファイルのリンクを開いてURLを確認してください。
- `https://$CIRCLE_BUILD_NUM-000000000-gh.circle-artifacts.com/0/coverage.html` はカバレッジファイルをどのようなパスで配置しているかによって変わるので適宜修正してくだい。
- `SLACK_NOTICE_HOOK` はさきほどCircleCIの管理画面上で登録した環境変数です。

## 完成
こんな感じで通知されます。
`open report` をクリックするとカバレッジレポートを見れます。
やったね！

<img width="641" alt="スクリーンショット 2019-08-02 15.45.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221948/12897de8-1c83-7c51-4d95-c7c4edb51a15.png">

# さいごに
これ作ったはいいけど結局誰も見てくれなそうだな。。。
必要な時に簡単に見れるようになったってことでよしとするか。

# 参考資料
[Circle CI で SimpleCov のカバレッジレポートを出力し、出力結果のリンクをSlackに通知する](http://tbpgr.hatenablog.com/entry/2016/10/26/022119)
console.logとdebuggerの違い

まだまだ、デバッグツールの使い方が分かっていないので、間違っている可能性があります。

jQueryを使ったAjaxの実装をそこそこやってきたので、デバッグツールの使い方をアウトプットします。

#console.log
**一つ**の変数やthisの中身をコンソール上で確認することができる。また、binding.pryのように処理の流れを止めることはない。

#debugger
**複数**の変数やthisの中身を確認することができる。また、debuggerは、binding.pryのようにイベント発火した時に一旦処理を停止して、コンソール上に変数などの値を表示してくれる。



※これらの他にも、自分がたまにデバッグツールとして使うのは、alert()である。
これは、引数括弧内に変数などを記述すれば、コンソールを開かずとも、アラートが表示されるので便利である。
jQueryで動的に生成されたHTML要素から属性値を取得する方法

動的に生成されたHTML要素から属性値を取得する方法

**attrメソッド**を使えば、要素が持つ属性の値を取得することができる(始めから設定してあるHTML要素にも使える。)。


動的に生成されたHTML要素の部分

```js 
       var html = `<div class="comment">
                      <p data-p-comment-id="${comment.id}">
                        <strong>
                          <a href=/users/${comment.user_id}>${comment.user_name}</a>
                          ：
                        </strong>
                        ${comment.text}
                        <a href=/tweets/${comment.tweet_id}/comments/${comment.id}/edit class="ajax_edit_button" >編集</a>
                        <span class="ajax_delete_button" data-tweet-id="${comment.tweet_id}" data-comment-id="${comment.id}" method="delete" >削除</span>
                      </p>
                    </div>`
        return html;
```

ここから、data-tweet-idというid属性(下から4行目の部分)を取得する方法
イベント発火したthisにattrメソッドを適用して、id属性を取得する。


```js
$(document).on("click",".ajax_delete_button",function(){
        var get_tweet_id = $(this).attr('id');
```
【Unityアドカレ2019】簡単にいい感じのUIが作れる Procedural UI Image について

この記事は、[Unity アセット真夏のアドベントカレンダー 2019 Summer](http://assetstore.info/eventandcontest/adventcalendar/eventandcontestadventcalendarasset-adventcalendar2019summer/) の、7日目の記事です。

本日ご紹介するのは、**Procedural UI Image** です。Procedural UI Image は、手続き的にUI画像を作成できるアセットです。アセットストアで人気上位のアセットなのですが、日本語の紹介記事がまだなかったため、書いてみようと思いました。

[Procedural UI Image - Asset Store](https://assetstore.unity.com/packages/tools/gui/procedural-ui-image-52200?utm_source=jppt&utm_medium=20190807)
![d.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159849/f2033646-8fba-98fc-d610-fd8b66282b62.png)

## 概要
Procedural UI Imageは、Unityの標準UIコンポーネントであるImageコンポーネントの拡張です。いくつかのパラメータを指定すると、それをもとにリアルタイムに描画してくれます。**画像素材を準備する必要がないので、Unityエディタから離れることなくサクッとフラットデザインのUIを作成できます。** パラメータをランタイムにいじることでアニメーションも簡単にすることができます。

## どういう人におすすめか

- 手軽にプロっぽいUIを作りたい人
- UIのプロトタイプをサクっと作りたい人
- Unityエディタと画像編集ソフトを往復するのが面倒臭い人

## デモ

記事冒頭にも貼りましたが、こちらは **Procedural UI Image のみ(アイコンを除く。) で作られた、同梱されているデモになります。** かっこいいですね。

![d.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159849/f2033646-8fba-98fc-d610-fd8b66282b62.png)

## 使い方
Procedural UI Image を使うには、まずプロジェクトにインポートします。すると全てのファイルが `Assets/ProceduralUIImage`に入ります。そうしたら、ヒエラルキーで右クリックして `UI/Procedural Image` を選択。これだけでProcedural UI Imageが画面に現れます。

![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159849/4021c40e-7109-417d-3dac-159dd66b5650.png)

## コンポーネント

Procedural UI Imageの各プロパティを説明します。

- `Color`, `Raycast Target`: 標準のImageコンポーネントと同様です。
- `Image Type`: `Filled`と`Simple`は、標準Imageコンポーネントと同様です。`Sliced`と`Tiled`は意味がなく、指定した場合は`Simple`と同じになります。
- `Modifier Type`: 現在のモディファイアタイプです。後で詳しく説明します。
- `Border Width`: ボーダーの太さを指定します。この値を0にするとボーダーのない画像になります。
- `Falloff Distance`: 境界線のぼかし具合を指定します。デフォルトは1になっており、いい感じのアンチエイリアスになります。1以上にすると、影っぽい感じになります。

![e.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159849/c46efcce-5758-cc09-4577-5b11a6c0f095.png)

## モディファイア

モディファイアについて説明します。Procedural UI Image コンポーネントをオブジェクトに追加すると、自動的にモディファイアコンポーネントも追加されます。

モディファイアは`Border Radius`(角丸具合)を柔軟に設定する仕組みです。以下の4つの組み込みモディファイアがあります。自作もできるらしいです。

- `Free Modifier`: 左上、右上、右下、左下の4つの角の丸みを個別に指定します。デフォルトです。
- `Only One Side Modifier`: 上下左右のうち1辺の両角の丸みを指定します。
- `Round Modifier`: まん丸になります。円。
- `Uniform`: 4つ角の丸みを一括で指定します。これが一番使うと思います。

## 設定例
![b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159849/6f1cd85c-7680-6d32-f3ac-4c9409d465fe.png)
![c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159849/f842e72f-c1e6-fca8-7e96-332244724b6d.png)

## 姉妹アセット

同作者のアセット、UI Gradient というアセットがあります。こちらも一緒に使えるようです。こちらは私はまだ購入していないのですが、グラデーションを取り入れると表現力がさらに上がりそうですね。欲しい。

[UI Gradient - Asset Store](https://assetstore.unity.com/packages/tools/gui/ui-gradient-133992?utm_source=jppt&utm_medium=20190807)

## おわりに

というわけで、基本的な説明は以上となります。いかがでしたでしょうか。個人的にマストバイなアセットです。私はこれからの全てのプロジェクトに使っていくと思います。

ちなみに、こちらは私が作成したミニゲームです。Procedural UI Image を使用して、Unity 1週間ゲームジャム で作成したものです。Webブラウザでプレイできますので、よければ是非遊んでみてください。

[寿司を探すゲーム | フリーゲーム投稿サイト unityroom](https://unityroom.com/games/sushi_sagasu)

ありがとうございました。
なぜコンピュータがクラッシュするのか

翻訳
Why do computers crash?

https://www.scientificamerican.com/article/why-do-computers-crash/

なぜコンピュータがクラッシュするのか。

電源部 (Power Unit) の不良:

交流を直流に変換しているが、それがおかしくなると、電源部がノイズを含んだシグナルを発するため、コンピュータがクラッシュする可能性がある。

RAM (Random Access Memory) の不良：

特に高温になると、RAM に保存されている内容が、破壊される可能性があり、コンピュータがクラッシュする可能性がある。

CPU (Central Processing Unit) の不良：

CPU も、高温になると、コンピュータがクラッシュする原因となる。大きな音を発するファンは、これを防ぐためにあるのだが、しばしばファンが回らなとかがある。
ファン自体が、埃やダストを筐体に吸い込んでしまう、ということもある。このダストが、舞い上がることにより、回路がショートすることが起こり、コンピュータがクラッシュする原因ともなり得る。
エアコンプレッサーでダストを吹き飛ばしたり、バキュームクリーナーで吸い込んだりして防ぐことができる。

その他の問題は、トリッキーであり、ソフトウェアのテストや、器材の部品交換によらなければわからない。

もっと永続的な障害は、コンピュータのディスクにおいて発生する。
システム情報を含んだセクタに障害が発生すると、コンピュータがクラッシュする原因となる。

ハードウェアエラーがコンピュータのクラッシュの原因と成りうるが、OS のソフトウェアのエラーによっておこるクラッシュが最も多い。

OS は、ユーザにコンピュータを使用させるインタフェースを提供しているだけではない。
アプリケーションとハードウェアの間の永続的インタフェースを提供しており、異なるプログラム間で、システムのリソースを共有する働きをしている。
その結果、いくつかのエラーが発生する可能性がある。
もっともよくあるものは、OS が誤ったメモリアドレスにアクセスしようとした際に発生する誤動作であり、プログラミングのエラーの結果であろう。
ウィンドウズにおいては、GPF（General Protection Fault） として知られている。
その他のエラーは、OS を無限ループに陥れ、コンピュータが同じ命令を何度も何度も実行して、そこから抜け出すことができなくなり、どんな入力をも受けつけなくなり、リセットするしかなくなる、という状態もある。
その他の問題の可能性もあり、それは、ほとんどないとは考えられるが、メモリバッファにバグ情報を書き込んでしまう、という可能性である。
バッファの限界を「超えて」メモリに書き込まれるという問題もある。
これら同様のエラーは、アプリケーションプログラムのいて発生する可能性がある。
最新の OS は、アプリケーションクラッシュに堅牢であろうが、古いシステムは、このようなバグがシステム全体のクラッシュへとつながる場合がある。
新しい OS 自体は、丁寧に作られており慎重にテストもされている傾向にあるため、比較的安定しているが、プリンタドライバ等、追加のデバイスを使用させるためのドライバ等には、クラッシュの元となる場合がある。
このために、ほとんどの新しい OS は、特別のブートモードにおいて、ドライバをロードさせないのである。
ドライバは、後で、一つ一つ、どのドライバでエラーが発生したかがわかるように、ロードされる。

OS は、それ自身のシステムリソースを正しくマネージすることのジョブに失敗すると、クラッシュする。
OS がデッドロックの状態になることはあり得る。というのも、多くのプログラムが、他のプログラムが必要とするリソースを制御するということが起こりうるからである。
スイッチングは、時間がかかる（メモリ情報がディスクから読み込まれディスクに書き込まれる）ため、マシンがスラッシュする（プログラムを出し入れするだけで、生産的な処理がなにも実行されない）可能性がある。
スラッシングが発生しているマシンは、遅い又は反応がない状態になっているが、ディスクが動作しており、一般的に、その状態から抜け出すのに数分間はかかる状態である。

スラッシングは、メモリスペースの回収・配分が正しくできていないことを示しています。
OS がプログラムを実行する時は、メモリを配分します。OS は、プログラムが停止するときに正しくメモリを回収できない。
そうなると、OS の内部上方では、ほとんど使用できるメモリがない、と出てしまう。
コンピュータは、異なるデバイスが同一の内部 ID を使用しようとして、クラッシュすることがある。
これらの種類のクラッシュは、あたらしいハードウェアをシステムに追加した場合に発生するタイプのクラッシュである。

最後に、OS は、ディスク上の情報に誤りがあると、クラッシュし得る。
これは、コンピュータがクラッシュし、電源が失われ、あるいは、メモリ上の内容を正しくファイルに書き込めなかった場合などにしばしば発生する。
システムのクラッシュは、リブート後にまたクラッシュすることがあり得る。
ファイル破壊は、システムがウィルスに罹患した場合にも発生する。

コンピュータがクラッシュする方法はこのように多くあるため、どのようにして問題を診断したらよいのだろうか？簡単ではないが、問題の解決へのアプローチについてのガイドラインがあります。
以下から入手可能。
http://www.pcguide.com/ts/x/sys/crash.htm

Clay Shields, a professor of computer science at Georgetown
University, explains.

ジョージタウン大学 クレイ・シールズ
2003年1月6日
Elm 条件次第でHtml要素に属性を追加

## viewIf

ElmでDOMを扱う時に`viewIf`という関数をよく使う

```elm:Util.elm
viewIf : Bool -> Html msg -> Html msg
viewIf condition content =
    if condition then
        content

    else
        text ""
```

こいつを使うとログアウトボタンを表示するかどうかなどスッキリかける

```elm:View.elm
a [ onClick CleanupAuthMsg, class "logout" ]
  [ span [ class "text-logout" ] [ text logout ] ]
      |> viewIf isShowLogout
```

## setAttributeIfが欲しい

同じようにsetAttributeIfみたいな関数を作りたくてチャレンジしたのが今回の記事

探したところ[arowMさんの記事](https://qiita.com/arowM/items/345660608ad71917c365)に行き当たった、そこには

```elm:
Attributes.none
```

なんて値があったためこれを使えば

```Utils.elm
setAttributeIf : Bool -> Attribute msg -> Attribute msg
setAttributeIf condition attribute =
    if condition then
        attribute
    else
        Attributes.none
```

が定義できて例えばPC/Mobileでイベントを出し分けたい時に

```elm:View.elm
div
    [ class "hoge"
    , onMouseLeave HogeMsg
        |> setAttributeIf (device == Pc)
    ]
    [ xxxx ]
```

みたいにかけていいなあと思ったのだけれど

> これらを使うには arowM/html に 乗り換える 必要があります。
> arowM/html は elm/html を 置き換える という戦略をとっています。

これがチームの方針的に採用できなかったので代替案を探したところredditでの議論を見つけた

[Adding an attribute based on some condition? | Reddit](https://www.reddit.com/r/elm/comments/b4uhqm/adding_an_attribute_based_on_some_condition/)

結構みんな同じことやりたいんだなあ、としみじみ。

また上記redditのページだけでなく、[このパッケージ](https://package.elm-lang.org/packages/bluedogtraining/bdt-elm/latest/Html-Styled-Bdt)にもあるように

```elm:Utils.elm
attributeIf : Bool -> Attribute msg -> Attribute msg
attributeIf bool attribute =
    if bool then
        attribute

    else
        class ""
```

こいつを採用することも考えたのだけれど

```elm:
class ""
```

これが例えばすでにclassが設定されている要素に対して追加された場合どうなるのだろうという懸念がぬぐい去れなかったためredditでもっとも汎用性高く記述できる以下の例を採用することに落ち着いた

## justIfとList.filterMapによる解決

まずExMaybeモジュールなどを作りjustIf関数を定義する

```elm:ExMaybe.elm
justIf : Bool -> a -> Maybe a
justIf condition x =
    if condition then
        Just x

    else
        Nothing
```

そいつを用いて条件が`True`なら`Just (Attrinbute msg)`を返し、`False`なら`Nothing`を返してやる

そして`List.filterMap`でList内の要素のうち`Nothing`だけをfilterして切り落としてあげると他所でも使えそうな汎用性を持った記述ができる

```elm:View.elm
div
    ([ Just (class "hoge")
     , onMouseLeave HogeMsg |> ExMaybe.justIf (device == Pc)
     ]
        |> List.filterMap identity
    )
    [ xxxx ]
```

最後に、filterMapとidentityの定義と使用例を載せておく

```elm:
filterMap : (a -> Maybe b) -> List a -> List b

numbers : List Int
numbers =
  filterMap String.toInt ["3", "hi", "12", "4th", "May"]

-- numbers == [3, 12]
```

filterMapってfilterとMap両方の特性を持っていて面白い

```elm:
identity : a -> a
```

P.S
`viewIf`に関しても`False`の場合`text ""`を返すことでInternet ExplorerでMsgが飛ばないバグが見つかっている、elmの文脈では慣習的に`viewIf`の中で`text ""`がよく使われるけれど、今回のように`filterMap`するなどの対応の方がBetterかもしれない

[Bug on IE (11,10) - nested Html.map(ed) submodule #156](https://github.com/elm/html/issues/156)

以上。
PPAP で reduce の基本を理解する

プログラミングスクールに通う友人から JavaScript の `reduce` を易しく解説してほしいと言われたので、サンプルコードを書いてみました。

PPAP をネタにして、 `['Pen', 'Pineapple', 'Apple', 'Pen']` という配列から `PPAP` を作るというコードです。
今さらすぎてクソ恥ずかしいネタですが分かりやすいと好評だったので、そのへんは目をつむって読んでいただければありがたいです。

### 対象者
- reduce って何？って人
- reduce が None of 理解 って人

### reduce の基本

基本的な考え方は、配列の要素から文字列や数値などの値に変えることです。

こちらをご覧ください。

[Array.prototype.reduce() - MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)

### さっそく解説

まずはピコ太郎を用意します。

```js
const piko = ['Pen', 'PineApple', 'Apple', 'Pen'];
```

このピコ太郎を reduce してあげて `PPAP` を完成させましょう。

#### 失敗例 1

MDN で reduce の基本構文を読むとこんな感じに書けますが、これは失敗です。
文字列をそのまま返しているから当然ですね。

※ ここでは accumulator を acc, currentIndex を cur と表記しています。

```js
// 失敗例
const ppap = piko.reduce((acc, cur) => {
    return acc + cur;
});
console.log(ppap);

// 出力結果 -> 'PenPineAppleApplePen'
```

#### 失敗例 2

では文字列の頭の 1 文字だけを取得して同じように処理してみましょう。
`string[0]` のようにすれば文字列の 0 番目の文字を取得できます。


```js
// 失敗例
const ppap = piko.reduce((acc, cur) => {
    return acc[0] + cur[0]; // 1 文字目を取得
});
console.log(ppap);

// 出力結果 -> 'PP'
```

なぜこのようになるのか解説します。

配列 piko を見てください。
reduce の基本として、 1 回目のループでは `0 番目の 'Pen' が acc` になり、 `1 番目の 'PineApple' が cur` になります。
そして、それぞれ 1 文字目を取得するので `acc は 'P'` , `cur は 'P'` となり、それを足し合わせた `PP` が次のループの acc となります。

2 回目のループでは `'PP' が acc` 、 `'Apple' が cur` となるわけですが、ここで 1 文字目を取得するため、 acc である `'PP'` は `P` となり、 結果 `PA` が次のループの acc となるわけです。

本来は `P` -> `PP` -> `PPA` -> `PPAP` と足されてほしいのですが、毎回 1 文字目のみを取ってしまうため意図しないものになってしまっています。

では acc はそのまま使って、 cur だけ 1 文字目を取得したらどうなるでしょう。

#### 失敗例 3

```js
// 失敗例
const ppap = piko.reduce((acc, cur) => {
    return acc + cur[0]; // cur だけ 1 文字目を取得
});
console.log(ppap);

// 出力結果 -> 'PenPAP'
```

後半は良さそうですね。ですが、 1 回目のループで acc をそのまま使っているため `Pen` がそのままになってしまいました。
acc, cur の変更だけではどうにもならないようですので、 reduce の第２引数を使ってみましょう。

#### 成功例
```js
// 成功例
const ppap = piko.reduce((acc, cur) => {
    return acc + cur[0];
}, ''); // 第２引数を指定
console.log(ppap);

// 出力結果 -> 'PPAP'
```

できました。
第２引数を指定すると、 1 回目のループの acc を指定することができます。
分かりやすく言い換えると、配列の `-1` 番目にこれを差し込むようなイメージです。

```js
// イメージ

// reduce で第２引数入れる前のピコ太郎
const piko = ['Pen', 'PineApple', 'Apple', 'Pen'];

// reduce で第２引数入れたときのピコ太郎
const piko = ['', 'Pen', 'PineApple', 'Apple', 'Pen'];
```

### 番外編: ピコ太郎以外の用途

要するに頭文字を取ってつなげる処理なので、略したい単語があれば何でも使えます。

```js
const tgif = "Thanks God It's Friday!";
const tgifArray = tgif.split(' '); // ["Thanks", "God", "It's", "Friday!"]

console.log(tgifArray.reduce((acc, cur) => acc + cur[0], ''));
// 出力結果 -> 'TGIF'
```

```js
const diy = "Do It Yourself";
console.log(diy.split(' ').reduce((acc, cur) => acc + cur[0], ''));
// 出力結果 -> 'DIY'
```
AWSのRedHat 7 でディスクの容量増やす時にプチハマった

とあるお仕事で、AWS上でRHEL7の環境を作らないといけなくて、EC2で作ったんですが、デフォルトだと/（ルート）の容量が6GBとかしかない。
「あれー？インスタンス作る時にディスク容量30GBとかにしたつもりなんだけどなー」
と思って確認してみると、ちゃんと30GBになってる。
どうやらパーテーションの拡張が必要らしい。
で、AWSの[ヘルプ](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/recognize-expanded-volume-linux.html)通りに作業。

```console
$ sudo growpart /dev/xvda 2
no tools available to resize disk with 'gpt'
FAILED: failed to get a resizer for id ''
```
ナニコレ初めて見るエラー。

## 素のRHEL7だとgdiskが必要だった
エラーを日本語に訳すと、

```bash
'gpt'でディスクのサイズを変更するツールはありません
```
という事でgptでyumを検索

```console
$ sudo yum search gpt
読み込んだプラグイン:amazon-id, rhui-lb, search-disabled-repos
========================================== N/S matched: gpt ==========================================
gdisk.x86_64 : An fdisk-like partitioning tool for GPT disks

  Name and summary matches only, use "search all" for everything.
```
発見したのでインスコ

```console
$ sudo yum install gdisk
```

### 再度パーテーション拡張
```console
$ sudo growpart /dev/xvda 2
CHANGED: partition=2 start=4096 old: size=12582912 end=12587008 new: size=62910430 end=62914526
```
無事拡張された模様

```console
$ sudo lsblk
NAME    MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
xvda    202:0    0  30G  0 disk 
├─xvda1 202:1    0   1M  0 part 
└─xvda2 202:2    0  30G  0 part /
```

ファイルシステムに反映

```console
$ sudo xfs_growfs /
meta-data=/dev/xvda2             isize=256    agcount=4, agsize=393216 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=0        finobt=0 spinodes=0
data     =                       bsize=4096   blocks=1572864, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=0
log      =internal               bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 1572864 to 7863803
$ df -H
ファイルシス   サイズ  使用  残り 使用% マウント位置
/dev/xvda2        33G  4.1G   29G   13% /
devtmpfs         496M     0  496M    0% /dev
tmpfs            519M     0  519M    0% /dev/shm
tmpfs            519M   14M  506M    3% /run
tmpfs            519M     0  519M    0% /sys/fs/cgroup
tmpfs            104M     0  104M    0% /run/user/1000
```

AWSのドキュメントやクラメソのブログとかでもgdisk無いとダメだよ的な事は書いてなかったので、盲点でした。
前はfdiskとかでドキドキしながらパーティーション変えてたのに便利になったなぁ...gdiskとか初めて知ったよ。
PHP For Beginnersチュートリアル　その8　値チェックについて

##このシリーズの目的

体系的なwebコーディングの訓練ができるようになるために、PHPの初学のきっかけかつ、PHPでログインフォームやフォームを実装することができるようになるために

[PHP For Beginners](https://www.youtube.com/playlist?list=PLgt-G5tEOlKX4LKrBCYfjcyrp7wmnRdAL)

上記のチュートリアルを進めているのでその備忘録。

[前回](https://qiita.com/shitikakei/items/4cf7c57c8a7fbd3c3f65)

##内容

**今回のチュートリアル**

[PHP Tutorial: PHP Forms Handling & Validation Tutorial](https://www.youtube.com/watch?v=3oD8ZNb7lLM&list=PLgt-G5tEOlKX4LKrBCYfjcyrp7wmnRdAL&index=9)

**このチュートリアルでやること**

・コンタクトフォームに値チェックを入れることでエラーメッセージを返せるようにする


**成果物**

```php:index.php
<?php 

	$msg= "";
	
	if(isset($_POST['submit'])) {
		$name = $_POST['username'];
		$email = $_POST['email'];
		$message = $_POST['body'];


	if(strlen($name) < 3) {
		$msg = "Please check your name!";

	} else if(!filter_var($email,FILTER_VALIDATE_EMAIL)) {
		$msg = "please check your email!";

	} else if(strlen($message) <10 ) {
		$msg = "Message is Short. Please check your Message!";

	} else {
		$msg = "Your data is Alllight. Sending an email.";
	}

	echo $msg;
}

 ?>



<!DOCTYPE html>
<html>
<head>
	<title>PHP function Tutorial</title>
</head>
<body>

<form action="index.php" method="post">
<input type="text" name="username" placeholder="Name......"><br>
<input type="text" name="email" placeholder="Email......"><br>
<textarea name="body" placeholder="what`s up? ......."></textarea><br>
<!-- <input type="file" name="attachment"><br> -->
<input type="submit" name="submit" value="Send">
</form>

</body>
</html>


```

## 今回のコードの注釈


```php:filter_varについて

 if(!filter_var($email,FILTER_VALIDATE_EMAIL)) {
        $msg = "please check your email!";
}


/*filter_varは指定したフィルタでデータをフィルタリングする関数である。
第一引数に検証する値を、第2引数にフィルタを指定する。
フィルタには様々な型があるが今回は検証フィルタの中で値が妥当なe-mailアドレスかどうか検証するFILTER_VALIDATE_EMAILを使う。

*/


```

```php:strlen関数

if(strlen($message) <10 ) {
	$msg = "Message is Short. Please check your Message!";
}


/*strlen関数は引数に設定した変数の長さを返す関数。
ここで注意しなければならないのはstrlenは長さを文字数で返すのではなく、バイト数で返すこと。
文字数で返したければmb_strlen関数を使う。
詳しくはマニュアルを見よう。
*/

```




## 参考

[strlen](https://www.php.net/manual/ja/function.strlen.php)
[filter_var]
(https://www.php.net/manual/ja/function.filter-var.php)