OmniAICreator/Qiita-1.07M huggingface dataset:
LeetCode - 104. Maximum Depth of Binary Tree


# 問題
[04. Maximum Depth of Binary Tree](https://leetcode.com/problems/maximum-depth-of-binary-tree/) - こんな感じのツリーが与えられて、これの深さ（高さ）を求める

```
    3
   / \
  9  20
    /  \
   15   7
```

# テストデータ

問題には Given binary tree `[3,9,20,null,null,15,7]` って配列っぽく書かれているが、実際はこんな `TreeNode` オブジェクト

```ruby

#<TreeNode:0x00000000011105e8 @val=3, @left=#<TreeNode:0x00000000011104a8 @val=9, @left=nil, @right=nil>, @right=#<TreeNode:0x0000000001110458 @val=20, @left=#<TreeNode:0x0000000001110408 @val=15, @left=nil, @right=nil>, @right=#<TreeNode:0x00000000011103b8 @val=7, @left=nil, @right=nil>>>
```

なので、テストデータはこんな感じで作ってみた

```ruby

Definition for a binary tree node.
  class TreeNode
    attr_accessor :val, :left, :right
    def initialize(val)
      @val = val
      @left, @right = nil, nil
    end
end

# t - top, l - left, r - right
t = TreeNode.new(3)
tl = TreeNode.new(9)
tr = TreeNode.new(20)
trl = TreeNode.new(15)
trr = TreeNode.new(7)

t.left = tl
t.right = tr
  tr.left = trl
  tr.right = trr

p t # => #<TreeNode:0x00000000011105e8 @val=3, @left=#<TreeNode:0x00000000011104a8 @val=9, @left=nil, @right=nil>, @right=#<TreeNode:0x0000000001110458 @val=20, @left=#<TreeNode:0x0000000001110408 @val=15, @left=nil, @right=nil>, @right=#<TreeNode:0x00000000011103b8 @val=7, @left=nil, @right=nil>>>
```

# 解答

再帰を使って解くことになる。再帰、もうちょっと慣れないとな...

```ruby

# Definition for a binary tree node.
# class TreeNode
#     attr_accessor :val, :left, :right
#     def initialize(val)
#         @val = val
#         @left, @right = nil, nil
#     end
# end

# @param {TreeNode} root
# @return {Integer}
def max_depth(root)
  if !root.nil?
    ld = max_depth(root.left)
    rd = max_depth(root.right)
    1 + [ld, rd].max
  else
    0
  end
end
```

- ノードが `nil` じゃなければ、その次のノード `root.left` `root.right` を再帰的によび、左右のノードがエッジかどうかを調べる
- `1 + recursive_func()`で呼ばれた回数（ツリーを降りた回数）を数える
- この `if !root.nil?` は `if root` でも[いけるようだ](https://stackoverflow.com/questions/18060790/ruby-if-object-nil-or-if-object)

> `if object` tests if `object` isn't either `nil` or `false`. `!object.nil?` tests if `object` isn't `nil`. So when `object` is `false`, they have different values.

つまりこれでいいのか...

```ruby

def max_depth(root)
  if root
    1 + [max_depth(root.left), max_depth(root.right)].max
  else
    0
  end
end
```

# スコア

```yaml

Runtime: 40 ms, faster than 52.11% of Ruby online submissions for Maximum Depth of Binary Tree.
Memory Usage: 9.8 MB, less than 100.00% of Ruby online submissions for Maximum Depth of Binary Tree.
```
curlコマンドでfitbit APIを叩いてみる

# はじめに
curlコマンドを使ってFitbit APIを叩いてみたので、忘れないようにメモしておきます。
<a href="https://dev.fitbit.com/apps">Fitbitデベロッパーサイト</a>からaccess_tokenを取得します。下図の赤枠の部分。
<img width="450" alt="Screen Shot 2020-02-21 at 16.51.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565739/5b4ddfaa-1886-d6f3-5c19-be32a1c3d494.png">

# プロファイルを取得

```
$ curl -H "Authorization: Bearer [your token]" https://api.fitbit.com/1/user/-/profile.json
```

レスポンスを見易くするためjqをインストールすると良いです。

```
$ brew install jq
```

# 歩数を取得
今日から１ヶ月前までの歩数を取得します。

```
$ curl -H "Authorization: Bearer [your token]" https://api.fitbit.com/1/user/-/activities/steps/date/today/1m.json | jq
```
```
{
  "activities-steps": [
    {
      "dateTime": "2020-01-22",
      "value": "6357"
    },
    {
      "dateTime": "2020-01-23",
      "value": "6405"
    },
...
    {
      "dateTime": "2020-02-21",
      "value": "2270"
    }
  ]
}
```

# 食事を記録する
食事を記録するには、Fitbit食品データベースからfoodIdを取得する必要があります。
テストでは「タピオカ」を検索ワードにしています。
検索ワードはエンコードしてPOSTしてあげなければエラーとなります。
エンコード方法はググるといろんなサイトが出てきます。

```
curl -X POST -H "Authorization: Bearer [your token]" https://api.fitbit.com/1/foods/search.json?query=%E3%82%BF%E3%83%94%E3%82%AA%E3%82%AB
```
query以下が検索ワードです。

```
{
  "foods": [
    {
      "accessLevel": "PUBLIC",
      "brand": "",
      "calories": 212,
      "defaultServingSize": 1,
      "defaultUnit": {
        "id": 304,
        "name": "食分",
        "plural": "食分"
      },
      "foodId": 19297945,
      "isGeneric": false,
      "locale": "ja_JP",
      "name": "タピオカフルーツ",
      "units": [
        304
      ]
    },
    {
      "accessLevel": "PUBLIC",
      "brand": "",
      "calories": 300,
      "defaultServingSize": 1,
      "defaultUnit": {
        "id": 304,
        "name": "食分",
        "plural": "食分"
      },
      "foodId": 19297918,
      "isGeneric": false,
      "locale": "ja_JP",
      "name": "タピオカアイス",
      "units": [
        304
      ]
    },
...
    {
      "accessLevel": "PUBLIC",
      "brand": "",
      "calories": 275,
      "defaultServingSize": 1,
      "defaultUnit": {
        "id": 304,
        "name": "食分",
        "plural": "食分"
      },
      "foodId": 21863417,
      "isGeneric": false,
      "locale": "ja_JP",
      "name": "タピオカフロート ココア(ファーストキッチン)",
      "units": [
        304
      ]
    }
  ]
}
```
いっぱいありますね！適当なfoodIdを拾ってきましょう。
ここでは"21863417"を使います。
それでは食事を登録します。

```
curl -X POST \
-H "Authorization: Bearer [your token]" \
--data "foodId=21863417&date=2020-02-21&amount=2&unitId=304&mealTypeId=7&favorite=false" \
https://api.fitbit.com/1/user/-/foods/log.json
```

<img width="200" alt="IMG_6217.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565739/86c3a0cb-05f3-a7ad-7842-3822f85b29eb.png">  <img width="200" alt="IMG_6218.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565739/c994ca18-4e49-4ae0-98d2-b595980da1c6.png">
ちゃんとタピオカフロート　ココア（・・・が登録されましたね！


### 参考
<a href="https://dev.fitbit.com/build/reference/web-api/">Fitbit API</a>
<a href="https://qiita.com/yasuhiroki/items/a569d3371a66e365316f">curlコマンド使い方</a>

今回はここまでです。
update django version 1.11.1 to 2.2

# 背景
Djangoのversionを`1.11.1`から`2.2`へあげた際に、
django-filterのversionも上げる必要があった。（`1.0.4`から`2.2.0`へ上げた。）
すると、`...?id=null`で投げたAPIがBadRequestで返ってきた。

# 原因
- FilterSetからSTRICT確認する処理が廃止されていた。
- https://github.com/carltongibson/django-filter/commit/78febd15cf975b924d47e88e1639e935bbfe5632#diff-c82ea95d2a317d98860bf154f27d3e17L183

### `1.11.1`
- https://django-filter.readthedocs.io/en/stable/ref/filterset.html#handling-validation-errors-with-strict

### `アナウンス`
-https://django-filter.readthedocs.io/en/master/guide/migration.html#filterset-strictness-handling-moved-to-view-788

# 対応１
- FilterViewでstrict=Falseを指定しないといけないとからしいのだが上手くいっていない。

# 対応2
- FILTER BACKENDを自作
- https://github.com/carltongibson/django-filter/pull/788
- こっちで対応した。
データベースにて文字数が最大、最小のデータを抽出する方法

hackerrank挑戦時、つまずいたため、備忘用に記録。

データベースより文字数が最小のデータを抽出するには、

```sql

MAX(LENGTH(カラム名))
```
こんな感じでいけるかなと、思いきやこれではエラー。

正解は、

```sql

SELECT カラム名 FROM テーブル名 ORDER BY LENGTH(カラム名) LIMIT 1;
```



文字数が最大の場合は、

```sql
SELECT カラム名 FROM テーブル名 ORDER BY LENGTH(カラム名) DESC LIMIT 1;
```

これでいける。


文字列の長さにてソートして、LIMIT 1 で1つだけデータを抽出するイメージ。
もちろんLIMIT 1 を指定しなければ文字列の長さが小さい順（DESCをつければ大きい順）に表示される。
『Unity C# 個人用メモ』 WASDや矢印キーでオブジェクトの位置を動かす

自分用メモであり同じような初心者の方へ向けた自分なりの解説
名称がちゃんとあっているのかどうかは正直わかりませｎ

#WASDや矢印キーを入力をしたときに移動させる
適当に作ったゲームオブジェクトに``Rigidbody``コンポーネントを追加してから
以下の様にスクリプトを書く

```
public class NewBehaviourScript : MonoBehaviour
{
    //Rigidbody型のrbという変数を作る
    private Rigidbody rb;

    //float型のpowerという変数を作り、3fを代入する
    private float power = 3f;

    private void Start()
    {
        //リジットボディを取得しrbに代入する
        rb = GetComponent<Rigidbody>();
    }

    void Update()
    {
        //キー入力による値を代入(解説は後で
        float x = Input.GetAxisRaw("Horizontal");
        float z = Input.GetAxisRaw("Vertical");

        //↑で代入された値をVector3型のIdouHoukouという変数に代入する
        Vector3 IdouHoukou = new Vector3(x, 0, z);

        //rbに力を加える
        //velocityは質量などの物理演算を無視するときに使う
        rb.velocity = IdouHoukou * power;

        //rbの回転をさせない様にする
        rb.constraints = RigidbodyConstraints.FreezeRotation;

        //移動範囲の制限
        transform.position = new Vector3(
            Mathf.Clamp(transform.position.x, -5f, 5f),
            Mathf.Clamp(transform.position.y,1f,1f),
         Mathf.Clamp(transform.position.z, 5f, 5f));
    }
}
```
これでWASDや矢印キーを入力したときに移動が出来るようになります
##解説コーナー
###入力受付
```
Input.GetAxisRaw("Horizontal");
Input.GetAxisRaw("Vertical");
```
``Input.GetAxisRaw``
とは入力された物に対してint型(整数)で-1～1を返す
``Horizontal``は``A``,``D``と``←``,``→``がUnityに初期設定として登録されており、
``A``や``←``が入力されている時は``-1``、
何も入力されていない時は``0``、
``D``や``→``が入力されている時は``１``を返す

同じように``Vertical``は、
``s``と``↓``が入力されている時は``-1``、
何も入力されていない時は``0``、
``w``と``↑``が入力されている時は``１``を返す

つまり先ほど書いた以下の

```
Vector3 idou = new Vector3(x, 0, z);
```
``new Vector3(x, 0, z)``この``x``部分と``z``部分に``-1``,``0``,``1``が代入される

###動かす

```
rb.velocity = idou * speed;
```
とあるので
``x``の値が``-1``なら```x(-1)*speed(3f)```となり``x軸``に``-3f``の力を加える
``x``の値が``0``なら```x(0)*speed(3f)```となり``x軸``に``0``の力を加える
``x``の値が``1``なら```x(1)*speed(3f)```となり``x軸``に``3f``の力を加える
ということになる
``y軸``も同じ考えなので割愛

###転がらないようにする
```
rb.constraints = RigidbodyConstraints.FreezeRotation;
```
こちらはゲームオブジェクトのインスペクタ内の
``Rigidbody``コンポーネントの下部にある
``constraints``という項目の２段目にある
回転するかどうかのチェックマークをスクリプト上でつけているだけなので
チェックマークを付けた場合は記入しなくても問題はありません。(てかチェック付けた方が楽)

###移動範囲に制限をつける
```
transform.position = new Vector3(
            Mathf.Clamp(transform.position.x, -5f, 5f),
            Mathf.Clamp(transform.position.y,1f,1f),
         Mathf.Clamp(transform.position.z, -5f, 5f));
```

``Mathf.Clamp(対象,最小値,最大値)``を使用することで
簡単に``transform.position``が``Mathf.Clamp()``内の範囲以上には移動できなくなるという処理が作れます
使わない場合

```
        if (transform.position.x >= -5f)
        {
            transform.position = new Vector3(-5f, transform.position.y, transform.position.z);
        }
```
こんな感じの物を``x``,``y``,``z``それぞれ２パターンで合計６回も書くことになるので``Mathf.Clamp``は偉大です

以上
ファイル操作

```py:
import os
import pathlib
import glob
import shutil

print(os.path.exists('test.txt'))
#test.txtが存在するかどうか判定する。
#存在すればtrue、存在しなければ、falseをかえす。
print(os.path.isfile('test.txt'))
#test.txtがファイルかどうか判定する。
#ファルであればtrue、存在しなければ、falseをかえす。
print(os.path.isdir('design'))
#designがディレクトリであるかどうか判定する。
#ディレクトリであればtrue、ディレクトリなければ、falseをかえす。

os.rename('test.txt', 'renamed.txt')
#test.txtをrenamed.txtに名前を変更する。
os.symlink('renamed.txt', 'symlink.txt')
#renamed.txtをsymlink.txtと同期させる。
#renamed.txtの中身を変更すると
#symlink.txtの中身もrenamed.txtと同じに変更される。
#逆も然り。

os.mkdir('test_dir')
#test_dirというディレクトリをつくる。
os.rmdir('test_dir')
#test_dirというディレクトリを削除する。(中身が入っている場合、削除不可)

pathlib.Path('empty.txt').touch()
#empty.txtというファイルをつくる。
os.remove('empty.txt')
#empty.txtというファイルを削除する。

os.mkdir('test_dir')
#test_dirというディレクトリをつくる。
os.mkdir(r'test_dir\test_dir2')
#test_dir2というディレクトリをtest_dirの中につくる。
print(os.listdir('test_dir'))
#test_dirの中にあるデイレクトリを出力させる。

pathlib.Path(r'test_dir\test_dir2\empty.txt').touch()
#test_dirディレクトリの中にあるtest_dir2ディレクトリの中にempty.txtというファイルをつくる。

shutil.copy(r'test_dir\test_dir2\empty.txt',
            r'test_dir\test_dir2\empty2.txt')
#test_dirディレクトリの中にあるtest_dir2ディレクトリの中にempty.txtファイルを
#test_dirディレクトリの中にあるtest_dir2ディレクトリの中にempty2.txtという名でコピーする。

print(glob.glob(r'test_dir\test_dir2\*'))
#test_dir2の中にあるものを出力させる。

shutil.rmtree('test_dir')
#test_dirを削除する(中身が入っていても削除可能)

print(os.getcwd())
#ディレクトリの位置を出力させる。
```
合成音声 (VoiceText)の利用方法について

# 概要
HOYA株式会社が提供している合成音声(VoiceText)の利用方法についてまとめます。
（VoiceTextを用いてwavファイルを出力してaplayで再生）

# 注意事項
 無料版で作成した音声データの商用利用、二次利用及び配布する行為は禁止されております。
[利用規約](https://cloud.voicetext.jp/webapi/terms-of-service)をご確認の上、本サービスをご利用ください。

※音声データの二次利用例
本WebAPIで作成した音声をYouTube等の動画投稿（共有）サイトにおいて使用・公開する行為

[VoiceText Web API](https://cloud.voicetext.jp/webapi)

# 利用手順
1. API無料利用登録
2. VoiceTextのAPIを呼びwavファイルを取得
3. aplayでwavファイルを再生

<font color="Red">①　API無料利用登録</font>
右記ページより登録し*APIキー*を取得     [VoiceText Web API](https://cloud.voicetext.jp/webapi/api_keys/new)

<font color="Red">②　VoiceTextのAPIを呼びwavファイルを取得</font>
右記マニュアルを参考にCurlコマンドなどでAPIを実行 [API マニュアル](https://cloud.voicetext.jp/webapi/api_keys/new)

例

```
curl "https://api.voicetext.jp/v1/tts" \
     -o "test.wav" \
     -u "YOUR_API_KEY:" \
     -d "text=おはようございます" \
     -d "speaker=hikari"
```

```
curl "https://api.voicetext.jp/v1/tts" \
     -o "test1.wav" \
     -u "YOUR_API_KEY:" \
     -d "text=こんにちわ" \
     -d "speaker=takeru" \
     -d "emotion=happiness" \
     -d "emotion_level=3" \
     -d "pitch=80" \
     -d "speed=80"
```

```
curl "https://api.voicetext.jp/v1/tts" \
     -o "test2.wav" \
     -u "YOUR_API_KEY:" \
     -d "text=こんばんわ" \
     -d "speaker=show"
```

<font color="Red">③　aplayでwavファイルを再生</font>
一つの音声ファイルを再生したい場合

```
$ aplay test.wav
```

複数の音声ファイルを再生したい場合

```
$ aplay test.wav test1.wav
```
MS Learnおすすめラーニングパス 2月号 【AI入門編】


## MSLearnのおすすめラーニングパス第1弾！【AI入門編】
※ [MS Learn](https://aka.ms/MSLearn-Japan)はマイクロソフトのラーニングプラットフォームです

  - [Python と Azure Notebooks での機械学習の概要](https://aka.ms/MLIntro-wPython-LP)：パターンを予測し、傾向を特定するため、Python と Azure Notebooks 上で実行する Jupyter Notebooks で関連付けられているライブラリを活用する方法を学べるラーニングパスです
     
  - [Machine Learning と Azure Data Science Virtual Machine について説明する](https://aka.ms/AzureDataScienceVM-LP)：Azure のデータ サイエンス タスクを実行するための事前構成済みの仮想マシン サービスである、Azure Data Science Virtual Machine を使用して一般的なデータ分析と機械学習タスクを行う方法を学べるラーニングパスです
 
  - [Azure Machine Learning service を使用した AI ソリューションの構築](https://aka.ms/usingAzureML-LP)：Azure の機械学習モデルの設計とデプロイのためのさまざまなサービスをデータ分析で活用する方法を学べるラーニングパスです  
  
  - [機械学習の短期集中コース](https://aka.ms/MLCrashCourse-LP)：AIの基本概念、無料ツールを使ったカスタム機械学習ソリューションを適用する方法、ニューラル ネットワーク、コンピューター ビジョン、ディープラーニング、教師なし学習など、最近話題になっている複雑なトピックについて説明しているコンピューターサイエンスや統計情報をほとんど、またはまったく知らない初心者向けのラーニングパスです
  - [AI エッジ エンジニア](https://aka.ms/AIEdge-LP)：Oxford 大学と協力して作成された複雑な AIアプリケーションの進化したランドスケープの実装方針が示されているラーニングパスです
Haskellのmap関数を使ってみた(はじめての投稿)

#Haskellで、map関数使ってみました。

まだまだHaskellのことはよく分からないですが、解説書を読みながら簡単なプログラムを作り動かしてみました。

```test.hs
sa 1 = "one"
sa 2 = "two"
sa n = "other"

main::IO()
main = do
    let l=[1,2 .. 20]

    print (map sa l)
```

実行結果は

```
["one","two","other","other","other","other","other","other","other","other","other","other","other","other","other","other","other","other","other","other"]
```

となります。

---

##解説

まずは最初の部分。

```test.hs
sa 1 = "one"
sa 2 = "two"
sa n = "other"
```

関数`sa`を定義しています。
引数に`1`が渡されれば`one`を返します。
`2`なら`two`を、それ以外なら`other`を返します。

```test.hs
    let l=[1,2 .. 20]

    print (map sa l)
```

`main`関数の中身です。
上の行は1から20までの整数のリストを表しています。
そのリストを`l`に束縛しています。

map関数は、関数とリストを引数に取り、リストの各要素を関数に適用します。
`map sa l`
つまり、リスト`l`の最初の要素は`1`で、
`sa 1`
を実行します。
次は`2`なので
`sa 2`
を実行します。
これをリストの最後、`20`まで繰り返します。

よって実行結果は、
`"one","two"`の後が`"other"`が連続します。
XcodeのProject間でUIコピペする方法

既に作成したProjectよりエディターエリアにStoryboardを表示させ、コピーするUIのSceneをクリックしxcodeのEditからcopyを選択して別のProjectのstoryboardをクリックしてペーストする。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101462/d344af67-f470-1e99-466e-ac08261d8814.png" width="600">

更にxxxxx.swiftファイルもナビゲータエリアに元ファイルからドラック＆ペーストで貼り付けダイアログの表示でcopyを指定すれば移行できます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101462/2cdf026a-01c9-0ce3-f1d4-99062acfeaa9.png" width="600">
PHPで送信したメールの開封率を計測する方法

# 恒例

https://www.php.net/manual/ja/function.mb-send-mail.php

# Code

```php

mb_language('uni');
mb_internal_encoding('UTF-8');


$from = 'from@me.com';//発信元
$to = 'to@user.com';//送信先のメールアドレス
$subject = '開封率を計測する方法';//メールの件名。

$v = '1';
//プロトコルのバージョンです。この値は 1 にする必要があります。

$t = 'event';
//個々のユーザーについて収集された操作の種類です。

$tid = 'UA-123456-1'
//データの送り先の Google アナリティクス プロパティを識別するための ID です。

$cid = md5($to); 
//個々のユーザーに固有の ID です。送信先をmd5して、uidを作ります。

$ec = 'event-category';
//イベントのカテゴリを指定します

$el = 'event-label';
//イベントのラベルを指定します。

$ea = 'event-action';
//イベントのアクションを指定します

$ev = 'event-value';
//イベントの値を指定します

$dp = 'mail/sale/2020';
//ページの URL のパス部分

$dt = $subject;
//ページやドキュメントのタイトルです


$message = 'メールの本文';
$message.= "
<img src='https://www.google-analytics.com/collect?v=1&t={$t}&tid={$tid}&cid={$cid}&ec={$ec}&el={$el}&ea={$ea}&ev={$ev}&dp={$dp}&dt={$dt}' />
";//開封率を計測する用

$mail_from_text = mb_encode_mimeheader('日本語名前');
$header = "From:{$mail_from_text}<{$from}>\nContent-Type:text/html;charset=UTF-8";
mb_send_mail($to , $subject , $message , $header ,"-f {$from}");

```

# 開封率を確認します

Google アナリティクスのイベントで確認します
【競プロ】セグ木は2冪で配列を取らなくていいという話と30行実装

#えびちゃんありがとうの章
~~可換性を必要とします~~
f(s,node[--r]);をf(node[--r],s);に変えると可換性を要求せずにすむらしいです(凄い)
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">可換性、不要...<a href="https://t.co/2yP0kCqrNP">https://t.co/2yP0kCqrNP</a></p>&mdash; えびちゃん (@rsk0315_h4x) <a href="https://twitter.com/rsk0315_h4x/status/1230769796662194178?ref_src=twsrc%5Etfw">February 21, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
#気持ち
![IMG_20200221_171036.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68551/8c54d358-0b6d-7f22-9b0e-92d00d3b4359.jpeg)

確かに上手く行きそう
#実装
非再帰です/可換性を要求しません

```c++:segment.cpp
template<typename T>
struct segment{
	vector<T> node;
	int n;
	segment(int n):n(n){node.assign(n*2,e);}
	T get(int l,int r){
		l+=n;r+=n;
		T s=e,t=e;
		while(l<r){
			if(l&1)s=f(s,node[l++]);
			if(r&1)t=f(node[--r],t);
			l/=2;r/=2;
		}
		return f(s,t);
	}
	void update(int t,T x){
		t+=n;
        node[t]=f(node[t],x);
		while(t>1)t/=2,node[t]=f(node[t*2],node[t*2+1]);
	}
    void change(int t,T x){
		t+=n;
        node[t]=x;
		while(t>1)t/=2,node[t]=f(node[t*2],node[t*2+1]);
	}
	T e={1,0};
	T f(const T& s,const T& t){
		return {t.first*s.first,t.first*s.second+t.second};
	}
};
```

#verify
[Range Sum Query(AOJ)](http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_B)
[タコヤキオイシクナール(atcoder)](https://atcoder.jp/contests/arc008/tasks/arc008_4)
ローカルで動作するチャットボットの構築（その②：Azure上で接続テスト）

# シリーズ概要
Microsoft Bot Framework を使用することでTeams、Slack、Lineなどのチャットアプリに簡単に接続することができます。今回はローカルPCで起動しているチャットボットアプリケーションをTeams上で使用する方法をご紹介します。
（注）この記事ではBot Frameworkを使用したチャットボット開発そのものは対象外です。

---

# 本記事の概要

ngrokを使用してネットワークごしに動作することを確認します。

---

# 準備と環境
* Azureの有効なサブスクリプション
* Bot Framework対応チャットボット
* [Bot Framework Emurator](https://github.com/microsoft/BotFramework-Emulator)
* [ngrok] (https://ngrok.com/)

ngrokについては、「[ngrokが便利すぎる](https://qiita.com/mininobu/items/b45dbc70faedf30f484e)」などを参考に。
 
---

# 1. ngrokを起動する

ngrokによりウェブに公開します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/339006/055faa8f-c3ee-c8c3-ecff-feca95ccc0dd.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/339006/b8ca7acb-caa5-320f-deb5-e47b4b19cd76.png)

上記、下線部のアドレス（アドレスは起動ごとに変更されます）でBotFramework Emulator などで接続できることを確認してください。

---

# 2. Azure Bot Serviceへ登録

## ① Bot Channels Registration

ホーム > Bot Service > Bot Service よりBot Channels Registrationを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/339006/9ced31a2-39c5-a7dd-839e-106b9ba64311.png)

前回作成したアプリをID、パスワードを設定します。
メッセージングエンドポイントは ngrokのhttpsアドレス + /api/messages を指定します。（エンドポイントは作成後「設定」より変更可能）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/339006/ca772e73-c9ec-32e9-e0b1-36248cc429ef.png)

---

# 3. 動作テスト

Azure「Web チャットでテスト」より接続が確認できれば完了です。
正常に接続できれば起動しているチャットボットのメッセージが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/339006/45a93a0b-abcb-485d-f09e-d0e0eade0c6e.png)

---

# まとめ
ローカル（オンプレミス）環境でチャットボットを起動・運用するための2つ目の手順としてAzure上にBot Serviceを作成しネットワーク環境でローカルチャットボットへ接続できることをが確認されました。

[その①：ローカル接続テスト](https://qiita.com/rei-yamamoto/items/c3eda7bac709ac355192) <- 前の記事
次の記事 -> [作成中]
GitLabでリポジトリをクローンする

# はじめに
GitLabを初めて使ったが、githubと似てるようで違うのでメモ。

# 鍵の作成と設定

```terminal:ターミナル
$ ssh-keygen -t rsa
```
いろいろ出てきますが、全部適当にenterを押したら鍵ができます。

次に必要な設定を`~/.ssh/config`に記述します。
ここら辺の書き方は他のブログにまとまっているので割愛。

# GitLabに鍵を追加
準備の最後として、GitLabに先ほど作った公開鍵を追加しSSHを登録します。

```terminal:ターミナル
$ pbcopy < ~/.ssh/id_rsa.pub
```
これで公開鍵をコピーできます。

次にGitLabの操作です。
『右上のアイコン→settings→SSH Keys』
ここで先ほどコピーした公開鍵を貼り付けます。
(titleは公開鍵を貼り付けたら自動で入力される。)

# クローン
GitLabのクローンしたいリポジトリに移動して、クローンボタンを押すとHTTPSとSSHの2種類があるので、今回はSSHをコピーします。

```terminal:ターミナル
$ git clone コピーしたSSH
```

これでリポジトリ名のディレクトリが作成されます。
その中にリポジトリの中身が入っていれば完了です。
クラスの継承 流れ

# クラス継承とは
クラスが増えていくと、別のクラスでも同じ情報が生まれることが多いです。

いちいち、それぞれのクラスに一つずつ同じ情報（メソッド）加えていくのは、
何度も何度もその回数分、その同じ内容のコードを繰り返し入力しなければいけないので
とても面倒...:frowning2:

そこで、「複数のクラスに同じ情報（メソッド）を付与したい！」
という声に応えた解決策が "クラス継承" になります。

今回はクラス継承の大まかな流れについて、具体的に説明していきます〜:eye:

# 親クラス と 子クラス
まず、クラス継承において、親クラスと子クラスという二つの関係があります。:man_tone1::boy_tone1::point_up_tone1:

親クラスは元からあるメソッド（情報）を持っているとします。

初めからそのメソッド（情報）を持って存在している "親クラス" :man_tone1:
親クラスのメソッド（情報）を受け継いで生まれた "子クラス":boy_tone1:
というような関係性になります。

コードで表記する際には、クラスを宣言する際に　"子クラス < 親クラス"　を用いて表記します。

# コードで見てみると

```ruby:qiita.rb
class 子クラス名 < 親クラス名

end
```

＊例えばドラゴンボールの孫悟空（親クラス）、その子供である孫悟飯（子クラス）、孫悟天（子クラス）、と例えて
以下のコードを見てみましょう。

# コードに振り分けてみると


悟空クラス（親クラス）:man_tone3:
持っている技："かめはめ波"、"舞空術"、"元気玉"の三つ。

```ruby:qiita.rb
class Gokuu
  def kamehameha
    puts "かめはめ波"
  end

  def Bukuu
    puts "舞空術"
  end

  def Genkidama
    puts "元気玉"
  end
end
``` 

孫悟飯クラス（子クラス）:boy_tone2:
持っている技："親子かめはめ波"

```ruby:qiita.rb
class Gohan < Gokuu  # クラスの継承
  def oyakokamehameha
    puts "親子かめはめ波"
  end
end
```

孫悟天クラス（子クラス）:boy_tone2:
持っている技："三代親子かめはめ波"

```ruby:qiita.rb
class Goten < Gokuu  # クラスの継承
  def sandaioyakokamehameha
    puts "三代親子かめはめ波"
  end
end
```

# 親と子、それぞれ使える技が異なる
上記で表記したように、
孫悟空（親クラス）は、"かめはめ波"、"舞空術"、"元気玉"の三つの技しか使えません。:man_tone3:

孫悟飯（子クラス）は、"かめはめ波"、"舞空術"、"元気玉"の他に、
最初から持っていた技である、"親子かめはめ波"の計4つも技を使えます。:boy_tone2:

孫悟天（子クラス）は、上記でみたように、
"かめはめ波"、"舞空術"、"元気玉"の他に
"三代親子かめはめ波"も使えるという事になります。:boy_tone2:



# まとめ
・クラス継承を使う（共通のメソッドを定義する）事で、子クラスのコードの量が少なくなり、よりみやすくなる。
・親クラスで定義された、共通のメソッド（情報）を変更するだけで、子クラスに簡単にそのメソッドを反映できる。
・ドラゴンボールは使いやすい。
Cakephp4.0で画像アップロード

Cakephp4.0で画像のアップロードをしようとしたけど、うまくいかず
長いことハマったので、備忘メモとして書いておきます。

参考になる記事はたくさんあったのですが、どうもうまくいかず。
ようやく以下のマニュアルで解決できました。
https://book.cakephp.org/4/en/controllers/request-response.html

前のバージョンだと、以下のURLが一番わかりやすく参考にさせて頂きました。
https://qiita.com/kurosu66666/items/239e14df7ea20091a53b

この記事の通りに書いてみたのですが、どうにもアップロードの処理で配列じゃない等と怒られてしまう。
解決のためには、Controllerの書き方を以下のように修正する必要があったようです。

```php:UserController.php
    public function edit($id = null)
    {
        $user = $this->Users->get($id);
        if ($this->request->is(['patch', 'post', 'put'])) {
            $file = $this->request->getData('image'); //受け取り
            
            //ここの書き方が前と違う。メソッドを使うやり方になっている。
            $filePath = './webroot/img/' . date("YmdHis") . $file->getClientFilename();
            $file->moveTo($filePath);

            $user->name = $this->request->getData('name');
            $user->image = date("YmdHis") . $file->getClientFilename(); //同じ名前でDBに入れる

            if ($this->Users->save($user)) {
                $this->Flash->success(__('ユーザー情報が変更されました'));

                return $this->redirect(['controller' => 'Users','action' => 'index']);
            }
            $this->Flash->error(__('ユーザー情報の変更に失敗しました'));
        }
        $this->set(compact('user'));
    }

```

私の探した限りでは日本語の方のマニュアルには、まだこの内容は載ってないようです。
s3fs-fuseでminioをマウントする

s3fs-fuseをインストールする。

# s3fs-fuseのインストール
ここに書いてある通りだが、macOSに関しては記述する。
https://github.com/s3fs-fuse/s3fs-fuse

```bash
$ brew cask install osxfuse
$ brew install s3fs
```

# 準備
やはり、ここに書いてある通りだが、記載する。
https://github.com/minio/cookbook/blob/master/docs/s3fs-fuse-with-minio.md

```bash
# アクセスキーとシークレットキーを保存
$ echo "access_key:secret_key" > s3cred
$ chmod 600 s3cred
# これをしないとマウント時に下記のエラーが出る
s3fs: credentials file s3cred should not have others permissions.
# マウント用のディレクトリを作成
$ mkdir test
```

## マウント
\<bucket>とhttp\://minio-server:9000は設定した値を代入する。
-oで必要なオプションを追加する。uid, gidを設定しないと、root権限になる。

```bash
$ s3fs <bucket> test -o passwd_file=s3cred,use_path_request_style,url=http://minio-server:9000,allow_other,uid=$(id -u),gid=$(id -g)
```

## 確認

```bash
$ mkdir test/test
$ mc ls <host>/<bucket>
# testができていることを確認できるはず
```
Java Listの入れ子をひとまとめにする

Java8以降であれば、`flatMap`を使えばいけそうです。

```java
Map<UserId, List<User>> userMap;
List<User> users = userMap.values()
  .stream()
  .flatMap(Collection::stream) // List<User> -> Stream<User>に変換
  .collect(Collectors.toList());
```

`map()`はCollectioinの要素を取り出して変換を行うメソッドで、
`flatMap()`はCollectionの要素を取り出してStreamへの変換を行うメソッドです。
連続するスペースを削除して1つにするpythonのコード

いつもわからなくなるのでメモ

```py
import re

text = "こういった、     ←半角スペースや　　　←全角スペース消したいけど、一個は残す。"
text = re.sub('[ 　]+', ' ', text)

print(text)
'こういった、 ←半角スペースや ←全角スペース消したいけど、一個は残す。'
```

スペースのところを明記すると
`re.sub('[(半角スペース)（全角スペース）]+','(半角スペース)',text)`
という感じです。
Process Hackerを利用した自動アンパックの手順

アンチウイルス製品の検知回避を目的として、多くの攻撃者は独自のパック処理を施したマルウェアを利用することが多くあります。
タイトル記載の「自動アンパック」についてですが、
本記事では「実行後にアンパックされたメモリをダンプして解析する」方法について説明しており、「静的解析を行わない」という意味で「自動アンパック」と表記しています。

「もっといい方法があるよ〜〜」というアドバイスがあればいただけると嬉しいです！

#そもそもパックとは？
パックの詳細につきましてはここでは割愛しますが、下記の論文がわかりやすかったのでぜひ読んでみてください。
[マルウェア検知におけるパッカーの役割についての検討](https://www.jstage.jst.go.jp/article/fss/28/0/28_619/_pdf/-char/ja)

#パッカーの判別方法
[Ditect It Easy](https://forest.watch.impress.co.jp/docs/review/752838.html)のような判別ツールを利用する方法がもっとも容易です。
ただし、多くの攻撃者は独自のパック方法を用いるため、正確にパックできるかどうかの保証はありません。

#メジャーなパッカーのアンパックについて
有名なパッカーについては、インターネット上に公開されているツールを利用してアンパックすることが可能です。
[・upxのアンパッカー](https://github.com/upx/upx)
[・ASPackのアンパッカー](http://www.aspack.com/downloads.html)
[・AutoItのアンパッカー](https://exe2aut.com/)

いづれも常に有効とは限りませんが、自力でアンパックするより早いため、試してみる価値はあります。

#攻撃者の独自パッカーのアンパックについて
以降では、ProcessHackerを利用したアンパック手順について記載します。

##1.事前準備
検体を動かす前に、下記の準備をしておきます。
・Process Hacker（管理者権限で）の起動
→管理者権限であげておかないとプロパティ情報が十分に読み込めません。

##2.検体の実行
パックされている検体を実行します。
立ち上げた直後アンパックし始めるため負荷が上がります。
System informationなどを確認しながら、CPU使用率が収まるのを少し待ちます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102081/c4c98a7f-ee2c-cd1b-0abe-e45b12fb1bfd.png)

##3.メモリのダンプ
負荷が落ち着いたら、検体をダブルクリック（または右クリック＞プロパティ）して、ウインドウのMemoryタブを開きます。
アンパック後のマルウェアはRWXに展開されることが多いので「Protection」欄をソートしてRWX権限で動いているプロセスを探します。
（複数ある場合もあります。その際はサイズの大きいものからあたりをつけます）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102081/4018df6d-e961-aeaf-3a94-ab672a5245f3.png)

RWX権限のプロセスを右クリックして、Saveします。

##4.バイナリエディタで開く
3.で取得したファイルをバイナリエディタで開きます。今回はHxDを使っています。
読んでいくと、途中から「MZ」の文字が出てくるのを見つけました。
ここがプログラムの開始地点だと推測します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102081/47e76e0a-deaa-a4a0-bc39-f81566817c16.png)

##5.ファイルの編集
4.であたりをつけた点（MZ）より前の部分を全て切り取り、保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102081/b3a49d5b-55b8-20e9-a634-4af77ad86a43.png)

##6.保存したファイルの形式確認
5.のファイルをpestudioなどで開いてみると、実行形式のファイルとして識別されていることがわかります。
これで中身を取り出すことができました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102081/eb8a998b-aab3-72fd-350a-1bdff87378bd.png)

##7.IDAなどで解析可能
以降は一般的な実行ファイルと同様の形で解析が可能になります。
試しにIDAで開いてみてもPEファイルとして認識されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102081/9f3ad26e-f989-8adf-8e7c-3a5146936a7a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102081/461a2496-969b-5354-632b-63ab764898f2.png)

#補足
今回は取り上げていませんが、手順4.の際ファイル冒頭からMZで開始する場合もあります。
この場合そのまま実行できるように見受けられますが多くの場合はこのままだと実行ファイルとして読み込むことはできません。
実行していない状態だとメモリの値などが入っておらずコンバートする必要があります。この方法については良い検体が見つかりましたら別途記載できたらと思います。
・・・忘れていなければ・・・・(⌒-⌒; )

以上。
UserDefaultsの中身全てを雑に出力する

Swift5.0。
デバッグしていて、「あーとりあえずUserDefaultsの中身ドバッと出したいな……」と思いました。
UserDefaultsから普通に取り出そうとすると、Key名が必要となりますが、mapみたいなのないかな〜と思ったら、下記がありました。

```swift:雑に出力
print(UserDefaults.standard.dictionaryRepresentation())
```

lldbデバッガのpoコマンドでやるのも手です。
出力結果は載せません。
とにかく汚いですが、全部出ます。辞書型。
自分のアプリドメイン外のものも出てる？　気がしますが、とにかく全部出ます。

アプリ内で接頭詞持ってて、キー名は必ずそれが付ける運用になっていたら、下記のようにしぼると捗りそうです。

```swift:キー名で絞る
print(UserDefaults.standard.dictionaryRepresentation().filter { $0.key.hasPrefix("hoge") })
```
DataFrameの年齢を階層分けする

# はじめに
データ分析をする際によく使いそうなので、備忘録として書くことにした。
Jupyter notebookで実装したものをこちらに書き写しているような感じなので、実行環境が異なれば違った動きになるかもしれません。

# データの準備
今回は、ある金融機関のデータを使用する。

```python
import pandas
import requests, zipfile
from io import StringIO
import io

zip_file_url = 'http://archive.ics.uci.edu/ml/machine-learning-databases/00222/bank.zip'

r = requests.get(zip_file_url, stream=True)
z = zipfile.ZipFile(io.BytesIO(r.content))
z.extractall()
```

`bank-full.csv`ファイルが保存されているので、それを読み込む。

```python
banking_c_data = pd.read_csv('bank-full.csv', sep=';')
banking_c_data.info()
```
出力結果↓

```
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 45211 entries, 0 to 45210
Data columns (total 17 columns):
 #   Column     Non-Null Count  Dtype 
---  ------     --------------  ----- 
 0   age        45211 non-null  int64 
 1   job        45211 non-null  object
 2   marital    45211 non-null  object
 3   education  45211 non-null  object
 4   default    45211 non-null  object
 5   balance    45211 non-null  int64 
 6   housing    45211 non-null  object
 7   loan       45211 non-null  object
 8   contact    45211 non-null  object
 9   day        45211 non-null  int64 
 10  month      45211 non-null  object
 11  duration   45211 non-null  int64 
 12  campaign   45211 non-null  int64 
 13  pdays      45211 non-null  int64 
 14  previous   45211 non-null  int64 
 15  poutcome   45211 non-null  object
 16  y          45211 non-null  object
dtypes: int64(7), object(10)
memory usage: 5.9+ MB
```

今回は年齢を年代別に階層分けすることが目的なので、注目するのは`age`カラムのみである。

# 年代別に階層分け

**15歳から5歳ごとに階層分けして、65歳から100歳は同じ階層にした。**

```python
bins = [15,20,25,30,35,40,45,50,55,60,65,100]
cut_result = pd.cut(banking_c_data.age, bins, right=False)
cut_result
```
 出力結果↓

```
0         [55, 60)
1         [40, 45)
2         [30, 35)
3         [45, 50)
4         [30, 35)
           ...    
45206     [50, 55)
45207    [65, 100)
45208    [65, 100)
45209     [55, 60)
45210     [35, 40)
Name: age, Length: 45211, dtype: category
Categories (11, interval[int64]): [[15, 20) < [20, 25) < [25, 30) < [30, 35) ... [50, 55) < [55, 60) < [60, 65) < [65, 100)]
```
うまく階層分けされてそうだ。
あとは元のテーブルとageカラムを入れ替えるだけ。

```python
banking_c_data['age'] = cut_result
```
これで完了。
今回は以上のように、元のageカラムと、新しく作成した階層分けのageカラムを入れ替える形で実装しましたが、元のageデータがなくなってしまうという問題が生じてしまうので、`pd.concat()`を使用して欲しいデータのみを取り出して結合するのが良さそうです。

例えば、`balance,campaign,previous`カラムと階層に分けた`age`カラムの結合は以下のよう。

```python
pd.concat([pd.DataFrame(cut_result), banking_c_data[['balance','campaign','previous']]], axis=1)
```
出力結果↓
<img width="300" alt="スクリーンショット 2020-02-21 16.14.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298735/d493f899-d29a-403e-c45e-5923d4747c19.png">

# おわりに

最後まで読んでいただきありがとうございました。
ものすごく単純なことしかしていないのでわざわざ書く必要があったのかわかりませんが、どなたかのお役に立つことができれば幸いです。
Kotlin入門:null許容型とは

実際に読んでみて良かった書籍について情報を発信していますので、
よろしければ[Twitter](https://twitter.com/KaoruTojo_Novel)のフォローもお願いします。


#前提条件

Javaの基本的な構文について理解していると読みやすいです。

簡単にKotlinを実行するには[こちら](https://kotlinlang.org)
#Kotlinではnullを許容しないのが既定

Javaではnullが許容されていました。

```Java
String str = null;
```

null状態の変数に対してアクセスしようとすると、
NullPointerExceptionという例外が発生します。

そこで、Kotlinではこの例外を発生させないためにnullを許容しないのが既定となっています。

```Kotlin
fun main() {
    var name = "山田"
    name = null
    println(name)
}
```

このコードを実行すると

```
Null can not be a value of a non-null type String
```

というエラーが発生します。

どうしてもnullを許容したいときは型名の後方に「？」をつけると許容されます。

```Kotlin
fun main() {
    var name:String? = "山田"
    name = null
	println(name)
}
```

このコードを実行すると

```
null
```

と表示されます。

型名?　をNullable型(null許容型)と言います。


##非null型への代入

Nullable型から非null型への代入はできません。
Nullable型にnullが代入されている可能性があるからです。

```Kotlin
fun main() {
    var name1:String? = "山田"
    var name2:String= name1
    println(name2)
}
```

このコードを実行するとエラーになります。

```
Type mismatch: inferred type is String? but String was expected
```


##セーフコール演算子
Nullable型のメンバーにアクセスするためには(?.)演算子を使います。

```Kotlin
fun main() {
    var name1:String? = "山田"
	println(name1?.length)
    
    var name2:String? = null
	println(name2?.length)
}
```

このコードを実行すると

```
2
null
```

以上が表示されます。


##!!演算子
Nullable型を強制的に非null型に変換する!!演算子があります。
しかし、Nullable型の中身がnullでないことが明らかな場合での使用が推奨されます。

```Kotlin
fun main() {
    var name1:String? = "山田"
    println(name1!!.length)
}
```
結果は以下の通りです。

```
2
```

中身がnullだと

```
Exception in thread "main" kotlin.KotlinNullPointerException
```

が発生してしまいます。
東京都IoT研究会主催「ＩｏＴ人材育成プログラム」（実習コース ）を受講したよ

IoT人材育成プログラム（実習コース）を受講したよ
2020年2月3・20日に実際されました。

株式会社サートプロの研修プログラムは一度受講してみたいと考えていたものでした。
##第1回
最初は、ブロックプログラミングでM5Stackを動かします。
次に、Arduinoを使用し、M5Stackから温湿度データをAnbientに送り、見える化します。
![IMG_1266.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/dd95fc40-fff0-5d3c-8403-ab1ac00f1696.jpeg)
![IMG_1267.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/699126d3-ff57-a17e-7c34-94c0fdb60eba.jpeg)


##第2回
機械学習を学びます。

午前は講義です。
午後からPCを使い機械学習を行います。
![IMG_1265.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/984c71d3-14a4-80cb-c224-7a83a339db3b.jpeg)

最後は、Azure Machine Learningの使い方を学びました。

2日間でIoTを体験することが可能なセミナーで非常に重要だと思いました。
人数は定員18名でしたが、欠席が多いのが残念でした
年齢層は、若干高めでしたが、大きな問題なく、時間延長することなく、カリキュラムを完了させたのは、さすがだなと思ってしまいました(失礼ｗ）
CQ出版や、ルネサス半導体セミナーと違い、初歩の初歩で触る事を目的としています。
何も知らない人への導入は非常に重要なだけに、今後も続いてほしいセミナーだと思いました。
PHPで気をつけること

# コードの可読性

### if文の順番
```php:
foreach ($array as $key => $val) {
  if (!empty($val)) {
    // ここに処理を書く
  } else {
    continue;
  }
}
```

### 車輪の再開発❌
- 既存の関数を用いる

### コードを書く前に 描く！
- フローチャートを書いてからコーディングする方が開発工数が短い!

### コメントは、コードに書けないことを書く

### 1万時間の訓練
- 週20時間(毎日約3時間)なら、10年で到達
- 週35時間(毎日 5時間)なら、6年弱で到達
- 週49時間(毎日 7時間)なら、4.3年で到達

## セキュリティ的に注意するコード (ユーザ引数を渡さない)
- eval
    - PHPのコードとして実行
- exec
    - 外部プログラムを実行
- file
    - ファイルの中身を配列に格納
- file_get_contents
    - ファイルを文字列として格納
- fopen
    - 指定ファイル/URLを開く


## 参考
- PHP開発者が心得ておくべき10の鉄則
https://qiita.com/ka215/items/c4bda101e51b7fe82ab2
- プログラマが知るべき97の https://qiita.com/masakinihirota/items/5fd5fffa5ac5e057a9df
SRF02超音波センサをi2cを使ってpytonで動かした

##超音波センサー　ＳＲＦ０２
![SRF02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590332/98fca366-d884-38af-0767-8a018938991a.png)

秋月で2400円くらい http://akizukidenshi.com/catalog/g/gM-06685/
・使用マイコン：16F687-I/ML
・測定範囲：16cm~6m.
・電源：5V(消費電流4mA Typ.)

超音波の距離センサ―の中で精度が結果良い?
これをラズパイにつないで12c通信で制御する

##i2c接続
![SRF02_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590332/a08c5e7c-fa82-369e-9f6b-dfa66d22a283.png)
ピンヘッダーを半田付け
Modeピンはi2cの場合未接続
各々のピンをラズパイに接続
　　ラズパイの場合はプルアップ抵抗不要
ターミナルで
```
sudo i2cdetect -y 1
```
アドレスを確認デフォルトなら0x70(112)のはず

##制御
pythonでプログラミング

```
from time import sleep
import smbus

i2c = smbus.SMBus(1)
address = 0x70
SLEEPTIME = 0.5
DELAY = 0.1

if __name__ == '__main__':
    try:
        print ("cancel：CTRL+C")
        cnt = 1
        while True:
            i2c.write_i2c_block_data(0x70,0x00,[0x51])
            time.sleep(DELAY)

            block = i2c.read_i2c_block_data(address,0x00,4)
            distance = (block[2]<<8 | block[3])
            print(int(cnt),distance)
            cnt = cnt + 1
            time.sleep(SLEEPTIME)
             
    except KeyboardInterrupt:
        print("finishing...")
    finally:
        print("finish!!")
```

###細かく書いていく

```
i2c.write_i2c_block_data(0x70,0x00,[0x51])
```
0x51が測定コマンド　センチメートル単位
(0x50であればインチ)

```
time.sleep(DELAY)
```
測定コマンド後は遅延をかけなければいけない
データシートでは70ms

```
block = i2c.read_i2c_block_data(address,0x00,4)
distance = (block[2]<<8 | block[3])
```
Location2がHigh Byte,　Location3がLow Byte
8bitずらして結合

##たまに値が飛ぶ
たまに上記プログラムだと値が飛ぶことがある
どうやら測定に用いているsoftwareが異なるよう
location0はReadの際、データシートによると"Software Revision"であり
普段はここが6だがたまに134を返す
値の意味は不明...

        i2c.write_i2c_block_data(0x70,0x00,[0x51])
        time.sleep(DELAYTIME)
        block = i2c.read_i2c_block_data(address,0x00,6)
        if(block[0]==6):
            distance = (block[2]<<8 | block[3])
        else:
            distance = (block[2]<<8 | block[3]) + block[4]

その場合はこちらに変更で問題なし
IoT@Loft #8 スマートホームのセキュリティ脅威と対策　を受講したよ!（2020年2月19日実施）

IoT@Loft #8 スマートホームのセキュリティ脅威と対策を受講したよ!
###セキュリティ対策にはOTA(DFU)が大事

今回は、コロナウィルスの影響で懇親会が中止となりました。
それもあってか、ちょっと軽めなセミナーでした。

##LT1 - Zero Touch Provision for AWS IoT
マイクロチップ・テクノロジー・ジャパン株式会社
篠崎 雅和 氏

少量でもセキュリティチップを製作可能
https://www.microchip.com/promo/zero-touch-secure-provisioning-kit-forAWSIoT
![IMG_1370.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/083cad6f-90e9-4027-d71b-6dd38b38bb2e.jpeg)
#LT2 - 非IoTスマートロックをIoT化する製品とそのバックエンド/セキュリティについて
株式会社ビットキー
山本 寛司 氏

スマートロックの脆弱性が見つかってもアップデートできないと大問題
ファームウェアの書き換え（DFU・OTA)出来ることが重要

バックエンドがしっかりしていると、実装作業(ソフト製作）に注力できる。
![IMG_1374.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/0492a7af-0a47-9644-8e04-d310cbf49ee5.jpeg)
![IMG_1373.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/fbb0e7cb-85c3-79ea-537a-86b8cc2fff8a.jpeg)
##スマートホームのセキュリティ脅威と対策
アマゾン ウェブ サービス ジャパン株式会社
飯田 起弘 氏
![IMG_1379.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/05550dea-76c6-d05f-758f-be965c241851.jpeg)
![IMG_1381.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/b0a63d5d-7be4-64a4-ca4b-2201a9c2b157.jpeg)

POCや少量(数個）ならば、ハイエンドデバイスを選ぶべき
逆に大量に作るときは、セキュリティを先に考えないと、セキュリティ対応できなくなるケースがある。
PHPのクラスをforeachで回せるようにする

PHPでは普通arrayをforeachしますが、クラスにIteratorAggregate、ArrayAccess、Countableを実装させればforeachで回せるようになります。

配列を直接使うのではなくクラスにすることで、引数に渡せる型を制限したり、クラスにロジックを書けたりして便利です。この考え方をファーストクラスコレクションといいます。

以下は例のコードです。

```php

<?php 

class ListValue implements \IteratorAggregate, \ArrayAccess, \Countable
{
    private $array;

    public function __construct(array $array)
    {
        // keyが連番の数字になることを強制する
        $this->array = array_values($array);
    }

    public function count(): int
    {
        return count($this->array);
    }

    /* IteratorAggregateインターフェースの実装 */

    public function offsetGet($offset)
    {
        return $this->offsetExists($offset) ? $this->array[$offset] : null;
    }

    /* ArrayAccessインターフェースの実装 */

    public function offsetExists($offset)
    {
        return isset($this->array[$offset]);
    }

    public function offsetSet($offset, $value)
    {
        if (is_null($offset)) {
            $this->array[] = $value;
        } else {
            $this->array[$offset] = $value;
        }
    }

    public function offsetUnset($offset)
    {
        unset($this->array[$offset]);
    }

    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->array);
    }

}
```
ruby 破壊の話②メソッド編

[前回](https://qiita.com/Kitasan_White/items/409cbd4b125caf210073)の内容を簡単にまとめると、

- =でidが変わる。(=はidを変える働きがある)
- idが変わることにより結果的に参照する値も変わる。

今回は=を使わなくても参照先の値が変わってしまう例を見ていく。

|ruby 破壊の話シリーズ|
|:-----------------|
| [ruby 破壊の話①「=」のふるまい](https://qiita.com/Kitasan_White/items/409cbd4b125caf210073)
| [**ruby 破壊の話②メソッド編**](https://qiita.com/Kitasan_White/items/7b2ede8d678431d878e1) |
|[ruby 破壊の話③関数編](https://qiita.com/Kitasan_White/items/eca7f816125ae44feebc)|
|[ruby 破壊の話④破壊的なメソッド編](https://qiita.com/Kitasan_White/items/b829ee99eb6e20fa95bd)|
|[ruby 破壊の話⑤dup編](https://qiita.com/Kitasan_White/items/4f8d6b822ac5c2c72e8b)|


# 破壊的メソッド
## mutableの例
=なしでidは変えられない。
idを変えずに参照先が変わってしまうというのはすなわち、そもそもidが対応している値自体が変わってしまう事象を指す。
こういったメソッドを破壊的メソッドと呼び、"!"が付いているのが特徴である。

```
irb(main):001:0> a='abc'　#aを文字列abcを指すよう設定する
=> "abc"
irb(main):002:0> a.__id__　#aのidを確認しておく
=> 47064986806140
irb(main):003:0> a.reverse　#reverseは元の文字列を逆さにする普通のメソッド
=> "cba"
irb(main):004:0> a #aの値自体は変わらない
=> "abc"
irb(main):005:0> a.__id__ #もちろんidも変わらない
=> 47064986806140
irb(main):006:0> a=a.reverse #左辺aを右辺aの逆さ文字列を参照するように設定
=> "cba"
irb(main):007:0> a.__id__ #=で異なるものを設定しなおしているのでidも変更される
=> 47064986914720
irb(main):008:0> a.reverse! #reverse!は元の文字列を逆さにし、上書きしてしまう破壊的メソッド
=> "abc"
irb(main):009:0> a #006で設定した値と異なる
=> "abc"
irb(main):010:0> a.__id__ #しかしidは007で確認したものと同じ
=> 47064986914720
```

このように、idを変えずidが指す値自体を変更するのが破壊的メソッドである。
値が変わってしまう危険性があるので、自分で破壊的なメソッドを作る場合にも!を付けることが推奨される。
ただしここで言う破壊的なメソッドとは、reverse!などの破壊的メソッドとは少し性質が異なる。
そのため私は、「破壊的メソッド」とはあらかじめ用意されているreverse!やsort!などを指すこととし、自作した破壊的なメソッドのことは「破壊的"な"メソッド」と呼ぶようにしている。

## immutableの例

immuttableの例というより、そもそもimmutableとは不変という意味で、破壊することは不可能である。
以下で、シンボルがimmutableであることがわかる。

```
irb(main):001:0> a=:abc #aをシンボルabcに設定
=> :abc
irb(main):002:0> a.reverse　#reverseは文字列のメソッドなので
NoMethodError: undefined method `reverse' for :abc:Symbol
        from (irb):2
        from /usr/local/rbenv/versions/2.4.2/bin/irb:11:in `<main>'
irb(main):003:0> a.reverse! #もちろん破壊できない
NoMethodError: undefined method `reverse!' for :abc:Symbol
        from (irb):3
        from /usr/local/rbenv/versions/2.4.2/bin/irb:11:in `<main>'
irb(main):004:0> a #シンボルは不変
=> :abc
irb(main):005:0> a.__id__ #idを確認
=> 1162268
irb(main):006:0> a.to_s.reverse! #to_sを使って破壊しようとすると表示は成功
=> "cba"
irb(main):007:0> a.__id__ #to_sは破壊的メソッドではないのでa自体は無傷
=> 1162268
irb(main):008:0>
```
# まとめ
破壊的メソッドは、idに紐付けられる値自体を変更する。

続きは[次の記事](https://qiita.com/Kitasan_White/items/eca7f816125ae44feebc)で

## 余談 rubyで i++ が出来ない話

統計を取ったわけではないが、i=i+1やi+=iの意味で、i++という記法が使えない言語は少ないのではないだろうか。
rubyは使えないようで、最初ちょっと驚いた。

c出身ということもあり、まあcの方がもっと全然実装されてないことあるわって思って気にせずi=i+1と書いていたが、rubyについて理解を深めると、納得の理由だった。

理由は数字がimmutableであることと=のふるまいで説明できる。
#### 例1
`i=1`
`i++`
`p i`

2が表示されてほしいところだが、=に注目してよくよく考えると、これで2が表示されるわけがない。

=はこのコードに一つ。最初の行だけ。1はimuttable

なのでiは1と同じidということ。その後には=が無いので、最後までiは1と同じidである。
これが2を指しているわけがない。

#### 例2
`i=1`
`i=i+1` 
`p i`

同じようでもこれは2になる。
なぜなら2行目でiのidを変更しているからだ。

まとめると、数字をimmutableに設定し、=なしではidを変えられない言語仕様上、i++という表現を許すわけにはいかなかったのだ。
とても理にかなっていて美しいなと思った。
[RHEL7/CentOS7] yumコマンドでPerlをインストールした環境でLWP実行エラー

# エラーが発生

動作確認済みの Web アクセスを行う Perl プログラムをある環境で動かすと実行エラーが発生。

HTTP で Web アクセスした場合のエラー

```
$ perl test.pl
501 Attempt to reload IO/Socket.pm aborted.
Compilation failed in require
```

HTTPS で Web アクセスした場合のエラー

```
$ perl test.pl
LWP will support https URLs if the LWP::Protocol::https module
is installed.
```


# 該当Perlスクリプト

```test.pl
#!/usr/bin/perl
use LWP::UserAgent;

my $url = "https://www.example.com";
my $request = HTTP::Request->new(GET => $url);
my $useragent = LWP::UserAgent->new;
my $response = $useragent->request($request);
my $result = $response->content;
print $result;
```

# 事前に構築していたPerl環境

Perl はこれまで実績のあるやり方で yumコマンドにてインストールを行っており、必要なライブラリも同様にインストール済み。なのに実行エラーが発生する。

```
$ sudo yum install perl
$ sudo yum install perl-Net-SSLeay
$ sudo yum install perl-Crypt-SSLeay
$ sudo yum install perl-IO-Socket-SSL
$ sudo yum install perl-IO-stringy
$ sudo yum install perl-URI
$ sudo yum install perl-LWP-Protocol-https
```

※LWP は Library for WWW in Perl の略で、Perl から Web アクセスを実現するライブラリです。

# 原因と対策

正常動作する環境と見比べると Perl のパッケージで perl-Socket がインストールされていないことがわかりました。
このパッケージを yum コマンドでインストールするとあっさり解決！

```
$ sudo yum install perl-Socket
```

※実際には他にも多くの Perl パッケージで差異があったため、一つ一つ順番に追加インストールして動作確認を行い、このパッケージにたどり着きました。

通常は依存関係でインストールされるパッケージであり、これだけ個別にインストールしたこと無いのですが、利用していた環境が某クラウドにインストールされた RHEL7 でパッケージ管理に問題を抱えていたのかもしれません。
Kotlin入門:変数の宣言

実際に読んでみて良かった書籍について情報を発信していますので、
よろしければ[Twitter](https://twitter.com/KaoruTojo_Novel)のフォローもお願いします。


#前提条件
初めてKotlin(コトリン)に触れる人

Javaの基本的な構文を理解していると読みやすいです。

[本家サイトでKotlinを簡単に実行する](https://kotlinlang.org)


###変数の宣言について
以下はKotlinでの変数の使い方についてザックリと解説しています。
※実際のソースコードに①や②は記載しない。

```Kotlin
①fun main() {
②    var name:String = "World"
③    println("Hello ${name}")
  }
```

KotlinではJavaと異なり、文の末尾に;(コロン)は不要です。

①では「mainという名前の関数を定義」しています。
main関数はJavaと同じくエントリーポイントとなっています。
エントリーポイントとは、プログラム上で最初に実行される関数のことです。

②ではString型の変数nameを宣言しています。
Kotlinの型宣言は「型　変数名」ではなく、「変数名:型」が基本となっています。
varは変数の宣言時に必要な命令です。
var命令で宣言しなければ変数の利用はできません。

③については後述します。

変数の宣言についての構文

```Kotlin
var name:type = initial
```

name は変数名
type はデータ型
initial は初期値

type(データ型)は省略でき以下のようにすることもできます。

```Kotlin
var name = "山田"
```

この場合、nameに代入できるデータ型はString型に決まります。
type(データ型)が省略された場合、初期値からデータ型を類推します。
この仕組みのことを型推論と言います。

初期値を省略して以下のようにすることもできます。

```Kotlin
var number:Int
```

なお、データ型と初期値の両方を同時に省略することはできません。


変数に任意の型を代入したい場合はAny型を宣言することで任意の型を代入できます。

```Kotlin
var name:Any = "山田"
name = 111
```

以上ではエラーが発生しません。
全てのデータ型はAnyを継承しているのでエラーになりません。
Any型の変数には全てのデータ型のデータが代入できるので、
エラーの発生要因となるため非推奨です。

以下はよく使われる基本的なデータ型です。

| データ型 | 概要 | 
|:-----------------|---------------:|
| Boolean          |          真偽型 |
| Byte             |      8bit整数型 |
| Short            |     16bit整数型 |
| Int              |     32bit整数型 |
| Long             |     64bit整数型 |
| Float            |32bit浮動小数点型 |
| Double           |64bit浮動小数点型 |
| Char             |          文字型 |
| String           |        文字列型 |



##文字列テンプレート
文字列に${}の形式で任意の式を埋め込むことができます。

```Kotlin
fun main() {
    var number = 10
    println("変数numberは${number}です")
    println("変数numberは$number です")
}
```
実行結果は以下の通りです。

```Kotlin
変数numberは10です
変数numberは10 です
```

中かっこ{}は省略できますが、変数の区切りの部分に半角空白を入れなければエラーとなります。
入れた空白は文字列にも反映されるため、省略は望ましくありません。
システム運用改善業務への三歩目

## はじめに
* 前回、可視化 / モニタリング / 標準化/リファクタリングのタスク（案）を列挙したところまで整理しました。
    * [システム運用業務改善への第一歩はこちら](https://qiita.com/yuta_k0911/items/310bb7105731ef996f1d)
    * [システム運用業務改善への二歩目はこちら](https://qiita.com/yuta_k0911/items/d0b746b9f98f8fc7a334)
* 今回は、`モニタリング`にフォーカスした内容を書きます。
    * 弊社が利用しているアーキテクチャの情報が載っていますが、適宜ご自分の環境に読み替えていただけますと幸いです

## 前提条件
* 弊社では、業務管理のツールとして、`Atlassian社のJIRA Software`を利用している。
    * システムのモニタリングはDatadog、コミュニケーションツールはslackを利用
* 弊社では`作業`というくくりで、以下を包括する。
    * 依頼作業
    * インシデント対応
    * 課題対応
    * セキュリティ対応
    * 業務改善

## 弊社における作業の流れ
* 基本的な作業発生から作業完了までの流れは以下の図の通り。

![作業の流れ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320001/5cf7b8bc-4c0b-ab85-3891-b2c6a1b73068.png)

## モニタリングの一例
* `JIRAのダッシュボード機能`を用いて、月単位の各作業区分におけるチケット数を集計し、トレンドを把握する。

<img width="665" alt="スクリーンショット 2020-02-21 15.03.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320001/9ad8d579-27c1-7d10-0f44-e12ac87cdc36.png">

* 上記の例で言うと、例えば以下を読み取ることができる。
    * 2019年12月のインシデント数が急激に増えている
        * 調査したところ、`Hadoopクラスタの停止`が12月に頻発していた
    * 2020年に入ってからはインシデント数が減少傾向にある
    * 長期休暇の前後は依頼作業が増える傾向にある
* 多角的に数値分析を可能にするために各作業区分に対応した`フィルター`を用意する。
    * ステータスで分類する
        * 完了
        * 着手中
        * 未着手
        * 未解決

<img width="509" alt="スクリーンショット 2020-02-21 15.07.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320001/2bc081cc-65ef-63c7-fe7c-4fe401012667.png">

## 苦労・工夫した点
* **業務内容を全てJIRAチケット化する**という文化を根付かせることからスタート。
    * 過去はslackに依頼事項やインシデント情報が書かれるのみで、集計や分析ができる状態ではなかった
    * このままでは`誰が何をしているのか？`が可視化・共有できておらず、課題と捉えて改善を実施
* ダッシュボードのモニタリングのみでは課題・懸案を吸い上げることができない。
    * 週次でJIRAチケットの状況を確認する会議体を設け、チケットベースでの進捗や課題・懸案事項を吸い上げる場を設定している
* Datadogが通知するアラートをトリガーにJIRAチケット起票を自動化した。
    * インシデントの集計・分析ができないとプロアクティブな対策が取れず、ナレッジも残っていなかった
        * 設定等は別で整理します