OmniAICreator/Qiita-1.07M huggingface dataset:
ACDLを提唱します。

# 概要

クラウドは、嫌いなので、ACDLを提唱します。

# ACDLとは

アプリは、クラウド、大切なデータは、ローカル。
クラウドに、データは渡さない。
「その船を漕いでゆけ
　おまえの手で漕いでゆけ
　おまえが消えて喜ぶ者に
　おまえのオールをまかせるな」

# クラウドの危険性

基本サービスは無料、一部特別な機能や保存領域を増やすために課金が必要など、利便性が高く、無料で業務に役立つアプリはたくさんあります。
もちろん、そのどれもが通信とデータの暗号化、セキュリティ性の確保などが前提となっており、なおかつ信頼のおける企業や組織としての地位を確立していることから、
安心・安全だと信じてしまっても仕方ないと言えます。
しかし、何らかのデータを外部に預けるということは、リスクが発生するということでもあります。
外部アプリやクラウドサービスに依存するということは、リスクを増やすことと同義と留意しておく必要があります。
無料で利便性の高いアプリの中には、最初から利用規約でデータの取扱いについて明記しているものがほとんどです。
もちろん、有名かつ大手のアプリであれば、ユーザー側が一方的に不利益になったり、預けたデータを勝手に使われたりする規約は「ほぼ」ないと言えますが、
知らず知らずのうちに自らにリスクとなる規約に同意していることが絶対にないとは断言できないのも事実です。
また、無料で使えるアプリの中には、運営者の故意の場合を除けば、アプリを利用したことによる被害に責任を持たないと明記している場合もあります。
言い換えれば、無料でアプリを使っていて、情報の保存をしてそれらが情報漏洩したとしても、責任は取らないということです。
もちろん、法律的な視点から見れば絶対に責任を取らなくて良いということはありませんが、そもそも無料で使っていて、責任も取れというのは虫がよすぎるというのも事実です。
外部アプリを使うことで、内部不正につながる可能性も考えられます。
第一に外部アプリの運営、もしくは運営の下請けの権限を持つ担当者による内部不正、
第二に自社従業員による外部アプリを利用した内部不正です。
特にクラウドサービスにおいては、アカウントさえあればブラウザや別のデバイスからもログイン可能なものもあり、
社内や組織内のネットワークの監視やPC操作ログの取得がない場合、もしくはWi-Fiのログインにデバイス制限がない場合など、
内部不正を行われても検知できない可能性が高くなります。
何となく便利だから、みんな使っているからと無料の外部アプリを使うことで起こるリスクであり、セキュリティに配慮しているとは言えない状況とも言えます。

それでも、貴方は、クラウドにデータを預けますか。

以上。
Flutter XCode12+flutter_soundのエラーを解消

こんにちは。Flutter赤ん坊です。

flutter_soundというパッケージがあるのですが、私の環境では動かせませんでした。周りを実装しながら時々flutter_soundを有効化するために奮闘していたのですが、先程ついに出来ましたので、その方法をご紹介します。

## 環境

XCode12.5.1

Flutter 2.5.0 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 4cc385b4b8 (11 days ago) • 2021-09-07 23:01:49 -0700
Engine • revision f0826da7ef
Tools • Dart 2.14.0




## 再現

### サンプルプログラムを実行

まずはコマンドラインから新規プロジェクトを作成します。

```bash
flutter create test
```

これでtestディレクトリが作られました。該当ディレクトリに移動します。

```bash
cd test
```

ここはもうプロジェクト内です。例の数字が増えていくサンプルプログラムが入っています。まずiOSシミュレータ(iPhone)を起動しておいてから、次のようにサンプルプログラムを起動します。

```bash
flutter run --device-id iphone
```

プログラムが正常に起動したことと思います。プロンプト内で半角の「q」を押すことで終了できます。なお環境によっては起動しないかも知れませんが、そこまでは私にも分かりませんので、ご了承ください。

![スクリーンショット 2021-09-19 10.49.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2001849/c03d4489-4339-839f-dd36-f54c6f5382e3.png)

### 問題のflutter_soundをインストール

ここでflutter_soundパッケージをインストールします。

```bash
flutter pub add flutter_sound
```

もう一度プログラムを起動します。

```bash
flutter run --device-id iphone
```

すると、以下のようなエラーが出ました。

```dart
Error output from CocoaPods:
↳

    [!] Automatically assigning platform `iOS` with version `9.0` on target
    `Runner` because no platform was specified. Please specify a platform for
    this target in your Podfile. See
    `https://guides.cocoapods.org/syntax/podfile.html#platform`.
