OmniAICreator/Qiita-1.07M huggingface dataset:
写真とUIデザインの意外な共通点　



1年ぶりです、Classi Advent Calendar 2020 7日目は、デザイナーの@shio312が毎年のいつもの記事とはちょっと違った味でお送りします。

# はじめに 
去年度から今年度にかけて、他部署の方に
「デザイナーの頭の中身ってどうなってるの？」とか、
「特にUIのような画面を起こす人君たち（特に私）の頭はどんな構成なんじゃ？」
とよく訊かれました。

と言うわけで、UIデザイナーの頭をかち割って中身を見せることはできないので、今年は自分はこんなふうにUIに紐づけて世界を見ていますよ、という実例を紹介しようと思います。

**写真で。**

「エッ？関係あんの？」
と思われるかもしれませんが、趣味として嗜む方も多い写真を例にお話しする事で、少しでも画面デザイナーに共感と親近感を覚えていただけると嬉しいなと思い、挑戦としてお話ししてみようと思います。

ちなみに、UI関連に携わるデザイナー皆が皆そうではないことだけは事前にご理解の上、拝読くださいね。

##4枚の写真を用いた実例紹介するよ
さてここに私自身が撮影した4枚の写真があります。
**----A----**
<img width="500" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132799/a19e044e-2d84-1194-5732-373bca95b777.png">
**----B----**
<img width="500" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132799/d148ae19-4118-441f-2340-2546fc699209.png">
**----C----**
<img width="500" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132799/07516193-7259-efe1-ea78-5ef13dbec1f2.png">
**----D----**
<img width="300" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132799/abcc0f90-3753-c49a-c1ce-ae7c2f16315f.png">

母と京都の南禅寺に行った際に撮った写真たちです。いや〜良い紅葉でした🍁

うん、写真を通じて友人に古都自慢したいな！

**よし、今から記載の写真のどれが一番<font color="Red">"秋の古都の魅力"が伝わるか</font>考えたいと思います。**
**↓**
**とすると、<font color="Red">1枚だけで秋の古都の魅力を伝える</font>という目的を達成するための<font color="Red">最低要件</font>は
以下3点が最低情報として写真に収まっていると分かりやすいと考えます**

**要件**
1. 画面に収まる建築物によって（おおよそ）直感でここは古い街だと言うことが分かること
2. 画面に収まり赤や黄色の紅葉が秋だと直感で分かること
3. 感情的に秋の終わりらしい古都の趣きが写真を通じて見る人に伝わること

##A〜Dの写真の考察##
**----A----**
紅葉がいっぱいある、秋だなきれいだな！けれど、場所がわからんしどこだよ此処
**----B----**
なんか古そうな建物もあるし紅葉もあるな、写真としても画角も良いしカッコええんじゃないか？
ただ天気良すぎて視線がそっち行くな...古都らしい雰囲気はCより下か？
**----C----**
Bほど写真としてのカッコよさはないけど、奥に古い建物（南禅寺の三門）があるし紅葉もあるな？
**----D----**
紅葉の絨毯が綺麗だけど、古木の渋さを伝えたいわけなじゃいんだ、目的がちがうぞ！

となります。
**BとCが目的達成に近そうですね。**
ここで写真A〜Dが要件をどれだけクリアしているか星取表を作ってみましょう。

| 必要用件 | 要件1 | 要件2 | 要件3 |
|:------:|:--:|:--:|:--:|
|  A |  × | ◯  | ×  |
|  B |  ◯ | ◯  | △  |
|  C |  ◯ | ◯  |  ◯ |
|  D |  × |  ◯ |  × |

はい、こうなりました。
画としてはBの方が奇をてらった面白い画ですが、**<font color="Red">要件の達成度としてはCに軍配が上がりました。</font>**

**マジか〜（本音）**

此処で思い出してみましょう。
Bの写真ですが、「ぱっと見イケてるサイト/アプリなんだけど、あともうちょい分かりやすいUIだったらな〜ファストビュー内にフォームとボタンがあったらな〜（使い勝手の要件が満たされていない）」
と同じ状態というわけです。

Cの写真は素人丸出しかもしれません。正直写真としては品質が微妙です。
けれど、**自分の目的における要件を達成しているのはCということになります。**

このあとも納得いく写真を求めて沢山撮りました。
先ほど結論づけた結果から、目的達成のための必要条件をクリアしながらも、更に画として目に入る情報の順番が（無理やり言い換えると情報設計ですね）より分かりやすい、そして品質の高い画を作るために私は写真のファインダーを絞っていきました。
目的が達成された品質の高い写真を見た友人との楽しい会話を想像しながら。

と言った感じで私はUIを「使う人がどうやって何ができるか、そして結果笑顔が生まれるか」を考えて画面に落とし込んでいっています。


#こんな感じでした、ジャンジャン。
写真や近代絵画などでも「何を伝えたがっているのか」を意識して見てみると、今まで思いもしなかった視点に気がつくかもしれません。
そんなの当たり前だよ〜と思う方が多いかもしれませんが、ぜひ改めて試してみてはいかがでしょうか。
機材で表現を広げるのも手ですが、同じ機材でどこまで伝え方の幅を広げるか工夫を凝らすのも中々楽しいもんです。


モノや絵画、写真、空間においても存在している、人と人とのコミュニケーションを産み、つなぐインターフェース。
そう考えると、この仕事の可能性とそれに携わることができている自分が誇らしいなあと思えます。

これを読んだ方の物づくりの楽しさの視野が、ほんのちょっと広がると私は嬉しいです。
それでは、良いお年を。
CentOS8でCockpitをインストールする


## インストール

```
dnf install -y cockpit
```

## サービス起動
```
systemctl start cockpit.socket
systemctl status cockpit.socket
systemctl enable --now cockpit.socket
```

## ファイアウォール開放
```
firewall-cmd --add-service=cockpit --permanent
firewall-cmd --reload
```

## アクセス
`https://192.168.11.223:9090`へアクセス

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293481/e43c3d5c-f3fd-9dfa-e81b-9478b55ebe30.png)

## ログイン
OSにログインするユーザー（root）でログイン

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293481/0057d838-bf3b-8b2b-01f0-56cf9c187721.png)
WSL2 のDocker for Windowsで動作が重い時の原因と対処方法

# 問題：WSL2のDocker for Windowsの動作が重い・・・
Windows10 Homeの環境に、WSL2でDocker for Windowsがインストールできるようになって、よかったなぁと思って使っていたら、Dockerコンテナの動作が遅かったり、Docker buildコマンドでイメージ作成がにやたらと時間がかかったりするようで、なんだかおかしいなと思っていました。

# 原因：WindowsとWSL2(Ubuntu)のファイルシステム変換処理に時間がかかっていた。
これまで、ソース群をWindowsの「C:\Source\Project」みたいなところに入れてました。WSL2（Ubuntu）では、この場所は「/mnt/c/Source/Project」に該当します。
実はこのように「/mnt/」以下の場所は、WindowsのファイルシステムからWSL2(Ubuntu)のファイルシステムに変換かける処理が発生するようで、このために動作がめっちゃ遅くなってたようです。

# 対処方法：ソース群をWindowsファイルシステム配下のフォルダから、WSL2(Ubuntu)ファイルシステム配下のフォルダに移動させる。
WSL2とDocker for Windowsがこの問題を解決してくれたら良いのですが、まだ対応方法がないようです。
現状のベストプラクティスとしては、ソース群をWindowsファイルシステムである「/mnt/」以下に配置せず、WSL2(Ubuntu)のファイルシステム管理下のフォルダに配置して、Dockerを動作させることみたいです。

私の場合Ubuntuのbashで、 mvコマンドを使い、「mv /mnt/c/Source/Project /home/username/Source」みたいなコマンドで、ソース群を「/home/username」配下に配置しました。
このファイル移動はファイルシステム変換があるため、かなり時間がかかります。

ファイル移動の後、Dockerコンテナを起動して動作を確認したところ、軽くなっていました。
また、Docker buildコマンドでイメージ作成したところ、COPYコマンドがめっちゃ早くなり、使用上耐えられるまでのビルド速度になりました。

# ファイル操作とGit操作にはVisual Studio codeを使う。
Windowsファイルシステム配下のフォルダから、WSL2(Ubuntu)ファイルシステム配下のフォルダに移動するということは、WindowsのGUIでどうやって使うようにするかが問題になります。

Windowsのエクスプローラーで使いたい場合は、パスに「\\\\wsl$」を入れると、ネットワークフォルダとして表示させることができます。
しかしエクスプローラーでは、ファイルシステム変換がかかるため、1つ1つのファイルを操作するにはいいですが、まとめてファイルを操作するときに、アプリによっては激重だったりエラーになったりするようです。

GitのGUIクライアントとしてSourcetreeを使っていましたが、この場合もファイルをまとめて操作するので、動作が重くならないか心配です。

おすすめな方法としては、ファイル操作とGit操作にはVisual Studio codeを使います。
https://azure.microsoft.com/ja-jp/products/visual-studio-code/


#### ①「Remote Development」プラグインで「Remote WSL」プラグインを入れる。
Visual Studio codeに「Remote Development」というプラグインを入れると「Remote WSL」というプラグインが入ります。
https://code.visualstudio.com/blogs/2019/05/02/remote-development
こちらをつかうと、WSL2(Ubuntu)配下のファイル群にアクセスして、自由にファイルを操作したり、編集して開発できるようになります。

