OmniAICreator/Qiita-1.07M huggingface dataset:
インベントリー／ナレッジ管理系のElasticsearchフロントアプリを1日で作る

# はじめに
Elasticsearchを使って、インベントリーデータをささっと検索して必要な情報を取り出すようなアプリをゼロから1日で作る手順です。所持品やナレッジを分類データ化したものをパソコンやスマホから検索できるようにします。当然データ自体は自分で用意する必要があります。

# 作成するもの
バックエンドはAmazon Elasticsearch Serviceを用意し、データはそこに蓄積します。
フロントエンドはブラウザで動作するReactアプリで、Reactivesearchというコンポーネントを活用して、Elasticsearch Serviceのデータを検索できるようにします。ブラウザ（のJavaScript）から直接Elasticsearch Serviceにアクセスします。
また、Reactアプリを自動でビルドしデプロイする環境もCodepipelineで作ります。

### アプリの画面イメージ
（この画面はインベントリー管理になっていませんが流用はできると思います）
<img width="400" alt="beautifiedcityrank.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603113/942dd5a4-cb23-8ea8-d288-0c74fabec8ad.png">

### インフラの概要図
![RactivesearchAP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603113/d58508fc-bc2e-4e7d-2c08-03ddf9348f1c.png)

### 環境
Elasticsearch v7.4
Node.js v13.10.1
React v16.13.0
Reactivesearch v3.5.0

# 手順
詳細手順を記述した記事をこの順番でやっていけば作れます。右端の時間は、順調に進められたときの目安の時間です。