```

iOSを特定しろと言うことのようです。

## 対処

### iOSのバージョンを指定

まずは指示通り、iOSのバージョンを指定します。test/ios/podfileを開くと、次のようになっています。

```
# Uncomment this line to define a global platform for your project
# platform :ios, '9.0'
```

二行目をコメントアウトし、バージョンを9から10に上げます。ちなみに9だと別のエラーが出てしまいます。

```
# Uncomment this line to define a global platform for your project
platform :ios, '10.0'
```

もう一度コンパイルしてみます。

```bash
flutter run --device-id iphone
```

すると、以下のエラーが出ました。

```
building for iOS Simulator, but linking in object file built for iOS,
file '/Users/user/test/ios/Pods/mobile-ffmpeg-audio/lame.framework/lame'
for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see
invocation)
```

arm64です。

### arm64を除外する

arm64は実機のCPUですが、シミュレータでは使われていません。ですので、これを使用しないように設定します。XCode11以前はこのエラーは無く、12から対応が必要になったようです。

まずXCodeで、test/ios/Runner.xcworkspaceを開きます。そこで以下のように、Excluded Architecturesにarm64を追加していきます。

![スクリーンショット 2021-09-19 11.25.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2001849/82ce6e1e-cc95-1719-5c21-b752f2c0311a.png)

赤矢印を入れ忘れたのですが、画面左端、RunnerとPodsに分かれているうち、Runnerの方です。上記はPROJECTに対する設定ですが、そのほかにTARGETSにも同様にarm64を追記します。すでに値が入っている場合は、 スペース区切りでOKと思われます。なおTARGETSの方はDebug, Profile, Releaseと分かれていますので、お好みで入れてください。

PROJECTとTARGETSの両方にarm64を追記できたら、完了です。改めてサンプルプログラムを起動すれば、きちんと動作するかと思います。

## 終わりに

いかがでしたでしょうか。この問題で他のこともしながら色々試しつつダラダラ３日間くらいかかりました。慣れてないもので致し方ないかも知れませんが、同じ苦労をしないよう、共有させていただきます。
Salesforceの変更セットを拡張機能を使って爆速で編集する

ステージング環境(Sandbox)で構築やテストをして、いざ本番環境へ資源を移行するぞ！となったときに避けては通れないのが「変更セット」を使った移行作業です。
エンジニアとしては設計も古く、使いづらいストレスマッハなこの機能を使いたくはないのですが、そうも言ってられないのでできるだけ使いやすくしてくれる便利ツールを探してみました。

#Salesforce Change Set Helper
https://chrome.google.com/webstore/detail/salesforce-change-set-hel/gdjfanbphogooppaefebaaoohdcigpoi
変更セットの条件検索やソートができてすごい便利
Lightning対応だけど自分の環境だと不安定（別の多機能な拡張機能（ORGanizer）と競合してるみたいなので、そういうものを入れていなければこれが一番いいかも）

#Salesforce Change Set Turbo
https://chrome.google.com/webstore/detail/salesforce-change-set-tur/dlcjllapchpeedkecmhfnpfenpbglioo
・検索機能あり
・追加した項目の一括削除機能あり←これすごい嬉しい
・編集画面で「View Mode」に切り替えて「コンポーネントの種類」をAllにすると追加したものを1ページで見れる
・ClassicのみでLightning非対応←シークレットモードだとどのみちClassicしか使えないので、そっちで開けば特に支障ないかも
・ORGanizer入れてても使える
####使い方
①Classicで編集したい変更セットを開き、変更セットコンポーネントの「追加」ボタンをクリック
（シークレットモードの場合はLightningの変更セットで「このページを Salesforce Classic で開くには、こちらをクリックしてください。」をクリックして直接Classicで変更セットを開く事もできる）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2003505/d0da6888-1b95-0ee0-023a-0c083f2b79ca.png)
②Edit Modeでコンポーネントを追加でき、最終変更日や最終更新者などでの絞り込み、昇順・降順のソートが可能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2003505/f82e04b8-2b88-efb7-08d7-e247da1d1566.png)
③移行するコンポーネントを選択し「Add to Change Set」をクリックするとEdit Modeのまま追加される
④View Modeを選択すると追加したものを一覧で見ることが可能で、こちらでも絞り込み、昇順・降順のソートが行える。変更セットから削除したいコンポーネントを選択し「Remove from Change Set」をクリックすると選択したものを一括で削除できる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2003505/00b6bb29-ba93-b17b-5b52-542d67818ddf.png)
また、コンポーネントの種類を「All」とすることで追加したすべてのコンポーネントを表示することができる。もちろんここでも一括削除やソートが可能だ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2003505/e2c1d48f-d489-ae90-61a8-73d729c885d0.png)
⑤作業が終わったらキャンセルをクリックして変更セットコンポーネントの編集ページから抜ける

#感想
この拡張機能を使うことで１００以上あるカスタム項目などを簡単に追加でき、間違って追加してしまったものや不要になったものを１つずつ探し出してちまちま消さなくてもソートして一括で削除できるようになるため、かなり楽に変更セットを編集することができるようになりました。

変更セットの不便さを軽減されたい方はぜひ試してみてください。
物流の非効率：「貿易DX」について考えてみる（ブロックチェーン）

<h2>初めに</h2>
こういった記事を書いて良いものなのか若干悩みましたが、
なんだか面白い記事を見つけたので、まとめていきたいと思います。

<h2>今回勉強した記事</h2>

https://www.sbbit.jp/article/cont1/51881

https://japan.zdnet.com/article/35146653/

https://gemba-pi.jp/post-188968


<h2>「貿易実務」とは</h2>

ここでの「貿易」は輸出・輸入のアレコレを想定しています。

輸出だったら、
船会社にブッキング入れて→「輸出申告」して→コンテナ運ぶ手配して→港にIN　みたいな。
この辺りは、乙仲・フォワーダー・海貨と呼ばれる人たちがメーカーの代わりに頑張ります。
（私はこの乙仲と呼ばれるところで働いていました）

輸出入の書類チェックしたり、法律に引っかかってるか確認したり、
関税額計算したり〜とやることはいっぱいです。


<h2>輸出入１回にEUは２時間、日本は７２時間かかってるらしい</h2>
うわ〜EUはさすがだな〜と思う反面。
「でもEUからの輸入書類って間違ってること多いし！！
それを指摘して直させてるの日本人で！！
日本人の仕事増やしてるのあなたたちですよね！？」と若干の苛立ち。
オランダからの輸入書類のチェックは２度手間、３度手間当たり前だったのでイラ・・・。

そういう話じゃないのか・・・・？
そんなことは置いて置いて、、

<h3>効率の悪さはどこからくるのか</h3>

物流は、荷主、港、運送会社、通関業者と色々な会社のリレーみたいな感じで成立していきますが、
それぞれが個別の紙文書、PDFを受け渡ししてるのが原因の一つです。

:boy:荷主からPDFで書類もらう
↓
:boy_tone3:乙仲（私）が社内システムでそれ見てデータ入力し、PDFにして渡す
↓
:girl:違うところ（船会社等）がPDFで受け取り、またデータを生成する

とまあ恐ろしく非効率。

<h6>そういうの効率悪いからマルっとみんなでデジタル化しよう！</h6>というのが流れのよう。

<h2>ブロックチェーンとは</h2>
それを解決するのに「ブロックチェーン」というものがあるそうです。
情報を鎖のように連結して保管し、
オープンなデータベースとして複数のユーザーに共有できる仕組みです。

https://gemba-pi.jp/post-188968

<h2>終わりに</h2>
ブロックチェーンについてはなんとなく理解できましたが、
そもそもの考え方等、深く調べていきたいと思います。
ASP.NETのWeb Live Preview(Preview)

# VisualStudioのWebLivePreviewという新機能。

従来VisaulStudioのデザインビューは使い勝手が悪く
最新のUIを反映する仕様にはなっていないため、
ブラウザをデザインビューとして活用するという機能。

現在のところは、ASP.NET Frameworkを対象にしている、とのこと。


ASP.NETブログ
[Introducing “Web Live Preview”](https://devblogs.microsoft.com/aspnet/introducing-web-live-preview/?utm_source=pocket_mylist)

Visual Studio MarketPlace
[Web Live Preview (Preview)](https://marketplace.visualstudio.com/items?itemName=WebToolsTeam.WebLivePreview&utm_source=pocket_mylist)
拡張関数 apply, run, also, let の違い

## それぞれの違いが一目で分かる画像

![スクリーンショット 2021-09-19 10.30.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59884/42216248-1fda-46c5-5e31-894dba0c57aa.png)

## それぞれの違い

* `apply` と `run` は `this` がスコープになります
* `also` と `let` は `it` がスコープになります
* `apply` と `also` は戻り値がスコープになります
* `run` と `let` は戻り値がブロックの評価値になります

## 使い分け方

* 私は `apply` と `let` だけを使います。拡張関数の `run` と `also` は使わないです
* `println` 関数で変数の内容を表示するときは `let` を使って `scope.let(::println)` と書きます
* `scope` が `null` でないときに何らかの計算を行いたい場合は `let` を使います。`val result = num?.let { (num + 1) * 2 }` のように書きます
* オブジェクトのプロパティを設定したい場合は `apply` を使います。ひとつのプロパティだけを設定する場合でも十分有用です。次のように書きます

```kotlin
val hoge = Hoge().apply {
    foo = 1
}
```

## その他

* 拡張関数でないほうの `run` は、変数のスコープを限定したいときによく使います。次のように使います

```kotlin
val sum = run {
    var sum = 0
    for (i in 1..100) {
        sum += i
    }
    sum
}
```

## 参考

[Scope functions | Kotlin](https://kotlinlang.org/docs/scope-functions.html)
Jenkins+Kubernetesで動的に並列ジョブを定義したい場合


```yaml:jenkinspipeline.yaml
def labelname = "sample"

pipeline {
  agent {
    kubernetes {
      label labelname
      yaml '''
apiVersion: v1
kind: Pod
metadata:
  labels:
    sample: sample
spec:
  containers:
  - name: sample
    image: sample
    command:
    - cat
    tty: true
    resources:
      limits:
        memory: "768Mi"
        cpu: "1000m"
      requests:
        memory: "512Mi"
        cpu: "500m"
'''
    }
  }
  stages {
    stage('sample-stage') {
      steps {
        container('sample'){ 
          script {
            def sitelist = [1,2,3]
            
            tasks = [:]
            for (name in sitelist) {
                def siteName = name
                
                tasks[siteName] = {
                    container('sample'){ 
                        sh """
                            echo Hello
                        """
                    }
                }
            }
            parallel tasks
          }        
        }
      }
    }
  }
  post {
    always {
      cleanWs()
    }
  }   
}


```
STM32 チャタリング処理 その1

Lチカに続いて，味わいのある（と勝手に思っている）押しボタンの処理。チャタリング処理とか，Debounceとか呼ばれている。

Arduino では，Button2 というライブラリーを愛用させてもらっている。

https://github.com/LennartHennigs/Button2

ボタンごとに， ```SINGLE_CLICK``` ```DOUBLE_CLICK``` ```TRIPLE_CLICK``` ```LONG_CLICK``` を判別できる優れもの。

C++のクラスを使っていて，すごく使いやすいんだけど，残念ながらそれをSTM32環境に移植するだけの腕がない...

ということで，プログラミング初心者の勉強として，少しずつ作ってみることにした。目標は，「ボタンごとにダブルクリックまでを判別する」だけど，今回は

- ボタンは1個だけ。場所限定
- シングルクリックを判定
- STM32 HALライブラリーを使うこと前提。

という割り切り仕様にしてみる。

# 出来上がり

定義部分

```cpp:
enum ButtonStateValue
{
  INIT,
  PRESSED,
  PRESSING,
  RELEASED,
  CLICKED
} ButtonState = INIT;

#define ButtonTime 10 // in msec
#define ButtonRead HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) // define Button place: Pull upped, 1 is OFF, 0 is ON

int Button_Loop(void)
{

  int prev_time;

  if (ButtonRead) // 1 is OFF, 0 is ON
  {
    // release?
    switch (ButtonState)
    {
    case PRESSING:
      ButtonState = RELEASED;
      prev_time = HAL_GetTick();
      break;
    case RELEASED:
      if ((HAL_GetTick() - prev_time) > ButtonTime)
      {
        ButtonState = CLICKED;
      }
      break;
    default:
      break;
    }
  }
  else
  {
    // push?
    switch (ButtonState)
    {
    case INIT:
      ButtonState = PRESSED;
      prev_time = HAL_GetTick();
      break;
    case PRESSED:
      if ((HAL_GetTick() - prev_time) > ButtonTime)
      {
        ButtonState = PRESSING;
      }
      break;
    case CLICKED:
      ButtonState = INIT;
      break;
    default:
      break;
    }
  }
  return ButtonState;
}
```

mainループ部分 ボタンを押したらPB3=LEDの点灯・消灯を切り替える。

```cpp:
  while (1)
  {
    if (Button_Loop() == CLICKED)
    {
      ButtonState = INIT;
      HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
    }
  }