#### ②「Git History」プラグインを入れる。
Visual Studio codeでは標準で基本的なGit操作ができますが、標準ではGitログ履歴がありません。
Visual Studio codeに「Git History」というプラグインを入れると、Sourcetreeのように、Gitのログ履歴をみながらGit操作ができるようになります。
https://marketplace.visualstudio.com/items?itemName=donjayamanne.githistory

#### ③WSL2(Ubuntu)でGitHubにアクセスするためのキーペアを作ってGitHubに登録する
Visual Studio codeのWSLでは、「/home/username/.ssh/」配下にある、下記のファイルがGitへのアクセス情報として使われますのでWSL2(Ubuntu)でキーペアを作って、GitHubに登録しておきましょう。
そうすると、Visual Studio codeのWSLでもGitHubを使えるようになります。

/home/username/.ssh/id_rsa
/home/username/.ssh/id_rsa.pub
/home/username/.ssh/known_hosts

https://docs.github.com/ja/free-pro-team@latest/github/authenticating-to-github/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent
（Linuxを参考にやってみてください）
容器と水量 (小学生算数5テスト投稿)

# 容器と水量 (小学生算数5テスト投稿)
TeXマクロ部分
$\def\fraction(#1/#2){\frac{#1}{#2}}$ $\def\bunsu(#1/#2){\frac{\,#1\,}{\,#2\,}}$ $\def\DIS{\displaystyle}$ $\def\unisq{\mathrm{cm^2}}$ $\def\unicube{\mathrm{cm^3}}$

## ★★5

図のような直方体の形をした容器に，$1600\unicube$の水を入れたところ，水の深さは10cmとなりました。この容器に水がもれないようにふたをして，下の図のように，この容器を辺CGが床から離れないようにして，(ア)の状態から(ウ)の状態に倒しました。途中の(イ)の状態では，水面の位置がPDになり，BP:PA=1:3となりました。また，(ウ)の状態では，水の深さは5cmとなりました。容器の厚さは考えないものとして，次の問いに答えなさい。

![](https://i.imgur.com/jJU8Wqx.png)



![](https://i.imgur.com/KzqlZHV.png)


![](https://i.imgur.com/dwmfLiR.png)


![](https://i.imgur.com/IeNyDmU.png)







(1)　辺ABの長さを求めなさい。


![](https://i.imgur.com/Dst1znx.png)





(2)　辺CGの長さを求めなさい。



![](https://i.imgur.com/vCeIz1h.png)
LaravelでRequestクラスを作成したら、403エラー

##概要
Requestクラスを作成し、バリデーション用コード書き、コントローラーに適応させた！！
さて、ブラウザでフォーム入力行いボタンを、ポチー！！
![スクリーンショット 2020-11-24 18.40.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658904/97aad228-0294-31d5-a331-bffbfc649d09.png)



「ファーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーｗｗｗ」
ここまでが、僕のリクエストクラス作成のルーティンです。（毎回やっている。。。）

戒めも込めて記事にします。



##結論
falseをtureに書き換える！！これだけ！！

```
class TestRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true; ←ここがデフォルトではfalseになっている。
    }
```

これからは絶対、忘れないようにしよう！絶対に！
[Swift]UITableViewでDrag&Dropする際の注意点

# はじめに
UITableViewでロングタップを使って並び替えをする際に、
上手く実装できずに時間を浪費してしまったので、参考になる方がいれば嬉しいです。

# 完成イメージ
UITableViewCellをロングタップするとDrag&Dropで並び替えができるようになります。
![RocketSim Recording - iPhone 12 Pro Max - 2020-12-06 19.58.14.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99869/77f7a971-8aa2-1098-8626-c49fe557ed42.gif)

# 基本的な実装方法
詳しい実装方法自体は検索すれば見つかるので概要だけ記載します。
UITableViewにDrag&Dropできるように以下の設定をします。

```Swift:ViewController.swift
tableView.dragInteractionEnabled = true
tableView.dragDelegate = self
tableView.dropDelegate = self
```

UITableViewDragDelegateの実装はこんな感じです。
Dragした際にセルの文字列を取得しています。

```Swift:ViewController.swift
extension HomeViewController: UITableViewDragDelegate {
    func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
        let todoName = db.getItem(at: indexPath.row).text // Dragするセルの文字列を取得
        let todoProvider = NSItemProvider(object: todoName as NSItemProviderWriting)
        return [UIDragItem(itemProvider: todoProvider)]
    }
}
```

Dropした際に、`tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator)`が呼ばれて、
並び替えの実装をここでおこないます。

```Swift:ViewController.swift
extension ViewController: UITableViewDropDelegate {
    func tableView(_ tableView: UITableView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UITableViewDropProposal {
        return UITableViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
    }
    
    func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) {
        // Dropした際の並び替えの実装
    }
}
```

# 上手く実装できなかったところ
今回つまずいたところは、Dropした際に`tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator)`の処理が呼ばれない問題でした。
他の`func tableView(_ tableView: UITableView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UITableViewDropProposal`は
ちゃんと呼ばれることは堪忍できたので、UITableViewDropDelegateが設定できていないわけではないようです。

# 解決方法
ロングタップのDrag&Dropで並び替えをする前に`navigationItem.leftBarButtonItem = editButtonItem`でUITabelViewの左上に編集ボタンを表示して、
並び替えをできるようにしており、こちらの機能を併用していると対象のメソッドが呼ばれなかったです。
`func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath)`などの並び替えするメソッドを削除したところ
ちゃんと`tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator)`が呼ばれるました。

# まとめ
簡単な実装からステップアップで機能を追加して行く際に、
似たような機能のイベントが影響することもままありそうなので気をつけたいところです。

# 参考記事
https://dev.classmethod.jp/articles/uitableview-dragdelegate-dropdelegate1/
https://developer.apple.com/documentation/uikit/drag_and_drop/adopting_drag_and_drop_in_a_table_view
firebase authentication(JavaScript SDK)サインイン時のエラーハンドリング

Firebase Authentication(JavaScript SDK)でメールアドレス、パスワードを利用してサインインする場合に、throwされるエラーをまとめました。

[ドキュメント](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#error-codes_12)に記述されてますが、以下のエラーがthrowされるので、エラーに応じて適切に処理することになります。

- メールアドレスの形式がおかしい
  - errorCode: `auth/invalid-email`
  - message: The email address is badly formatted.
- ユーザが無効になっている
  - errorCode: `auth/user-disabled`
  - message: The user account has been disabled by an administrator.
- ユーザが存在しない
  - errorCode: `auth/user-not-found`
  - message: There is no user record corresponding to this identifier. The user may have been deleted.
- パスワードが間違っている
  - errorCode: `auth/wrong-password`
  - message: The password is invalid or the user does not have a password.

また、パスワードを5回間違えると、以下のエラーが返ってきます。

- 何度もパスワードを間違えた
    - errorCode: `auth/too-many-requests`
    - message: Access to this account has been temporarily disabled due to many failed login attempts. You can immediately restore it by resetting your password or you can try again later.
    - https://firebase.google.com/docs/reference/js/firebase.auth.Error

```typescript
try {
  const data = await firebaseAuth.signInWithEmailAndPassword(
    "email-adress@example.com",
    "password"
  )
} catch (error) {
  if (error.code === 'auth/invalid-email') {
    // メールアドレスの形式がおかしい
  } else if(error.code === 'auth/user-disabled') {
    // ユーザが無効になっている
  } else if(error.code === 'auth/user-not-found') {
    // ユーザが存在しない
  } else if(error.code === 'auth/wrong-password') {
    // パスワードが間違っている
  } else if (error.code === 'auth/too-many-requests') {
    // 何度もパスワードを間違えた
  } else {
    // その他
  }
}
```
jarファイル内の一部を差し替える方法

# はじめに
jarファイル内の一部を、再ビルドすること無く差し替えたい場合の解決方法を記載します。

# 環境
OS：macOS Catalina 10.15.6
jar：14.0.2

# 手順
1. jarファイルを解凍する。
 * `jar xvf hoge.jar`
    * x：解凍
    * v：冗長に解凍結果を表示する。
    * f：ファイルの指定
2. 古いjarファイルを削除する。
 * `rm -rf app.jar`
3. ファイルを差し替える。
 * macOSの場合は、DS_Storeも不要なので削除する。
 * `find . -name ".DS_Store" | xargs rm`
4. 再アーカイブする。
 * `jar cmf0 META-INF/MANIFEST.MF ../app.jar  *`
    * c：アーカイブの作成
    * m：マニフェストの指定
    * 0：圧縮なし

# 参考
* https://stackoverflow.com/questions/6629361/how-could-i-repack-a-jar-file-with-all-of-its-dependencies
「Gtk-WARNING **: 20:13:24.077: cannot open display:」エラーが出たとき

## 事象
* SSH経由でラズパイにウィンドウを表示させようとしたらエラーが出た。

## 発生したエラー

```
pi@raspberrypi:~ $ python3 samplepy 
Unable to init server: Could not connect: 接続を拒否されました

(frame:1868): Gtk-WARNING **: 20:13:24.077: cannot open display:
```
## 原因
* リモート操作で画面（X11）の操作が許可されていない
* おそらく、Linux系のCent0SやUbuntuも同様だと思われる。

## 対処
* 表示させたい端末（リモート端末）で実施

```
# 何も表示されないことを確認（今回のが原因であれば表示されない）
$ echo $DISPLAY

# ディスプレイ操作を許可する端末をしていする
# 制限したい場合は「DISPLAY=192.168.0.1:0.0」など
$ export DISPLAY=:0.0

# 下記のように表示されることを確認
$ echo $DISPLAY
:0.0
```
ローカル変数とインスタンス変数の違い

現在、「Ruby on Rails 5 速習実践ガイド」を読みながら勉強をしているのですがローカル変数とインスタンス変数についてあまり理解せずに進んでしまいました。

なので、きちんと理解するため記事にしてみました。

プログラミング初心者のため認識違いがあった場合などは是非ご指摘下さい。

#ローカル変数とは
その場限りの一時的な変数です。メソッド内で定義したローカル変数はそのメソッドの中でしか使うことができず、他のメソッドからは使うことができません。

#インスタンス変数とは
オブジェクトの保持する変数です。オブジェクトのどのメソッドな内からも利用できます。

#試したこと

今回、自分でMyClassを作ってみました。

```ruby
class MyClass
  def method_1
    number = 100
  end

  def method_2
    number
  end
end
```
そしてこのクラス (MyClass) のオブジェクトを作って、method_1を呼び出してみます。

```ruby
> object = MyClass.new
> object.method_1
=> 100
```

このメソッドにはnumberというローカル変数に100という数値のオブジェクトをいれています。
そのためメソッドを呼び出すと100という値が返ってきています。

それに続けて、method_2を呼び出してみます。

```ruby
> object.method_2
Traceback (most recent call last):
...
NameError (undefined local variable or method `number' for #<MyClass:0x00007ffe439012580>)
```
「numberという名前のローカル変数やメソッドは知りません」というエラーが表示されてしまいました。

ここではmethod_1で定義したnumberというローカル変数がmethod_2でも生き残っていれば表示されるはずです。
エラーが返ってきてしまったということは、method_1で使ったnumberは使えないという状況になりました。

次にローカル変数ではなくインスタンス変数を使ってみます。

```ruby
class MyClass
  def method_1
    @number = 100
  end

  def method_2
    @number
  end
end

```
```ruby
> object = MyClass.new
> object.method_1
=> 100
> object.method_2
=> 100
```
今度は、method_2でエラーが出ず、無事に100という値が返ってきました。
ここで同じインスタンス変数を利用できていることがわかります。

#まとめ

ローカル変数は1つのメソッドの中で一時的に使うデータを参照するために使います。
一方、インスタンス数は、特定のオブジェクトの内部で使いまわしたりできます。

#参考本
・ 現場で使える Ruby on rails 5 速習実践ガイド
HooksのuseStateがどのように実現されているか調べた話

この記事は [2020年 Reactアドベントカレンダー](https://qiita.com/advent-calendar/2020/react) 12日目の記事です。

## はじめに
React の Functional Componentで副作用を実現するためのhooksのうち、おそらく最もわかりやすいuseStateがどのように実現されているかを調べた。

## 調べる

### Reactのリリースをcheckout

Reactをgithubからcloneし、執筆時点で最新の v17.0.1 のtagをcheckout

```
$ git clone git@github.com:facebook/react.git
$ cd react
$ git checkout v17.0.1
```

### useStateがexportされている部分を検索

VSCodeで開き、愚直に `useState` で検索したところ、 [React.js の 95行目](https://github.com/facebook/react/blob/v17.0.1/packages/react/src/React.js#L95) がexportしており、その実装は [ReactHooks.js の 80行目](https://github.com/facebook/react/blob/v17.0.1/packages/react/src/ReactHooks.js#L80) にあることがわかった。

### ひたすら実装を探る

```javascript
const dispatcher = ReactCurrentDispatcher.current
```
とあるので、とりあえず `ReactCurrentDispatcher.current` が何かを調べる必要がある。
`ReactCurrentDispatcher` の実装が↓ 

```javascript
const ReactCurrentDispatcher = {
  /**
   * @internal
   * @type {ReactComponent}
   */
  current: (null: null | Dispatcher),
};

export default ReactCurrentDispatcher;
```

これだけなので、多分currentに値を突っ込んでいる部分があるはず、ということで `ReactCurrentDispatcher.current =` で検索したところ、 7ファイルの中に112件も引っ掛かっていしまい早々と心が折れそうになる。

とはいえ、多分いろんなところから値がセットされるんだろうからstaticなDispatcherが取れれば良いんだろう、ということで見なかったことにして `Dispatcher` が何なのかを調べたら、[その中に `useState` のインターフェースがあった。](https://github.com/facebook/react/blob/v17.0.1/packages/react-reconciler/src/ReactInternalTypes.js#L265)

じゃあDispatcherの実装を調べればそれで済む話になりそう、というわけでDispatcherの実装を調べる。

実装している部分ではDispatcherをimportしているはずなので、 `type {Dispatcher` で検索したら、 `ReactPartialRendererHooks.js` がimportしていて、 [それが `useState` やその他のhooksの実装をexportしていた。](https://github.com/facebook/react/blob/v17.0.1/packages/react-dom/src/server/ReactPartialRendererHooks.js#L494) 
やったぜ。

肝心のuseStateの実装を見ると、[内部ではuseReducerが使われている](https://github.com/facebook/react/blob/v17.0.1/packages/react-dom/src/server/ReactPartialRendererHooks.js#L254) ので、今度は `useReducer` の実装を読む。

`useState` から `useReducer` に渡されているreducerが、 `basicStateReducer` なので、 `useState` は `useReducer` の特別なもの、として実装されている様子。

`useReducer` の中で `isReRender` というフラグが参照されていて、おそらく再描画のときにはこのフラグが立っているんだろう。

とりあえず再描画でないほうの実装を読むと、 [この中でDispatchの実装が作られ、これが呼ばれると再描画が走るような作りになっているらしい。] (https://github.com/facebook/react/blob/v17.0.1/packages/react-dom/src/server/ReactPartialRendererHooks.js#L335)
再描画の仕組みは今回の調査の対象ではないので気にしない。

次に再描画のほうの実装を読むと、 値を `memoizedState` にキャッシュし、更新された値とすでに作成済みのDispatchを返している様子。

Hooks自体がやっていることはここまでで、あとは `Dispatch` で再描画を走らせる部分なのでここでおしまい。

## 調べてみて
少なくとも `useState` と `useReducer` は状態管理だけで大したことはやっていなかった。
大したことをやっているのは、おそらくDispatchで再描画する部分。
その部分も追々調べてみたい。

使うときは最初に宣言しておしまいだから1度作った参照が使い回されている気になっていたけど、描画されるたびに新しい参照が返されるんだな。そりゃそうか。
Singletonな状態管理がめっちゃたくさんあってバグらないようにするのは大変そうだがそのへんはライブラリあるあるなんだろうきっと。


## 終わりに
内部実装を見ると新しい気付きがあって面白い。
アドベントカレンダーに参加しなかったら絶対やらなかったことなので、参加してよかった。
Railsのカスタムバリデーション(ActiveModel::Validator)

# はじめに

独自のバリデーションを実装する`validates_with`に関して簡単にまとめます。

# バリデーションの作り方

`app/validators`フォルダにカスタムバリデーションを書いていきます。

例えば、退社済みのスタッフの場合エラーが出る様なバリデーションを作る場合、下記の様になります。

```ruby
class ActiveStaffValidator < ActiveModel::Validator
  def validate(record)
    if record.end_date < Date.today
      record.errors[:base] << "退社済みのスタッフです。"
    end
  end
end
```

# 使い方

使い方としては、対象のモデルのファイルに

```ruby
validates_with ActiveStaffValidator
```

と記載するだけです。
Maya 保存できないノードを作る

この記事は[Takumi Akashiro ひとり Advent Calendar 2020](https://qiita.com/advent-calendar/2020/takumi_akashiro "ひとり Advent Calendar 2020")の8日目の記事です。

今日も小粒です。小粒といえば納豆ですね。久しぶりに水戸[^1]に旅行に行って小粒納豆を買いたい。
[^1]: アンコウが食べたいので大洗でも可。というか冷静になると大洗の方がいいな。アンキモ食べたい！

## 前置き

保存したくない一時ノードを作ったことはありますか？
自分はあったような、なかったような気もします。

もう1年以上程度前に調べたことを出すので、同期の曖昧さはお許しください。

## やってみる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294868/211b4cdd-1f28-fbba-e988-54039ca85a6d.png)


このシーンで以下を実行して保存してみます。

```python

from maya import cmds

cmds.toggle("pCubeShape2", doNotWrite=True)

```

そして開きなおすと……

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294868/c3af4872-7866-d0f2-5f11-9b08b40863a4.png)

pCubeShape2が消え、3dViewにあるCubeも一つになりました。
成功ですね！

## 締め

いやいや、最初はこんなに短くなる予定じゃなかったんですよ！

「OpenMaya使わないといけないんですねー面倒ですねー」みたいなことを言って、使えないニッチな知識を披露する予定だったんですって！本当です！
でも書いてるときにOpenMayaのどのクラスに`donotwrite`をセットするやつあるんだっけ？って悩んで、「Maya donotwrite」で検索したら、`toggle`のMELコマンドリファレンスが出るじゃないですか？
cmdsで試したら普通に保存されないノードができるじゃないですか。
変に難しいやりかたでやるより、cmdsで出来る方が大体のTAは喜ぶじゃないですか？
結果一行で済む記事が出来上がったんであって、私は悪く…いや悪いですね。主に頭が。

...と思っていました。

どちらかと言えば、ポリゴン形状を作るノードのpolyCube2の方を消したいんですよね。
ちょっと試しにやってみましょう。

```python
from maya import cmds

cmds.toggle("polyCube2", doNotWrite=True)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294868/1fa4c89d-a3f0-ae8e-282e-e620fa4eb687.png)

消えない……だと…？！

`toggle`コマンドのヘルプを読んでみましょう！

> toggle コマンドは、オブジェクトが持つさまざまな オブジェクト コンポーネントの表示と非表示を切り替えます。
> たとえば、リストにある NURBS カーブやサーフェスに対して、 CV およびエディット ポイントの表示と非表示を 切り替えることができます。

オブジェクトコンポーネント……？
pCubeShapeはオブジェクトですし、形状なのでコンポーネントも持ってますよね。
PolyCubeはオブジェクトコンポーネントに含まれないので操作不可能なのか……

というわけでOpenMayaを使いましょう！

```python

from maya.api import OpenMaya

def set_flag_of_dont_write(nodename):
    sel = OpenMaya.MSelectionList()
    sel.add(nodename)


    if sel.isEmpty():
        return

    for i in range(sel.length()):
        mobj = sel.getDependNode(i)
        mfn = OpenMaya.MFnDependencyNode(mobj)
        mfn.setDoNotWrite(True)



set_flag_of_dont_write("polyCube2")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294868/822db44c-d265-9927-3de4-f9b4b509fa00.png)


無事(?)、polyCube2(と3dView上のCubeが)消えましたね。

## 本当の締め

今回はpolyCubeを消したせいで、Shapeの中の形状データまで失ってしまいましたが、
確か探ってた時は、ツール用に一時的なノードを作りたかったんだと思います。

それ以外にもノードエディタ使うとできてしまう、`MayaNodeEditorSavedTabsInfo`とかをシーンに保存しないためにつかえるんじゃないですかね。

……どうしてあのノードはデフォルトで`doNotWrite`フラグ立ってないんだ…
「パネルとレイアウトを保存」をオフにしても当たり前のように保存されるし……

思えば、おそらく一年前の私も同じことを検証した気がします。
……まあそういう事もあるよね！
Windows10でherokuのCLIダウンロードとアカウント作成

①heroku　CLIのダウンロード

このサイトにアクセスします。
https://devcenter.heroku.com/articles/heroku-cli

![Something went wrong]()

使っているPCのバージョンに合わせたものを選択
（私はWindows10の64bitを使用しているのでそちらを選択）
![herokuダウンロード②.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865589/31a04af9-12c2-bd21-9ea3-9d26e2ce02da.png)

DLしたインストーラーを起動すると下記の画面が表示されるのでそのまま「Next」
![herokuセットアップ①.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865589/add36b2b-0dbb-01cc-70c3-1886f2724ee0.png)

ダウンロード場所を聞かれるのでデフォルトのまま「Install」
ダウンロード処理が走ります。
![Something went wrong]()


完了したら「コマンドプロンプト」もしくは「PowerShell」でバージョンを確認してみましょう。
heroku --version

![herokuバージョン確認.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865589/ab9bdf71-34a1-113b-e814-1546f23b8cf6.png)

このようにバージョンが表示されたらダウンロード成功です。


続いてherokuにログインします。
heroku login

![herokuログインコマンド.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865589/da9f22d0-28e4-e284-ffb3-895e46fbd41c.png)

「heroku: Press any key to open up the browser to login or q to exit:」
→ブラウザーを開いて始めるなら何かキーを押してください。”q”を押すと終了します。
みたいな意味だと思います。

何かキーを押すとブラウザが起動し、下のような画面が表示されます。
ログインボタンを押しましょう。
![herokuログイン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865589/1903e837-2b64-db16-85f6-37ff6594b2a5.png)

押した後、登録が済んでいない場合は下の画面が表示されます。
「sing up」ボタンを押下して登録を行いましょう。

設定項目の中に「Role」という項目があります。
どういう立場で利用をするか？ということだと思います。
私は仕事外で使用するので「Hobbyist」を選択しました。

その後メールアドレスにメールが届くので、パスワードを設定し、次の画面で「accept」を押して設定は完了です。

もう一度ログインコマンドを実行するとまたブラウザが起動するので、ログイン情報を入力するとログインができます。

今回はとりあえずここまでにします。
実際に使用するにあたってGitとの連携が必要になってきますので、そちらについてもまた書きます。
Botを作成するにあたってい色々と調べましたが、herokuというものが何なのか？いまいち理解ができていないので、
それについてもかみ砕いて記事にできたらと思います。
マンガでわかる機能的分解アンチパターン

![07563311-DCD9-400D-AA55-21158EB9D3B0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/8f9c47c1-42af-d12a-eba0-5f3ccf6dba89.png)
http://wiki.c2.com/?FunctionalDecomposition

オブジェクト指向にかぎらず、大きな仕事があるからといって、単純にタスクを分割しただけでは、情報のやりとりが非効率になることがよくあります。

長い手続きを何の考えもなしにオブジェクトに分けてしまうと、グローバル変数を使うサブルーチンのようになってしまいます。つまり、元のスコープからアクセスしていた情報を共有するために、引数が無駄に多かったり、あるいは大きなコンテキストになったり、乱暴なパブリックフィールドアクセスが起きたり、といったことが起こります。

仕事をオブジェクトに分けましょうというのは、責務の専門性でグルーピングするということです。どこから何を参照するかの関係線が最少になるようにし、意味がわかるようにメタファーでくくるようにしましょう。

それぞれの社員が、プロダクトの開発と営業をどちらもやるのではなく、開発者は倍の開発を、営業マンは倍の営業をすると偏らせるほうが、どう考えても正常ですよね
Slackの新しいWebApiに対応したGasでのRequestに変更してみた

## はじめに
こんにちは、今年は[Slack Advent Calendar 2020](https://qiita.com/advent-calendar/2020/slack)に挑戦させていただきました！
今回は、GasでのSlackの新しいWeb API requestsに対応したGasを作成しましたので、是非活用をしていただけると幸いです！！

## Slack WebApi Request変更に関して
Slackより新しい[WebApi Request変更に関して](https://api.slack.com/changelog/2020-11-no-more-tokens-in-querystrings-for-newly-created-apps)の内容を確認し自分でまとめてみました。

- 2021年2月24日以降に、新しく作成されたSlackアプリは、新しいRequest方法で行う必要があり
- 2021年2月24日より前に作成したトークンは、利用できるが、新しいRequest方法へ変更をすることを推奨
- GET Requestを利用する場合は、headerのAuthorizationに付与してRequestを送ってね
- POST Requestを利用する場合は、Request bodyに付与してRequestを送ってね

Requestの具体的な方法が丁寧に記載されていたので、早速変更を実施しました！

## 新しいGasRequestに関して
昨年、[自分で作成したコード](https://qiita.com/tkazu0806/items/4c6a27736e4bc7329e9d)を使って変更を行っていきます。

### 変更が必要だったプログラム
昔のRequest方法は、RequestURLにクエリパラメーターを付与して、Requestを送っていました。
`URL：https://slack.com/api/{SlackMethod}?token={xoxb- か xoxp}&{それぞれのSlackMethodのoption}`

```js:oldSlackApi.gs
function oldSlackApi(token, path, options) {
  if (!options) options = {};
  var url = "https://slack.com/api/" + path;
  var q = "?token=" + encodeURIComponent( token );
  for (var key in options) {
    q += "&" + encodeURIComponent( key ) + "=" + encodeURIComponent( options[ key ] );
  }
  url += q;
  var res = UrlFetchApp.fetch(url);
  var ret = JSON.parse(res.getContentText());
  if (ret.error) {
    throw "GET " + path + ": " + ret.error;
  }
  return ret;
}
```
今回はPOST形式に変更してみました！

```js:newSlackApi.gs
function newSlackApi(token, slackMethod, options) {
  if (!options) options = {};
  let url = "https://slack.com/api/" + slackMethod;
  let params = "token=" + encodeURIComponent( token );
  for (var key in options) {
    params += "&" + encodeURIComponent( key ) + "=" + encodeURIComponent( options[ key ] );
  }
  const body = {
    "method" : "post",
    "payload" : params,
    "Content-type" : "application/x-www-form-urlencoded",
    "muteHttpExceptions": true
  };

  let response;
  try {
    response = UrlFetchApp.fetch(url, body);
  } catch(e) {
    // fetch失敗時の処理
    console.log("エラー内容：" + e);
    throw "fetch error";
  }
  let responseJson = JSON.parse(response.getContentText());
  if (responseJson.error) {
    throw "POST " + slackMethod + ": " + responseJson.error;
  }
  return responseJson;
}
```
### 試しにリクエストを送った結果
実行プログラム

```js:testChannelsListPost.gs
function testChannelsListPost() {
  const token = PropertiesService.getScriptProperties().getProperty("slackApiToken");
  const options = { "limit" : 5 };
  let channels =  newSlackApi(token, "conversations.list", options);
  console.log(channels)
}
```

返ってきた結果
![スクリーンショット 2020-12-06 20.05.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282719/df87ecda-b7aa-9091-9894-c8d7d793b8db.png)

よし無事に返ってきて安心しました〜！

## 終わりに
GASでの新しいRequest方法について、今回まとめてみました。
公式ドキュメントが丁寧ですごく実装をしやすかったです！
移行や新しいSlackアクセストークンを利用する際に参考にしていただけると幸いです！！
【3D Detection-Mono】OFT-Net : 

<h1>Orthographic Feature Transform for Monocular 3D Object Detection</h1>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/65feaab3-a36b-9f74-3ec4-b0fcd6e6ca32.png)


<h1>手順</h1>
1. ResNetで特徴量抽出
2. Orthografic Feature Transform(Bird Eye Viewに変換)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/3392a949-2989-2292-8f5f-e48c252aba33.png)
r: 図中のx,z平面(地面の平面)のvoxel size

3. A topdown network, consisting of a series of ResNet
residual units, which processes the birds-eye-view feature maps in a manner which is invariant to the perspective effects observed in the image


4. 物体のクラス、位置、信頼度スコア、位置のオフセット、大きさのオフセット、向きのオフセットを推定する

5. NMSとdecoding stage,
which identifies peaks in the confidence maps and generates discrete bounding box predictions.


<h2>Orthografic Feature Transform</h2>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/e0ff103f-7524-f842-0e26-fd8f981b2d7e.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/3b8abfde-9c4e-feee-1d66-dcbd3ea26a8e.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/c30f5fa0-3f0a-2aff-cc92-78913cb270ef.png)
3次元の高さ方向の特徴量を足していく事で2次元に変換する(Orthografic Feature Transform)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/b324ec0e-1684-bab9-1404-00e779173437.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/3272c626-07c3-b9d4-7dd0-ec2f98ff743b.png)


<h2>Confidence Score</h2>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/90ed323e-f57e-8cd1-a564-9b881e4c212c.png)


<h1>結果</h1>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/daed1d2e-878d-0307-ce3f-170640f1cf15.png)
10 epoch
ダメダメですね

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/16e01581-c06c-7512-e2c6-ddb885c08275.png)

20 epoch
ダメダメですね

半日ほどで20 epoch
600 epoch終了するのに、後10日と出ていたので諦めました><
動画ではそこそこ良い感じですね
https://www.youtube.com/watch?v=ZpV51Fgc4jE&t=87s

<h1>結論</h1>
もう少し勉強して時間ある時にまた走らせます！
下記途中な所も後々修正しますm(_ _)m

<h1>参考文献</h1>
Orthographic Feature Transform for Monocular 3D Object Detection
https://arxiv.org/pdf/1811.08188.pdf

https://github.com/tom-roddick/oft
「hello, world」と表示されるだけのなんちゃってOS（ブートセクタ）を作ってみた。1/5時限目


おりょうの寺子屋、教師兼生徒を務めますわたくし、
おりょうが、本日は出張授業ですよ～　なんちゃって。

#はじめに

[HTC Advent Calendar 2020](https://qiita.com/advent-calendar/2020/htc)の7日目を担当します。
ONEJAPAN HACKATHONに参加したチームHTCのメンバー、おりょうです。

今回は私が絶賛挑戦中のOS作成の一部分を切り取ってご紹介しようかなと思います。
OSってみんな知ってるけどいざ作るとなるとなんだかハードルが高く感じますよね？
でも実際ちょっと興味ありません？
少なくともここまでの前説を読んでくれているあなたは、
少なからずOSに興味があるから見に来てくれているのでしょう。

そんなあなただけに今回は！
めちゃくちゃ簡単な「なんちゃってOS（ブートセクタ編）」をご紹介いたします。
合計3回に分けて紹介する予定です。

早速見ていきましょう！

##概要
成果物：OS(フロッピーディスクで、フォーマットはFAT12）
アセンブラ：[NASK](http://hrb.osask.jp/wiki/?tools/nask)
想定対象読者：OS自作をこれから始めようとしている人。

##シラバス
1時限目：アセンブリ言語でソースコードを書こう①（ORG命令～entryラベルまで）
2時限目：アセンブリ言語でソースコードを書こう②（putloopラベル）
3時限目：アセンブリ言語でソースコードを書こう③（finラベル～msgラベルまで）
4時限目：出来たソースコードを機械語にアセンブルしてみよう。
5時限目：PC/ATエミュレータを使ってOSを起動させてみよう。

#1時限目：アセンブリ言語でソースコードを書こう①<br>（ORG命令～entryラベルまで）
まずは講義3回分のソースコードの全容を見てみましょう。





```
		ORG		0x7c00

; 以下はFAT12フォーマットフロッピーディスクのための記述

		JMP		entry
		DB		0x90
		DB		"HELLOIPL"
		DW		512
		DB		1
		DW		1
		DB		2
		DW		224
		DW		2880
		DB		0xf0
		DW		9
		DW		18
		DW		2
		DD		0
		DD		2880
		DB		0,0,0x29
		DD		0xffffffff
		DB		"HELLO-OS   "
		DB		"FAT12   "
		RESB	18

;ここからブートセクタについて書いていくで！

entry:
		MOV		AX,0
		MOV		SS,AX
		MOV		SP,0x7c00
		MOV		DS,AX
		MOV		ES,AX

		MOV		SI,msg

		
putloop:
		MOV		AL,[SI]
		ADD		SI,1
		CMP		AL,0
		JE		fin
		MOV		AH,0x0e
		MOV		BL,13
		INT		0x10
		JMP		putloop
fin:
		HLT
		JMP		fin

msg:
		DB		0x0a, 0x0a
		DB		"hello, world"
		DB		0x0a
		DB		0

		RESB	0x7dfe-$

		DB		0x55, 0xaa
```

ざっと目を通しましたか？

それではさっそく説明開始！

##ORG命令

上から順に行きますと、
まずORG命令が出てきますね。
意味は「メモリの○○番地から読み込んでいくよ～」です。
メモリの番地は16進数で指定してあげてくださいね。

むむ、「なぜ0x7c00なんですか？」って質問が飛んできそうですね。
理由はズバリ、ブートセクタが読み込まれるアドレスが
　　**0x7c00 ～ 0x7dff**
と決まっているからなんです。
なぜそう決まったのかを私に問うのは禁止です。

##FAT12

では次に、FAT12フォーマットフロッピーディスクのための記述部分ですが、
ここもほとんどが決まり文句と言いますか、このように記載するルールとなっています。
なのでここはあまり気にせずこの通真似して書いてください。

まあ気軽にいじれるところとしたら下記くらいですかね。
DB		"HELLOIPL"　　 ;任意のブートセクタ名
DB		"HELLO-OS   "　　;ディスクの名前
バイト数は固定なので、そこだけ注意してくださいね。


##entryラベル

ここからが本題のブートセクタ部分です。
ラベルごとに説明していきますね。

今日紹介するのは[entryラベル]。
ここでは、レジスタの初期化を行います。
ここについても順に説明していきますよ。
         
```
entry:
		MOV		AX,0
		MOV		SS,AX
		MOV		SP,0x7c00
		MOV		DS,AX
		MOV		ES,AX
		MOV		SI,msg
```

###MOV命令とレジスタ
アセンブリ言語にはMOV命令というものがあって、
「MOV A,B」で「AにBを代入する」といった意味になります。

そしてAX,SS,SP等が何者かと申しますと、レジスタです。
レジスタというのは、CPUにある記憶回路のことで、
ここでは変数のようなものだと思っていただいて結構です。

今の説明を踏まえて上記ソースコードを人間様にわかりやすいように解読すると下記のようになります。

```             AX=0
		SS=0
		SP=0x7c00
		DS=0
		ES=0
```
これだと数学みたいで分かりやすいでしょ？

あとは最終行の「MOV SI,msg」だけですね。
これもMOV命令ですので、結局は上記と同じです。

違いとしては、代入する値がラベル名となっている点ですね。
一見ラベル名を変数に代入なんておかしな話に聞こえますが、
代入される値は結局のところただの数値です。

実は、ここにラベル名を指定することで代入されるのは、
そのラベルが読み込まれるメモリの番地なのです。

つまり、msgラベルが読み込まれる番地(**0x7c74**)ということです。

そのため、「MOV SI,msg」を書き換えると、
「MOV SI,0x7c74」と書くことができます。

あらためてentryラベル部分を人間様の理解しやすいよう書き換えてみるとこうなります。

```             AX=0
		SS=0
		SP=0x7c00
		DS=0
		ES=0
        SI=0x7c74
```
ここまでで、ブートセクタの下準備は完了です！
次回からは実際に「hello world」と表記させるためのコードを書いていきますよ。

1時限目は以上！休み時間！


##参考
[oswiki.osask.jp](http://oswiki.osask.jp/?FrontPage)
Railsのカスタムバリデーション(ActiveModel::EachValidator)

# はじめに

`ActiveModel::EachValidator`を使うことで、独自のバリデーションを追加することができます。

# フォルダ作成

まず、`app/validators`フォルダを作成します。

この`validators`フォルダに独自のバリデーションを追加していきます。

# バリデーション作成

例えば、カラーコードかどうかを判定したい場合に、

`app/validators`フォルダに`color_validator.rb`のファイルを作成し、下記の内容を記載します。

```ruby
class ColorValidator < ActiveModel::EachValidator
  PATTERN = /カラーコードかどうか判定するための正規表現を記載/.freeze

  def validate_each(record, attribute, value)
    unless value =~ PATTERN
      record.errors.add(attribute, "はカラーコードでなければいけません。")
    end
  end
end
```

この様にすることで、値がカラーコードで無い場合にエラーを出すカスタムバリデーションを作成できました。

# 使い方

使い方としては対象のモデルに対して


```ruby
validates :color_code, color: true
```

の様に`color_code`カラムにカラーコード以外の値が保存されるときにエラーを出す様にすることができます。
UITableViewDataSourceとUITableViewDelegateについてのまとめ

UITableViewの使い方記事を見ているとUITableViewDataSourceとUITableViewDelegateは絶対に実装する事と書いてあります。

これらが具体的に何をするのかについての記事が見当たらないようなので、自分用メモとして残します。
誤っていたらご指摘お願いいたします。


##UITableViewDataSourceって何？
UITableViewDataSourceはテーブルに表示するデータの管理をするもの
(TableViewはテーブルの表示の管理のみでデータの管理はしない)
テーブルにデータを表示するにはTableViewにUITableViewDataSourceプロトコルを実装する必要がある

UITableViewDataSourceプロトコルを実装する事で下記等ができるようになる

・テーブル内のセクションと行の数の取得
・テーブルの各行にセルを提供
・セクションのヘッダーとフッターにタイトルを付ける
・テーブルのインデックス
・データの変更や更新
・テーブル行の挿入や削除


##UITableViewDelegateって何？
テーブル行のスワイプやその他のアクションに応答するもの
UITableViewDelegateを実装する事で下記などができるようになる

・行の内容をインデント
・行、ヘッダー、およびフッターのカスタムの高さの指定
・カスタムヘッダービューとフッタービューを作成および管理


##UITableViewDataSourceとUITableViewDelegateは絶対に実装するようにと言われている理由
上述した通り、UITableViewDataSourceがなければセルやデータ(セル内に表示したい文字など)が表示できません
UITableViewDelegateがなければカスタマイズしたテーブルが作れません(データの表示だけであればUITableViewDelegateがなくとも実装可能ですが、カスタムする前提のテーブルを使う事が多いので必須と言われていると思います)

##参考にした記事
https://developer.apple.com/documentation/uikit/uitableviewdatasource
https://developer.apple.com/documentation/uikit/uitableviewdelegate
https://qiita.com/kagemiku/items/22b74010365723c5c4fe
【VBA】日付が和暦のCSVデータを読み込む方法

VBAを使ってCSVファイルのデータを読み込む時、日付が和暦の場合はそのまま読み込んでも文字列として認識されてしまいます。

【読み込み対象のCSVファイルの例】

```
"年月日（和暦）","お引出し","お預入れ","お取り扱い内容","残高"
R02.02.10,,80000,"振込　ｼﾞﾄﾞｳﾃｱﾃ",99999999
R02.02.17,,30,"普通預金利息",99999999
R02.06.10,,80000,"振込　ｼﾞﾄﾞｳﾃｱﾃ",99999999
```

【上記CSVファイルをエクセルで開いた結果】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459893/d3e9a89e-45ce-744a-cf80-4eba36bb6f22.png)

これは、文字列として読み込まれているのかと思っていたのですが、セルの書籍設定を確認してみると以下のような設定に自動変換されていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459893/a3bf565f-e6a4-00c5-4886-cd11e8bac4a9.png)

つまり、**文字列ではなく和暦として認識されている**のです。

そのため、以下のようにセルの書籍設定を変更するだけで西暦表記に変換することができます。

【ユーザー定義として指定した場合】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459893/a1ddea3b-48a6-e7d7-b9fd-a9ed125d16a4.png)

【日付として指定した場合】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459893/d0494be9-6093-8f5f-ffd9-4398c40d8394.png)

【結果】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459893/a4a3fef2-e225-48ce-0db0-176cfe6f10e6.png)
マンガでわかる曖昧な視点ミニアンチパターン

