OmniAICreator/Qiita-1.07M huggingface dataset:
Linuxにおける権限に関するまとめ(`chmod 777`は何をしているのか)

`chmod 777 <ファイル名/ディレクトリ名>`というコマンドが権限を付与するコマンドであることは初心者のエンジニアの方もご存知かもしれません。
ですが、この`777`という数字、具体的にどういう意味なのか、はっきりと理解できていますでしょうか。

「全権限を付与するということは知っている、、、」という方(過去の自分)向けに、Linuxの権限の意味についてまとめました。

# パーミッション（権限）について
`ls -l`というコマンドを叩くと下記のようにディレクトリ内のファイルを確認することができます。

```
drwxr-xr-x  2 toshiokun  staff  64  3  5 09:25 dir1
-rw-r--r--  1 toshiokun  staff   0  3  5 09:25 file1
-rw-r--r--  1 toshiokun  staff   0  3  5 09:25 file2
```

右側の`dir1` `file1` `file2` はそれぞれディレクトリ名とファイル名を指していますが、左側の`drwxr-xr-x`は「何のことやら」となっている方もいるかと思います。
実はこの`drwxr-xr-x`の部分が「誰に何の権限を渡しているのか」というパーミッションを表している表記になります。

## Linux内のパーミッション(権限)の定義について
パーミッション(権限)には下記のような概念が存在します。

- 誰に
    - オーナー
    - グループ
    - その他のユーザー
- 何に対して
    - ファイル
    - ディレクトリ
- どの権限を渡すか
    - read（読み取り）権限
    - write(書き取り)権限
    - execute（実行）権限

それぞれについて詳細を説明していきます。

### オーナーとグループ(誰に権限を渡すのか)について
ファイルとディレクトリにはそれぞれ「オーナー」と「グループ」が存在します。
「オーナー」は文字通り、対象の所有者のことを指します。

「グループ」についてですが、Linuxのユーザーは「グループ」という単位でひとくくりにすることができます。
ファイルとディレクトリは、オーナーとは別に、グループという単位で与える権限を定義することができるのです。

```:【参考】グループを確認するコマンド
groups <user_name>
```

### 権限の意味について
権限には「読み取り権限」「書き取り権限」「実行権限」がありますが、権限の意味は「ファイルに対して」と「ディレクトリに対して」で意味が少し異なるので注意が必要です。

|  | ファイル | ディレクトリ |
|:-:|:-:|:-:|
| read（読み取り）権限  |  ファイルの中身を閲覧できる |  ディレクトリ内に配置されているファイル一覧を取得できる |
| write(書き取り)権限  | ファイルの中身を編集できる  | ディレクトリ内に配置されているファイルを作成/削除できる  |
| execute（実行）権限  |  ファイルの中身を実行できる(シェルスクリプト等の場合有効) | ディレクトリをカレントディレクトリにできる  |

## 権限の表記について
上記の定義を踏まえて、`drwxr-xr-x`という表記は、「誰に」「何に対して」「どの権限を渡すか」という権限の内容を簡潔に表しているものになります。
`drwxr-xr-x`の部分は下記のように意味を分解できます。

| d | rwx | r-x | r-x |
|:-:|:-:|:-:|:-:|
| 対象が「ディレクトリ」か、「ファイル」か  |  オーナーのパーミッション | グループのパーミッション  | その他のユーザーのパーミッション  |

### 対象の表示
- `d`と表示される場合
    - ディレクトリを指す
- `-`と表示される場合
    - ファイルを指す

### パーミッションの表示
- `r`と表示される場合
    - read（読み取り）権限があることを指す
- `w`と表示される場合
    - write(書き取り)権限があることを指す
- `x`と表示される場合
    - execute（実行）権限があることを指す
- `-`と表示される場合
    - 該当の権限がないことを指す

### つまり`drwxr-xr-x`は何を指している？
上記のことを踏まえると、`drwxr-xr-x`は

- 何に対して
    - ディレクトリである`dir1`に対して
- 誰に
    - オーナーに
        - 「読み取り権限」「書き取り権限」「実行権限」を渡す
    - グループに
        - 「読み取り権限」「実行権限」を渡す
    - その他のユーザーに
        - 「読み取り権限」「実行権限」を渡す

ということを意味することになります。


## `chmod 777 <ファイル名/ディレクトリ名>`というコマンドについて
最後に、導入で話をした`chmod 777 <ファイル名/ディレクトリ名>`というコマンドの`777`について説明をして、この記事を終わりたいと思います。
`777`は

| 7 | 7 | 7 |
|:-:|:-:|:-:|
|  オーナーのパーミッション | グループのパーミッション  | その他のユーザーのパーミッション  |

と、それぞれの数字が、「オーナーのパーミッション」「グループのパーミッション」「その他のユーザーのパーミッション」を表しています。
7は`rwx`の別表記だと言い換えてもいいでしょう。

この数字は、下記のように２進数ごとに権限を割り当て、足し合わせた数値で表現することで、渡す権限を表現しています。

| 4 | 2 | 1 |
|:-:|:-:|:-:|
| read（読み取り）権限  | write(書き取り)権限  | execute（実行）権限  |

```:具体例
7 = 4(読み取り権限) + 2(書き取り権限) + 1(実行権限)
5 = 4(読み取り権限) + 1(実行権限)
3 = 2(書き取り権限) + 1(実行権限)
```

なので

- `chmod 777`なら、すべてのユーザーに「読み取り権限」「書き取り権限」「実行権限」を渡す
- `chmod 7５５`なら、オーナーに「読み取り権限」「書き取り権限」「実行権限」を渡し、オーナー以外のユーザーには「読み取り権限」「実行権限」を渡す

という意味になります。


# まとめ
今回は`chmod 777 <ファイル名/ディレクトリ名>`というコマンドの解説をしました。
このコマンドは本番環境などでアプリケーションの運用をするときだけでなく、ローカル環境の構築でも使用することも多いと思います。

何となくコマンドを叩いていた方がしっかりと意味を理解して、使いこなすことができる手助けになれば幸いです。
Initialization Closureとglobal定数を組み合わせて、computedライクなglobal定数を作る

# Initialization Closureとは?
Initialization closureは、以下の特徴を持ちます

- closure内でpropertyに操作を加えられる
- stored propertyである(値が割り当てられるタイミングはclassからinstanceが生成された時)

>If a stored property’s default value requires some customization or setup, you can >use a closure or global function to provide a customized default value for that >property. Whenever a new instance of the type that the property belongs to is >initialized, the closure or function is called, and its return value is assigned >as the property’s default value.