```

# 使い方

- PB0限定。PullUp等，ポート設定は事前に行っておく。ボタンを押す = L となることが前提。
- ```Button_Loop()``` を適度にコールして読む。 ```== CLICKED``` なら「押したあと離された」ことを表す。

- ボタン判定したら ```ButtonState = INIT;``` で状態をクリアする。これは **取りこぼし** を防ぐため。

次回があれば... 複数ボタン，ダブルクリックに挑戦します。
必ず「成果」が表れる方法

#前書き

　致知出版社[『1日1話、読めば心が熱くなる365人の仕事の教科書』][1]の一節の感想文である。
[1]:https://www.amazon.co.jp/1%E6%97%A51%E8%A9%B1%E3%80%81%E8%AA%AD%E3%82%81%E3%81%B0%E5%BF%83%E3%81%8C%E7%86%B1%E3%81%8F%E3%81%AA%E3%82%8B365%E4%BA%BA%E3%81%AE%E4%BB%95%E4%BA%8B%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E8%97%A4%E5%B0%BE%E7%A7%80%E6%98%AD/dp/4800912474

　私は今年の4月から、毎日この本を1ページづつ読み、その感想文を会社のSlackの公開チャンネルで投稿している。
　世の中の先人たちが語るコトバはとても参考になる。何かしらの成功者たちは、それぞれ自らの経験に基づく何かしらの「信念」がある。
　それを知り、教訓とし、自分の糧とするためだ。

　今日は3連休の中日だが、休日も毎日書くように自分に課している。
　【1月1日】から初めて、今日は【5月27日】。149日目だ。もう当たり前の朝のルーチンとなっている。
　
　Qiitaにも書こうと考えたのは、社内だけに共有するだけより皆の役に立つとおもったからである。
　Slackで書いた記事をコピペして、社内向けの言葉を一般用に編集するくらいなので負荷もかからないから、機会があればシリーズ化しようと思う。


#本題　【5月27日】仕事は自分で探し出すもの 桜井正光 リコー会長

この記事の出典は2012年、雑誌「致知」の3月号インタビュー記事とのこと。
桜井正光。元リコーの技術者・経営者。1996年に上席役員を8人抜いて社長に抜擢されたという。
今では当たり前に叫ばれている「環境経営」を打ち出し、リコーの業績を押し上げた。
1942年生まれ。現在、御年79歳。


桜井さんが語るのは、リコーに入社して最初に配属された部署の話。
>『最初に配属されたのは原価管理課という部門だった。』
『しかし、不況の真っ只中、会社も無配の状態である。上司に言われたのは「おまえたちにやる仕事はない」ということだった。』

ほう（笑）

>『最初こそ仕事がなくて楽だと思ったが、三か月も経つと何もする仕事がないというのはこんなにつらいものなのかと身に染みて感じた。
　他の部署の人が仕事をしていることへの焦り。また、もっと本質的な部分で、自分は会社や社会に何も貢献できていないという「役割」のなさへの焦りがあった。』

いや、私なら1週間も持たないだろうけどな。

>『後々振り返って、社会人のスタート段階で「仕事があるありがたさ」「する仕事のないつらさ」を体感できたのは幸せだったと思う。』

リコーもリスキーな教育指導をしたものだ。実際桜井さんの上司が当時、どのように、どういう意図をもって部下を指導したのかはわからないが、
「お前に~~くわせるタンメンは~~やらせる仕事はない」って言っちゃって、桜井さんが辞めなくて良かったね。後に多大な功績を遺すんだから。

>『さて、そこで私は「こうなったら、自分で仕事を探そう」と決意した。』

桜井さんは、開発、設計、生産部門の人たちのもとへヒヤリングに回ったという。例えば複写機においても、いくつもの製品があるが、
それぞれの製品間で部品が類似しながらも微妙に違うものを使っていることに気がついたという。

>『「本当に違う必要があるのか」「コストアップの原因になってはいないか」・・・。』
『私は五か月間、倉庫にこもって部品図面を種類ごとに分類。材質や形状、原価などを加えたリストを作成し、設計部所に渡した。
　その後、改善した方がいい部分を指摘してもらい、どんどんブラッシュアップしていった。
　すると、現場は「部品を探す手間が省けた」と重宝してくれる一方で、同じような形状であれば一番安い部品を選ぶようになり、
　大きなコストダウンに繋がったのである。』

桜井さんはこの経験からタイトルのコトバを実感し、今の若い人たちに伝えたいという。

>『自分の仕事のアウトプットを利用するお客様は誰なのかを考え、その人たちの役に立つことを探して実行すれば、必ず成果となって表れる。』
　すなわち、それは自主自立、自己責任の全うということであり、いま日本全体で最ももとめられていることではないだろうか。』

うむ。的を得ている。わかりやすい。
皆さんの仕事のアウトプットを利用する「お客様」は誰なのか、把握されてますか？



#結論　必ず「成果」が表れる方法とは

　**自分の仕事のアウトプットを利用するお客様は誰なのか？**
　**その人たちにとって役に立ってもらえることは何なのか？**
　**それを探して実行すること。**

一つの定理（＝明文化）を教えてもらった。

（参考）
桜井正光。　-Wikipedia
https://ja.wikipedia.org/wiki/%E6%A1%9C%E4%BA%95%E6%AD%A3%E5%85%89
Laravelのbladeのbuttonタグで名前付きルートを使う

普通にHTMLで<button>タグ使って画面遷移するURL部分にroute関数を埋め込むだけです。

なんでわざわざそんな事を記事にしたかというと、vscodeでこのコードを書くと思いっきり警告出て、あれ間違えたかな？って混乱したからです。

使用しているvscodeのライブラリによっては何も警告でないかもしれません。
bladeとvscodeの相性なので気持ち悪いですが無視してこのまま使って大丈夫そうです。

selectタグでold関数とか使おうとしても警告出たりしますがそういうものと諦めるしかなさそうですね。

            
```sample.blade.php
<button type="button" onclick="location.href='{{ route('admin.template_item.index') }}' ">様式レイアウト作成へ</button>
```
Category Encodersでテストデータセットにも学習用データセットと同じ数字をマッピングする

## 前提

- いくら調べても出てこなかったので書き下すことにしました。
    - もしかしたら当たり前過ぎて誰も書いてないのかもですが、誰かの役に立てればと。
- lightgbmを使うので、OrdinalEncoderを想定して書きます。
    - 他のエンコーダは試してないですが、同じ方法で解決できるのではないかと思います。

## 解決したいこと

「モデルの学習をするランタイム」と「実際にモデルから予測するランタイム」が別れているときに、category_encodersが別々のアルゴリズムでカテゴリ特徴量を変換してしまう現象を解決したい。

OrdinalEncoderの`fit_transform`は与えられたデータセットから各カテゴリに1から順番に数字を採番する仕組みのようなので、学習に使うデータセットと予測に使うデータセットで**カテゴリ数が一致していて出現する順番も等しくないと**、別の数字が振られてしまう。
実際には予測に使うデータセットの方がカテゴリが少ないことが多いため、以下のようなやり方だと学習用と予測用のデータセットで異なる値に変換されるはず。

```learn.py
# a~iのカテゴリを持つ特徴量を変換する
df1 = pd.DataFrame({'label': ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
                   'value': ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']})

list_cols = ['value']
ce_oe = ce.OrdinalEncoder(cols=list_cols,handle_unknown='impute')
df = ce_oe.fit_transform(df1)

print(df)

"""
a~iに1から順に数字が振られる

    A   B
0   a   1
1   b   2
2   c   3
3   d   4
4   e   5
5   f   6
6   g   7
7   h   8
8   i   9
"""

```

```pred.py
# aとiを変換する
df2 = pd.DataFrame({'label': ['a', 'i'],
                   'value': ['a', 'i']})

list_cols = ['value']
ce_oe = ce.OrdinalEncoder(cols=list_cols,handle_unknown='impute')
df = ce_oe.fit_transform(df2)

print(df)

"""
a->1, i->9を期待するが、実際には上から順番に採番されてしまう

    A   B
0   a   1
1   i   2
"""
```

## 解決方法
`fit_transform`ではなく`fit`と`transform`を別々に使う。

`fit`はデータセットを受け取り、エンコーダを返す関数。
ここで返されたエンコーダは**カテゴリと数字のマッピングを学習済なので**、このインスタンスを予測用データセットにも使い回せば学習用データセットと同じ数字を割り振ることができる。

```learn.py
# df1とdf2は同上のため定義を省略

fitted = ce.OrdinalEncoder(cols=list_cols,handle_unknown='impute').fit(df1)

# fit済エンコーダを使い回すのがポイント
df1_trans = fitted.transform(df1)
df2_trans = fitted.transform(df2)

print(df1_trans)
print("==========")
print(df2_trans)

"""
    A   B
0   a   1
1   b   2
2   c   3
3   d   4
4   e   5
5   f   6
6   g   7
7   h   8
8   i   9
==========
    A   B
0   c   3
1   i   9
"""
```

あとはインスタンスを使い回せない別のランタイムでどうするかですが、お察しの通り`pickle`を使います。

```learn.py
ce_oe = ce.OrdinalEncoder(cols=list_cols,handle_unknown='impute').fit(df1)
with open('model.pickle', mode='wb') as fp:
	pickle.dump(model, fp)
	pickle.dump(ce_oe, fp)
```

```pred.py
with open('model.pickle', mode='rb') as fp:
	model = pickle.load(fp)
	ce_oe = pickle.load(fp)

df = ce_oe.transform(dataset)
```

## 参考
- [Ordinal - Category Encoders documentation](https://contrib.scikit-learn.org/category_encoders/ordinal.html)
[超入門]VSCodeで画像が表示されない時の対処法

Googleで「VSCode 画像　表示されない」などと検索して、”パスがちゃんと指定されてない”とか"誤字脱字がある"などといったことが書かれていたから、それらを全て試したけど、それでも画像が表示されなかったって場合は、次のことを試してみてください。

まず、拡張機能を「HTML　Preview」にするのではなく、「Live Server」に変えてみてください。

そして、HTMLファイル内で右クリックすると、下の方に「Open With Live Server」という記述があると思うので、それをクリックしてください。

するとwebでプレビューが開くので、それを見ると表示されてるのではないかと思います。(表示されなかったらごめんなさい)
UnknownAttributeErrorが出た時の対処方法

UnknownAttributeErrorはカラムが追加されていない時のエラー
<p>テーブル確認</p>
<p>schema確認</p>
<p>そもそものところ確認して問題なし</p>

```
rails db:migrate:status
```

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

```
rails db:migrate
```
<p>エラーが解消された</p>
初心者が1から始めるJava開発-Vol.6- Javaの可視性

Javaには可視性という概念があります。（ほかの言語にもありますが、使いこなせないのでちゃんと説明することはできない）
可視性を理解せずに実装すると、危険なので必ず理解しましょう。
といいつつ、この記事ではメソッド形式での紹介にとどめます。

※毎度のことながら、こう書いた方がわかりやすい、そこちょっと認識違うとかあればぜひコメントなどで教えてください。

#可視性とは？

可視性とは「どこまで見えるか」「どこまで使えるか」のようなイメージです。
Vol.5まで見ている前提でいうと、可視性によって「どのクラスで使えるか」という観点になります。

#可視性の種類

Javaにはクラス、メソッド、などに用いるか姿勢の種類が大きく4つあります。

- public
- protected
- package private
- private

上から順に広範囲で利用することができます。

※下記ページのAccess Levelsの表を参照
https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html


## public

同一プロジェクト内からならどこからでも利用が可能。
publicがついたメソッドは、属するクラスのインスタンスを生成すれば、利用可能です。

例)

```java
package jp.co.sorpy.main;

public class MainController{

    public void outputLog(){
        System.out.println("このメソッドはpublic")
    }
}
```
前述のように記述すると

```java
package jp.co.sorpy.main.controller.hogehoge;

public class SubController{

    public void hoge(){
        MainController mainController = new MainController();
        mainController.outputLog();
    }
}
```

のように記述すればどこからでも呼び出しは可能。


## protected

または継承（extends）したクラス内で利用可能、publicより可視性が狭くなる（低くなる）。（継承はこのシリーズでは紹介していないのでいずれ。。。）
また同一package内でも呼び出し可能。
後述するpackage privateと同等の使い方が可能。


例）

```java
package jp.co.sorpy.main;

public class MainController{

    protected void outputLog(){
        System.out.println("このメソッドはpublic")
    }
}
```
前述のように記述すると

```java
package jp.co.sorpy.main.controller;

public class SubController extends MainController{

    public void hoge(){
        outputLog();
    }
}
```
このように**extends MainController**のついたクラス内で、
MainControllerをnewしていなくても呼び出すことができます。
（正確にはextendsをつけている場合は子が呼ばれたときに親子同時にnewされる）

なおpublicもこの利用方法は可能ですが、protectedにすることで、
publicのようにどこでも使えては困るが、
継承したクラスでは使えていい場合にこのようにprotectedを利用します。

##package private

同一packageであればどこからでも利用が可能。
同一packageとは、Javaのクラスに必ず記載のある1行目の「**package jp.co.hoge.controller.fuga;**」の記述部分である。
package privateはほかと違い、「何もつけない」（例参照）。

例）

```java
package jp.co.sorpy.main;

public class MainController{

    void outputLog(){
        System.out.println("このメソッドはpublic")
    }
}
```
前述のように記述すると

```java
package jp.co.sorpy.main;

public class SubController{

    public void hoge(){
        MainController mainController = new MainController();
        mainController.outputLog();
    }
}
```
このようにpackageの部分が同じであれば呼び出すことが可能です。


##private

同一クラス内でのみ利用可能である。
もっとも可視性の狭い（低い）のがこのprivate。

例）

```java
package jp.co.sorpy.main;

public class MainController{

    private void outputLog(){
        System.out.println("このメソッドはpublic")
    }

    public void hoge(){
        outputLog();
    }
}
```
前述のとおりoutputLog()メソッドはMainControllerからしか呼べません。
前段の3種類の方法で利用しようとするとコンパイルエラーになります。

#可視性を検討する際に留意すべきこと

プログラムにおいては、「できることを極力減らす」ことが読みやすく、
メンテナビリティの高いコードになると、筆者は考えています。
※機能に関してはできることが多いほうがいい場合もある。

そのため、原理原則としては、privateで実装し、
必要に応じ可視性を上げていくというのが安心、安全なコードになると考えています。

ただし、可視性をどうするかについては一言で説明できないし、
時と場合によって検討の余地もあります。
各クラスがAPIであると解釈すれば、外部とのやり取りのために必ずpublicメソッドが必要になります。

新人、若手の皆さんは実際にコードレビューで指摘を受けたり、
イケてるコードを参照することをお勧めします。
やはりこの辺りは実践して身に着けていただきたいところ。
これを知っているだけでは有効な状況を理解するのは難しい。
[AWS基礎⑤]サブネットマスク表記について　(IPアドレスの範囲の表記法）

<h2>初めに</h2>
以前の記事で、IPアドレス　CIDRについて学習しましたが、
同様にIPアドレスの範囲を記載する方法としてサブネットマスク表記があります。

サブネットマスク表記が何なのかようやく少しわかったのでまとめていきます。

前回の記事

https://qiita.com/ki_87/items/1b2c9007ad4a7f7c8c18

<h2>CIDR表記と目的は同じ:frowning2:</h2>
私はCIDRと混乱し、意味がわからなかったのですが、
目的（どこまでがネットワーク部が定義する）は同じなんですね！

「どちらもIPアドレスの範囲の表記方法の1つ」ということが理解できました。

<h2>サブネットマスク表記とは</h2>

IPアドレス＝（例）192.168.128.0 の後ろに、
ネットワーク部を表すビットの部分を全部「１」に！
ホスト部を全部「０」にしたものを表記し、範囲を定義する！

<h5>　192.168.128.0/255.255.255/0　となる:fist:</h5>


![スクリーンショット 2021-09-19 10.11.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/42c3f735-3e25-c2ca-628a-36f741e3bb95.png)

<h4>補足：１０進数→２進数</h4>
![スクリーンショット 2021-09-19 10.12.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/f1799e30-3f14-022d-96c9-f0ec18fc2857.png)

<h4>補足：２進数→１０進数</h4>
![スクリーンショット 2021-09-19 10.12.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/6f0a3084-e87b-c6d2-09ce-ae958fe1cc3f.png)

<h2>終わり</h2>
サブネットマスク表記がようやく理解できてスッキリです。
Cypress を用いたE2Eテスト方法 メモ

* E2Eテストツールの調査をする際にCypressに少し触れたためメモしておく。

## Cypressとは

* JavaScript製のブラウザテストに特化したE2Eテストフレームワーク。



## Cypress インストール

```shell
npm install cypress
```

## Cypress プロジェクト作成

* `cypress`という名称のプロジェクトディレクトリを作成する場合

```
npx cypress open
```



## テストコード

* `test.js`

  * `{project名}/integration`配下に配置する。
  * `cypress.io`でGoogle検索を行い、検索結果の1番上のページにアクセスし、タイトルの値を確認する。

  ```javascript
  describe("Test Suite", function(){
  	it("Test 01", function(){
  		// Googleページへ
  		cy.visit("https://www.google.com/");
  
  		// 検索boxにcypress入力 → エンター入力
  		cy.get('input[type="text"][name="q"]').type("cypress.io").type("{enter}") 
  
          // 最初の検索結果をクリック
          cy.get('#search a').first().click();
      
  		// アサーション ページタイトル確認
  		cy.title().should("include", "JavaScript End to End Testing Framework | cypress.io"); 
  		// その他の操作
  		cy.screenshot(); // スクリーンショット
  		cy.reload(); // ページのリロード
  		cy.log("test log"); // ログ出力
  
  	});
  });
  ```

* `cypress.json`

  *  same origin ではないサイトへ飛ばすための設定

  ```json
  {
    "chromeWebSecurity": false 
  }
  ```

  

## テスト実行

* cypress起動

  ```shell
  npx cypress open
  ```

  ※cypressコンソールが開く

* `Test`タブを選択し、`test.js`を選択

  ※テストが実行される。

## 参考情報

* [Cypress入門～初心者でも簡単にE2Eテストが作れる～](https://future-architect.github.io/articles/20210428a/)
* [Cypress を利用した E2E テスト](https://softwarenote.info/p1454/)
* [docs.cypress.io](https://docs.cypress.io/guides/overview/why-cypress)
[Python]GeoLite2を用いたIPアドレス国判定方法 メモ

* IPアドレスから国判定を行う方法についてメモする。

## 事前準備

* GeoLite2データベースのダウンロード

  * [こちら](https://dev.maxmind.com/geoip/geolite2-free-geolocation-data)でアカウントを作成し、「[GeoLite2 City](https://www.maxmind.com/en/accounts/604902/geoip/downloads)」データをダウンロードする。
  * データを解凍し、「GeoLite2-City.mmdb」を取得する。

* GeoLiteAPIインストール

  ```shell
  pip install geoip2
  ```

  

## コード`main.py`

* HTTP X-Forwarded-ForヘッダーにIPアドレスが付与されるケースを想定し、ヘッダーから取得した値から国コードを返却するAPIを作成する。

  * API構築用フレームワークとして、FastAPIを使用。
  * エラーハンドリング未実施。
  * 複数プロキシ経由時の対応は別途必要となる。

  ```python
  import geoip2.database
  from fastapi import FastAPI, Request
  app = FastAPI()
  
  
  # API
  @app.get("/country_code")
  def search_shop(request: Request):
      ipaddress = request.headers['X-Forwarded-For']
      reader = geoip2.database.Reader('GeoLite2-City.mmdb')
      country_code = reader.city(ipaddress).country.iso_code
      response = {"country": country_code}
      return response
  
  ```

  

## 動作確認

* **API起動**

  ```
  uvicorn main:app --reload
  INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
  INFO:     Started reloader process [18624] using statreload
  INFO:     Started server process [10596]
  INFO:     Waiting for application startup.
  INFO:     Application startup complete.
  ```

* **リクエスト**

  ```http
  GET /country_code HTTP/1.1
  Host: localhost:8000
  Content-Type: application/json
  X-Forwarded-For: xxx.xxx.xxx.xxx
  ```

* **レスポンス**

  ```json
  {
      "country": "JP"
  }
  ```



## 参考情報

* [MaxMind Developer Portal](https://dev.maxmind.com/?lang=en)
* [GeoLite2でサクッとできるIPアドレスの国判定](https://dev.classmethod.jp/articles/geolite2-python/)
VSCode で使う snippets

## はじめに
VSCode に登録している snippets をメモ代わりに書き残しています。
順次アップデートしていきます。

## React(TypeScript)
https://github.com/burkeholland/simple-react-snippets/blob/master/snippets/snippets-ts.json

https://github.com/dsznajder/vscode-es7-javascript-react-snippets/blob/master/snippets/ts-snippets.json

これらを参考にしています。

```json:typescriptreact.json
{
	"React Functional Component": {
		"prefix": "rfc",
		"body": [
			"interface Props {",
			"\t",
			"}",
			"",
			"const ${1:${TM_FILENAME_BASE}}: React.FC<Props> = (props) => {",
			"\treturn (",
			"\t\t<div>",
			"\t\t\t$0",
			"\t\t</div>",
			"\t)",
			"}",
			"",
			"export default ${1:${TM_FILENAME_BASE}}",
			""
		],
		"description": "Functional Component を作成"
	},
	"useState": {
		"prefix": "cus",
		"body": [
			"const [${1}, set${1/(.*)/${1:/capitalize}/}] = useState($2);",
		],
		"description": "useState を定義"
	},
}
```
OpenID Connect Back-Channel Logout 1.0 - draft 06 メモ

* SLOの調査にあたって、Open ID Connect Back-Channel Logout について調べたためメモしておく。


## RP-initiated LogoutとBack-Channel Logout

* RP-initiated Logoutは、RP が、ユーザーエージェントをOPのログアウトエンドポイントにリダイレクトすることで、OPにエンドユーザーからログアウトすることを要求する機能。
* Back-Channel Logoutは、OPからログアウトしたことをログイン中のRPにバックエンド間通信で通知する方法。

## Back-Channel Logoutの流れ

(バックチャネルログアウトをサポートするOPは、ログイン中のRPを追跡し、バックチャネルログアウトURIでどのRPに接続してログアウトさせるかを把握しておく必要がある。）

(OP側でログアウトした後...)

**1.** OPはログアウトトークンをログインしたRPに送信する。

   * ログアウトトークンは`application/x-www-form-urlencoded`形式で `logout_token` パラメータに指定し、POSTメソッドで送信する。

     ```http
     POST /backchannel_logout HTTP/1.1
     Host: rp.example.org
     Content-Type: application/x-www-form-urlencoded
     
     logout_token=eyJhbGci ... .eyJpc3Mi ... .T3BlbklE ..
     ```

   * クレーム


| クレーム | 必須/任意 | 説明                                                         |
| -------- | --------- | ------------------------------------------------------------ |
| iss      | 必須      | トークンの発行者                                             |
| sub      | 任意      | サブジェクトID                                               |
| aud      | 必須      | トークンの発行対象                                           |
| iat      | 必須      | 発行日時                                                     |
| jti      | 必須      | トークンのID                                                 |
| events   | 必須      | JSONオブジェクト。メンバー名：http://schemas.openid.net/event/backchannel-logout。値：{}。 |
| sid      | 任意      | セッションID                                                 |


```json
      {
        "iss": "https://server.example.com",
        "sub": "248289761001",
        "aud": "s6BhdRkqt3",
        "iat": 1471566154,
        "jti": "bWJq",
        "sid": "08a5019c-17e1-4977-8f42-65a12843ea02",
        "events": {
          "http://schemas.openid.net/event/backchannel-logout": {}
          }
       }
```

**2.** RPは受信したログアウトトークンを検証して、ログアウトトークンで指定されたセッションを無効化する。

   * ログアウトトークンの検証に成功した場合はステータスコード `200` 、失敗した場合は `400` を返却する。

## Security Considerations

* DoS攻撃を防ぐためにログアウトトークンの署名検証を行う。
* OPは、キャプチャされたログアウトトークンを再利用されないようにログアウトトークンに短い有効期限を使用することが推奨される。



## 参考

* [OpenID Connect Back-Channel Logout 1.0 - draft 06](https://openid.net/specs/openid-connect-backchannel-1_0.html)
Unity：3Dモードから2Dモードに変更した時2DObjectの作成項目がない

※使用UnityVersion 2020.3.18f1

3Dでプロジェクトを作ったけどやっぱり2Dゲームにしよう！

そうなるとこちらにあるように3Dモードから2Dモードへ切り替えると思います
https://docs.unity3d.com/ja/2018.4/Manual/2DAnd3DModeSettings.html

####ここで問題発生！！

## 問題
Hierarchy右クリックで2DObjectの作成項目がない…
Createできない

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304931/d0549919-a90b-3bb8-5015-8b5b3f04f34d.png)

## 原因
初期インポートされるPackageが足りていないのが原因でした

```
com.unity.2d.animation,
com.unity.2d.pixel-perfect,
com.unity.2d.psdimporter,
com.unity.2d.sprite,
com.unity.2d.spriteshape,
com.unity.2d.tilemap
```

## 解決方法
PackageManagerからインポートしましょう。
Swift で LCS：Longest Common Substring（最長共通部分文字列）


備忘用メモ

## NOTE

- 問題：https://leetcode.com/problems/longest-common-subsequence
- 解法：DP
- 注意：この問題はLongest Common **Substring** の問題で、Longest Common **Subsequence** ではないです。Subsequence の問題は下記で書いてます。

https://qiita.com/snamiki1212/items/5245505139657c39572e

## 解法

Kadane's Algorithm とほぼ同じ考え方になる。

https://qiita.com/snamiki1212/items/4818c12c051fe644ce9c

### 部分問題を定義する

まずは、DPなので部分問題に分解するが下記のように部分問題を定義する。

- **「文字列SのI番目の文字」と「文字列TのJ番目の文字」を含んでいる** 最長共通部分列の長さ

`(1`: **「文字列SのI番目の文字」と「文字列TのJ番目の文字」を含んでいる**、という条件のため、もしも「文字列SのI番目の文字」と「文字列TのJ番目の文字」が異なった場合、その時点で部分列共通ではなくなるため、長さは０になる。


`(2`：もしも「文字列SのI番目の文字」と「文字列TのJ番目の文字」が同じ場合は、１つ前の状態から長さを＋１する

### 最終的な答えを取り出す

`(3`: 最終的な答えはdp全体の中から調べる必要がある。なぜなら、`dp[I][J]`が保持しているのは **「文字列SのI番目の文字」と「文字列TのJ番目の文字」を含んでいる** 最長共通部分列の長さ だから。dpだからといってなにも考えずにdpの末尾の値を取り出しても、それは「**最後の文字を含んだ**最長共通部分列の長さ」になってしまう。

----

これらをもとに理解を優先して愚直に書くとこうなる。

```swift
func findLength(_ nums1: [Int], _ nums2: [Int]) -> Int {
    var dp = [[Int]](repeating: [Int](repeating: 0, count: nums2.count+1), count: nums1.count+1)
    for i in 1..<nums1.count+1 {
        for j in 1..<nums2.count+1 {
            let I = i-1, J = j-1;
            if nums1[I] == nums2[J] {
                dp[i][j] = dp[i-1][j-1] + 1 // (2) 1つ前の状態から長さを+1する
            } else {
                dp[i][j] = 0 // (1) 文字が違うので0になる
            }
            
        }
    }
    
    // (3) dp 全体から一番長い数値を取り出す
    var maxSoFar = 0
    for i in 0..<nums1.count+1 {
        for j in 0..<nums2.count+1 {
            maxSoFar = max(maxSoFar, dp[i][j])
        }
    }
    return maxSoFar
}
```

ただ、冗長な記述ばっかりなのでもっとすっきりさせたい。

## コード

最終的にこうなる。初期値は0なのでわざわざ0を代入する必要はなく、dp全体の中から最大値を取り出すのも緩和をしているループの中で合わせて行う。

```swift
func findLength(_ nums1: [Int], _ nums2: [Int]) -> Int {
    var dp = [[Int]](repeating: [Int](repeating: 0, count: nums2.count+1), count: nums1.count+1)
    var maxSoFar = 0
    for i in 1..<nums1.count+1 {
        for j in 1..<nums2.count+1 {
            let I = i-1, J = j-1;
            if nums1[I] != nums2[J] { continue }
            dp[i][j] = dp[i-1][j-1] + 1
            maxSoFar = max(maxSoFar, dp[i][j])
        }
    }
    return maxSoFar
}
```

### dp テーブル

dpのテーブルはこんな感じになる。

![LeetCode-5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186228/f2579bc5-92e3-73c1-df86-db815ab88019.jpeg)


## 詰まったら

この問題で詰まった人は先にMaximum Substringをやるのがいいです。

Maximum Subarray の問題は1次元配列のDPだったのでより簡単だったが、今回の問題は2次元配列になる。今回の問題が詰まったら、先にMaximum Subarray やるほうがよりわかりやすいステップになると思う。

https://qiita.com/snamiki1212/items/4818c12c051fe644ce9c
Fctory_bot アソシエーション：belongs_toの記述

<h2>comment(コメント)がstaff(ユーザー)、ostomy(投稿)にbelongs_to</h2>
```models/comment.rb
class Comment < ApplicationRecord
  belongs_to :ostomy #投稿
  belongs_to :staff #ユーザー
  validates :comment, {presence: true}
end
```
```models/staff.rb
#ユーザーモデル
class Staff < ApplicationRecord
  has_many :comments
end
```
```models/ostomy.rb
#投稿モデル
class Ostomy < ApplicationRecord
  has_many :comments
```

<h2>associationを用いて記述</h2>
<p>has_manyはassociationの記述不要</p>
```factorys/cooments.rb
FactoryBot.define do
 #医療staffがかくストマ記録
    factory :comment do
      sequence(:comment) { |n| "comment#{n}" }
      
  　　   association :ostomy
     　　association :staff
    end
end
```
```models/comment_spec.rb
require 'rails_helper'

RSpec.describe Comment, type: :model do
  pending "add some examples to (or delete) #{__FILE__}"
  
   before do 
    @ostomy = build(:ostomy) #関係するオブジェクトostomyを作成
    @staff = build(:staff) 　　　#関係するオブジェクトstaffを作成　
    @comment = build(:comment,　staff: @staff, ostomy: @ostomy)　#入れこむ
  end
```
<h2>has_manyは記述不要でわからず記述してしまいエラーになった</h2>
```
rspec ./spec/models/comment_spec.rb  
確認
```
【Python】変数や関数の名前に使えない"予約語"

<img src="https://img.shields.io/badge/MacOS-10.15.7-999999.svg?logo=apple&style=flat-square"> <img src="https://img.shields.io/badge/-Docker-1488C6.svg?logo=docker&style=flat-square"> <img src="https://img.shields.io/badge/Python-3.8.2-3776AB.svg?logo=python&style=flat-square">

# 予約語とは？
予約語というのはプログラム内であらかじめ使われている
言葉のことで、プログラムの中では特別な意味を持つ言葉になります。

# 予約語一覧


```python
# 予約語の一覧を出す
import keyword
print(keyword.kwlist)

#結果
['False', 'None', 'True', 'and', 'as', 'assert', ...

# 縦に並べると
False
None
True
and
as
assert
break
class
continue
def
del
elif
else
except
finally
for
from
global
if
import
in
is
lambda
nonlocal
not
or
pass
raise
return
try
while
with
yield
```

  
これら"予約語"は変数や関数の名前に用いることはできません。

~~宣言を英単語2個以上にすることで 
こういった問題は回避できたりします。~~

```python
# 例
return_pass
from_lambda
```

(9/22追記)
コメントにて下記、ご教示いただきました。
規約上、予約語と同じ名前を使う場合はアンダースコアをひとつだけ入れる
形が正しいようです。

https://pep8-ja.readthedocs.io/ja/latest/#id24

>single_trailing_underscore_: Python のキーワードと衝突するのを避けるために使われる規約です。例を以下に挙げます:

>tkinter.Toplevel(master, class_='ClassName')

勉強になりました、ありがとうございます。
ゲームサーバーに欲しいDiscordBot

作りたいもの
---
・Discordを使ってチーム分けをしたい（みんなでゲームをしてて欲しい時がある）
・誰かがボイスチャットに入室したときに、入室したチャンネルとユーザーをメンションで知らせてくれる


開発環境
---
 OS：Ubuntu20.10
 Python：3.9.5
 Discord.py：1.7.3

やること
---
>
1. メッセージからメンション情報を取得
1. コマンドの入力を受ける
1. メッセージに返信する
1. リアクションを集計
1. チーム分け
1. 結果を送信

1. メッセージからメンション情報を取得
---
メッセージが送信されたときに、Bot に対してメンションが行われたかを確認する
- > メンションに続くコマンドを取得する

メッセージを取得 -> メンション情報を取得
>メンション情報は `message.mentions` で取得することができる

https://discordpy.readthedocs.io/ja/latest/api.html?highlight=on_message#discord.Message.mentions


```
# message.mentions の構造
[<Member id=******** name='*****' discriminator='****' bot=True nick=None guild=<Guild id=******** name='*****' shard_id=None chunked=False member_count=*>>]
```

リストの要素として `<Member ~ >>` が入っている
メンションの数が増えると `[<Member ~ >>, <Member ~ >>]` と要素が増えていく

取得したい情報は `name#discriminator` の形式の文字列

```python
async def on_message(message):
  # ここの name と discriminator は Bot のものを入れる
　my_name = 'name#discriminator'

  mentions = message.mentions
  
  for mention in mentions:
    mention_name = mention.name + '#' + mention.discriminator

    if mention_name == my_name:
      message_in_cmd = message.content
      break
```
`message.content` でメッセージの本文を取得することができる

2021/09/19 09:00 JST 時点ではここまでが完成しています。
---
今後進捗が出たら、更新します。
k-NN(k近傍法)のPythonによる実装

k-NN(k近傍法)について説明し、Pythonでの分類タスクにおける簡単なモデル構築を紹介します。

## k-NN（k近傍法）とは
あるグループAとグループBがあるとして、その人たちの属性がわかっているとき、どちらのグループに属するか分からない新しい人が来たケースを考えます。
![IMG_411A340FD957-1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1859982/350fc4ed-8742-6d6a-c276-08b278de1ac7.jpeg)

ここでその人がAとBのどちらのグループに属するか考えるとき、その人と属性が近いk人を選び、その人たちがグループAに多いのかそれともグループBに多いのかを調べて、多い方を新しい人のグループにするのがk-NNによる分類方法です。k-NNの`k`は決定に利用する人数に相当します。k-NNは怠惰学習やとも言われ、訓練データをそのまま覚えて学習させます。

![IMG_AB3217C5CDCC-1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1859982/3f859b7e-ab77-dc73-c4a4-cf1026f75301.jpeg)

## k-NNのモデル構築
k-NNを使ってモデル構築をしてみます。`sklearn.neibors`モジュールの`KNeighborsClassifier`クラスを使用します。データ例としては乳がんに関するデータセットを`load_breast_cancer`関数で取得し使用します。

ここでは`k`を1から10まで変化させ、訓練データとテストデータの正解率の変化を見ていまきす。`k`が小さい時は正解率に差がありますが、6～8あたりで訓練とテストの正解率が近くなります。それ以上増やしてもモデル精度に大きな変化は見られません。精度に改善が見られない場合、あまりkを大きくする必要はないので、本ケースにおいては6～8程度に設定しておくのが良いと考えられます。

```python
# インポート
import matplotlib.pyplot as plt
from sklearn.datasets import load_breast_cancer
from sklearn.neighbors import  KNeighborsClassifier
from sklearn.model_selection import train_test_split

# データセットの読み込み
cancer = load_breast_cancer()

# 訓練データとテストデータに分ける
X_train, X_test, y_train, y_test = train_test_split(
    cancer.data, cancer.target, stratify = cancer.target, random_state=0)

# 可視化のためのリスト作成
training_accuracy = []
test_accuracy = []

# 学習
for n_neighbors in range(1, 11):
    model = KNeighborsClassifier(n_neighbors=n_neighbors)
    model.fit(X_train, y_train)
    training_accuracy.append(model.score(X_train, y_train))
    test_accuracy.append(model.score(X_test, y_test))

# 可視化
plt.plot(range(1, 11), training_accuracy, label='Training')
plt.plot(range(1, 11), test_accuracy, label='Test')
plt.ylabel('Accuracy')
plt.xlabel('n_neighbors')
plt.legend()
```
![スクリーンショット 2021-09-19 8.20.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1859982/297f3705-c92a-259c-21e2-c7fa9d41851d.png)
DockerでReact+TypeScriptの環境を構築する手順

#なぜこの記事を書いたのか

ReactとTypeScriptは相性が良いといわれており、この二つを組み合わせて開発する人も多いため、Dockerfile と docker-compose.ymlを一から作成して環境構築する方法を記事としてまとめておきたかった。

#環境構築完了（ゴール）の確認

この記事のゴールは以下のようにReactのページが起動すること。

![react-top.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/758310/2dc134b3-0ef5-0551-0aa4-5d81f0449be5.png)

#環境構築の手順

①Docker、nodeのインストール
②Dockerfile、docker-compose.ymlの作成
③ビルド
④TypeScriptで動くReactアプリの作成
⑤コンテナの実行

##①Docker、nodeのインストール
- Dockerのインストール
https://www.docker.com

:::note info
Dockerはコンテナ型の仮想環境。
Dockerをインストールして、Dockerの環境の中で開発をすることになる。
:::

- nodeのインストール
https://nodejs.org/ja/download/

:::note info
Dockerで環境構築したり、ライブラリをインストールする為にnodeが必要になる。
:::

##②Dockerfile、docker-compose.ymlの作成
docker-react-ts-app（プロジェクトフォルダ）
　└┬─  Dockerfile
　　└─ docker-compose.yml

上記のフォルダ構成を参考に、ファイルを作成する。

:::note info
「docker-react-ts-app」というフォルダを作成し、その直下に「Dockerfile」「docker-compose.yml」という名称で新規ファイルを作成すればOK。
:::

###Dockerfile

```Dockerfile
FROM node:14.17.5

ENV LANG=C.UTF-8
ENV TZ=Asia/Tokyo

WORKDIR /usr/src/app
```

- ターミナルで「node -v」を実行することでnodeのバージョンを確認できる。バージョンを「FROM node:○○.○○.○」という形で指定する。
- 「ENV LANG=C.UTF-8」は環境変数LANGにC.UTF-8を設定することを意味する。Cは最低限の英語表記を表す。日本語を指定する場合はja_JPだが文字化けを起こすことがある。（参考 https://eng-entrance.com/linux-localization-lang ）
- 「ENV TZ=Asia/Tokyo」はタイムゾーンをAsia/Tokyoに設定する。

###docker-compose.yml

```docker-compose.yml
version: '3'

services:
  frontend:
    build: .
    environment:
      - NODE_ENV=development
    volumes:
      - ./:/usr/src/app
    command: sh -c 'cd frontend && yarn start'
    ports:
      - '3000:3000'
    tty: true

```

- version: '3' はdocker-composeで使用するバージョンを定義している。このバージョンによって、docker-compose.ymlの書き方が異なる。
- servicesはアプリケーションを動かすための各要素をネストさせて定義する。上記docker-compose.ymlの場合はfrontendというServiceを定義している。（参考 https://qiita.com/yuta-ushijima/items/d3d98177e1b28f736f04 ）
- commandは「docker-compose up -d」したとき、flontendディレクトリに移動してdevサーバーを起動する。
- ttyはコンテナが起動してすぐ終了してしまうのを防ぐ。


##③ビルド

「③ビルド」「④Reactアプリの作成」「⑤コンテナの実行」で実行する「docker-compose」コマンドは、Dockerfileが存在するディレクトリで実行する必要がある。ターミナルにて「cd  docker-react-ts-app」を実行してディレクトリを移動しておく必要がある。

このコマンドを実行してビルドする。

```
docker-compose build
```

※buildコマンドはimageを作成する。コンテナは作成しない。

##④TypeScriptで動くReactアプリの作成

```
docker-compose run --rm frontend sh -c 'npx create-react-app frontend --template typescript'
```

上記「①Docker、nodeのインストール」でnpmをインストールしていれば「npx create-react-app frontend --template typescript」が実行され、TypeScriptで動くReactアプリが作成される。生成されるファイルもjsxファイルではなくtsxファイルとなる。


##⑤コンテナの実行

```
docker-compose up -d
```

ここまで完了したらWebブラウザで「 http://localhost:3000 」へアクセスする。以下のようにReactのページが起動すれば環境構築完了となる。
![React-top](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/758310/2823d6eb-abea-c83f-d7df-6ce90795373f.png)

#docker-compose upに失敗する場合
compose upやcompose downを繰り返していると、いくつもコンテナが立ち上がってしまい、docker-compose upに失敗することがあります。その場合は起動中のコンテナを停止したりするなどしてみてください。（参考  https://qiita.com/musatarosu/items/31d6293a93e75ca6073e ）


#参考
- [Docker上にReact+TypeScriptの環境を構築](https://saitoblog.page/posts/2020-11-15)




#Dockerで環境を構築する手順の記事

- [Reactの環境構築](https://qiita.com/kashimuuuuu/items/48aacfa24cb5df44389f)
- React + TypeScriptの環境構築 👈今ここ
【AWS】初心に戻って1からVPCを構築してみた　プライベートサブネット構築編

#はじめに
昨日の記事の続きです。昨日はVPCとパブリックサブネットを作成しました。
本日はプライベートサブネットを作成します。

https://qiita.com/hirockio2206/items/303f7f4ac993f7dabdb8

#構成図
以下のプライベートサブネットを作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/a11418aa-9072-5597-f4e6-f011ecac454d.png)


#手順
1.AWSのマネジメントコンソールにログインし、上部の検索バーで　VPCと入力します。
2.左側のメニューペインから[サブネット]を選択し、[サブネットを作成]をクリックします。
![スクリーンショット 2021-09-19 7.31.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/97e88495-1660-748f-dca5-beb465b936a4.png)
3.VPC ID:自分で作成した[10.0.0.0/16]のVPCを選択します。例では(VPC)という名前を付けています。
サブネット名:[プライベートサブネット]
AZ(アベイラビリティーゾーン): ap-northeast-1a
IPv4 CIDRブロック:[10.0.2.0/24]
![スクリーンショット 2021-09-19 7.36.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/08bd61bc-87ef-12ae-bdb6-ee7d35ff41e7.png)
4.1件のサブネットが正常に作成されました。と表示されたら成功です。
![スクリーンショット 2021-09-19 7.42.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/ecfa7cd1-afd7-7d4e-6bc7-9784e78279da.png)

ここまででプライベートサブネットの作成は完了です。
[VPCウィザード]でVPCを作成した場合は、以下の画像のようにインターネットゲートウェイのメニューから作成したVPCに既にアタッチされていることを確認して下さい。
![スクリーンショット 2021-09-19 8.00.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/c81c8ead-32c9-3e2a-be12-835be67fb83f.png)


※以下はVPCを手動で作成した場合に必要です。
5.次にVPCをインターネットに接続します。
VPCの左側メニューペインから[インターネットゲートウェイ]を選択し、[インターネットゲートウェイの作成]をクリックします。
![スクリーンショット 2021-09-19 7.47.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/3c84471c-4eaf-8fe8-8864-f472433c40b7.png)

6.名前タグは任意でつけます。(例:VPC-IG)
[インターネットゲートウェイの作成]をクリックします。
![スクリーンショット 2021-09-19 7.50.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/9d15f1a8-3efe-5a46-ed78-f8d4e17fb953.png)

7.インターネットゲートウェイが作成されました。と表示されたら作成完了です。
[VPCへアタッチ]ボタンからVPCへアタッチしてください。
![スクリーンショット 2021-09-19 7.52.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/24df8b3e-fc67-6b0a-b458-7d303fc4dbe2.png)
※注意
VPCウィザードで作成された場合はアタッチできるVPCがないので以下のエラーが出ます。
![スクリーンショット 2021-09-19 8.05.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/62aa232f-4d44-defa-c961-7c718791050e.png)

#最後に
いかがでしたでしょうか。無事プライベートサブネットを構築できましたでしょうか。
次回はルートテーブルの設定や作成した空間にEC2(仮想サーバ)を配置していきたいと思います。
ご参考になれば幸いです。
GooglePlayのアプリ提出仕様変更に伴いUnity2020でGradleビルドエラー

# はじまり
Androidアプリ申請の仕様が変わりaab形式のビルドを提出する必要ができました。

apk形式からaab形式の切り替えは問題なく行えたのですがTargetAPILevelを30以上にする必要があるとストア側に言われ30に設定したところGradleビルドエラーが発生して積みました、、、

```
FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':launcher:processReleaseResources'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade
   > Android resource linking failed
```

```
CommandInvokationFailure: Gradle build failed. 
/${OpenJDK_PATH}/bin/java -classpath 
"${Gradle_PATH}/lib/gradle-launcher-5.6.4.jar" org.gradle.launcher.GradleMain "-Dorg.gradle.jvmargs=-Xmx4096m" "assembleRelease"
```

有難いことに先駆者様がいくつか対応したメモを残してくれていたのですが、すぐには解決はせず、先駆者様のメモを複数対応した結果ビルドエラーを解消できました。

今回はこの解決までの手順を備忘録でまとめていきます。

# 環境（成功したの環境)

Unity2020.3.18f1(LTS最新)
Android TargetAPI Level 30
Android Build Tool 31.0.0

# 0.Unityを更新

VersionをUnity2020.3.18f1(現状LTS最新)に更新

# 1.BuildTargetをAAB形式に設定

BuildSettingsからBuildAppBudleにチェック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119898/4ba8fcdd-9c58-5424-6a81-abcf9cddf876.png)

# 2.TargetAPILevel設定

PlayerSettingsからTargetAPILevelを30に変更

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119898/8c3c13bc-cfa2-57ec-16af-360c01059a51.png)

# 3.PreferencesからAndroidSDKをAPILevel30に対応したSDKに設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119898/60b4a758-582c-e8e0-aa6d-5ba9d35503e1.png)

対応したAndroidSDKがない場合はAndroidStudioからインストールしてください

https://developer.android.com/studio?hl=ja

# 4.Gradle系ファイルを出力

多分やる必要はないですが、試した結果成功した環境はこういう形になっています

ProjectSettings->PublishingSetingsから設定

内容は変更していません

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119898/da533adb-0e32-9139-ee0a-7a431ee69057.png)

こちらの記事から出力すると解決する旨が記載されていましたので参考にしました

https://qiita.com/tanakaPH/items/789cdfe9472d4727f001

#5.BuildTool31.0.0のエラーを修正する

私の環境では手順4まで行うとビルドエラーの内容が変わりました。

```
Installed Build Tools revision 31.0.0 is corrupted. Remove and install again using the SDK Manager.
```

Build Toolsが導入されていない方は事前にAndroidStudioからインストールしてください。

結論から、2つファイル名を変更することで対応できます

・1つ目　d8.bat => dx.bat

ファイル場所

```
 "C:\Users\user\AppData\Local\Android\Sdk\build-tools\31.0.0"
```

・2つ目 d8.jar -> dx.jar

ファイル場所

```
"C:\Users\user\AppData\Local\Android\Sdk\build-tools\31.0.0\lib"
```

以上です

Mac、Lunuxはこちらで行えるようです

```
# change below to your Android SDK path
cd ~/Library/Android/sdk/build-tools/31.0.0 \
  && mv d8 dx \
  && cd lib  \
  && mv d8.jar dx.jar
```

この問題はこちらの記事が大変参考になりました

https://stackoverflow.com/questions/68387270/android-studio-error-installed-build-tools-revision-31-0-0-is-corrupted

これで私の環境ではビルドできました。
あなたの環境でもビルドできれば良いのですが、、、
【Ruby on Rails】頻出しそうなFormHelperをまとめる

#対象者

* form_with, form_forを使っている方へ


#目的

* FormHelperにどんな種類があるか把握して、引き出しを増やすこと

#実際の手順と実例
###1. 前提

form_withの基本構文は下記の通りです。

https://qiita.com/nao0725/items/e5685d4851d8329d9e73


###2. よく使用するFromHelper一覧

| 1 | 2 |
|:-:|:-:|
|  check_box | チェックボックスタグを生成  |
|  file_field |  ファイルアップロード用のタグ生成 |
| hidden_field  |  特定の属性にアクセスするための、隠されたinputタグを返す |
| label  | フォームに属した名前（ラベル）を返す|
|  password_field |  パスワードのためのタグ生成 |
|  radio_button |  ラジオボタンをタグを生成|
|   text_area|長文用テキストを生成|
|   text_field |   短文用のテキスト生成|
|   email_field|  メール用のタグ生成|
|  url_field |  URL用のタグ生成


#参考にさせて頂いた記事

* [Railsガイド FormHelper](https://railsguides.jp/action_view_overview.html#:~:text=2%0A-%203%0A%3C/pre%3E-,6.8%20FormHelper,-%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E3%83%98%E3%83%AB%E3%83%91%E3%83%BC%E3%82%92)
Laravelで楽天APIを叩いて商品情報を取得する

#はじめに#
　APIとは、Application Programming Interfaceの略です。Interfaceとは、何かと何かをつなぐものといった意味があり、この場合はアプリケーションやプログラムをつなぐものになります。これにより、APIを提供する外部のソフトウェアへリクエストを送り、認証機能や商品情報取得といった外部ソフトウェアの機能を使うことが出来ます。
　APIを使った機能は我々の生活に深く浸透しており、例えばカード決済やSNSログインなどがこれにあたります。


#Laravelで楽天APIから商品情報を取得#
　Laravelで楽天APIを使用するにはまず、[RakutenDevelopers](https://webservice.rakuten.co.jp/)でアプリIDを取得する必要があります。![スクリーンショット 2021-09-19 7.23.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558223/067b37f2-76a9-bd75-8b03-ffe16fce7e3e.png)
アプリ名とかURLは適当で大丈夫です。アプリIDさえ取得できればOKです。


次に、ComposerでSDKをインストールします。Rakuten Web Service SDK for PHPのことで、PHPから楽天APIに簡単にアクセスできるSDK（Software Development Kit）になります。楽天APIを簡単に使えるようになるライブラリという認識で大丈夫だと思います。

```
$ composer require rakuten-ws/rws-php-sdk
```
このようにコマンド入力すると、インストールすることが出来ます。

ここまでくればあとはAPIにアクセスするだけです。
まずは.envファイルにアプリケーションIDを設定します。

```.env
RAKUTEN_APPLICATION_ID='アプリケーションIDを入れてください'
```

次に、config/app.phpに.envファイルに設定した環境変数を定義します。

```config/app.php
return [
  //略
  'rakuten_id' => env('RAKUTEN_APPLICATION_ID', false),
];

```

次に、楽天APIにアクセスします。

```controller.php
use RakutenRws_Client;

class HomeController extends Controller{
  
   public function get_rakuten_items()
      {
        $client = new RakutenRws_Client();

        define("RAKUTEN_APPLICATION_ID", config('app.rakuten_id'));

        $client->setApplicationId(RAKUTEN_APPLICATION_ID);

        $response = $client->execute('IchibaItemSearch',array(
            'keyword' => '任意のキーワードを入れてください'
        ));

        if(!$response->isOk()){
            return 'Error:'.$response->getMessage();
        } else {
            $items = [];
            foreach($response as $key => $rakutenItem){
                $items[$key]['title'] = $rakutenItem['itemName'];
                $items[$key]['price'] = $rakutenItem['itemPrice'];
                $items[$key]['url'] = $rakutenItem['itemUrl'];
                
                if($rakutenItem['imageFlag']){
                    $imgSrc = $rakutenItem['mediumImageUrls'][0]['imageUrl'];
                    $items[$key]['img'] = preg_replace('/^http:/','https:',$imgSrc);
                }
            }
            return $items;
        }
    }
}
```
これで\$itemsという配列に商品情報を格納することが出来ます！


#終わりに#
　APIは未経験からエンジニアを目指す我々にとっても必須の知識ですので、ぜひ扱えるようにしておきましょう！
【Python】ちょっとしたメモ

次のSphinx拡張を作りながら、メモしておくといいと思った事柄。

https://qiita.com/koKekkoh/items/4563b63fdb8eaa3ef4f9

#文字列データ

文字列の基本。これらの説明は「字句解析」のページで見つかる。

- ``r"文字"`` 正規表現で大活躍
- ``f"文字"`` ``f"http://{host}/{paht}/{file}"`` の用に変数が書ける
- ``u"文字"`` Python3では使わない
- ``b"文字"`` 使わない

英数字の並びを一文字ずつforループで処理する場合に

- ``list(string)`` 文字列を１文字毎のリストにしてくれる

#リスト型データ

###🍳基本的な使い方

https://docs.python.org/ja/3/tutorial/datastructures.html

###🐾pprint

大量のデータを持つリスト型を見やすく視覚化する「 ``pprint`` 」

https://laptrinhcanban.com/ja/python/nhap-mon-lap-trinh-python/nhap-xuat-trong-python/ham-pprint-trong-python-va-cach-in-list-va-tu-dien-thong-minh/

``from pprint import pprint`` して、後は ``print()`` と同じ感覚で使うだけ。

###🩸やらかし（その１）

関数内でのコード

```python
return [node], []
```

受け取り側（間違い）

```python
node, message = func()
```

これで、「 ``node['key']`` がエラーになる。何で？」と思っていた…

受け取り側（正解）

```python
[node], message = func()
```

#yield

これが分かりやすかった。

http://ailaby.com/yield/

#関数内の関数
https://excel-ubara.com/python/python014.html

- 関数内の関数からは、関数内の変数の参照はできても更新はできない。

#テスト

- doctestは使い方の説明程度に留めて、unittestでガツンとチェックする
    - syntaxエラーのチェック、その他くらい。コミットする前に最低限やることとして。

#🌤reStructured流のdocstring

- クラスやメソッドのdocstringでは引数の説明や、使い方の説明にもなるdoctestの記述に留めて、全てはモジュールのdocstringに書く。``sphinx-apidoc`` に掛けて見たら ``reStructuredText`` の流儀の意図がわかった。

#以上

思い出したら追記します。