![7166DF08-E023-4281-A21B-D8CB07E23A65.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/8d87c9b5-7329-89b8-dabb-28e90353ecb5.png)
http://wiki.c2.com/?AmbiguousViewpoint

ドメイン駆動設計はアンチパターンの出版より後なので、当時はそのように表現されていませんでしたが、このアンチパターンは DDD の「実践的モデラー」を誤解したケースと言えます。

特定の実装技術で作るのが難しいかもしれないと邪念が入って、実装が簡単になるようにしてやろうとすると、あるべき姿から少しずれた分析モデルが生まれます。けれど本当は、いったん実装を忘れてあるべき姿とぴったり一致するモデルを立てるほうが、長期的に見ると簡単になります。

現実に即したモデルは、固有の特殊仕様を知らなくても理解できます。後になってから、工数をケチった箇所にやっぱり都合悪いと言われて、せっかく安定したものがひっくり返ることもありません。

実装の難しさはあっても、それが真に合理的なモデルからの実装落とし込みなら、開発者の心理的負担も少ないです。その難しさをクリアすることこそ、腕の見せどころですね。
WindowsのVagrant環境でDockerを並列にインストールできたときのメモ

### ①VirtualBox最新版をインストール
　https://www.virtualbox.org/wiki/Downloads
 　私がインストールしたバージョン（6.1.16 r140961）

