OmniAICreator/Qiita-1.07M huggingface dataset:
SETが開発チームに自動テスト導入支援をするときの心得


# はじめに
この記事における **自動テスト導入支援** とは開発プロセスに自動テストを組み込むことで、なにかしらの長期的なプラスの効果を作り上げることを指します。
例. 毎リリースごとに実行していた回帰テストの自動化

LIFULLのSETチームはこの長期的に価値をもたらす支援とある特定のリリースの際にスポット的に行う自動テスト支援と２パターンの関わり方がありますが、今回は前者に関する内容になります。

この支援において学んだことを心得としてをまとめてます。少しニッチな内容ですがお付き合いください。

ちなみに下記が弊社のSETの支援体制です。
![DEV-SET.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10800/5806ca8f-27a1-3761-c1ef-780287b8d61e.png)

# 支援フェーズごとの心得
心得は以下のフェーズごとにあると考えています。
※ このフェーズは目安なので、対象に合わせて調整します

- 支援開始
- テスト計画・設計
- テスト実装
- 運用開始
- 支援終盤

# 支援開始

### 支援対象チームのテスト自動化についての状況を把握しましょう
例えば「自動化したいテストケースが設計済で自動化を進めたい」と「まずはテスト自動化について知りたい」だと支援内容がかなり違います。
自動化の準備がどのくらい進んでいるのか、自動テストの要求分析が済んでいるのか、そもそも自動テストに関する知識がどの程度あるのかなどを確認する必要があります。

### 支援対象チームメンバーはどのくらい工数をさけるのかを確認しましょう
何人が、週に何時間くらい使えるのかを確認しましょう。

### コミュニケーションのとり方を決めましょう
共通のチャットツールがあればチャンネルをつくったり、定期的なMTGを行うのかを決めましょう。
私の経験上、初期段階では最低週１回は定期的なミーティングを行うべきだと思います。
顔合わせ機会を増やすことと進捗の同期が重要です。
相手の心情やスキルの把握ができ、心理的安全性の確保（話しやすい関係の構築）にも繋がります。
かなり大事です。
アジェンダには次回定例までに何をやるかを決めて終わりにするのも有効です。
テスト自動化はサブプロジェクトになることが多いため明確なアクションを握っておくことも大事です。

# テスト計画・設計
### テスト計画書をつくりましょう
自動テストにおいてもどのようなテストにするかをテスト計画に落とすのは大事です。
テストアプローチが明確になります。