1. [Amazon Elasticsearch Serviceで検索できる状態まで最速で立ち上げる](https://qiita.com/NorihitoYamamoto/items/5b2c63ee52215014c0f3)（30分）
2. [React版Reactivesearch v3を使ってゼロから最速でElasticsearchフロントアプリを作る](https://qiita.com/NorihitoYamamoto/items/be6d7a245b1e8864952c)（1時間）
3. [React版ReactivesearchアプリをiPhone縦でも見やすくする](https://qiita.com/NorihitoYamamoto/items/721a9e48525a859879bd)（15分）
4. [AWS S3 + CloudFrontでReactアプリをHTTPS公開するための正しい構成](https://qiita.com/NorihitoYamamoto/items/63df7d87dfd67628d775)（1時間）
5. [AWS Codepipelineを使ってReactアプリのCI環境をゼロから作る](https://qiita.com/NorihitoYamamoto/items/a463c5641bc3401a4439)（1時間）
6. [Bracketsエディタからgit pushボタンで自動でデプロイされるCI環境を作る](https://qiita.com/NorihitoYamamoto/items/89ff814b2cdd16609ba8)（15分）

# 番外編
今回は対応していませんが、派生での参考記事です。

Amplifyを使えば今回と同等の環境はもっと簡単に作れます。ただし、制約はあります。
[AWS Amplify Consoleを使ってReactアプリのCICD環境を10分で作る](https://qiita.com/NorihitoYamamoto/items/a866b3692c472f38320d)

Elasticsearch Serviceに認証を付けたいところですが、今回は制約から見送りました。
[Amazon Elasticsearch ServiceのKibana Cognito認証設定をゼロから最小限の設定で実現する](https://qiita.com/NorihitoYamamoto/items/2da392ac8133c067bc96)
Vue.jsでTo-Do Listを作ってみた。

Vue.jsの学習を本日から始めました！
めちゃくちゃ面白かったので、記事にします。

#やったこと
「今日のTo-Do List」を作成しました。
普段はUdemyや本を参考に学習することが多いのですが、今回は久しぶりにドットインストールを使ってみました。
ドットインストールさん、分かりやすかったです。ありがとうございます。回し者ではありません。

作ったものはこんな感じです。
![スクリーンショット 2020-03-29 16.54.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577071/efe9e244-d9bd-ab86-d5e9-4e1cf1817cc7.png)

ドットインストールを参考に作ったので、見た目はほぼドットインストールのままですが、ToDoをする予定時刻を自分で入れてみました。
これからもっと手のこんだアプリケーションをVue.jsで作っていきたいです。

#学んだこと
###導入が楽
scriptタグをhtmlファイルに記載するだけで使えました。
開発環境の構築は大変な時が多々ありますが、Vue.jsは非常に楽でした。

###双方向データバインディング
テキストボックスに入力した途端に出力される文字が変わる、といったことがこの双方向データバインディングに例になると思います。
これを最初学んだときは驚きました。しかも、それが数行のコードですぐ簡単に実装できてしまうのです。

###学びやすい
学習コストが少し低いように感じました。まだ最初だからだと思いますが、最初にしてはとっつきやすかったです。
これからVue Routerを使ってSPAを作ろうと思っておりますが、おそらくその過程で苦戦することでしょう。。。

#これから
初めてJavaScriptのフレームワークを本格的に学習してみましたが、非常に興味深かったです。
上でも書いたようにこれからはVue.jsでシングルページアプリケーションを作ってみます。
その際にはまた記事にします！

#参考
[ドットインストール　Vue.js入門](https://dotinstall.com/lessons/basic_vuejs_v2)
Python Version 変更する方法

pythonを勉強している初心者です。
この記事は学習の目的として記録中です。
なので、参考にできる記事とか内容が間違ってたらコメントをよろしくお願いします。

#開発環境
OS : macOS Catalina
Version : 10.15.3

# Install可能なpython Version確認
```
$ pyenv install --list
```
# Version確認
```
$ python  --version
Python 2.7.16
```

#変更可能なpython Version確認
```
$ pyenv versions
  system
* 3.9.0 (set by /Users/******/.python-version)
```
※インストールされているバージョンにより、変更可能なVersionが異なります。

#python変更可能なVersionに切り替え
```
pyenv global 3.9.0
```

#変更されてるかを確認
```
$ python  --version
Python 2.7.16
```

えーーー！！
うまく行かない。。

その時は👇

# 追加コマンド
```
$ eval "$(pyenv init -)"
```
この仕組みについては参考記事をご覧ください。

#変更されてるかを確認
```
$ python  --version
Python 3.9.0
```

できた〜！

# 参考記事
[pyenvがバージョンを切り替える仕組みを理解する](https://akamist.com/blog/archives/2610)
redirect_toとrender, flashとflash.nowの違い

ポートフォリオ作成中、バリデーションのエラーメッセージが表示できずに苦戦してました
redirect_toとrenderの違いを理解していなかったのが原因です。
redirect_toとrender, ついでにflashとflash.nowの違いについても今更理解したのでまとめます。

## 参考
https://railsguides.jp/layouts_and_rendering.html#redirect-to%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B

https://railsguides.jp/action_controller_overview.html#flash

## renderとredirect_toの違い

- render => ビューを描画するだけで、新たにhttpリクエストを送信するわけではない
- redirect_to => 新たにhttpリクエストを送信して、その結果コントローラからビューが描画される

```ruby:app/controllers/tweets_controller.rb
class TweetsController < ApplicationController
  def new
    @tweet = Tweet.new
  end

  def create
    @tweet = Tweet.new(tweet_params)
    if @tweet.save
      # 成功時の処理
    else
      flash[:danger] = '失敗しました'
      redirect_to new_tweet_path
    end
  end

  private

    def tweet_params
      params.require(:tweet).permit(:content)
    end
end
```
```slim:app/views/tweets/new.html.slim
= form_with model: @tweet, local: true do |f|
  - if @tweet.errors.any?
    .alert.alert-danger
      ul
        - @tweet.errors.full_messages.each do |message|
         li= message
  = f.label :content
  = f.text_area :content
  = f.submit 'tweet'
```

こんな感じの設定があったとします（tweetモデルはpresence: trueのconent: stringカラムを持つ)
この場合、空白で送信してもエラーメッセージは表示されません
redirect_toでリダイレクトするとコントローラを経由してしまうため、新たに`@tweet`が生成され、エラーメッセージを含んだ`@tweet`が消えてしまうから…だと考えています

ここで、コントローラを経由せずにページを描画するrenderを使用します

```ruby:app/controllers/tweets_controller.rb
class TweetsController < ApplicationController
  def new
    @tweet = Tweet.new(tweet_params)
  end

  def create
    @tweet = Tweet.new(tweet_params)
    if @tweet.save
      # 成功時の処理
    else
      flash[:danger] = '失敗しました'
      render action: :new # ここを変更
    end
  end

  private

    def tweet_params
      params.require(:tweet).permit(:content)
    end
end
```

renderを使用すればコントローラを経由せずにページを描画することができるため、エラーメッセージを含んだ`@tweet`がビューに渡され`if @tweet.errors.any?`に引っ掛かり、エラーメッセージを表示することができます

これで無事エラーメッセージを表示することができました！

## flashとflash.nowの違いについて

- flash => 次のリクエスト終了時まで表示される
- flash.now => 次のリクエスト開始時まで表示される

コントローラーが上の最終状態のまま空白で送信した場合、`失敗しました`というflashメッセージが表示され、失敗します。
しかし、このままでは次別のページに遷移した時flashが残ったままになってしまいます。

renderを使うとリクエストを送信しないため次にリクエストを送信した時もflashが残り、その次のリクエストを送信した時点でやっとflashが消えるからだと思われます

そこでflash.nowを使ってみましょう

```ruby:app/controllers/tweets_controller.rb
class TweetsController < ApplicationController
  def new
    @tweet = Tweet.new(tweet_params)
  end

  def create
    @tweet = Tweet.new(tweet_params)
    if @tweet.save
      # 成功時の処理
    else
      flash.now[:danger] = '失敗しました' # ここを変更
      render action: :new
    end
  end

  private

    def tweet_params
      params.require(:tweet).permit(:content)
    end
end
```

flash.nowは次リクエストを送信した時点で消えるため、これでflashを残さずに次のページへ移動することができます

### それぞれの組み合わせ

- flash[]とredirect_to => 次のページにリダイレクトした時点でflashは消える
- flash[]とrender => renderはリクエストを送信しないため、次のページに移動してもflashは残る
- flash.now[]とredirect_to => redirect_toの時点でflashが消えるため、flash自体表示されない
- flash.now[]とrender => 次のページへリダイレクトした時点でflashは消える

## 最後に

Railsチュートリアルで丁寧に説明されていた箇所なんですが、実際に自分で試行錯誤して初めて理解できました

何かおかしい部分があれば指摘して頂けると嬉しいです

読んでいただきありがとうございました！
【SIRモデル入門】Diamond Princess号のフィッティング結果を考察する♬

気になっていたデータそれは、DiamondPrincess号のデータである。
さぞ、美しいデータが残っているかと思ったが、がっかりでした。
しかし、一応やれるのでフィッティングしてみました。
方法は先ほどの[【SIRモデル入門】COVID-19データをフィッティングしてみる♬](https://qiita.com/MuAuan/items/2bcc7f3c2f258ef71137)と同様に実施しています。
###DiamondPrincess号のデータ
以下のように、治癒率は80%超えて、終息してきています。
死亡率も1.4%程度なので、世界の各国の現状と比較すれば、誇れる数字だと思います。
![fig_Diamond Princess_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233744/3a43d71f-2e5f-1e06-3780-5e6ede9077db.png)
###フィッティングの結果
ということで、前回のSIRモデルで早速フィッティングしてみました。
結果は以下のとおりになりました。
N=5*N0つまり感染者の5倍としています。
実際は、乗組員など3700人位だったと思いますが、この系も医療従事者などの追加の対象者が不明なのでざっくり推定して5倍にしました。
![SIR_Diamond Princessf1_1f2_0;b_1.04e-04g_1.49e-01r0_2.52N_3610S0_3610I0_1R0_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233744/edae7c63-ad88-ad84-a299-d5caef2fc3ab.png)
今回も、治癒者の曲線は捨てています。
同時に一致させようとすると全くフィッティング出来ません。

得られたパラメータは以下のとおりです。
各国の値と比較すると、大きな値になっています。

```math
{\begin{align}
\beta &= 1.04e^{-4}\\
\gamma &= 1.49e^{-1}\\
N &= 3610\\
R0 &= 2.52\\
R(27.3.2020) &= 0.29\\
\end{align} 
}
```
###結果の評価
つまり、感染も治癒(実際には隔離)も素早く進んだことがうかがえます。
そうです！
感染しても、SIRモデルではその感染者が隔離されると他へ感染しなくなり、まさしくこの場合はremovedされたことになります。
したがって、今回も治癒者はこのremovedされた人々が別ルートで治癒するので、この方程式とは無関係に回復するということだと解釈しました。
このように考察すると、DiamondPrincess号のケースは特殊ですが、いい対策が取れたとも評価出来ると思います。
###まとめ
・DiamondPrincess号のデータを表示した
・SIRモデルで感染数のフィッティングを実施した
・隔離の効果について議論した

・今回の議論を踏まえて各国の結果を評価する
実行された全てのSQLクエリをログに出力するLaravelプラグイン

Laravelで新しいプロジェクトを作るたびに毎回似たようなコードを書いている気がしてきたので、プラグインにして公開しました。

https://github.com/ngmy/laravel-query-log-tracker

![Demo](https://ngmy.github.io/laravel-query-log-tracker/demo.gif)

PHP 7.2〜7.4、Laravel 5.6以上、6.x、7.xで動作するはずです。
PHP 7.2〜7.4とLaravel 7.xでユニットテストしています。
PHP 7.3.16とLaravel 7.3.0で実際に動作確認しました。

ログには次の項目が出力されます。

* バインド後のSQL
* バインド変数
* 実行時間（ミリ秒）
* コネクション名

インストール方法はREADMEに書いていますが、Composerでインストールして、（パッケージディスカバリーを使っていない場合は）サービスプロバイダとファサードを`config/app.php`に追加するだけです。

実行時にログを無効化することもできます。

```php
QueryLogTracker::beginDisable();
// ログを無効化したいSQL
QueryLogTracker::endDisable();
```
```php
QueryLogTracker::disable(function () {
    // ログを無効化したいSQL
});
```

設定ファイルで次の項目を設定できます。

* ログレベル
* ログから除外するSQLのパターン（正規表現）
* ログスタック
* ログチャンネル

テストはしていますがOSSなので自己責任で使ってください。
本番環境で使う場合は無効化や除外パターンを使って、ログに個人情報や秘密情報が出力されないように注意してください。
【Win10】AnacondaでPython環境構築

#経緯
PythonでFXチャート予測してみたいな～と思って、色々ググりつつAnacondaにたどり着きました
恐らくPythonistからすると王道の道を辿っているんじゃないかな？

#手順
① Pythonを公式サイトからインストール
② Anacondaをインストール (Windows 64bit版)
③ Anaconda動作チェック[(参考にしたサイト)](https://www.creativevillage.ne.jp/72837)

今回は③で躓いたので備忘録。

#トラブル
③のAnaconda動作チェック時にトラブル発生！
具体的には
A) Condaコマンドが使えない
B) Anaconda Navigator で jupyter notebookの"Launch"を押下しても起動しない

の二点です。

#解決方法
**A)「Condaコマンドが使えない」の解決方法**
 Condaコマンドが使えない事象はpathが通っていないという超絶初歩的な問題でした。
Anacondaインストール時に通してくれないのかなぁ？
コマンドプロンプトで以下を入力したらcondaコマンドが使えるようになりました。

```
PATH ~\Anaconda3
PATH ~\Anaconda3\Scripts
```

※~はAnaconda3がインストールされている場所です。
参考にしたサイトはこちら[「AnacondaからJupyter notebookを起動したい」
](https://teratail.com/questions/102628)

---
**B)「Anaconda Navigator で jupyter notebookの"Launch"を押下しても起動しない」の解決方法**
100%解決に至らず。Jupyter notebookは開けるようになったので、あくまで「最適解」です。
スタートキー→Anaconda3→Jupyter Notebookでコマンドプロンプトが起動して以下の返答が帰ってきます。

```
[I 16:43:12.736 NotebookApp] JupyterLab extension loaded from C:\Anaconda3\lib\site-packages\jupyterlab
[I 16:43:12.737 NotebookApp] JupyterLab application directory is C:\Anaconda3\share\jupyter\lab
[I 16:43:12.786 NotebookApp] Serving notebooks from local directory: C:\Users\Username
[I 16:43:12.786 NotebookApp] The Jupyter Notebook is running at:
[I 16:43:12.786 NotebookApp] http://localhost:8888/?token=02~~~~~~~~~~~~~~~~~~~~~
[I 16:43:12.787 NotebookApp]  or http://127.0.0.1:8888/?token=02~~~~~~~~~~~~~~~~~~~~~
[I 16:43:12.787 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[C 16:43:12.936 NotebookApp]

    To access the notebook, open this file in a browser:
        file:///C:/Users/Username/AppData/Roaming/jupyter/runtime/nbserver-8###-open.html
    Or copy and paste one of these URLs:
        http://localhost:8888/?token=02~~~~~~~~~~~~~~~~~~~~~ %トークンは英数字の羅列
     or http://127.0.0.1:8888/?token=02~~~~~~~~~~~~~~~~~~~~~

```

言われるがまま，

```
http://localhost:8888/?token=02~~~~~~~~~~~~~~~~~~~~~
```
をchromeで開いてみると開けた！

参考サイトはこれ→[「Pythonの為のJupyter Notebookの基本的な使い方」](https://note.com/mc_kurita/n/n4261e54d2539)

取り敢えず止血対応としてはこの方法を使うけど，できる事ならAnaconda Navigatorから直接開きたい。。。
Python × Flask × Tensorflow.Keras 猫の品種を予測するWebアプリ２

# はじめに
[Python × Flask × Tensorflow.Keras 猫の品種を予測するWebアプリ](https://qiita.com/Susasan/items/52d1c838eb34133042a3)で作ったPythonプログラムを変更しました。

#変更内容
- 変更前
    - 入力画像をファイル保存して扱う
- 変更後
    - 入力画像をメモリに一時保存して扱う

# 変更ファイル

- sever.py
    - 画像書き込み用バッファを確保
    - 画像データをバッファに書き込む
    - バイナリデータをbase64でエンコード
    - utf-8でデコード
    - 付帯情報を付与する
    - HTMLに渡す

```python:sever.py
from flask import Flask, render_template, request
from tensorflow.keras.preprocessing.image import load_img
from tensorflow.keras.models import load_model
import numpy as np
from image_process import examine_cat_breeds
from datetime import datetime
import os
import cv2
import pandas as pd
import base64
from io import BytesIO

app = Flask(__name__)

# モデル(model.h5)とクラスのリスト(cat_list)を読み込み
model = load_model('model.h5')
cat_list = []
with open('cat_list.txt') as f:
    cat_list = [s.strip() for s in f.readlines()]
print('= = cat_list = =')
print(cat_list)


@app.route("/", methods=["GET","POST"])
def upload_file():
    if request.method == "GET":
        return render_template("index.html")

    if request.method == "POST":
        # アプロードされたファイルをいったん保存する
        f = request.files["file"]
        #filepath = "./static/" + datetime.now().strftime("%Y%m%d%H%M%S") + ".png"
        #f.save(filepath)
        # 画像ファイルを読み込む
        # 画像ファイルをリサイズ
        input_img = load_img(f, target_size=(299, 299))
        
        # 猫の種別を調べる関数の実行
        result = examine_cat_breeds(input_img, model, cat_list)
        print("result")
        print(result)

        no1_cat = result[0,0]
        no2_cat = result[1,0]
        no3_cat = result[2,0]

        no1_cat_pred = result[0,1]
        no2_cat_pred = result[1,1]
        no3_cat_pred = result[2,1]

        # 画像書き込み用バッファを確保
        buf = BytesIO()
        # 画像データをバッファに書き込む
        input_img.save(buf,format="png")

        # バイナリデータをbase64でエンコード
        # utf-8でデコード
        input_img_b64str = base64.b64encode(buf.getvalue()).decode("utf-8") 

        # 付帯情報を付与する
        input_img_b64data = "data:image/png;base64,{}".format(input_img_b64str) 

        # HTMLに渡す
        return render_template("index.html", input_img_b64data=input_img_b64data, 
        no1_cat=no1_cat, no2_cat=no2_cat, no3_cat=no3_cat,
        no1_cat_pred=no1_cat_pred, no2_cat_pred=no2_cat_pred, no3_cat_pred=no3_cat_pred)

if __name__ == '__main__':
    app.run(host="0.0.0.0")
```

- index.html

```html:index.html
<!DOCTYPE html>
<html>
   <body>
      {% if no1_cat %}
      <img src="{{input_img_b64data}}" border="1" ><br>
      予測結果<br>
      {{no1_cat}}:{{no1_cat_pred}}<br>
      {{no2_cat}}:{{no2_cat_pred}}<br>
      {{no3_cat}}:{{no3_cat_pred}}<br>
      <hr>
      {% endif %}
      ファイルを選択して送信してください<br>
      <form action = "./" method = "POST" 
         enctype = "multipart/form-data">
         <input type = "file" name = "file" />
         <input type = "submit"/>
      </form>
   </body>
</html>
```

# 実行結果
画像は299×299で表示されます（モデルの入力サイズのまま・・・）

<img width="500" alt="スクリーンショット 2020-03-29 16.46.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251117/d66c6d1a-b972-f524-6fa8-4da51675b1af.png">
拝啓「インデックスは作れるけど説明できない僕へ」

##記事概要
■**作成までの経緯、状況**
「インデックスは、辞書の目次みたいなものだから。使えば検索が早くなる」
SQLを使い始めてまだ間もないころ、先輩に言われた言葉です。
「お！なるほど！とりあえず貼ればいいのかあ」
と馬鹿の一つ覚えのようにテーブルにインデックスを貼りまくった結果、
その後のパフォーマンスチュー二ングにとても苦しみました。
インデックスの作成はできる。けれどしくみが説明できない。。
当時の自分への備忘録として、本記事の作成に至りました。
使用する用語はMySQLに準じます。

■**発生した問題**
インデックスの作成方法はわかるが、なぜ効果があるのかがわからない。

■**期待する効果**
インデックスのしくみを説明できるようにする。

■**問題を解決するための用法**
Qiitaで記事を書く。

■**しくみ、動作原理**
以下のポイントでインデックスのしくみを説明します。
1. テーブルを用意する。
2. データ検索の流れを理解する。
3. インデックスのしくみを理解する。
4. インデックスが使えない場合を理解する。


##ポイント１ 「テーブルを用意する」

インデックスを作成するには、テーブルが必要です。
今回は、あるアニメの「登場人物」テーブルを用意します。

| 登場人物       | 
|:-----------------|
| イカリ シンジ|
| アヤナミ レイ|
| スズハラトウジ|   
|カツラギ ミサト|   
| アカギ リツコ|
| カジ リョウジ| 
| イカリ ゲンドウ|
| ・・・|
| ヒュウガ マコト|
| ナギサ カヲル|


2020/06/27　楽しみだなー( ´∀｀ )

##ポイント２ 「データ検索を理解する」
テーブルを検索する流れは以下の通りです。
① HDD上のデータがページ単位でキャッシュメモリに載る。
② キャッシュメモリに載ったテーブルをCPUが処理する。
③ メモリがパンパンになったら削除され、①に戻る。

![Qiita_Index2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243294/5c8535a4-6eba-d997-f2e7-af3e1d32c519.jpeg)






①の「ページ」とは、データをかたまりで見た時の単位を意味します。
上記では、P2のデータをメモリに載せています。
Oracleでは「ブロック」と言います。

この図を見たときの疑問点として以下のものが挙げられます。
「②の時に検索したいデータがあれば、その時点で検索が終わるんじゃない？」

これに対する答えは**「検索は続くよどこまでも」**です。

インデックスを作成していないと、データがソートされません。
そのため、「ほかにも同様のデータがあるんじゃ。。」
となり、結局テーブル全体が検索されます。これがフルスキャンです。
（メモリにキャッシュされている部分は除く）
だからパフォーマンスが落ちるのですね！！:eyes:

##ポイント３ 「インデックス作成ロジックを理解する」
数あるインデックスの中で、MySQLで使用されているのはB+treeです。
B-treeとも呼ばれますが、厳密には、B-treeを実用的扱いやすく改良したものがB+treeです。

B-treeインデックスについての説明は以下の記事がとても分かりやすいです。
[「B-treeインデックス入門」](https://qiita.com/kiyodori/items/f66a545a47dc59dd8839)


以下はメモリやHDDページを省略した簡単な図解です。

![Qiita_Btree2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243294/67d3fb8a-c610-e451-7acd-173aec1bdf09.jpeg)


ここでは検索対象として「アヤナミ　レイ」を２件用意しました。
HDD全体を検索するフルスキャンでは、検索終了までに何回もHDDを読み込む必要があります。
しかし、B-treeインデックスを使用した場合、図からもわかるように2か所のHDDページだけを直接読み込むことで検索が終了します。
インデックスのデータ構造はただテーブルがソートされていただけでなく、
このようなしくみで検索されていたから早くなるのです。:thinking:

##ポイント４ 「インデックスが使えない時を知る」
インデックスが役に立たない場合は以下の通りです。
・データ数が少ないとき
・後方一致検索
・前方一致検索（検索結果が多いときのみ）

後方検査でインデックスが使用できない理由は、上記の図からもわかりますね。
要は**「データは頭文字から照合されていくため、中間地や後方一致検索にインデックスを使用できないから」**です。

前方一致検索でインデックスが使用できない理由は、**「頭文字が同じものが多数ある場合、結局検索する対象が多くなるから」**です。

##おわりに
最後までお読みいただき、ありがとうございました！
本記事の作成を通して、インデックスのしくみが理解できました。
内容に誤りがありましたら、ご指摘ください。


##参考書籍
オススメの技術書籍を楽天Roomで紹介しています。

「SQLの苦手を克服する本　データの操作がイメージできれば誰でもできる」
https://room.rakuten.co.jp/room_39a28b3432/items#!
自然言語処理で大活躍のBERTって何？

自分のメモとして、こちらを共有しておきます。間違っていたら随時更新していきます。

BERTは、Google AI Languageチームが2018年10月に発表されたBERTは、質疑応答や自然言語推論といった様々な自然言語処理のタスクにおいて先行する言語モデルとなってます。

BERTは、以下の２つのアイディアで構成されます。

「マスクされた言語モデル」(Masked Language Model)→学習データとして与えられた文字列における任意の単語を隠して、その隠れた単語を予測するように学習するアイデア

「次文予測」(Next Sentence Predicition)→次文予測とは文字通り後続する文を予測するように学習するアイデア　で教師なしコーパスからpre-trained modelsを作成してます。 

#BERTが及ぼす影響
これは、BERT以前の言語モデルは前にある単語から後ろに続く単語を予測したり、Word2vecなどで文章の中で近い距離にある単語同士の関係を把握したりするだけでしたが、それに対してBERTは文章中の遠い距離にある単語同士の関係を把握したり、文脈を基に文章の各所にあるべき単語を予測したりできます。

以下のQiitaがとても参考になります。
BERTの使い方 - 日本語pre-trained modelsをfine tuningして分類問題を解く
https://qiita.com/kenta1984/items/7f3a5d859a15b20657f3

```python:qiita.py

import torch
from transformers import BertJapaneseTokenizer, BertForMaskedLM

# Load pre-trained tokenizer
tokenizer = BertJapaneseTokenizer.from_pretrained('bert-base-japanese-whole-word-masking')

# Tokenize input
text = 'テレビでサッカーの試合を見る。'
tokenized_text = tokenizer.tokenize(text)
# ['テレビ', 'で', 'サッカー', 'の', '試合', 'を', '見る', '。']

# Mask a token that we will try to predict back with `BertForMaskedLM`
masked_index = 2
tokenized_text[masked_index] = '[MASK]'
# ['テレビ', 'で', '[MASK]', 'の', '試合', 'を', '見る', '。']

# Convert token to vocabulary indices
indexed_tokens = tokenizer.convert_tokens_to_ids(tokenized_text)
# [571, 12, 4, 5, 608, 11, 2867, 8]

# Convert inputs to PyTorch tensors
tokens_tensor = torch.tensor([indexed_tokens])
# tensor([[ 571,   12,    4,    5,  608,   11, 2867,    8]])

# Load pre-trained model
model = BertForMaskedLM.from_pretrained('bert-base-japanese-whole-word-masking')
model.eval()

# Predict
with torch.no_grad():
    outputs = model(tokens_tensor)
    predictions = outputs[0][0, masked_index].topk(5) # 予測結果の上位5件を抽出

# Show results
for i, index_t in enumerate(predictions.indices):
    index = index_t.item()
    token = tokenizer.convert_ids_to_tokens([index])[0]
    print(i, token)

````

他、こちら参考になります。
[BERT日本語モデルを使って、クリスマスプレゼントに欲しいものを推測してみた](https://www.cresco.co.jp/blog/entry/11517/)


#構成
BERTのモデルはBASEとLARGEの2種類があります。また、通常版とWhole Word Masking (WWM)版の2種類があります。BASEよりLARGEの方が精度は高いですが、学習コストがかかります。
[BERTのGitHub](https://github.com/google-research/bert)



【参考】
[BERT解説：自然言語処理のための最先端言語モデル](https://ainow.ai/2019/05/21/167211/#BERT)

[汎用言語表現モデルBERTを日本語で動かす(PyTorch)](https://qiita.com/Kosuke-Szk/items/4b74b5cce84f423b7125)

[日本語BERTで文章要約「要約マン」](https://medium.com/lsc-psd/%E6%97%A5%E6%9C%AC%E8%AA%9Ebert%E3%81%A7%E6%96%87%E7%AB%A0%E8%A6%81%E7%B4%84-%E8%A6%81%E7%B4%84%E3%83%9E%E3%83%B3-b5ce2f9f88c7)

[京都大学 大学院情報学研究科 知能情報学専攻 知能メディア講座 言語メディア分野（工学部電気電子工学科）/BERT日本語Pretrainedモデル](http://nlp.ist.i.kyoto-u.ac.jp/index.php?BERT%E6%97%A5%E6%9C%AC%E8%AA%9EPretrained%E3%83%A2%E3%83%87%E3%83%AB)
深層学習／行列積の誤差逆伝播

#1.はじめに
　行列積の誤差逆伝播が分かりにくかったので、まとめておく。

#2.スカラー積の誤差逆伝播
　スカラー積の誤差逆伝播から復習すると、
　![スクリーンショット 2020-03-29 15.41.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209705/aaff755d-2340-a6ac-ad21-e590c81d87db.png)
　勾配を行う対象をLとし、あらかじめ$\frac{\partial L}{\partial y}$が分かっているものとすると、連鎖律から
![スクリーンショット 2020-03-29 15.51.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209705/bee6f5ee-3e66-3d54-c417-c3a13a327a4a.png)
　これは問題ないですよね。

#3.行列積の誤差逆伝播
　ところが、行列積になると直感と変わって来ます。
![スクリーンショット 2020-03-29 16.04.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209705/f17acf9e-bc93-f195-ff82-0a4cfe20838f.png)

　なんか、ピンと来ませんよね。なので、具体的に確認します。
　設定は、2つのニューロンXと4つの重みWの内積を経てニューロンYに接続されていると考えます。
![スクリーンショット 2020-03-29 16.20.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209705/5dd58965-80e3-df1c-22d5-67c7edeb4407.png)
![スクリーンショット 2020-03-29 16.24.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209705/cdb1b164-f3ce-e90b-285f-d9d4291f42c8.png)
**1)最初に、$\frac{\partial L}{\partial X}$を求めます。**まず、これらを事前に計算しておきます。
![スクリーンショット 2020-03-29 16.30.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209705/9ce87c13-a8e8-aa3f-fbf8-de7125309798.png)
この計算を途中で利用しながら、
![スクリーンショット 2020-03-29 16.35.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209705/45ba6127-5bf3-710c-ca3a-d511c9ca7050.png)


**2)次に、$\frac{\partial L}{\partial y}$を求めます。**まず、これらを事前に計算しておきます。
![スクリーンショット 2020-03-29 16.44.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209705/a467f1be-1b7a-edc1-52be-0cf3e0f5640c.png)
この計算を途中で利用しながら、
![スクリーンショット 2020-03-29 16.46.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209705/e4ba2377-e47e-6701-99c4-e8701d30c143.png)

#4.行列積の順伝播、逆伝播のコード
 x1=X, x2=Y, grad=$\frac{\partial L}{\partial y}$とすると、

```python
class MatMul(object):
    def __init__(self, x1, x2):
        self.x1 = x1
        self.x2 = x2

    def forward(self):
        y = np.dot(self.x1, self.x2)
        self.y = y
        return y

    def backward(self, grad):
        grad_x1 = np.dot(grad, self.x2.T)
        grad_x2 = np.dot(self.x1.T, grad)
        return (grad_x1, grad_x2)
```
Xojo でコマンド実行した結果を受け取る

Xojo は

何から何までXojoで作るのはめんどくさい。
例えば すでにCUIがあるとして、それをみえるようにしよう。

# shell 呼び出し

基本の形
CUIに皮を被せられるので便利！

```

Dim Command as new Shell
Command.Execute("ls")
MsgBox(Command.Result)
```
# 時間のかかる処理を非同期で受け取る
 
## デスクトップアプリ

以下を配置する

- PushButton を配置し、 PushButton1 とする  
- Label を配置し、Label1 とする
- Shell を配置し、Shell1 とする


PushButton1  の Action に以下のように書く

```

Shell1.ExecuteMode = Shell.ExecuteModes.Asynchronous
Shell1.TimeOut = -1 // for Windows
Shell1.Execute("start /w notepad %USERPROFILE%\Documents\test.txt && type %USERPROFILE%\Documents\test.txt")
```
Shell1 の DataAvailable に以下のように書く

```

Label1.Text = Me.ReadAll()

```


このようにすると、ボタンを押すと notepad が起動し、保存するとコンテンツ内容が Label1 に反映される。

Xojo と notepad が非同期で動作する

ここの、

```

Shell1.Execute("start /w notepad %USERPROFILE%\Documents\test.txt && type %USERPROFILE%\Documents\test.txt")
```

は Windows10 用なのでほかの環境では適当に変更。

## Web アプリ

Desktop アプリと同様に動作する。

### Windows10

以下のコードはIDE上で動かしたら動作したが、CGIとして動かした場合、GUIアクセス権限などに依存するだろう。

```

Shell1.Execute("start /w notepad %USERPROFILE%\Documents\test.txt && type %USERPROFILE%\Documents\test.txt")
```
### RaspberryPi

以下のようなサンプルが動作した。

```

Shell1.Execute("sleep 5; date")

```
これは、5秒後の時刻を表示する。

```

Shell1.Execute("for i in {100..0}; do echo $i ;sleep 1; done")
```
これは、100 から 0 までカウントダウンする。ただし、UIの更新は3秒おきぐらいだった。


```

Shell1.Execute("while true; do date; sleep 10; done ")

```
10秒おきに時刻表示。



```

Shell1.Execute("python3 /home/pi/read_once_with_key_LCD_onlyID.py 4")

```
「RaspberryPi + ondryaso/pi-rc522 ライブラリで MyFare を操作する」
https://qiita.com/nanbuwks/items/9cbf05609974870e9088

ここで作った、MyFare カードのアクセスプログラム。 セクタ 4 の内容を表示。
eCognition Developerの使い方の概要（セグメンテーション編）

# eCognition Developerとは
Trimble社が提供する、画像分類をするためのGUIソフトウェアであり、高精度の分類ができるソフトウェアです。しかし、数十万円単位のライセンス料が必要なために個人で使うのは厳しく、私も大学院の研究で使っています。優れたソフトウェアですが、高額なライセンス料の問題からこのソフトウェアを使っている人は非常に少なく、日本語どころか英語の情報でさえも少ないのが実情です（2020年時点）。ということで基本的な使い方をマスターするのに難儀したので、いくつかの記事に分けて基本的な使い方を説明していきます。

#セグメンテーションとは
オブジェクトベースと呼ばれるタイプの画像分類をする際に使われる手法です。画像を色で分類する場合は色が近くて隣り合っているピクセルを同じグループとみなして画像全体をいくつかのグループに分けます。例えるなら、新学期の学校で席が近くて気が合う人同士でつるむような感じです。画像分類をする際にはそのグループごとに分類し、同じグループに属するピクセルは全て同じ分類にします。これまでの研究ではセグメンテーションをしてから分類することで、ピクセルごとに分類するよりも画像分類の精度が高い傾向にあります。


#バージョンと前提
 - eCognition Developer 9.5.1, Revision 1.0 (2019年12月版)
 - 各章の(p○○)というのは、公式文書のUserGuide.pdfの対応するページ数を指します
 - 本記事は公式文書の直訳ではなく、一部意訳や省略、追加等が入っています
 - ビューは上のアイコンでの１番（Load and Manage Data）を使用しています。右下などという場所を指している時はこのビュー画面での大まかな位置と考えてください
 - 法律の詳しいことは分かりませんが、著作権に抵触する恐れがあるため、スクショは入れません。ご了承ください

#セグメンテーションのやり方(p31)

①右上の「Process Tree」ウィンドウで右クリックして「Append New」を選択
→「Edit Process」ダイアログが表示されます
②「Edit Process」ダイアログの「Name」フィールドで好きな名前にして「OK」をクリック
→「Process Tree」ウィンドウに指定した名前が表示されます
③「Process Tree」ウィンドウ内の、②で指定した名前を右クリックして「Insert Child」を選択
→（①の操作時と同様の）「Edit Process」ダイアログが表示されます
④「Edit  Process」ダイアログの「Algorithm」で「Multiresolution Segmentation」を選択
⑤ダイアログボックスの右側の「Scale Parameter」（この数字が大きいほどセグメント１個が大きくなる）を変更して「Execute」を押して実行（その他設定変更は適宜） 
（しばらく時間がかかります。進捗状況は左下に表示されます）
※一連のプロセスで特定の結果を作成する場合は、③のように関連するルールを親プロセスにグループ化がおすすめです
※セグメンテーションの詳細は(p48)の多重解像度セグメンテーションを参照してください

次回は、（余白になっている背景がある場合のみ）背景の分離をしていきます。
【Ruby】外部ファイル読み込み require・require_relative・load・autoloadの違い

外部ファイル読み込みの違いを明確にしたかったのでまとめてみました。

## require("絶対パスまたは相対パス")
ライブラリや外部ファイルを絶対パス、相対パスで読み込む(1回のみ読み込み)

## require_relative("相対パス")
ライブラリや外部ファイルを相対パスで読み込む(1回のみ読み込み)
 
## load("絶対パスまたは相対パス")
ライブラリや外部ファイルをファイルを絶対パス、相対パスで読み込む(再読み込み、拡張子は省略できない)
 loadはrequireやrequire_relativeよりも再読み込みするため遅くなる
 
## autoload("クラス/モジュールの定数", "絶対パスまたは相対パス")
定数を最初に参照した時に第２引数を絶対パス、相対パスで読み込む(1回のみ読み込み)
クラス・モジュールの遅延ロードを実現

## まとめ
| モジュール関数       |パスの仕方                |読み込み回数    　　          |遅延ロード　　　　　　　        |
|:------------------|:---------------------|:--------------------|:------------------|
| require             |絶対・相対パス         |        1回           |✖︎|
| require_relative           | 相対パス|       1回             |✖︎|
| load             |絶対パス、相対パス            |        再読み込み        |✖︎|
| autoload              |絶対パス、相対パス           |         １回       |○|

参考
[Ruby 2.7.0 リファレンスマニュアル](https://docs.ruby-lang.org/ja/latest/method/Kernel/m/require.html)
【初心者向け】PHPマスター講座 vol.2（変数を学ぼう）

みなさんこんにちは！けいです

今回は「変数」について解説します！！

#【PHPマスター講座】変数とは

===========================
###▶︎変数とは何か🐼？

まず変数とは...
**データを一時的に保存する【箱みたいなもの】**です。

・変数はまず宣言を行い
・宣言した変数に対して値の代入する

基本的にはこの流れで進めていきます！

===========================

###▶︎変数を実践で学ぼう🐼(基礎編)

ただ…

変数の説明だけだと
正直イメージがしにくいです。

なので

実際に「**変数を使った計算式**」を見てみましょう！

【計算式】
`<?php $total = 100+200+300; ?>`
`合計金額は：<?php print($total); ?>円になります。`

このように変数名（$total）を使うと…

【表示結果】
合計金額は：600円になります。

上記のように結果を出力することができます。

===========================

###💡ポイント💡

・変数名はPHPだと必ず「$」をつける
**▶︎今回だと【$total】が変数名となります。**

・変数として使えるもの
**▶︎英単語、英語とアンダースコア「_」、日本語でつけることが可能。**
「$value」,「$value_kei」, 「$けい」

（最初だけ大文字・小文字・全部大文字は可能）
（一般的に変数は全て「小文字」で書く）

・変数として使えないもの
**▶︎記号・空白が含まれている・先頭を数字で始める、は使用不可**
「＄"#」,「$my　name」,「$123kkk」

・変数は最初に「代入」という操作を行う
**▶︎変数名を書いて「＝」を書いて「記憶しておきたい情報」を書く。**

実際に変数を使用することで

--------------------------

▶︎記入漏れ
▶︎書き間違い
▶︎同じ言葉や計算式を何度も書く

--------------------------

上記を**【未然に防ぐこと】**ができます！

===========================

###▶︎変数を実践で学ぼう🐼(応用編)

たとえば

あなたが「3つの商品」の

--------------------------

▶︎合計金額
▶︎税込金額
▶︎値引金額
▶︎セール後の金額

--------------------------

上記内容の情報を確認したい場合
PHPで変数をどのように使いますか？

3分だけ、じっくり考えてみてください！！

（下に参考例を書いていますが、まず考えてみましょう！）

…

……

………

さて、どうでしょうか？

わたしだったら

下記のように「PHPの変数」を使います。

--------------------------

**▶︎前提条件(変数の設定)**

<?php $total = 100+200+300; ?>

//3つの商品の合計金額を出力する変数名（$total）を定義

<?php $tax = 1.08; ?> 

//消費税の変数名（$tax）を定義

<?php $discount = 0.2?>

//値引金額の変数名（$discount）を定義

<?php $final_price = 0.8 ?>

//セール後最終金額の変数名（$final_price）を定義

--------------------------

**▶︎文字列と計算式**
合計金額は：<?php print(＄total); ?>円になります。

税込金額は：<?php print(＄total*＄tax); ?>円になります。

値引金額（税込）は：<?php print(＄total*＄tax*＄discount); ?>円になります。

セール後最終金額（税込）は：<?php print(＄total*＄tax*＄final_price); ?>円になります。

--------------------------

**▶︎【表示結果】**
合計金額は：600円になります。
税込金額は：648円になります。
**値引金額（税込）は：129.6円になります。**
**セール後最終金額（税込）は：518.4円になります。**

※ただし、太字にした箇所が「小数点」になっていて変なので「小数点の対応」が必要になります。

--------------------------

###💡ポイント💡
「小数点の対応方法」
▶︎小数点切り捨て：「floor」
▶︎小数点切り上げ：「ceil」
▶︎小数点四捨五入：「round」

--------------------------

**▶︎文字列と計算式(小数点の対応)**

値引金額（税込）は：<?php print **ceil**(＄total*＄tax*＄discount); ?>円になります。

セール後最終金額（税込）は：<?php print **ceil**(＄total*＄tax*＄final_price); ?>円になります。

--------------------------

**▶︎【表示結果】**
**値引金額（税込）は：130円になります。**
**セール後最終金額（税込）は：519円になります。**

--------------------------

===========================

さて、今回のPHPマスター講座 vol2（変数を学ぼう）はここまでとなります！

少しでもあなたのPHP学習のお役に立てれば幸いです😌
識別子における命名規則の種類について

## はじめに
コーディングやgitのブランチ名を決める際，命名規則としてどのようなルールがあるのか気になったので備忘録としてまとめました．

## 識別子の命名規則
使いそうな規則を書いておきます．(1)(2)

| 種類 |例示  |使い道|
|---|---|---|
|Lower Snake Case | ```akane_kotonoha```|pythonの変数とか|
|Upper Snake Case (Constant Case) |```AKANE_KOTONOHA``` |定数定義|
|Lower Camel Case|```akaneKotonoha```|swiftの変数とか|
|Upper Camel Case|```AkaneKotonoha```|クラス定義でよく見る|
|Kebab Case|```akane-kotonoha```| gitのブランチ名でよく見る|
|Lower Case|```akane```|短い変数名とか|
|Upper Case|```AKANE```|短い定数とか|

他にもありましたがとりあえずこの辺りが知りたかった．

## さいごに
命名規則って大事なんだけどよく蔑ろにするので注意せねば・・・

## 参考資料
(1) [wmaurer/vscode-change-case](https://github.com/wmaurer/vscode-change-case#commands)
(2) [変数や関数などの識別子の命名規則の種類について](https://www.tmp1024.com/articles/naming-convention)
【Rails】SQliteでのDBの内容確認周りのコマンドまとめ（追加していく所存）

# 【Rails】SQliteでのDBの内容確認周りのコマンド

## モデルのカラム数の確認

```:terminal
>rails console

>モデル名.new
```
↓こんな感じ
ちゃんとカラム作れてるかとかの確認に良きです
<img width="552" alt="スクリーンショット 2020-03-29 14.11.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411851/cf0f5cfe-7734-78b8-0346-db53dc0423c9.png">

## モデルの内容確認（全ては見れません）

```:terminal
> rails console

> モデル名.all
```
↓こんな感じ
<img width="1438" alt="スクリーンショット 2020-03-29 14.15.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411851/626fb175-8116-5b89-e22c-bdbf8abe784e.png">

## モデルの特定のidをもつデータのもつ内容の確認

```:terminal
> rails console

> モデル名.find(特定のid)
```
↓こんな感じ
<img width="870" alt="スクリーンショット 2020-03-29 16.16.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411851/a006dab0-22fc-c4fb-c7b6-e5047d152c9c.png">

## モデルの特定のカラム内容をもつ行の確認

```:terminal
> rails console

> モデル名.find_by(カラム名: "文字列や数字")
```
↓こんな感じ
<img width="854" alt="スクリーンショット 2020-03-29 17.22.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411851/6f12c967-3a80-d249-4414-237de9369063.png">


## 投稿の数やユーザーの数の確認

```:terminal
> rails console

> モデル名.select("調べたいカラム名").count
```

例えば、Userモデルに登録されているユーザーの数を知りたいとき

```:terminal
> rails c

> User.select("id").count

この結果
irb(main):007:0> User.select("id").count
   (1.5ms)  SELECT COUNT("users"."id") FROM "users"
=> 1
↑ユーザーの数が1だとわかる
```

例えば、Postモデルに登録されている投稿の数を知りたいとき

```:terminal
> rails c

> Post.select("id").count

この結果
irb(main):007:0> User.select("id").count
   (1.5ms)  SELECT COUNT("posts"."id") FROM "users"
=> 27
↑ユーザーの数が1だとわかる
```
[Heroku] ワイルドカードのサブドメインでSSL化にする方法


2020年3月29日 作成

# ワイルドカードでSSL化にする方法

こんにちは、ITエンジニアの田中です！
今回は、少しディープな内容ですが、Herokuでワイルドカードのサブドメインに対してSSL化する方法です。

具体的な事例を元に説明します。
anysalon.workというドメインでSSL化すると下記のサブドメインを全てSSLかできます。

```
sample.anysalon.work
test.anysalon.work
xxx.anysalon.work
```

下記のURLで正しくSSL認証されます。

```
https://sample.anysalon.work
https://test.anysalon.work
https://xxx.anysalon.work
```

想定しているケースとしては、ユーザがサブドメインを登録できるようなマルチテナント サイトを運営していることを想定しています。
Slackみたいにユーザがワークスペースを作るとサブドメインが増えていくようなサイトを作りたいですよね？
そんな開発者向けに作った記事です。

## 前提条件

下記がこの記事の内容を実行するための前提条件です。

- 独自ドメインを購入している
- HerokuでHobby以上のプランに加入している

独自ドメインのネームサーバーの設定は、
下記のURLを参照してください。
https://qiita.com/matcham/items/c0dbe7310f8d4d1dfa00

## なぜこの記事が必要なのか？

Herokuでは、Automatic Certificate Management (ACM)を使うと、
簡単にサイトをSSL化できます。しかし、2020年3月29日時点では、ワイルドカードでのドメインをHerokuで登録できません。
そのため、Let's Encryptにて追加料金無料にてワイルドカードのドメインをHerokuに登録しましょう。

https://letsencrypt.org/ja/

## 全体の流れ

1. HerokuでのSSL設定を自動から手動に変更
2. Herokuでワイルドカードのドメインを登録
3. Let's Encrypt ワイルドカード証明書
4. HerokuでTXTを登録
5. Heroku SSL認証をuploadする

## HerokuのSSLを手動設定に変更する

HerokuでのSSL設定を自動から手動に変更します。

1. Herokuにアクセスしてログインします。
https://jp.heroku.com/
2. ダッシュボードから対象のアプリケーションを選択します。
3. Settingsを選択します。
4. Configure SSLを選択し、Manual Certificateを選択します。

## Herokuにて、ドメイン設定

heroku domains:addコマンドによりドメインを追加します。
私の場合は、下記のドメインを登録しました。
- ワイルドカードのドメイン
- サブドメインなしのドメイン
- wwwのドメイン

私の場合の例を下記に記述します。

```
> heroku domains:add *.anysalon.work --app アプリ名
> heroku domains:add anysalon.work --app アプリ名
> heroku domains:add www.anysalon.work　--app アプリ名
```

## Let's Encrypt ワイルドカード証明書

Let's Encrypt ワイルドカード証明書の方法としては、下記の記事を参照してください。
私の場合は、docker上のコンテナでcertbotをインストールしてワイルドカード証明書を発行しました。
https://blog.apar.jp/web/9619/

１点補足があります。
下記のメッセージが出力されるところまで行きましたら、
そのままEnterを押さずにHerokuに戻りTXTレコードを追加する必要があります。

```
-------------------------------------------------------------------------------
Please deploy a DNS TXT record under the name
_acme-challenge.example.com with the following value:
 
sg5c_j37WuxggEnX9mriWvR3IBf_vhBZuOxGGIcTtxk
 
Before continuing, verify the record is deployed.
-------------------------------------------------------------------------------
Press Enter to Continue
```

TXTレコードを追加方法

1. Herokuにアクセスしてログインします。
https://jp.heroku.com/
2. ダッシュボードから対象のアプリケーションを選択します。
3. Resourcesを選択します。
4. PointDNSを選択します。
5. My domainsにて、ご自分の設定したドメインを選択します。
6. Add recordよりnew zone recordを追加します。

Record Type = TXT
Name = _acme-challenge.anysalon.work
Text = 上記のコマンドライン上に表示された30桁ぐらいの文字列

Herokuにて、TXTコードを登録したら、先ほどのコマンドプロンプトに戻りEnterを押し進めてください。
Congratulationsが表示されたら、設定完了です！

## HerokuにSSL証明書をuploadする

下記のコマンドでHerokuにSSL証明書をuploadしてください。

```
sudo heroku certs:add [証明書＋中間CA証明書のファイルパス] [秘密鍵のファイルパス] --app [アプリ名]
```

## テスト

下記のコマンドを実行しSSL certificate verify okと表示されば、成功です。なお、反映には1時間暗い時間がかかる可能性はあります。

```
curl -vI https://www.example.com
```

## 課題

Let's Encryptの証明書は3ヶ月毎に更新する必要があります。
今回は手動で実行したのですが、3ヶ月毎に手動は手間をとるので、
自動化したほうが良いと思っています。

自動化は次回説明します！

## 終わりに

分かりにくいポイントがあればコメントください。
私自身たくさんの記事を読んでやっと設定できました。
その経験を元に書いたので絶対あなたも設定できます。

参考になれば、フォローお願いします！
ServerlessFrameworkでdotenvを使う

## 概要

- 環境ごとに変更する値やgitのリポジトリに含めたくない値はdotenvを使って環境変数で設定することが多いと思います
- ServerlessFrameworkを使ってymlで設定する値にもdotenvで値を設定したくなりました
- [serverless-dotenv-plugin](https://github.com/colynb/serverless-dotenv-plugin)を使うと`.env`で設定した値を`serverless.yml`から読み込めるようになります

## 使い方

- インストール

```sh
yarn add -D serverless-dotenv-plugin
```

- `.env`に環境変数を設定します

```config:.env
ACCESS_TOKEN=abcde12345
```

- `serverless.yml`に設定を追加します
    - `plugins`に`serverless-dotenv-plugin`追加
    - `${env:XXX}`の形式で`.env`で設定した値を取得できます

```yml:serverless.yml
service: sample
provider:
  name: aws
  runtime: nodejs12.x
  environment:
    # .envから値を取得してセットしている
    ACCESS_TOKEN: ${env:ACCESS_TOKEN}
plugins:
  # pluginsにserverless-dotenv-pluginを追加
  - serverless-dotenv-plugin
# ...他の設定
```

- このように設定することで例えばLambdaを定義しているJSから`ACCESS_TOKEN`を取得することができます

```js:handler.js
const ACCESS_TOKEN = process.env.ACCESS_TOKEN;
console.log(ACCESS_TOKEN); // abcde12345
```
jetson nano とmomoでWebRTCで送信するときにマイクの代わりに音声ファイルを使用する


** 2022/05/13 新しい記事を書いたのでこちらを参照してください。
https://zenn.dev/tetsu_koba/articles/d931a843f16a4c

** 以降は古い記事。

以前に書いた[ラズパイ+momoでWebRTCで送信するときにマイクの代わりに音声ファイルを使用する](https://qiita.com/tetsu_koba/items/b887c1a0be9f26b795f2) と同じことをjetson nano でもやってみました。

## オーディオループバックのカーネルモジュールのビルド

なんと、jetson nano のカーネルではオーディオループバックのカーネルモジュール(snd-aloop.ko)が標準では入っていません。
そこで自分でこれをビルドします。

ビルドの手順は以下のページの手順にそってやって問題なくできました。
https://developer.ridgerun.com/wiki/index.php?title=Jetson_Nano/Development/Building_the_Kernel_from_Source

私がやったときの手順をここに残します。
Jetson nano のリリースは 32.3.1 でした。

```
wget http://releases.linaro.org/components/toolchain/binaries/7.3-2018.05/aarch64-linux-gnu/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu.tar.xz
sudo tar xf gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu.tar.xz -C /usr/local

wget https://developer.nvidia.com/embedded/dlc/r32-3-1_Release_v1.0/Sources/T210/public_sources.tbz2
tar xvf public_sources.tbz2 
cd Linux_for_Tegra/source/public/

JETSON_NANO_KERNEL_SOURCE=$(pwd)
tar xf kernel_src.tbz2 
vi env.sh
```

```env.sh
JETSON_NANO_KERNEL_SOURCE=$(pwd)
TOOLCHAIN_PREFIX=/usr/local/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
TEGRA_KERNEL_OUT=$JETSON_NANO_KERNEL_SOURCE/build
KERNEL_MODULES_OUT=$JETSON_NANO_KERNEL_SOURCE/modules
```

```
. env.sh 
make -C kernel/kernel-4.9/ ARCH=arm64 O=$TEGRA_KERNEL_OUT LOCALVERSION=-tegra CROSS_COMPILE=${TOOLCHAIN_PREFIX} tegra_defconfig
make -C kernel/kernel-4.9/ ARCH=arm64 O=$TEGRA_KERNEL_OUT LOCALVERSION=-tegra CROSS_COMPILE=${TOOLCHAIN_PREFIX} menuconfig
```
ここでオーデォオループバックデバイスをモジュールでビルドするように指定します。

```
Device Drivers  ---> 
 <*> Sound card support  ---> 
     <*>   Advanced Linux Sound Architecture  --->   
           [*]   Generic sound devices  --->   
                 <M>   Generic loopback driver (PCM)   
```

module をビルドします、

```
make -C kernel/kernel-4.9/ ARCH=arm64 O=$TEGRA_KERNEL_OUT LOCALVERSION=-tegra CROSS_COMPILE=${TOOLCHAIN_PREFIX} -j2 --output-sync=target modules
```

```
cp build/sound/drivers/snd-aloop.ko .
```

必要なのはこのファイルひとつだけです。これをjetson nano に持っていきます。
面倒ですが、jetson nanoのカーネルのバージョンが上がるたびに同様の作業が必要になります。
snd-aloop.ko も標準で入れてくれないかなあ。

## オーディオループバックのカーネルモジュールのロード

jetson nano で

```
sudo insmod snd-aloop.ko pcm_substreams=2
```
これで特にエラーメッセージがでなければOK。
念のために `sudo lsmod |grep aloop` でこのモジュールが入っていることを確認します。


## pulseaudio を無効にする

ALSAを直接使いたいので、pulseaudio を無効にします。
このページの手順でできました。
https://kodi.wiki/view/PulseAudio/HOW-TO:_Disable_PulseAudio_and_use_ALSA_(without_removing_PulseAudio)_for_Ubuntu

以降はこのページの手順でいけます。
[ラズパイ+momoでWebRTCで送信するときにマイクの代わりに音声ファイルを使用する](https://qiita.com/tetsu_koba/items/b887c1a0be9f26b795f2)
Macでアカウント名変更したらpipやipythonが使えなくなったので、pythonごと再インストールしたら治った

#概要
macのアカウント名を変更したらpyenvでインストールしたpipやipythonが使えなくなったので、pythonを再インストールしたら使えるようになりました。
#環境
macOS Catalina 10.15.4
Homebrew 2.2.11
pyenv 1.2.17
python 3.8.0
#経緯
macにbrewを使ってpyenvをインストールし、そのpyenvでpythonをインストールして使っていました。
そのあと諸事情でmacのアカウント名（とホームディレクトリ名）を変更しました。アカウント名の変更方法は[公式の説明](https://support.apple.com/ja-jp/HT201548)に従いました。
変更自体はうまくできたのですが、pipやipythonを実行するときに下記のエラーが出て使えなくなってしまいました。

```
>> ipython
/usr/local/Cellar/pyenv/1.2.17/pyenv.d/exec/pip-rehash/pip: /Users/[new home directory name]/.pyenv/versions/3.8.0/bin/pip: /Users/[old home directory name]/.pyenv/versions/3.8.0/bin/python3.8: bad interpreter: No such file or directory
```
古いホームディレクトリ名のpythonを探しに行って見つからないと怒られているようです。
どこかに古い設定が残っているのだと思いますが、"/Users/[old home directory name]/.pyenv/versions/3.8.0/bin/python3.8"がどこで定義されているのかよく分からなかったので、諦めてpyenvでpython 3.8.0を再インストールしたら治りました。

```
pyenv uninstall 3.8.0
pyenv install 3.8.0
```
LPIC-1を受けてみた感想。「おすすめ度・難易度・勉強時間」

## LPIC-1を受けてみた
私は受託開発のベンチャー企業で約1年実務を経験しています。技術力と知識量を上げるため、LPIC-1を受けてみました。なので、資格で合格することが目的ではなく、**資格を受ける上で学習で得られる知識が目的**でした。試験に合格したので、そこで得られた情報を共有します。

**この記事はこんな方におすすめ**

- LPICが実務に役立つのか知りたい
- おすすめ度・難易度が知りたい
- 学習時間やおすすめの学習教材が知りたい

## 実務で役立つのか？

僕は結構**役立ち**ました。以前はLinuxのことをよくわからずにその場しのぎで使用していたのですが、LPICで学習したことで体系的に知識が身につきました。
ただし、資格は手段なので別に受けなくても問題ありません。僕の場合は、明確な目標がないと学習しないのでLPICを活用しました。

## 試験概要

- Linux技術者認定試験で、Linux技術者としての技術力を認定するIT資格
- 国際的に認められたIT資格
- 試験会場は全国(各国)
- 対象試験:101試験/102試験（5年以内に両方取得する必要あり）
- 受験料金：15,000円(合計30,000円)
- 回答方法：コンピュータを使った選択式
- 試験時間：90分
- 合格ライン：65～75%程度

## 試験項目

■101
- システムアーキテクチャ
- Linuxのインストールとパッケージ管理
- GNUとUnixのコマンド
- デバイス、Linuxファイルシステム、ファイルシステム階層標準

■102
- シェル、スクリプト、およびデータ管理
- インターフェイスとデスクトップ
- 管理タスク業務
- 必須システムサービス
- ネットワーキングの基礎
- セキュリティ

## おすすめ度・難易度


| 項目 |評価（5段階） |
|---|---|
| おすすめ度 | 3 |
| 難易度    | 3 |

例えば基本情報処理試験を目安にすると、おすすめ度3、難易度3といった具合ですね。なので、基本情報処理試験に同じくらいですね。

## 学習時間、おすすめの学習教材

学習時間は完全未経験なら150時間、Linuxを触っている方なら50時間くらいだと思います。
おすすめの学習方法は、あずき本と呼ばれる教科書の[Linux教科書](https://www.amazon.co.jp/dp/4798160490/ref=cm_sw_em_r_mt_dp_U_BpeGEbSXNDGBK)とWeb版問題集[Ping-t](https://ping-t.com/)を交互にやれば、費用も安くておすすめです。過去問は本だと問題数が限られるので、Webサイトがおすすめですね。あとは、手を動かした方が知識が定着するので、環境構築して実際に動かしたいですね。環境構築は、ドットインストールの[レッスン](https://dotinstall.com/lessons/basic_localdev_mac_v2)通りにやれば簡単に構築できます。
[Linux教科書](https://www.amazon.co.jp/dp/4798160490/ref=cm_sw_em_r_mt_dp_U_BpeGEbSXNDGBK)が難しくて訳わかんない方は、[1週間でLPICの基礎が学べる本](https://www.amazon.co.jp/dp/429500636X/ref=cm_sw_em_r_mt_dp_U_2reGEbVCQXX4G)が読むとだいぶ理解が進みますよ。

## LPICついてのまとめ

LPICの費用は高いですが、時間とお金を投資できるなら、体系的な知識を得られるのでおすすめです。ちなみにPing-tが申し込むと1,000円安くなるので、合計2,000円お得ですね。

## 参考サイト

- [LPICとはどんな資格？難易度から勉強方法までまとめました](https://proengineer.internous.co.jp/content/columnfeature/3241#section100)
CNNの良さを検証してみる

##### CNNが普通のニューラルネットワークよりも性能が良いか検証をしてみる
##### 題材はMNIST

# まず、普通のニューラルネットワーク

```
from keras.datasets import mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

from keras import models
from keras import layers

network = models.Sequential()
network.add(layers.Dense(512, activation='relu', input_shape=(28 * 28,)))
network.add(layers.Dense(10, activation='softmax'))

network.compile(optimizer='rmsprop',
                loss='categorical_crossentropy',
                metrics=['accuracy'])

train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype('float32') / 255

test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype('float32') / 255

from keras.utils import to_categorical

train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)

network.fit(train_images, train_labels, epochs=5, batch_size=128)

test_loss, test_acc = network.evaluate(test_images, test_labels)

print('test_acc:', test_acc)

#test_acc: 0.9801999926567078
```

0.98くらい。


# CNNで同じことをやってみる

## まずデータの前処理

```
from keras.datasets import mnist
from keras.utils import to_categorical

(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

train_images = train_images.reshape((60000, 28, 28, 1))
train_images = train_images.astype('float32') / 255

test_images = test_images.reshape((10000, 28, 28, 1))
test_images = test_images.astype('float32') / 255

train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)
```

## モデルの構築

```
from keras import layers
from keras import models

model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))

model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))
```

- Conv2D(output_depth, (window_height, window_width))
- output_depth:フィルターの数
- window_height:フィルター高さ
- window_width:フィルター幅
- MaxPooling2D:ダウンサンプリング層(この例の場合は2x2の中で最大の値を採用する)

## コンパイルと学習

```
model.compile(optimizer='rmsprop',
              loss='categorical_crossentropy',
              metrics=['accuracy'])
model.fit(train_images, train_labels, epochs=5, batch_size=64)
```

## 評価

```
test_loss, test_acc = model.evaluate(test_images, test_labels)
print(test_acc)
#0.987500011920929
```
一概にはなんとも言えないけどまあこんな値
【ECCUBE4】管理メンバーがそれぞれ設定した商品タグしか管理画面に表示されないようにする。【マーケットプレイス化】

# 目的
マーケットプレイス型ECのように、管理メンバーごとの商品管理・受注管理をできるようにカスタマイズしていきます。
主にカスタマイズする場所は下記です。
・商品管理
・受注管理

---

# 方針
メンバーに割り当てられているcreator_idを活用します。

---

# 今回すること
・管理メンバー毎にそれぞれ設定した商品タグしか表示されないようにします。

---

# 管理メンバーがそれぞれ設定した商品タグしか表示されないようにします。

---

tagにcreator_idを付与

```app/Customize/Entity/TagTrait.php
<?php

namespace Customize\Entity;

use Doctrine\ORM\Mapping as ORM;
use Eccube\Annotation\EntityExtension;

/**
  * @EntityExtension("Eccube\Entity\Tag")
 */
trait TagTrait
{
    /**
     *  @ORM\Column(type="string", nullable=true)
     */
    public $creator_id;

}
```

---

・タグ保存時にcreator_idを付与
・タグ取得時はcreator_idが一致するもののみ取得

```app/Customize/Repository/CreatorTagRepository.php
+use Eccube\Entity\AbstractEntity;
+use Eccube\Repository\AbstractRepository;
+use Eccube\Entity\Member;
+use Eccube\Entity\Master\Authority;
+use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;

class TagRepository extends AbstractRepository
  {
-    public function __construct(RegistryInterface $registry)
-    {
+
+    /**
+     * @var TokenStorageInterface
+     */
+    protected $tokenStorage;
+
+    /**
+     * TagRepository constructor.
+     *
+     * @param RegistryInterface $registry
+     * @param TokenStorageInterface $tokenStorage
+     * @param AuthorizationCheckerInterface $authorizationChecker
+     */
+    public function __construct(
+        RegistryInterface $registry,
+        TokenStorageInterface $tokenStorage
+    ) {
         parent::__construct($registry, Tag::class);
+        $this->tokenStorage = $tokenStorage;
     }

・・・
・・・

+        if (null !== $token = $this->tokenStorage->getToken()) {
+            if($token->getUser()->getAuthority()->getId() != Authority::ADMIN) {
+                $tag->creator_id = $token->getUser()->getCreator()->getId();
+            }
+        }
         $em = $this->getEntityManager();
         $em->persist($tag);
         $em->flush($tag);

・・・
・・・

     public function getList()
     {
-        $qb = $this->createQueryBuilder('t')->orderBy('t.sort_no', 'DESC');

-        return $qb->getQuery()->getResult();
+         $qb = $this->createQueryBuilder('t');
+
+         if (null !== $token = $this->tokenStorage->getToken()) {
+             if($token->getUser() instanceof Member) {
+                 if($token->getUser()->getAuthority()->getId() != Authority::ADMIN) {
+                     $qb = $qb
+                         ->andWhere('t.creator_id = :creator_id')
+                         ->setParameter('creator_id', $token->getUser()->getCreator()->getId())
+                         ->orderBy('t.sort_no', 'ASC');
+                 }
+             }
+         }
+
+         return $qb->getQuery()->getResult();
     }

```

---

# 宣伝
ハンドメイド猫グッズ専門ショップを運営しています。
ネコ好きの方、親しい間柄にネコ好きがいらっしゃる方、ぜひご覧ください。
■キャットギフト
https://cat-gift.net/
なぜかパッケージマネージャーエラーが起きてしまった【unity2018.4.x LTS】

同一端末で、不特定多数のプロジェクトが作られており、
不定期に2018.4.x LTSのアップデートが行われた際に起きると思います。
(しかも各バージョンでアドオンが変わっていたときとか)

この記事では、
取り急ぎでできる、簡単な対処の仕方を記載します。

---

[window]メニュー内にあるPackagesウィンドウを押下すると、
下図のようにウィンドウが開かれる。

![a03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/b5f411bd-b790-5a35-577f-786cd4e83566.png)


---

要は、**「エラーを起こしているパッケージをremoveしようぜ!」ということです。**

---

Packagesウィンドウに表示されているパッケージは、
プロジェクトフォルダの[Packages]フォルダにmanifest.jsonファイルで保存されています。

プロジェクト起動時に、このファイルを参照してパッケージがインストールされるので、
もしエラーを起こしているパッケージをremoveする際は、
manifest.jsonファイル内のテキストを別途テキストエディタなどに控えておくと良いです。
(removeした瞬間に、manifest.jsonファイルも書き換わるため)
【Python】for文の使い方の整理

#1.はじめに

私のプログラミングは、MATLABがベースであります。
Pythonを始めたとき、**For文の使い方**がMATLABと大きく異なったため、大変な時期がありました。
今日は、PythonのFor文の使い方を整理します。

#1.1.MatlabでのFor文

>形式
for 変数=初期値:増分:最終値
    statements
end

必ずfor変数を宣言して、その初期値：最終値を入れる必要があります。

```matlab
x = ones(1,10);

for n=2:6 
    x(n) = 2 * x(n-1);
end
```

#2.PythonでのFor文
>形式
for 変数 in リスト（or Tuple, Dictionary等):
    statements

Matlabのように、**変数の初期値：最終値を宣言するのではなく、リストを宣言する**ことに注意しましょう。この部分の概念が大きく異なります。

##2.1.典型的なFor文
リストを作成し、その要素をprintする。

```Python
test_list = ['one','two','three']
for i in test_list: #<-one, two, threeを順序にiに代入する。
  print(i)
```
Result
>
>one
two
three

##2.2.多様なFor文
リストの要素がTupleの場合、

```Python
a = [(1,2),(3,4),(5,6)]

for (first, last) in a:
  print('first element:', first)
  print('last element :', last)
  print('sum of first and last element =', first + last)
```
Result
>first element: 1
last element : 2
sum of first and last element = 3
first element: 3
last element : 4
sum of first and last element = 7
first element: 5
last element : 6
sum of first and last element = 11


##2.3.応用

5名の学生のテストを受けたとします。テストスコアが60点を超えた場合は、合格とします。そうでない場合は、不合格とします。テストスコアによって合格・不合格を表示するプログラムを作成します。

```Python

score = [90,25,67,45,80]　#テストスコア

number = 0 #学生に付ける番号
for mark in score: #<- 90,25,67,45,80を順序にmarkに代入する。
  number = number + 1
  if mark >= 60:
    print("{:d} 番目の学生は合格です。".format(number))
  else:
    print("{:d} 番目の学生は不合格です。".format(number))
```
Result
>1 番目の学生は合格です。
2 番目の学生は不合格です。
3 番目の学生は合格です。
4 番目の学生は不合格です。
5 番目の学生は合格です。


##2.4.よく使うrange()
for文は数字リストを自動に作るrangeという関数とともに使われることが多いです。

```Python
ar = range(1,11) %<- 1,2,3,4,5,6,7,8,9,10
```
range()で作られたarは、**リストではなくrangeオブジェクトである**ことに注意しましょう。

```Python
type(ar)
```
Result
>range

それでは、for文とrange()を使い、1から10までの和を求めるコードを作成します。

```Python
sum = 0
for i in range(1,11):
  sum = sum + i

print(sum)
```
Result
>55

先ほどの60点以上の場合、合格という文章を出力するコードは、下記のように書き換えられます。

```Python
score = [90,25,67,45,80]

for number in range(len(score)):
  if score[number] >= 60:
    print("{:d} 番目の学生は合格です。".format(number))
  else:
    print("{:d} 番目の学生は不合格です。".format(number))
```
Result
>0 番目の学生は合格です。
1 番目の学生は不合格です。
2 番目の学生は合格です。
3 番目の学生は不合格です。
4 番目の学生は合格です。

##2.5.リストの中にfor文を入れる
aというリストを作成し、各要素を3倍した結果をresultというリストに格納するコードです。

```Python
a = [1,2,3,4]
result = []
for yoso in a:
  result.append(yoso*3)

print(result)
```
Result
>[3, 6, 9, 12]


これを、リストの中にfor文を入れる方法を使うことで、次のように簡略なコードにすることが可能です。

```Python
a = [1,2,3,4]
result = [num * 3 for num in a]
```
Result
>[3, 6, 9, 12]

もし、偶数だけに3倍した場合、次のようにif文を追加すればいいです。

```Python
a = [1,2,3,4]
result = [num * 3 for num in a if num%2 ==0]
```
Result
>[6, 12]

#3.まとめ
Pythonのfor文の多様な使い方を整理してみました。奥が深いですね。