### ②VirtualBox Extension Packをインストールする
　https://www.virtualbox.org/wiki/Downloads

### ③Vagrant最新版をインストール
　https://www.vagrantup.com/
　私がインストールしたのバージョン（Vagrant 2.2.10）

### ④windowsの機能の有効化または無効化で「仮想マシン プラットフォーム」「Windowsハイパーバイザープラットフォーム」「Linux用Windowsサブシステム」をONにする

### ⑤WSL2を有効化、Ubuntuインストール
https://docs.microsoft.com/ja-jp/windows/wsl/install-win10

### ⑥Docker for Windows を「Enable WSL2 Windows Features」にチェックつけた状態でインストール
https://docs.docker.com/docker-for-windows/install/#download-docker-for-windows

### 注意したところ
・ステップを達成するたびにVagrantを起動して、正しく動作するかチェックしながら実行した。
カラダ持ってくれよ！3倍難易度だっ！

# 難易度3倍の法則

***再利用可能なモジュールを作るのは、単一のソフトウェアのモジュールを作るのに比べ、3倍の難易度がある***

再利用可能＝共通の、とも言えます。
単一のソフトウェアのモジュールであればそのソフトウェアの要件だけを満たせばよいですが、広くあらゆるところで使われることを想定したモジュールでは、どういう使われ方をするかするかあれこれ想像して作らないといけません。