### テスト自動化に関するコストの算出
構築にどのくらいかかって、運用にどのくらいのコストがかかる見込みなのかを構築前に出してあげると納得感をもって進むことができます。
詳しい話はこちらをご覧ください。
[自動テストの効果測定に使われるEMTEとは？ - LIFULL Creators Blog](https://www.lifull.blog/entry/2020/10/19/110000)

### テスト対象の優先度を決めましょう
私達の支援は自動システムテストが多いです。
その場合テスト対象を絞って導入する必要があります。
どのような基準で絞っていくかを支援対象チームと決めていく必要があります。
例えば「壊れたらビジネスにクリティカルな被害が出る機能を優先する」や「過去に障害が起きた機能を優先する」などがあります。

# テスト実装
### 自動テストに関する学習を手伝いましょう
長期的な価値を生み出す支援は最終的には支援対象チームが自走している状態にならなければなりません。
自動テストの基礎知識から、テストコードの実装方法、テスト結果の確認手順などを教えていきます。
ハンズオン形式で手を動かすようにすると自動化楽しいという気持ちを植え付けることができて、その後実装が進めやすくなります。

### テストコード実装をモブ・ペアプロで行いましょう
一つ前の学習に関連する項目です。
実装しておいてくださいといったところでなかなか前に進めないことが多かったです。特にテストコードの実装については走り始めはSETがブースターとなって学習を促す必要があります。
基本的には開発チームメンバーがドライバーとなる形が良いでしょう。

### テスト対象システムのデプロイまでのフローを確認しておきましょう
自動テストは可能な限り自動で実行開始するべきだと思います。
そのためには開発スタートしてからどのようなフローでテスト対象環境までデプロイされるかを把握する必要があります。
知ることで適切な提案が可能になります。

### テストデータの整備を可能な限り自動化しましょう
テストコードの実装に注力するとテストデータを整備することを忘れがちです。
自動でデータを更新するための仕組みを検討することをおすすめします。

# 運用開始
### 少ないテストケース数の段階で運用を始めましょう
達成感によりテスト自動化のモチベーションを高めます。
また、早めの運用で運用フローの検討不足なども早期発見できます。
また繰り返し実行した分だけ価値が生まれるので早期に運用開始するべきです。
短い期間で運用に載せてスクラムのように改善・テスト追加を繰り返していくのが良いと思います。

# 支援終盤
### 自走できる状態を定義してそこまで引っ張りましょう
運用がSETの支援なしに回っている状態やテストコードのメンテナンスやテストケースの新規追加が支援対象チームだけでできている状態など自走できる状態を定義し、できていない箇所の学習や経験ができるように手伝いましょう。
はじめのほうでモブプロをした人から別のメンバーに指導してもらうのもいい手です。

# 終わりに
心得を簡単にですがまとめてみました。
まとめてみてこの心得はSETによる支援だけでなく開発チームが自発的にテスト自動化に取り組む際にも役立つことがあると思いました。

うまくまとめられず記載できていないものもまだまだありますが、それはまたの機会にでも共有できればと思います。
jupyterLab で tqdm を用いたプログレスバーの表示が上手くできなかったのでその備忘録

#はじめに
へ～プログレスバーの表示がtqdmってライブラリで簡単にできるのか～！
表示できんやんけ！となったので解決した方法をまとめておきます．

#実装環境
* Windows10
* Anaconda3
* Python3
* juyterLab2.2.6

#tqdmのinstallと実装
```
pip install tqdm
```
Anacondaの人は以下で，私は最初から入ってたのでinstall不要でした

```
conda install tqdm
```
###さっそく実装
```python3:tqdm.py
import pandas as pd
import numpy as np
import tqdm
import time

for i in tqdm(range(10)):
  time.sleep(1)
```
しかし出力は以下のHBoxなんとかかんとかというテキスト

```
HBox(children=(IntProgress(value=0, max=10), HTML(value='')))
```

そういえばJupyter notebookではnotebook用のメソッドを使う必要があったっけ？と思い以下に変更．


```python3:tqdm.py
import pandas as pd
import numpy as np
from tqdm.notebook import tqdm
import time

for i in tqdm(range(10)):
  time.sleep(1)
```

しかし結果変わらずテキストを出力．
これは困ったので解決策を検索

#解決策
どうやら以下の三つを実行しないと初期状態のnotebookでは表示されない様子．

* ipywidgetsのインストール
* nodejsのインストール
* JupyterLab Extensionのインストール

それぞれ順番にAnacondaプロンプトで実行する

```
conda install -c conda-forge ipywidgets
```

```
conda install -c conda-forge nodejs
```

```
jupyter labextension install @jupyter-widgets/jupyterlab-manager
```

しかし，上2つはうまくいったもののJupyter Extensionのインストールが出来ずつまづく．
どうやらJupyterLabのバージョンによってインストールのバージョンを指定する必要があるらしい．
私の使っているJupyterLabは2.2.6だったので

```
jupyter labextension install @jupyter-widgets/jupyterlab-manager@2
```
と実行してやっとインストールできた！
labの各バージョンにどのバージョンが対応しているのかどこを調べればいいのかわからず…
先駆者の方の記事を参考にさせて頂きました．
[jupyter lab で tqdmつかうと改行されてわーとなるときは拡張機能オン](https://blog.amedama.jp/entry/2019/01/29/235642)

#改めて実行
```python3:tqdm.py
import pandas as pd
import numpy as np
from tqdm.notebook import tqdm
import time

for i in tqdm(range(10)):
  time.sleep(1)
```
うまいこと動いた！！！！！！！
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655678/4e525e11-8ad5-530b-def6-bab9593f7e9b.png)

#おわりに
ということでtqdmを使ってプログレスバーの表示ができました．
何に使うか全然決まってないけどとりあえずできてよかったです．

#参考記事
[Pythonで進捗表示したい！]
(https://qiita.com/kuroitu/items/f18acf87269f4267e8c1)
[jupyter lab で tqdmつかうと改行されてわーとなるときは拡張機能オン](https://blog.amedama.jp/entry/2019/01/29/235642)
[JupyterLabでtqdmを使えるようにするためにcondaでnodejsとipywidgetsをインストールする]
(https://marumalog.hatenablog.jp/entry/2019/07/11/021409)
ChromeDevToolsでコントラスト比をチェックする

## 概要

- 先日[Webページのコントラスト比をチェックしてみよう](https://qiita.com/ozaki25/items/da08c332f487ef421760)という記事を書いてコントラスト比をチェックするChrome拡張を紹介しました
- ですが、その後情報収集しているとChromeのDevToolsだけでもいろいろできることが分かったので紹介します

## 1.個別要素のコントラスト比をチェックする

- DevToolsのElementsタブを開いて矢印ボタンを押します（画像内の①）
- その状態でページにカーソルを持っていくとかざした要素のコントラスト比などの情報を見ることができます（画像内の②）

![スクリーンショット 2020-12-10 13.30.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/e380992e-67b9-1d9f-b3c4-dfe40165cdd1.png)

## 2.個別要素のコントラスト比を修正する

- 1では確認だけでしたがさらに修正もできます
- Elementsタブに出てくるStylesタブで対象の要素のcolorを選択します

![スクリーンショット 2020-12-17 17.45.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/05a20096-2ddb-bf6f-c986-86331b72efbc.png)

- コントラスト比に問題がある場合は現在のコントラスト比とAA,AAAの基準を満たすための代替案が提案されます

![スクリーンショット 2020-12-17 18.19.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/389d947c-106f-a9cb-17ee-3d4536011043.png)

- 提案を受け入れると画面上にも反映されて見た目を確認することができます

![スクリーンショット 2020-12-17 18.26.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/d21a56f5-956f-2825-bfb1-79e9d332240a.png)

## 3.ページ全体のコントラスト比をチェックする

- 1と2は事前にあたりをつけてチェックするものでしたが、ページ全体をチェックして問題のある箇所を表示する方法もあります
- DevToolsのCSS Overviewタブを開きます
    - Capture overviewボタンを押すとページを解析し結果が表示されます

![スクリーンショット 2020-12-17 17.48.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/d86bf79e-fcd0-3217-da92-83a68f7cbde4.png)

- ページ内でどのような色が使われているかなどサマリが表示されます
- その中のContrast issuesにコントラスト比に問題のある箇所が表示されます

![スクリーンショット 2020-12-17 17.48.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/24cd6c25-e3b9-ebea-447d-100d68c74282.png)

- これをクリックするとElementsタブの対象の要素に飛ぶことができるため2で紹介したの手順を行って色の調整をしていくことができます

![スクリーンショット 2020-12-17 17.50.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/6ae467d3-fc84-7326-e186-a216f210e408.png)


## まとめ

- ChromeのDevToolsは本当に高機能ですね
- 便利なツールを使いこなして効率的によりよいWebを作っていきましょう！
Keycloakにフィルタを登録してホゲホゲする

# 読んで嬉しいかもしれない人
Keycloakへのリクエストをフィルタで捕まえてホゲホゲしたい人向けです

# 概要
KeycloakにContainerRequestFilterを登録する方法を書いています
KeycloakのJAX-RS全リソースに対して、アクセスされる前に処理を入れることが可能になります

# この記事を利用して出来そうなこと
ユーザを大量に作成するIPアドレスからのリクエストを全拒否する、とか

# 実装方法
1. ホゲホゲしたい処理を行う`ContainerRequestFilter`クラスを実装したFilterクラスを作成します
2. フィルタを登録するための`AuthenticatorFactory `クラスを実装したFactoryクラスを作成します

# コード

```java:Filterクラス
@Provider
public class Filter implements ContainerRequestFilter {
    
    @Override
    public void filter(ContainerRequestContext context) throws IOException {
        // やりたい処理
    }
}
```


```java:Factoryクラス
public class FilterFactory implements AuthenticatorFactory {
 
    @Override
    public String getDisplayType() {
        return null;
    }
 
    @Override
    public String getReferenceCategory() {
        return null;
    }
 
    @Override
    public boolean isConfigurable() {
        return false;
    }
 
    @Override
    public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
        return new AuthenticationExecutionModel.Requirement[0];
    }
 
    @Override
    public boolean isUserSetupAllowed() {
        return false;
    }
 
    @Override
    public String getHelpText() {
        return null;
    }
 
    @Override
    public List<ProviderConfigProperty> getConfigProperties() {
        return null;
    }
 
    @Override
    public Authenticator create(KeycloakSession session) {
        return null;
    }
 
    @Override
    public void init(Config.Scope config) {
    }
    
    // 起動時のイベント(PostMigrationEvent)をリッスンしてApplicationクラスにフィルタを追加
    @Override
    public void postInit(KeycloakSessionFactory factory) {
        factory.register(new ProviderEventListener() {
            public void onEvent(ProviderEvent pe) {
                if (pe instanceof PostMigrationEvent) {
                    KeycloakApplication ka = ResteasyProviderFactory.getContextData(KeycloakApplication.class);
                    ka.getClasses().add(Filter.class);
                }
            }
        });
    }
 
    @Override
    public void close() {
 
    }
 
    @Override
    public String getId() {
        return "dummy";
    }
}
```
#登録方法
1. META-INF配下に作成したFactoryクラス名を記載した定義ファイルを作成してください
2. ビルドしてデプロイしてKeycloakを再起動してください

# 終わりに
JAX-RSのリソース名なり、リクエストPathなりで絞って、各リソースへのアクセス前に処理を入れることが出来たりします
リスクベース認証用のAuthenticatorを作って、リスク情報でアクセス制御とかも出来そうですな

Keycloakでリスクベース認証をやってみた記事はこちら
https://qiita.com/naokiiiii/items/c5bc7ed2204507f4ad6a#15-%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4

～～後日、サンプル実装公開予定～～
VagrantでDockerや他のOSを頻繁に使った際のエラー　Stderr: VBoxManage.exe: error: Failed 

環境 Windows10　Pro 64bit
Oracle VM VirtualBox6.1

VagrantでDockerを構築したり、他のOSを構築するとネットワークに障害が起きる。
過去にもあったのでメモとして残す。


````
There was an error while executing `VBoxManage`, a CLI used by Vagrant
for controlling VirtualBox. The command and stderr is shown below.

Command: ["startvm", "aae238ff-e315-4213-9a5b-b94825bc0997", "--type", "headless"]

Stderr: VBoxManage.exe: error: Failed to open/create the internal network 'HostInterfaceNetworking-VirtualBox Host-Only Ethernet Adapter #2' (VERR_INTNET_FLT_IF_NOT_FOUND).
VBoxManage.exe: error: Failed to attach the network LUN (VERR_INTNET_FLT_IF_NOT_FOUND)
VBoxManage.exe: error: Details: code E_FAIL (0x80004005), component ConsoleWrap, interface IConsole

````
VagrantでUbuntu　の上にDockerを動かしているので、
Vagrantで別にCentOSを動かそうと思ったら上記のエラーが・・・。
[陽はまたのぼりくりかえす](https://process9.hatenablog.com/entry/2018/06/18/002647)を参考に

コントロールパネル > ネットワークとインターネット > ネットワークと共有センター > アダプターの設定を確認。
ネットワーク接続を確認。
 VirtualBoxのアダプターを有効と無効を繰り返しながら、
vagrant reloadを実行
正常に立ち上がった。
空間統計学(統計ライブラリ)　自然科学から人文・社会科学まで

```{r}

#空間統計学(統計ライブラリ)　自然科学から人文・社会科学まで　p.112

#空間ダービンモデル(Durbin):SDM

library(dplyr)

#各都道府県の距離データ(https://www.gsi.go.jp/KOKUJYOHO/kenchokan.html)
d=read.csv("C:/Users/kozakai ryouta/Documents/都道府県の距離データ.csv")

name=as.character(d[,1]);d=d[,-1]

d=as.matrix(d)

rownames(d)=name

d[d=="" | is.na(d)>0]=0

d=matrix(as.numeric(d),ncol=ncol(d))

rownames(d)=c(name);colnames(d)=c(name)

d=d+t(d);d=d/10

d=d[-nrow(d),-ncol(d)]

W=1/d;diag(W)=0

#y:交通事故死傷者数、x1:人口密度、x2:道路投資額、x3:道路改良率、x4:トラック・バス・乗用車登録台数

data=data.frame(prefecture=c("Hokkaido","Aomori","Iwate","Miyagi","Akita","Yamagata","Fukushima","Ibaragi","Totigi","Gumma","Saitama","Tiba","Tokyo","Kanagawa","Niigata","Toyama","Ishikawa","Fukui","Yamanashi","Nagano","Gifu","Shizuoka","Aichi","Mie","Shiga","Kyoto","Oosaka","Hyogo","Nara","Wakayama","Tottori","Shimane","Okayama","Hiroshima","Yamaguchi","Tokushima","Kagawa","Ehime","Kouchi","Hukuoka","Saga","Nagasaki","Kumamoto","Ooita","Miyazaki","Kagoshima"),x1=c(6364,7135,7266,7186,6274,6497,6740,6687,6917,6725,7928,7403,13500,8537,7315,6730,8875,7589,7249,6319,7673,7270,8149,6385,7049,10861,11548,9986,6728,7596,7324,6166,5889,8170,5147,6997,6460,6657,7979,7301,6564,8866,6928,6983,6016,7688),x2=c(90547,12634,20101,15486,12471,12446,27026,19486,19919,16611,42768,37630,147481,55648,27569,11709,13660,11161,10092,22957,20135,36377,48255,19562,9889,16925,146758,75350,16405,13007,8005,10334,22146,23029,15488,9905,7407,14795,12387,31172,8151,11117,14634,11504,11415,12546),x3=c(19.7,20,16.3,20.6,18.1,21.2,14.2,9.6,28.8,16.3,15.5,28.4,49.1,31.8,14.6,35.3,30.8,32.9,24.2,11.4,18.3,19.6,21.4,14.6,21.4,23.6,40.9,24.8,10.7,16.8,26.6,10.2,11,16.3,23.3,10.8,21.9,16.2,11.8,17.7,24.7,17.5,18.5,20.9,25.2,32.5),x4=c(640.9,128.2,113.8,171.7,97.4,134.4,166.5,225.1,187.5,212,337.3,319.4,1584.3,559.2,234.3,121.4,120,93.5,93.2,238.1,255.1,419.1,825.1,160.5,91.8,233.6,807.5,404.6,85.8,111,44.1,52.9,156.6,256.1,126.8,71.4,81.5,108.1,72.7,367,70.6,89.6,136.6,97.5,96.3,119.4),y=c(44523,10395,8669,12808,7640,7094,17556,20320,18715,16755,34601,27811,88406,48030,18213,8839,12086,8871,8961,15280,17837,37421,50998,14809,12610,35478,75497,55464,7916,14259,6244,5400,19015,36771,13827,9372,11088,9960,8516,51175,10384,10652,15987,10216,8460,12932))

Y=data$y;X=as.matrix(cbind(rep(1,nrow(data)),data[,colnames(data) %in% c("x1","x2","x3","x4")]))

X_star=cbind(X,W%*%X)

n=nrow(data)

beta0=solve(t(X_star)%*%X_star)%*%t(X_star)%*%Y

betad=solve(t(X_star)%*%X_star)%*%t(X_star)%*%(W%*%Y)

epsilon0=Y-X_star%*%beta0

epsilond=W%*%Y-X_star%*%betad

loglik=function(p){
  
return(-n*log(sum((epsilon0-epsilond*p)^2)/n)/2+log(det(diag(rep(1,nrow(W)))-p*W)))  
  
}

P=0.3

ite=1000

eta=0.001

h=0.01

for(l in 1:ite){
  
P=P+eta*(loglik(P+h)-loglik(P))/h  
  
print(loglik(P))

}

beta=beta0-P*betad

sigma=sum((epsilon0-epsilond*P)^2)/n

pre=P*W%*%Y+X_star%*%beta

plot(c(1:length(Y)),Y,xlab="index",ylab="predict",xlim=c(1,length(Y)),ylim=c(min(c(Y,pre)),max(c(Y,pre))),col=2,type="o")

par(new=T)

plot(c(1:length(Y)),pre,xlab="index",ylab="predict",xlim=c(1,length(Y)),ylim=c(min(c(Y,pre)),max(c(Y,pre))),col=3,type="o")


```
tensorflow_datasetsのインストール方法。

Anacondaのtensorflow_datasets古いので使えるデータセットの種類がすくない。

なのでpipでインストールするべき。

tensorflowのバージョンが < 2.1のときは

```
pip install tensorflow-datasets==3.2.1 
```

が最新。

tensorflow >= 2.1のときはバージョン4以降が使える。
海外配信のモバイルゲームQAの言語検証で気をつけたい観点

#はじめに
私は今年から海外配信のモバイルゲームQA業務にも携わることになり、色々な国の言語検証に触れる機会が増えました。
今回は実務経験から言語検証の際に気をつけたい観点を紹介していきたいと思います。

#日付や時刻
国毎に表記方法や時差の関係上、以下のように日付や時刻の記載内容が変わってくる場合があります。

##YYYY/MM/DD表記の違い
国毎で日付の表記方法には違いがあります。
プロジェクト毎でも各々表記方法のルールが違っていたりするので確認の際には注意が必要です。
「2020年7月9日」を例に国毎の違いを以下に纏めています。

|地域|表記順|例|
|:--:|:--:|:--:|:--:|
|日本、中国、韓国など|YYYY/MM/DD|2020/07/09|
|アメリカなど|MM/DD/YYYY|07/09/2020|
|イギリス、ヨーロッパ地域など|DD/MM/YYYY|09/07/2020|

国毎のルールに則っていないと月や日付の記載が逆になったりとリスクが生じます。
※アメリカの記載をイギリスの記載と誤ると「2020年7月9日」が「2020年9月7日」になってしまう。

##現地時間での記載
国毎のタイムゾーンに合わせて時間の記載は変わることがあります。
「2020年7月9日(木) 15:00:00」を例に国毎の違いを以下に纏めました。

|タイムゾーン|日本との時差|例|備考|
|:--:|:--:|:--:|:--|
|(JST)表記にする場合|0時間|2020年7月9日(木) 15:00:00|JSTとは日本標準時のこと|
|(UTC)表記にする場合|-9時間|2020年7月9日(木) 06:00:00|UTCとは協定世界時のことで世界各地の標準時|
|(PST)表記にする場合|-17時間|2020年7月8日(水) 22:00:00|PSTとは太平洋標準時のことで主にアメリカ西海岸地域の標準時|

日本時間との時差の整合性が取れていないとリスクが生じてしまいます。
施策リリース日時や有効期限などの記載に誤りがないかは、各国毎に入念なチェックが必要になってきます。

実際の日付や時刻の記載以外にも注意しないといけないポイントもあります。
例えば「"明日"○○:○○リリース」という表現の記載は時差の関係上、他言語でそのまま翻訳してしまうと「明日」でなくなってしまう場合などもあるので注意が必要です。

実務で取り扱ったことはないのですが、日本ではあまり馴染みがない北米やヨーロッパの国々で導入しているサマータイム制度についても気をつける観点として持っておいてもよさそうですね。


#訴求内容
説明文言については、誤った訴求がされると甚大なリスクを生じる可能性があります。
その中の確認時に気をつけている観点を大まかに表で纏めてみました。

##キャラクターの記載
キャラクターは以下のような観点をしっかり抑えておくと不具合検知率も上がるかと思います。
中でも特殊効果は内容が細かく記載されていることが多く、色々な解釈ができてしまう場合があるので観点は幅広く持っておいた方が良いです。

|大項目|中項目|備考|
|:--:|:--:|:--|
|名称|-||
|ステータス|-||
|性別|-|人称代名詞のhe/sheなど|
|特殊効果|数値||
|〃|上昇/下降|+、-、×、÷、%、割合など|
|〃|大きさ(威力など)|小、中、大、特大、超特大など|
|〃|タイプ|属性や種類など|


##ガチャ説明の記載
ガチャの説明は以下のような観点をしっかりと抑えて確認できると良いと思います。

|大項目|中項目|備考|
|:--:|:--:|:--|
|ガチャ名称|-||
|ガチャ回数|-||
|確率/提供割合|-||
|金額|-|各国毎に通貨の単位やカンマの区切りなど違うので注意|
|訴求力のあるワード|確定/保証など||
|〃|～以上、～以下など||
|〃|1日○回など||

訴求力のあるワードについては各プロジェクト毎に違いや特色があると思うので、
事前に翻訳時にどういった単語に置き換わるのかはピックアップしておくことが大切です。

#UI表示
##表示崩れ
日本語から海外言語に翻訳される際に、文字数が著しく増える場合が多々あります。
そういった場合UI崩れが起きやすいので注意が必要です。

文字数が多くUI崩れが発生する場合、他言語では単語が省略されて記載されることがあります。
この際は省略された単語に問題がないかもしっかりと確認する必要性が出てきます。

余談ですが、UI調整時に文字の仮入れを行う際は、一番文字幅が広いとされている「W」が用いられるようです。

|字幅比較(1文字)|字幅比較(10文字)|
|:--:|:--:|:--:|
|W|WWWWWWWWWW|
|A|AAAAAAAAAA|
|M|MMMMMMMMMM|

##文字色
UIは文字色が日本語と相違ないかも確認しています。
言語が変わると色の付く単語範囲が文法などの違いにより変わる場合があり、
訴求を強調したい箇所が変わっていないかなど注意深く見る必要が出てきます。

#さいごに
海外版アプリQA時の言語検証で気をつけたい観点の紹介は以上となります。
観点は他にもたくさんあると思いますが、少しでも参考になれば幸いです。
コマンドラインでpdfをTextに。Pythonの知識も不要。pdfminer付属のpdf2txt.py と調整用パラメーターについて。 

この記事は セゾン情報システムズ [Advent Calendar 2020](https://qiita.com/advent-calendar/2020/sisco) 18日目の記事です。

## 先にコマンドの解説をします。
- 色々調べてここにたどり着いた方のために、pdf2txt.py のパラメーターについて先に記載します。
- こちらに詳しく出ていました。 https://www.unixuser.org/~euske/python/pdfminer/

```shell-session
python.exe pdf2txt.py [options] -o [OutFilename] [InFilename] 
```

例：

```shell-session
c:\python38\python.exe c:\python38\Scripts\pdf2txt.py -M 3.0 -o c:\work\OutFile.txt c:\work\InFile.pdf
```

###解説
####主に読み込み調整が必要なパラメータ。
（どこかで、標準のままだと変換結果がイマイチなことが多いという記載を見ました。）

- 調整は[options] に設定します。文字間隔(M)　単語の間隔(W)　行間隔(L)　縦読み(V)
- パラメータ無指定の場合はデフォルト値が採用されます。 M = 1.0, W = 0.2, L = 0.3 。横読みです。
- 縦読みをしたい場合は、 -V を指定します。

#### リンクしたURLのGoogle和訳を貼っておきます。

これらは、レイアウト分析に使用されるパラメーターです。実際のPDFファイルでは、オーサリングソフトウェアによっては、テキスト部分が実行中にいくつかのチャンクに分割される場合があります。したがって、テキスト抽出ではテキストチャンクをスプライスする必要があります。次の図では、距離がchar_margin（Mとして表示）よりも近い2つのテキストチャンクが連続していると見なされ、1つにグループ化されます。また、line_margin（L）よりも距離が近い2本の線は、テキストボックスとしてグループ化されます。これは、テキスト部分の「クラスター」を含む長方形の領域です。さらに、2つの単語間の距離がword_margin（W）より大きい場合、単語間の空白はスペースとして表されない可能性があるため、必要に応じて空白文字（スペース）を挿入する必要がありますが、それぞれの位置によって示されます。語。
各値は、実際の長さとしてではなく、問題の各文字のサイズに対する長さの比率として指定されます。デフォルト値は、それぞれM = 1.0、L = 0.3、およびW = 0.2です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123399/62399eb3-a950-2729-65ed-b84f7bf2a313.png)

その他、画像の書き出しなどのパラメーターがありますが、本稿では割愛いたします。詳細は以下を参照いただけると幸いです。
https://www.unixuser.org/~euske/python/pdfminer/
- - -

## では改めて概要です。
- Pythonライブラリの１つpdfminerですが、pdf2txt というそれを呼べば動作するモジュールがあります。
- pdf2txtを使い、pdf→textに変換できますが、期待通りの動作をしてくれない場合があります。
- そんなときにもpdfminerは調整用のパラメーターを持っているので調整次第で読み込みができるようになります。
- pdfminerでの記載は他にもありましたが、便利な pdf2txt.pyで実施する場合について、調べたところ日本語記載の資料がなかったので記載します。
- コマンド実行できるので、DataSpiderなどのETLツールやジョブコントローラーからも実施できて便利です。

※Pythonの知識は不要ですがPythonの実行環境は必要です。
※画像化されているpdfからテキストは抽出できません。テキストが抜けるかどうかの判断は、Pdfファイル内を文字検索し、検索できるようでしたらテキストが抜けます。

- - -

## Pythonの実行モジュールとして使いたい場合の手順について
Pythonの開発環境は不要です。実行環境は必要です。(リンクで済ませようと思ったのですが意外とない T_T)

- Python 実行環境のインストール（windows）　　
https://www.python.org/downloads/
から
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123399/1e11cd0a-e443-8185-76fe-5f306324a188.png)
windowsを選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123399/c10488be-cc91-0ef5-07bc-28def50adedd.png)
最終を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123399/d250c573-125f-c439-98ed-a5f853616453.png)
インストーラー付きのパッケージを選択してダウンロードしてインストール。
インストール先は人それぞれですが、個人的にはドライブ直下のpythonxxx(バージョン。3.9.1 なら391)が好きです。

- pdfminner.six を pip でインストール
コマンドプロンプトで

```shell-session
pip install pdfminer.six
```

pythonフォルダのScripts配下に、pdf2txt.py ファイルが有れば動くはず。です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123399/0cef97b9-be67-cb99-97fd-a40f547b4977.png)

ところで、記事を書いていて気づいたのですが、とっても便利なpdfminerですが作者は日本の方のようです。Yusuke Shinyama さん。ありがとうございます。

以上　

記事に不具合。不都合などございましたらご連絡いただけると幸いです。記事内容は会社公式のものではなく、個人として記載するものです。
Ruby の #{ } は変数展開じゃない

以下のコードを見てください。

```rb
name = "Ruby"
puts "Hello, #{ name }!"
```

実行すると

```
Hello, Ruby!
```

が表示されます。
2 行目の文字列リテラルの中に， `#{ name }` という部分があります。
これのことを「変数展開」と書いている記事が非常に多いのですが，PHP や Perl などのそれとは異なり，Ruby の場合は**中に式が書ける**，ということが本質的に重要です[^pp]。
それゆえ，[式展開](https://docs.ruby-lang.org/ja/2.7.0/doc/spec=2fliteral.html#exp) と呼ばれています。

[^pp]: 最新版の PHP でどうなのかは知らない。また，PHP でも変数展開のところに式を書く手段がある。参考：[PHPで文字列リテラルに式展開 - Qiita](https://qiita.com/tadsan/items/e4796449c736cfb5c9bd)

以下のようなことができます。

```rb
scores = {
  Foo: 3,
  Bar: 8,
  Baz: 5,
}

puts "Total score of #{ scores.keys.join(", ") } is #{ scores.values.sum }."
# => Total score of Foo, Bar, Baz is 16.
```

英語としておかしいじゃんよ[^fbb]，というツッコミは無しでお願いします。
また，こんなふうに複雑な式を入れるのがよいかどうかはまた別問題として。

[^fbb]: 「Foo, Bar, and Baz」もしくは「Foo, Bar and Baz」と書くべきでしょう。知らんけど。

この例では，`" "` で記述した文字列リテラルの式展開の中で `" "` を使っていますが，とくに問題なく意図どおりに解釈される，ということが見て取れます。

それにしても「式**展開**」って用語は若干引っかかるものがあります。展開って？
「式埋め込み」とか「式挿入」とかじゃダメだったのかな。
競技プログラミングの本まとめ

#競技プログラミングの本まとめ
[1.はじめに](#1-はじめに)
[2.本の紹介](#2-本の紹介)
[3.Python勢はこちら](#3-Pythonの本)
##はじめに
競技プログラミングを始めて三週間が経ったが、なかなか強くなれないので本を買おうと思った。
本といっても競プロの本はいろいろありすぎてどれがいいかよくわからなかったので、この記事を書くことにした。
##本の紹介
###プログラミングコンテストチャレンジブック [第2版]　～問題解決のアルゴリズム活用力とコーディングテクニックを鍛える～
>https://www.amazon.co.jp/gp/product/4839941068/ref=as_li_ss_il?ie=UTF8&camp=247&creative=7399&creativeASIN=4839941068&linkCode=as2&tag=yuki200600-22

定番の競プロ本。C++でサンプルコードが書かれていて、内容も難しめ。これ一冊でほとんど事足りるので、グラフがある程度わかっている人などにおすすめ。
通称蟻本。
###最強最速アルゴリズマー養成講座 プログラミングコンテストTopCoder攻略ガイド
>https://www.amazon.co.jp/gp/product/4797367172/ref=as_li_ss_il?ie=UTF8&camp=247&creative=7399&creativeASIN=4797367172&linkCode=as2&tag=yuki200600-22

AtCoderの社長であるchokudai氏の著書。難易度は中くらいで、とても丁寧に書かれている。グラフとかわからん><って人におすすめ。
通称チーター本。
###プログラミングコンテスト攻略のためのアルゴリズムとデータ構造
>https://www.amazon.co.jp/gp/product/4839952957/ref=as_li_ss_ilie=UTF8&camp=247&creative=7399&creativeASIN=4839952957&linkCode=as2&tag=yuki200600-22

満遍なくすべてを網羅してくれる本。
解答例はC++で書かれている。
通称螺旋本。
##Python勢へ
###アルゴリズム実技検定　公式テキスト［エントリー～中級編］
>https://www.amazon.co.jp/dp/B08QRNJ7M3

2021年2月から販売されるpythonのプログラミング本。python勢で初心者の人におすすめ。chokudaiさんにマシュマロを投げて「中学生で始めたばかり、python勢におすすめの本はなんですか？」と聞いたら、この本をおすすめされた。

#まとめ
レビューなども参考にしながら、自分に合った本を選ぼう。自分は一番下のアルゴリズム実技検定　公式テキストと蟻本を買うことにした。
docker-composeのPORT番号について

# はじめに
docker-composeでポート番号を指定する項目について、意味がいまいち分かっていなかったので自分用にメモ。
ポート番号の項目を色々試してみて、挙動を確認してみる。

# `3000:3000`の場合
React用のdocker-composeを用意。
ポート番号のところは`3000:3000`にしてみる。

```yml:docker-compose.yml

version: '3'

services:
  front-end:
    build: ./docker/react
    container_name: react
    tty: true
    volumes:
      - ./:/usr/src/app
    ports:
      - 3000:3000
```

コンテナに入って`yarn start`してみると、ターミナルに以下の表示が。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241394/828e0a8e-87eb-29b1-5414-0a03072de4c3.png)
どうやら`http:localhost:3000`が開かれている様子。

ホスト側で`http:localhost:3000`に入ってみると、ちゃんと初期画面が表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241394/603bb53a-41b9-ff55-c66d-5a404799d509.png)

これが、ポート番号を特にいじらなかった場合。

# `3000:4200`の場合
次に、ポート番号を`3000:4200`としてみる。
`<Host Port>:<Container Port>`なので、ホスト側のポート番号が3000で、コンテナ側が4200になっている。

コンテナ側はポート番号を4200にしたので、`.env`ファイルを以下のように書き換える。

```:.env
PORT=4200
```

コンテナに入って`yarn start`してみると、以下のような表示が得られる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241394/723eff68-541d-bdf1-6a53-29ea1331bd5d.png)
しかし、これの通り`http:localhost:4200`を入力しても、アクセスできない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241394/103fab81-c8f7-2bf1-ac74-6fba5ac7bd1e.png)
ホスト側はポート番号を3000としているので、`http:localhost:3000`にアクセスする必要がある。
`http:localhost:3000`を入力すると、ちゃんと初期画面が表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241394/603bb53a-41b9-ff55-c66d-5a404799d509.png)
ローカル、リモートブランチの削除

<h1>不要になったブランチの削除方法</h1>
<p>　複数人での開発では、developブランチに自身のブランチを切り、自身の作業ブランチをローカルに切ることが一般的かと思います。作業量に比例しブランチも増えるので、小まめに整理することで他のメンバーの作業環境を整えることにつながるので、重要な作業といえます。</p>
<h2>ブランチの確認</h2>
<h4>ローカルブランチの確認</h4>

<p>　下記コマンド以外にもありますが、私は普段確認、削除にそれぞれ2つしか使いません。</p>


```
git branch
```

<h4>リモートブランチの確認</h4>

```
git branch -a
```



<h2>ブランチの削除</h2>

<h4>ローカルブランチの削除</h4>

```
git branch --delete "ブランチ名"
```

<h4>リモートブランチの削除</h4>

```
git push --delete origin "ブランチ名"
```


<h2>え、さっき消したやんってなったとき</h2>
<p>消したはずのブランチが表示され、消そうとしても下記のエラーが出る</p>

```
error: unable to delete '消したはずのブランチ名': remote ref does not exist
```

<p>そんな時に使うのが</p>

```
git prune origin
```

<p>削除したはずなのに手元に残ってしまっているブランチを整理してくれます☆</p>


<h2>おわりに</h2>
<p>この上なくシンプルな記事ですが、特に書くことないので終わりです。
<br>
あ、作業ブランチ消さないように気を付けてくださいね</p><br><br><br>
プログラミング技術は変化しても、稟議のあり方は変わらないです

#要約

今回のプロジェクトで活用した新技術：IBM　Visual Recognition　
使っている画像：NASA夜間光 @Nasa NASA Earth Observing System Data and Information System (EOSDIS)
AIにより、いままで感覚で判定したものが、定量的に数字で判断できるようになりました。しかし、稟議のありかたは変わらず,です。(書いている間に、稟議を通すためのTIPSになってしまいました)

#はじめに

AI/機械学習を活用することで、今まで感覚で行っていたものが定量的に数字で出せるようになりました。
それと、昔ながらの会社の決定プロセスである稟議は別。こればかりはどんなにプログラミング技術の変化しても変わらない、ということです。
(NDA期間が終わってないので、データそのものは別に個人的に算出したものを使ってます)
プログラミング技術の変化の中で、自分はもちろん他の開発者さんが同じ壁にぶつからないよう、また、ぶつかってもすぐに乗り越えられるよう、その壁の乗り越え方をまとめていきたいと思います。


**<<基本>>**
「新規案件を提案してほしいんだよね」
→提案する
「他の会社で成功した例は」
→他で実施していたら新規ではない

新規案件を提案して稟議を通すためには、これを超えなくてはいけません。


#その１．稟議にかかると、とにかくとにかく別の方向に行く

**解決策：定量的に数字で出せる事を示すことで回避。**

今回のプロジェクトの目的はAIの活用と定義しているのに、アプリリリースという話が横から出てきて、そのためAIの活用ではなくアプリのリリースが目的化します。（手段の目的化）
そのためまず最初に、アプリを開発してもなかなか認知してもらえない、ダウンロードしてもらえないことを提示しておきます。（政府が国家のメンツをかけて半年推進しても、国民の２０％いかない）

![アプリ１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387051/933abe56-cbd3-5b7e-80f5-40e7735ff28e.png)




https://www.mhlw.go.jp/stf/seisakunitsuite/bunya/cocoa_00138.html



#その２. 稟議にかかると、とにかくとにかく時間がかかる

**解決策：とにかくとにかくその場で実装して、議決にまで持っていく**

新規開発は、AIだろうが何だろうが圧倒的に時間がかかります。

**「他で成功した例は」**

会議中にこの流れが出れば、１００％その案件は流れます。
その際は、その場で実装して新技術でできることを示しましょう。できればその場で実装、実演しましょう。
（主要機能は、すぐできるように準備しておく）

中国本国の夜間光画像をtweetするだけで、日次GDPを算出する。
![アプリ２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387051/2acfa671-26fe-9797-c4da-07135fe94ca8.png)





経済活動が変動すると夜間光量が変動することを利用して算出しています。
![アプリ２1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387051/90d88cb6-5c8f-c1b6-ea29-2f54963f15b4.png)




会議中に実際に動けば、それだけで喜んでもらえます。まずは、実際にできることを示す。これです。



#その３. 稟議にかかると、とにかくとにかく人間関係で決まる

**解決策：今回のプロジェクトの目的が、一目でわかるもの、にする。**

まずは、１つの課題が実際に、解決可能である、というだけでも魅せる。実際に動けば＝１つの課題が解決すれば、まず喜んでもらえます。
まずは、１つの解決策だけかたちにしてみましょう。すぐに動くことが分かると、かつ実装可能というと、実装しないと、なんでしょうね・・・すぐメンツの問題になってしまうの。
（それ、あんたのメンツだけ）

動くことが分かると、とくに会議中にあれもこれも案が出て、目的がどこかにいってしまいます。
その際は、主要１つだけに絞りましょう。今回のプロジェクトの成果が、AIの活用が一目でわかるもの（表とか表）、にする。
**（中国本国　武漢封鎖時の日次GDPの変動）**
![アプリ３.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387051/82c1639c-de2d-d0d2-ab1a-78d581536c1b.png)


2020/1/23
![20200123.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387051/e137353e-4788-2824-df28-9c43ce50ebd2.jpeg)



2020/2/5
![20200205.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387051/c64b5566-923e-4061-79a6-4ce7068adeb3.jpeg)




#要するに

プログラミング技術の変化で、いままで感覚で判定したものが、定量的に数字で判断できるようになりました。しかし、人間の行うこと、稟議は変わりません。その、誰もが一度はぶつかるであろうプログラミング技術の変化でも稟議の壁ですが、少しでも参考になったら。
少しでも参考になれたなら嬉しいです！
v-for と v-card の組み合わせで Use v-bind or the colon shorthand instead というエラーが起きた

Vue始めました。

まだ何も知らないんですが、今後のメモみたいな感じで残せたらと。
今回はvuetifyも使う環境でやっているのでvueというかvuetifyに関することのほうが多いかも。

## やりたいこと
カードコンポーネントをループさせて、動的にデータを表示させたい。

```vue
<v-col cols=6 v-for="card in cards" v-bind:key="card.title">
  <v-card 
    href="{{card.url}}"
    target="{{card.target}}"
    class="mx-auto"
    max-width="100%"
    outlined a
    hover
  >
    <v-list-item>
      <v-list-item-avatar
        tile
        size="40"
        color="grey"
      ></v-list-item-avatar>
      <v-list-item-content>
        <v-list-item-title class="headline mb-1">
          {{card.title}}
        </v-list-item-title>
        <v-list-item-subtitle>{{card.summary}}</v-list-item-subtitle>
      </v-list-item-content>
    </v-list-item>
  </v-card>
</v-col>
```

## エラー
単なるテキスト表示とかは問題なくできたが、v-cardのPropsにあるhrefやtargetにデータを指定するとエラーが出ました。
書き方が悪いみたいです。

```vue
(Emitted value instead of an instance of Error)

  Errors compiling template:

  href="{{card.url}}": Interpolation inside attributes has been removed. Use v-bind or the colon shorthand instead. For example, instead of <div id="{{ val }}">, use <div :id="val">.

  9  |        <v-col cols=6 v-for="card in cards" v-bind:key="card.title">
  10 |
  11 |          <v-card
     |
  12 |            href="{{card.url}}"
     |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  13 |            target="{{card.target}}"
```

## 修正後
新しいもの勉強するときってググるのも一苦労ですよね。

```vue
<v-col cols=6 v-for="card in cards" v-bind:key="card.title">

  <v-card 
    :href="card.url"
    :target="card.target"
    class="mx-auto"
    max-width="100%"
    outlined 
    hover
  >
    <v-list-item>
      <v-list-item-avatar
        tile
        size="40"
        color="grey"
      ></v-list-item-avatar>
      <v-list-item-content>
        <v-list-item-title class="headline mb-1">
          {{card.title}}
        </v-list-item-title>
        <v-list-item-subtitle>{{card.summary}}</v-list-item-subtitle>
      </v-list-item-content>
    </v-list-item>
  </v-card>
</v-col>
```

## できた

![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170830/903efb97-38c8-f495-1b95-242ee3d38765.png)

## ちなみにscript部分はこんなかんじです。

```vuejs
export default {
  auth: false,
  data () {
    return {
      cards: [
          {
          url: "http://url1.html",
          target: "_blank",
          title: "AAAAAAA",
          summary: "AAAAAAAAAAAAAAAAAAAAA"
          },
          {
          url: "http://url2.html",
          target: "",
          title: "BBBBBBBB",
          summary: "BBBBBBBBBBBBBBBBBBBBBBBB"
          },
          {
          url: "http://url3.html",
          target: "_blank",
          title: "CCCCCCCCCCC",
          summary: "CCCCCCCCCCCCCCCCCCCCCC"
          },
          {
          url: "http://url4.html",
          target: "_blank",
          title: "DDDDDDDDDDDDDDD",
          summary: "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
          } 
        ]
    }
  }
}

```
複合主キーのテーブルをSqoopで並列転送する

# はじめに
この記事は [MicroAd Advent Calendar 2020](https://qiita.com/advent-calendar/2020/microad) 22日目の記事です。　　
業務でApache Sqoopを使って複合主キーのテーブルを転送する際に工夫したことを記事にします。

# 状況設定
やりたかったことは以下の通りです。

- レコード数が多いMySQLのテーブルをCDHに転送する
- レコード数が多いため、レコードを分割して並列に転送しないとメモリエラーで落ちてしまう
- MySQLのテーブルは複合主キー

MySQLの主キーが一つだったら非常に話は簡単です。 `--split-by`オプションに主キーを設定し、並列したい数を `--num-mappers`オプションに設定すれば均等に分割されて転送されます。  
一方で複合主キーだった場合には `--split-by`オプションに複数カラムを設定することができないため、工夫が必要となります。複合主キーとは別のカラムを設定することもできますが、均等に分割されないことが予想されます。うまく転送できないかもしれません。

なお使用しているSqoopのバージョンは1.4.6です。
参考: [Sqoop User Guide (v1.4.6)](https://sqoop.apache.org/docs/1.4.6/SqoopUserGuide.html)

# 解決方法
複合主キーを結合後にmd5で変換し、桁数を減らして10進数に戻したものを`--split-by`オプションに設定しました。
具体的には複合主キーをkey1、key2として以下のように変換された値を使用します。

```sql
CAST(CONV(LEFT(MD5(CONCAT(key1, key2)), 7), 16, 10) AS UNSIGNED)
```

これだけだと分かりにくいので、内側から順に確認します。

## 第一工程

```sql
CONCAT(key1, key2)
```

複合主キーを結合した文字列を作成します。

## 第二工程

```sql
MD5(CONCAT(key1, key2))
```

結合した文字列をmd5でハッシュ化します。
ハッシュ値は概ねランダムで与えられます（少なくとも検証した範囲ではほぼランダムでした）。

## 第三工程

```sql
LEFT(MD5(CONCAT(key1, key2)), 7)
```

ハッシュ値の上から7桁を取得します。
md5で変換された32桁の16進数をそのまま10進数に戻してMySQLで扱った場合、桁数が大きすぎてうまく扱えません。

## 第四工程

```sql
CONV(LEFT(MD5(CONCAT(key1, key2)), 7), 16, 10)
```
16進数を10進数に変換します。

## 第五工程

```sql
CAST(CONV(LEFT(MD5(CONCAT(key1, key2)), 7), 16, 10) AS UNSIGNED)
```

UNSIGNEDのINT型にCASTします。

# 最後に

この方法だと主キーがどの型か、いくつあるか等を気にする必要がありません。パフォーマンスも良好で、レコードが数千万件に上るMySQLのテーブルも上手く分割され、並列に転送されるようになりました。
他にも上手く転送する方法がありましたら、教えていただけると幸いです。
打つコマンドは短ければ短いほど良い。cd,lsを逐一打たずにディレクトリを横断しよう

# 打つコマンドは短ければ短いほど良い。cd,lsを逐一打たずにディレクトリを横断しよう

打つコマンドの短縮形を定義したり、ディレクトリをより素早く移動するにはMacであれば
>.zshrc

をいじれば、作業を効率化できます

## 私の.zshrc

```rb:.zshrc
# 小文字でも大文字ディレクトリ、ファイルを補完できるようにする
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}'

# '^' を押すと上のディレクトリに移動する
function cdup() {
echo
cd ..
zle reset-prompt
}
zle -N cdup
bindkey '\^' cdup

#cdとlsの省略
setopt auto_cd
function chpwd() { ls }

#beep（ぷって言う音）を消す
setopt nolistbeep

#alias類
alias la="ls -a"
alias ga="git add"
alias gc="git commit"
alias gp="git push"
alias rn="rails new"
alias r="rails"
alias rs="rails server"
alias rc="rails console"
alias hrr="heroku run rails"
alias hlt="heroku logs --tail"

#予測変換
autoload -U compinit
compinit
```

特にalias系のところは、作業の短縮最も期待できるところですね！
例えば、``rails db:migrate:status``とか
めっちゃ打つのめんどくさいですよね

そんな時は、

```rb:.zshrc
alias rdms="rails db:migrate:status"
```

とか設定しておいてあげると、コマンドでrdmsって打つだけで``rails db:migrate:statu``できちゃいます！！
これで開発スピード爆上がりですね！

この設定もおすすめだよってのがございましたらコメントお願いしまする！

Author : [Kazuhito Nakayama](twitter.com/facultyoflaw11)
jestの書き方やエラーなどや補足(自分用)

###shallowとmount
mountは全て展開してくれる。

```
const wrapper = mount(<Sample {...props} />)
// デバッグを表示したいときは
console.log(wrapper.debug());
// などで表示する。
```

### ボタンをクリックさせたいとき
```
await act(async () => {
   wrapper
     .find("クラスやidなど")
     .at(0)
     .simulate("click")
});
```

### クラスのモック化
```
jest.mock("react-redux");

// 関数が呼ばれたかどうかのモック化
const testFunk = 関数名 as jest.MockedFunction<typeof 関数名>
// 利用するのは 1回呼ばれたかどうかの確認など
expect(testFunk).toHaveBeenCalledTimes(1)
```

### 画面の表示のテストを実施する
```
const test: 型 = {
  isTest: true,
}

// dispatchを行う "test/sample"
// dispatch({type: "xxxx", payload: state});

const wrap = mount(
  <Test />
);
console.log(wrap.debug());

// storeの値や画面表示の検証
// ボタン押下など検証
await act(async () => {
      wrap
        .find("#testButton")
        .at(0)
        .simulate("click")
});
// changeなどもsimulateに入れると動作する
```
[MySQL] インデックスの貼り方

# 概要 
<!-- 発端や概要を記載 -->
MySQLインデックスのメモ（コマンド一覧）．

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [インデックスの貼り方](#インデックスの貼り方)
2. [インデックスの確認](#インデックスの確認)
3. [インデックスの削除](#インデックスの削除)


#インデックスの貼り方

```:>mysql
ALTER TABLE テーブル名 ADD INDEX インデックス名(カラム名);
```

　インデックスを貼るとデータの検索，抽出が早くなる．しかし，データの追加，更新などの処理が遅くなるデメリットがある．


#インデックスの確認

```:>mysql
SHOW INDEX FROM テーブル名;
```


#インデックスの削除

```:>mysql
ALTER TABLE テーブル名 DROP INDEX インデックス名;
```




<!--
# 参考文献
- [リンクテキスト](URL)
- [リンクテキスト](URL)
-->
Homebrewで「Your CLT does not support macOS 11.0」が出た時の対応

# 概要

Big Sur で nodebrew をインストールしようとしたら以下のようなエラーとなってしまった。

```
Error: Your CLT does not support macOS 11.
It is either outdated or was modified.
Please update your CLT or delete it if no updates are available.
Update them from Software Update in System Preferences or run:
  softwareupdate --all --install --force

If that doesn't show you an update run:
  sudo rm -rf /Library/Developer/CommandLineTools
  sudo xcode-select --install

Alternatively, manually download them from:
  https://developer.apple.com/download/more/.

Error: An exception occurred within a child process:
  SystemExit: exit
```

# 原因
CLT (Command Line Tools) が古いか更新されているらしい。

以下のコマンドでインストールしてみたけれど状況は変わらず。

```
$ sudo xcode-select --install
xcode-select: note: install requested for command line developer tools
```

# 対策
言われた通り、一度削除してインストールで解決しました。

```
$ sudo rm -rf /Library/Developer/CommandLineTools
$ sudo xcode-select --install
```

また、以下からダウンロードすることもできるようだ。
https://developer.apple.com/download/more/
![ScreenShot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118488/e34572a3-3187-7f15-6c5a-f2a64ca9daf1.png)
CPEクレジットの稼ぎ方（CISSP）

# 1. 結論
CPEクレジットを比較的容易に稼ぐ方法として、以下のような手段があります。

### 1-1. ウェビナー系
- セキュリティベンダーとの打合せやプレゼン参加（ウェビナーを含む）
- (ISC)² Webinar

### 1-2. トレーニング系
- 教育トレーニング・セミナー参加
- 自己学習、オンライントレーニングコース完了
- Professional Development Institute（Course）

### 1-3. 読み物系
- セキュリティ関連書籍の読了・情報セキュリティ雑誌の定期購読
- InfoSecurity Professional Magazine（Quiz）など

# 2. 参考URL
- [(ISC)² 日本語版サイト -> メンバーの方々へ -> CPEクレジット](https://japan.isc2.org/member_cpecredit.html)
- [(ISC)² 日本語版サイト -> メンバーの方々へ -> 日本語Webinar](https://japan.isc2.org/webinar_2021.html)
- [(ISC)² 英語版サイト -> MEMBERS -> CPE Opportunities](https://www.isc2.org/Membership/CPE-Opportunities)

# 3. 更新履歴
- 2020/12/17：初版投稿
- 2021/5/17：記事全体を見直し
ドメイン名(FQDN)から配下のページにリダイレクトする.htaccessの書き方

# はじめに
`http://hoge.com`にアクセスされた時に
`http://hoge.com/fuga/index.html`にリダイレクトさせる.htaccessの書き方を紹介します。

# コード&解説

`.htaccess`はルートディレクトリに配置し、最終的な記述はこうなります↓

```text:.htaccess
<IfModule mod_rewrite.c>
	RewriteEngine on
	RewriteBase /
	RewriteRule ^$ http://hoge.com/huga/index.html [R=301,L]
</IfModule>
```

一行ずつ解説していきます。

### `<IfModule mod_rewrite.c>`
mod_rewriteはApacheサーバでURLの書き換えを行うモジュールです。
mod_rewriteが使えない環境ではmod_rewriteのコードが実行されるとエラーが発生します。
`<IfModule mod_rewrite.c>`,`</IfModule>`はmod_rewriteが使える環境でのみタグの中に記述されたコードを実行します。


### `RewriteEngine on`
mod_rewriteの機能を有効化します。`off`とすれば無効化されます。


### `RewriteBase /`
Rewrite処理のベースとなるディレクトリを指定します。
`RewriteBase /`とした場合、`.htaccess`が配置されているディレクトリが指定されていることになります。
(`.htaccess`の有効範囲については[このサイト](https://kana-lier.com/web/redirect/)が参考になりました)

また、この記述がない場合は、htaccessを設置しているディレクトリが自動的に選択されますが、これはRewriteRuleを相対パスで記述した場合にのみ適用されるそうです。
なので特に理由がなければ`RewriteBase`を指定した方がいいかと思います。


### `RewriteRule ^$ http://hoge.com/huga/index.html [R=301,L]`
#### 基本の書き方
```
RewriteRule A B [C]
```
AにアクセスされたらBにリダイレクトする[恒久的か一時的か指定]
という風に書きます。
#### Aの部分
転送元を指定します。
`RewriteBase`で指定したディレクトリ以下を記述することに注意です。

今回の`^$`はどちらも正規表現で
- `^`：文字列の始まりの意味
- `$`：文字列の終わりの意味
になります。
`.htaccess`がルートディレクトリに配置し`RewriteBase /`としているので、「hoge.comにアクセスされたら」という意味になります。

#### Bの部分
リダイレクト先のURLを書きます。
転送元の記述と違って、URLの先頭から記述します。

#### Cの部分
301リダイレクトか、302リダイレクトか指定します。
302リダイレクトにしたい場合は`[R=302,L]`とします。


# まとめ
`.htaccess`について調べると`RewirteRule`について書かれている記事がたくさん出てきますが、うまくいかない理由として.htaccessを置く場所、`RewriteBase`の記述もある気がしました。
誰かの参考になれたら嬉しいです。

# 参考サイト
[.htaccessを使ったよく使うリダイレクトまとめ](https://kana-lier.com/web/redirect/)
[ .htaccessを用いたURL書き換えをマスターする・前編](http://studio-arz.com/bliki/2010-01/002017.html)
[今さら人に聞けない！WordPressで使われているmod_rewriteの説明書](https://html-coding.co.jp/knowhow/tips/wp_modrewrite/)
スクラムガイド2020について

## はじめに

この記事は2020年12月16日に行われた[スクラムガイド2020解説ビデオ オンライン上映会](https://scruminc.jp/?p=2924)に参加し、得た気づきや感想を私なりにまとめたものです。

## 個人的に印象的だったこと

このイベントを通じてたくさんの新たな発見や気づきを得ることができました。
その中でも特に印象的だったことを少し書いていこうと思います。

### 「Why」を明確にする

今回のスクラムガイドのアップデートにより、スプリントプランニングのトピックに新しく「このスプリントはなぜ価値があるのか？」が加わりました。
そして重要なのは3つあるトピックの中の1番最初に書かれているというところだと思います。
解説ビデオの中でJeff Sutherlandは素晴らしい結果を達成するには「Why」を理解している必要があると述べていました。
なぜ、「Why」からなのか、なぜ「Why」を知る必要があるのかは、Jeff Sutherlandも解説ビデオの中で述べていた「Whyから始めよ」のTEDの動画を見ると理解できると思います。
https://www.ted.com/talks/simon_sinek_how_great_leaders_inspire_action?language=ja

チーム全体が「Why」を理解し、プロダクトを生み出していかないとユーザには「欲しい」「使いたい」と思ってもらえません。
プロダクトオーナーにはこの「Why」をチーム全体に伝え、巻き込んでいく責任があります。

### 「役割」から「責任」への変化

これまで「プロダクトオーナー」「スクラムマスター」「開発チーム」でそれぞれどのような役割を担うかとしていたものを、今回のアップデートではそれぞれにどのような「責任」があるかが記されるように変わりました。(「開発チーム」という表現も「開発者」へと表現が変わりました。)
これまで「役割」という印象が強かったことで、プロダクトオーナーは「プロダクトバックログを作ればいい、あとは開発チームが作ってくれる。」やスクラムマスターは「イベント全て開催し、このチームがスクラム開発できていればいい。作るモノへの責任はない。」といった、スクラムガイドに書かれているそれぞれの役割をこなせばいいものという誤解を与えているケースが多かったようです。
事実、私自身の経験的にもプロダクトオーナーはプロダクトバックログを作ることと、実際にできたもの(結果)にしか興味を持っていないというケースはありました。
逆に開発チームもプロダクトオーナーが提示したプロダクトバックログの優先度順に作っているだけで、なぜ欲しいのかを深堀したり、より良いアイデアを提示するといったことが少なかったように思えます。
しかし、これでユーザに最大の価値を提供できるでしょうか？ユーザに最大の価値を届けるためにスクラムチームといいながら「一つ」のチームになれていなかったチームが多かったことが問題でした。
その解決のためにそれぞれの「役割」ではなくそれぞれの「責任」を明確にし、それぞれの「責任」を果たし、「一つ」のチームでユーザの価値を最大化するように取り組んでいけるようにしたのが、変更の理由だそうです。

### スクラムの価値基準と日本の文化

個人的に一番なるほどと思ったのはこの話だったかもしれません。
スクラムの価値基準の中で日本人は「公開」が苦手だという話がありました。それはなぜか。
日本では学校で授業を受けるとき、生徒(下の立場)が挙手をして先生(上の立場)が許可を出して初めて発言や質問をすることができるのが一般的な文化になっています。
我々日本人は小さい頃から上の立場の許可を得ないと発言・発信・質問ができない、すなわち公開には許可が必要という文化の中で生活をしてきています。
これが日本人に「公開」を難しくしてしまっている文化だという話がありました。

したがって、何も意識しないまま日本人がスクラムで開発をしてしまうと、チーム内で「公開」することを恐れたまま作業を進めてしまう可能性があります。
なので、「公開」することをチーム全体に浸透させること、「公開」へのハードルを下げることをスクラムで開発するにあたり、強く意識し変えていく必要があります。
逆に日本人はゴールに向かって全力を尽くすところは得意としている点なので、「集中」という点では長けているという話がありました。

## 最後に

今回のアップデートによって変わった点はいくつかありましたが、このイベントで話を聞いているうちに本質的な所は何も変わっていないことに気づきました。
私たちがスクラムを進める上で解釈を誤ってしまい、本質からずれてきてしまっている所を今回のアップデートで軌道修正することで、スクラムの本質へより導いてくれた気がします。
【Xcode12+Swift5+iOS14】 アプリ開発初心者の勉強日記 １

##はじめに

###簡単な紹介
Udemy の Yuta Fujiiさんのコース "【iOS14対応】未経験者がiPhoneアプリ開発者になるための全て iOS Boot Camp "の授業メモです。

今回はコースの　"セクション１　〜　セクション５"　のメモとなります。

あくまでも自分用ですが、同じコースの受講者やアプリ開発の初心者の方に役に立てたら嬉しいです。



###記事の見方について
この記事のおすすめの見方としては、一回講師の動画をちゃんと見て、自分でコードいじってみる時に、

「これの意味はなんだったけ？」

「あれのショートカート忘れた！！」

の時に、この記事をみるのがお勧めします。



###今回の記事の構成について

この記事での構成は以下となります。

- よく使うコマンド、機能について

- 関数の中身について

- よく使う操作について

- 他の大事そうな情報

さー、始めましょ！




##よく使うコマンド、機能について

- シミュレーションを開く　command+R

- シミュレーション閉じる　command+Q

- Optionキー + ファイルを選択すると、　storyboardと同時に開ける

- 画面の右上のマーク（二つの円が重なっているマーク）　
　>　Assitantを選択すると、関連づけのプログラムファイルを開くことができる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960378/c2dd57de-472b-23ea-8974-8f66d853a7b5.png)



##関数の意味について

- viewDidLoad ->画面表示

- @IBAction  ->タップした時に呼ばれる場所　変化をかける時にこれ



```instanse.swift
    @IBOutlet weak var label: UILabel!
    
    var count = 0

    label.text = "Pictureのロゴです"


```

- label →変数（インスタンス）→箱


実はこのlabel と countの役割（？）が一緒で変数の箱に名付けただけです！
label と count は変数の名前です。

textは属性です。。属性についてもう少し詳しく説明すると、

```label.swift

    label.text = "Pictureのロゴです"

    label.font = XXXX

```


Xcodeの右の方の属性(attributes)たちを label.text の"text" "font"の部分になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960378/878528e8-09b3-2505-ad1d-651c1e44f924.png)

具体的にどのような属性がtextのところに入れるかを確認するため、
command押しながら、textの部分をクリックし、jump to defintionを押し、そこに飛ぶと、使える関数が分かります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960378/8db3dca2-e1d8-9168-376e-e71e698fdd0b.png)

## よく使う操作について

####ViewController、Storyboard関連

- ControllerViewの矢印の設定→最初の画面の矢印はIs initial View Controllerで選ぶ

- control + storyboardのブロック　両方押した状態で、ドラッグドロップしてコードのところに引っ張っていくと、コードが作成される。

####ファイルとView Controllerに関連づける方法
1. File > Cocoa Touch Class > Class : "NextViewController"(などなど) > Sub Class of :UIViewController > Create
2. Storyboardの方に戻って、右の属性欄のクラスのところに"NextViewController"を入力して、作成したファイルに関係づける

## 他の大事そうな情報
####ファイルの説明について

- Info.listの中身は情報（プライバシー）に関連のあるリスト

## 終わりに
2020年12月17日にこの記事を書きました！
初めての公開記事へ。

##参考サイト
[【iOS14対応】未経験者がiPhoneアプリ開発者になるための全て iOS Boot Camp](https://www.udemy.com/course/ios14-iphone-ios-boot-camp/)
go-mysqlを使ったレプリケーション

https://github.com/siddontang/go-mysql/ というライブラリを使ったレプリケーションについて書きます。

# go-mysql

ググラビリティがとても悪いのですが https://github.com/siddontang/go-mysql/ というGolangのライブラリがありまして、次のような機能があります。

* MySQLのクライアント
* MySQLプロトコルを受け付けるサーバ
* MySQLのレプリケーションプロトコルのハンドラ
* ...etc

三つ目の「MySQLのレプリケーションプロトコルのハンドラ」が面白い機能で、Golangのプログラムでbinlogを出力するMySQLサーバに接続してレプリケーションを処理することができます。

# プログラム例

READMEのexampleをもう少し実装してROWS_EVENTを処理するプログラムが以下のようになります。

```go
package main

import (
	"context"
	"fmt"

	"github.com/siddontang/go-mysql/mysql"
	"github.com/siddontang/go-mysql/replication"
)

func handleRowsEvent(ev *replication.BinlogEvent) {
	rowsEvent := ev.Event.(*replication.RowsEvent)
	//rowsEvent.Dump(os.Stdout)
	fmt.Printf("rows event: table=%s, values=%v\n",
		rowsEvent.Table.Schema, rowsEvent.Rows)
}

func handleQueryEvent(ev *replication.BinlogEvent) {
	queryEvent := ev.Event.(*replication.QueryEvent)
	//queryEvent.Dump(os.Stdout)
	fmt.Printf("query event: table=%s, query=%v\n",
		queryEvent.Schema, queryEvent.Query)
}

func main() {
	cfg := replication.BinlogSyncerConfig{
		ServerID: 100,
		Flavor:   "mysql",
		Host:     "127.0.0.1",
		Port:     13306,
		User:     "root",
		Password: "",
	}

	syncer := replication.NewBinlogSyncer(cfg)

	binlogFile := "14a3896dc697-bin.000001"
	var binlogPos uint32 = 177
	streamer, _ := syncer.StartSync(mysql.Position{Name: binlogFile, Pos: binlogPos})

	for {
		ev, _ := streamer.GetEvent(context.Background())

		switch ev.Header.EventType {
		case replication.WRITE_ROWS_EVENTv2:
			handleRowsEvent(ev)
		case replication.UPDATE_ROWS_EVENTv2:
			handleRowsEvent(ev)
		case replication.DELETE_ROWS_EVENTv2:
			handleRowsEvent(ev)
		case replication.QUERY_EVENT:
			handleQueryEvent(ev)
		case replication.ROTATE_EVENT:
			rotateEvent := ev.Event.(*replication.RotateEvent)
			binlogFile = string(rotateEvent.NextLogName)
		}

		fmt.Printf("current position: %s:%d\n", binlogFile, ev.Header.LogPos)
	}
}
```

MySQLサーバへの再接続や、binlogのローテーションなんかはライブラリがうまいこと処理してくれます。
なので上記のプログラムを立ち上げっぱなしにしておくと、流れてくるbinlogを処理し続けます。

# 利用例

https://github.com/siddontang/go-mysql-elasticsearch というMySQLからElasticsearchにレプリケーションするツールで使われているようです。

あと、手前味噌ですが https://github.com/winebarrel/binrpt という自作のRDS向けの本番→ステージングレプリケーションツールでも使用していて、わりと元気に動いています。

# 注意点

* 現在のポジションはメモリ上にしかないので、プログラムの再起動後に前回の続きからレプリケーションを続けたい場合、どこかに保存する必要があります
* 現在のbinlogのファイル名はreplication.BinlogEventに含まれていないのでROTATE_EVENTをハンドルして、新しいファイル名を取得する必要があります
* RowsEventの場合、値は取得できるんですがカラム名は取得できないので、ソースのMySQLなどから取得する必要があります
* TABLE_MAP_EVENTが取得できないポジションから始めようとすると`Err: table id XXX: invalid table id, no corresponding table map event`でエラーになります
    * https://github.com/siddontang/go-mysql/issues/396
* MySQLのクライアントとしては完成度があまり高くないように思いました。メモリを結構消費するのと、深追いできてないのですが複数行をScanしたときたまに値の途中が欠けることがあり…（のでbinrptではクライアントとして
go-sql-driver/mysqを使っています）

# まとめ

以前あったC++のMySQL Binlog EventライブラリはすでにMySQL Labsには無いようなので、レプリケーションを自前でごにょごにょするというのはすでに廃れた技術なのかなと思っていたんですが、go-mysqlはなかなか完成度が高くて、いろいろと応用が利きそうな感じでした。
SkaffoldでKustomize使っていて"yaml: invalid trailing UTF-8"が出て対処した方法

## 状況
複数コンテナ使う関係でSkaffold、Kustomizeを使っている環境で、最近brew upgradeしてからか急にskaffold runするとエラーが出るようになりました（Macでローカル実行）

```
running [kustomize build ./hogehoge]
 - stdout: ""
 - stderr: "Error: accumulating resources: 2 errors occurred:\n\t* accumulateFile error: \"accumulating resources from '../fugafuga': '/Users/*****/hogehoge' must resolve to a file\"\n\t* accumulateDirector error: \"recursed accumulation of path '/Users/******/hogehoge': yaml: invalid trailing UTF-8 octet\"\n\n\n"
 - cause: exit status 1
```

## 解決した方法
今回はアプリ内にあるkustomize設定ファイル（yaml）のうち一部コメントに使用していた全角文字を全て削除すると解消しました。
UTF-8で保存し直すだけじゃなく、ここまでやる必要があったみたいです
サーヴァントリーダー論〜とあるエンジニアの理想論〜

# サーヴァントリーダーとは

リーダーと聞くとチームを引っ張っていくイメージがありますが、サーヴァントリーダーはメンバーを支援してチームを導いていくタイプのリーダーです。

---
# 提唱者
アメリカのロバート・グリーンリーフ博士がリーダーシップを研究する中で提唱したリーダーシップ哲学です。

**特性**

* 傾聴：メンバーの話をしっかり聞き、リーダーとしてどうすれば役に立てるかを考える。
* 共感：完璧な人間などいないという前提を十分認識した上で、相手の立場に立って相手の気持ちを理解する。
* 癒し：相手が失敗して落ち込んでいるときやチームの成績が上がらないときに元気づける言葉をかけ、本来の力を取り戻させる。
* 気づき：偏見にとらわれずに相手と接し、気づきを与えることができる。
* 納得：命令ではなく、相手のコンセンサスを得て納得を促しながら話を進める。
* 概念化：個人やチームとしてのビジョンを明確に示し、相手に伝えることができる。
* 先見力：チームの現状を俯瞰するとともに、現在と過去の出来事と照らし合わせながら、これから起こる出来事・問題を予測する。
* 執事役：自分の利益よりも、相手に利益を与えることに喜びを感じる。
* 成長への関与：相手の潜在能力に気づき、成長を促すことに日頃から積極的にコミットする。
* コミュニティづくり：愛情と癒し、思いやりの気持ちで満ちていて、メンバーが大きく成長できるコミュニティをつくる。

ちなみにサーヴァントとは、「使用人」、「召使い」を意味します。

---
# この特性って

傾聴できて、共感できて、癒しを与えられて、小さな変化に気付き、メンバーの合意を得て、概念を言語化し説明でき、チームの現状を俯瞰的に見て未来を予測し、メンバーの利益を優先し、メンバーの潜在能力を察知し成長を促し、メンバーが大きく成長できるコミュニティを作れる特性って、超人じゃない？

---
# もう少しゆるく

サーヴァントリーダーは、以下の特性を持ち合わせていれば良い。

* メンバーが自由に発言できる。
* メンバー、チーム、クライアントの状況を言語化し、説明できる。
* メンバーの成長に寄与できる。

この3点が重要です。（コミュニケーション能力は必須です）

---
# メンバーが自由に発言できる

リーダーは、聞き手になってください。
重要なのは、ある程度の答えや方向性を持って、聞く、相談することです。
新入社員を例にあげると、初めて仕事に接する際、分からないから何も考えず質問すると出来ない新人と認知されるケースがよくあります。
リーダーも同様ですというか、リーダーがそれを出来ないと新入社員以上にダメです。
リーダーとメンバーが会話し、相互の得意・不得意、理解度がわかり、関係を築くことが出来ます。

---
# メンバー、チーム、クライアントの状況を言語化し、説明できる

言語化重要。
ほんと重要。
1つ1つのタスク、チームの状況を言語化できることはサーヴァントリーダーでなくても必要ですが、サーヴァントリーダーとして支援するためには、何故このタスクや作業が必要なのか、今このチームに必要なのは何か理解してもらうことが重要です。
理解してもらうことで信頼が生まれます。

---
# メンバーの成長に寄与できる

メンバーの得意・不得意とする部分を理解し、メンバーが新しいことに挑戦することを支援し、挑戦することに対して、フォローしてあげる。
挑戦には、リスクがついてくるので、リスクマネジメントが重要です。
結果、メンバーは、リーダーが自分の挑戦へ理解を示してくれていること、挑戦に失敗してもフォローしてくれていることで安心して、挑戦でき、リーダーへの信頼が深まります。

---
# 信頼関係

結果、チームとは信頼関係ですね。
SREチームに配属されてぶつかった最初の壁「何から手をつければいい？」から脱却するために私がやったこと

この記事は<a href="https://qiita.com/advent-calendar/2020/mcs">モチベーションクラウドシリーズのアドベントカレンダー2020</a>の20日目の記事になります。

## はじめに
私はエンジニア組織にジョインしてから約1年webアプリケーションの開発に携わった後、今年９月から未経験なSREチームにジョインしました。

SREチームは対応すべきスコープが広く、対応しなければならないタスクが多岐にわたるため、
SREチームにジョインしてすぐに、「一体何から手をつければいいの？」とタスクの優先度が全くわからず、混乱していた時期がありました。

書籍『Site Reliability Engineering』の中でも、「SREがすべきこと」について、「サービスの可用性」「レイテンシ」「パフォーマンス」「効率性」「変更管理」「モニタリング」「緊急対応」「キャパシティプランニング」が責務であると書かれております。
これ以外にも、弊社では「セキュリティリスク」と「コスト」と「開発生産性」についてもSREの責務としています。

| 項目       |内容      | 
|:---------|:---------|
|セキュリティリスク   | 顧客が安心して弊社サービスを使えるように、セキュリティリスクを減らす。  |
|コスト  | システム運用にかかるコストを最適な状態にする。また、定めた予算を超えないよう管理する。  |
|開発生産性 | Toilの撲滅やデプロイフロー改善などにより、開発生産性を向上させる。|

この記事では、上記の通り多岐に渡るSREの日々の業務をどのように優先度を決めているか、弊社チームで工夫したことについてまとめました。何かの参考になれば幸いです。

## タスクの整理について
タスクの優先度を決めるためにまず最初に以下の観点でタスクを整理しました。

| 項目       |内容      |  備考 |
|:---------|:---------|:---------|
|影響の対象     |影響が出る対象はどこなのか？ | ・顧客影響<br>・内部影響|
|影響度     |自組織において、影響範囲はどのくらいか？    |・影響の度合いが大きい<br>・影響の度合いが普通<br>・影響の度合いが小さい|
|頻度    　|どのくらいの頻度でその現象が起こるのか？     | ・今まさに起きている<br>・起きる可能性がある<br>・起きる可能性はほぼ無い|
|コスト     |対応するとどのくらい時間がかかるか？        | ・1日以内<br>・数日以内<br>・1週間以上 |



## 優先度の付け方
各観点に関して、重み付けにすることで<b>プライオリティスコア</b>を算出し、優先度を決めました。
それぞれについてスコアとその理由を説明していきます。
### 影響の対象
弊社では顧客が第一と考えており、内部影響のあるタスクより、顧客影響があるタスクを優先的に解決していく必要があると考え、以下のようにスコアを策定しています。

| 項目       |スコア      | 
|:---------|:---------|
|顧客影響       |5   |
|内部影響     |3  |

### 影響度
影響度は現場から開発組織、顧客、etc、様々な要素があり、一つ一つの粒度を細かくしても優先度は決められないので
粒度を粗くすることで、優先度を決めやすくし、かつ影響度に関しては重要度が高いため以下のようなスコアで割り振っています。


| 項目       |スコア      | 
|:---------|:---------|
| 影響の度合いが大きい|5  |
| 影響の度合いが普通 |3  |
| 影響の度合いが小さい| 1 |

### 頻度
そのタスクを早く片付けないと、今まさに問題が起きている場合、何度も時間を割いて対応する場合があります。
よって、<b>今まさに問題が起きているかどうか</b>から考えて、スコアを決めます。

| 項目       |スコア    | 
|:---------|:---------|
| 今まさに問題が起きている     | 3  |
| 問題が起きる可能性がある     |2 |
| 問題が起きる可能性はほぼ無い | 1 |


### コスト
コストはそのタスクを終わらせるまでの対応期間を指しています。
スコアを決定する際は、自分一人で考えるのではなく、チーム内でどのくらいで終わらせることができるかの認識を合わせることで
誰に振っても、納期が遅れることのないようにスコアを割り振ります。

| 項目       |スコア      | 
|:---------|:---------|
| 1日以内     |3  |
| 数日以内    |2   |
| 1週間以上   | 1  |


### 論理式
以下のようにプライオリティスコアを定義しました。

```
プライオリティスコア = カテゴリ × 影響度 × 頻度 × コスト
```
プライオリティスコアが70以上を意識をして、その中からスケジュールを組むことで、何をやるべきかが明らかになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575460/d70d628f-8264-fbbb-58aa-97fa1eaddf4c.png)

## アウトカム
今までチーム内の一人一人の中で優先度があり、多少のズレがありましたが、チームの優先度が揃いました。
その結果、今日、1週間という短期の時間軸で何をやるべきかで迷うことがなくなり、パフォーマンスが上がりました。

## 最後に
SREとしての何をすべきかを悩んだときは、日々のタスク整理と優先度を付けることで
今日一日何に集中してやるべきかが明らかになり混乱しなくなりました。

タスク整理から優先度付けまでを毎日やることは蔑ろにしがちかもしれませんが、
意識して取り組むことが重要です。