OmniAICreator/Qiita-1.07M huggingface dataset:
5000兆円の凄さを実感するためのアプリ

この記事は[PONOS Advent Calendar 2019](https://qiita.com/advent-calendar/2019/ponos)の16日目の記事です。
![download (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356727/8c80600d-2b6f-68d2-af59-4a323f4c4879.png)
# きっかけ
5000兆円欲しいねって話になって、どれぐらいの量になるんだろうと思って調べたら[「積み上げたら5万km」という情報](https://dic.nicovideo.jp/a/5000%E5%85%86%E5%86%86)が出てきた。
イマイチ実感が沸かない、きっと誰かがシミュレータを作ってるはずだ！だって3年前、つまり平成のネタだしね！
でも検索しても出てこなかった。。。
よし！作ろう！！！
# 完成品
こちらです。
https://ackyla.com/5000chouen.html
# 技術とか
最初はcanvasでもりもり動くものを作ろうかなーとか思ってましたが、時間がないので色々諦めて簡単な作りにしました。
ただhtmlとjavascriptとcssを書いてgithubにおいただけです。
[The deep sea](https://neal.fun/deep-sea/)の影響を受けました。
# 最後に
5000兆円はすごい！！
5000兆円欲しい！！！
ShellScript bash case文の書き方

## 目的

- ShellScript bashにおけるcase文の書き方をまとめる

## 書き方の例

- 下記に変数に特定の値や文字列が入っているときに特定の処理を行うcase文を記載する。
- 変数には任意の値が格納されているものとする。

    ```bash
    #!/bin/bash

    case ${変数A} in
      "文字列B")
        変数Aに文字列Bが格納されている時に行いたい処理;;
      "文字列C")
        変数Aに文字列Cが格納されている時に行いたい処理;;
      "文字列D")
        変数Aに文字列Dが格納されている時に行いたい処理;;
      *)
        変数Aに文字列B、文字列C、文字列D以外のものが格納されている時に行いたい処理;;
    esac
    ```

## より具体的な書き方の例

- 変数`number`に格納された文字列によって異なる内容を出力する処理を記載する。
- 変数`number`には任意の二桁の数字の文字列が格納されているものとする。
- 変数`number`に00が格納されている時、「変数numberに00が格納されている時の処理を実行します。」と出力する。
- 変数`number`に20が格納されている時、「変数numberに20が格納されている時の処理を実行します。」と出力する。
- 変数`number`に30が格納されている時、「変数numberに30が格納されている時の処理を実行します。」と出力する。
- 変数`number`に10、20、30いずれも格納されていない時、「変数numberには00、20、30いずれも格納されていません。」と出力する。
- 前述の条件を満たしたcase文を下記に記載する。

    ```bash
    #!/bin/bash

    case ${number} in
      "00")
        echo "変数numberに00が格納されている時の処理を実行します。";;
      "20")
        echo "変数numberに00が格納されている時の処理を実行します。";;
      "30")
        echo "変数numberに00が格納されている時の処理を実行します。";;
      *)
        echo "変数numberには00、20、30いずれも格納されていません。"
    esac
    ```
【13日の金曜日】KubernetesやOpenShiftのマニフェストをJSONで書く

本記事は [Kubernetes3 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/kubernetes3)
13日目のエントリになります。

カレンダー見たら今日だけ1日空いており、でも今日はノートPC持ってきてなかったのでAndroidタブレットからお送りします！

# はじめに

13日の金曜日ということでJSONの日！みなさん今日は`kubectl`や`oc`で`-o json`で出力されていることかと思います。

元ネタ … AnsibleのプレイブックをJSONで書くというのは、横地さんがこちらですでに記事にされています。
[[Ansible] 小ネタ: Playbook は JSON で書ける - てくなべ (tekunabe)](https://tekunabe.hatenablog.jp/entry/2019/05/22/ansible_json_playbook)

今回は、普段YAMLで書いているKubernetesやOpenShiftのマニフェストファイル、JSONでも書けるという小ネタです。

# 環境

## KatacodaでKubernetes(Minikube)

今回使用した環境です。

https://kubernetes.io/ja/docs/tutorials/hello-minikube/

ここの[Minikubeクラスタの作成](https://kubernetes.io/ja/docs/tutorials/hello-minikube/#minikube%E3%82%AF%E3%83%A9%E3%82%B9%E3%82%BF%E3%81%AE%E4%BD%9C%E6%88%90)の「Launch Terminal」を使って、使い捨てのMinikube環境をブラウザから利用できます。

Androidタブレットだと全画面表示にすると操作しやすいです。

## Android用キーボードアプリ

普段はATOK for Android使ってますが、ターミナル作業だと[Hacker's Keyboard](https://play.google.com/store/apps/details?id=org.pocketworkstation.pckeyboard)というキーボードアプリを使用します。CtlrやTab、Escキーなど使えるのでターミナル作業をするときはとても便利です。

![Screenshot_20191213-121008.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256859/a099c400-a6b2-ee31-36e1-2354c62c4cdd.jpeg)


# Podをデプロイする

```json:pod.json
{
    "apiVersion": "v1",
    "kind": "Pod",
    "metadata": {
        "name": "json-sock"
    },
    "spec": {
        "containers": [
            {
                "image": "zakihmkc/socket-sample1:latest",
                "name": "json-sockserv"
            }
        ]
    }
}
```

コンテナイメージの元ネタはこちらです

[tcpSocket設定で覚えるKubernetesとOpenShiftのヘルスチェック機能 (ソケットサーバーPodをビルド&デプロイ)](https://qiita.com/zaki-lknr/items/768d77363c3b566c4c19#pod%E5%8D%98%E4%BD%93%E3%81%A7%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4)

コンテナイメージ: https://hub.docker.com/r/zakihmkc/socket-sample1

DockerHubのページをメンテしてなくてすみませんが、コンテナイメージの中身はこちらです。
https://github.com/zaki-lknr/tcp-probe-example/tree/master/src

# 実行と結果

ふつうに`apply`を実行します。

```
$ kubectl apply -f pod.json
```

AndroidのChromeだとターミナルのテキストコピーできなかった…😅

ので、画面キャプチャ。

<img width="768" alt="Screenshot_20191213-121808.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256859/e0cb183f-d1bf-4108-735b-54f2cddfb12d.jpeg">

動いてますね！

# さいごに

ということで、マニフェストはYAMLだけでなくJSONでも書けるというネタでした！

作業環境はこんな感じでした！

![DSC_4781-01.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256859/d207fe52-d0d3-ab2a-6440-0e898587669b.jpeg)
【OpenGL】エンジンを使わないゲーム開発 -環境構築とウィンドウの表示-

#緒論
ゲーム会社を目指して就活をしている身であるが，目指している企業のエンジニアブログを拝見したところ，新卒の人も，ゲームエンジンに頼らない低レベルのフレームワーク？API？などを用いて基礎を学んでおくと良い，とのことだったので早速勉強を開始していく．
最終的にエンジンに頼らず自由にゲームが制作できることを目的とする．私は力学を大の得意科目ということにしているので，物理挙動をある程度自由に組めるようになりたい．
~~早くねねっちになりたい．~~

今回，`MacOS`で`Xcode`を環境に`OpenGL`，`GLUT`を使用していく．参考にさせていただいたサイトを以下に示しておく．


**参考文献**
[GLUTによる「手抜きOpenGL入門」](https://tokoik.github.io/opengl/libglut.html)
こちら基本関数の説明とともに網羅的に書いてあり，章も分かりやすい．
[OpenGL道場再生リスト](https://www.youtube.com/watch?v=wtC03LR3VFo&list=PL8_ASIpg7ciG3btmV6RElRjmWrfAL0q2P)
動画で実際に動かした様子を見比べながら勉強できる．

#方法
##1. 環境構築
毎回，環境構築するたびに思うのが，あまり何を設定しているのか理解していないということ．一度プログラムの基礎の基礎を学ぶような必要があると思う．
早速だがまず，嬉しいことに，MacだとXcodeをダウンロードしておくとOpenGLとGLUTは最初から入っている状態となるらしい．

次に，以下のコマンドでコンパイルができ，実行ファイル **a.out** が作成される．

```tarminal:tarminal
gcc -framework GLUT -framework OpenGL ***.cpp
```
あとは実行するだけのようだ．

```tarminal:tarminal
./a.out
```


##2. プログラム
だいたいコメント文入れてみた．

```cpp:main.cpp
#include <OpenGL/OpenGL.h>
#include <GLUT/GLUT.h>

// この中に描画したいものを入れる
void Display()
{
}

int main(int argc, char *argv[])
{
    // GLUTとOpenGL環境の初期化
    glutInit(&argc, argv);
    // ウィンドウを開く関数
    glutCreateWindow("Title");
    // ウィンドウが開かれたり再描画の際に実行
    glutDisplayFunc(Display);
    // 無限ループの関数，イベント待ち状態
    glutMainLoop();
    return 0;
}
```
先のコマンドでコンパイルすると結構な数の警告文が出てきた．どうやら

>
Mac OS X 10.9 (Mavericks) / Xcode 5 以降で GLUT を使ったプログラムをコンパイルすると, "deplicated" (非推奨) という警告が出ます. 

とのことなので，無視しておこうと思う．
MacとOpenGLもまあまあ相性が悪いらしい．

#結果

以下のように，ウィンドウが表示された．

![スクリーンショット 2019-12-13 11.02.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499636/a53fb05b-1b46-67a3-98b4-00d2adc362a5.png)

#結論
- ウィンドウが表示できた！
遺伝研スパコンでR（とRstudio）を使う

遺伝研スパコンでRを使うにはmoduleコマンドでR環境をロードします。

```
$ module load r/3.5.2
$ which Rscript

/opt/pkg/r/3.5.2/bin/Rscript
```

これでRのスクリプトを投げれば動くはず。
Rstudioを使いたいのだけど、Rstudio serverのインストールにはroot権限が必要なので一般ユーザには無理...
(トライはするので追記予定）

ちなみに
遺伝研スパコンでJupyter notebookを使いたいときはこちら↓
[遺伝研スパコンでJupyter Notebookを利用する方法](https://qiita.com/nigyta/items/6cb321735dba0a6215b2)

遺伝研スパコンのデフォルトはPython2.7なので、
Jupyter notebookはminiconda3[^1]を入れてcondaからインストールしました。

＊2019-12-13 module名が間違っていたので修正しました。


[^1]: moduleにpython/3.7.2があったので、`module load python/3.7.2` してからpipでインストールしてもよかったかも
v1.38からAtomのfuzzy finder（ファジーファインダー）が高速になった

Atomの検索ですごく便利なものの一つとして
ファイル検索``Command + p``のfuzzy finderがありますが、

このファジーファインダーがv1.38から

- 中規模or大規模プロジェクトへのインデックス作成が約11倍
- フィルタリングして表示するプロセスが約6倍

のモード追加が追加され改善されているそうです。
v1.39からはこの高速モードがデフォルトでONになっているようです。


現在1.41のAtomを使用していますがあまり気づきませんでした。
プロジェクトの規模に比例するのでしょう。
大きめのプロジェクトの時は確かにインデックス作成と検索時の若干のラグは感じていたので
エディタはAtom派の私としてはそこが改善されるのはすごく嬉しいです。


参考：https://github.blog/2019-06-12-atom-editor-is-now-faster/
Codecademy 何？

# 初めに
この記事は、SLP KBIT Advent Calendar 2019 の13日目の記事です。

プログラミングを自分でやってみたいときこのウェブサイトは役に立つかもしれない。
#どうして Codecademy❓
良い点
○ たくさん言語を学ぶことができる
○ 説明が詳しい
○ シラバスに沿って勉強する
悪い点
○ 日本語に翻訳しなければならない
○ 無料ではない 
#やってみよう
１．言語を選択する
![Capture.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549495/df380ea5-981b-0df3-216a-ab3f2fefe3aa.jpeg)
![Capture2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549495/c1ec0253-872f-352b-8733-f43acc7dc3db.jpeg)
２．説明を読む
![Capture5.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549495/217d5a07-e278-17af-a1a8-df145cdf0cc2.jpeg)
３．実際にやってみよう
![Capture4.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549495/32cbf4de-0e00-3bb0-f56d-c8d631af0d60.jpeg)
４．問題あったら教えてくれる
![Capture6.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549495/48e7730f-3ea5-0883-e919-3a500ee62e2f.jpeg)
#最後に
― 色々な言語やってみたぜひやってください
― わかりやすく勉強できる
ー お金がかかるだけどとても役に立つ
#参考
codecademy.com
今年読んで効いた本（Di, PM, EM向け）

この記事は、[マイナビ Advent Calendar 2019](https://qiita.com/advent-calendar/2019/mynavi) 13日目の記事となります。
今年読んだ本のうち、仕事に効いた数冊を紹介します。
# 本
## 技術書（っぽいやつ含む）
- [広木「エンジニアリング組織論への招待」技術評論社](https://www.amazon.co.jp/gp/product/4774196053/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1)
- [畑村「技術の創造と設計」岩波書店](https://www.amazon.co.jp/%E6%8A%80%E8%A1%93%E3%81%AE%E5%89%B5%E9%80%A0%E3%81%A8%E8%A8%AD%E8%A8%88-%E7%95%91%E6%9D%91-%E6%B4%8B%E5%A4%AA%E9%83%8E/dp/4000052446)
    - [畑村「失敗学のすすめ」講談社文庫](https://www.amazon.co.jp/dp/4062747596/ref=cm_sw_r_tw_dp_U_x_kcV8DbKMXXPEH )
- [西村ほか「SCRUM BOOT CAMP THE BOOK」翔泳社](https://www.amazon.co.jp/gp/product/B00DIM6BMI/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1)
- [Kent Beck「テスト駆動開発」オーム社](https://www.amazon.co.jp/gp/product/4274217884/ref=dbs_a_def_rwt_bibl_vppi_i0)

### コメント
- 「エンジニアリング組織論」が今年一番影響を受けた本。対エンジニアはもちろん、ビジネスサイドの人とのコミュニケーションを本の内容を念頭にしたものにしてみたら、相手にすんなり意図が伝わることが増えた気がする
- 「スクラムブートキャンプ」は、スクラムを入れる前に読み直した。来年はスクラムマスター取りたいです


## ビジネス
- [磯崎「起業のファイナンス増補改訂版」日本実業出版社](https://www.amazon.co.jp/gp/product/4534052456/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1)
- [Angela Duckworth「GRIT やり抜く力」ダイヤモンド社](https://www.amazon.co.jp/dp/B01LMP9RLY/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)
- [Alain Lempereur 「交渉のメソッド」白桃書房](https://www.amazon.co.jp/gp/product/4561236287/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1)
- [Linda Gorchels 「プロダクトマネジャーの教科書」翔泳社](https://www.amazon.co.jp/gp/product/4798111929/ref=ppx_yo_dt_b_asin_title_o09_s00?ie=UTF8&psc=1)

### コメント
- 主要な経営指標からOKRで目標を決めたい、でも指標ってなんぞや…となったときに「起業のファイナンス」を読んで、目標を決めていく具体的なイメージがつかめた。また、数字を意識して意思決定することも増えた

## その他
- [水野「法のデザイン」フィルムアート社](https://www.amazon.co.jp/dp/4845916053/ref=cm_sw_r_tw_dp_U_x_LAV8DbK5XHTJZ )
- [中北「自民党」中公新書](https://www.amazon.co.jp/dp/4121024281/ref=cm_sw_r_tw_dp_U_x_g-U8DbHCW8M9D)
- [原「吉田茂」岩波新書](https://www.amazon.co.jp/gp/product/B00SF0V71S/ref=ppx_yo_dt_b_d_asin_title_o03?ie=UTF8&psc=1)
- [有馬「児玉誉士夫」文春新書](https://www.amazon.co.jp/dp/B00BUETYUC/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)
- [BNN編集部編「クリエイターのためのやさしい英語&英文パターン1500」ビー・エヌ・エヌ新社](https://www.amazon.co.jp/dp/B07XVFM7CV/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)

### コメント
- お堅めな業界向けの仕事に携わることになったとき上の4冊を読んだら、ルールやガイドライン、業界の構造や歴史を深く読めるようになった
- 「児玉誉士夫」は関係ないと言えばないけど、派手で有名な仕事で目立ちたいみたいな感情を殺せるので息抜きにどうぞ
特定のリポジトリに特定のユーザにadmin権限を付与する方法

# 概要

あるユーザに、組織のowner権限は与えずに
特定のリポジトリだけ自由に編集する（admin）権限を与える方法

# 方法

開発者チームと別に、管理者チームを作成し、
対象リポジトリに `admin` 権限を与える

# 設定例

## メンバー

- 開発者
    - Aさん
    - Bさん
    - Cさん
- 管理者
    - Aさん

## 権限

- `開発者` には、αリポジトリのWrite権限、βリポジトリのRead権限を与えたい。
- `管理者` には、αリポジトリのAdmin権限を与えたい。

## 設定内容

以下のチームを作成する。

1. 開発者チーム
  - メンバー : Aさん、Bさん、Cさん
  - 権限 : αリポジトリのWrite権限、βリポジトリのRead権限
2. 管理者チーム
  - メンバー : Aさん
  - 権限 : αリポジトリのAdmin権限

# 備考

- 複数チームに所属しているユーザは、どちらか権限が強い方の設定が適用される。
    - Aさんは `開発者チーム` 側で βリポジトリのRead権限があるので、 βリポジトリを見れる。
- ぐぐるとよく [所有権の委譲](https://help.github.com/ja/github/administering-a-repository/transferring-a-repository) が引っかかって（これかな？）と思いがちだが
これは組織の資産を誰かに委譲する、という機能なのでダメ。絶対。
mockkのslotを使って通信周りの負債解消のリファクタリングをする

ハロー、[@seto_hi](https://twitter.com/seto_hi)です。

最近は本業でも副業でも3年以上前に作られた既存プロダクトの負債解消を行っています。
負債になってしまった実装に対して、mockkのslotを使ったテストによって動作の同一性を保証しながらリファクタリングしていく方法について紹介します。

# どんな場面で使えるか
ほぼブラックボックスになっている負債があるとします。
負債クラスのメソッドを叩くと値が返ってくるようなものだと結果をassertするだけでテストができますが、そうもいかない場合があります。
例えば通信周りが負債になっており、サーバーにどのようなリクエストを送信しているかわからない場合などです。

そのような場合であっても、その負債が最終的に呼ぶクラスがmockやspyができるようになっており、呼ばれるメソッドに引数がある場合に使えます。
例えば[OkHttpClient](https://square.github.io/okhttp/4.x/okhttp/okhttp3/-ok-http-client/)であればnewCallというメソッドの引数にRequestがあります。
OkHttpClientをmockすることができれば、newCallの際に呼ばれたRequestの値をslotによって取得できます。

# サンプルリポジトリ
[こちらのリポジトリ](https://github.com/hiroyuki-seto/slot-sample)に実装しています。
特に、[このPR](https://github.com/hiroyuki-seto/slot-sample/pull/1)が記事の内容を実装したものになります。

## どんな状態か
Apiにpostする`BadImplementationClass`が負債になっており、手入れできない状態です。
(サンプルコードの `BadImplementationClass` はあまり負債になっていませんが、心眼で置き換えて下さい。)
それを新しいコードに置き換えるお仕事を任された状態です。

# 実践
前提を確認したところで、手を動かします。

## 手順0: Respsitoryを作成する
一番最初にRepositoryクラスを作成して、負債であるAPIを叩くクラスをラップします。
[Recommended app architecture](https://developer.android.com/jetpack/docs/guide#recommended-app-arch) に近づくというメリットもありますが、リファクタリング後も変わらないクラスを作成することでテストによる動作の同一性が保証できます。

## 手順1: テストを導入する
前述の通り、ブラックボックス(負債)の最終的なアウトプットをするクラスがmockできるようなパターンの場合に使うことができます。
今回はOkHttpClientが最終的なアウトプットをするのでこちらをmockし、OkHttpClientProviderがmockしたクラスを返すようにします。

```kotlin
  val okHttpClient = mockk<OkHttpClient>() {
    every { newCall(any()) } returns mockk(relaxed = true)
  }
  every {
    OkHttpClientProvider.client
  } returns okHttpClient
```

OkHttpClientはnewCallで実際の通信を行うので、このメソッドの引数を保証しておけばブラックボックス(負債)を置き換えられるのですが、ここがslotの出番です。
slotメソッド呼んでインスタンス生成をしverifyの中でcaptureをしてあげると、verifyが呼ばれた際の値を取得することができます。

```kotlin
  val slot = slot<Request>()
  verify(exactly = 1) {
    okHttpClient.newCall(capture(slot))
  }
```

この結果をassertしてあげることによって、どのような値でメソッドが叩かれたかを保証することができます。

```kotlin
  val capturedRequest = slot.captured
  assertThat(capturedRequest.header("header-name")).isEqualTo("header-value")
  // 以下もassert文が続く
```

## 手順2: 負債を書き換える
テストが書けたのであとはコードを書き換えるだけです。
Repositoryのテストを書いているので、Repository層以下を書き換えてもテストが通るのならば動作は保証されます。
今回はRetrofitを導入してみました。
Requestに書いているheaderとbodyが一致していることはテストによって保証できます。

今回はうまく行くようなケースにしていますが、例えばheaderをInterporatorで追加したい場合などはもう少し複雑になります。
(InterporatorはnewCall以後に呼ばれるため)

## 手順3: 完
これにてリファクタリング完了です。
お疲れ様でした！
flexアイテムの中でellipsisが効かない件


タイトル通りですがコードペンにあげたので見てください（Bootstrapを使ってますので知らない人は分かりづらいかもしれません）。

https://codepen.io/masamoto-miyata/pen/RwNRedO


フレックスアイテムの中にdivをおいてそこにellipsisを書いても効きません。親のフレックスアイテムに`overflow: hidden;`をかける必要があります。かけないと中のdivがまったく縮まないではみ出ます。ちなみに`overflow: auto;`でも大丈夫でした。

しかも、中のdivがinline-blockだと、はみ出はしませんが`...`になりません。blockである必要があります。

Chrome、FireFox、Safariで確認したのでバグではないでしょう。どういう理屈でこうなるのか分かりません。ご存じの方いらっしゃいましたら教えていただけるとうれしいです。

## 追記(2019/12/13 12:24)

`min-width`問題を忘れていた。flexアイテムは`min-width`がautoになるんでしたね。コードペンの方を編集しましたが、`overflow: hidden;`の代わりに`min-width: 0;`でもいけました。ただ、中のdivが`inline-block`だと`min-width: 0;`でも縮まないですね。うーん。多分細かい仕様を聞けば納得いきそうな話ではありますが、ややこしいですね。
SwiftGenを使ってみる

## 初めに
文字列とかを管理するのにSwiftGenというものがあるらしいので使ってみました。
## 導入
まず最初にcocoaPodsを使ってプロジェクトに読み込みます。
1. pod init
2. pod 'SwiftGen'をpodfileに書く
3. pod install

## 実際に使ってみる
まずプロジェクト直下にswiftgen.ymlファイルを追加して以下の設定を追加します

```swift:swiftgen.yml
strings:
  inputs: Localizable.strings
  outputs:
    templateName: structured-swift4
    output: Project名/strings.swift
```
上の設定ではLocalizable.stringsからProject/strings.swiftを生成するというものです。
今回は文字列を管理するのでstrings:をしています。
次にLocalizable.stringsを作ります。
xcodeのFile -> New -> Fileの順に選んでstringsファイルを作ります。
作れたらとりあえず中身を記述します。

```swift:Localizable.strings
"name"="defaultname";
"labelText"="ウヒョーーーー";
```
こんな感じです。
それでは最後にTerminalで

```
Pods/SwiftGen/bin/swiftgen
```
を実行すると
strings.swiftというファイルができていると思います。

```swift:strings.swift
import Foundation

// swiftlint:disable superfluous_disable_command
// swiftlint:disable file_length

// MARK: - Strings

// swiftlint:disable explicit_type_interface function_parameter_count identifier_name line_length
// swiftlint:disable nesting type_body_length type_name
internal enum L10n {
  /// ウヒョーーーー
  internal static let labelText = L10n.tr("Localizable", "labelText")
  /// defaultname
  internal static let name = L10n.tr("Localizable", "name")
}
// swiftlint:enable explicit_type_interface function_parameter_count identifier_name line_length
// swiftlint:enable nesting type_body_length type_name

// MARK: - Implementation Details

extension L10n {
  private static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String {
    // swiftlint:disable:next nslocalizedstring_key
    let format = NSLocalizedString(key, tableName: table, bundle: Bundle(for: BundleToken.self), comment: "")
    return String(format: format, locale: Locale.current, arguments: args)
  }
}

private final class BundleToken {}
```

これができているともう文字列が使えるようになっています。
試しにViewControllerで使ってみると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255216/9269b931-1190-595c-cdda-debaf9ad27c9.png)
こんな感じで文字列を参照できるようになっています。
## 最後に
他にも色々管理できるみたいなので詳しくは公式ドキュメントをみましょう
https://github.com/SwiftGen/SwiftGen
僕のpyautogui(Python)

自分用のまとめ
随時更新

**自分がわかればいいからところどころ用語が間違ってるかも**

！見方

```python
#コマンド
    #引数のオプションの説明
```

#pyautoguiって何に使うの？
なんちゃってRPA作るときとか。
PCの自動操縦
---



###モジュール読み込み

```python
import pyautogui as auto

```



##頻出操作
#####マウス操作

```python
#マウス移動
auto.moveTo(x,y)
   #x座標,y座標に移動

#クリック
auto.click()
    #引数に座標を渡すとそこをクリック

#右クリック
auto.rightClick()
     #引数に座標を渡すとそこを右クリック

#スクロール
auto.scroll()
```


#####画像認識

```python
#画像の中心位置を取得
auto.locateCenterOnScreen()
    #引数に画像
    grayscale=True  #画像をグレースケールで認識

#画像の有無を取得（の時に使う）
l = auto.locateOnScreen()
#locateOnScreenの返り値の中心をとる
auto.Center(l)
```

#####キーボード操作

```python
#キー押しっぱなし
auto.keyDown()

#キー離す
auto.keyUp()

#キー押す
auto.press()

#複数のキーを押す
auto.hotkey()

#文字の入力
auto.typeWrite()  #なぜかうまくいかないことが多いからあんま使わない。
    #引数に打ち込む文字

#文字入力の代替案
pyperclip.copy()
auto.hotkey('ctrl','v')


```
【GitLab】MergeRequestがリロードしても最新状態にならなかったときの原因と対処

MRで最新状態にならないと困惑していた→latest versionになっていなかった
![latest_image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504081/59bd2884-ebda-7d9c-b8ce-7d61d4c76d3a.png)
テスト自動化未経験者がテスト自動化エンジニアになったお話

#はじめに
こんにちは。
Mikatus株式会社の川嵜です。
Mikatusには1年と少し前にQAとして入社しました。これまで、QAとして品質保証を行ってきましたが、突然「テスト自動化よろしく！」と言われ、3ヶ月前に経験したことの無いテスト自動化エンジニアなるものにジョブチェンジしました。
開発もしたことがなく（ほんの少しだけpythonに触れたことはあるくらい）、「Javascript?、selenium？なにそれ？」みたいな状態で、突然テスト自動化エンジニアになりました。
テスト自動化エンジニアエンジニアになってからの3ヶ月間で少しずつではありますが、自分でテストコードを書いて動かしたり、既存のコードを保守したり、それっぽいことができるようになってきました。

テスターやテストエンジニアの方の中には、将来「自動テストエンジニアになりたい！」という方が多くいると思います。（自分の周りだけかな？）
そんな方に向けて、この3ヶ月間でどのようなことをしてきたのかを紹介します。
（「◯◯をした方がもっと成長できるよ！」とかありましたら、ぜひコメントでご意見ください！）

#まずは言語のお勉強
弊社の自動テストはJavascript（ExtJS）で書かれています。
そもそもJavascriptを学習したことがなかったので、まずはJavascriptの勉強からはじめました。
####やったこと
① [ドットインストール](https://dotinstall.com/lessons)を使って基本的なことからお勉強
以下のレッスンを受講
・はじめてのJavaScript (全11回)	
・詳解JavaScript 基礎文法編 (全24回)
・詳解JavaScript オブジェクト編 (全23回)
・詳解JavaScript DOM編 (全15回)

② [Javascript入門書](https://jsprimer.net/intro/)を読んで、より詳細に学習

③ そして、開眼!!（まだ開眼しきっていないけど）
[『開眼！JavaScript』](https://www.oreilly.co.jp/books/9784873116211/)を読む

ただ、動画を見る、本を読むだけでなく、もちろん手を動かしながら学習しました。
だいたい、上の内容を1ヶ月くらいかけて学習しました。



#自動テストのお勉強
「自動テストって、PCがテストやってくれるんでしょ？」くらいのレベルだったので、Javascriptのお勉強と平行して自動テストの勉強も実施。

####やったこと
①書籍読む
・[初めての自動テスト ―Webシステムのための自動テスト基礎](https://www.amazon.co.jp/%E5%88%9D%E3%82%81%E3%81%A6%E3%81%AE%E8%87%AA%E5%8B%95%E3%83%86%E3%82%B9%E3%83%88-%E2%80%95Web%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E8%87%AA%E5%8B%95%E3%83%86%E3%82%B9%E3%83%88%E5%9F%BA%E7%A4%8E-Jonathan-Rasmusson/dp/4873118166)
　自動テストがどういったものなのか、とてもわかりやすく記述されていてとても参考になりました。
　また、自動テストのことだけでなく、これまで行ってきたマニュアルテストに関しても考え直す機会にもなりました。

・[システムテスト自動化 標準ガイド](https://www.amazon.co.jp/%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%83%86%E3%82%B9%E3%83%88%E8%87%AA%E5%8B%95%E5%8C%96-%E6%A8%99%E6%BA%96%E3%82%AC%E3%82%A4%E3%83%89-CodeZine-BOOKS-Fewster-ebook/dp/B00R48BEEW)
　全ては読めていません。辞書のように使っています。

②SenchaTestの勉強
担当しているプロジェクトでは、[SenchaTest](https://www.sencha.com/products/test/)を用いて自動テストを行っているので、SenchaTestの勉強も。

③外部のイベントに参加
以下、参加させていただいたイベントです。
・[ソフトウェアテスト・QA勉強会【（仮）テスト自動化の光と闇（1年間の苦労話）】](https://d-cube.connpass.com/event/149831/)
・[システムテスト自動化カンファレンス2019](https://testautomationresearch.connpass.com/event/144768/)
特に、[D-Cubeさん](https://d-cube.connpass.com/)のイベントは面白く、いつもお世話になっています。
他社でどのようにQAが行われているのか、自動テストを推進しているのかなどを知る機会として利用させていただいています。


#実際に手を動かす
ある程度、勉強を終えたタイミングで実際にテストを書き始めました。
はじめから全てできるようになるのは厳しいので、作業工程ごとに分けて少しずつできるようにしました。

今担当しているプロジェクトの作業をざっと洗い出すと以下のようになります。
・テストスクリプトの作成
・PageObjectの作成
・共通部品・処理の作成（開発にの知識がなくても、テストスクリプトを誰でも簡単に書けるようにした部品）

下に行くにつれに、作成難易度が高くなります。
ですので、まずはテストスクリプトの作成からスタートしました。
ここは、開発でなくても簡単に書ける仕組みがあるので難無くクリア。
PageObjectの作成。
プロダクトのコードを見ながらの作成。開発の知識が無い自分には少しずつ辛くなってくる。
先人たちが作成したものを参考にしながら作成したので、なんとかできた。
そして、共通処理・共通部品の作成。（今、まさに戦っているところ）
開発の知識が無いと本当に厳しい。。

#おわりに
ど素人が自動テストエンジニアになってからの約3ヶ月間で行ったことをまとめてみました。
「これから自動テストエンジニアになってみたい！」「自動テストエンジニアに興味ある！」といった方々の参考に少しでもなっていれば幸いです。
今回の記事では、技術的なところには触れていないので、別の機会に「その２」として記事を書いてみようと思います。
乞うご期待！
TypeScriptで自己参照

自己参照っていう言い方が正しいかわからないですが。。

たとえばこういうやつ :point_down: 
冗長なのでもっと楽したい。けどわざわざ型を追加したくもない。

```ts
interface Player {
  status: "playing" | "stopped";
  prevStatus: "playing" | "stopped";
}
```

## 環境
TypeScript 3.6.2


## こうやる
`this`を使います。

```ts
interface Player {
  status: "playing" | "stopped";
  prevStatus: this["status"];
}
```

以上です :hugging: 

## 参考
- [How to reference type of self in Typescript interface \(for a IClonable interface\) \- Stack Overflow](https://stackoverflow.com/questions/36744033/how-to-reference-type-of-self-in-typescript-interface-for-a-iclonable-interface)
僕のurllib(Python)

自分用のまとめ
随時更新

**自分がわかればいいからところどころ用語が間違ってるかも**

！見方

```python
#コマンド
    #引数のオプションの説明
```

#urllibって何に使うの？
URLへの接続とか操作。
まぁWebDriverあれば、それでいいんだけどね！

---



###モジュール読み込み

```python
import urllib
```



##頻出操作
```python
#プロキシ設定
proxy = urllib.request.PloxyHandler()
    #引数に辞書型でプロキシ設定を渡す。
    #こんな感じ→{'http': 'http://proxy.sample.com:8080'}

#urlを開くオブジェクトを作成
opener = urllib.request.build_opener()
    proxy= #PloxyHandler()で作ったインスタンスを設定

#urlを開くオブジェクトをインストール
urllib.request.install_opener()
    #引数はbuild_openerのインスタンス

#urlに接続
response = urllib.urlopen()
    #引数は開きたいURL

#HTMLのインスタンス取得
html = response.read()
```
マンガでわかる Chain of Responsibility

![A0648B40-3BAD-4B11-AC4E-70F948750216.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/cdb65333-b3ca-b7db-f536-64bdf73fbdce.png)

ゆうしゃくるみよ、このお使いクエストはラスボス戦の直前まで続くのじゃ。なんとか of かんとか ... ファンタジー RPG みたいな名前だったもので。

問い合わせた先が自身で結果を返せないとき、次の人にバトンパスして、どんどん数珠つなぎで結果を返せるオブジェクトに当たるまでやるのが、Chain of Responsibility パターンです。

[Composite](https://qiita.com/tanakahisateru/items/e01be6c630de72b23a36) パターンが多重下請け構造だとするなら、顧客企業が投げた質問を返せる人がいる会社まで、伝言ゲームが続く様子を表しているのがこのパターンって感じですね。(ちょっと〜 ファイルの探索とか HTML DOM のセレクタとか、もっと無難な例を出せませんか)

Proxy を Proxy に接続したような場合も、応答を得るときこのパターンに該当することがあります。Web サーバーの物理構成がまさにそうですし、PHP の PSR15 ミドルウェア (ミュータブルなものの加工ではなくイミュータブルなレスポンスを返す) は HTTP プロクシのチェーンをひとつのプロセスで行うモデルです。

もっとありふれた例でいえば、リンクリストの末尾を返す `last` は Chain of Responsibility そのものです。cons が末尾でない場合は cdr に委譲する処理を末尾再帰最適化で...

デザインパターンはオブジェクト指向言語のためのものだから関数型は関係ないよねなんて言ってたら、そんなの大間違いですね。何指向の言語だとか、そういう話ではないですよね。
MATLABの講習会で学んだこと

# はじめに…

先日、金沢工業大学で行われたMathWorksJapanさんのMATLABの講習会に行ってきました
この記事はその講習会で学んだことの特に基礎の基礎の部分をまとめていきます
MATLABでどんなことができるのかを中心に話していきたいと思います



# 目次
1. MATLABとは
2. MATLABでできること
3. 機械学習とは
4. 学習方法の種類
5. 機械学習の現状
6. 機械学習の問題と解決策
7. まとめ
8. 感想




# 1. MATLABとは
- Matrix Laboratoryの略
- 対話的開発環境(=指示を出すと答えがすぐに帰ってくるような開発環境のこと)
- 豊富な拡張ライブラリがある
- 使用目的
 - 数値解析
 - データ解析、可視化
 - アルゴリズム開発、プログラミング
 - 外部アプリケーションとの連携
- MATLABを用いて作られた機械学習を取り入れているアプリケーションの例
 - 喘息症状管理アプリ (呼吸情報から喘息症状を管理)
 - 再利用可能なロケット (ソフトランディングの成功)
 - ロボット義手 (複雑なリズムを演奏可能)


 
# 2. MATLABでできること
全体の流れ : 入力 → 解析 → 出力


## 入力 : データへのアクセス
- ファイル
- ソフトウェア
- ハードウェア
- ウェブサービス


## 解析 : 処理方法、アルゴリズムの探求
- データ解析モデリング
- アルゴリズム解析
- アプリケーション開発


## 出力 : 結果の共有、アプリ配布
- ドキュメント生成
- 組み込み開発
- アプリケーション配布



# 3. 機械学習とは


## 基礎知識
- プログラムなしにデータから機械が学習することができる能力
- 複雑な非線形な関係性を学習する
- データに随時適合するように更新する
- 大規模データから効率的に学習する


## 機械学習の種類
- 機械学習
  - 教師なし学習
      - クラスタリング (プロットしたデータ同士の距離からクラスに分ける)
  - 教師あり学習
      - 分類 (出力する値が離散量)
      - 回帰 (出力する値が連続量)
  - 強化学習 : はじめにはデータがなく試行の繰り返しによってデータを取り込む
      - 意思決定
      - 制御



# 4. 学習方法の種類
- パーセプトロン
  - 特徴量に重みづけをする
  - ステップ関数を通して特徴を2つに分ける
  - 重みを更新しながら学習結果を正確にする
- ニューラルネットワーク
  - データをニューロンに保存する
  - 入力層から隠れ層を経て出力層にデータを受け渡す
  - 活性化関数を用いてError関数が小さくなるように変える
- Deepニューラルネットワーク
  - ニューラルネットワークの隠れ層を2つ以上にしたもの



# 6. 機械学習の問題と解決策


## 問題点
- 大量のデータを扱う
- 長い学習期間を要する


## 解決策

### 深層学習以外の手法 + 特徴抽出
- 主成分分析(次元の削除 = 可視化と計算量削減)
- 特徴抽出を識別する基準をデータによって変える(例:平均値、標準偏差、ピーク周波数、...etc)

### 転移学習(Transfer Learning)
- 学習済みネットワーク + 独自分類器
- 学習して得る特徴抽出を既存のネットワークから行う
- 得たデータを分類する部分だけを独自で行う



# 7. まとめ
機械学習はいろんなところで利用されている
MATLABは初心者でも機械学習ができるアプリケーションがそろっている
現在、機械学習といってもやり方がたくさんある
機械学習のポイントとなるのは特徴抽出と分類



# 8. 感想
授業ではやらないような機械学習の今を知れたのでとても面白かった
Demoも多かったので実際にどういう風に活用すればいいのかがわかりやすかった
機械学習の細かい仕組みの内容は私が知識不足だったので少し難しく感じた
これからは機械学習を学ぶツールとしてMATLABを活用していきたい
僕のos(Python)

自分用のまとめ
随時更新

**自分がわかればいいからところどころ用語が間違ってるかも**

！見方

```python
#コマンド
    #引数のオプションの説明
```

#osって何に使うの？
フォルダの操作かな～

---



###モジュール読み込み

```python
import os
#globはおまけ
import glob
```



##頻出操作
####フォルダ・ファイル取得
```python
#カレントディレクトリを取得
os.getcwd()


#ファイル名を取得
os.basename()

#絶対パスを取得
os.path.abspath()
    __file__  #実行されてるファイルのパス

#フォルダ名を取得
os.path.dirname()

#一致するファイル名をリストで取得
glob.glob(...*.txt)  #...ってパスにある拡張子.txtのファイル名が取れる。




```

####ファルダ・ファイル変更

```python
#カレントディレクトリを変更
os.chdir()

#引数のフォルダを作成
os.mkdir()

#パスをすべて小文字に変換するらしい
os.path.normase()
    #引数にパス
```


####ファルダ・ファイル確認

```python
#フォルダの存在確認
os.path.isdir()

#ファイルの存在確認
os.path.exists()

```
DataTablesを日本語化したときの留意点

## DataTablesについて
[DataTables](https://datatables.net/)はHTML上で表（テーブル）を扱う時に非常に便利なJavaScriptのライブラリです。
高機能で、必要になりそうな操作はほとんどがプラグイン形式で用意されています。
そのなかで、1点、**重要と思われる留意点**を見つけましたので共有したいと思います。

## 国際化プラグイン（language.urlオプション）はテーブルの初期化を非同期にする
[国際化プラグイン](https://datatables.net/plug-ins/i18n/)を使ってUIの日本語化（国際化）を行うと、設定オブジェクトの取得がAjaxで行われるため、`$(dom).DataTable()`による初期化とそれ以降の処理のタイミングがずれます。
公式ドキュメントにもちゃんと[注意書き](https://datatables.net/reference/option/language.url)がありました。

>Note that when this parameter is set, DataTables' initialisation will be asynchronous due to the Ajax data load. That is to say that the table will not be drawn until the Ajax request as completed. As such, any actions that require the table to have completed its initialisation should be placed into the `initComplete` option callback.

つまり、公式ドキュメントで仮に下記のような見本があったとして、

```javascript
var table = $("#DataTable").DataTable({...});//オプションを渡して初期化
table.xxxApi().doAnythng();//何かのAPIを呼び出してDateTablesを操作する
```
初期化のオプションに **`language.url`が含まれていると2行目のAPIの動作は保証されません。**
DataTablesを使っていて、**APIの挙動がおかしい、イベント処理やDOM制御が上手くいないときは、これを疑ってください。**

## 解決策
### initCompleteオプションを使う
DataTablesの初期化オプションに用意されている[`initComplete`オプション](https://datatables.net/reference/option/initComplete)でハンドラを設定して、DataTablesの初期化が完了してから後続の処理を行います。

```javascript
$("#DataTable").DataTable({
    "language" : {"url":"any.json"},
    "initComplete" : function(settings, json) {
        this.xxxApi().doAnythng();//ここで処理する
    }
});
//以下、DataTablesとは関係しないその他の処理
```
この場合は`this`でAPIにアクセスできますが、別途、関数を定義して実行する場合には[`$(dom).DataTable()`と`$(dom).dataTable()`の違い](https://datatables.net/manual/api)にも注意が必要です。
ちなみに、このハンドラではDataTableの設定オブジェクトとテーブル内のデータを受け取ることができますので、それらに応じて諸々の処理が可能です。

### language.urlを使用しない
素直に`language`オプションにコードから[オブジェクトで設定を渡す](https://datatables.net/reference/option/language)方法もあります[^1]。日本語の設定は[このページ](https://datatables.net/plug-ins/i18n/Japanese)に記述されています。カスタマイズの際にも参考にしましょう。
[^1]: 項目も多いしバージョン変更などがあると対応に追われそうですが…
この場合は実行タイミングのずれがないため、公式ドキュメントの例の通りに記述しても動作してくれるはずです。

## まとめ
DataTablesは便利で高機能ですが、それだけに動作は複雑です。機能とそれに関わるAPIやオプションは、Google先生の翻訳に頼りながらでも一読しておきましょう。
私は拡張機能の[ButtonsのDOM操作](https://datatables.net/extensions/buttons/)で数時間悩みました。Buttons自体はとても便利な拡張ですよ。
Pandas環境を整える

# 目的
Pandasの環境を整える

# Ref.
[pyenv](https://github.com/pyenv/pyenv)
[venv](https://qiita.com/fiftystorm36/items/b2fd47cf32c7694adc2e)
[pandas](https://github.com/pandas-dev/pandas)
[sample code](https://algorithm.joho.info/programming/python/pandas-data-analysis-sample/)

# 環境と作業概要
- vagrantを使ってubuntu18.04を用意
- ubuntu18.04上でpyenvを使ってpython3.7.5をinstall
- venvを使って、python packageの仮想環境を構築
- 仮想環境上でpandasをinstall
- 簡単なpython sample codeを書いてpandasの動作確認

# 作業ログ
```bash:bash
# vagrant用のディレクトリ作成
$ mkdir python-study && cd python-study

# vagrantfileを生成
$ vagrant init bento/ubuntu-18.04

# 仮想マシンを起動
$ vagrant up

# 仮想マシンにlogin
$ vagrant ssh

# pandasと依存関係のあるpackageをaptでinstallする
vagrant@vagrant:~$ sudo apt-get install libffi-dev libbz2-dev liblzma-dev

# pythonのversionを複数切り替えて使えるようになるpyenvをinstallする
vagrant@vagrant:~$ git clone https://github.com/pyenv/pyenv.git ~/.pyenv
vagrant@vagrant:~$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
vagrant@vagrant:~$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
vagrant@vagrant:~$ echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n  eval "$(pyenv init -)"\nfi' >> ~/.bash_profile

# 一度logout => loginする

# python 3.7.5をinstallする
vagrant@vagrant:~$ pyenv install 3.7.5

# directoryを作成し、その配下でのみpython 3.7.5を使うようにする
vagrant@vagrant:~$ mkdir pj01 && cd pj01
vagrant@vagrant:~/pj01$ pyenv local 3.7.5
vagrant@vagrant:~/pj01$ pyenv version
3.7.5 (set by /home/vagrant/pj01/.python-version)

# 参考: 動作確認。こんな感じで、directoryを移動すると、pythonのversionが変わる
vagrant@vagrant:~$ python -V
Python 2.7.15+
vagrant@vagrant:~$ cd pj01/
vagrant@vagrant:~/pj01$ python -V
Python 3.7.5

# 先ほどのpython3.7.5環境上で、venvを使って、python package管理の仮想環境を作る。
# これで、他のpython3.7.5環境とpython packageを独立管理できるようになる。
# tips: venv という名前でプロジェクトディレクトリ直下に作成しておく（$ python3 -m venv venv）のが良い．ディレクトリ移動 → venv アクティベート → 作業 という流れができたり、IDEによっては1つのプロジェクト内でソースコードと一緒にvenvも管理できるので．
vagrant@vagrant:~/pj01$ python -m venv venv

# Activateして今回作った仮想環境に入る
vagrant@vagrant:~/pj01$ source venv/bin/activate
(venv) vagrant@vagrant:~/pj01$

# pipをversion up
(venv) vagrant@vagrant:~/pj01$ pip install --upgrade pip

# pipを使ってpandasをinstall
(venv) vagrant@vagrant:~/pj01$ pip install pandas
```

# Pandasの動作確認
pj01ディレクトリにて、pandasを使ったtest用のpython codeを作成する

```python:main.py
# -*- coding: utf-8 -*-
import pandas as pd

# リスト作成
data1 = [158, 157, 157]

# インデックスラベル
index_data = ['aaa','bbb','ccc']

# リストをSeriesに変換
data2 = pd.Series(data1, index=index_data)
print(data2)
```
# Pandasを使ったテストコードを実行する
```bash:bash
pvagrant@vagrant:~/pj01$ python main.py
aaa       158
bbb       157
ccc       157
dtype: int64
vagrant@vagrant:~/pj01$
```

# 参考: 仮想環境から抜ける方法
```bash:bash
(venv) vagrant@vagrant:~/pj01$ deactivate
```
アダプティブアイコン(Adaptive Icon)にとりあえず対応する

# アダプティブアイコン(Adaptive Icon)とは？
Adaptive Icon(アダプティブアイコン)とは、Android 8.0以降から実装された機能のこと。
https://blog.digimerce.jp/2018/11/19/6809/
背景とか説明はこのサイトが分かりやすいです。

<img src="https://developer.android.com/guide/practices/ui_guidelines/images/NB_Icon_Layers_3D_03_ext.gif" width=50%><img src="https://akira-watson.com/wp-content/uploads/2018/07/image-asset_04.jpg" width=50%>

背景画像の上に、メインとなる画像を重ねて、
その上から中心に丸や四角の穴が空いたマスクで覆って表現するみたいです。

# 対応方法
## アイコンにする画像の準備
アダプティブアイコンは２つの画像が必要です。
- アイコンの前面になる画像
- アイコンの背景になる画像（色指定も可能なので必須ではない）

画像さえあれば30分もかからずに対応できます！
今回はこれで作ります。
<img src="https://img.esa.io/uploads/production/attachments/10384/2019/10/02/47651/d91acb3d-b154-45df-b03f-7ed8b11a8323.png" width=50%>

Androidで使うアイコン画像の中で1番大きいサイズのものが512×512なので
それより大きければ大丈夫だと思います。
今回は1024×1024で用意しました。背景は透過しておきます。

## Image Asset
画像が用意できたのでアダプティブアイコンを作るのですが、Android StudioのImage Assetを使って作成します。
Android Studio上で操作するのでデザイナーではなくエンジニアの作業になります。

## いざ作成
1. Android Studioのナビゲーションバーの「app」の上で右クリックし、[New]→[Image Asset]の順で選択します。
![スクリーンショット 2019-10-02 14.19.46.png (175.2 kB)](https://img.esa.io/uploads/production/attachments/10384/2019/10/02/47651/928c30cb-306d-4c5a-afa0-42bef444c2e0.png)

1. アイコンの前面になる画像を設定
   1. 「Foreground Layer」タブが選択されている状態で「...」を押して画像を選択する
   1. Trim、Resizeをいじっていい感じに配置する
 ![スクリーンショット 2019-10-02 15.00.44.png (285.4 kB)](https://img.esa.io/uploads/production/attachments/10384/2019/10/02/47651/fbdb446d-b58c-4a1f-8fad-60f4da8e90b5.png)

2. アイコンの背景を設定
今回は背景は画像ではなく単色指定にします。
   1. 「Background Layer」タブが選択されている状態でAsset Typeを「Color」にし、好きな色を選ぶ
 ![スクリーンショット 2019-10-02 15.02.19.png (264.4 kB)](https://img.esa.io/uploads/production/attachments/10384/2019/10/02/47651/1fdc56bf-fe61-4fbd-a3f1-3517b028e158.png)
   いい感じに配置できたら右下のNextを押します。

1. 問題なければそのままFinish
![スクリーンショット 2019-10-02 15.05.05.png (246.2 kB)](https://img.esa.io/uploads/production/attachments/10384/2019/10/02/47651/230da006-f889-44d2-9f50-f93242b8b655.png)
赤文字のファイルがImage Assetが自動で作ってくれたファイルです。
各サイズごとのアイコンと、xmlファイルも自動生成してくれています。

1. ビルドしてシミュレータで見てみましょう
   <img src="https://img.esa.io/uploads/production/attachments/10384/2019/10/02/47651/ccc4fdaf-ab1d-4370-ad75-99105c0e7086.png" width=50%><img src="https://img.esa.io/uploads/production/attachments/10384/2019/10/02/47651/bfd8c6b3-83d1-453f-b536-efd3c726abb7.png" width=50%>
   Androidのバージョンによって、同じアイコンが丸になったり四角になったりするようになりました！

こんな感じで簡単にアダプティブアイコンに対応できます。
僕のBeautifulSoup(Python)

自分用のまとめ
随時更新

**自分がわかればいいからところどころ用語が間違ってるかも**

！見方

```python
#コマンド
    #引数のオプションの説明
```

#BeautifulSoupって何に使うの？
HTMLを解析してスクレイピングやら


---



###モジュール読み込み

```python
import bs4
```



##頻出操作
#####HTMLインスタンス取得から頻出の解析

```python
#解析用オブジェクト取得
soup = bs4.BeutifulSoup()
    #第一引数にHTMLオブジェクト→webdriver.get_sourceとかで取れるやつ
　　#第二引数にHTMLパーサー
      #→代表的なのlxml,html5lib,html.parser

#要素情報で一つ見つける
element = soup.find()
    class= #クラス名
    href= #リンク
　　""　#何もつけないとタブ

#要素情報ですべて見つける
element = soup.find_all()
    #引数はfind()と同じ
    #複数ある場合は返り値はリスト

#cssセレクタですべて見つける
element = soup.select()

#見つけた要素のテキスト部分だけにする
element.string
```
Rocket.ChatをCentOS 7にインストール

Rocket.ChatをCentOS 7にインストールしたときの躓きポイントをメモ。

Rocket.Chat 2.3.2 
CentOS 7.7.1908
Mongodb 4.0.13
NodeJS 8.16.2

# インストール
基本的に公式ドキュメントの手順通り → [Rocket.Chat in CentOS](https://rocket.chat/docs/installation/manual-installation/centos/)

# 躓きポイント


### nodejsのバージョン指定を変更

インストールされているNodeJSに合わせてバージョンを指定する必要がある

```Bash
sudo npm install -g inherits n && sudo n 8.11.4
```
☟

```Bash
sudo npm install -g inherits n && sudo n 8.16.2
```

### ストレージエンジンの設定

ストレージエンジンの設定を実行するとmongodの起動時エラーが発生するので☟のコマンドは実行しない。

```Bash
sudo sed -i "s/^#  engine:/  engine: mmapv1/"  /etc/mongod.conf
```

エラー内容

```Bash
[root@centos7-chat server]# systemctl status mongod
 mongod.service - MongoDB Database Server
   Loaded: loaded (/usr/lib/systemd/system/mongod.service; enabled; vendor preset: disabled)
   Active: failed (Result: timeout) since Fri 2019-12-13 11:07:15 JST; 25s ago
     Docs: https://docs.mongodb.org/manual
  Process: 1410 ExecStart=/usr/bin/mongod $OPTIONS (code=killed, signal=TERM)
  Process: 1409 ExecStartPre=/usr/bin/chmod 0755 /var/run/mongodb (code=exited, status=0/SUCCESS)
  Process: 1407 ExecStartPre=/usr/bin/chown mongod:mongod /var/run/mongodb (code=exited, status=0/SUCCESS)
  Process: 1406 ExecStartPre=/usr/bin/mkdir -p /var/run/mongodb (code=exited, status=0/SUCCESS)

Dec 13 11:05:45 centos7-chat systemd[1]: Starting MongoDB Database Server...
Dec 13 11:05:45 centos7-chat mongod[1410]: about to fork child process, waiting until server is r...ons.
Dec 13 11:05:45 centos7-chat mongod[1410]: forked process: 1413
Dec 13 11:07:15 centos7-chat systemd[1]: mongod.service start operation timed out. Terminating.
Dec 13 11:07:15 centos7-chat systemd[1]: Failed to start MongoDB Database Server.
Dec 13 11:07:15 centos7-chat systemd[1]: Unit mongod.service entered failed state.
Dec 13 11:07:15 centos7-chat systemd[1]: mongod.service failed.
Hint: Some lines were ellipsized, use -l to show in full.
```

以上。
React

#自分用メモ

##ArrayにsetStateでデータを追加したい時
####pushではなくconcatを使う
```javascript
          this.setState({
              myArray: this.state.myArray.concat(e.file.response.data)
          })
```


#Router

```react:index.js
<Router>
    //初期画面
    <Route exact path="/" component={App} />
    //他の画面
    <Route path="/newPage" component={newPage} />
</Router>
```

##Componentから移動したいとき

```react:app.js
this.props.history.push({
    pathname: "/newPage"
})
```

##編集しやすいため、ページリンクまとめ作るの推薦

```react:PageRoute.js
const PAGEROUTE = {
    NEW_PAGE: "/newPage"
}
export default PAGEROUTE;
```
```react:Router.js
const Routing = (
    <Router>
         ...省略
    </Router>
)
export default Routing;
```


```react:index.js

import Routing from './Router';

render() {
    render(
        <div>
            <Routing />
        </div>
```

```react:app.js
import PAGEROUTE from './PageRoute';

this.props.history.push({
    pathname: {PAGEROUTE.NEW_PAGE}
})
```
OpenSSHで作成した鍵がOpenSSLでpemに変換できなかった

タイトルが無駄に長いけど、まぁ、そういうことなんですよ。

## NGパターン

```bash
$ ssh-keygen -t rsa -f ~/.ssh/ssh_key
$ openssl rsa -in ~/.ssh/ssh_key -outform pem > ~/.ssh/ssh_key.pem
$ unable to load Private Key
```

## OKパターン

```bash
$ ssh-keygen -t rsa -f ~/.ssh/ssh_key -m PEM
$ openssl rsa -in ~/.ssh/ssh_key -outform pem > ~/.ssh/ssh_key.pem
$ writing RSA key
```

## 解説

[OpenSSH 7.8](https://www.openssh.com/txt/release-7.8)で秘密鍵のヘッダが変わったらしい。

```bash
# old style
-----BEGIN RSA PRIVATE KEY-----

# new style
-----BEGIN OPENSSH PRIVATE KEY-----
```

鍵生成時の`-m PEM`がミソ。これを追加することで、古いPEM形式の鍵を生成できる。OpenSSLで`.pem`に変換する時は、古い形式のヘッダじゃないと秘密鍵を読み取れないっぽい。
CRUDとは

# CRUDとはなにか
**CRUD**とはデータベースの基本的な処理を表しています。
`create`、`read`、`update`、`delete`,それぞれの頭文字をとった造語になります。
それぞれの処理は以下のようになります。

| 言葉     |       意味 | 
|:-----------------|------------------:|
| create             |             新規に作成する |         
| read           |            データを読み込む、選択する |      
| update             |              更新する |     
| delete           |                削除する | 

webアプリに使われる多くのフレームワークに採用されています。
RailsもCRUDを使ったフレームワークの一つになります。
collection_check_boxesの作り方

hamlを使ってransackとcollection_check_boxesを使った検索機能を実装しました。
その際属性付けなどに苦労したので記事にします。


```ruby:complex-search.haml
  = s.collection_check_boxes :status_in, @statuses, :first, :second do |b|
  　　.search-box-left
     　　　= b.check_box
      　　　= b.label  { b.text }
```
それぞれのコードを分解して説明

```
= b.check_box
```
= b.check_boxで以下のようなチェックボックスを画面上に表示
<img width="443" alt="スクリーンショット 2019-12-13 10.52.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543837/f129e73a-6666-7ca2-4d23-79436d9dbe8c.png">


```
= b.label  { b.text }
```
チェックボックスの横にラベル化された文字を表示させる
<img width="309" alt="スクリーンショット 2019-12-13 10.57.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543837/7bb0e5a6-aa27-eb66-618e-5545b2664159.png">

この文字がどこから引っ張り出されているかというと・・

```exhibits_controller.rb
@statuses = [["", "すべて"],["新品", "新品・未使用"],["未使用に近い"," 未使用に近い"],["目立った傷や汚れ無し","目立った傷や汚れ無し"],["やや傷や汚れあり","やや傷や汚れあり"],["傷や汚れあり","傷や汚れあり"],["全体的に状態が悪い","全体的に状態が悪い"]]
```
配列内の第二引数の文字列が実際に画面に表示される文字で第一引数がDB内の検索用に使う値


自分でcollection_check_boxesを作った際にラベルの付け方やクラス付けに苦労しました。
この記事もそんな方々の参考になれば幸いです。
AmazonLinuxでPHPを5.3→5.6にバージョンアップする

### 概要
* PHP5.3を最新版ではなく5.6（もしくは何らかのバージョン）指定でアップデートしたい時の方法です
* PHP5.3はApache2.2系、PHP5.6はApache2.4系と依存関係があるので、一緒にアップデートする必要があります
* Apache再インストールの際にダウンタイムが発生するので、必要であればメンテナンス時間を設けましょう

### 流れ
1. サーバーの状態を確認
1. 現在のPHP,Apacheをアンインストール
1. アップデート対象バージョンのPHP,Apacheをインストール
1. （必要な場合）Apacheのhttpd.confを修正
1. Apacheを起動

### 手順
#### OSの確認
対象サーバーにSSHでログインして以下コマンドを実行

```
# cat /etc/system-release
```
  
#### PHPバージョンの確認

```
# php -v
PHP 5.3.29 (cli) (built: May 12 2015 22:42:19)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2014 Zend Technologies
```

#### インストールされているPHPおよびライブラリのバージョン確認  

```
# yum list installed | grep php
php.x86_64                           5.3.29-1.8.amzn1              @amzn-main
php-cli.x86_64                       5.3.29-1.8.amzn1              @amzn-main
php-common.x86_64                    5.3.29-1.8.amzn1              @amzn-main
php-mbstring.x86_64                  5.3.29-1.8.amzn1              @amzn-main
php-mysql.x86_64                     5.3.29-1.8.amzn1              @amzn-main
php-pdo.x86_64                       5.3.29-1.8.amzn1              @amzn-main
php-xml.x86_64                       5.3.29-1.8.amzn1              @amzn-main
```

#### インストールされているApacheのバージョン確認  

```
# yum list installed | grep httpd
httpd.x86_64                         2.2.34-1.16.amzn1             @amzn-updates
httpd-tools.x86_64                   2.2.34-1.16.amzn1             @amzn-updates
```

#### インストール可能なPHPおよびライブラリのバージョン確認

```
# yum list available | grep php
（〜中略〜）
php56.x86_64                          5.6.40-1.143.amzn1            amzn-updates
php56-cli.x86_64                      5.6.40-1.143.amzn1            amzn-updates
php56-common.x86_64                   5.6.40-1.143.amzn1            amzn-updates
php56-mbstring.x86_64                 5.6.40-1.143.amzn1            amzn-updates
php56-pdo.x86_64                      5.6.40-1.143.amzn1            amzn-updates
php56-xml.x86_64                      5.6.40-1.143.amzn1            amzn-updates
php56-mysqlnd.x86_64                  5.6.40-1.143.amzn1            amzn-updates
（〜以下略〜）
```

#### php.iniのバックアップ

```
# cp /etc/php.ini /home/php.ini.yyyymmdd
```

#### httpd.confのバックアップ

```
# cp /etc/httpd/conf/httpd.conf /home/httpd.conf.yyyymmdd
```

#### インストール済みPHPおよびライブラリの削除

```
# yum remove php
# yum remove php-common
# yum remove php-cli
# yum remove httpd
# yum remove httpd-tools
```

#### PHP5.6およびライブラリのインストール  
※Apacheは依存関係で自動的にインストールされる

```
# yum install php56 php56-common php56-cli
```

#### httpd.confの修正
バックアップしたhttpd.confを読み解き、必要な設定を加える

```
# vi /etc/httpd/conf/httpd.conf
```

2.2系と2.4系でアクセス許可設定の記法が変わっているので注意
（参考：https://qiita.com/nwsoyogi/items/c8eb1fedef3c00c5fbac）

```2.2系
<Directory "/home/xxx/htdocs">
    Order allow,deny
    Allow from all
</Directory>
```

```2.4系
<Directory "/home/xxx/htdocs">
    Require all granted
</Directory>
```

#### Apache起動
 
```
# service httpd start
```

#### 確認
PHPのサンプルコードやPHPアプリケーション（phpmyadminなど）で動作確認ができたらOKです
FortiGateのアプリケーションコントロールIDを取得する

# はじめに
FortiGateのアプリケーションコントロールIDは[fortiguard.com](https://fortiguard.com/appcontrol)にて公開されてますが、一覧では表示されません。。。
フローコレクタに情報を読み込ませる時など、csvで一覧が欲しいと思った方は少なからずいるはず。

## 本体から取得する
下記のコマンドを利用してCLIから一覧を取得できます。

```
config application list
edit default
config entries
edit 1

# set application ?
```
?を入力すると出力されるわけですが、機器によって対応しているアプリケーションが[異なる](https://fortiguard.com/appcontrol/categories)ので、できればfortiguard.comから全てのデータを取得したい。

## 自作ツール作りました。
pythonで自作ツールを作りました。

```bash
pip install beautifulsoup4 lxml requests
```

```python
import requests
import csv
import re
import time
from bs4 import BeautifulSoup

s = requests.Session()

url = 'https://www.fortiguard.com/appcontrol'

user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36'
headers = {'User-Agent': user_agent, 'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7'}

while True:
    try:
        get_url_info = s.get(url, headers=headers, timeout=5)
        get_url_info.raise_for_status()
        bs4Obj = BeautifulSoup(get_url_info.content, 'lxml')
        result = bs4Obj.find('div', class_='sidebar-content')
        appids = int(re.findall('[0-9]+', result.find('a').get_text().replace(',', ''))[0])
        perPage = int(len(bs4Obj.find_all('div', class_='title')))
        break
    except Exception as e:
        print(e)
        time.sleep(1)
        continue

if appids % perPage == 0:
    pages = int(appids // perPage)
else:
    pages = int(appids // perPage) + 1

i = 1
datas = []
url_base = 'https://www.fortiguard.com/appcontrol?page='

while pages + 1 > i:
    print('page:', i, '/', pages)
    url = url_base + str(i)
    try:
        time.sleep(1)
        get_url_info = s.get(url, headers=headers, timeout=5)
        get_url_info.raise_for_status()
        bs4Obj = BeautifulSoup(get_url_info.content, 'lxml')
        app_list = bs4Obj.find_all('div', class_='title')
        if len(app_list) != perPage:
            if i == pages:
                pass
            else:
                continue
    except Exception as e:
        print(e)
        continue
    j = 0
    while True:
        try:
            app_name = str(app_list[j].find('a').get_text())
            app_num = int(re.findall('[0-9]+', app_list[j].find('a').get('href'))[0])
            data = [app_num, app_name]
            datas.append(data)
            j += 1
        except:
            break
    i += 1

print('result:', len(datas), '/', appids)

with open('appid.csv', 'w') as file:
    writer = csv.writer(file, lineterminator='\n')
    writer.writerows(sorted(datas))
```
Githubに同じコードをアップしてます。
https://github.com/Connie-Wild/FortiOS_AppControlID
それでは！
ストロングパラメーターとは

# ストロングパラメーターについて
フォームから値を送信したいのにDBに保存されない・・・
そんなときにみるポイントの一つが**ストロングパラメーター**です。

ストロングパラメーターとはざっくりいうとセキュリティーのことです。
まず、ビューのフォームで入力された値は`params`でコントローラーに送られます。
その際に許可していない不正の`params`を受け取らないようにするのがストロングパラメーターになります。
メリットとして、意図しないデータを受け取らないようにできることや、管理者のみ変更できるデータの変更を外部から変更されることを防ぐなどがあります。

以下、ストロングパラメーター例文

```tweets_controller.rb
  def tweet_params
    params.require(:tweet).permit(:text,:image)
  end
```

今回は`tweets_params`というメソッドでストロングパラメーターを定義しています。
`require`の部分で何の値を受け取るのか、
`permit`は`require`で指定した値の中からどのカラム値を許可するのかどうかを定義しています。
今回の場合tweetsテーブルのtextカラム,imageカラムのみ受け取るという状態になります。

セキュリティーとして非常に大切なものになりますが、受け取りたい値の誤字、脱字によってDBに保存されないことが起こりうるので、気をつけて使いましょう。
僕のWebdriver(Python)

自分用のまとめ
随時更新
**自分がわかればいいからところどころ用語が間違ってるかも**

！見方

```python
#コマンド
    #引数のオプションの説明
```

###モジュール読み込み

```python
#Webdriver
from selenium import webdriver

#webdriverの待機モジュール
from selenium.webdriver.support.ui import WebDriverWait

#要素の読まれ具合とかをみるモジュール
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.common.by import By

#Webdriverのオプション設定モジュール(Chrome)
from selenium.webdriver.chrome.options import Options

#要素に値を送るときに使う
from selenium.webdriver.common.keys import Keys
```

##WebDriver頻出操作

#####起動～接続

```python
#Webdriver起動
driver = webdriver.Chrome()
    executable_path=  #Webdriverの格納パス
    chrome_options= #起動オプション

#全ての要素が読み込まれるまで待機
WebDriverWait(driver,15).until(ec.presence_of_all_elements_located)

# ID指定したページ上の要素が読み込まれるまで待機（15秒でタイムアウト判定）
WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.ID, 'ID名')))

#URL・HTMLファイル接続
driver.get()
    #引数にURLかHTMLのパス

#HTMLを取得
driver.get_source()

```

#####オプション設定

```python
#オプションのオブジェクト作成
options = Options()

#オプションの追加
options.add_argument()
    '--headless' #ヘッドレスモード
```


#####ウィンドウ操作

```python
#HTMLを取得
driver.get_source()

#ウィンドウサイズを取得
driver.get_window_size()

#ウィンドウサイズを設定
driver.set_window_size()
    #第一引数が幅
    #第二引数が高さ
    
#ウィンドウの最大化
driver.maximize_window()

#ウィンドウの位置設定
driver.set_window_position(x,y)
    #第一引数がx座標
    #第二引数がy座標
```
#####要素の取得と操作

```python
#IDで要素取得、下は複数取得
element = find_element_by_id()
elements = find_elements_by_id()

#nameで要素取得、下は複数取得
element = find_element_by_name()
elements = find_elements_by_name()

#xpathで要素取得、下は複数取得
element = find_element_by_xpath()
elements = find_elements_by_xpath()

#linktextで要素取得、下は複数取得
element = find_element_by_link_text()
elements = find_elements_by_link_text()

#タグ名で要素取得、下は複数取得
element = find_element_by_tag_name()
elements = find_elements_by_tag_name()

#クラス名で要素取得、下は複数取得
element = find_element_by_class_name()
elements = find_elements_by_class_name()

#cssセレクタで要素取得、下は複数取得
element = find_element_by_css_selector()
elements = find_elements_by_css_selector()

#取得した要素をクリック
element.click()

#取得した要素に値を送る
element.send_keys()
    #引数に送る値

#取得した要素にRETURNキー
element.send_keys(Keys.RETURN)

#入力欄を空に
element.clear()　#値が入ってないのに消そうとするとエラーが起きる


```
rpmbuildで "fg: no job control" エラーが出る場合

## 参考

* [エンタープライズ：特集：第2回　RPM活用のステップアップ－SRPMリビルドとコンパイルマスター (5/6)](https://www.itmedia.co.jp/enterprise/0309/26/epn02_5.html)

## 例

別のディストリビューションやバージョンのspecファイルをrpmbuildする場合、
マクロ定義が不足していることがありそれでエラーになっている。

以下例だと、 `%ldconfig_scriptlets` という定義が無いことが原因。

specファイルから該当行を削除し今一度rpmbuildし成功することを確認。

![スクリーンショット_2019-12-13_10-55-29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/9412f342-b16c-0e37-0780-1dab699c365e.png)

```diff:libpng.spec
- %ldconfig_scriptlets
```
GitLab CEで .gitlab-ci.yml を変更されないようにファイルロックする方法　Git LFS 

## [はじめに](#はじめに)
色々調べて、Git LFSによるファイルロックができたので、忘備録として作ってみた

## [要望](#要望)
* gitlab-ci.ymlをいじられたくない
* 有料版Gitlabは使いたくない。CEのままがいい

## [ググる](#ググる)
「Gitlab file lock」とかでググると以下の二つにあたる

* CODEOWNERS
* FILE LOCKING

### CODEO WNERS
[Code Owners | GitLab
](https://docs.gitlab.com/ee/user/project/code_owners.html)
version historyを開くと

>Introduced in GitLab Starter 11.3.
>Support for group namespaces added in GitLab Starter 12.1.
>Code Owners for Merge Request approvals was introduced in GitLab Premium 11.9.

CEに導入されてないので、パス

### FILE LOCKING
GitLab Docs
[File Locking | GitLab
](https://docs.gitlab.com/ee/user/project/file_lock.html)

>Introduced in GitLab Premium 8.9.

CEに導入されてないので、パス

## [Git LFS (Large File Storage)](#Git LFS)
GitLab Docs
[Git LFS | GitLab
](https://docs.gitlab.com/ee/administration/lfs/manage_large_binaries_with_git_lfs.html)

サイズが大きいバイナリファイルをGitで管理しやすくする拡張機能の一つで、以下の記事にわかりやすく説明されてた
[Git LFS で大きいサイズのバイナリファイルも Git で管理する](https://qiita.com/msh5/items/582c086311d3630563bc)

もう一つの特徴として、ファイルロック機能があったので試してみることに

## [Git LFS 導入](#Git LFS 導入)

※Gitlabサーバーとは別のサーバーで作業してます

適当にディレクトリ作って、lockしたいファイルがあるgitをcloneする

~~~
mkdir git_lfs_test
cd git_lfs_test
git clone http://11.111.11.111/hoge/hogehoge.git
~~~

GitLab version8.2以降ならパッケージにgit-lfsがあるので、yum

~~~
yum install git-lfs
~~~

インストールされているかコマンドうってみる

~~~
git lfs install
Git LFS initialized.
~~~

ファイルロック

~~~
git lfs lock .gitlab-ci.yml
Username for 'http://11.111.11.111': GitlabのUsernameを入力
Password for 'http://root@11.111.11.111':パスワード入力
.gitlab-ci.yml  GitlabのName   ID:User ID

# ファイルロック一覧を確認
git lfs locks
Username for 'http://11.111.11.111': GitlabのUsername
Password for 'http://root@11.111.11.111':
.gitlab-ci.yml  GitlabのName   ID:User ID
~~~

Gitlabでlock時に入力したUsername以外でログインして、指定したファイルを編集し、commitすると

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469943/e4b6c611-c22e-fb7a-031c-5a87db2aebcf.png)

できた