OmniAICreator/Qiita-1.07M huggingface dataset:
簡単にできるgit導入からdocker起動まで python編

# これは何?
作業を忘れる俺のための備忘録
pycharmからgitを操作する予定
これをやれば自分のパソコンを汚さず作業ができるようになる

だからやれ
とにかくやれ
# git導入
gitはいろいろと便利だから使えるようになってるといいね

## 1.インストール
まずは、以下のサイトからGitをダウンロード
https://git-for-windows.github.io/

あとは道なりに進めばインスト―ル完了
詳しい道のりは説明がめんどくさいから調べて

## 2.ユーザ名とメールアドレスの登録
コンソールで
`$ git config --global user.name "ユーザー名"`
`$ git config --global user.email "メールアドレス"`
を打ち込むと登録が完了する
# github側の作業
githubのアカウントを作成し、githubのホームページへ行き右上の"+"からnew repositoryでリポジトリを作成する
Repository nameで名前を決める
publicかprivateか決めてcreate repositoryをクリック

すると画面に意味深なurlが出てくるからそれをコピーしてターミナルへ

<img width="938" alt="image.png (51.7 kB)" src="https://img.esa.io/uploads/production/attachments/10037/2021/01/05/90543/90d86ef4-d3d7-4933-915c-947dd6a29821.png">

Codeからでもurlを発行できるからcloneしたときとかはここからやろう

gitのプロジェクトを置きたいディレクトリに移動をして`git clone <url>`
こうすることでgitと繋がったディレクトリができるのでpycharmでもなんでも開く

## .gitignoreの作成
ディレクトリは完成したがこのままではなんでもgithubで共有されるので`.gitignore`を作る
ディレクトリ直下に`.gitignore`って名前のファイルを作る

https://github.com/github/gitignore/blob/master/Global/JetBrains.gitignore
JetBeain系列のIDEを使ってるなら上のソースコードをコピペする
他のIDEは知らん

共有したくないファイルのパスをここに追記する
これでメモなどの他人と共有したくないファイルがgit側に共有されなくなる

# Docker側の作業
github側の作業が終わったら次はdockerの作業

## インストール
これにDocker for desktopのインストールからpycharm連携まですべてが詰まってる
https://qiita.com/Denpa_Ghost/items/caeddaa29bd9d7514cce

## docker-compose.ymlの作成
ディレクトリ直下にdocker-conpose.ymlを作って以下をコピペする

 ```docker-compose.yml
 version: '3'
services:
  app:
    build: docker/python
    tty: true
    volumes:
    - ./app/:/app
    working_dir: /app
 ```

`build:`がdockerfileの格納先の指定

`tty:`が起動後待機状態にするか
falseや未記入で動いてるものがないとすぐに落ちるため必須

`volumes:`がホスト機のフォルダとコンテナ内のフォルダをつなげる役割を持つ
左がホスト機、右がコンテナ内
ホスト側でフォルダがない場合新規に作成される

`working_dir:`はデフォルトの作業場の指定

## dockerfileの作成
docker-compose.ymlを作ったら`build:`で指定したパスにdockerfileを作る
slackのbotを動かすなら以下をコピペする

```dockerfile:dockerfile
FROM python:latest
RUN mkdir -p /app
RUN pip install slackbot
```

`FROM`はdocker imageを設定する
`RUN`はコンテナ生成後に入力するコマンドを入れる
docker imageに入ってない他のパッケージを入れたい場合などに使うといい

上記のならコンテナ生成後、appディレクトリを作成してslackbotのパッケージをインストールをする
主にlinuxのターミナルでできることならなんでもできる

## コンテナの生成
ここまで来たらあとはコンテナを作るだけ
docker-compose.ymlがあるディレクトリ内で
`docker-compose up --build -d`
をすることでコンテナを生成できる

初回起動
`docker-compose up --build -d`

次回以降
`docker-compose up -d`
コンテナをまとめて止める
`docker-copose stop`

コンテナをまとめて消す
`docker-compose down`

コンテナとイメージをまとめて消す
`docker-compose down --rmi`

## .pyの実行
プログラム作った実行したいときは
`docker ps`で実行したいコンテナのnameをコピーして
`docker exec -it <name> bash`
でコンテナ内のターミナルへアクセスできる
あとは普通に`python main.py`などでpythonの実行をする

ターミナルへアクセスせずに実行をしたい場合は
`docker exec -it <name> <プログラム名>`
でターミナルへ入らずに実行ができる

# 終わりに
質問や文句があるなら荒川までお願いします
対応したりしなかったりします

これで快適python生活を楽しもう！
AWS Session Manager SSH接続時に俺の考えた最高の名前でつなぐためのメモ

俺です。
AWS EC2使うにあたって踏み台潰さないと2021年はじめられないけどインスタンスIDで接続するの辛いなあと思ったのでメモを残します。

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-getting-started-enable-ssh-connections.html

# ~/.ssh/config

```
Host 最高-prod-app
    Hostname i-0123456789ABCDEF
Host 最高-prod-*
    User ec2-user
    IdentityFile ~/.ssh/saikou.pem
    ProxyCommand sh -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"
```

# いざssh

```
❯ ssh 最高-prod-app

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
[ec2-user@ip-XX-XX-XX-XX ~]$
```

最高。
cmakeのinstallについて


CMakeのバージョンが古かったので更新して詰まった際のメモ