例えば何かの金額に関するモジュールなら

- 為替の対応は必要か
- 為替の情報はどう取るか
- 為替はどこまで対応するか
- 税率の対応は必要か
- 税率の情報はどう取るか
- 3桁ごとのカンマ区切りの文字列のアウトプットは必要か

など、仕様に関して想像できることは色々出てきます。

新規のプロジェクトで最初に便利な共通関数みたいのを作るときに「どこまで便利にするか」悩みがちですよね。

YAGNIの法則につながるところでもありますが、最初からあまり作り込まないのが懸命です。結局使い始めてみないと何が必要でどこまでさせるのが適当なのかが見えてこないからです。想像で時間かけて作り込んだけど結局後で大分作り直した、または、結局使わなかった、なんてことも多々あります。

便利な共通モジュールのようなものを作るのは難易度3倍ですが、その3倍は1箇所にある必要はなく、長く時間をかけて広く見た場合での3倍にしたほうが、良いものが作れそうです。
シェルスクリプトで待ち時間にスピナーを表示する

## 使用例

![spinner.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100313/8d70d906-3cbe-62a4-7124-486908756bb3.gif)


```shell
spinner proccessing... & pid=$!
sleep 5
kill $pid
wait $pid 2>/dev/null
printf "%s%s\n" "$ERASE_LINE" 'Done!!'
```

