OmniAICreator/Qiita-1.07M huggingface dataset:
[SwiftUI] 親から1つObservedObjectを渡して、子viewでそれを使いたいが、Generic struct 'ObservedObject' requires that 'Test１Manager?' conform to 'ObservableObject'が出る


親viewからObservedObjectを子viewへ１つ渡す。
子viewで多種類あるObservedObjectから、渡されたObservedObjectだけを使いたい。

@ObservedObjectのproperty wrapper に準拠しないといけないので、以下のようなことができなくて困った。


### ・子viewでObservableObjectをnilにして使う。

Generic struct 'ObservedObject' requires that 'Test１Manager?' conform to 'ObservableObject'
でエラーが出る。

```swift

struct ParentView: View {

    @ObservedObject var test１Manager: Test１Manager
    @ObservedObject var test２Manager: Test２Manager
    @ObservedObject var test３Manager: Test３Manager

    var body: some View {
        ChildView(test１Manager: test１Manager)
    }
}

struct ChildView: View {

    @ObservedObject var test１Manager: Test１Manager?
    @ObservedObject var test２Manager: Test２Manager?
    @ObservedObject var test３Manager: Test３Manager?

    var body: some View {
        Text("\(test２Manager.text)")
    }
}
```

## 解決

子viewでは、複数あるObservedObjectのうちどれを使うか条件分岐し、孫でObservedObjectを使う。
親から子viewへ使いたいObservedObjectを１つ渡し、子では変数に格納して、その変数がnilかどうかで条件分岐し、孫にObservedObjectを渡す。

```swift

struct ParentView: View {

    @ObservedObject var test１Manager: Test１Manager
    @ObservedObject var test２Manager: Test２Manager
    @ObservedObject var test３Manager: Test３Manager

    var body: some View {
        ChildView(test１Manager: test１Manager)
    }
}

struct ChildView: View {

    var test１Manager: Test１Manager?
    var test２Manager: Test２Manager?
    var test３Manager: Test３Manager?

    var body: some View {
        if let test１Manager = test１Manager {
            Content(test１Manager: test１Manager)
        } else if let test２Manager = test２Manager {
            Content2(test２Manager: test２Manager)
        } else if let test３Manager = test３Manager {
            Content3(test３Manager: test３Manager)
        } else {
            Text("データはありません。")
        }
    }

    private struct Content１: View {
        @ObservedObject var test１Manager: Test１Manager?
        var body: some View {
            Text(test１Manager.text)
        }
    }

    private struct Content２: View {
        @ObservedObject var test２Manager: Test２Manager?
        var body: some View {
            Text(test２Manager.text)
        }
    }

    private struct Content３: View {
        @ObservedObject var test３Manager: Test３Manager?
        var body: some View {
            Text(test３Manager.text)
        }
    }
}
```
ConfluenceをCSSで読みやすくする

Confluenceのページを、CSSを使って読みやすくする方法を紹介します。

# 設定方法
## 前提
* スペースの管理者権限があることが前提です。

## 設定手順
### 1. 「スペースツール＞ルックアンドフィール」を選択

画面左下の「スペースツール」から、「ルックアンドフィール」を選択します。

![スクリーンショット 2021-10-27 16.29.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311681/367a93c7-dd6c-9b3c-f2ee-6188e8cccb0e.png)

このメニューはスペースの管理者権限がないと見えないので注意です。

### 2. 「サイドバー、ヘッダーとフッター」を選択

タブから「サイドバー、ヘッダーとフッター」を選択します、

![スクリーンショット 2021-10-27 16.33.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311681/011522be-526a-bc10-2402-769ce5384661.png)

### 3. 「フッター」欄にCSSを追加

フッター欄にお好みのCSSを入力します。

#### 注意点①

ヘッダーではなくフッター欄に入力するという点に注意してください。

ヘッダー欄に入れた場合、プレビュー時に表示崩れが起きます。
フッター欄だと上記事象は起きませんが、プレビュー時はスタイルが適用されません。。。
#### 注意点②

全体を`{html}~{html}`で囲みます。

これはHTMLマクロに該当するショートカットキーのようなもので、これで囲んだ範囲をHTMLとして処理してくれます。

#### 注意点③

`{html}~{html}`の内側にCSSを記載しますが、`style`タグで囲むのをお忘れなく。


#### 注意点まとめ

①〜③をまとめると、このような状態です。

![スクリーンショット 2021-10-27 16.51.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311681/81ba18e3-c556-70a7-d331-b9250837c24b.png)

```
{html}
<style type="text/css"> 
/* ここにCSSを書く */
</style>
{html}
```
### 4. 保存

保存ボタンを押すと、スペース全体にCSSが適用されてみやすいページが出来上がります！
プログラミングデバッグでよくみる単語帳

<h1>抑えておきたい単語集</h1>

<h2>phpの編集の場合</h2>

<table>
<thead>
<tr>
<th>単語</th>
<th>意訳</th>
</tr>
</thead>
<tbody>
<tr>
<td>undefined</td>
<td>未定義の(⇆ define:決定する)</td>
</tr>
<tr>
<td>scyntax</td>
<td>構文</td>
</tr>
 
<tr>
<td>fatal</td>
<td>致命的な</td>
</tr>

<tr>
<td>method</td>
<td>関数</td>
</tr>

<tr>
<td>propaty</td>
<td>所有物(取り出したい値の名前)</td>
</tr>

<tr>
<td>uncought</td>
<td>取得できない</td>
</tr>

<tr>
<td>array</td>
<td>配列</td>
</tr>

<tr>
<td>row</td>
<td>列(左右)</td>
</tr>

<tr>
<td>line</td>
<td>列(前後)</td>
</tr>

<tr>
<td>accept</td>
<td>受け入れる</td>
</tr>

<tr>
<td>refuse</td>
<td>拒否</td>
</tr>

<tr>
<td>attribute</td>
<td>属性</td>
</tr>

<tr>
<td>aboid</td>
<td>避ける</td>
</tr>

<tr>
<td>string(str)</td>
<td>文字の(文字型の)</td>
</tr>

<tr>
<td>intiger(int)</td>
<td>数字の(数字型の)</td>
</tr>

<tr>
<td>boolean(bool)</td>
<td>ブーリアン型(真偽、true,false型)</td>
</tr>

<tr>
<td>inbalid</td>
<td>無効な</td>
</tr>

<tr>
<td>argument</td>
<td>引数(引数)</td>
</tr>

</tbody>
<tfoot>
</tfoot>
</table>
ja-ginzaとja-ginza-electraの速度比較