(「[Ubuntu に cmake を install する。](https://qiita.com/YutakakINJO/items/69f01d2abfb958ada88b)」 を参考にさせていただきました．)

## すでにあるcmakeを消す

```sh
sudo apt remove cmake
```

## 最新のcmakeを落とす

[CMakeのダウンロードページ](https://cmake.org/download/)からインストールしたいバージョンのcmakeを落としてきます

```sh
wget https://cmake.org/files/v3.19/cmake-3.19.2.tar.gz
```

## configureしようとする

tarを解凍して./configureをしようとします．
([[Linux][cmake] 最新のcmakeをインストールする方法](https://qiita.com/koara-local/items/9d01c6bb9dd93563b7c6)によると，./bootstrapというコマンドでも良いらしいです)

```sh
tar xvf cmake-3.19.2.tar.gz
cd cmake-3.19.2
./configure
```

エラーが出ました

```sh
  Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the
  system variable OPENSSL_ROOT_DIR (missing: OPENSSL_LIBRARIES
  OPENSSL_INCLUDE_DIR)
```

## エラーを解消する

OpenSSLがないらしいので，落としてきます．
[この記事](https://www.it-swarm-ja.tech/ja/openssl/cmakeはopensslライブラリを見つけることができません/1071887079/)に解決方法が書いてありました．

```sh
sudo apt install libssl-dev
```

これで./configureが動くようになりました．

```sh
./configure
```

## 後処理

```sh
make
sudo make install
```

これでcmakeが動くようになりました．
JetsonNx にrosのgmappingとnavigationを入れる備忘録

ros-melodic jetson Nx

```
sudo apt-get install ros-melodic-joy ros-melodic-teleop-twist-joy ros-melodic-teleop-twist-keyboard ros-melodic-laser-proc ros-melodic-rgbd-launch ros-melodic-depthimage-to-laserscan ros-melodic-rosserial-arduino ros-melodic-rosserial-python ros-melodic-rosserial-server ros-melodic-rosserial-client ros-melodic-rosserial-msgs ros-melodic-amcl ros-melodic-map-server ros-melodic-move-base ros-melodic-urdf ros-melodic-xacro ros-melodic-compressed-image-transport ros-melodic-rqt-image-view ros-melodic-navigation
```

```
$ git clone https://github.com/ros-perception/slam_gmapping.git
$ git clone https://github.com/ros-perception/openslam_gmapping.git
$ git clone https://github.com/ros-planning/navigation_msgs.git
$ git clone https://github.com/ros-planning/navigation.git
$ git clone https://github.com/ros/geometry2.git

$ cd ~/catkin_ws/src/navigation
$ git checkout melodic-devel
$ cd ~/catkin_ws/src/geometry2
$ git checkout melodic-devel

$ cd ~/catkin_ws
$ catkin_make
```

おまけにturtlebot3用のパッケージも

```
$ cd ~/catkin_ws/src
$ git clone https://github.com/ROBOTIS-GIT/turtlebot3.git
$ git clone https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git
$ git clone https://github.com/ROBOTIS-GIT/turtlebot3_simulations.git
$ git clone https://github.com/ROBOTIS-GIT/turtlebot3_gazebo_plugin.git

$ cd ~/catkin_ws
$ catkin_make
```
create-react-appで作成したReactプロジェクトに、TypeScriptを導入する

すごい今更感ありますが、React の勉強も兼ねて、環境を1から作っていきました。
create-react-app で作成したプロジェクトに、TypeScriptを導入していきます。

## やったこと

- 必要なパッケージのインストール
- create-react-app で作成された js ファイルを置換する
- React の型定義をコンパイラに伝える

### 必要なパッケージのインストール

[公式サイト](https://create-react-app.dev/docs/adding-typescript/) に必要なパッケージが記載されています。
~~プロジェクト作成時にテンプレート使えば良かったじゃんとあとで気づきました~~

プロジェクトのルートディレクトリで下記コマンドを実行
公式では普通にインストールしていますが、ビルド時に必要なものと思うので、devDependencies でインストールします。

```bash
yarn add -D typescript @types/node @types/react @types/react-dom @types/jest
```

### create-react-app で作成された js ファイル置換する。

- レンダリングを行う js ファイル(jsxを使用しているファイル) -> tsx ファイル
  - 今回は `src/App.js`、`src/App.test.tsx`、`src/index.js`が該当
- ロジックのみ書かれているjsファイル -> ts ファイル
  - `src/reportWebVitals.js`、`src/setupTests.js`

```diff:src/App.tsx
import logo from './logo.svg';
import './App.css';
- function App() {
+ // 返り値の型書いておく
+ function App(): JSX.Element {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
-          Edit <code>src/App.js</code> and save to reload.
+          Edit <code>src/App.tsx</code> and save to reload.
        </p>

```

```diff:src/reportWebVitals.ts
- const reportWebVitals = onPerfEntry => {
+ import { ReportHandler } from 'web-vitals';
+
+ const reportWebVitals = (onPerfEntry?: ReportHandler) => {
  if (onPerfEntry && onPerfEntry instanceof Function) {
    import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
      getCLS(onPerfEntry);
    });
  }
};

export default reportWebVitals;
```

### React の型定義をコンパイラに伝える

d.ts を作成します

```ts:src/react-app-env.d.ts
/// <reference types="react-scripts" />
```

これにて TypeScript の導入は完了です！

## 終わりに

GitHubのリポジトリにプルリクとして、やったことまとめてます。([こちら](https://github.com/fussy113/react-tutorial/pull/2))
現在ならコマンド一つで TypeScript 込みの React プロジェクトを作ってくれますが、自身で書き換えを行ったことで、なんとなく理解度が上がった気がします。

これから実際に何か作ってみて、React の tips みたいなものをアウトプットしていきます:muscle:
Flexプロパティが分からない！

皆なさん「Flexプロパティ」はご存知でしょうか？
私自身flex:1 1 auto;というコードをみて
「何それ？美味しいの？」と思い調べて理解したので共有させていただきます。
まず、このflex:1 1 auto;こちらは
flex-grow、lex-shrink、flex-basisの３つを一気に指定するものになります。では、一つずつ見ていきましょう。

・flex-grow

こちらはflexコンテナ全体の幅にflexアイテム合計幅が満たない場合の伸縮率になります。
もっと噛み砕いていうと、flex-grow:1;の場合　「一つの部屋を３人でシェアする時、みんな均等にスペースを分けようね」っていうことです。
![参照.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/981654/8c8dd980-5b0e-5046-a518-102487bd8290.png)

もしflex-grow:1 2 1;の場合
２の人が欲張りになっちゃいます。
![参照２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/981654/40eb5025-1506-736b-7994-b1bb57c15966.png)
続きまして。。。

・flex-shrink

こちらはflexコンテナ全体の幅よりflexアイテム合計幅が多い場合の縮む比率になります。
先程とほぼ一緒になりますが、噛み砕いていうと、flex-shrink:1 1 1;の場合　「一つの部屋を３人でシェアする時、俺だけ多めに撮ってしまってるからみんなで分け合おうぜ」っていうことです。
![参照３.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/981654/e2967b9e-aabc-c2d5-d088-692b27628e5a.png)
続きまして。。。

・flex-basic

flexアイテムの基準幅を設定するものになります。
px, em などの単位付きの数値や、親の Flex コンテナの main size に対するパーセンテージで指定します。
例えば親要素に今までのgrowやshrinkが設定されているとbasicで設定した値になるとは限らないので注意してください。

ここまできていうのもなんですが、一番王道な均等に全ての要素を配置したい場合はflex: 1 1 auto;としてしまえばOKかと思われます。

以上Flexプロパティでした!
collbackFlowをFirebase Realtime Databaseに使うといい感じ

## 概要

個人AndroidアプリでFirebase Realtime Database（略してRTDB）を使っているが、`ValueEventListener`のコールバックで実装する書き方がイマイチ好きではなかった。

そこで`collbackFlow` を使うと、RTDBとの接続をキレイに分離可能かつがStateFlow化できて、スッキリ書くことができた。
また、RTDBとの相性もよくて、値が何度も更新されてもFlowでちゃんと受け取れる。

## コード: 状態管理

例として、天気を取得する機能を実装するコードを紹介する。

StateFlowで管理する状態クラス
今回は分かりやすいようにSuccess内の変数を`WeatherInfo`にしている

```kotlin
sealed class WeatherUiState {
    // 値の取得成功
    data class Success(val weatherInfo: WeatherInfo) : WeatherUiState()
    // 失敗
    data class Error(val message: String) : WeatherUiState()
}

```

## コード: Repository

RTDBに接続して値を取得してくる

```kotlin
class WeatherRepository(private val dbRef: DatabaseReference) {

    /**
     * 天気を取得
     */
    @ExperimentalCoroutinesApi
    fun fetchWeather(): Flow<WeatherUiState> = callbackFlow { // callbackFlowの戻り値はFlow型
        // DBへの接続
        dbRef.addValueEventListener(object : ValueEventListener {
            // 正常に取得できた場合
            override fun onDataChange(snapshot: DataSnapshot) {
                snapshot.getValue(WeatherInfo::class.java)?.let { weather ->
                    // offerで購読側に値を流せる
                    offer(WeatherUiState.Success(weather))
                }
            }

            // エラーの場合
            override fun onCancelled(error: DatabaseError) {
                offer(WeatherUiState.Error(error.message))
            }
        })
        awaitClose {
            // 後始末はここでするが、DatabaseReferenceは自動で破棄されるで、やる事なし
        }
    }
```

## コード： ViewModel

RepositoryのStateFlowを購読するだけ。


```kotlin
class WeatherViewModel : ViewModel() {

    private val _weather = MutableLiveData<WeatherInfo>()
    val weather :LiveData<WeatherInfo> = _weather

    @ExperimentalCoroutinesApi
    fun fetchWeather() {
        viewModelScope.launch {
            // StateFlowの購読
            weatherRepository.fetchWeather().collect { state ->
                when (state) {
                    // 成功
                    is WeatherUiState.Success ->  _weather.value = state.weatherInfo
                    // エラー処理
                    is WeatherUiState.Error -> // 画面にエラー通知など
                }
            }
        }
    }
```

## 感想
Flowの学習もかねて`callbackFlow`を触ったが、すごくシンプルかつスッキリ書けていいね。

今回はFirebase RTDBと組み合わせたが、Firestoreにも同じように使えるはず。

あと、位置情報やBLEスキャンにcallbackFlowを使っている記事もあるので、けっこう便利に使えそう

## 参考リンク
- [callbackFlow - kotlinx-coroutines-core](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/callback-flow.html)
- [Kotlin Flow | Android Developers](https://developer.android.com/kotlin/flow?hl=ja)
Postgresqlはシングルクォーテーションとダブルクォーテーションを区別する

## 概要

Rake TaskでデータベースSQLを実行するスクリプトを作成中にPostgreSQLでデータの挿入（INSERT INTO）を試みたものの、何度も下記のようなエラーが発生し、結構苦戦したので自分なりに調査してわかったことをまとめることにした。

## 環境

macOD Catalina 10.15.7
PostgreSQL     13.1


## エラーの詳細

テーブルにレコードを挿入する一番基本的な下記のコマンドを実行しても毎回同様のエラーメッセージが発生していた
この時の自分は、varchar型のnameカラムに値( "sample_name" )を挿入しようとしていました

- 実行クエリ

```実行コマンド
 INSERT INTO sample_table VALUES ("sample_name");
```

- 発生していたエラーメッセージ

```
 column "sample_name" does not exist
```


## 解決方法

どうやら、Postgresqlはダブルクォーテーション（""）とシングルクォーテーション（''）を区別しているらしく、具体的な区別の仕方は、

- ダブルクォーテーション（""）は、カラム名などを表現する際に用います

- シングルクォーテーション（''）は、文字列定数を表現する際に用います


つまり今回の自分のケースに当てはめると、一生懸命"sample_name"として値を挿入しようとしていましたが、これは毎回sample_nameという名前のカラムとして認識されていたということになります。


実行クエリは以下のようになります。

```
 INSERT INTO sample_table VALUES ('sample_name');
```


## まとめ

かなりちょっとしたことではありますが、知っているか知らないかで大きく変わる知識かなと思います！

覚えておきましょう。
【Eclipse】Version 1.8.0_261 of the JVM is not suitable for this product. Version: 11 or greater is required　エラー

Pleiades All in One Javaをダウンロード
手順に従って、ファイルを解凍
pleiades/eclipse/eclipe.exeと進んだところ

<p>Version 1.8.0_261 of the JVM is not suitable for this product. Version: 11 or greater is required

といったエラーが出て、eclipseを起動できませんでした

<h4>【解決策】</h4>
まずこちらの動画を参考にしました
https://www.youtube.com/watch?v=CgwpdheXvls

eclipse.iniファイル（画像の下から3番目、名前はeclipseとしか書いてないのでわかりづらい）を編集
![スクリーンショット (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1003099/ff5ffc01-5052-4bd8-7a93-959f8275e8b9.png)

-vm
Javaのバージョンを指定

のように書いてありましたが、Javaのファイルは、Pleiaes All in Oneであればインストールされていないので、バージョンが分かりません

そこで 
pleiades/eclipse/readme/eclipse.ini

こちらのファイルにはすでに
-vm
Javaのバージョン情報

が載っていたので、この2行をコピーして、先ほどの
pleiades/eclipse/eclipse.ini
のファイルにペーストすれば解決しました。
Dartのxmlパッケージ(4.5.1)でparseEventsのこと

取り合えずメモ。誤解も勘弁。
Dartでxmlを扱いたい。xmlパッケージがある。しかしドキュメントは当然ながら英語。いまいち使い方がよくわからない。
そんな中を手探りで見つけたXMLをSAXで解析するスッキリな方法のメモです。

```dart:インポート
import 'package:xml/xml_events.dart';
```

```dart:XMLデータ
    final bookshelfXml = '''<?xml version="1.0"?>
    <bookshelf>
      <book>
        <title lang="english">Growing a Language</title>
        <price>29.99</price>
      </book>
      <book>
        <title lang="english">Learning XML</title>
        <price>39.95</price>
      </book>
      <price>132.00</price>
    </bookshelf>''';
```

```dart:処理
    await Stream.fromIterable(parseEvents(bookshelfXml))
        .forEachEvent(onStartElement:(e) => print(e));
```

```text:結果
<bookshelf>
<book>
<title lang="english">
<price>
<book>
<title lang="english">
<price>
<price>
```
Stream&lt;XmlEvent>の拡張関数としてforEachEventが書かれているようでonStartElement以外にonEndElementなどなど必要そうなものがあります。

##でも結局...
以下のようにbook内のことを処理するにはよくわからんかったから私は原始的な方法で使うことにしました。だって趣味だしどうせ趣味だし。

```dart:コード
    var it = parseEvents(bookshelfXml);
    var iterator = it.iterator;
    while (iterator.moveNext()) {
      var v = iterator.current;
      if (v is XmlStartElementEvent) {
        if (v.name == 'book') {
          print("Start:book");
          while (iterator.moveNext()) {
            var e = iterator.current;
            if (e is XmlEndElementEvent && e.name == "book") {
              print("End:book");
              break;
            } else {
              print(e.nodeType);
            }
          }
        }
      }
    }
```

```text:結果
Start:book
XmlNodeType.TEXT
XmlNodeType.ELEMENT
XmlNodeType.TEXT
XmlNodeType.ELEMENT
XmlNodeType.TEXT
XmlNodeType.ELEMENT
XmlNodeType.TEXT
XmlNodeType.ELEMENT
XmlNodeType.TEXT
End:book
Start:book
XmlNodeType.TEXT
XmlNodeType.ELEMENT
XmlNodeType.TEXT
XmlNodeType.ELEMENT
XmlNodeType.TEXT
XmlNodeType.ELEMENT
XmlNodeType.TEXT
XmlNodeType.ELEMENT
XmlNodeType.TEXT
End:book
```
きれいに書けんものか...(TT)
Go言語インストール後の実行環境テスト

# 最終確認
インストール、Version確認後
VSCordでフォルダを作成し、期待する結果が出力されるまでテストする
[Go言語の環境構築はこちら](https://qiita.com/coxcoa/items/39782fe00be03de2dcf7)

# 実行環境テスト

```
# テスト用ディレクトリを作成
$ mkdir -p ~/go/src/test

# ディレクトリへ移動
$ cd ~/go/src/test

# テスト用のファイルを作成
$ touch test.go

#　テスト用のファイルを編集
$ vi test.go
```

```go

//test.go

package main

import "fmt"

func main() {
    fmt.Printf("test, go\n")
}
```

```
# 作成したディレクトリへ移動
$ cd ~/go/src/hello

# ビルドしてバイナリファイルを生成
$ go build

```
:wqで保存し、ビルドしてバイナリファイルを生成

#### 実行する

```
$ ./test
```
```
test, go
```

#### ※エラーが出てしまう場合

```
$ go env
```
Go言語関連の環境変数を確認し、PATHあたりを確認してみると良いのかな？

#### ※出力結果を適応

テストで出力した内容を変更した場合は上書きが必要なので、再度ビルドする

```
$ go build
```
#### テストまでクリアしたので、これからGoの勉強を開始します！！
【Ruby】ブロック

# ブロック

## ブロック付きのメソッド呼び出し

主な用途は次の3つ。

1. ループの抽象化
2. ブロックへの機能付加。典型的にはリソース管理。
3. コールバック関数・イベントハンドラ

## クロージャーとしてのブロック

ブロックはクロージャである。
つまり、**ブロックの中のコードに現れる自由変数はブロックの外部環境に従う**。ブロックにおける自由変数は、外部環境であるブロックの外側のコンテキストで解決される。

下記の例では、ローカル変数 count がブロックの外と中で共有されている。

```rb
str = 'Hello, World'
count = 0
str.each_line do |line|
  print line
  count += 1
end
print count # => 1
```

ローカル変数や self 、 self に紐づいているインスタンス変数、メソッド呼び出しなどは全てブロックの中でも外側と同じように利用できる。

```rb
def some_method
  3.times { p self } # self は 3 ではなく、some_method の self
end
```

### 環境の保存


**ブロックが参照している外部環境は、ブロックが存在する限り保存されている**。メソッド実行は終了しても、内部のコードブロックはメソッド実行時のローカル変数を利用する。

下記の例では、 create_counter はメソッド内部のコードブロックを Proc オブジェクトに変換して呼び出し側に返す。
Proc#call メソッドを呼ぶとコードブロックを実行する。

create_counter メソッドの実行コンテキストにおけるローカル変数 count は、 メソッドが返した Proc 以外からは参照できない。
つまり、内部状態を隠蔽することができる。

```rb
def create_counter
  count = 1
  return Proc.new do
    count += 1
    p count
  end
end
counter = create_counter
p counter.class # => Proc
counter.call # => 2
counter.call # => 3

counter2 = create_counter
counter2.call # => 2
counter.call # => 4
counter2.call # => 3
```

## ブロックパラメータ

メソッドに渡したブロックは、メソッドから呼び返されるときに引数を受け取ることができる。また、ブロックは独自のローカル変数 = ブロックパラメータを持つことができる。

```rb
a = "str"
[1, 2, 3].each { |a| p a } # この a は、上の a とは別物
p a # => "str"
```

ここまでにわかることから、注意しなければならない2点。

* **外部のローカル変数と同名のブロックパラメータを用いない**
* **外部で既出のローカル変数は、ブロック内外で共有される（クロージャー）**

## ブロック付きのメソッドの定義

### yield 式

```rb
def foo_bar_baz
  yield "foo"
  yield "bar"
  yield "baz"
end

# または

def foo_bar_baz
  # ブロックを与えられていないとき、enum_for で Enumerator を生成して返す
  return enum_for(:foo_bar_baz) unless block_given?
  %w[ foo bar baz ].each do |item|
    yield item
  end
end

foo_bar_baz do |item|
  puts item
end
# => foo
#    bar
#    baz
```

### map もどき

```rb
def my_map
  [yield(1), yield(2), yield(3)]
end
p my_map { |i| i + 1 }
# => [2, 3, 4]
```

## Proc

呼び出し側のブロックをオブジェクトとして取得したい場合、Procオブジェクトを使う。

下記の例における &handler を、ブロック引数と呼ぶ。

```rb
class SleepyPerson
  def register_handler(&handler)
    @event_handler = handler
  end
  def wake_up!
    @event_handler.call Time.now, "woke up"
  end
end
john = SleepyPerson.new
john.register_handler { |time, message| p [time, message] }
john.wake_up!
```

### Proc からブロック

```rb
proc = Proc.new { puts "Proc was called" }
3.times(&proc)
# => Proc was Called
#    Proc was Called
#    Proc was Called
```


# まとめ

とりあえずこれだけ大事そう

* 外部で既出のローカル変数は、ブロック内外で共有される（クロージャー） 
* & 修飾で ブロック <-> Procオブジェクト


# 参照

- [初めてのRuby](https://www.oreilly.co.jp/books/9784873113678/)
AWS SMS とは

## 勉強前イメージ

SNS(通知するやつ)とかSES(メール送るやつ)の仲間？
正直S？Sがありすぎて難しい・・・なんの略なんやろ

## 調査

### AWS SMS とは

AWS Server Migration Service の略で、仮想マシンの移行サービスです。
VMware、Hyper-V、Azure上の仮想サーバをAMIとしてAWSに移行することができます。
移行時のダウンタイムを最小限にしたいサイトや仮想マシンの数が多いシステムの移行に利用することができます
あくまで、`仮想マシンのサーバを移行することはできますが、物理サーバの移行はできません`

### AWS SMS の特徴

#### 既存環境への影響が少ない

既存の仮想サーバの再起動などは必要なく、稼働したまま移行することができます。
増分レプリケーションも可能なため、切り替えの際のダウンタイムを最小限にすることができます。

#### 移行の手間が少ない

AWSのコンソール画面から操作できるので、移行が楽にすすめることができます

#### 無料で利用できる

SMS自体の費用は無料です。
SMSで使用するs3とEC2の費用は発生します。

### 移行図

1. AWSでSMS Connecterをダウンロードし、VM上に仮想マシンを作成。
2. AWS SMS から SMS Connecterを通じてサーバの情報を取得できるので、確認し任意のサーバを選択し、s3を経由してAMIを作成
3. AMIからEC2インスタンスを起動することでVM上と同様のサーバ起動ができる

![Untitled Diagram.drawio - diagrams.net 2020-12-30 00-43-54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/3cd6ab33-a6f3-dd9a-1b2f-6f72bb612b7c.png)


## 勉強後イメージ

通知系のサービスとは全然違ったw
VM上のサーバをAWSに構築するやつ。
VMで動かしてるサービスならすごい便利そう...物理サーバもできたらいいのにねー
今度VMのサーバをAWSに打ち上げてみよう。

## 参考

- [[クラウド移行が加速する]VMImport使ってるの？Server Migration ServiceでVMwareを移行する[AWS移行]](https://dev.classmethod.jp/articles/server-migration-service/)
- [AWS Server Migration Service（SMS）でAWSへの仮想マシンの移行を手軽に行うには](https://cloudnavi.nhn-techorus.com/archives/1454)
- [AWS Server Migration Serviceについて調べてみました](https://recipe.kc-cloud.jp/archives/9840)
- [AWS Server Migration Service](https://qiita.com/fjisdahgaiuerua/items/2aa48204e4e5f0494235)
- [ツールを使ったAWSへのサーバー移行の考察](https://dev.classmethod.jp/articles/consider-servers-lift/)
【VR空間サービス Spatial.io】 #3自分の姿を確認する

#サマリ
VR空間サービスSpatial使用できるようになりましたでしょうか。
VR空間に入っても自分の姿が見えませんね。
鏡を使って自分の姿を見てみましょう。


##環境
- Windows 10
- Chrome
- Oculus Quest2
- Spatial 1.9

##目次
1. 鏡をVR空間に出す

##1.鏡をVR空間に出す

- 右手コントローラーAボタンまたは左手コントローラーXボタンを押して第一階層のメニューを出す。真ん中のプラスボタンをポイントしてトリガーを押す。

![メニュー_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933978/a52cbafe-cbea-fb58-f9e8-0e0603f64ed0.png)

- 第二階層のメニューで左から4番目の「Stuff」をポイントしてトリガーを押す。

![メニュー_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933978/c23be832-63dd-e5a1-5fbd-95a22958db39.png)

- 左の「Avatar Mirror」をポイントしてトリガーを押す。

![AvatarMirror.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933978/d4e8170a-c4aa-8344-126a-460cf7acf7d9.png)

- 鏡が出現しました。自分の姿が見えましたね。

![AvatarMirror2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933978/b5ddcb0d-9ea4-d500-6de5-1f72d1b0bcda.png)

#　
チームハイエナ <img width="120" alt="hyaeninae_tomei.png"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933978/99b448d3-7ff0-58f3-302b-8528cf339b8d.png">
さくらのVPSを利用したsshでSOCKSプロキシを立ち上げる

とりあえず、書きかけです。

# はじめに
とある理由により、VPNサーバが必要になり、当初はさくらのVPSを使ってVPNサーバを構築するつもりでした。しかし、VPNサーバを構築する時間的な余裕がなかったため、別の手段を探していました。

そこで、[さくらの VPS を踏み台にし、 SOCKS プロキシ経由でブラウジングする方法](https://4to.pics/article/post/99)を発見し、試してみることにしました。

Macだとこの記事のまんまで接続できるのですが、今回Windowsではまったので、備忘録もかねての記録です。

#さくらVPSの設定

#(VPS側の)OSの設定(セキュリティ周り)


#クライアント側の設定
##Mac編

##Windows編
パスワードを入力する時に使用するTextFieldについて

# 問題

アカウント作成画面を作成していた時に、パスワード入力のViewにTextFieldを使用していたのだが、よく見るパスワード入力は入力文字が見えないようになっている。
SwiftUIを使用している場合、このようなTextFieldはどうやって実装するか分からなかったので調べた。

# 解決方法

TextFieldにオプションをつけるのかと思っていたが違うらしい。
SecureFieldというViewを使用すれば良いみたい。

https://developer.apple.com/documentation/swiftui/securefield

![スクリーンショット 2021-01-05 0.35.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567975/86cdcffb-44e0-ff23-c2b3-df0b43f915a7.png)
非同期処理中にユーザー操作を無効にする方法

# 問題

アカウント作成という非同期処理があるのだが、作成中にはユーザーの操作を無効化したい。
ただ、調べてもユーザー操作を無効にする方法はないっぽい。
そこで、ZStackを使用して、上にViewを重ねることで解決できないか検討した。

# 解決方法

以下のコードのように、isBusyがtrueの時にのみ、Color.whiteを重ねてみたところ、下のViewを操作できないことを確認できたので、これで良さそう。
もし、より良い方法があればコメント頂けると助かります・・・。

```swift
ZStack{
	VStack{
		TextField("ユーザー名", text: $vm.userName)
			.autocapitalization(.none)
			.textFieldStyle(RoundedBorderTextFieldStyle())
		TextField("メールアドレス", text: $vm.emailAddress)
			.autocapitalization(.none)
			.textFieldStyle(RoundedBorderTextFieldStyle())
		SecureField("パスワード", text: $vm.password)
			.autocapitalization(.none)
			.textFieldStyle(RoundedBorderTextFieldStyle())
		SecureField("パスワード確認", text: $vm.passwordConfirm)
			.autocapitalization(.none)
			.textFieldStyle(RoundedBorderTextFieldStyle())
		if vm.validationText != "" {
			Text(vm.validationText)
				.foregroundColor(.red)
				.font(.footnote)
		}
		Button(
			action: {
				vm.createAccount()
			}
		){
			Text("アカウント作成")
				.padding(4)
				.frame(maxWidth: .infinity)
				.foregroundColor(Color.white)
				.background(Color.gray)
				.cornerRadius(8)			
		}
	}
	.padding(.horizontal)
		
	if vm.isBusy {
		Color.white
			.opacity(0.7)
			.edgesIgnoringSafeArea(.all)
			.overlay(
				ProgressView("アカウント作成中...")
					.foregroundColor(.black)
			)
	}
}
```

![ezgif.com-gif-maker (2).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567975/40215d45-6994-89db-1903-54e07673932d.gif)
[ Java Script 入門 ] グローバルスコープとスクリプトスコープは同じものなのか？


##グローバルスコープとスクリプトスコープ　

```　
let a = 0;
var b = 0;
function c() {}
debugger;
```

これらを定義し、ブラウザ上で検証をぶちかます。
（**debugger**はブラウザを開いていると、この時点に達すると処理が止まる。）
検証の**Sources**内、Command + R　で更新。



```
Script
a: 0  

           
Global                Window
PERSISTENT: 1
TEMPORARY: 0
addEventListener: ƒ addEventListener()
alert: ƒ alert()
atob: ƒ atob()
b: 0
blur: ƒ blur()
btoa: ƒ btoa()
c: ƒ c()
```
Scope内にこのように表示された。　　
これがdebuggerから見える変数ということになる！


##グローバルスコープとは？

`Sources内の結果からわかるように、VarやFunctionで定義した際は、Globalの               Windowオプションにプロパティーとして保持される。`

##スクリプトスコープとは？
`letやconstにて宣言をとるとスクリプトの方に保持される`

##windowオブジェクト自体がグローバルスコープ？

```
console.log(window.b);
を
console.log(b);と省略しても取得する値は変わらない。
```
ってことは、windowオブジェクト自体がグローバルスコープなんだ:hand_splayed:

なので

```
window.d = 1;
console.log(d);
```
すると、d = 1はグローバルスコープに追加されているので、コンソール上には１が表示される:hand_splayed:

**使い勝手ではグローバルスコープもスクリプトスコープも変わらない**

ただ、

```
window.d = 1;
let d = 2;
console.log(d);
```
とすると2が表示される。これはスコープチェーンによるもの！






##まとめ

`一般的には、スクリプトスコープもグローバルスコープと呼ばれるとのこと。
ただ、スコープチェーンによる挙動の変化があるので、別のスコープであるという考え方は大切になる！`
【mongoDB】mongooseで、1対多のseedモデルを作成する。

※当方駆け出しエンジニアのため、間違っていることも多々あると思いますので、ご了承ください。また、間違いに気付いた方はご一報いただけると幸いです。

###モデルの関係

DriverモデルがPositonモデルを所有している。

###Driverモデル

```m_driver.js
"use strict";

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

const driverSchema = Schema({
  name: {
    type: String,
  },
  position: [{ //所有なので配列
    type: Schema.Types.ObjectId,
    ref: "Position" 
  }]
});

module.exports = mongoose.model("Driver", driverSchema);
```
###Positonモデル

```m_position.js
"use strict";

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

const positionSchema = Schema({
  longitude_k_x: Number,
  latitude_i_y: Number,
  driver: { 
    type: Schema.Types.ObjectId,
    ref: "Driver"
  }
});

module.exports = mongoose.model("Position", positionSchema);
```

###シードファイル

```seed.js
const mongoose = require("mongoose"); //モジュールロード
const seedDriver = require("./models/m_driver.js");
const position = require("./models/m_position.js");

//===================================
//mongoose接続
//===================================
mongoose.connect(
  `mongodb://${process.env.DB_USER}:${process.env.DB_PASS}@mongo:27017/db`,
  { userNewParser: true }
);
mongoose.set("useCreateIndex", true);
mongoose.Promise = global.Promise;
//===================================
//driver
//===================================
// 親
const parents =
  [
    {
      name: "driverTaro",
    },
    {
      name: "driverKen",
    },
    {
      name: "driverJiro",
    }
  ];

// 子
const children =
  [//配列内に、それぞれの親と結びつく順番で配列で格納
    [//"driverTaro"
      {
        latitude_i_y: 1,
        longitude_k_x: 1
      },
      {
        latitude_i_y: 2,
        longitude_k_x: 2
      }
    ],
    [//driverKen
      {
        latitude_i_y: 3,
        longitude_k_x: 3
      },
      {
        latitude_i_y: 4,
        longitude_k_x: 4
      }
    ],
    [//driverJiro
      {
        latitude_i_y: 5,
        longitude_k_x: 5
      },
      {
        latitude_i_y: 6,
        longitude_k_x: 6
      }
    ]
  ];
//===================================
//データクリア
//===================================
seedDriver.deleteMany().exec()
position.deleteMany().exec()
//===================================
//ループ
//===================================
for (let i = 0; i < parents.length; i++) {
  parent = new seedDriver(parents[i]);
  for (let g = 0; g < children[i].length; g++) {
    let child = new position(children[i][g]);
    parent.position.push(child);
    child.driver = parent;
    child.save();
  }
  parent.save();
}
```
Cのデータモデルについて

こんにちは、wattak777です。

[前回の投稿](https://qiita.com/wattak777/items/5e1ef52536f795e578ff) で、プログラミングデータモデルのことを少し記載しましたが、そもそもの話をしていなかったので今回はそれをネタにします。

##プログラミングデータモデルとは

C/C++に限った話ではないかもしれませんが、変数のデータ型のサイズを指します。
プラットフォームのCPUのスペックに依存して変わります。

幾つかのモデルがありますが、主に以下があります。

|データモデル|char型ビット数|short型ビット数|int型ビット数|long型ビット数|ポインタ型ビット数|主なプラットフォーム|
|:------------|:-------------|:-------------|:-------------|:-------------|:-------------|:-------------|
|LLP64|8|16|32|32|64|Win64|
|ILP32|8|16|**32**|**32**|32|32bit Unix/Linux|
|LP64|8|16|**32**|**64**|64|64bit Unix/Linux|
|ILP64|8|16|64|64|64|64bit Unix/Linux|

##整数型について

表の太字になっている箇所がポイントです。

intとlongはサイズが同じ[^1]、という形で覚えたりするとこれに陥るのですが、処理系が変わるとビットが変わるので注意が必要です。

ご存知の方は自明の話ですがintやlong、はたまたshortやchar[^2]といった各データ型のビット数は処理系依存でして、明確にサイズが定義されている訳ではありません。そのため上記のようなデータモデルのサイズが変わる場合があります。

##解決策、というより、こうしましょう的なお話

stdint.hをincludeして(u)int8_t/(u)int16_t/(u)int32_t/(u)int64_t[^3]を使い、使用する変数の範囲を元にビット数を明記したデータ型で定義する、だけです。[^4]

データモデルが変わることはそうないとは思いますが、扱いたい値の範囲を明示することでソースの可読性も上がる、と筆者は考えています。

##参考文献

[2016年、C言語はどう書くべきか](https://postd.cc/how-to-c-in-2016-1/)
原文は [How to C (as of 2016)](https://matt.sh/howto-c)

[^1]: この認識だったためかデータモデルでサイズ変わるよ、というと驚く知り合いが結構居ました…。
[^2]: charは「1バイト」と定義されていますがビット数は定義されていません。その後1バイト＝8ビットになりましたが…。
[^3]: uが入ると符号なし、uがないと符号あり。
[^4]: 参考文献にもありますがintを要求するqsort、longを要求するftellといった例外はあります。
Selenium Alert Confirm Box のOK キャンセルボタン押下

## SeleniumでAlert Confirm Boxを操作する。
下記をOKしたい場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/709188/42ce25d6-f9ce-33dd-a970-16f4e4cf5545.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/709188/bfbb0ec5-d4d3-e195-5c15-68add9820dfd.png)

```
from selenium import webdriver
from selenium.webdriver.common.alert import Alert

driver = webdriver.Chrome("driverPath")

# OKボタン押下
Alert(driver).accept()

# キャンセルボタン押下
Alert(driver).dismiss()
```

##環境情報
###IDE
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/709188/bd7dccd8-1544-7425-d628-d21d132c60d7.png)
###Python
python-3.9.1

###OS
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/709188/6eb21931-28b7-16ca-ea32-0ecee8ef60bf.png)
TextFieldにてアルファベット入力時に先頭文字が大文字になってしまうことを防ぐ

# 問題

TextFieldを用いた画面を作成した際に入力時に先頭文字が自動的に大文字になってしまうことがある。
特に、Canvasを使用して画面の動作を確認する際に、キーボードからの入力だと、大文字を小文字に変換する術がなく、辛い。
![ezgif.com-gif-maker.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567975/29425af9-16d3-0649-5706-3a4cc20e302e.gif)

# 解決方法

TextFieldのModifiersである、autocapitalization(_:)を使用して、大文字への自動変換を制御すれば良い。

https://developer.apple.com/documentation/swiftui/textfield/autocapitalization(_:)

``` swift
TextField("ユーザー名", text: $vm.userName)
    .autocapitalization(.none)
TextField("メールアドレス", text: $vm.emailAddress)
    .autocapitalization(.none)
```
![ezgif.com-gif-maker (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567975/b934010e-bbe6-c8dc-6b0d-26437c5365ef.gif)
🔰「HTMLへBootstrapを組み込み後CSSが反映されない」エラー解消

今日の勉強時に発生したエラー記録です。

＜内容＞
htmlへBootstrapを組み込んでいた際に、`<hr>,<h1>`のcssが反映されないエラーが発生しました。

```index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>ご利用アンケート</title>

  <link rel="stylesheet" href="../css/style.css">
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
</head>
<body>
  <div class="container">
    <header>
      <div class="row">
        <div class="col-sm-6">
          <h1>ご利用アンケート</h1>
        </div>
        <div class="col-sm-6 align-right">
          <a href="/">HOMEへ戻る</a>
        </div>
      </div>
    </header>
  </div>

    <hr>

    <hr>

  <div class="container">   
    <footer>
      <p>&copy; H20 space</p>
    </footer>
  </div>
  
</body>
</html>
```

```style.css
header {
  margin-top: 30px;
  color: #2e99a9;
}

hr {
  border-width: 3px;
  border-color: #2e99a9;
}

h1 {
  font-size: 18px;
  font-weight: bold;
  margin: 0;
}

.align-right {
  text-align: right;
}
```

＜web上画面＞
![スクリーンショット 2021-01-04 23.28.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993977/35dff51a-0e64-2677-1e4c-d7fa44f169b6.png)

＜確認事項.1＞デベロッパーツールの確認

![スクリーンショット 2021-01-04 23.26.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993977/d378deea-aaac-a6cc-7b1b-69792b461e1d.png)
![スクリーンショット 2021-01-04 23.28.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993977/1b7cd51f-f5f6-d896-461b-c626f50b6d4c.png)

＜確認事項.2＞コードのスペルミスの確認
問題なかったので、google検索を実施しました。
＜検索結果＞
Bootstrapとcssのファイルが喧嘩していたのが原因のようです。

＜検証①＞cssタグの前に直前のクラス名を入れてみる
`.col-sm-6 h1`
`.conteiner hr`
＜結果①＞全く効果無しのため次の検証②へ進みました。

＜検証②＞`link`タグ順を入れ替えcssファイルの優先順位を上げる

```index.html
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
  <link rel="stylesheet" href="../css/style.css">
```

＜結果②＞成功！！cssファイルが`<hr>,<h1>`へ反映されました！
![スクリーンショット 2021-01-04 23.59.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993977/7c02f604-eda2-dfb3-f792-d3e63856f219.png)

ファイルの優先順位に関する知識の復習不足が原因でした。復習、アウトプットを今後も続けていきます🔥

google検索時の参考記事↓↓
cssが効かない・反映されないときの対処法
https://saruwakakun.com/html-css/wordpress/cant
teratail Q&A
https://teratail.com/questions/86446
Gitea を推していく！

Gitea が大好きです！
みなさんにも使ってほしいので推していきます！


## Gitea - Git with a cup of tea
[Gitea](https://gitea.io/en-us/)とは、**セルフホストのGitサービス** です。
**セルフホストのGitサービス** とは、ざっくりいうと、https://github.com/ のようなものを自分で構築できるサービスです。
https://github.com/ は、すごいサービスですが、障害が発生すると使えなくなってしまいます。
障害なども、コントロール化における**セリフホストのGitサービス** は、強い味方です。

## 私の考えるGiteaの魅力
**セルフホストのGitサービス** には、Github.comのエンタープライズ契約や、Gitlabがあります。
それらと比較して、私はGiteaを魅力的に感じています。
今回は、魅力と感じる点を３つ紹介します。

1. 軽量
2. シングルバイナリ
3. クロスコンパイル

---

#### 1. 軽量

Giteaは、必要最低限のサービスを提供しているので、とても軽量に動作します。
Gitlabのように、多機能ではありません。
しかし、使っていく上で必要最低限のサービスや連携機能は存在しており、使っていく上でものすごく困ることは無いと思っています。

CD/CIまわすときは、痒いことがありますが、足りないならAPI呼び出しで作ればいいだけです！
Webhookできっくできるので、なんでもコイですよ！

なので、Giteaとしては、本当に、必用な機能しか動かないので、とても軽量に動作します。
私の環境では、起動時のメモリ使用量は、128MiB以内で収まっています！

#### 2. シングルバイナリ

Giteaは、シングルバイナリで動作します。（これは、開発言語のGo言語によるものです）
パッケージの展開や、色々なところにファイルを展開する必用もありません。
`gem`がんばったり、`pip`がんばったり、`apt install -f`する必用もなく、バイナリを[リリース](https://github.com/go-gitea/gitea/releases) から持ってくればいいだけです！
環境汚しも気にならないんですよね。導入の敷居がとても低く感じます！

#### 3. クロスコンパイル

Giteaは、クロスコンパイルされています。（これは、開発言語のGo言語の機能を上手に使ったからです）
Windowsでも、Macでも、Linuxでも動作します。
手元のPCで動かしてみて、使えそうだったらVPSとかで動かすことも可能です。
データ形式は、環境が異なっても同じデータベーステーブルを使えます。
なので、.gitフォルダとデータベースをお引っ越しすれば環境移行も楽勝です！
（クロスコンパイルと関係ないですが、Dockerの提供もあるので、お引っ越しし放題です！）

---

いかがでしょう！
今回は魅力３つの紹介をしましたが、私個人的に魅力を感じる機能は、まだいっぱいあります。

## ぜひ使ってみてください！

手元のWindowsでもすぐ動きますので、ぜひちょっとつけてみて、魅力を知ってください！
ちょっとクリックすれば、Github.comの小さいものがお手元に！
あと、[公式サイト](https://gitea.io/en-us/) のアイコンもとても可愛いので、ぜひ〜。

## リンク

* [公式サイト](https://gitea.io/en-us/)
* [ドキュメントページ](https://docs.gitea.io/en-us/)
* [ブログ](https://blog.gitea.io/)
bcacheを使ってSSDをキャッシュ化してみる

# 概要

Linuxでブロックデバイスをキャッシュに用いることができるbcacheを試してみる。SSDをHDDのキャッシュとして用いることでランダムアクセスや大きなサイズのファイル書き込みの性能向上が期待できる。

# システム構成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189186/e90f4ffc-68fc-5387-15f0-89b228523642.png)

### ハード
* マザーボード: GIGABYTE GA-H270-HD3
* CPU : Intel Core i5 7600T
* メモリ: DDR4 32GB
* SSD(VMwareデータストア用):Inte SSD 665p 1TB 
* HDD(データ用) : TOSHIBA DT01ACA300 3000GB

### ソフト
* ゲストOS・直接マウント用OS:Ubuntu Server 20.04
* ESXi : VMWare ESXi 7.0 Update 1

# 設定手順

```bash
# bcacheデバイスを作成。/dev/bcache*として生成される。
sudo make-bcache -B /dev/sdb1 -C /dev/sdd1
# 書き込みモードをwritebackに設定。
echo writeback | sudo tee /sys/block/bcache0/bcache/cache_mode
# xfsファイルシステムを作成。
sudo mkfs -t xfs /dev/bcache0
```

# 性能測定

`dd`コマンドによるファイルコピーで簡易的に計測を行った。

まずはbcacheデバイスを作成する前の時点で、SSD上の仮想ディスク(.vmdk)と、ESXiのrawマウントでマウントしたHDDの性能を測定する。

### 測定方法

```bash
mkdir tmpfs sdb sdc
sudo mount -t tmpfs tmpfs tmpfs    # RAMディスク作成
# 4GBのダミーファイルtest.imgをRAMディスク上に作成。
# RAMディスクはアクセスがSSD・HDDと比べて極めて速いので正確な書き込み性能を測れる。
sudo dd if=/dev/urandom of=tmpfs/test.img bs=32M count=128
sudo mkfs -t xfs /dev/sdb1
sudo mkfs -t xfs /dev/sdc1
sudo mount /dev/sdb1 sdb   # HDDマウント
sudo mount /dev/sdc1 sdc   # SSDマウント
sudo dd if=tmpfs/test.img of=sdb/test.img bs=4k oflag=direct
sudo dd if=tmpfs/test.img of=sdc/test.img bs=4k oflag=direct
# オプションの意味：
# bs=4kはセクタサイズの等倍になるようにして書き込みを高速化させるために指定。
# oflag=directはLinuxのキャッシュ無効化しディスクへの実際の書き込み速度を測定するために指定。
```

bcacheの性能測定

```bash
mkdir bcache
sudo mkfs -t xfs /dev/bcache0
sudo mount /dev/bcache0 bcache
sudo dd if=/dev/urandom of=tmpfs/test.img bs=32M count=128 iflag=fullblock
sudo dd if=tmpfs/test.img of=bcache/test.img bs=4k oflag=direct
```

### 結果

SSD：71.7 MB/s
HDD：40.2 MB/s
bcache：84.9 MB/s

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189186/be244fdd-397d-d652-85f9-15243dc30e20.png)

### 考察

結果としてはHDD<SSD<bcacheの順に書き込み速度が速いという結果となった。
ただ、bcacheはSSDをキャッシュ化しているだけなのでSSDよりも速度が速くなっているのはたまたまであろう。
何度か繰り返せば同等程度になるのではないか。

# おわりに

bcacheを用いることで、HDDの大容量とSSDの高速性を併せ持つブロックデバイスをUbuntu上で使えるようになった。
このデバイスをsambaやNFSでファイル共有して活用する予定だが、例えばキャッシュサイズよりも大きなサイズのファイルを配置した場合にどうなるかなど追加検証していく。
HyperLinkFieldクラス

#HyperLinkFieldクラスとは
GridViewコントロールは，フィールドの表示，編集を行います。詳細にカスタマイズするためクラスが用意されており，HyperLinkFieldクラスは，データに基づいてリンクを出力します。

#例
```html:GridViewSample.aspx
<asp:HyperLinkField DataNavigateUrlFields="EmployId" DataNavigateUrlFormatString="~/Basic/FormViewSample.aspx?EmployeeId={0}" Text="詳細" />
```

#使い方
1. デザイン画面で「>」ボタンを押下します。
![grid.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700136/41bfe29b-e545-c304-1c7a-8fff646aa931.png)

2. 「HyperLinkField」を選択し，「追加」ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700136/69d33c78-a04c-aa43-c490-71bda392b384.png)

3. 追加した「HyperLinkField」を選択し，プロパティを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700136/f8ef73c0-a071-dffd-e177-e2af5c7e6c50.png)

>プレースホルダ・・・
>{}で数値を囲ったもので，フィールドの値が埋め込まれます。プレースホルダの数値は0から順に，指定された複数のフィールドに対応します。HyperLinkFieldクラスのDataNavigateUrlFormatStringプロパティ内の{0}にDataNavigateUrlFieldsプロパティで指定したEmployeeのフィールドの値が埋め込まれます。

4. [OK]ボタンを押下すると，以下のようにリンクが出力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700136/3dda3421-b91b-e0fd-f34e-326f85a5b558.png)

#プロパティ
以下のようなプロパティがあります。

|プロパティ|意味|
|---|---|
|DataNavigateUrlFormatString|リンク先URL生成のための書式指定文字列|
|DataNavigateUrlFields|リンク先URLを生成するのに使用するフィールド名。複数指定可能|
|DataTextFormatString|リンクテキスト生成のための書式指定文字列|
|DataTextField|リンクテキストを生成するのに使用するフィールド名。複数指定可能|
|NavigateUrl|リンク先URL。固定値|
|Text|リンクテキスト。固定値|
|Target|リンクのターゲット|

##参考文献
TECHNICAL MASTER はじめてのASP.NET Webフォームアプリ開発 VisualBasic対応 第２版
『OpenCVによる画像処理入門』6章

# 濃淡変換
## 濃淡画像
多くの種類の階調で表現された画像を濃淡画像と呼ぶ。
カラー画像のまま処理するのは時間がかかるため、超高速な処理が求められる製造ラインの外観自動検査などは、濃淡画像が用いられる。
また、ステレオカメラやKinnectから得られる距離画像は、奥行きが濃淡で表現された濃淡画像。

## ヒストグラムを用いた濃淡変換
__ヒストグラム__
画像に対する画素値の分布度合いをグラフ化したもの。

p.75のヒストグラム描画プログラムを使用して、以下の画像のヒストグラムを出力した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581044/76a9aba1-b22b-8286-6dcd-0e07298d7ff1.png)

ヒストグラム（0(黒) → → 255(白)）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581044/9510edb5-3686-0eb7-3923-c8f62dbc4ff0.png)



全画素数をN、画素値をi、度数分布(ある画素が出現する数)をhiとすると、以下の関係式が成り立つ。

N = Σ[i=1..255]hi
0-255までの各々の度数が1つの画像に出現する数を合計すると、その画像の全画素数になる。

__ヒストグラム均一化__
画素値の度数分布は画像によってまちまち。
ヒストグラム均一化（平坦化）を行うことで、コントラストが悪かったり、明るさが偏っている画像のバランスを調整できる。
例えば、学習データを作る際に、様々な画像の明るさを整えられるので役に立つ。

※ヒストグラム均一化はグレースケールの場合は効果があるが、カラー画像の場合は色合いが変わってしまうため、使われることは少ないらしい。

## トーンカーブによる濃淡変換
__トーンカーブ__
画像全体の明るさや色を補正する際に必要な校正曲線。
明るさや色の補正前のデータ値と補正後のデータ値の対応関係を示したもの表したもので、画素ごとの調整を行うことで、画像全体の明るさや色を補正できる。一般的に、入出力データの対応関係を__階調変換関数__と呼ぶ。

階調変換関数は以下の関数fで表す。

f(入力画素値, 出力画素値)

入力画素値がX(0-255まで)の時に出力画素値を何にするかで関数fの内容は変わってくる。
fの定義によって、様々な変換方式が作られている。
（例：ガンマ変換、ネガポジ変換、ソラリゼーション、ポスタリゼーション、疑似カラー処理、明度調整、コントラスト低減、コントラスト強調）

練習問題は割愛。
「今あなたはプロキシサーバなの？リバースプロキシサーバなの？どっち？？」

# きっかけ
知識がなかなか身につかないので、どうしようかと社内のスキル表とにらめっこしていたら、
__「自分の仕事をちゃんと説明できなそもそも話にならへんやん」__
__「逆に自分の仕事を同業者にちゃんと伝えられたらそれって知識身についてるってことちゃうん？」__
とひらめいたのでさっそくまとめだした次第です。

## nginx
今これを使っています。
ただ、設定的なものは配属時にマニュアルどおりに済ませてしまうので、
普段の業務では全く意識しておりません。
「ふーん」ぐらいにしか思っていません。
~~何ならひらめくまで存在自体忘れていました。~~

## ざっくりまとめると
+ 複数の人が同時アクセスすることがあるサーバにはApacheよりnginxのが向いている
+ いきなりたくさんの処理が来て負荷がかかったときに耐えられる

今開発している製品的に、上２つの理由があるからnginxを使ってるんだろうなと思います。

## プロキシサーバとリバースプロキシサーバ
プロキシサーバ自体は、とりあえず基本情報の勉強の中で「ブラウザの代わりに他のサーバとやり取りをしてくれる」と覚えたのですが、そこに「リバース」なんてついたもんだからもう？？？でした。

プロキシサーバ・・・サーバ側
リバースプロキシサーバ・・・ブラウザ側
とのことですが、__正直厳密な差なんてないんちゃうか__と思ったのが本音です。

### でもまあ
プロキシサーバとリバースプロキシサーバ、これを見たら最後こう思ったわけです。
__「今使っとるnginxはどっちなんや」__

### 結論としては
__「『プロキシサーバ』です。なぜならブラウザから社内の開発専用サーバにアクセスし、社内の開発専用サーバから更にnginxにアクセスしているからです。」__

非常にシンプルでした。
それから普段社内の開発専用サーバにアクセスすることはあっても、
いきなりnginxにつなぐことはないしそもそも設定でしか見た記憶もなかったので、
ほぼ間違いなくプロキシサーバだと思います。
~~だから忘れてたわけですが。~~

### 逆に
リバースプロキシサーバでnginxを使っている場合どんな感じなのか非常に気になりました。
おそらくターミナルで起動するのは変わらないのでしょうが、そこから先ただのプロキシサーバとどう違ってくるのか比較してみると面白そうだなと思いました。

----------------------------------------------
最後までお読みいただきありがとうございます。
ではまた次の記事で。
Herokuアプリお引っ越し（rails）

# 概要
heroku上のrailsアプリを別アカウントに引っ越しする(dbはpostgresql)

# 前提
heroku cliをインストールしておく。
https://devcenter.heroku.com/ja/articles/heroku-cli

記事作成時点

```
heroku --version
heroku/7.47.6 darwin-x64 node-v12.16.2
```

# アプリの移行
```bash
# 現行アカウントにログイン
heroku login

# ソースをダウンロード
heroku git:clone -a 現行アプリ名
cd 現行アプリ名

# git remoteを削除
git remote rm heroku

# git remoteを確認
git remote -v

# 設定している環境変数があれば控えておく(basic認証用パスワード等)
heroku config -a アプリ名

# ログアウト
heroku logout

# 必要に応じてruby,railsのバージョン変更、ソース修正等実施

# 新アカウントにログイン
heroku login

# 新アカウントにアプリを作成
heroku create 移行用アプリ名

# git remoteを確認（create時に自動設定されるはず）
git remote -v

# アプリのデプロイ
git push heroku master

# 環境変数を設定（必要に応じて）
heroku config:set BASIC_AUTH_PASSWORD="password" -a 移行用アプリ名
heroku config:set BASIC_AUTH_USERNAME="user" -a 移行用アプリ名

# 環境変数確認
heroku config

# アドオン追加（必要に応じて）
heroku addons:create heroku-postgresql:hobby-basic
heroku addons:create papertrail:choklad

# addon で登録されているのを確認
heroku addons

# ログアウト
heroku logout
```
### dynoのアップグレード（必要に応じて）
webブラウザでherokuのアプリ設定画面を開く
Resources->Change dyno types->Hobbyなど

## 移行開始連絡
これ以降アプリ触っても責任取れない旨を通知（必要に応じて）

# DBの移行
```bash
# 現行アカウントにログイン
heroku login

# メンテナンスモードにする
heroku maintenance:on -a 現行アプリ名

# ワーカーを停止しておく（あれば）
heroku ps:scale worker=0 -a 現行アプリ名

# 現行データ件数確認等（必要に応じて）
heroku run rails c -a 現行アプリ名
MyModel.count

# マニュアルバックアップする
heroku pg:backups capture -a 現行アプリ名

# バックアップ結果を確認する
heroku pg:backups -a 現行アプリ名

# バックアップのdumpファイルをローカルに取得する
heroku pg:backups:download  -a 現行アプリ名

# 現行アカウントからログアウト
heroku logout

# dumpをアップロード（例はs3）
#  好きな方法でs3にアップロード
#  ファイルを公開（パブリックアクセス）に変更
#  ファイルのURLを取得

# 新アカウントにログイン
heroku login

# リストア実施
heroku pg:backups restore 'https://kwgch-upload.s3-ap-northeast-1.amazonaws.com/db_migration/latest.dump' DATABASE_URL

# 移行件数確認
heroku run rails c
MyModel.count

# workerの起動（あれば）
heroku ps:scale worker=1
```

# 動作確認
よしなに

# 問題が発生した場合
現行アプリを再開する

```bash
# メンテナンスモードoffにする
heroku maintenance:off -a 現行アプリ

# ワーカーを起動しておく（あれば）
heroku ps:scale worker=1 -a 現行アプリ
```

# 問題が発生しなかった場合
## アプリ名変更
※アプリ名を変更することで、URLも変更される

現行アカウント
現行アプリ名 → バックアップ用アプリ名

新アカウント
移行用アプリ名 → 現行アプリ名

## 移行終了連絡
（必要に応じて）

# そのほか
本番移行前に、手順書の作成と、リハーサルの実施をおすすめします。
本番は1人でさわるより、ペアオペが望ましいです。
Mac > 初期化後の開発環境インストールメモ


年末休みを利用して[Macをクリーンインストール](https://qiita.com/sugasaki/items/80223fbc0ca6a2cc05cc)したので、環境構築のメモ
都度更新していきます。

クリーンインストールする前に、設定をクラウドに飛ばせるものは飛ばすこと


### VSCode

まずは、VSCode

https://code.visualstudio.com/download


設定は同期済みなので、復旧は容易
事前に↓を参考に設定を行なっておくこと。

[Visual Studio Code Settings Sync](https://code.visualstudio.com/updates/v1_48#_settings-sync)



### Homebrew

[macOS（またはLinux）用パッケージマネージャー — Homebrew](https://brew.sh/index_ja)


インストールは以下をターミナルから実行

```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```


### zsh

Homebrewでインストール
以下をターミナルから実行

```
brew install zsh zsh-autosuggestions zsh-completions zsh-syntax-highlighting colordiff reattach-to-user-namespace tmux
```


### Git


Homebrewでインストール
以下をターミナルから実行

```
brew install git


### 一度ターミナルを再起動した後、インストール確認
git --version

### 参照しているパスを確認
which git
```


### Git Account


キーチェーンを使うよう credential.helper という config を設定します。

```
git config --global credential.helper osxkeychain
```


```
git config --global user.name "username"
git config --global user.email "mailaddress"

### 確認
git config --global -l
```

もし、GitHubの複数アカウント使っている場合には

[GitHubの複数アカウントを使い分け \- Qiita](https://qiita.com/sugasaki/items/e75544a4ec5f1ac79241)


リポジトリを最初にcloneするときだけ「ユーザー名@」をつけてcloneする

https://username@github.com/xxxxxx/xxxxxxx.git



以後は
キーチェーンにアカウント情報が格納され、それが使われる

![スクリーンショット 2020-12-21 17.12.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49910/71baa8bd-3d42-44b0-7f8f-b22a675e09e1.png "スクリーンショット 2020-12-21 17.12.12.png")


### jq

Homebrewでインストール
以下をターミナルから実行

```
brew install jq
```


### Java

[Mac > jEnvで複数バージョンのJDK（JAVA環境）を切り替える \- Qiita](https://qiita.com/sugasaki/items/e10071cc791d23dd16c8)


### Node & yarn

[Mac > anyenv,nodenvをMacに設定 \- Qiita](https://qiita.com/sugasaki/items/8cb12c06d2a44515194a)


##### yarn

```
npm install -g yarn
exec $SHELL -l
```

### tree

```
brew install tree
```

https://formulae.brew.sh/formula/tree

### Postman

[Download Postman \| Try Postman for Free](https://www.postman.com/downloads/)

### IntelliJ

[ダウンロード IntelliJ IDEA](https://www.jetbrains.com/ja-jp/idea/download/#section=mac)


### DBeaver

[Download \| DBeaver Community](https://dbeaver.io/download/)



# memo

### Notion

[Notion – Mac & Windows](https://www.notion.so/desktop)


### CotEditor

[CotEditor \-Text Editor for macOS](https://coteditor.com/)



# Communication

### Slack

[Mac \| ダウンロード \| Slack](https://slack.com/intl/ja-jp/downloads/mac?geocode=ja-jp)


### Discord

[Discordをダウンロード](https://discord.com/download)



# Google

### google-cloud-sdk

```
brew cask install google-cloud-sdk

cd /usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk
./install.sh
```



# 仮想環境

### VirtualBox

brew caskを使ってVirtualBoxをインストール

```
brew install --cask virtualbox
```


### Vagrant

brew caskを使ってVagrantをインストール

```
brew install --cask vagrant
```

```
vagrant box add ubuntu/xenial64
vagrant box list
```


```
vagrant plugin install vagrant-disksize vagrant-hostsupdater vagrant-mutagen vagrant-docker-compose
```



### mutagen


```
brew install mutagen-io/mutagen/mutagen
```
Effective Python 学習備忘録 3日目 【3/100】

## はじめに
Twitterで一時期流行していた 100 Days Of Code なるものを先日知りました。本記事は、初学者である私が100日の学習を通してどの程度成長できるか記録を残すこと、アウトプットすることを目的とします。誤っている点、読みにくい点多々あると思います。ご指摘いただけると幸いです！

## 今回学習する教材

- [Effective Python](https://www.amazon.co.jp/Effective-Python-%E2%80%95Python%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%82%92%E6%94%B9%E8%89%AF%E3%81%99%E3%82%8B59%E9%A0%85%E7%9B%AE-Brett-Slatkin/dp/4873117569/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=Effective+python&qid=1609408832&sr=8-3)
    - 8章構成
    - 本章216ページ

## 今日の進捗

- 進行状況：29-37ページ
- 本日学んだことの中で、よく忘れるところ、知らなかったところを書いていきます。

### None を返すよりは例外を選ぶ

python では、None, 0, 空文字列, などがすべて条件式においてFalseと評価されてしまう。そのため、戻り値にNoneを使ってしまうと、思わぬ問題を引き起こしてしまう可能性がある。boolメソッドを使って、確認してみる。

``` False_check
a = 0
b = []
c = {}
d = None
e = ''
bool(a)
# False
bool(b)
# False
bool(c)
# False
bool(d)
# False
bool(e)
# False
```

Noneを使ったときに起こる問題の一例として、ある数を別の数で割るヘルパー関数を考える。ゼロで割る場合には、結果が未定義なので、Noneを返すように定義。

``` zero_divide
def divide(a, b):
    try:
        return a / b
    except ZeroDivisionError:
        return None
```

a / b の結果がゼロの場合を考える。この時、Noneも0も共に、条件式ではFalseと判定されてしまうため、以下の条件だと誤った結果になってしまう。

```  miss_code
a, b = 0, 5
result = divide(a, b):
    if not result:
        print('Invalid inputs')  # 間違い
```

Noneをそもそも返さず、例外を呼び出し元にあげて、その処理をさせることがこの問題の解決策。

``` solution
def divide(a, b):
    try:
        return a / b
    except ZeroDivisionError as e:
        raise ValueError('Invalid inputs') from e
```

関数が例外を上げなければ、戻り値は問題ないはずと判断することができる。

### クロージャが変数スコープとどう関わるかを知っておく

- クロージャとは、定義されたスコープの変数を参照する関数のこと
- クロージャ関数は、定義されたスコープのどこからでも変数を参照できる
- デフォルトでクロージャは変数代入で、周囲のスコープには影響できない
- python3ではnonlocal分を用いてクロージャが外のスコープにある変数を修正できる
- nonlocal分を単純な関数でのみ使うようにする

スコープの範囲について確認する

``` find_group
def scope1(x):
    number = x
    def scope2(x):
        number = 1
    scope2(number)
    return number

number = 0
x = scope1(number)
print(x)
# 0
```

scope2でnumberに1を代入したが、戻り値は0になっている。この原因は、スコープが異なるためでである。scope1内のnumberと、scope2内のnumberは別の変数として処理されているため、値が変わっていない。異なるスコープの変数を横断するために、nonlocalを使って次のように定義する。

``` find_group
def scope1(x):
    number = x
    print(x)
    def scope2(x):
        nonlocal number 
        number = 1
    scope2(number)
    return number

number = 0
x = scope1(number)
print(x)
# 1
```

### リストを返さずにジェネレータを返すことを考える

- ジェネレータを使うと、格納した結果をリストで返すよりもコードが明確になる
- ジェネレータが返すイテレータは、ジェネレータ関数の本体でyield式に渡される一連の値を生成する
- ジェネレータでは、作業メモリにすべての入出力を保持する必要が無いので、どのような長さの入力に対しても出力のシーケンスを生成できる

リストで返すコード

``` list
def index_words(text):
    result = []
    if text:
        result.append(0)
    for index, letter in enumerate(text):
        if letter == ' ':
            result.append(index + 1)
    return result

words = 'Hello Effective Python'
result = index_words(words)
print(result)
```

出力結果

``` result
[0, 6, 16]
```

ジェネレータで返すコード

``` generator
def index_words(text):
    result = []
    if text:
        yield 0
    for index, letter in enumerate(text):
        if letter == ' ':
            yield index + 1
    return result

# ジェネレータ呼び出しで返されるジェネレータは、組み込み関数listでlistに変換できる
result = list(index_words(words))
print(result)
```

出力結果

``` result
[0, 6, 16]
```