## 関数

### Bash
```shell
ESC=$(printf '\033')
CSI="${ESC}["
RESET="${CSI}0m"
GREEN="${CSI}32m"
ERASE_LINE="${CSI}2K"
HIDE_CURSOR="${CSI}?25l"

function spinner() {
	local i=0
	local spin='⠧⠏⠛⠹⠼⠶'
	local n=${#spin}
	while true; do
		sleep 0.1
		printf "%s%s" "${ERASE_LINE}"
		printf "%s %s" "${GREEN}${spin:i++%n:1}${RESET}" "$*"
		printf "%s\r" "${HIDE_CURSOR}"
	done
}
```

#### 説明

* `n=${#spin}`: `spin`という変数の文字列の長さを取得しています
* `printf`: ここでは`echo -en` と同等。エスケープシーケンスを解釈して最後に改行はしない
* `${<文字列>:n:m}`: 文字列のn文字目からm文字分の長さの部分文字列 (※ Bash依存)
* `i++%n`: iの数値をnで割ったあまりを返してiに1を加えます
* `$*`: spinner関数に渡された引数を全て出力します
* `\r`: キャリッジリターン。カーソル位置を行頭に戻します
* 最初のCSIについては参考記事を参照されたい[^1][^2]


### zsh
```shell
ESC=$(printf '\033')
CSI="${ESC}["
RESET="${CSI}0m"
GREEN="${CSI}32m"
ERASE_LINE="${CSI}2K"
HIDE_CURSOR="${CSI}?25l"

function spinner() {
  local idx
  local spin='⠧⠏⠛⠹⠼⠶'
  local n=${#spin}
  while true; do
    sleep 0.1
    printf "%s" "$ERASE_LINE"
    printf "%s %s" "${GREEN}${spin[idx++ % n + 1]}${RESET}" "$*"
    printf "%s\r" "$HIDE_CURSOR"
  done
}
```