# 概要
日本語NLPライブラリ**GiNZA**でリリースされた`ja-ginza-electra`モデルでは従来の`ja-ginza`に比べて精度が向上したようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130670/18ee9153-8df5-6d73-fad9-143f5d979106.png)
(出典：https://megagonlabs.github.io/ginza/)

ただ、速度面でどの程度差があるのか気になったので、本記事では両者速度を比較してみました。

# 準備
`python = "^3.9"`
`pip install ja-ginza = "^5.0.0"`
`pip install ja-ginza-electra = "^5.0.0"`


# コード
検証のために下記コードを用意
それぞれのモデルごとにトークン化を実施し、その際にかかった秒数をそれぞれ計測します。

```python:main.py
import time

import spacy


def use_ja_ginza(text, cache=None):
    nlp = spacy.load('ja_ginza') if cache is None else cache
    [token for token in nlp(text)]
    return nlp


def use_ja_ginza_electra(text, cache=None):
    nlp = spacy.load('ja_ginza_electra') if cache is None else cache
    [token for token in nlp(text)]
    return nlp


def stopwatch(func, times=100):
    # 桃太郎 芥川龍之介 https://www.aozora.gr.jp/cards/000879/card100.html
    s = 'むかし、むかし、大むかし、ある深い山の奥に大きい桃《もも》の木が一本あった。大きいとだけではいい足りないかも知れない。この桃の枝は雲の上にひろがり、この桃の根は大地《だいち》の底の黄泉《よみ》の国にさえ及んでいた。何でも天地｜開闢《かいびゃく》の頃《ころ》おい、伊弉諾《いざなぎ》の尊《みこと》は黄最津平阪《よもつひらさか》に八《やっ》つの雷《いかずち》を却《しりぞ》けるため、桃の実《み》を礫《つぶて》に打ったという、――その神代《かみよ》の桃の実はこの木の枝になっていたのである。'
    time_s = time.perf_counter()
    cache = None
    for i in range(times):
        cache = func(s, cache)
    time_e = time.perf_counter()
    return time_e - time_s


def main():
    d = {
        'ja-ginza': stopwatch(use_ja_ginza),
        'ja-ginza-electra': stopwatch(use_ja_ginza_electra)
    }
    d = sorted(d.items(), key=lambda x: x[1])
    print('\n'.join(map(str, d)))


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

# 結果
結果は以下の通り、`ja-ginza-electra` は `ja-ginza`と比べて４倍弱遅いことがわかりました。

```bash
$ python main.py
('ja-ginza', 6.013060999999652)
('ja-ginza-electra', 22.437576700000136)
```

# まとめ
精度面で向上した反面、速度はかなり遅いようです。
`ja-ginza-electra`を選択する際の参考になればと思います。
AfterEffects　文字を一文字づつ表示する方法

![一文字.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558142/b8fc3cb6-47cd-43e8-bd3f-b77a49de29ed.gif)

###■1テキストを書く

###■2テキストのアニメーターを追加
スケールを選択

###■3範囲セレクター
スケールを0に

開始を始めは0に
開始を表示したい秒数で100に

完成
【Python】月位置(方位角･高度･月齢)計算APIから月齢を取得してみた

# 初めに
ダッシュボード作成のために、月齢をAPIにて取得する
[月位置(方位角･高度･月齢)計算API ](https://mgpn.org/api/moon/)を使用すると取得できる。
⇒Pythonを用い、HP等で表示させる用途を想定

## 環境
- Windows10
- Python 3.8.12

## パラメータ
lat (float):必須、取得したい場所の緯度、
lng (float): 必須、取得したい場所の経度

本コードではparamsにてパラメータをセットしてください。

# コード
```Python:moon_age_api.py
# -*- coding:utf-8 -*-
import requests
import json

# moon_age_apiより月齢を取得する
moon_url = "https://mgpn.org/api/moon/position.cgi?json&lat={lat}&lon={lon}"
moon_url = moon_url.format(lat="34.00000", lon="135.00000")
moon_json = requests.get(moon_url).json()

# 小数2桁にまるめる
moon_age = round(float(moon_json["result"]["age"]), 2)
print(moon_age)

```

# 参考サイト

https://mgpn.org/api/moon/
IBMCloud ポータルからリソースが見えない時

##対処
複数ユーザ、それぞれ同じIAMポリシーで権限が全く一緒だが表示されるリソースリストに差異がある。
この場合、サポートチケットを起票してユーザと権限を同期してもらうことで正常に見れる様になった。

IAMポリシーに問題がないことが前提なので、そこは自分で確認しておく
https://cloud.ibm.com/docs/openwhisk?topic=openwhisk-iam&locale=ja#iam_set_policies_me
AfterEffects バウンドしてアイテムを出す方法。

#■バウンドして飛び出させる！
![バウンド.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558142/e78a9b49-9997-2d57-7490-a8b9a8380960.gif)

###■1アイテムを用意
丸シェイプレイヤー
テキスト
![スクリーンショット 2021-10-27 15.59.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558142/5911b064-cc85-b0c1-d2bc-126fffc75c24.png)

###■2テキストと丸シェイプレイヤーのトランスフォームを同期させる。
同期させないと二つのアイテムが分かれている状態。
同期させればシェイプレイヤーのトランスフォームの動きが同じになる。

![スクリーンショット 2021-10-27 15.59.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558142/4af1cd7b-f31a-d5e0-b415-2e007bc595e7.png)
丸の🌀を選択しシェイプレイヤーにドラック

###■3スケールをアニメーションはじめる場所は0表示したい時間で100に。

###■4エクスプレッションを使用しバウンドさせる。
シェイプレイヤーのスケールのタイマーマークをoptionおしながらクリック。
![スクリーンショット 2021-10-27 16.01.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558142/7dcfae1e-c0f5-42a2-f35c-7411c151459f.png)

文字打てるところが出現
そこに下記javascriptのコードを書く。

``` javascript
amp = .06; // amplitude
freq = 2; // frequency 
decay = 7; // decay (the more the value, the faster oscillations fade)
//----------------------------------
n = 0; 
if (numKeys > 0){ 
  n = nearestKey(time).index; 
  if (key(n).time > time){ 
    n--; 
  } 
}
if (n == 0){ 
  t = 0; 
}else{ 
  t = time - key(n).time; 
} 

if (n > 0){ 
  v = velocityAtTime(key(n).time - thisComp.frameDuration/10); 
  value + v*amp*Math.sin(freq*t*2*Math.PI)/Math.exp(decay*t); 
}else{ 
  value; 
}
```

完成。
Cloud BuildでPHPUnitテストを行う

# やること

1. `cloudbuild.yaml` に`docker-compose` の処理を追加
1. CloudBuild用の`docker-compose-test.yaml` を作成
1. CloudBuild用の`.env.testing` を作成


## `cloudbuild.yaml` に`docker-compose` の処理を追加

```yaml:cloudbuild.yaml
timeout: 1200s
steps:
  # builds the container image
  - name: 'gcr.io/cloud-builders/docker'
    id: Build
    args:
      - 'build'
      - '-t'
      - 'gcr.io/$PROJECT_ID/test:$SHORT_SHA'
      - '-f'
      - 'Dockerfile'
      - '.'

  - name: 'docker/compose'
    id: UnitTest
    args: [
        '-f',
        'docker-compose-test.yml',
        'run',
        '--rm',
        'php',
        'bash',
        '-c',
        'phpdbg -qrr vendor/bin/phpunit'
    ]
    env:
      - 'PROJECT_ID=$PROJECT_ID'
      # docker-compose-test.xmlで利用する環境変数
      - 'TAG=gcr.io/$PROJECT_ID/test:$SHORT_SHA'
```

## CloudBuild用の`docker-compose-test.yaml` を作成

```yaml:docker-compose-test.yaml
version: '3'
services:
  php:
    container_name: php
    # cloudbuild.yamlで設定した環境変数を利用
    image: ${TAG}
    depends_on:
      - redis
      - db
    ports:
      - 8080:8080
      - 8888:8888
    volumes:
      - ./:/var/www
      - ./php.ini:/usr/local/etc/php/php.ini
    environment:
      - TZ=Asia/Tokyo
  db:
    container_name: db
    image: mysql:5.7
    environment:
      - TZ=Asia/Tokyo
    ports:
      - 3306:3306
    command: mysqld --character-set-server=utf8mb4
    volumes:
      - mysql_data:/var/lib/mysql
  redis:
    image: redis:latest
    ports:
      - "6379:6379"
    command: redis-server --appendonly yes
networks:
  default:
    external:
      name: cloudbuild
volumes:
  mysql_data:
```

## CloudBuild用の`.env.testing` を作成

テスト用の環境変数を設定

```:.env.testing
APP_ENV=testing
APP_KEY= // 空にしておく

// 接続したいDBの情報を設定する
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=test_database
DB_USERNAME=root
DB_PASSWORD=
```
[Azure] Application Gateway v1 で構築検証してみる（E2E TLS/パスベース規則）①

Application Gateway v1 を触る機会があったので、構築検証した内容をまとめてみます。
各ポイントでの気づきを交えながら、解説していきます。

長くなるため、全4回の記事に分割して解説します。
　1回目：構築する構成図と事前準備（今回）
　[2回目：Application Gatewayの作成とエンドツーエンドTLSの設定](https://qiita.com/ninob/items/0d1f681f4edfce5bf882)
　[3回目：パスベース規則の設定](https://qiita.com/ninob/items/167beb82fff74f7f6b0d)
　[4回目：運用TIPS](https://qiita.com/ninob/items/0308e5aff4f12eaebf50)

## 検証構成
仮の要件として、犬システムと猫システムに1台のApplication Gatewayで負荷分散する構成とします。
＜要件＞
・犬用URL（dogs.test.co.jp）はエンドツーエンドでTLS化し、犬システムへ分散させる
・動物用URL（animals.test.co.jp）は「/dogs/」のパスを犬システムへ、「/cats/」のパスを猫システムへ分散させる。
　それ以外のパス（/birds/等）が来たらエラーページを表示させる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2139241/f1dac9d7-7a8f-08bd-f50b-32b4d6b5a178.png)

## 事前準備
#### ■ バックエンドのAPサーバ作成
・犬システム用に2台、猫システム用に1台、APサーバを作成する
・各サーバにIISをインストール
　（参考：https://docs.microsoft.com/ja-jp/azure/application-gateway/create-ssl-portal#install-iis-for-testing）
・自己署名証明書を作成
　（参考：[https://kogelog.com/2021/06/10/20210610-01/](https://kogelog.com/2021/06/10/20210610-01/) CER証明書とPFXファイルが必要）
・作成した証明書を、犬システムAP#1,2にインストール

アクセスすると、下記画像が表示されるようにしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2139241/6ce363a8-9db2-47a2-8fed-743cc5ad9a0a.png)

#### ■ Application Gateway用のサブネット/NSG作成
Microsoftの[こちら](https://docs.microsoft.com/ja-jp/azure/application-gateway/configuration-infrastructure)のサイトを参考に作成します。
＜NSG＞

:::note warn
送信インターネット接続は拒否しないように。
サポートに確認したところ、Application Gateway は、マネージドサービスのため、
Azureデータセンター内の管理用エンドポイント (パブリック IP) と通信できる必要があるそうです。
:::
上記サイトの設定規則を守らないと、ログやメトリックの収集ができない可能性があり、
また非サポート構成となるため、Microsoftのサポートを受けられない可能性があるとのこと。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2139241/d4e1b39a-9aeb-c0b5-c9af-31214423495a.png)
＜サブネット＞
Application Gateway専用サブネットが必要です。
Application Gatewayであれば、複数台同梱可能ですが、V1 SKUとV2 SKUは同梱できないなど制約があるようです。

:::note warn
記載はないのですが、サブネット名は命名ルールがあるようです。（2021年9月時点）
「アルファベットまたはアンダースコアで始まり、空白、ドット、アンダースコアで終わらない名前にする必要があります。」
:::
例えば数字始まりのサブネット名にすると、デプロイ時に上記の鍵括弧メッセージでエラーとなります。
作成画面での設定入力時にはチェックされませんでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2139241/c4bfaf2d-2af3-0b09-4596-d554fe734630.png)

#### ■ DNSの登録
Application Gateway経由でアクセスするFQDNを登録します。
フロントエンドIPは「10.5.0.84」にしますので、下記をAレコードで登録します。
・dogs.test.co.jp：   10.5.0.84
・animals.test.co.jp：10.5.0.84
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2139241/0f6ae52e-26f1-d066-07b2-ed6dcf3eb359.png)

事前準備は以上です。
次回は、実際にApplication Gatewayを作成し、エンドツーエンドTLSの規則を設定します。
第2回URL：https://qiita.com/ninob/items/0d1f681f4edfce5bf882
資産のドローダウン率・ドローダウン期間を出す[Python]

# はじめに
トレーディングシステムのバックテストで、資産のドローダウン期間の平均を求めたくなりました。

いろいろ調べてみたところ、最大ドローダウン率を出すプログラムはあるけれど、個々のドローダウン期間を出すプログラムって案外見つからないんですよね。

そこで自分で実装してみました。

# 環境
* Python 3.9.5

  
# コード
```Python:sum_model.py
def calc_drawdown(input):
    """calc drawdown list

    Args:
        input [list]: 資産推移

    Returns:
        [list]: [(ドローダウン率, ドローダウン期間, ドローダウンが始まった箇所のインデックス), ...]
    """
    
    hist = input + [float("inf")]
    dd = [] # 結果
    down_start_price = 0 # ドローダウン開始時の資産&ドローダウン突入のフラグ
    down_strat_day = 0 # ドローダウン開始時のインデックス
    tmp_min = float("inf") # ドローダウン後の最小値
    
    for day, price in enumerate(hist):
        if day == 0: continue
        
        # dd期間外
        if not down_start_price:
            # dd突入
            if hist[day] < hist[day-1]:
                down_start_price = hist[day-1]
                down_strat_day = day-1
                tmp_min = min(tmp_min, price)

        # dd期間中
        if down_start_price:
            tmp_min = min(tmp_min, price)
            # dd脱出
            if price >= down_start_price:
                dd.append(((down_start_price-tmp_min)/down_start_price, day - down_strat_day, down_strat_day))
                down_start_price = 0
                tmp_min = float("inf")
        
    return dd
```

### 実行例
資産を時系列順に格納した配列を入力します。

```Python:input
assethist = [350, 370, 400, 200, 100, 400, 350, 800, 400]
calc_drawdown(assethist)
```

### 結果
`(ドローダウン率, ドローダウン期間, ドローダウンが始まった箇所のインデックス)`をリストで返します。

```Python:output
[(0.75, 3, 2), (0.125, 2, 5), (0.5, 2, 7)]
```

最大ドローダウン75%は、ちょっと耐えられそうにありませんね。。
After effects マット設定　文字を空白から出す方法

#■マット設定を利用し文字を空白から出す方法

![飛び出すよ.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558142/3c7d6101-b288-fbdf-a38b-aaf375ef9b56.gif)

####■1飛び出す文字を用意
テキストを書くだけ

####■2テキストの位置を例として0秒で下がっている状態。1秒で真ん中に移動するようにキーフレームを打つ 

####■3文字を隠すように長方形のシェイプレイヤーを被せる。

####■3エフェクトでマット設定を検索　テキストに設定。
テキストを選んだ状態でマット設定をダブルクリック。

####■4エフェクトコントロール
レイヤーからマットを取り込むを作成したシェイプレイヤーに設定。
マットに使用　アルファチャンネル
反転マットにチェックマーク

![スクリーンショット 2021-10-27 15.41.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558142/e0cd3ee1-b579-965e-b3cd-925a5eac3d5c.png)


完成
PowerQuery でセルの値をパラメーター変わりに使う

#PowerQueryのパラメーター
PowerQueryにパラメーターというものがあるが、
使い勝手を知らない人には説明しづらいため、
セルに入力した値をPowerQuery内のSQLクエリに反映する方法を探した。

#パラメーターをつくる
##入力セルを決める
まずはパラメーターを入力する箇所を作り、テーブル化する。
「ID」がヘッダー、「neko.cat」は任意の値。
![excel6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2217989/53e1b4b8-3736-842d-0e9e-b09807acf94b.png)

##セルを取り込む
テーブルにカーソルを合わせて、データ⇒テーブルまたは範囲から　を押すと、
PowerQuery内の数式に以下が入力される。

```M
= Excel.CurrentWorkbook(){[Name="テーブル1"]}[Content]
```

これではテーブルとして認識されているため、以下のようにする
0番目（テーブルの1行目）だけを取り出した状態になる。

```M
= Excel.CurrentWorkbook(){[Name="テーブル1"]}[Content]{0}[ID]
```

##SQLを用意する
実行したいSQLを用意して、パラメーターに使いたい箇所に、
任意の文字列を入力する。
今回はWHEREの「--PARAM--」の位置にパラメーターを使う。

```SQL
SELECT
	*
FROM
	(values
	('NEKO'),('CAT'),('neko.cat'),('cat.neko')
	) as cat_neko_table (nekocat_id)
WHERE
	nekocat_id = '--PARAM--'
```

##クエリに取り込む
上記で用意してきたものを組み合わせて、１つのクエリにしていく。

```M
let
/*先ほど取り込んだセルの式を入れる*/
PARAM = Excel.CurrentWorkbook(){[Name="テーブル1"]}[Content]{0}[ID],

/*先ほど書いたSQLを入れる*/
BASESQL = "
SELECT
	*
FROM
	(values
	('NEKO'),('CAT'),('neko.cat'),('cat.neko')
	) as cat_neko_table (nekocat_id)
WHERE
	nekocat_id = '--PARAM--'",

/*「--PARAM--」の文字列を、PARAM（セルの値）にReplaceする*/
SQL = Text.Replace(BASESQL, "--PARAM--", PARAM),

ソース = Sql.Database("サーバー名", "データベース名", 
        [Query=SQL])
/* ODBCなら「ソース = Odbc.Query("dsn=DSN", SQL)」 */
in
    ソース
```
閉じて読み込みデータを出力すると、パラメーターに入力された内容で
条件付けがされていることがわかる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2217989/0ae5fcb5-1aee-0da4-a2de-9f4bb67826a0.png)

パラメーターを「CAT」に変えて更新してみると、出力データも変わった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2217989/5846c9dd-efba-4728-63ee-0f8ace5f0847.png)




#結果
日付の期間指定をする場合は2つパラメーターが必要である。
PowerQueryの相対日付フィルターなどでよいのでは？と思う場面もあるが、
データ量が多い場合は、SQLから期間指定をしたほうが都合がよい時がある。

難点としては、毎回更新する度に「ネイティブクエリ実行の許可」を
しなくてはならない。

本来パラメーターとして用意されている機能も、
よく調べたらユーザーライクに使えるものなのかもしれない。
Intel ControlFlagをCentOS7で動かしてみた

## Intel ControlFlag とは？
### レポジトリ
https://github.com/IntelLabs/control-flag
"A system to flag anomalous source code expressions by learning typical expressions from training data" ということで、機械学習によって生成されたデータを使って、ソースコードのパターン異常（要はおかしい箇所）を検出してくれるらしいです。

参考：
機械学習でコードの問題を自動検出、オープンソース化されたインテルの「ControlFlag」
https://japan.zdnet.com/article/35178435/
>Intelの自動コードデバッグツール「ControlFlag」がオープンソースとして公開され、無料で利用できるようになった。この動きは、潜んでいる異常を見つけるためにプログラムを精査することに疲れた多くの人にとって救いとなるだろう。… Gottschlich氏によれば、ControlFlagをたった2つの自社のソフトウェアのリポジトリーに使用しただけで、製品レベルの品質を備えた、実際に使われているプログラムに300以上の欠陥を発見することができたという

## 準備
手元で使ったサーバ。CentOS 7.9 minimalを使用。

```
[root@localhost control-flag]# cat /etc/redhat-release 
CentOS Linux release 7.9.2009 (Core)
```
cmake3, gcc10が必要、ということで、とりあえず下記を。
手順が抜けていたらすみません。指摘お願いします。

```
yum install epel-release
yum install scl-utils centos-release-scl
yum install devtoolset-10
scl enable devtoolset-10 'gcc -v'
source scl_source enable devtoolset-10
gcc -v
```
```
yum install epel-release
yum remove cmake
yum install cmake3
ln -s /usr/bin/cmake3 /usr/bin/cmake
cmake --version
```

## インストール
```
cd /home
yum install git
git clone https://github.com/IntelLabs/control-flag.git
cd control-flag/
```

現状、"cmake ."だと失敗したので下記のようにしたらビルドできたのですが、これで正しいのですかね…。

```
cmake -H. -Bbuild
cd build
make -j
make test
```

## データを準備
https://github.com/IntelLabs/control-flag
のページから、Medium のデータをとりあえず取得。公開されているのはC用のデータです。
とりあえずどんな方法ででも、ダウンロードしてサーバに配置すればOK。

## いざ検査

/home/control-flag/build/binの下に実行ファイルができているので安直にコピー。

```
cd /home/control-flag/build/bin
cp * /home/control-flag/bin/
```

### 検査方法：

```
[root@localhost control-flag]# ./scripts/scan_for_anomalies.sh -d /home/★検査したいソースコードのディレクトリ★ -t c_lang_if_stmts_6000_gitrepos_medium.ts -o /home/logs
```

### 検査時の様子

```
Training: start.
Trie L1 build took: 55.360s
Trie L2 build took: 18.067s
Training: complete.
Storing logs in /home/logs
Scan progress:3/36 ... in progress
Scan progress:6/36 ... in progress
Scan progress:9/36 ... in progress
Scan progress:12/36 ... in progress
Scan progress:15/36 ... in progress
Scan progress:18/36 ... in progress
Scan progress:21/36 ... in progress
Scan progress:24/36 ... in progress
Scan progress:27/36 ... in progress
Scan progress:30/36 ... in progress
Scan progress:33/36 ... in progress
Scan progress:36/36 ... in progress
[root@localhost control-flag]# 
```

### ログの確認
ログを見ると、結果が色々書いてあります。
手元のC++コードはみんな "Expression is Okay"で完了。
WordCloudの使い方簡単に

**初めに**
*自然言語処理のタスク*はますます普及していくと言われています。例えば、行政手続きを処理できるように、CVだけではなく、自然言語処理が大切にします。
今回、私はWordCloudについて紹介させていただきたいと思っています。
**コ－ド**：
私はGoogleColabでコ－ディングします。
まず、pipでPythonの必要なライブラリをインストールしなければなりません。
以下のイメ－ジの中で、二つのライブラリはmecab(日本語を処理するためのライブラリ）とunidic-lite（日本語の辞書のライブラリ）です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611568/86a49304-0c17-ab6a-9330-9fcf2e846380.png)
`!pip install mecab-python3`
`!pip install unidic-lite`
`!pip install wordcloud`

次はそのライブラリを使うために、importにする必要があります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611568/d60fff03-b5e2-7a3d-20be-301594d0f87c.png)
MeCabのライブラリを使用することは簡単だと思いました。以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611568/a66225a9-62f0-81e0-7944-bfc19a9d5ac1.png)


それから、resultの値を表示することです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611568/e4f3c2e1-6b35-209e-b14c-6403562ca188.png)
以上のイメ－ジから見ると、長い文章を分割してから、簡単あ言葉として、表示されています。
「最初」という言葉はカタカナの書き方もあるし、漢字の書き方もあるし、言葉のタイプもあります。このツ－ルは良いと思います。
日本語を表示するために、もう一つのライブラリを追加しないといけないです。それは`!apt-get -y install fonts-ipafont-gothic` です。
最後は一番大切なステップはWordCloudで言葉を表示することです。以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611568/10e5012f-4064-822e-348a-6dfa3639de8e.png)

MatplotlibでWordCloudの変数値を表示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611568/6463cb11-797e-6ff6-06fb-97a4b12a2ed5.png)
**まとめ**
これはWordCloudの使い方を簡潔に説明する記事です。質問があれば、教えてください。
Ps:私は外国人だから、日本語を勉強しています。日本語のミスがあれば、教えてくれませんか。
Bolt for pythonからSlackに画像をアップするには

小ネタです。備忘録

Slack Bolt for pythonを使って外部から取得した画像をSlackにアップロードするには。以下のようなやり方

```fileupload.py
import requests

def get_and_upload():
    filename = "test.gif"
    url = "https://lne.st/test.gif" #取得したいファイルの存在するURLを入れる
    urlData = requests.get(url).content
    download_file(url, filename)
    try:
        result = client.files_upload(
            channels=body['channel'],#channel_id を適宜入れること
            file=filename,
        )
        logger.info(result)
        uploadedurl = result['file']['permalink_public']
    except SlackApiError as e:
        print("Error uploading file: {}".format(e))
    finally:
        pass


import urllib.error
import urllib.request
def download_file(url, dst_path):
    try:
        with urllib.request.urlopen(url) as web_file, open(dst_path, 'wb') as local_file:
            local_file.write(web_file.read())
    except urllib.error.URLError as e:
        print(e)
```
DatabricksとLabelboxを利用したより包括的で安全なオンラインコミュニティの構築

[Curating More Inclusive and Safer Online Communities With Databricks and Labelbox](https://databricks.com/blog/2021/10/21/curating-more-inclusive-and-safer-online-communities-with-databricks-and-labelbox.html)の翻訳です

ビデオゲームやデジタルコンテンツは、世界中の多くの人々にとって、娯楽、人とのつながり、楽しみの源である一方で、炎上、荒らし、ネットいじめ、ユーザー生成コンテンツの形でのヘイトスピーチなど、有害な行為が頻繁に発生する場所でもあります。ソーシャルメディアのプラットフォームやゲーム開発会社は、最新のAIを駆使してネット上の有害行為に立ち向かおうとしています。しかし、実際には、AIのトレーニングは、モデルトレーニングのためにコンテンツを分類するために、有毒なユーザーコメントと良性のユーザーコメントの山をふるいにかける、手作業による手間のかかるラベリング作業から始まることが多いのです。

非構造化テキストデータを構造化データに変換するための、より迅速で費用対効果の高い方法を見つけることは、不要なコンテンツを識別して削除するという、より高度なユースケースをサポートする上で非常に有益です。ビジネス上のメリットとしては、DatabricksとLabelboxを利用して、より包括的で安全なオンラインコミュニティを構築するための作業と効率を向上させることができます。

- DatabricksからLabelboxにテキストデータを簡単にアップロードして注釈を付けることができます。
![02_screenshot_text_classification-e1634838957225-1024x608.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190656/4aaf79dc-bfc1-99c2-f9b5-2ac37dc49257.png)

ゲーム内の有害性モデルは、偽陰性率や偽陽性率が高いと、実際にはゲーマーの体験を損なう可能性があります。偽陰性の場合は、毒性のある行動をそのまま継続させることになり、偽陽性の場合は、健全なプレイヤーに削除のフラグを立てることになります。アクティブラーニングは、偽陽性や偽陰性を減らすのに役立つ効率的なプロセスです。Labelboxでは、アクティブラーニングを促進するために、モデルからの予測を素早く検査し、承認または修正することができます。訂正されたラベルを使ってモデルを再学習することで、将来同じ間違いを犯さないようにすることができます。

- Labelbox Connectorを使ってDatabricksにアノテーションをロードする

:::note warn
警告
提供されたコンテンツは、攻撃的または不快とみなされる可能性のある例示目的で使用されています。
:::

![03_db_screenshot-1024x358.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190656/2c45c337-c456-37a9-3f9b-941a82eb3c69.png)


- Labelbox Connectorは、非構造化データのワークフローをサポートします。

![04_db_workflow-1024x624.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190656/f4e4d830-58a6-1d67-41b4-12b0abba9320.png)

また、モデルエンベッディングをLabelboxに保存することで、次元削減による分析を容易にすることができます。例えば、モデルエンベッディングによって、今まで思いもよらなかった新しいデータのグループが見つかるかもしれません。また、偽陰性率や偽陽性率の高い特定のデータタイプが見つかるかもしれません。

このブログ記事で紹介されているプロジェクトは、[こちら](https://databricks.com/notebooks/model-assisted-labeling.dbc)からご覧いただけます。これらのデモノートブックは、有害コンテンツとの戦いに合わせて作られていますが、AIモデルの学習に高品質のトレーニングデータが必要な他のNLPのユースケースにも広く適用することができます。DatabricksとLabelboxの統合についての詳細は、[Data & AI Summit 2021](https://databricks.com/session_na21/productionizing-unstructured-data-for-ai-and-analytics)での講演をご覧ください。ご質問ですか？[こちら](sales-jp@databricks.com) までお問い合わせください。

Toxicity Solutions Acceleratorをダウンロードして、LabelboxによるModel Assisted Labelingを今すぐお試しください。Labelboxの無料トライアルでモデルアシストラベリングを有効にするには[こちら](sales-jp@databricks.com) までご連絡ください。

## Databricks 無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
dplyrを使った自作関数にfilterの条件とかを関数外から与えたいのにエラーになるとき！

ちょっと特殊な悩みですが、なるほどとおもったのでメモしておきます。
tidyverseをつかっていると、filter(hoge＜5)  みたいに条件を直書きしますが、これを関数化しようとするとエラーが出ます。
↓動く

```R
library(tidyverse)

mydata = tibble(hoge=c(100,10, 1), hit=c(T,T,F))
mydata%>%
  filter(hoge<5) 
```

↓動かない

```R
pattern="hoge<5"

myfunc <- function(INDATA, PATTERN){
Out<-
INDATA%>%
filter(PATTERN) 
return(Out)
}

myfunc(mydata, pattern)
```


これは、tidyシリーズが、NSEという記法を採用しているからだそうで、それを抜ける為には以下の様にする。

```R
pattern=quo(hoge<5) #quo()で内容を未評価のまま、patternに入れることが出来る

myfunc2 <- function(INDATA, PATTERN){

  Out<-
    INDATA%>%
    filter(!!PATTERN) #!!をつけると、「以下の物が変数であるので評価しろ！（NESでのPATTERN直打ちではないよ!)」となる
  return(Out)
}

myfunc2(mydata, pattern)
```

詳しくは以下のページに説明されています。
こういうときにrlangつかうのね、と実感しました。

雰囲気で理解するtidy evaluation(1): tidy evaluationの導入
https://qiita.com/uri/items/6d5f285280387dff0caa
pipenvとは

#pipenvとは
***pipenv***は、***pip***（パッケージ管理）と***venv***（仮想環境構築）をまとめて使えるツールのこと。
■ ***pip*** : パッケージのインストールや管理を行うためのツール。
■ ***venv*** : 同じシステムの中に異なるPythonの環境を構築することができるツール。
仮想環境を作成することで、Pythonのバージョンが異なるものや同じモジュールでも複数のバージョンの使い分けなどを行うことができる。また、システムで使用している環境に影響を与えることなく、モジュールの追加や入れ替えを行うことができるメリットがある。

#pipenvの使い方
####■ pipenvのインストール
pipenvのインストールは、pipを使って下記のコマンドでインストールを行う。

```
$ pip install pipenv
```

####■ 仮想環境の作成
使用するPythonのバージョンを指定して、以下のコマンドを実行すると仮想環境が作成される。指定バージョンがインストールされていない場合は、自動的にインストールされる。

```
$ pipenv --python 3.9    // Python3.9の環境を作成する場合
```

####■ パッケージのインストール、アンインストール
パッケージをインストール、アンインストールする場合は以下のコマンドで行う。

```
$ pipenv install <パッケージ名>        // インストール
$ pipenv uninstall <パッケージ名>      // アンインストール
```

####■ 仮想環境への出入り
仮想環境に入ったり、抜けたりする場合は以下のコマンドを使う。

```
$ pipenv shell   // 仮想環境へ入る
$ exit           // 仮想環境から抜ける
```
TransactionsRoot(もしくはTransactionsTrieなど)の手動での計算方法

Londonハードフォーク以降の話

誰も見ないシリーズ（シリーズになるかどうかは不明）

EthereumのBlockのBlockHeaderに格納されているTransactionsRoot(もしくはTransactionsTrieなど)
はBlockに格納されるTransaction一式から生成されるMerkle Patricia Trieのroot hashである。

Rootの計算方法は、ひたすらTrieにKey-Valueを登録すればよい。
Merkle Patricia Trie自体の説明は他に譲り、かつ、そこらへんの処理はライブラリに任せて、ここでは何をKeyとValueに入れなければいけないのかのみ説明する。

Key : TransactionIndexをRLP encodeした値
Value : Transactionの中身全部をserializeした値*

*余談だが、この値をKeccak256でハッシュ化するとTranasactionHashが計算可能である


Keyに関しては単純でRLPEncodeなので(RLPEncode自体の説明は調べれば出るのでGO!)
indexが1なら0x01みたいな感じである（もちろん文字列ではない、念のため）

Valueに関しては、とりあえずTransactionHashが正しく計算できるならばその一段階前と考えれば問題ない。
serializeの中身は、格納されたデータをRLPEncodeして、Transactionタイプを付記している
https://github.com/ethereumjs/ethereumjs-monorepo/blob/f15f28b580923d040c6bdf9de68ff38cf1f5fab4/packages/tx/src/eip1559Transaction.ts#L297
(上記のeip1559Transactionの場合、Transactionタイプである2をencode後、追記していることがわかる)

厄介なのは、LegacyなTransaction以外が出現したことにより、Transactionタイプによって分岐をかけないといけない点である

https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/tx/src
Ethereumjsを参考として提示するが、
2021/10現在
eip1559Transaction
eip2930Transaction
legacyTransaction
の三つのTransactionが存在しているので、それぞれのTransactionで正しい値を格納して処理しよう
キャンバスアプリで水平にスクロールバーを追加したい

https://qiita.com/taku_maru/items/3cc86cab108ad7f32826

基本的には上記リンクを参考にしていますが、その他に気づいたことなども本記事ではまとめています。

# 作成例
![qitta_横スクロールバーを追加する.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/b5465389-4ea4-f32f-6b24-9269737db842.png)
こちらの例では、垂直コンテナの下に水平コンテナ及びギャラリーを追加しています。

### 水平コンテナについて
水平コンテナには追加したギャラリーの項目に対応するラベルを追加しています。

### 垂直コンテナ下に追加するのはなぜ？
水平コンテナとギャラリーを垂直コンテナ下に追加する理由は、**水平コンテナに追加したラベルとギャラリーの項目を連動して**スクロールさせたいためです。

:::note warn
LayoutOverflowX(もしくはLayoutOverflowY)プロパティについて
この時、水平コンテナのこれらのプロパティはいずれも「非表示」に設定します。
:::


#こんな時は
実装中、以下のような場合に遭遇する場合があります。

###LayoutOverflowX/Yプロパティが見当たらない
左側サイド バーにある 挿入 ペインの レイアウト タブで、水平コンテナー を選択してください。

:::note warn
Power Apps上部の挿入タブから追加できるコンテナではLayoutOverflowXプロパティは存在しません。
:::

### LayoutOverflowX/Yプロパティの設定は正しいのにスクロールバーが出現しない
親コンテナ配下にいる**子コンポーネントの幅を親コンテナよりも大きく**することを忘れていないか確認してください。

### 水平コンテナの高さが思い通りにならない
プロパティ「高さ(伸縮可能)」がオンになっている可能性があります。
デフォルトではオンになっているのでこの設定が不要な場合はオフにしましょう。
<dl>
<dt>オンになっている場合</dt>
<dd>![qitta_水平コンテナ①.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/f93b9aeb-4d96-5193-ba68-fbdde9b17d14.png)</dd>
<dt>オフになっている場合</dt>
<dd>![qitta_水平コンテナ②.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/d5260ad9-5c80-183c-2b8c-62f238e8c76b.png)</dd>
</dl>

# その他参考

https://docs.microsoft.com/ja-jp/powerapps/maker/canvas-apps/build-responsive-apps#auto-layout-containers

###コンテナコントロールのメリットについて

https://ippu-biz.com/development/powerplatform/powerapps/container/
Montereyのバンドルソフトウェアのバージョン

Montereyがリリースされたので年に一回のいつものやつ

| path | High Sierra (10.13) | Mojave (10.14) | Catalina (10.15) | Big Sur (11) | Monterey (12) |
|------|---------------------|----------------|------------------|--------------|---------------|
|/bin/bash|3.2.57|3.2.57|3.2.57(1)| 3.2.57(1) | 3.2.57(1) |
|/bin/zsh|-|5.3|5.7.1| 5.8 | 5.8 |
|/usr/bin/perl|5.18.2|5.18.2|5.18.4| 5.28.2 | 5.30.3 |
|/usr/bin/php|7.1.7|7.1.19|7.3.8| 7.3.22 | N/A |
|/usr/bin/python|2.7.10|2.7.10|2.7.16|  2.7.16 | 2.7.18  |
|/usr/bin/python3|-|-|3.7.3| 3.8.2 | 3.8.9 |
|/usr/bin/ruby|2.3.3p222|2.3.7p456|2.6.3p62| 2.6.3p62 | 2.6.8p205 |
|/usr/bin/emacs|22.1.1|22.1.1|N/A| N/A | N/A |
|/usr/bin/vim|8.0|8.0|8.1| 8.2.850 | 8.2.2671 |
|/usr/bin/git|2.13.5|2.17.1|2.21.0| 2.24.3 | 2.30.1 |

[Big Sur](https://qiita.com/seiyakubo/items/ceea6ba1c236ddee948f) でDeprecatedになってたけど、ついにPHPが削除された。
/etc/resolve.conf　の書き換え防止

AWSのEC2でサーバを再起動させると、/etc/resolve.confが書き換わります。
その対処法として、これまで再起動のたびに書き換えるという作業をしていました。。。
これはNetworkManagerに原因があるようです。
以下の方法をとることでこの書き換わりが防止できます。

〇NetworkManagerのインストール

```
yum install NetworkManager
```
〇NetworkManager.confの書き換え

```
cd /etc/NetworkManager
cp NetworkManager.conf NetworkManager.conf.org
vi NetworkManager.conf
```
下記、追記

```
------------------------------------------
[main]
#plugins=ifcfg-rh,ibft
dns=none

------------------------------------------
```
〇NetworkManagerのリロード

```
systemctl start NetworkManager
systemctl reload NetworkManager
```
これで設定ファイルの内容が反映される。
あとは/etc/resolve.confを書き換えて
systemctl reload NetworkManager
したときに、nameserverの場所が変わっていなければ成功です。
aws lambda + nodejs + mysqlのコールドスタート時スピンアップ速度比較

AwsLambda + nodejs + mysql + ORMごとのInit　Duration比較

# 環境
- nodejs 14.x
- メモリ 1024GB
- DB接続 => 1行取得 => 切断
- 試行回数 それぞれ3回くらい
- serverless framework 使用
- typescript 4

# 結果

|  ライブラリ  |  InitDuration  |
| ---- | ---- |
|  mysql2  |  270ms  |
|  sequelize |  470ms  |
|  typeorm |  780ms  |
|  prisma |  デプロイ出来んかった  |

typeorm入れただけでけっこー重くなるの、ツラミがある。
typeormは、mysqlだけ使いたくてもpostgresql/oracle/sap/mongodbとか色々なコードが入ってしまうため、重くなってる模様。

Webpack Bundle Analyzerを見た感じだとprismaが非常にコンパクトだったので、期待したい。
【CakePHP3】DBから取得したデータを自由自在に



# cakephp3でクエリを使ってテーブルのデータを取得する方法

cakephp3でクエリを使ってデータを取得するお作法は下記の通り

```
// すべての article を検索
// この時点ではクエリーは走らない。
$query = $articles->find('all');

// イテレーションはクエリーを実行する
foreach ($query as $row) {
}

// all() の呼び出しはクエリーを実行し、結果セットを返す
$results = $query->all();

// 結果セットがあれば すべての行を取得できる
$data = $results->toList();

// クエリーからキーと値の配列への変換はクエリーを実行する
$data = $query->toArray();
```

ただ、contain等を使って、情報を取得すると助長なオブジェクトまで取得したり、配列の構造上使いづらくなってしまうことが発生する。

そこで

```
$query->hydrate(false);
```

を使うと、素となる配列だけが取得できるので扱いやすくなる。

また、Hashなどを組み合わせると、

```
$a = [
    [
        'User' => [
            'id' => 2,
            'group_id' => 1,
            'Data' => [
                'user' => 'mariano.iglesias',
                'name' => 'Mariano Iglesias'
            ]
        ]
    ],
    [
        'User' => [
            'id' => 14,
            'group_id' => 2,
            'Data' => [
                'user' => 'phpnut',
                'name' => 'Larry E. Masters'
            ]
        ]
    ],
];
```

から

```
$result = Hash::combine($a, '{n}.User.id');
/* $result は以下のようになります:
    [
        [2] =>
        [14] =>
    ]
*/

$result = Hash::combine($a, '{n}.User.id', '{n}.User.Data.user');
/* $result は以下のようになります:
    [
        [2] => 'mariano.iglesias'
        [14] => 'phpnut'
    ]
*/

$result = Hash::combine($a, '{n}.User.id', '{n}.User.Data');
/* $result は以下のようになります:
    [
        [2] => [
                [user] => mariano.iglesias
                [name] => Mariano Iglesias
        ]
        [14] => [
                [user] => phpnut
                [name] => Larry E. Masters
        ]
    ]
*/

$result = Hash::combine($a, '{n}.User.id', '{n}.User.Data.name');
/* $result は以下のようになります:
    [
        [2] => Mariano Iglesias
        [14] => Larry E. Masters
    ]
*/

$result = Hash::combine($a, '{n}.User.id', '{n}.User.Data', '{n}.User.group_id');
/* $result は以下のようになります:
    [
        [1] => [
                [2] => [
                        [user] => mariano.iglesias
                        [name] => Mariano Iglesias
                ]
        ]
        [2] => [
                [14] => [
                        [user] => phpnut
                        [name] => Larry E. Masters
                ]
        ]
    ]
*/

$result = Hash::combine($a, '{n}.User.id', '{n}.User.Data.name', '{n}.User.group_id');
/* $result は以下のようになります:
    [
        [1] => [
                [2] => Mariano Iglesias
        ]
        [2] => [
                [14] => Larry E. Masters
        ]
    ]
*/
```

と使えるので、keyを元に配列操作をしやすくなる。

https://book.cakephp.org/3/ja/orm/retrieving-data-and-resultsets.html

https://book.cakephp.org/3/ja/core-libraries/hash.html
WINDOWSでCドラをクローンする方法

# ソフト

クローンソフトをダウンロードする。
Macrium Softwareを推奨する．
https://www.macrium.com/reflectfree

特徴：
・クローン先が元SSDより容量が小さくても保存クローン作製可能．
・ドラッグアンドドロップで簡単にPartitionを設定可能．
・メルアドを入力すれば無料で，ダウンロード用のリンクが得られる。
・トライアル期間が過ぎても1週間延長できる．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527627/86bcfb11-e7a5-cf98-ebb1-353ebc786d0a.png)

手順：
新SSDをアクティブにする．
NTFSでよい．
ドライブZなど適当に選ぶ．

Macrium Softwareを起動する．
クローン元を選択して，クローン先を選ぶ．

ドラッグアンドドロップでPartitonを選択する．
次へを押せばクローン処理が始まる．

・注意事項：
Cドライブだけでなく，回復Partition，システムPartitionなども漏れなくクローンしないと起動しない．
Kubernetesの無料SSL設定

#GoogleマネージドSSL証明書
K・8・Sのキャラクターingressについて今日は触れたい。
中でもSSLという昨今は基本と言われる技について詳しく見ていきたい。

いまはLet's EncryptなGoogleマネージドSSL証明書というものが
無料で扱えるので、牽制技(テスト)として使う分には十分な性能といえる。

参考：
https://qiita.com/munaita_/items/d250d1872e3fb4178aa7
#yamlファイルの書き方
設定は「kind: Ingress」で以下のようにする。

```yaml:ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: example-ing
  annotations:
    kubernetes.io/ingress.allow-http: "false"
    nginx.ingress.kubernetes.io/rewrite-target: /
    kubernetes.io/ingress.global-static-ip-name: "prod"
    ingress.gcp.kubernetes.io/pre-shared-cert: "managed-prod"
spec:
  rules:
    - host: admin.example.jp
      http:
        paths:
          - path: /*
            backend:
              serviceName: example-svc
              servicePort: 8080
```
複数設定したい場合は、「ingress.gcp.kubernetes.io/pre-shared-cert」のところをカンマ区切りで記載する。

これを知っていれば立ち回りで圧倒されることもないだろう。
ただ、マネージドSSLは無料なだけ、セキュリティの質は下がる。
大会(本番)時は有料の方は望ましい。

現場からは以上です。
【プリントクリエイター】チェックボックス、ラジオボタンの表示方法

## はじめに
プリントクリエイターでチェックボックス、ラジオボタンを表現したい場合には工夫が必要です。kintoneで保存している値をそのまま出力しているため、例えばラジオボタンの場合だと値を「●」で保存する必要があります。

以下サイトを参考にしつつ、自分なりにkintoneをカスタマイズをしてチェックボックスとラジオボタンの実装を行いましたので紹介します:point_up_tone1:

https://toyokumo-blog.kintoneapp.com/printcreator_checkbox/

## ラジオボタンの場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700107/090bdfae-0c47-4b7e-7c2f-91d361d1c48e.png)
通常のラジオボタンの選択画面はこのような感じですね。できるだけユーザーにいつも通り操作できるようこの状態を保ちつつ実装する方法を検討しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700107/3db31677-19d2-95e3-d7d2-398e0a7e533a.png)

実装したのがこちらです。選択肢分の別項目(PDF用)を用意しました。ユーザーはこのPDF用の項目は使用することはないため以下のJavaScriptのコードを設定し画面には表示しないように設定します。

```javascript
kintone.app.record.setFieldShown('フィールド名', false);
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700107/a01e016c-b92b-c420-044d-df3fbc4f2063.png)


また、値「●」を保存する必要があるので、上記の計算式を使用して「はい」が選択された場合にのみ値を設定します。
これが完了したら、プリントクリエイターにて「●」を上手いこと調整すれば完了です！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700107/6989cadf-1470-31af-9ae7-007ed96c10f1.png)

結構きれいに設定できました:information_desk_person_tone1:

## チェックボックスの場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700107/0f8eba19-1bef-64ba-158e-ee90c7d0c39d.png)
ラジオボタン同様に選択肢分の別項目(PDF用)を用意し、画面では非表示となるように設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700107/a1fd314a-3133-80d3-1b4b-7d25a0ffd0b4.png)
上記の計算式を使用して選択肢の中に「１」が含まれている場合にのみ値を設定します。
こちらもプリントクリエイターにて「✔」を上手いこと調整すれば完了です！！

## さいごに
上記で紹介した方法にてプリントクリエイターにて試してみてください:pray_tone1:
[Win10] PowerShellのSSHで公開鍵(public key)のPermission対策

こういうエラーをどう対応するか？
Windowsではchown，chmodとかできない。でもcygwinは嫌いな人向け。

```
CurrentDir> ssh hoge
The authenticity of host 'hoge' can't be established.
ECDSA key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
Are you sure you want to continue connecting (yes/no)? yes
Failed to add the host to the list of known hosts (C:\\Users\\sugimura/.ssh/known_hosts).
sugimura@hoge: Permission denied (publickey).
```

Windowsはuser直下フォルダはadminもアクセス可能になっていて、user onlyのpermissionとしてDocumentsを使うみたい。
したがって下記のようにconfigとkeyの格納フォルダを分けておくとうまくいく。
**すごく残念**

- sshのconfigファイルは  %homepath%\.ssh フォルダに置いておく
- sshのkeyファイルは %homepath%\Documents\.ssh フォルダに置いておく
- configファイルでのIdentityFileの指定は ~/Documents/.ssh/<key> とする

なお、configファイル内はpath separatorが\でも/でもいいみたい。
mac, linuxとの互換性（Documents/を消すだけなので修正が容易）を考えて"/"を使ってる。




## 過去情報

**コマンドで頑張ってWindows内部のPermissionを制御する方法**

こんな感じのコマンドで行けます。**<publickey>**は自分のファイル名に置き換えてください。

- コマンドプロンプトを管理者モードで起動
    - コマンドプロンプト起動時に，右クリックで管理者で実行すればよい。

```
anyDir> cd %USERPROFILE%
CurrentDir> takeown /F .ssh /A
CurrentDir> takeown /F .ssh
CurrentDir> icacls .ssh /grant Administrators:F

anyDir> cd ~/.ssh
CurrentDir> takeown /F <publickey> /A
CurrentDir> takeown /F <publickey>
CurrentDir> icacls <publickey> /grant Administrators:F
```
PHP Unitで、最後までテストケースが処理されない問題

## 状況
仮で以下の3つのテストケースを作成していました。

```
1.データ取得系
2.例外発生系
3.サービスクラスの中のとある処理
```

上記で実行すると、1番と2番しか実行されていない。なんでや。。。。

## 原因
2番の、例外発生のテストケースの存在が原因だった。実際に例外を発生させるテストケースで、それをキャッチして例外のメッセージが正しいか判定しているのですが、
冷静に考えたら、エラーとか例外発生したらプログラムって途中で終わるよなと。。。

以下のように例外メッセージが正しいかを判定しているので、通常の「例外が発生しました」的な表示が出ないので、問題なく最後まで正常に処理されているような気持になっていた。

```php:anime-suko.php
$this->expectExceptionMessage(json_encode($custom_message));
```

## 解決方法
テストの期待結果として例外発生やエラーメッセージの判定だけなら上記だけでいいが、テスト対象メソッド実行後にDBのデータの判定などした場合は、テストコードの中でtry-catchで囲って、catchの中で新たな期待結果の確認のコードを書く。
PHPUnitでテストケースを個別に指定して実行したい場合

phpunitでテストコードを書いている場合、全体実行だけでなくグループ単位だったり、書いているケースを個別で実行したい場合があります。
そんな時のコマンドメモです。

## グループ単位の場合

```
phpunit --group=testA
```

## ケース指定の個別の場合

```
phpunit --group=testA --filter "testA-001"
```

filterのみでも実行可能です

```
phpunit --filter "testA-001"
```

日本語のテスト関数名にしている場合も実行可能です

```
phpunit --filter "テスト〜〜〜がエラーにならないことを確認する"
```
djangoにおけるテンプレートの継承についてまとめてみた

本日のお題
-
本日のお題はdjagoアプリケーションにおけるテンプレートの継承です。

少し理解に時間がかかったので、整理するためにまとめます。

テンプレートの継承とは
-
テンプレートの継承とは、他のテンプレートファイルを読み込む機能のことです。
これにより共通部分を何度も記述する必要がなくなったりメンテナンスが簡単になったりといういつものやつですね。

継承には、
- 共通の親に不特定多数の子要素を埋め込むパターン
- 一つの子要素が不特定多数の親要素に出張するパターン

の2つがあります。
head要素やヘッダー・フッターなどを共通化しておいてそこに各種テンプレートを埋め込むというのが前者、いくつかのページでサイドバーを使い回すのが後者といった感じですね。

前者の方法を取る際にはdjangoではextendsを、後者ではincludeを用います。

共通の親要素を用いた継承〜extends
-
複数の子要素で親要素を共有する場合には、親要素子要素に以下のように記述します。

```html:myapp/index.html(子要素)
<!-- extendsを用いて親要素をtemplates以下の相対パスで指定 -->
{% extends "myapp/base.html" %>
  <!-- block body ~ endblockまでが、親要素に読み込まれる。 -->
  {% block body %}
  {% endblock %}
```


```html:myapp/base.html(親要素)
<html>
<head>....</head>
<body>
  <!-- block body ~ endblockの部分に子要素が埋め込まれる。 -->
  {% block body %}
  {% endblock %}
</body>
</html>
```
親要素が共通化されている場合には、親と子の両方の編集が必要です。

共通の子要素を用いた継承~include
-
逆に、子要素が共通化されている場合であれば、親要素の記述のみで大丈夫です。

```html
<!-- includeする子要素を、templates以下の相対パスで指定 -->
{% include "myapp/result.html" %}
```
とっても簡単ですね。

終わりに
-
以上が、djangoにおけるテンプレートの継承の仕組みになります。
うまく使って効率化していきたいですね。
glslでノイズだけでそれっぽい水を作る

中の人の作ったマイクラ統合版向けシェーダーESBEシリーズのテクスチャを使わない比較的コスパの良い水です
流れだけの解説です雑です(コードはある)

# コンセプト
## 前提条件
(マイクラ統合版の制約でもある)

- ワールドの絶対座標とカメラからの相対座標がわかっている
- バッファ等(普通のテクスチャも)は使わない
- 地形情報の取得手段もない

## 目標
- 波と空の反射のみ実装する
- ノイズの使用回数は最低限に抑える

# ノイズまわり
ここではコストを下げるためvec2→floatのノイズを使う
ESBE_1G,2Gではシンプレックスノイズ3Gではタイリングするために仮でパーリンノイズを使っている
これを重ねて所謂fbmを作るわけだがESBEでは横に引き伸ばしたほぼ同じ倍率のの2枚のノイズを違う方向に動かすことで質感を表現している
タイリングする場合は拡大縮小の際に注意が必要

水本体とは別に反射した空の雲を描くためにもノイズを使う
ESBE_3Gではシンプレックスノイズを2回用いている
色が取得できれば良いので波の反射の結果の座標を投げて色を返す形の関数なら何でも良い

# 法線
前章で述べた通り今回はfloatで波のマップを計算しているので単純に法線でreflectしてというわけにはいかない
ポリゴン本体の法線はコストは高いがcross(dFdx,dFdy)で求められる
(マイクラ統合版の場合は法線すらattributeにないのであらかじめ算出しておくことがよくある)
波の高さ(本質的には法線)が影響する事象を考える

- 反射
- 屈折
- 透明度

実質同じことを言っている気もするが大体こんなところ
1番見た目に関わってくるのが反射と屈折で2番目が透明度といったところ
しかしコンセプトで述べた通りバッファは使わない約束なのでフラグメントシェーダーで実装する以上屈折については諦めざるを得ない
透明度の実装は反射のついでに作れる

## 反射
最初に空が平面でありy軸と垂直であると仮定しておく
一次元のデータしか与えられていないので相応の関数を用意しない限り反射先の座標を直線上に移動させることしかできない
法線によって反射先の座標が決まるが実際だと波による遮蔽があることから横方向のずれよりも前後方向のずれが強調されると仮定する
法線等のデータを二次元に落とし込んで実装することもできるしESBE_1G,2Gはそうしてきたがそれに起因するデメリットの方が大きいので3Gではreflectを使う実装にしている
視線ベクトルはカメラからの相対座標に等しいので反射はreflect(relative.xyz,N)

波の高さの影響がカメラから見て前後方向に出ると仮定したので反射先の座標のxz座標の長さに波の高さの任意倍のオフセットをつける
p.xz+h*p.xz/length(p.xz)
もちろん整理するともう少し簡単な形になる
さらに距離によってオフセットの倍率を変えると良い

空が平面である仮定から最終的にその平面の座標は反射座標のxzをyで割る形になる
しかし単純にyで割るだけだと無限遠に雲があることになってしまい画面に貼り付いているように見えて不自然なので指数関数で処理する
p.xz*pow(p.y,-.8)
0.8は適当
好みでどうぞ

## 透明度
波の高さなんてポリゴンから見ればないようなものなので無視してポリゴンの法線と視線ベクトルのdotを関数に投げるなどして反射率とみて混ぜていく
ポリゴン本体の透明度は反射率をそのまま用いてもそれっぽくなるので良い
ところで波の高さを反射率に加えて考慮する場合は反射の章のreflectの前に波の高さの処理を挟むべきである

# 空
平面に雲を描く流れは自サイトで解説済み
https://mcbeeringi.github.io/mc/how/8.html
2次元座標を渡して色が帰って来れば良いので雲である必要はない
ただその場合は反射の章の最後の無限遠の描写についても考慮すべき

# 例
![img](https://mcbeeringi.github.io/esbe-3g/photo/2.0-0.jpg)

# コード
https://github.com/McbeEringi/esbe-3g/blob/master/ESBE_3G/shaders/glsl/terrain.fsh#L54
Human InterFaceGuideline を理解する　その4

「Requesting Permission」
-
ユーザーには、アプリが現在の場所、カレンダー、連絡先情報、リマインダー、写真などの個人情報にアクセスできるかを決める許可を提示する必要がある。
この情報にアクセスできるアプリを使用することの利便性は高く評価される。
ただ、ユーザーが自身で個人データを管理できることも求められている。
また、明らかに必要なデータもとる必要がある。

注意点
・アプリがその情報を必要とする理由を明記しなければならない。なるべく簡潔な内容で辺に凝りすぎてもよくない
・アプリの機能に必要な場合にのみ、起動時に許可をリクエストする
・過剰に個人情報をリクエストすると離脱につながる
・同様に不必要に位置情報を要求しないこと
・システム提供のアラートを使用する。システムが提供しているアラートを使用した方が良い。見慣れているから。

Settings
--
アプリでは、設定を選択する方法を提示する必要がある。しかし、ほとんどのアプリはそれらは回避できる。
設定をしてくれるとほとんどのユーザーにとってよりよく機能する。エクスペリエンスを調整する便利な方法も提供している。

・システムからできることを考える。ユーザー、デバイス、または環境に関する情報が必要な場合は、ユーザーに尋ねるのではなく、可能な限りシステムに問い
・アプリ内での設定オプションには慎重に優先順位を付ける。
・頻繁に変更されない設定オプションは「設定」アプリに配置しましょう
「設定」アプリは、システム全体で構成を変更するための中心的な場所ですが、ユーザーがアプリを離れる必要があります。
・必要に応じて「設定」アプリへのショートカットを提供する。設定の変更が必要である場合はそれをタップして該当する設定場所にジャンプする。
Vue.jsで "Mixed spaces and tabs  no-mixed-spaces-and-tabs"というエラーに直面

##エラー文
Vue.jsで以下エラーに直面しました。

```
Failed to compile.

./src/components/Top.vue
Module Error (from ./node_modules/eslint-loader/index.js):

/Users/XXXX/Desktop/XXXX/src/components/Top.vue
  44:2  error  Mixed spaces and tabs  no-mixed-spaces-and-tabs

✖ 1 problem (1 error, 0 warnings)
```

##原因

コードを書く際スペースを打つと思うのですが、
スペースキーでやるか、tabキーでやるかだと思います。

今回のエラーは下図でいう赤枠部分に上記両方のキーでスペースを作ったことが原因です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1475666/c51f829b-e218-df2e-9c25-d00e36d29e20.png)

##解決方法
tabキーのみでコードをフォーマットしたら、上記エラー解消しました。

その他、タブとスペースの混在を許可する設定をして解消する方法もあるみたいですね。
Jetpack Composeのスクリーンショットを撮影する最小構成

## 概要

* Jetpack Composeのコンポーザブル関数のスクリーンショットを撮るという記事です
* とても簡単です :thumbsup: 


# プロジェクトを作る

Android Studio で新規プロジェクトを作ります。テンプレートは **Empty Compose Activity** を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56635/330a33d4-7ff5-2fb2-2a83-d6881629cf50.png)

次に必要なライブラリを追加します。`androidx.compose.ui:ui-test-manifest`だけデフォルトで入っていないはずなので追記します。

```gradle
dependencies {
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
    androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
    debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version" // ←デフォルトで入っていないので注意
}
```

スクリーンショットを撮りたいコンポーザブルを作成しますします。この例ではテキストとボタンを縦に並べたものを作成しました。プレビューとコードはこんな感じ。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56635/67088360-5b85-e40a-e9e2-5117d623b452.png" width="320" />


```kotlin
@Composable
fun HelloWorldContent() {
    Column(
        modifier = Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.spacedBy(12.dp, Alignment.CenterVertically),
    ) {
        Text("Hello, World!")
        Button(onClick = { }) {
            Text("Click me")
        }
    }
}

@Preview(showBackground = true)
@Composable
private fun HelloWorldContentPreview() {
    HelloWorldContent()
}
```

# スクリーンショットを撮影する

スクリーンショットを撮るテスト用クラスを`androidTest`配下に作成します。やることはたったの4つだけです。

1. `createComposeRule()` で `composeTestRule` を作成する
1. `composeTestRule` に `setContnet{ }` で対象のコンポーザブルをセットする
1. `captureToImage()` でスクリーンショットを撮影する
1. `saveScreenshot()` で撮影したスクリーンショットを保存する (`saveScreenshot()`は[CodelabのRallyアプリ](https://developer.android.com/codelabs/jetpack-compose-testing#0)内にある関数ですが、ここでは割愛します)

```kotlin
class HelloWorldContentTest {
    @get:Rule
    val composeTestRule = createComposeRule()

    @Test
    fun helloWorldScreenshot() {
        composeTestRule.setContent {
            HelloWorldContent()
        }

        val bitmap = composeTestRule.onRoot().captureToImage().asAndroidBitmap()
        saveScreenshot("hello-world", bitmap)
    }
}
```

このテストを実行すると、エミューレータ内上でスクリーンショットが撮影されます。撮影したスクリーンショットを確認するには、Android Studio の **Device File Explorer** を使います。私の環境では `/data/data/<アプリパッケージ名>/files/hello-world.png` に保存されていました。ばっちりスクリーンショットが撮れています :thumbsup: 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56635/fb4914eb-ff77-4213-d09d-911bb0ee9148.png)



# 補足

* `setContent()`は1つのテスト(`@Test`を付けている関数)あたり1回だけ呼ぶことができます
* Android上で実行される Instrumentation Test なので、スクリーンショットの保存先も Android 上になります。デスクトップに保存するといったことはできないので、スクリーンショット撮影後に適当な場所に移動する必要があります
* 実際のスクリーンショットを撮影する用途はコードの変更によって意図しないUIの変化が発生していないかを検証することだと思います。スクリーンショットはBitmapで取得できるので、ゴールデンファイルを用意してそれと1ピクセルずつ一致していることをチェックすることで実現できます
* Compose のテストに関する情報は、[Codelab](https://developer.android.com/codelabs/jetpack-compose-testing ) や[ドキュメント](https://developer.android.com/jetpack/compose/testing?hl=ja), [YouTube](https://www.youtube.com/watch?v=kdwofTaEHrs) に分かりやすくまとまっているので一度チェックしてみることをおすすめします！
Rubyではシンボルと文字列ならシンボルの方が早い

## 概要
Rubyで、大量の文字列とシンボルを比較する際にはシンボルの方が早い。

## シンボルの特徴
####Ruby内部で文字列でなく整数として扱われるので、早い。
比較検索の際に、有利なのでハッシュのキー、メソッドへの引数に使える。

####イミュータブルなオブジェクトである。
破壊的変更を意図したくない場合に使える。

## 計算
```ruby
require 'benchmark'

Benchmark.bm 10 do |r|

  fruits = ['apple','orange','lemon']

  r.report 'string' do
    target = 'orange'
    fruits.each {|fruit| fruit == target}
  end

  r.report 'symbol' do
    target = :orange
    fruits.each {|fruit| fruit == target}
  end
end
```

##結果
```linux
                 user     system      total        real
string       0.000014   0.000014   0.000028 (  0.000012)
symbol       0.000006   0.000001   0.000007 (  0.000006)
```

参考
[Rubyの文字列とシンボルの違いをキッチリ説明できる人になりたい](https://qiita.com/Kta-M/items/53a13ef60e14fcb41193)
[Rubyのシンボルは文字列の皮を被った整数だ！
](https://melborne.github.io/2008/08/02/Ruby/)