[公式ドキュメント](https://docs.swift.org/swift-book/LanguageGuide/Initialization.html)

主にUIをコードで記述する際に用いられます。
[参考記事](https://qiita.com/taji-taji/items/fd46d9a04ef50386fcca)


# Globalな定数(変数)の特徴
Globalな定数(変数)は以下の特徴を持つ

- lazyである(割り当てられるタイミングは値が呼ばれた時)

>Global constants and variables are always computed lazily, in a similar manner to >Lazy Stored Properties. Unlike lazy stored properties, global constants and >variables don’t need to be marked with the lazy modifier.
>Local constants and variables are never computed lazily.

それぞれの特徴を組み合わせると、computedライクなglobal定数を作ることができます。

```swift:ViewController.swift
let somePattern: FetchedValue = {
   let defalutValue = "hoge"
   return isFetchedCompleted ? fetchedValue : defaultValue
}()

```


これは、外部サービスを使って、複数画面でABテストを行いたい/アプリの挙動を変えたい場合に以下の性質を持つので便利です。

- lazyなので、アプリ起動後にfetchが間に合わない場合でも、対象画面に遷移するまで時間を稼げる(＝テストパターンに割り振られるユーザー数を増やせる)
- globalなので、各画面でfetchを行わなくて良い
- 各画面でfetchを行わないので、画面毎に挙動が異なることがない
SwiftUIからUIKitへ値を渡す。

# はじめに
SwiftUIからUIKitの利用を理解する為の二歩目として
・値を渡す。
・値が変わったら、表示を変更する。
最低限の実装方法を記載したものです。
最初の一歩は下記参照
https://qiita.com/ikaasamay/items/108ac5c211b75a9739d4

# 環境
macOS Big Sur 11.1
XCode 12.4
Swift 5

# 実装
加算ボタンを押したら、値が＋１されます。
![スクリーンショット 2021-03-06 11.14.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16101/58c490ea-d7b9-8391-ed77-3d5c39a479a0.png)

SwiftUI側でボタン押下時に
countを＋１して、
UIKit側では+1された値を追従して表示しています。

```swift:ContentView.swift
import SwiftUI

struct ContentView: View {
    @State var count = 0
        
    var body: some View {
        ZStack (alignment: .center) {
            // SwiftUI -------------
            VStack {
                HStack {
                    Text("SwiftUI")
                    Spacer()
                }

                // 加算ボタン
                Button(action: {
                    // 加算処理
                    count += 1
                }){
                    // 加算ボタンのレイアウト
                    Text("加算ボタン")
                        .font(.largeTitle)
                        // ボタンらしくレイアウトを調整
                        .frame(width: 250, height: 40, alignment: .center)
                        .overlay(
                            RoundedRectangle(cornerRadius: 10)
                                .stroke(Color.blue, lineWidth: 2)
                    )
                }
                Spacer()
            }

            // UIKitへcountを引数で渡す。
            CountUIKitLabel(count: $count)
                .frame(height: 100)
        }
    }
}

struct CountUIKitLabel:UIViewRepresentable {
    // 表示する値を保持するプロパティ
    @Binding var count:Int

    // SwiftUI側に返却するUILabelのインスタンスを返却する。
    func makeUIView(context: Context) -> UILabel {
        let label = UILabel()
        label.backgroundColor = UIColor.red
        label.textAlignment = NSTextAlignment.center
        
        return label
    }
    
     // プロパティ（count）が変更されると、その都度実行する。
    func updateUIView(_ uiView: UILabel, context: Context) {
        uiView.text = "UIKit  " + count.description
    }
}

次回はコーディネーターを記事にする予定

```
dockerメモ

# dockerに関するメモ

### dockerfileを更新してコンテナを更新する方法

    docker build -t user_name/repository_name:tag .

user_name:あなたのユーザー名
repository_name:リポジトリ名（イメージ名）
tag:タグ


### イメージの削除
コマンド： docker rmi [イメージID]
【PHP】アロー関数入門

# はじめに
PHP 7.4から**アロー関数**が使えるようになりました🥳
これで、PHPをJavaScript風に書けるようになりますねー

# 実行バージョン

```
$ php -v
PHP 8.0.2 (cli) (built: Feb  4 2021 18:01:33) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.2, Copyright (c) Zend Technologies
    with Zend OPcache v8.0.2, Copyright (c), by Zend Technologies
```

# アロー関数とは
> アロー関数は 無名関数 を簡潔に書ける文法として PHP 7.4 で追加されました。
> [公式より](https://www.php.net/manual/ja/functions.arrow.php)

```php:php
// 今まで
$calc = function($x,$y) {return $x+$y;};

// アロー関数
$calc = fn($x,$y) => $x+$y;
```
今まではクロージャーで関数を定義する場合、``function``と``return``を書く必要がありましたが、アロー関数で記載することで、``function``→``fn``にして、``return``を省略することができます。
アロー関数で書いた方がスッキリ🐿

# できない書き方

```php:php
$calc = fn($x) => {$x};
// PHP Parse error:  syntax error, unexpected token "{"

$calc = fn($x) => return x;
// PHP Parse error:  syntax error, unexpected token "return"

$calc = fn($x) => {
    $y = 2;
    return $x+$y+;
};
// PHP Parse error:  syntax error, unexpected token "{"
```
``return``, ``{``を書くと怒られます。また、複数行で記述することもできません。。
JavaScriptはできるのに。。


# コールバック関数として使用

```php:php
$arr = [1,2];
$res = array_map(fn($n) => $n*$n, $arr);
// array(2) {
//   [0]=>
//   int(1)
//   [1]=>
//   int(4)
// }

$res = array_filter($arr, fn($n) => $n === 1);
// array(1) {
//   [0]=>
//   int(1)
// }
```
もちろんコールバック関数でも使うことができます。


# 最後に
私はこの書き方を結構気に入っています！若干、JavaScriptと書き味が違うので気をつけてください。親のスコープの変数を参照できる等、少し癖があるので、[公式](https://www.php.net/manual/ja/functions.arrow.php)を読んでから使うようにしてください！
トランスファー申請不承認のご連絡 - お名前.comから Cloudflare Registrar にドメインを移管出来なかった時

# 手順

大体の流れはここを参考
https://qiita.com/MatYoshr/items/60f93f3d42f82027d664

https://developers.cloudflare.com/registrar/domain-transfers/transfer-to-cloudflare

https://developers.cloudflare.com/registrar/transfer-instructions/generic

大雑把に言うと

1. お名前.comで`.jp`ではない一般的なドメインを持っている
2. ドメインを取っていて60日は経っている（ICANNのルール）
3. この前提から
4. cloudflareにまずは無料アカウント登録
5. cloudflareに自分のドメインを登録
6. そうするとcloudflareがネームサーバーを提供してくれる
7. お名前.comでこのネームサーバーへ変更する
8. cloudflareでネームサーバー変更の完了を確認する
9. お名前.comで[ドメイン移管ロック][3]がONではないか確認（デフォルトではOFFのはず）
9. **お名前.comで[whois公開代行設定を解除][1]する！！！**
10. お名前.comで[AuthCode][2]をコピー
11. cloudflareでtransferを進める
12. AuthCodeが要求されるのでペースト
13. カード登録してtransfer申請

## 問題がある場合

[トランスファー申請不承認のご連絡]というメールが来る。

## 問題がない場合

[トランスファー申請に関する確認のご連絡]というメールが来る。
このメールの中に承認のお手続きリンクがあるので必ず期日以内に承認する。

ドメイン代は.comで卸値の$7.85。transferをしてもすぐに年間の課金が始まるんではなく、現在のドメインの有効期限が切れた後にこの代金が毎年発生する。

https://github.com/judge2020/Actual-Domain-Prices



# [公開代行解除][1]

ここにも書いてあるがざっくり読んでたので見落としてた。

![Transfer_to_Cloudflare_·_Cloudflare_Registrar_docs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16757/45e096b4-a3f6-19de-4e0d-e63ed708d209.png)


[![Whois情報公開代行__Whois情報公開代行メール転送オプション｜お名前_com_Navi_ガイド｜ドメイン取るならお名前_com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16757/5bfadc8f-a1ad-05be-5248-55f65e368d04.png)][1]

[1]: https://www.onamae.com/guide/p/29?_ga=2.267570062.1247844519.1614906398-327554176.1614906398#on
[2]: https://help.onamae.com/answer/8581
[3]: https://www.onamae.com/guide/p/27
【いっこく堂風アルゴリズム】1 ステップ後に処理を遅延させる（１回ズラして出力する）

# いっこく堂風アルゴリズム

> ループ処理で、出力を 1 処理ぶん遅らせて出力させたい。[遅延評価](https://ja.wikipedia.org/wiki/%E9%81%85%E5%BB%B6%E8%A9%95%E4%BE%A1)と言うより、ディレイみたいな。

```text:ループ回数：出力（出力はループ回数を1回遅延させたもの）
0:
1:0
2:1
3:2
4:3
5:4
6:5
7:6
8:7
9:8
10:9
```

実装は難しくないものの「もっと効率的な方法がある ... の ... か？」と[「1ステップ 処理 遅延 アルゴリズム」でググって](https://www.google.com/search?q=1%E3%82%B9%E3%83%86%E3%83%83%E3%83%97+%E5%87%A6%E7%90%86+%E9%81%85%E5%BB%B6+%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0)も、基本的すぎるのかアルゴリズムとも呼べないのか、ヒットしなかったので自分のググラビリティとして。

## TL; DR <sub><sup><sub><sup>（今北産業）</sup></sub></sup></sub>

1. 現在の処理をするも、処理結果としてバッファ（一時保存されたデータ）を利用する。
2. 1 ループの処理の最後に、現在の処理結果をバッファリング（一時保存）する。
3. 全ループが終わった後に、1 回同じ処理をさせる。（バッファの最後の吐き出し）

```php
// ループ処理
for i = 0; i < 10; i++ {
    // 実際の処理（このループでは使わない）
    curr = process(i)

    // 出力（このループの処理結果としてバッファを使う）
    fmt.Printf("%v:%s\n", i, buff)

    // 更新
    buff = curr // バッファリング
}

// 最後のバッファを吐き出す
fmt.Printf("%v:%s\n", i, buff)

function process(i int): int
{
    // なんか処理する
    return i
}
```

<details><summary>Go言語（Golang）のサンプル</summary><div><br>

```golang

package main

import (
	"fmt"
	"strconv"
)

func main() {
	var (
		buff   string = ""
		result string = ""
		i      int
	)

	for i = 0; i < 10; i++ {
		curr := process(i)

		result = buff
		fmt.Printf("%v:%s\n", i, result)

		buff = currResult
	}

	result = buff
	fmt.Printf("LAST: %v:%s\n", i, result)
}

func process(i int) string {
	return strconv.Itoa(i)
}
```

- [オンラインで動作をみる](https://go.dev/play/p/3rKHwe3roBA) @ Go Playground

</div></details>


## TS; DR <sub><sup><sub><sup>（遅延させて何が嬉しいの？）</sup></sub></sup></sub>

> 1 つ前もしくは 1 つ後の状態を踏まえて処理を考えることができる。

例えば、文字列操作などで 1 文字ずつ処理をするケースです。

```
こんにちは。今日は天気
が良いですね。
そうですね。
Hello. It's a nice
day. Isn't it?
Hell, yea.
```

これを処理して以下のような出力をしたい場合、などです。

```
こんにちは。今日は天気が良いですね。
そうですね。
Hello. It's a nice day. Isn't it?
Hell, yea.
```

処理結果で `天気` と `が良い` の間にスペースがなく、`nice` と `day` の間にスペースが入っていることに注目してください。

「え？正規表現で置換すれば良いじゃん。」とか「文字列置き換えで `。\n` や `?\n` を一旦エスケープして `\n` を一括置換で削除して戻せば良いじゃん。」と思うかもしれません。

その通〜りです！

しか〜し！日本語などの「マルチバイト文字」と「ASCII でおk」系のスペース区切り系が混在した文字列の処理を考える際に問題がおきます。例えば処理速度やメモリ使用量などです。

もちろん置き換えを駆使して文字列を何度も置換するのも良いのですが、やはり 1 文字（1 ユニコード文字単位）つまり「[コードポイント](https://ja.wikipedia.org/wiki/%E7%AC%A6%E5%8F%B7%E7%82%B9)」ごとにループさせて処理させた方が、速度やメモリ使用量の改善ができます。

なぜ悩んだかと言うと、日本語と英語とスペイン語が混在した改行入りの文字列を綺麗に <code>[word wrap](https://en.wikipedia.org/wiki/Line_wrap_and_word_wrap)</code>（特定幅で文字列を単語単位で改行）したかったのです。

ところが、`hell\no, w\norld\n!` のような単語の途中に改行が入っている文書でつまづいてしまいました。

```text
input:
hell
o, w
orld
!

want:
hello, world!
```

また、`こんにちは\n。` のような、禁則処理（`こんにちは\n。` → `こんにち\nは。` としないといけない）などが必要になって来たりとキリがありませんでした。

```text
input:
こんにちは。今日は
天気が良いですね。
そうですね。

want:
こんにち
は。今日は
天気が良い
ですね。
そうです
ね。
```

結論から言うと、言語によって専用のライブラリがあるので、それを使いました。それでも満足した結果ではないのですが。そう考えるとブラウザの CSS などの <code>[justify](https://ja.wikipedia.org/wiki/%E6%96%87%E5%AD%97%E6%8F%83%E3%81%88)</code> の禁則処理ってすごいな、と思いました。
HTML / CSS 覚書 Vol.2 displayプロパティーとflexbox 

##1...displayプロパティー基礎
###①インライン要素
* 幅と高さは中の要素分だけ。
* `margin`は横にしか効かない。段落を変えると`margin`同志の間に少し余白ができる。
* `padding`は縦横に効く。縦方向は他の要素を無視して被さる。
* 段落の有無に無関係で横に並ぶ。

###②ブロック要素
* 幅と高さは指定できて、要素は含まない。（要素の高さが50px、指定した高さが50pxの時高さは100pxでなく50pxになる。）
* `margin`は縦横に効き、他の要素には干渉しない。
* `padding`は縦横に効くが中の要素は下方に押し出される。
* 段落の有無に無関係で段落ができる。（横に並ばない。）

###③インラインブロック要素
* CSSで指定する。
* 幅と高さはブロック要素と同じ。
* `margin`はインライン要素と同じ。
* `padding`はブロック要素と同じ。
* 段落はインライン要素と同じ。

こんな感じ。
![HTML _ CSS (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132336/f60d62eb-3521-454b-4277-4df187a414e0.png)
![HTML _ CSS (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132336/f5aa2c9b-4b3e-a2f5-f18d-dc5c749af4cc.png)
###④ブロック要素のマージン相殺
ボーダーで囲まれていないブロック要素の上下の`margin`は相殺される。
これはインライン要素、インラインブロック要素では起きない。
こんな感じ。
![HTML _ CSS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132336/89f591a8-5b6a-8e4d-8f3d-f85d3463d08e.png)
###⑤おまけ・・・切れ目の無い半角文字の要素が中にある時
切れ目の無い半角文字の連続は右横からはみ出してしまう。
適度に切れ目を設けると折れ曲がるが、量が多いと下からはみ出す。
切れ目なく折れ曲がらせるには``word-wrap: break-word;`を指定する。
こんな感じ。
![HTML _ CSS (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132336/c25bca52-6521-feab-1161-08630cd050e6.png)


##2...flexbox
###①基本の横並べ
* 横並べにしたい要素の**親要素**に`display: flex`を指定する。
* 初期値は左から右に横に並ぶ。（`flex-direction: row;`の状態）

省略記法：`df`=>`display: flex;`
こんな感じ。
![HTML _ CSS (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132336/9a4d30d0-a900-220f-c849-98b21cdd3fae.png)
###②`flex-direction`
* 基本の並べる向きと開始位置

省略記法：
`fd`=>`flex-direction` +
`c`=>`column`
`cr`=>`column-reverse`
`r`=>`row`
`rr`=>`row-reverse`
こんな感じ。
![HTML _ CSS (8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132336/58271b18-2989-2c06-a710-f3e3f0ad4250.png)


###③横の位置決め`justify-content`
省略記法：
`jcc`=>`justify-content: center`
`jcfs`=>`justify-content: flex-start`
`jcfe`=>`justify-content: flex-end`
`jcsaro`=>`justify-content: space-around`
`jcsb`=>`justify-content: space-between`
こんな感じ。
![HTML _ CSS (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132336/3511c374-16d3-3c18-2f8f-86fcfd241392.png)
###④縦の位置決め`align-items`
省略記法：
`aic`=>`align-items: center;`
`aifs`=>`align-items: flex-start;`
`aife`=>`align-items: flex-end;`
`aic`=>`align-items: center;`
`aic`=>`align-items: center;`
こんな感じ。
![HTML _ CSS (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132336/04eb5663-000b-771f-6e9a-3ec4710b33b5.png)

![HTML _ CSS (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132336/b1d1d07e-978e-f31e-1382-c7a11366a942.png)


![HTML _ CSS (10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132336/1765a3fb-fd33-1b37-8077-21643d21cdfb.png)







##⑤カラム落ちさせる`flex-wrap`
省略記法：`fwr`=>`flex-wrap` + `w`=>`wrap`
こんな感じ。
![HTML _ CSS (9).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132336/5c3be5ef-6f54-c18e-46f3-920962f19420.png)
UITableViewの高さをcell数に応じて可変にしたい

# 課題事例

- 元々、画面全体がUIScrollViewになっていて、真ん中にUITableViewを差し込みたい（※新規画面なら全体をUITableViewにすれば済む話ではあります）。
- 画面全体をスクロールさせる点に変わりはないので、UITableViewはスクロールさせない。
- UITableViewはcell数が可変、かつcellごとの高さも違っていて、それに応じてUITableViewの高さを変えたい（そうしないと全てのcellが表示されなかったり、余白ができてしまったりするので）。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122917/d8db23cc-78ec-bc9e-0a80-2588af7001a8.png" width=70%>

# 解決法

(1) 高さのconstraintを変数に格納。

```swift
private weak var tableViewHeightConstraint: NSLayoutConstraint?
```

(2) KVO(Key Value Observing)でUITableViewのcontentSize.heightを監視。

NSKeyValueObservationを格納するための変数を宣言し、UITableViewのcontentSize.heightをobserve。
heightが変わった時に上の制約のconstantをセットする処理を定義する。

```swift
private var observation: NSKeyValueObservation?

override func viewDidLoad() {
// 略
    observation = tableView.observe(\.contentSize, options: [.new]) { [weak self] (_, _) in
        guard let self = self else { return }
        self.tableViewHeightConstraint?.constant = self.tableView.contentSize.height
    }
}
```

(3) 後始末

```swift
deinit {
    observation?.invalidate()
    observation = nil
}
```

私は以上のような解決法で課題をクリアできましたが、もっとシンプルな解決法をご存知でしたら、ぜひ教えてください。:bow_tone1:
逆説的思考（ライフハック）

>「昼間の住宅街の道路」　と　「夜中の首都高」　どちらが安全で　どちらが危険だろうか？

昨日、住宅街の中を運転（直進）していると、左側の脇道から突然　車が右折してきた。
ぶつかりそうだったので、急ブレーキをかけました。

相手の若い女性もびっくりした顔をしてました。

左側の脇道から突然　左折してくる車なら、不注意の可能性もありますが、
左側の脇道から突然　右折してくる車は、
**「目は曲がる方向を見ているのに、他車を認識していない」**ということになります。

危うくもらい事故になるところでした。

「夜中の首都高」の方が危険に思えるかもしれませんが、高速を走っている時はみんな緊張しているので安全意識が高いのかもしれません。

「昼間の住宅街の道路」は、歩行者も運転者も安全意識が低いため、注意が必要です。

以下のような方を時々見かけます。
>・好き勝手に自分のルールで車を運転する人
　（交通量が少ない交差点でUターン）
　（後ろから車が来ているのにハザードを出さずに停車）
・ゆっくり歩くことしかできないのに、横断歩道じゃないところを渡る人

また、以下のような車やバイクを見たら、ある程度距離を保って運転するようにしています。
>・車の後部に凹みがある車。（ぶつけた跡がある）
・ライトやウインカーが片方だけ切れている車。
・（後ろから見て）左右のタイヤの圧力に偏りがある車。
・圧力不足のタイヤで走っている原付バイク。

「昼間の運転」は、ゆっくり、落ち着いて運転するように心がけていこうと思います。皆さんもご自愛ください。

自動運転が実現するとこの問題は解決するのかなぁ。
自作apiでauthが効かない（laravel）

バックエンドにlaravel、フロントにreactを利用してSPAでwebアプリを作っているのですが、
authの処理ではまりました。
具体的には、フロント側からlaravelで自作したapiを利用する際、Authファサードを利用しても値がとれないという状態でした。

# 解決方法
laravelで自作したapiのrouteはapi.phpに記述していたのですが、どうやらデフォルトではapi.phpはsession機能を読み込まないようです。

RouteServiceProvider.phpで以下の修正を行いました。

```
public function boot()
    {
        $this->configureRateLimiting();

        $this->routes(function () {
            Route::prefix('api')
                // ->middleware('api') 　  ←　元々
                ->middleware('web')　　　　 ←　修正後
                ->namespace($this->namespace)
                ->group(base_path('routes/api.php'));

            Route::middleware('web')
                ->namespace($this->namespace)
                ->group(base_path('routes/web.php'));
        });
    }

```


ちなみに、middleware('web')などで読み込んでいるいるのは、Kernel.phpの$middlewareGroupsの部分みたいです。
amplifyの作法 その25

#概要

amplifyの作法、調べてみた。
ハッカソンに、応募してみた。

#アプリ名　三択コンパイラー
##アプリ概要
三択問題を、マウスでクリックするだけで、pythonソースコードを生成する、webアプリケーションである。

##アプリによって実現された事
守備範囲は、限定的だが、ソースコードは、自動生成される。

##アピールポイント1
QUBO、イジング模型を理解できなくとも、ソースが書ける。
逆にソースコードから、理解が期待できる。

##アピールポイント2
評価関数の展開に、sympyを利用した。

##アピールポイント3
webアプリケーションである。

##想定問題
「看護師、aさん、bさん、cさん、から２人を選べ。」

「aさんとbさんは、気が合うので、同じ事をすると、気分が良い。
bさんとcさんは、軋轢があり、違うことがしたい。
みんなが、気持ち良くなる組み合わせを求めよ。」

##アプリのurl
https://embed.plnkr.co/plunk/2nOl0AYjrVAbLJsK

##関連Qiita
https://qiita.com/ohisama@github/items/2890cb3c5ea2b54e3ef7
https://qiita.com/ohisama@github/items/5954b7f5a79b3c401877
https://qiita.com/ohisama@github/items/1eb4d7c95836fe921485
https://qiita.com/ohisama@github/items/0c6ed7c9d4d0fb03f0c8
https://qiita.com/ohisama@github/items/8edc64afc90169e485b2


以上。
instascrapeの使い方

#instascrapeとは
インスタグラムのデータをスクレーピングする際に用いるツールです。以前まではrequestsとBeautoful SoupでWebスクレーピングすることができたが仕様の変更によりセキュリティが上がりinstascrapeを使う流れとなった。

#インストール
・instascrape：インスタグラムをスクレーピングするときに使うライブラリー

```python
$ pip install insta-scrape
```

#使い方
まずはインポートする

```python
from instascrape import *
```
次に使用するインスタグラムのurlを指定する。
指定したurlがプロフィールのものである場合Profile()とする。
同様に投稿urlの場合Post(), ハッシュタグの場合Hashtag()。

```python
google = Profile('https://www.instagram.com/google/')
google_post = Post('https://www.instagram.com/p/CG0UU3ylXnv/')
google_hashtag = Hashtag('https://www.instagram.com/explore/tags/google/')
```
次にスクレーピングしていく。

```python
google.scrape()
google_post.scrape()
google_hashtag.scrape()
```

最後にスクレーピングしたものの各要素を出力する。

```python
print(google.followers)
print(google_post['hashtags'])
print(google_hashtag.amount_of_posts)
```

もっと詳しいスクレーピング属性を確認したい場合は[こちら](https://github.com/chris-greening/instascrape/wiki/Scraped-data-points)を確認してください
PCでRubyを使えるようにしよう！| 初めてのプログラミング環境構築 ① 

##目次
この記事ではPCで、つまりローカル環境でRubyが使えるようになることを目指しています。
Macの場合とWindowsの場合で作業が異なります。

####Macをお使いの場合 -> **Macの場合**をご覧ください。
####Windowsをお使いの場合 -> **Windowsの場合**をご覧ください。


##Macの場合
**MacではデフォルトでRubyがインストールされています。**
Rubyのバージョンの確認をしてみましょう。

ターミナルを開きます。
![スクリーンショット 2021-03-05 17.52.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553021/25bb9741-95cb-6e5d-a04e-dc6ab193510f.png)

###Rubyのバージョンを確認
Macでは標準でRubyがインストールされているようです。
ターミナルで、以下のコマンドを入力し、Enterを押下します。

```terminal:ターミナル
ruby -v
ruby 2.6.3p62 (2019-04-16 revision 67580) [universal.x86_64-darwin19]
```

私の場合は、バージョン2.6.3がインストールされていました。

## Windowsの場合
### インストーラーのダウンロード
以下サイトへアクセスしてファイルをダウンロードし、Rubyインストーラーのインストールを開始して下さい。
https://rubyinstaller.org/downloads/

現時点での推奨バージョンは**太字**で記載されています。
![スクリーンショット 2021-03-05 17.25.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553021/455451f2-8839-591a-ebe2-e5a4acdf9bd6.png)

途中で問われる選択項目は、基本的に全て変更せず「Next」ボ タンを押して頂いて問題ありません。
![スクリーンショット 2021-03-07 18.52.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553021/9d21d9fc-668c-c131-27fa-e57e53e0a67c.png)

下図のような画面が出たら**Install**を押します。
![スクリーンショット 2021-03-07 18.53.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553021/21fd5ce5-7893-e357-aeca-81fd218d2636.png)

下図のMSYS2の項目は必ずチェックして下さい。
![スクリーンショット 2021-03-07 18.53.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553021/4cfd6f5e-fe45-a77c-1b0b-75de2a912081.png)

完了したら**Finish**を押します。
![スクリーンショット 2021-03-07 18.53.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553021/45c50bd3-9c40-3daa-9af6-cfa82cfd7229.png)


Rubyインストーラーのインストールが完了すると、下図のような実行画面が出ます。
ここでは表示される選択3つとも全て実行する必要があります。
もう少し具体的にいうと、「1」を入力してEnter、「2」を入力してEnter、「3」を入力してEnter、と全て行う必要があります。
なれている方であれば、半角の「1,2,3」を入力して一度に入力してEnterを押しても同じことなので大丈夫です。
※なおこれが結構時間がかかって20分くらいかかりました...!
![スクリーンショット 2021-03-07 18.53.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553021/aaaaf682-d745-1c17-3eec-29a2800994d6.png)

自動的に画面は閉じると思います。
これでWindowsのRubyインストールは完了です！


###インストールできているか確認
PowerShellから「ruby -v」のコマンドを実行することで、インストールが成功しているか確認できます。
![スクリーンショット 2021-03-05 17.39.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553021/b4acd374-ed7a-c297-2e43-9d342f507c4c.png)

ここではちょっと古い画像を使っていますが、ちゃんと「ruby 2.5.5」と表示されて、インストールができている事が確認できていますね。

今回は以上です！
amplifyの作法 その24

#概要

amplifyの作法、調べてみた。
ハッカソンに、応募してみた。

#githubでつまずいた。

資料をgithubに、上げて提出することになってるが、
```git push origin master```
したら、行方不明になった。
ブランチされてた。
ディフォルトは、mainらしい。

#masterから、mainに移る。

```
git branch -m master main
git merge --allow-unrelated-histories origin/main

```

#mainに、push

```
git push -u origin main
```

以上。
Qiita Daily Survey memo 2021.03.06

# Qiita Daily Survey memo 2021.03.06
Qiita の記事を可能な限り毎日読むために、読んだmemoを公開することでモチベーションを維持しようという試み。

## [無料、独学で機械学習エンジニアになる！~機械学習が学べる無料サイト、書籍~](https://qiita.com/KamikawaTakato/items/73b748414567d27a9c52)
Kamikawa takato さんの記事
タイトルの通り独学で機械学習エンジニアになるためのサイトを紹介してくださっています。
日本語、英語に大きく分かれており、Pythonや数学、機械学習などのジャンルごとに初級～上級者のくらいに分かれて紹介してくださっています。
知っているサイトもいくつかありましたが、多くは名前は知っていましたが見たことがないページでした。
参考になります…！
また、「機械学習やりたいけど、どうすればいい…？」という質問に対しても、紹介させてもらえるような記事だなと思いました。


## [【LINEBOT】LINEの音声メッセージをAmazon Transcribeで文字起こし](https://qiita.com/ay__1130/items/faf95d3f5c96b0612d15)
Ay(ay__1130) さんの記事。
Line - AWS の連携で、しゃべった言葉を文字起こししてみました、という記事になります。
code もフルで記載されており、どこで何の処理をしているかの説明も書いてくださっています。
記事では単語の発声に対して、その文字起こしの結果が書かれていますが、それなりに長い文章でも精度はかなり高いそうです。

自分が試したのは数年前ですが、いくつかの音声の文字起こしを試したところ、日本語でうまくいくのはiPhoneの音声入力くらいでした。
技術の進化が半端ではないので、現代ではどうなっているかもう一度調べてみたいと思いました。
AWS の Amazon Transcribe も本記事で便利そうなのは分かりましたし、精度が出るようであれば使ってみたいと思いました。
ssh ログインをして、リモート先で sudo コマンドを一斉に行う方法

ssh ログインをして、リモート先で sudo コマンドを一斉に行う方法です。

sshpass だけ必要になりますので先にインストールを行います

````bash
sudo apt install -y sshpass ;
````

シェルファイルの作成

````bash
gedit login_and_cmd.sh;
````

以下のコードを保存します。

````bash:login_and_cmd.sh
#!/bin/bash

# 環境変数の指定。ユーザー名とIPアドレスの指定
LOGIN_USER_NAME=myloginname
IP_ADDRESS_ARR=(
  "192.168.0.xxx"
  "192.168.0.xxx"
  "192.168.0.xxx"
)

# コマンド実行にパスワードを格納する
echo -n "Type your password: "
read -s SSHPASS

# IPアドレスの分だけfor文を回す
for IP_ADDRESS in ${IP_ADDRESS_ARR[@]}
do

  # 実際のコマンド
  sshpass -p $SSHPASS ssh $LOGIN_USER_NAME@$IP_ADDRESS -tt << EOL

    echo "${SSHPASS}" | sudo -S hostname
    echo "${SSHPASS}" | sudo -S apt update
    echo "${SSHPASS}" | sudo -S apt upgrade -y
    echo "${SSHPASS}" | sudo -S apt autoremove -y

    exit
EOL

done
````

実行

````bash
bash login_and_cmd.sh ;
````

ちょっとターミナルにパスワードが表示されるのでアレですが、もしかしたらもっとうまく隠せるかもしれません。

####参考リンク
- [シェルスクリプトでリモート先にコマンドを実行する際のTips – inamuu.com ](https://inamuu.com/%E3%82%B7%E3%82%A7%E3%83%AB%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%81%A7%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E5%85%88%E3%81%AB%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%82%92%E5%AE%9F%E8%A1%8C/)
- [sshコマンドでパスワードをオプションとして入力出来るようにする『sshpass』 | 俺的備忘録 〜なんかいろいろ〜]( https://orebibou.com/ja/home/201501/20150126_001/)
- [配列を使用する | UNIX & Linux コマンド・シェルスクリプト リファレンス ](https://shellscript.sunone.me/array.html)
STM32F103C8とOLED、OLED096UNO-AでHello Worldを表示(8x8)

STM32F103C8とOLED、OLED096UNO-AでHello Worldを表示

x mbedが使える人が対象

1.mbedでstm32f303k8をコンパイル出来るようにする。
2.新規プログラムを開く
3.下記のソースを書く。
4.oledのライブラリをインストールする。
Dai YokotaさんのSSD1306_128x64_I2Cライブラリを使用した。
https://os.mbed.com/users/jk1lot/code/SSD1306_128x64_I2C/file/46dcbaa430f4/SSD1306.h/


ライブラリのインストール方法は、
mbedの画面のプロジェクトディレクトリー名の所で右クリックして
新しいライブラリー...を選択してOLED検索画面からDai Yokotaを選択
する。
5.コンパイルする。
6.何らかの方法で書き込む。
7.Hello Worldが表示されたら終わり。

ファイル名
oled_helloworld_8x8_103_1

忙しい人よう
https://os.mbed.com/users/caa45040/code/oled_helloworld_8x8_103_1/

```

#include "mbed.h"
#include "SSD1306.h"

#define ADDR     (0x3c<<1) //  address
//#define ADDR     (0x3d<<1) //  address

//I2C i2c(I2C_SDA, I2C_SCL);
I2C i2c(PB_7, PB_6); // STM32F103C8

// Host PC Communication channels
//Serial pc(USBTX, USBRX); // tx, rx
Serial pc(PA_9, PA_10); // tx, rx 103

// Instantiate OLED
SSD1306 oled(i2c, ADDR);

int main() {       
    pc.baud(9600);    
    oled.writeString(0, 0, "Hello World !");  
    pc.printf("Printed something\r");    
    while(1){}
}


```

![103_mbed_oled_hloo_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/be0b49c6-5733-78c9-3347-c25263e41db1.jpeg)

![103_mbed_oled_hloo_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/ccce5668-468e-b571-674c-ea8a74141dd7.jpeg)

![103_mbed_oled_hloo_3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/f23e3c3a-2012-0a9b-0071-379f800911f9.jpeg)

![103_mbed_oled_hloo_4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/b76a638c-090f-9d14-3a72-4b57c24ec078.jpeg)

![103_mbed_oled_hloo_5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/a0851d77-e870-4de1-a4a5-f24312415e8c.jpeg)

![103_mbed_oled_hloo_6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/459d8d17-7dd0-01e5-5d9d-5338e30d1682.jpeg)

![103_mbed_oled_hloo_7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/41e04c08-2785-b53e-c21f-89e6be1c49d2.jpeg)
Ruby言語とは

本日は、Ruby言語の特徴とメリットデメリットについて
記事を書きたいと思います。

### 特徴
Rubyは、1995年に公開されたプログラミング言語。
日本で開発され、日本初の国際規格で認定されたプログラミング言語。
開発者は、「まつもとゆきひろ」さん。
言語の名前の由来は宝石のルビーからきている。

・インタプリタ方式
実行エンジンがプログラムソースを解析して1行ずつ実行する方式である、インタプリタ方式を採用している。
なので、プログラム作成中に実行できるため、エラーが発見しやすい


・汎用性が高い
汎用性が高く、Web開発以外の現場でも使用されている。その原因は、Windows、Linux、Mac OS等いろいろな環境で動作可能なマルチプラットフォームであるため。
gemと呼ばれるライブラリ群が充実している点が挙げられる。このため、Webシステム以外でも幅広く活用できる。

### メリット
メリットは、文法や書式はシンプルなものを使っているので、初心者でも勉強しやすい。
コードの記述する量も他の言語に比べると圧倒的に少ないため、開発効率も高い。
日本発のプログラミング言語というのもあり学習環境が充実している。
書籍なども多く販売されている。

### デメリット
デメリットでは、処理速度が遅いこと。
インタプリタ方式を採用しているため、先ほど少し話たがコードを1行ずつ訳しながら
実行するため、プログラム全体を訳してから実行するコンパイル方式と比べると処理速度
は遅くなる。
コンパイル方式はコードが複雑なため、記述に時間がかかってしまう。

### Ruby on Railsとは
RubyとRuby on Railsは混同されがちだが別物。
Ruby on Railsとは、Webアプリケーションフレームワークのひとつ。
フレームワークとは、最小コストでwebアプリケーションの開発ができる仕組みのこと。
つまり、Webアプリケーション開発で、「必要となる作業やリソースを事前に仮定し、
用意してある便利なもの」

■Ruby on Railsの理念
・DRY(Don`t Repeat Yourself)
同じコードを繰り返し書くことを避け、保守管理しやすい状態に保ちバグを減らす。

・CoC(Convention Over Configuration)
Ruby on Rails自体で規約を用意しているため、規約に則ったコードを書くことで記述量を少なくすることができ、スピーディーな開発が可能。

Rubyはプログラミング言語でRuby on Railsは開発を効率的に行えるフレームワークと覚えよう。
ちなみに、Ruby言語を使用し作られた有名なものは、Huluやクックパッドなどがある。

以上がRubyについての説明です。
今回は、自分が使用している言語について記事を書いてみたが他の言語についての
記事も書いていきたいなと思いました。
Webスクレイピングの使い方

python3でWebスクレイピングのための勉強

#install
まずは下記を使ってスクレーピングしていきます。
・requests: HTTPライブラリ
・beautifulsoup4: htmlパーサー（pythonから呼び出し）

```
pip install requests
pip install beautifulsoup4
```

##インストールの確認
```
pip freeze | prep -e request -e beautiful
beautifulsoup4==4.6.0 
requests==2.18.4
```

#使い方
```python
import requests 
from bs4 import BeautifulSoup
```

次に、HTMLを取得していきます。

```python

url = 'https://www.google.com/'

# web情報を取得し、その結果を変数rに格納
r = requests.get(url, headers={'user-agent': '[chrom-version]'})
```

[chrom-version](chrome://version/)を検索！

htmlパース用のオブジェクトを作成します。`html.parser`を使う

```python
#HTMLを解析している。
#res.textとはwebサイトの情報を取り込む　
soup = BeautifulSoup(r.text, "html.parser")
#print(soup.prettify())を使えばHTMLが整った状態で表示される。
```

#特定のタグを取得
先ほどまででhtmlの全ての情報を取得することができた。しかしここままでは使いづらいので特定のタグの取得方法を学ぼう。

```python
soup.find("a")  #最初のaタグを取得
soup.find_all("a") #全てのタグを取得
soup.find_all("a", attrs={"class":"link", "href":""/link}) #属性を辞書形式で指定できるattrsを使えばカスタムデータ属性に対応できる.

今日の課題
instagramscrapeを使って
【LOG】macOS｜Selenium-chromedriverのプロセスが残ってしまった際の対処方法

# はじめに
* `quit()メソッド` で `chromedriverプロセス` を終了するようにしても、処理途中でエラーになれば、プロセスが残ります…
* プロセスが残ると、OSのリソースを圧迫してしまうため、プロセスの終了方法を記載しておきます🕺

# 環境
* `macOS BigSur Version ： 11.2.2`
* `Selenium : 3.141.0`
* `chromedriver-binary : 89.0.4389.23.0`

# 一連の流れ
* 残ってしまったchromedriverプロセスの確認
* chromedriverプロセス全てを終了
* chromedriverプロセスが終了されたか確認して完了🕺

---

#1. ターミナルで `ps aux | grep chromedriver` コマンドを実行
* 以下の例は1つしかありませんが、`chromedriver --port=xxxxx` が該当のプロセスです

```
% ps aux | grep chromedriver

user        33263   0.0  0.1  4388096   6064 s000  S    12:16PM   0:00.10 chromedriver --port=xxxxx
user        33442   0.0  0.0  4278648    704 s000  S+   12:20PM   0:00.00 grep chromedriver

```

#2. `killall` コマンドで `chromedriverプロセス` を終了

```
% killall chromedriver
```


#3. `chromedriver --port=xxxxx` が終了
* ばっちり消えましたね🕺 お疲れ様でした！

```
% ps aux | grep chromedriver

user        33462   0.0  0.0  4259000     12 s000  S+   12:21PM   0:00.00 grep chromedriver
```
【LOG】macOS｜JupyterLabをダークテーマにして、JupyterNotebookセル行ごとに通し番号表示設定にする

# 環境

* `macOS BigSur Version ： 11.2.2`
* `pip3 Version ： 21.0.1`

#1. `JupyterLab Light` → `JupyterLab Dark` に設定
* `Settings` → `JupyterLab Theme` → `JupyterLab Dark` で設定する

![JupyterLab.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181400/f7df6c9b-c7bc-5b76-7286-6ae266299fe1.png)

***

![スクリーンショット_2021-03-05_11_35_19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181400/94ebcd2c-0449-6e14-bf44-b651c83e0cc8.png)

#2. セル内、行ごとに通し番号表示を設定
* `Settings` → `Advanced Settings Editor` → `Notebook` → `User Preferences` に 以下を貼り付ける

```
{
     "codeCellConfig": {
        "lineNumbers": true
     }
}
``` 

* 以下、手順画像
* 
![スクリーンショット_2021-03-05_11_50_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181400/cb02a7b0-9ec6-dc9e-2f48-57ab2549c36f.png)

***

![スクリーンショット_2021-03-05_11_42_19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181400/55925839-ee64-985a-addf-a7eb954e086a.png)

***

![スクリーンショット_2021-03-05_11_42_39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181400/3d429080-80df-98de-f1fa-a6402127d29b.png)

***

![スクリーンショット_2021-03-05_11_42_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181400/b6e3aebd-e58e-eabd-3fa9-592a4fa1ed35.png)

***

![スクリーンショット_2021-03-05_11_43_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181400/2d9e4cda-b4bf-0a73-8e2a-56a0866e7133.png)
【LOG】macOS｜pip3でJupyterLabインストール→起動→終了

# 環境

* `macOS BigSur Version ： 11.2.2`
* `pip3 Version ： 21.0.1`

#1. JupyterLabインストール
`pip3 install jupyterlab` コマンドで `JupyterLab` をインストールする（1〜2分で完了した）

```
% pip3 install jupyterlab
```

#2. JupyterLabを起動
`jupyter lab` コマンドで起動する
Chromeで、`JupyterLab` が立ち上がる

（Safariで立ち上がる場合、ターミナルに表示された `http://localhost …` で始まるURLを
　ブラウザURL入力窓に入れれば開けました🕺）

```
% jupyter lab
```

#3. `JupyterNotebook` を起動
表示された画面の `Notebook下 Python` を選択すれば、お待ちかねの `JupyterNotebook` 編集画面が立ち上がります🕺

![スクリーンショット_2021-03-05_0_08_53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181400/d4d4b8fe-e78c-7795-1586-ed6a1c8b97c2.png)

***

![スクリーンショット_2021-03-05_0_11_58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181400/9bac534b-563d-7811-8f47-fa8346896bda.png)

#4. `JupyterLab` を終了
`JupyterLab` 起動時に以下表示があったので、ターミナルにてショートカットキー `control + C` を実行し、
`Shutdown this notebook server (y/[n])?`  と聞かれるため、 `y → Enter` で答えて、 `JupyterLab` を終了する

※ `JupyterLab` の `画面左上 「FILE」 メニュー → Shut Down` からでも終了できるようです🕺

```
Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
```
【LOG】pip自体をアップデートする

# 環境

* `macOS BigSur Version ： 11.2.2`
* `pip3 Version ： 10.0.1`

#1. `You should consider upgrading via the 'pip install --upgrade pip' command.` の表示

`pip3` コマンドでパッケージをインストールしたら、 `pipをアップデートしなさい` と表示されました。

```
% pip3 install selenium

You are using pip version 10.0.1, however version 21.0.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
```

#2. `pip自体` をアップデート
というわけで、 `pip3 install --upgrade pip` コマンドで `pip自体` をアップデートしました。
久しく、自宅PCでpipをいじっていなかった…これからはもっと触れ合おうと思います🕺

```
% pip3 install --upgrade pip

Collecting pip
  Using cached https://files.　 【 〜〜〜　長いので中略　〜〜〜 】 　/pip-21.0.1-py3-none-any.whl
Installing collected packages: pip
  Found existing installation: pip 10.0.1
    Uninstalling pip-10.0.1:
      Successfully uninstalled pip-10.0.1
Successfully installed pip-21.0.1
```
【LOG】macOS｜Anaconda3 アンインストール

# 環境

* `macOS BigSur Version ： 11.2.2`
* `pip3 Version ： 10.0.1`

#1. `Anaconda3` がどこにインストールされているかを把握する
`env | grep CONDA` コマンドで、 `Anaconda3` が `/anaconda3 配下` にインストールされていることがわかる

* `CONDA_PREFIX` から Anaconda3 が /anaconda3 にインストールされていることがわかる
* `CONDA_PYTHON_EXE` からも /anaconda3 配下に Python があることがわかる

```
% env | grep CONDA

CONDA_EXE=/Users/（各自のユーザーネーム）/opt/anaconda3/bin/conda
_CE_CONDA=
CONDA_PYTHON_EXE=/Users/（各自のユーザーネーム）/opt/anaconda3/bin/python
CONDA_SHLVL=1
CONDA_PREFIX=/Users/（各自のユーザーネーム）/opt/anaconda3
CONDA_DEFAULT_ENV=base
CONDA_PROMPT_MODIFIER=(base)
```


#2. `conda` コマンドで `anaconda-clean` をインストールする

```
% conda install anaconda-clean
```

#3. `anaconda-clean` コマンドを実行して、全てに `y → Enter` を入力して、対象フォルダを削除する

```
% anaconda-clean

Delete .anaconda? (y/n): y
Backup directory: /Users/（各自のユーザーネーム）/.anaconda_backup/2021-03-04T131006
Delete .conda? (y/n): y
Delete .condarc? (y/n): y
Delete .idlerc? (y/n): y
Delete .ipynb_checkpoints? (y/n): y
Delete .ipython? (y/n): y
Delete .jupyter? (y/n): y
```

#4. `.anaconda` を削除後に生成される `.anaconda_backup` が不要な場合、削除する
私は削除しました🕺

```
% rm -fr ~/.anaconda_backup
```

#5. `Anaconda3` ディレクトリを削除する
```
% rm -fr /anaconda3
```

#6. `Anaconda3` への `Path` を追加している記述も削除する
`# added by Anaconda3 2019.10 installer` から `# <<< conda init <<<` までを削除しました🕺

```
# added by Anaconda3 2019.10 installer
# >>> conda init >>>
# !! Contents within this block are managed by 'conda init' !!

　　〜〜　略　〜〜

# <<< conda init <<<
```

#7. アプリケーションディレクトリの `Anaconda-Navigator.app` というショートカットを削除する
JsでUnixタイムスタンプを取得する

# JavascriptでUnixタイムスタンプを取得する

firebaseを使うにあたってタイムスタンプ変換を学習したので備忘録的に残すことにしました。

## Unixタイムスタンプとは
UTCで1970年1月1日 00:00 からの経過時間のこと
単位は秒数

## タイムスタンプを取得する

現在時刻のタイムスタンプを取得

```js
console.log((new Date().getTime())/ 1000 ); 
```

指定した時間のタイムスタンプを取得

```js
let d = new Date(2000,3,1,10,30).getTime()); 
//getTime()ではミリ秒で取得されるので、1000で割ります
console.log(Math.floor( d / 1000 ));
```

### 逆にUnixタイムスタンプからDate型へ

```js
const dateTime = new Date(timestamp * 1000)
```

### momentを使用して楽に取得・変換を行う

```js
// 取得
moment().unix() 

// 変換
moment.unix(timestamp).format()
【コードリーディングのお供】じつはRubyDocは任意のGitHubリポジトリのyardドキュメントを生成できる。とても便利！

## はじめに

　この記事は自分が何年も気が付かなかったRubyDoc.infoの便利機能について書きます。

　みなさんは、GitHubで新しいRubyのプロジェクトを見た時に何をしますか？　私はYardでドキュメントを生成してモジュールやクラスの構成をつかもうとします。Yardはプロジェクトの全体構造を把握するのにとても便利です。RubyのGemのYardドキュメントは[RubyDoc.info](https://www.rubydoc.info) というサイトでオンラインで読めるようになっています。

## RubyDoc.info で任意のGithubリポジトリのドキュメントを表示する

　RubyDocでは、GemだけでなくGithubという項目があります。ところが、全部のRubyリポジトリが登録されているわけではなく、一部のレポジトリしか閲覧できません。実は、RubyDock.info には Add Projectボタンがついていて、任意のGithubリポジトリを追加できます！

（ご存知でしたか？　私は今日までこれに気付きませんでした。RubyDoc側が何らかの基準で表示できるGithubのレポジトリを選定していると思い込んでいました！）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/1bbb40c7-c11f-557f-0d15-3cb5630f1ab0.png)

Add Projectボタンを押すと、下のように任意のGitHubのリポジトリを追加できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/4a612409-22b9-3c73-4fdf-b0f53d6a6a93.png)

　この機能を活用すれば、短時間のうちに任意のGitHubのリポジトリのコードの構成を把握する作業がブラウザで完結できるようになります。

　やったね！

　しばしばRubyはコードは書きやすく読みにくい、と言われます。Rubyは記法に緩さがありますので、確かにそのような側面もあると思います。しかし、YardDoc.infoのような便利なサイトを活用すれば、コードを読むのがかなり楽になるのではないかと思います。

　この記事は以上です。

#### 関連記事

https://qiita.com/kojix2/items/08a8c02bfb0f23b972b6
【Rails】データが作成された時間によってビューの表示を条件分岐する

# 環境
macOS: Big Sur Ver11.2.2
Rails: 6.0.0
Ruby: 2.6.5

# やりたいこと
作成中のWebサービスのトップページに新着のお店を掲載しています。
そこで、３日以内に登録された店舗であれば「NEW!!」の表示をしたいなあと思い、条件分岐の方法を探りました。

# 結論
今回実装したのは、３日以内に登録された新規ユーザーであれば「NEW!!」の表示をするというもの。
結論、以下の記述で簡単に条件分岐できました。

```erb
<div class="contents-box">
  <div class="image-box">
    <%= image_tag user.image, class: "contents-image" %>
  </div>
  <h3 class="contents-title">
    <%= user.shop_name %>
  </h3>
  <p class="contents-price">
    <%= user.category.name %>
  </p>
  <%# お店の登録が３日以内であればnewマークを表示 %>
  <% if user.created_at > 3.days.ago %>
  <p><i class="fas fa-star"></i>NEW!!</p>
  <% end %>
</div>

```

実装した結果がこちら！
テストデータなので、全部NEW!!が表示されていますが、ご容赦ください。
![8f9c95c9b443a9523e700afe9ca2afd5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/788596/982ddf07-d284-ee39-6c0e-4263b959b986.png)


以上！
[swift] 型とその要素のデフォルトのアクセスレベル

理解していなかったのでメモ。

## アクセスレベルの種類

- open
- public
- internal
- fileprivate
- private

## 型のデフォルトアクセスレベル

- internal

## 型のアクセスレベルとその要素のデフォルトアクセスレベル

|型|要素|
|:-:|:-:|
|open|internal|
|public|internal|
|internal|internal|
|fileprivate|fileprivate|
|private|private|

## ユニットテストの場合
ユニットテスト側でimportする際に`@testable`をつけると、テスト対象クラスがinternalでもユニットテスト側で読み込める。
`@testable import MyClass`

## 参照

https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html
RakeタスクのテストをRSpecで書く

# はじめに
開発環境にダミーデータを入れてテストする際に、「SQLのINSERT文を実行！」などはせず、rakeを使ってコマンドラインからデータを作成するようにしてみましたので、記録として残します。
# rakeタスクファイルの作成
※ 今回はuserのインスタンスを作成するケースで進めていきます。



```
rails g task task_user
```

# rakeファイルの編集

```ruby:task_user.rb
namespace :task_users do
 desc "create user"
 task :create_user, ["name", "email", "password"]=> :environment do |task, args|
   user = User.new(
       name: args[:name],
       email: args[:email],
       password: args[:password]
   )

   user.save!
end
```

# RSpecでテストを書く

※説明上rakeファイルの編集から記載してありますが、実際にコードを書いていく際はテストから書いた方がいいです。

```ruby:task_users_spec.rb
require 'rails_helper'
require 'rake'

describe "TaskUsers" do
  before(:all) do
    @rake = Rake::Application.new
    Rake.application = @rake
    Rake.application.rake_require 'tasks/task_users'  #specディレクトリ内の/lib以下のパスを指定します
    Rake::Task.define_task(:environment)
  end

  before(:each) do
    @rake[task_name].reenable
  end

  context "create user" do
    let(:task_name) { 'task_user:create_user' }
    let(:name) { "kantai" }
    let(:email) { "hogehoge@.hoge.jp" }
    let(:password) { Faker::Alphanumeric.alphanumeric(number: 10) } # ランダムな数列を作成しています

    # matcherは、「Userのレコードが1増えているかどうか」という条件で設定しています。
    it "created user" do
      expect{ @rake[:task_name].invoke(name, email, password).to change(User, :count).by(1)
    end
end
```

# コマンドで実行

```
rake 'task_users:create_user[name,email,password]'
```



# おわりに

なかなかrakeを使ってコマンドからレコードを作成するケースは少ないかと思いますが、チームでドキュメントとして残しておくことで、レコード作成を属人化することなく誰でも作成しやすくできるのが良い点かなと思います。

# 参考

- [RailsでRakeタスクの作成](https://qiita.com/suzuki-koya/items/787b5562d2ae1a215d94)

- [Rakeタスクの実装](https://qiita.com/yoshito410kam/items/26c3c6e519d4990ed739)

- [rake taskの作り方と、意外とハマりがちな引数の扱い](https://bottoms-programming.com/archives/rake-task-handling-of-arguments.html)

- [Rakeタスクのテストの仕方](https://qiita.com/kawakubox/items/26cf71a14bd5827175f6)

- [RailsでRakeタスクをシンプルかつ効果的にテストする手法](https://qiita.com/aeroastro/items/c97bd26ce8b8818b6bed)

- [【RSpec】Rakeのテストの書き方](https://ayacai115.hateblo.jp/entry/2018/12/09/092105)
[iOS] ダークモードを考慮したAsset Catalogの管理

本記事では、Swiftの画像の命名規則とAsset Catalogのフォルダ構成について、個人で最適だと考える方法について説明します。

# 画像の命名規則について
## 注意点
本記事では，画像のパターンが2種類あります。
例）sampleという画像の名前の場合
Asset Catalog内の画像
→ sample

Asset Catalogに追加する前の画像
→ sample.png

## 命名規則
#### 画像の命名は以下で統一
スネークケースを使用

- `ic_画像名_修飾.png`
    - 小さめなアイコンの画像
    - 例: `ic_star_fill.png`
- `img_画像名_修飾.png`
    - 大きめなillust, logoなどの画像
    - 例: `img_logo.png`

修飾について以下の例があります。
- fill
- off/on

#### ダークモード用の画像の場合
語尾にdarkを付ける
- `ic_画像名_修飾_dark.png`
- `img_画像名_修飾_dark.png`

**ダークモード用の画像分けて命名する理由**
iOSでは，同じ命名で各モードの画像をAsset Catalog内に追加すると，〇〇-1.pngのように重複によって番号が付与されてしまう．
内部的に不都合が生じるため，ダークモード用の画像の命名が必要である

## Asset Catalogのフォルダ
現在のAsset Catalog内のフォルダ構成は以下の通りです。

**Assets**

- iconフォルダ
    - `ic_画像名`
- imageフォルダ
  - `img_画像名`
- colorフォルダ
ローカル環境でのGithub連携方法

#はじめに
ローカル環境でのGithub連携方法についてまとめました。
railsアプリをGithubに連携させるためには、gitの知識も必要なため、gitを含めて説明します。

#到達点
以下の2点を達成する
・gitが使えるようになる
・railsアプリをGithubに連携させる

#流れ
① railsアプリを作成
② Github新規登録し、リポジトリを作成
③ gitコマンドを行い、連携させる

#① railsアプリを作成
手前味噌ではありますが、私の記事を参照すると、ローカル環境でのrails環境構築ができます。
[ローカル環境開発　Ruby on Railsの環境構築方法](https://qiita.com/holdout0521/items/1126ab7ae81a08eaf03d)

　　
#② Github新規登録し、リポジトリを作成
###Githubを新規登録し、新しいリポジトリを作成する。
以下の画像の赤枠の New もしくは　New repository をクリックしてください。

<img 　height='300' alt="スクリーンショット 2021-03-01 19.29.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/8c49e3e8-929e-0d3a-b4f9-fff1532d03b5.png">

Repository nameは、自身のアプリ名(rails new `アプリ名`)を入力し、Create Repositoryをクリックしてください。

<img width="400" alt="スクリーンショット 2021-03-01 19.24.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/4e815d06-7f8c-e11b-52ea-e5deb9f2834b.png">

#③ gitコマンドを行い、連携させる

```
$ cd 自分のアプリ名
$ git init
$ git status   #作業ディレクトリでの現在の状態を表示する
$ git diff     #差分を見る
$ git add ..   #すべてのファイル・ディレクトリ
```

git addでファイルをstagedという状態にします
git add する前に変更した箇所とインデックスとの変更点を必ず確認しましょう

　　

```
$ git commit -m "Initialize repository"
```
git commitでローカルレポジトリにコミットします
git commit -m"コミット名" でコミット名が作成できます。


```
$ git remote add origin http://Github.com/GitHubで作成したID/リポジトリ名.git
$ git push -u origin master

```
git pushで、ローカルレポジトリの内容がリモートに反映されます。
Githubのページからも確認しましょう。

#参考記事
[今日からはじめるGitHub 〜 初心者がGitをインストールして、プルリクできるようになるまでを解説]
(https://eh-career.com/engineerhub/entry/2017/01/31/110000)
環境構築　4　MySQL

#MySQLの導入

#1. MySQLのインストール
ターミナルに入力

```
% brew install mysql@5.6
```

#2. MySQLの自動起動設定
自動で起動するように設定する。

```
% mkdir ~/Library/LaunchAgents 
% ln -sfv /usr/local/opt/mysql\@5.6/*.plist ~/Library/LaunchAgents
% launchctl load ~/Library/LaunchAgents/homebrew.mxcl.mysql\@5.6.plist
```

#3. mysqlコマンドをどこからでも実行できるようにする
rbenvやreadlineの時と同様に、どこからでもMySQLを操作するためのコマンドmysqlを実行できるようにする。

```
% echo 'export PATH="/usr/local/opt/mysql@5.6/bin:$PATH"' >> ~/.zshrc # mysqlのコマンドを実行できるようにする設定
% source ~/.zshrc #  設定を読み込むコマンド
% which mysql # mysqlのコマンドが打てるか確認する

# 以下のように表示されれば成功
/usr/local/opt/mysql@5.6/bin/mysql
```

#4. MySQLの起動を確認

```
% mysql.server status # MySQLの状態を確認するコマンド

# 以下のように表示されれば成功
 SUCCESS! MySQL running
```
環境構築　3　Rubyのインストール

#Rubyの環境構築
#1. rbenv と ruby-buildをインストール
rbenvとruby-buildを、Homebrewを用いてインストールします。

ターミナルに入力

```
% brew install rbenv ruby-build
```

#2. rbenvをどこからも使用できるようにする
PCにおけるどこの場所からも使用できるようにする。

```
% echo 'eval "$(rbenv init -)"' >> ~/.zshrc
```

CatalinaかMojave以前の方で、設定ファイルの場所が個々で異なるのでご注意。

#3. zshrcの変更を反映させる
zshrcを再読み込みし、変更を反映させる。

```
% source ~/.zshrc
```

#4. readlineをinstallしよう
日本語入力を可能にする設定。

```
% brew install readline
```

#5. readlineをどこからも使用できるようする

```
% brew link readline --force
```

#6.rbenvを利用してRubyをインストール
Webアプリケーション開発用のRubyをインストール。

```
% RUBY_CONFIGURE_OPTS="--with-readline-dir=$(brew --prefix readline)"
% rbenv install 2.6.5
```

処理に10分程度かかる可能性あり。
2.6.5と書いてあるのは今回インストールするRubyのバージョン。

#7. 利用するRubyのバージョンを指定
インストールしたRuby 2.6.5を使用するため。

```
% rbenv global 2.6.5
```


#8. rbenvを読み込んで変更を反映
rbenvを読み込み、変更を反映させる

```
% rbenv rehash
```

#9. Rubyのバージョンを確認
正しくバージョンを指定することができたか確認。
先ほどインストールした2.6.5であることが表示されれば完了。

```
% ruby -v
```
CORSのエラーで困った。

CORSのエラーで困った

Jqueryのajaxを使ってhttp通信しています。gasを使ってスプレッドシートに書き込みをしています。
CORSエラーに関してはたくさんの記事があったので参考の一つになれば嬉しいです。
まだわかっていないとこも多いですがとりあえず解決できたところに注目して書いてみました。


原因は
**単純リクエストで良いはずのリクエスト内容なのにoptionメソッドが呼ばれてしまっていた。**

改善策
書きすぎていた余計なことを消す。

いろいろな記事を参考にしながら手探りでやってしまったせいで余計なものをたくさん書いてしまっていました。

http通信には2種類あるようです。「単純リクエスト」と「プリライトリクエスト」です。
二つの違いは[公式サイト](https://developer.mozilla.org/ja/docs/Web/HTTP/CORS)を見てください！

単純リクエストを実装したい場合にとにかく書いて良いのは、
https://developer.mozilla.org/ja/docs/Web/HTTP/CORS
この公式ドキュメントの「単純リクエスト」のところに書いてあるものだけ！！！

一つでも余計なものを書いてしまうとプリフライトリクエストが送られて、実行したいpostメソッドやgetメソッドのまえにOptionメソッドが呼ばれてしまいます。
下の写真で言うと、コメントアウトされているものは単純リクエストの際には書いてはいけないものです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569820/ebbe31e2-1530-2c28-63ce-448f27406580.png)
￼


参考記事
https://qiita.com/im36-123/items/775aa7fd4ba3b171768c
https://developer.mozilla.org/ja/docs/Web/HTTP/CORS
Minecraftで葉っぱを風で揺らそう！

前回：[光に色をつける方法](https://qiita.com/MCH_YamaRin/items/b086544a0c5891b26131)
次回：未定

#はじめに

**風で葉っぱなどの植物が揺れる！**

これも影Modならではの要素ですよね。

**今回はVertexシェーダーを使って、葉っぱを風で揺らしてみましょう！**

#Vertexとは？

今まではFragmentという、主に色を担当するシェーダーファイルをいじっていたのですが、**Vertexは座標系の操作をするシェーダーになります。**

形を変えたり移動させたりしてくれるものだと思ってくれて構いません。

それではいじっていきましょう！

#基本

今回は、主に地形の座標系を操作する「gbuffers_terrain.vsh」を編集していきます！

```glsl
#version 120

varying vec2 lmcoord;
varying vec2 texcoord;
varying vec4 glcolor;

void main() {
	gl_Position = ftransform();
	texcoord = (gl_TextureMatrix[0] * gl_MultiTexCoord0).xy;
	lmcoord  = (gl_TextureMatrix[1] * gl_MultiTexCoord1).xy;
	glcolor = gl_Color;
}
```

基本的な構文はFragmentと変わらないです。

```glsl
gl_Position = ftransform();
```

これで「ftransform()」という基本的な座標の情報を「gl_Position」に入れることで、Minecraftの座標の情報が決定されています。

**直接「gl_Position」を編集し、風の表現をしていきましょう！**

#風の表現

葉っぱを風で揺らしていくのですが、Minecraftには風なんて無いですよね。

風の代わりに、**「frameTimeCounter」という、ゲーム起動時からの時間の情報が入っている変数を使います！**

「frameTimeCounter」はそのままでは使うことができず、「uniform」で呼び出す必要があります。

```glsl
uniform float frameTimeCounter;
```

「void main() {」よりも上にこれを書くと、呼び出すことができます！

**「frameTimeCounter」はそのままだと使いずらいので、「sin()」という関数を使って周期的にします。**

```glsl
gl_Position.x += sin(frameTimeCounter);
```

こちらのコードを書いてみましょう。

「=」や「*=」を使うと座標の根幹が変わってしまうので、「+=」で足し算しています。

![5ap9e-dvwic.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1087947/0797c6d1-5430-2c7c-7389-2863cf14edfa.gif)


何も指定していないので、すべてのブロックが揺れています...

**葉っぱだけを指定するために、「mc_Entity」を使用して、ブロックのIDを選択します！**

```glsl
attribute vec4 mc_Entity;
```

「mc_Entity」は、「uniform」と同じような感じで「attribute」で定義すれば使えるようになります。

```glsl
if(mc_Entity.x == 18.0){
gl_Position.x += sin(frameTimeCounter);
}
```
葉っぱのデータは18なので、ifを使って葉っぱを指定します。
（ブロックのIDは、mc_EntityのX座標に入っています）

MinecraftのWikiにIDの情報が載っていたので、参考にしてみてください。
(ここに書かれているIDはすべて正確ではないので、そこは自力で探し出すしかないようです...)

[Wikiはこちら](https://minecraft-ja.gamepedia.com/Java_Edition%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E5%80%A4/%E5%B9%B3%E5%9D%A6%E5%8C%96%E5%89%8D/%E3%83%96%E3%83%AD%E3%83%83%E3%82%AFID)

![f53f0-kxw7a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1087947/34ed2d39-0058-ebde-5b17-4ef2cc4f5665.gif)

葉っぱだけ動かせましたが、揺れが大きすぎですね...

```glsl
if(mc_Entity.x == 18.0){
gl_Position.x += sin(frameTimeCounter*3.0)*0.02;
}
```

少し調整してみましょう、

![6f9o3-8isi5.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1087947/89829239-587d-9465-0762-e41504232a5c.gif)

だいぶマシになりましたが、まだまだ動きが単純ですよね...

**チャンクの座標を使って、動きを複雑にしてみましょう！**

```glsl
if(mc_Entity.x == 18.0){
gl_Position.x += sin(frameTimeCounter*3.0 + gl_Vertex.x + gl_Vertex.y + gl_Vertex.z)*0.03;
}
```

**「gl_Vertex」に、チャンクの座標の情報が入っています。**

上のコードでは、X、Y、Zの情報を一気に足すことで動きを複雑にしています。

それでは動かしてみましょう！

![sfccw-22p3e.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1087947/14555310-35de-151d-161d-293b750e9f84.gif)

いい感じに揺らせましたね！

数値は好きなように調整してください！

このままだと洞窟などの屋内でも揺れてしまうのですが、前回までに学んだことを使えばきっと改善できるはずです...

#おわりに

葉っぱを揺らすことによって、Vertexシェーダーの基礎を学べたかと思います！

それでは次回で会いましょう！さようなら～