## 参考

1. [command line - How to create a rotation animation using shell script? - Ask Ubuntu](https://askubuntu.com/questions/623933/how-to-create-a-rotation-animation-using-shell-script)
2. [BashFAQ/034 - Greg's Wiki](https://mywiki.wooledge.org/BashFAQ/034)
[^1]: [シェルスクリプトのechoで”問題なく”色をつける(bash他対応) #Bash - Qiita](https://qiita.com/ko1nksm/items/095bdb8f0eca6d327233)
[^2]: [Pythonで出力した文字を消す方法 #Python3 - Qiita](https://qiita.com/exy81/items/99e99ab8c184343948cc)
ちゃんと考えよう、IAMのはなし

## はじめに
AWSを利用する際に必ず使用するIAM。
なんとなく利用することも多いのではないでしょうか。
IAMについて考える機会があったので、今一度整理してみようと思います。

## 目次
1. IAMとは
1. IAMポリシーとは
1. IAM設計で意識すべき４つのこと
1. 本番運用に耐えうるIAMとは

## 1. IAMとは

### AWS Identity and Access Management(IAM)
- AWSリソースへのアクセスを安全に管理
- 下記のいずれかの方法でアクセス許可を付与
  - 適切なアクセス許可ポリシーがアタッチされたグループのメンバーにする (推奨)
  - ポリシーをユーザーに直接アタッチする

## 2. IAMポリシーとは
AWSでのアクセスを管理するために権限を定義したもの。
IAMポリシーには６つのタイプがあります。
1. アイデンティティベースのポリシー
2. リソースベースのポリシー
3. アクセス許可の境界
4. 組織 SCP
5. アクセスコントロール (ACL)
6. セッションポリシー

このうち、アイデンティティベースのポリシーには大きく分けて３つの種類があります。

#### AWS管理ポリシー
- AWS が作成および管理するスタンドアロンポリシー

![スクリーンショット 2020-12-06 17.15.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542703/29cbbfc5-1070-6651-053b-aebf827becc8.png)

#### カスタマー管理ポリシー
- AWS利用者が作成および管理するスタンドアロンポリシー

![スクリーンショット 2020-12-06 17.28.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542703/9c74a5b8-b856-71fa-33ad-c90f08cf16fe.png)

#### インラインポリシー
- IAM アイデンティティ (ユーザー、グループ、またはロール) に埋め込まれたポリシー

![スクリーンショット 2020-12-06 17.30.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542703/9d821532-b458-5293-5ccb-f8ba0d4829ae.png)

## 3. IAM設計で意識すべき４つのこと
個人的所感ですが、IAM設計する場合は以下のことに気を付ける必要があります。

1. 権限を付与する方法をどうするか？
  - IAMロール
  - IAMグループ
  - インラインポリシー
2. 付与する権限は頻繁に変更が入るか？
3. 権限のパターンは多いか？少ないか？
4. 独自の権限ルールが必要か？

## 4. 運用に耐えうるIAMとは
よくあるパターンを考えてみます。

1. 権限を付与する方法は**IAMグループ**
2. 付与する権限は頻繁に変更する可能性が**高い**
3. 権限パターンは**少ない**
4. 独自の権限ルールが**必要**

上記を満たすために、何をすべきか考えます。
1. 必要なAWSマネージドポリシーを洗い出します。
2. 要件に即したカスタマー管理ポリシーを作成します。
3. 必要となる権限要件を満たすように、AWSポリシーとカスタマー管理ポリシーを組み合わせたIAMグループを作成します。
4. 作成したIAMグループに該当IAMユーザーをアタッチします。

図にすると下記のようになります。
![スクリーンショット 2020-10-25 22.09.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542703/5b817684-304a-007e-056a-7fc726d62a83.png)

この設計の良いところは、下記だと思っています。
1. AWS管理ポリシーとカスタマー管理ポリシーを組み合わせて権限要件を満たすことで、メンテナンス対象ポリシーを絞ることができる
2. 権限パターンごとにIAMグループを作成するので、付与する権限を変更する場合はIAMグループを変更するだけで良い

逆にデメリットとしては下記ですかね。
1. 権限パターンが多いと、IAMグループが乱立する
2. ポリシーの組み合わせでは、複雑な権限ルールを表現することが難しい

## 最後に
IAMはAWSにおけるアクセス管理において非常に重要なサービスです。
権限設定を間違えると、AWSアカウントへの不正アクセスを許してしまい被害は計り知れません。
適切な権限を設定し、安全にAWSを利用しましょう。

## 参考資料
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/introduction.html
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies_managed-vs-inline.html
killコマンドでTerminatedメッセージを表示しないようにする

```shell
# killする対象のpidを予め変数に入れておきます
hoge_function & pid=$!
:
(処理)
:
kill $pid
wait $pid 2> /dev/null
```

参考: https://qa.codeflow.site/questions/81520/how-to-suppress-terminated-message-after-killing-in-bash
kali linuxでhydraを使ってパスワードクラックをしてみた

# 初めに
株式会社シーエー・アドバンスで脆弱性診断をしている宮里と申します。
普段はwebアプリケーションやAndroid,iOSなどのネイティブアプリの脆弱性診断をしています。

今回は普段の診断では行っていない部分に触れてみたいと思い、簡単にですがhydraを利用したパスワードのクラッキングを試してみました。

真似する場合は自身で環境を用意し、絶対に自分以外の環境に対して行わないでください。

## hydraとは
パスワードクラックを行うツールです。
SSHやFTPなどのサービスや、webアプリのログインフォームに対して攻撃が出来ます。
攻撃時は、あらかじめ攻撃する値を記載したファイルを利用することが出来ます。

## 環境
攻撃側はhydraがデフォルトで入っているkali linuxを利用します。
また、今回はFTPサービスに対して攻撃を行います。
![image (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529348/4230ec0b-8820-4a38-5863-27abb34934d5.png)

こちらのサイトを参考にvirtualboxで上記環境を用意しました。
https://www.dot-plus.com/server/linux/kalilinux/1851/
https://ts0818.hatenablog.com/entry/2015/12/24/134100

## 攻撃の準備
先ほども触れましたが、hydraはあらかじめ攻撃する値を記載したファイルを使うことが出来ます、今回はファイルを利用して攻撃をしてみようと思います。

下記リンクにてよく使われているユーザ名、パスワードがまとめられています。
https://github.com/danielmiessler/SecLists/blob/master/Usernames/xato-net-10-million-usernames-dup.txt
https://github.com/danielmiessler/SecLists/blob/master/Passwords/xato-net-10-million-passwords-1000000.txt

## 実際に攻撃してみる

kali linuxにて実行したコマンドは下記です。
``` hydra -l userlist.txt -P passwordlist.txt 192.168.0.107 ftp```
![image (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529348/e0660cb0-f536-ac63-9725-e7b528c0e89c.png)


利用したオプションは下記です。
-l: ユーザ名で利用するファイルを指定
-P: パスワードで利用するファイルを指定

今回はFTPサーバ側のユーザ名、パスワードはとても脆弱です、が実際に攻撃してみるとやっぱりわくわくしますね
わくわく.....


わくわく。。。。。。



₍₍◝((((((΄◞ิ(΄◞ิ(΄◞ิ౪◟ิ‵)◟ิ‵)◟ิ‵))))))◟⁾あ、終わらないかも...


![image (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529348/885e368c-b71c-02f9-79e3-f648cc0cb99c.png)


ファイルの中身を見てみたらユーザの数は2132563、パスワードの数は9999998でした。
1ユーザに対しての総当たりがだいたい57分くらいで終わるので、57×2132563で121556091分、時間だと2025934時間、日数だと84413日。

このまま続けるとこの記事は2254年度のアドベントカレンダーでやっと間に合う計算になります、僕はそこまで長生き出来る自信がちょっとないので、今回はユーザ名は予めわかっているシチュエーションで攻撃をやり直します。

下記のコマンドにて再度攻撃します
``` hydra -l ftpuser -P passwordlist.txt 192.168.0.107 ftp ```

## 結果
パスワードが脆弱すぎたのもありますが、無事成功しました。
![image (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529348/11daed5a-913f-f0c4-221a-9ed8cabe5097.png)

ユーザ名はftpuser,パスワードはpasswordでした。

こちらのユーザとパスワードを利用して実際にftpにログインしてみます。
![image (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529348/fcaa613c-6757-4564-f7bc-28dfd47f0dfc.png)

出来ました！　

## まとめ
今回はhydraを利用してパスワードのクラッキングに挑戦してみました。
やっている内容は簡単な事でしたが、やったことのない攻撃をしてみるのはやっぱり楽しかったです。

また、普段の診断ではアカウントロック機能の有無を確認しているのですが、ただ無い事を確認するだけでなく、こういった攻撃が実行可能になってしまう事を実際に触って理解することが出来たので良い機会でした。

簡単にでも実際に攻撃に触れる事でほかの脆弱性についてももっと理解が深まる気がしたので、自己学習として今後もこういった自分の環境で試してみて、得た知識を普段の業務でも生かせるようになればいいなと思いました。

次記事を書くときはもっとレベルの高い事を書けるようにこれからも頑張ります、ここまで読んで頂きありがとうございました！
Alibaba Cloud: Cloud Firewall を試す。

この記事は <A HREF=https://qiita.com/advent-calendar/2020/alibabacloud target=_blank>Alibaba Cloud Advent Calendar 2020</A> の6日目です。皆様の参加をお待ちしております。

# 0. あらすじ

アリババクラウドのマネージドサービスによるセキュリティプロダクト `Cloud Firewall` が登場しました。
中国のネットワークセキュリティ等級保護条例2.0対応とのことで色々できそうです。
7日間の無用お試しができるようなので試してみました。


# 1. 早速試してみる

## 1.1. Cloud Firewall のページへアクセス

ログインした状態で初めて<A HREF=https://yundunnext.console.aliyun.com/?p=cfwnext target=_blank>Cloud Firewall</A>へアクセスすると、無料体験を申し込めます。
![cfw1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96018/5f987be3-a809-cbe9-73dd-68fd468e5c3c.png)
後は画面の指示に従い進むだけです。

## 1.2. RAMによるアクセス権限の付与
Cloud Firewallサービスへアクセス権限を付与するためにRAM設定の確認が出ます。
![cfw2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96018/911e1211-77dc-35fc-9c4a-618c056889a1.png)
サービスに対するロールの付与は必須のためそのまま進めます。

使い方の説明が何画面が表示され、読み進めれば準備完了です。
元々稼働していたインスタンス等のリソースは自動的に保護対象へ登録されます。
![cfw3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96018/7a98c2f5-5f47-a3f6-4e44-1dffe3182639.png)


# 2. Cloud Firewallでできること

## 2.1. Overview
サービスのトップ画面がOverviewで、ダッシュボード的な感じです。
![cfw4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96018/8d59e6b4-2624-eee1-5256-73f66e8daf1c.png)
脆弱性への攻撃や危険な設定等があると件数が表示されるようです。
これはアリババ独自の判断らしく、AWSでは警告される全世界へSSHを開放する設定を行っても Risk Configurations には表示されませんでした。


## 2.2. 外向きトラヒックの監視
アリババクラウド内部から外部への通信を全て監視し、拒否・無視（許可し以後通知しない）を選択できます。
![cfw5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96018/728fb8e9-13af-aedb-f6ac-1d18543b738f.png)
試しにサーバ上からFacebookへアクセスしてみましたがしっかり記録されました。
参考情報として接続先サイトのアリババ的分類も表示されます。
不正アクセスを受けバックドアを仕掛けられたり外部へ情報流出が行われているのを検出できますから便利そうです。
中国のインスタンスからやるとどう記録されるのかは次回の宿題にします。

## 2.3. インターネットアクセス状況
インターネット向けにIPアドレス・空いているポート、稼働中アプリケーションと危険な物があるかが表示されます。
![cfw6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96018/603a6b1a-4b75-39b2-773a-2df120b283ea.png)
今回はSSHが開いているサーバだけなのでポートもアプリケーションも１と表示されています。
トラヒックグラフも表示されますから、異常なトラヒックに気づけそうです。

## 2.4. 攻撃ブロックの状況
IPSがブロックした攻撃とその発信地が地図上に表示されます。
![cfw7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96018/141cad90-7464-8c04-9d85-a6ad7d0686fd.png)
攻撃の概要が地図で、それぞれの攻撃詳細は下に表示されます。
インスタンスを作成して早々、SSHへブルートフォースアタックが沢山来ています。
Malicious IP一覧をアリババが持っているようで、そこからの接続は自動ブロックのようです。
（これらのIPアドレスからのSSH接続はインスタンス側に来ていなかった）



# 3. 制限が多いお試し版
試せたのはこんな感じでした。
公式ホームページのサービスを見ていると、セキュリティグループトラヒック可視化とか色々と興味深い機能があります。
しかし、<A HREF=https://www.alibabacloud.com/help/ja/doc-detail/90274.htm target=_blank>お試し版は制限があり有償版でしかできない機能が多いです</A>。
上のリンクの料金表を見ての通り、有償版は月額420~3900米ドルとなかなかのお値段。
時間課金なら試せるんですけど諦めです。


# 4. まとめ
お試し版では全ての機能を利用できませんでしたが、Security Hubのように使えそうなサービスです。
有償版が時間課金になったらまた試してみたいと思います。
PHPで、あいうえお配列の取得 (簡単)

入力
（str_splitだとなぜか文字化けするので、このようにしないといけません。）

```php
<?php
$arr = preg_split("//u", "あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわ");
var_dump($arr); // 表示のためのコード
?>
```

結果

```
array(46) { [0]=> string(0) "" [1]=> string(3) "あ" [2]=> string(3) "い" [3]=> string(3) "う" [4]=> string(3) "え" [5]=> string(3) "お" [6]=> string(3) "か" [7]=> string(3) "き" [8]=> string(3) "く" [9]=> string(3) "け" [10]=> string(3) "こ" [11]=> string(3) "さ" [12]=> string(3) "し" [13]=> string(3) "す" [14]=> string(3) "せ" [15]=> string(3) "そ" [16]=> string(3) "た" [17]=> string(3) "ち" [18]=> string(3) "つ" [19]=> string(3) "て" [20]=> string(3) "と" [21]=> string(3) "な" [22]=> string(3) "に" [23]=> string(3) "ぬ" [24]=> string(3) "ね" [25]=> string(3) "の" [26]=> string(3) "は" [27]=> string(3) "ひ" [28]=> string(3) "ふ" [29]=> string(3) "へ" [30]=> string(3) "ほ" [31]=> string(3) "ま" [32]=> string(3) "み" [33]=> string(3) "む" [34]=> string(3) "め" [35]=> string(3) "も" [36]=> string(3) "や" [37]=> string(3) "ゆ" [38]=> string(3) "よ" [39]=> string(3) "ら" [40]=> string(3) "り" [41]=> string(3) "る" [42]=> string(3) "れ" [43]=> string(3) "ろ" [44]=> string(3) "わ" [45]=> string(0) "" }
```
【初心に帰れた！】" fatal: Not a git repository (or any of the parent directories): .git " の対処法

#初めに(状況)
・今回扱う自分のGit学習歴：3か月目
・Gitを使ってGithub内でデータを管理する操作に少し小慣れてきた時期。
　そんな時に今回のエラーが発生しました。

##ターゲット
自分と同じ少しGitの扱いに小慣れてきた方

##事象
・Vue.jsの勉強ようにGitHubを使ってリモートリポジトリで管理しようとした
・いつも通り以下コマンドを実行しようとコマンド入力

```
git add .
git commit -m "first commit"
```

・しかし以下エラーが出てできない。。。

```
fatal: Not a git repository (or any of the parent directories): .git
```

・なぜだ？？？

##結論
原因は以下いずれかの処理ができていないため
1. Github内の設定が間違っている
2. git のセットアップができていない
3."git init(ファイルの初期化)"をしていなかった ← 自分のエラーの原因・・・

##解決方法詳細

###1.Github内の設定が間違っている

<解決策>
・Github内で"my page" ⇒ "Settings" ⇒ "Emails" に移動
・以下選択肢から:ballot_box_with_check:を外す
![Email settings - Google Chrome 2020_12_06 18_40_10 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/780929/9b04d65a-dff4-170d-2bf2-fbb59434daf6.png)

###2.git のセットアップができていない

<解決策>
以下Gitのセットアップを実施する

```
$ git config --global user.name "xxxx"
$ git config --global user.email "xxxxxx@gmail.com"
```

###3."git init(ファイルの初期化)"をしていなかった ← 今回の自分のエラーの原因・・・

<解決策>
一番シンプル。以下コマンドを実行するだけ。

```
git init // 新しいリポジトリ作成 //
```

その後は以下コマンドも問題なく実行しました。

```
git add .
git commit -m "first commit"
```


##最後に
非常に情けないミスででしたが、こんな初歩初歩のところでつまづくこともあるんだな、と初心に帰ることができたいい機会でした！
皆さんもこんなシンプルな凡ミスをしたら
・凡ミスしても笑って凡ミスした自分を受け入れる！
・気落ちせず「初心に帰れた！ラッキー！」くらいで次の作業を進めましょう！

最後まで読んでいただきありがとうございました！

###※参考
1. [エラー：fatal: Not a git repository (or any of the parent directories): .git　対処方法](https://qiita.com/gosairei1207/items/701b7ae494b96db0f9a1)
2. [GitHub でエラーが出た時（Not a git repository)](https://qiita.com/uizprg/items/334f9b390cd8f19c4b2d)
パルナスの魔女

# パルナスの規則

- モジュールの利用者には、そのモジュールを利用するために必要なすべての情報を与え、それ以外の情報は見せない
- モジュールの作成者には、そのモジュールを実装するために必要なすべての情報を与え、それ以外の情報は見せない

# で？

オブジェクト指向の設計原理で、カプセル化や情報隠匿の原理となるのがパルナスの規則です。
要するにモジュールなどを作る際に「そういうことされたらバグの温床になるよね」ってことを予測して、そのモジュールの利用者ができることは最低限にしましょうということです。

例えば、そのモジュールの中で`会員の誕生日`が特別な意味を持っていて、取得した後に変更されると他の処理で問題が起きる可能背がある場合に、**Getterは作るがSetterは作らない**というような設計にするような場合です。

何でもかんでもできるのは柔軟性があって、ある意味では便利なのですが、何でもできるものは壊すのも簡単なので、それが起きにくい設計にしておくことも大事なことです（Rubyは柔軟性ありすぎてそのへんが心配になる）。