OmniAICreator/Qiita-1.07M huggingface dataset:
Bottleのログをloggingに統合する

## 目的

Pythonの軽量webフレームワーク[Bottle](http://bottlepy.org/)はログをstderrに出力するが、これを[logging](https://docs.python.org/ja/3/howto/logging.html)で扱いたい。

## Bottle自体のログ

https://github.com/bottlepy/bottle/blob/release-0.12/bottle.py#L74
ここで設定されている`_stderr`を改竄する。

```python
import logging
import bottle

logger = logging.getLogger(__name__)
bottle._stderr = logger.info
```

改行は除いた方が見やすい。

```python
bottle._stderr = lambda x: logger.info(x.replace('\n', ''))
```

しかしこれだけだと、アクセスログは依然stderrに出る。こちらはbottleの利用するバックエンド（デフォルトでは[wsgiref](https://docs.python.org/ja/3/library/wsgiref.html)）のものなので、別の処置が必要になる。

```
INFO:__main__:Bottle v0.12.17 server starting up (using WSGIRefServer())...
INFO:__main__:Listening on http://127.0.0.1:8080/
INFO:__main__:Hit Ctrl-C to quit.
127.0.0.1 - - [15/Oct/2019 12:21:22] "GET / HTTP/1.1" 404 720
```

## バックエンド（wsgiref）のログ

https://github.com/bottlepy/bottle/blob/release-0.12/bottle.py#L2773
ここから出力されているので、`ServerAdapter.options['handler_class']`を設定する。
https://github.com/bottlepy/bottle/blob/release-0.12/bottle.py#L3113
ここで`bottle.run`の残りのキーワード引数が`options`に引き継がれるので、結局`handler_class`を`bottle.run`に渡せばよい。

```python
import datetime
import logging
from wsgiref.simple_server import WSGIRequestHandler
import bottle

logger = logging.getLogger(__name__)

bottle._stderr = lambda x: logger.info(x.replace('\n', ''))

class WellLoggedHandler(WSGIRequestHandler):
    def address_string(self):  # Prevent reverse DNS lookups please.
        return self.client_address[0]
    def log_request(self, code='-', size='-'):
        req = bottle.request
        protocol = req.get('SERVER_PROTOCOL')
        logger.info(f'{req.address_string()} - - [{datetime.datetime.now()}] "{req.method} {req.path} {protocol}" {code} {size}')

# logging.basicConfig(level=logging.DEBUG)
bottle.run(handler_class=WellLoggedHandler)
```

という感じになる。（例えば[apacheのドキュメント](https://httpd.apache.org/docs/2.4/ja/logs.html#accesslog)を見るに`- -`の部分はユーザーの認証情報などが入るらしい。）

https://github.com/python/cpython/blob/3.7/Lib/http/server.py#L546
`log_error`や`log_message`というメソッドもあるので必要に応じて再定義するといいだろう。
【Rails】RSpecによるテスト　3.コントローラーのテスト

##RSpecを使ったコントローラーのテスト

今回はコントローラーの単体テストを行っていきます。
コントローラーのテストで確認したい点は大きく2つで、

- 定義しているインスタンス変数が思ったものになっているか
- アクションの後に思ったビューが表示されるか

となります。
例として、ブログのposts_controllerのeditアクションについてテストを行います。
posts_controller内のeditアクションについての記述は以下の通りです。

```Ruby:posts_controller.rb
  def edit
    @post = Post.find(params[:id])
  end
```
編集する元の記事をインスタンス変数に定義しています。
すなわち、今回のテストで行うことは@postが正しく定義されているかと、アクションの結果editビューが呼び出されるかどうかの2つとなります。

####factory_botの設定

まずはfactory_botを設定してpostの生成をする準備を行います。

```Ruby:spec/factories/post.rb
FactoryBot.define do
  factory :post do
    title { Faker::Food.dish }
    text { Faker::Food.fruits }
    user
  end
end
```
タイトルと本文の決め方は正直適当です。emailのように重複してもエラーは出ないので、Fakerを使わず直接値を入力しても問題ないと思います。

####コントローラーのテストを実行

factory_botの準備ができたらテストを実行していきます。

```Ruby:spec/controller/posts_controller_spec.rb
require 'rails_helper'

describe PostsController do
  describe 'GET #edit' do

    it "assigns the requested post to @post" do
      post = create(:post)
      get :edit, params: { id: post }
      expect(assigns(:post)).to eq post
    end

    it "renders the :edit template" do
      post = create(:post)
      get :edit, params: { id: post }
      expect(response).to render_template :edit
    end
  end
end
```
モデルのテストと違ってくる点は、

- buildではなくcreateを使用
今回は保存したpostの呼び出しを行えるかテストをするため、作成したpostデータをテーブルに保存するためcreateメソッドを用います。

- assigns(:〜)
アクション内で定義されたインスタンス変数をシンボル型で指定します。
この書き方で、 @post は post と同じかどうかを確認します。

テストの結果を確認します。
`bundle exec rspec`でもテスト結果は確認できますが、他のテストも同時に実行されます。
今回のテスト結果のみを確認する場合は、ターミナルで実行するテストファイルを指定します。

```Ruby:ターミナル
$ bundle exec rspec spec/controllers/posts_controller_spec.rb
```

```:ターミナル
PostsController
  GET #edit
    assigns the requested post to @post
    renders the :edit template

Finished in 0.35048 seconds (files took 2.88 seconds to load)
2 examples, 0 failures
```
テストの結果は問題ないようです。
Unknown argument type '__attribute__' in method -[RCTAppState getCurrentAppState:error:]

# うざい赤エラーが出続ける
僕の場合はXcodeをアップデートしたらエラーが出るようになりました。

```
Unknown argument type '__attribute__' in method -[RCTAppState getCurrentAppState:error:]. Extend RCTConvert to support this type. -[RCTModuleMethod processMethodSignature] RCTModuleMethod.mm:369 -[RCTModuleMethod invokeWithBridge:module:arguments:] facebook::react::invokeInner(RCTBridge*, RCTModuleData*, unsigned int, folly::dynamic const&) facebook::react::RCTNativeModule::invoke(unsigned int, folly::dynamic&&, int)::$_0::operator()() const invocation function for block in facebook::react::RCTNativeModule::invoke(unsigned int, folly::dynamic&&, int) _dispatch_call_block_and_release _dispatch_client_callout _dispatch_main_queue_callback_4CF __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ __CFRunLoopRun CFRunLoopRunSpecific GSEventRunModal UIApplicationMain main start
```

# 正しい対処方法
React Nativeのバージョンを上げると解決します。
確か0.60.0とか

# 応急処置

事情があってアップグレードできない場合は、`node_modules/react-native/React/base/RCTModuleMethod.mm`を以下のように変更すると動く。

```js:RCTModuleMethod.mm
// 91行目
static BOOL RCTParseUnused(const char **input)
{
  return RCTReadString(input, "__unused") ||
         RCTReadString(input, "__attribute__((__unused__))") || //　この行を追加
         RCTReadString(input, "__attribute__((unused))");
}
```
#Mac OS を Catalina にアップデートしたら zoom の画面共有に不具合？デスクトップ画面だけが表示される。

Macの設定でZoomを許可することで直った。

![image](https://user-images.githubusercontent.com/13635059/66792873-b3c75100-ef35-11e9-8598-f27c96d9ce45.png)
https://support.zoom.us/hc/en-us/articles/201362153-How-Do-I-Share-My-Screen-?mobile_site=true

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2594








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
staticメソッドはインスタンスに依存しない機能を持つ？

## はじめに
phpを勉強する際に**「そもそもstaticってなによ？」**となるパターンが多いので、ここで簡単に解説する場を設けます。

## そもそもstaticとは何か
**「クラスに張り付いている」**変数やメソッドを示す修飾子です。

クラス内の変数やメソッドは、個別のインスタンスを生成してそのインスタンス経由でアクセスすることができます。
しかしstatic修飾子のついた変数やメソッドは、インスタンスを生成しなくてもクラスから直接呼び出すことができます。

今回はstatic変数とstaticメソッドのうち、staticメソッドについて取り扱います。
<br>

## どんな時に使うか？
例えば、呼び出したい機能の単なる集まりとしてクラスを利用して、**個別に値をずっと持たせておく必要のないとき(newしなくてよいとき)**に使います。

まずはstaticでない例から見てみましょう。

```php:例

<?php
class Calculator
{

  public function add($x,$y){
      return $x+$y;
  }    
  public function diff($x, $y){
      return $x - $y;
  }
    
}

$calc = new Calculator();
echo $calc->add(2,3)."\n";//5
echo $calc->diff(4,1)."\n";//3
?>
```

Calculatorは足し算や引き算などの計算機能をまとめたクラスです。
変数は特になく計算をするメソッドだけを提供してくれます。

しかし下記のようにしても良いでしょう。

```php:例
<?php
class Calculator
{

  public static function add($x,$y){
      return $x+$y;
  }    
  public static function diff($x, $y){
      return $x - $y;
  }
    
}

echo Calculator::add(2,3)."\n";
echo Calculator::diff(4,1)."\n";

?>
```

`Calculator::add(2,3)`と、addメソッドをクラスから呼び出しているのがわかるかと思います。

**「計算機能を一箇所(クラス)にまとめて管理・使用したい」**という用法であれば、インスタンス化しなくてもstaticメソッドで代替できます。
<br>

## まとめ
まとめると**「インスタンスに依存しない機能」**はstaticメソッドにすることができます。
<br>

## 参考
この記事は「CodeShip」内での実際の質疑応答や指導・アドバイスの一部を基に作成しています。
Googleスライドで取り消し線を使う方法

Googleスライドで取り消し線を使おうとしたら、メニューバーに見当たらなかったのでメモ。


# ショートカットキーを使う
Googleスライドでテキストに取り消し線を入れるには、キーボードショートカットを使用する。
`⌘ + shift + X`

対象テキストを選択して、上記のショートカットキーを使えば取り消し線が入る。
<img width="129" alt="スクリーンショット 2019-10-15 12.36.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6380/99faa0ad-511b-19f0-7287-e3c73c0e9333.png">

# ヘルプでその他のショートカットも確認できる
なお、`⌘ + /` でショートカットキーのヘルプを呼び出せる。
[Google スライドのキーボード ショートカット - パソコン - ドキュメント エディタ ヘルプ](https://support.google.com/docs/answer/1696717?hl=ja)
<img width="801" alt="スクリーンショット 2019-10-15 12.20.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6380/4d1de191-e327-58c3-4d03-c66bcc4e69d9.png">

キーワード検索もできるので、操作に困ったらこれを見れば良さそう。
<img width="366" alt="スクリーンショット 2019-10-15 12.21.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6380/9de7ab41-bdb8-da03-f2ca-55512a5e2f2c.png">

ちなみにGoogleドキュメントも同じ仕様の模様。
[Google ドキュメントのキーボード ショートカット - パソコン - ドキュメント エディタ ヘルプ](https://support.google.com/docs/answer/179738)
Embulkの利用、の前の準備。2019-10-15

# 概要
Embulkの利用、する前のEmbulk自体のインストール方法についてなどを記します。

# 環境

```
% cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.3 LTS"
```

# インストール

## Java

Embulkのインストールの前にJavaをインストールします。

```
% sudo apt-get install openjdk-8-jre
% java -version
openjdk version "1.8.0_222"
OpenJDK Runtime Environment (build 1.8.0_222-8u222-b10-1ubuntu1~18.04.1-b10)
OpenJDK 64-Bit Server VM (build 25.222-b10, mixed mode)
```

## Embulk

https://github.com/embulk/embulk#quick-start
上記の通りインストールします。
`$HOME` 以下にインストール手順なのでインストールするディレクトリは適宜変更してください。

```
% curl --create-dirs -o ~/.embulk/bin/embulk -L "https://dl.embulk.org/embulk-latest.jar"
% chmod +x ~/.embulk/bin/embulk
% ~/.embulk/bin/embulk --version
embulk 0.9.19
```

`PATH` の設定も必要があれば。

```
% echo 'export PATH="$HOME/.embulk/bin:$PATH"' >> ~/.bashrc
% source ~/.bashrc
% which embulk
/home/vagrant/.embulk/bin/embulk
```

# まとめ

Embulkを使うための準備は、Javaのインストールとバイナリを持ってきて完了の簡単な作業でした
OpenPyXLでセル文字の書式を判定したい

OpenPyXLでセル文字の書式(太字かどうか、イタリックかどうか…等)を判定したいです。

###筆者環境
* Python 3.7.2
* OpenPyXL 2.6.2


## リファレンスを見る
https://openpyxl.readthedocs.io/en/stable/styles.html#cell-styles より。

```python
from openpyxl.styles import Font, Color

wb = Workbook()
ws = wb.active
a1 = ws['A1']

# 中略

a1.font.italic = True # is not allowed # doctest: +SKIP
```

これは`ws['A1']`をイタリック体に設定するコードのようです。しかし、逆に`a1.font.italic` が`True`かどうか判定するコードを書けば、`ws['A1']`がイタリックかどうか判定できそうです。  
イタリックの代わりに、__太字__bold の判定をやってみましょう。

## 実装
```python
flag = ws['A1'].font.bold
```
または

```python
flag = ws.cell(row=1, column=1).font.bold
```
これでよさげと思いきや、もしA1セルが太字ではなかったらこの`flag`にはなんと`False`ではなく`None`が入ります。`False`にしたい場合は、素朴な方法ではありますが次の一行を加えましょう。

```python
flag = False if flag is None else flag
```
コンジョイント分析

```{r}

#数量化1類

data=data.frame(販売率=c(3.0,1.8,1.5,3.3,2.2,2.0,3.5,2.0,1.7,2.3),大都市=c(1,0,0,1,1,1,1,0,1,1),地方都市=c(0,1,1,0,0,0,0,1,0,0),温暖=c(0,1,0,0,0,0,1,1,0,0),普通=c(1,0,1,1,0,0,0,0,0,0),寒冷=c(0,0,0,0,1,1,0,0,1,1))

X=data[,colnames(data)!="温暖"];X=X[,2:ncol(X)]

x=array(0,dim=c(length(colnames(X)),length(colnames(X))))

for(i in 1:ncol(X)){
for(j in 1:ncol(X)){  


  x[i,j]=sum(X[,i]*X[,j])


}
}

xy=array(0,dim=c(ncol(X),1))

for(i in 1:ncol(X)){

xy[i]=sum(X[,i]*data$販売率) 

}

A=solve(x)%*%xy

y=c()

for(j in 1:nrow(X)){

y=c(y,sum(X[j,]*A))  

}

U=y



#MONANOVA

for(k in 2:length(y)){
  
if(U[k]<U[k-1]){
  
MU_data=data.frame(num=1:(k-1),MU=0,sig=0)

for(l in 1:(k-1)){  
  
MU=sum(U[k]+U[(k-1):(k-l)])/(l+1)

if(k-l-1==0){

MU_data$MU[l]=MU;MU_data$sig[l]=ifelse(MU>0,1,0)

}else{

MU_data$MU[l]=MU;MU_data$sig[l]=ifelse(MU>U[(k-l-1)],1,0)

}  

}

no=min(MU_data$num[MU_data$sig==1])

MU=MU_data$MU[no]

U[k:(k-no)]=MU

}

U_ave=c()  
    
for(l in 1:length(U)){
  
U_ave=c(U_ave,mean(U[1:l]))  
  
}  
  

eta=sqrt(sum((U-U_ave)^2)/sum((U-mean(U))^2))

print(eta)
  
}  

```


```{r}

#効用推定法


X=as.matrix(data[,2:ncol(data)]);Y=c(data$販売率)

a=rep(1,ncol(X));b=rep(1,nrow(X))

ite=10000;delta=0.01

for(j in 1:ite){
  
a_pre=a;b_pre=b  
  
A=sum((U-U_ave)^2);B=sum((U-mean(U))^2)

eta=sqrt(sum((U-U_ave)^2)/sum((U-mean(U))^2))

  
for(i in 1:length(a)){

da=2*sum(X[,i]*(U-U_ave))

db=2*sum(X[,i]*(U-mean(U)))

de=(da*eta/A-db*eta/B)/2

a[i]=a[i]-delta*de
  
}  
  
for(i in 1:length(b)){

da=2*sum((U-U_ave)*Y)

db=2*sum(U-mean(U)*Y)

de=(da*eta/A-db*eta/B)/2

b[i]=b[i]-delta*de

} 

U=c(X%*%a)+c(b*Y)

U_ave=c()

for(l in 1:length(U)){
  
U_ave=c(U_ave,mean(U[1:l]))  
  
}

print(sum(abs(c(a_pre,b_pre)-c(a,b))))
  
}

```
Amazon RDS を日本語&絵文字対応にする。

### はじめに

Thanks: [MySQL5.5で🍣絵文字🐟を挿入/検索する](https://qiita.com/suzuki_sh/items/f02fc88a8514fd23a47e)

大抵の場合、国内のシステムでは

 - 日本語対応
 - 絵文字対応
 - 各絵文字をそれぞれ別の文字として扱う

上記条件はクリアした方がベターかと思いますので、
この記事のタイトルは「Amazon RDSの文字コードを utf8mb4_bin に変更する方法」と言い換えることができます。

### 手順
1. RDS管理画面のメニューから「パラメータグループ」に飛ぶ。
2. パラメータグループがDefaultだけだった場合は、新規作成する。
   （Defaultは変更できない。）
3. 作成したパラメータグループの設定画面にて、下記項目の値を utf8mb4 に変更する。
    1. character_set_client
    2. character_set_connection
    3. character_set_database
    4. character_set_results
    5. character_set_server
4. 同じく設定画面にて、collation_connection の値を utf8mb4_bin に変更する。
5. RDSダッシュボードからインスタンスの設定画面に飛び「データベースの設定」の中の「DB パラメータグループ」を、作成したグループに変更する。
6. RDSインスタンスを再起動する。

### 最後に
勉強中の身ですので、ためになる周辺知識やご意見はいつも大歓迎です。
コメントお待ちしてます。
RSpecで削除メソッドのControllerをテストしたら"expected #count to have changed by -1, but was changed by 0"が出た件

## この記事の目的

未経験エンジニア3ヶ月目のたっきーです。
開発に携わってRSpecでテスト書いてと言われましたが、とても苦戦し特にError文を検索しても回答が出てこない事が辛すぎてポエム記事を書くことになりました。
書き方や原因が考えていることと違ったら、「トンチンカンな事言ってるぞ」と編集リクエストください。
みなさまに育てていただけると嬉しいです。
※そのままのコードではなく、紹介用なので簡素化したコードで書いてます。

## 起きた事

Railsで書いたdestroyアクションのメソッドのテストを書いたら、
"expected #count to have changed by -1, but was changed by 0"と出た。
ググっても、日本語の記事が全然出てこないしよくわかんないし、そもそもRSpec自体よくわかんない状態でとても困った。
あとExpected response to be a <redirect>, but was <404>もエラーで出ていた。

## コード

```spec.rb
    context 'categoryを削除し、更新する' do

      before :each do
        @delete = create(:category)
      end

      subject { delete :category_destroy, id: @category_delete }

      # カテゴリ(category)を削除する
      it "deletes the category" do
        expect{ subject }.to change(Category,:count).by(-1)
      end

      # その後#index にリダイレクトすること 
      it "redirects to admin/custom#index" do
        subject
        expect(response).to redirect_to customizes_index_path 
      end

    end
```

## 指摘されている事

僕のコード上では-1になる事をexpect(期待)しているのに、結果は0だよって言われてる。
つまり、削除がされていないんじゃないのか？？

## どこを確認すればいいのか

僕は今回、先輩に泣きついてlogディレクトリのtest.logってファイルを調べて。ヒントをもらった。
もう一度$bundle exec rspec テストファイル名してみると、色々コードが出てきたが
その中にちゃんとcategory deleteの文字がある。
通ってはいるが、どこかで落ちているのだ。

## 解決方法
結論をいうと、factorybotと呼ばれるgemにテストデータを書いていなかったから怒られたのだ。
なので、factories.rbファイルに下記を追加した。

```factories.rb
  factory :category do
    name {Faker::Name.title}
    label {Faker::Name.title}
    priority {1}
  end
```

Fakerはテストデータを簡単に作ってくれるgemのようです。
https://qiita.com/Keisuke69/items/edcaadc100361cf945e2

##結論

結局、controllerで定義したメソッドをviewで呼ぶように
RSpecでもfactorybotで定義したテストデータの変数をspecでファイルで呼んでくるだけのようだ。

##RSpecの書き方ととfactorybotの書き方

```[書き方]spec.rb
RSpec.describe '削除' do
  it 'カテゴリ削除' do
    expect(条件式).to eq 
　　#expectの内容はcontrollerによる！
  end
end

```
RSpecの書き方細かく説明できません。
もし書き方について知りたい方は@jnchitoさんのこちらの記事で見てみてください。
https://qiita.com/jnchito/items/42193d066bd61c740612
まだまだ全然わからないけど、未経験の僕でも雰囲気だけでもバンバン伝わってくる
非常に丁寧な記事です。

```[書き方]factory.rb
factory :◯◯ do
    カラム名１ {Faker::Name.title}
    カラム名２ {Faker::Name.title}
    カラム名３ {1}
  end
```
JavaScript　覚えておくべき注意点！（５）　ジャンケンゲームの作り方　数値をランダムにするプログラム

### ランダム数の導き方、使い方

```javascript:random.js
Math.random () // ０以上１未満の数値をランダムに作る…①
↓
Math.random () * 3; // ０以上３未満の数値をランダムに作る…②
↓
Math.floor(Math.random () * 3); // ０、１、２の数値をランダムに作る…③
↓
Math.floor(Math.random () * 3) + 1; // １、２、３の数値をランダムに作る…④


/* このプログラムで使うメソッドの構文 */
var r = Math.random() // ０以上～１未満のランダムな実数を返す
var f = Math.floor(r) // 指定された数値以下の最大の整数を返す

```

###ジャンケンプログラムを作る

- ユーザーにジャンケンの手を入力してもらいます。
- ジャンケンの手は[グー:1][チョキ:2][パー:3]という数値で表現しますが、数値のままでは何を表わしているか分かりにくいので、それぞれGU、CHOKI、PAとい変数に代入したものを使います①。ユーザの手は入力ダイアログボックスを使って入力してもらい、結果を変数humに代入します。②最後にparseInt関数を使い文字列から数値に変換します③ 10は10進数の数値に変換するという意味です。

```javascript:random_1.js
// ジャンケンの手の番号を設定
var GU    = 1;
var CHOKI = 2;
var PA    = 3;

// ジャンケンの入力ダイアログボックスを表示
var hum = prompt('半角数字で1～3の数字を入力してください。\n\n' + GU + ':グー\n' + CHOKI + ':チョキ\n' + PA + ':パー');
hum = parseInt(hum, 10);

```
GU、CHOKI、PAの値は一度定めたら変化させる必要がありません。このような値を「定数」と言います。それが定数であるか分かるように変数名を大文字にする習慣があります。
JavaScriptには明示的に定数を表わす「const」というキーワードがありますが、一部のブラウザは対応しておりません。

###ジャンケンゲームの基本的な原理の例示
1.ジャンケンの手を入力してもらう
2.入力値をチェックする
3.コンピュータのジャンケンの手を決める
4.どちらが勝ったか判定する
5.結果を表示する

とプログラムを製作していきます。
プログラム作成時の手順をしっかり考えて、理解します。

```javascript:jyanken.js
// ジャンケンの手の番号を設定
var GU    = 1;
var CHOKI = 2;
var PA    = 3;

// ジャンケンの入力ダイアログボックスを表示
var hum = prompt('半角数字で1～3の数字を入力してください。\n\n' + GU + ':グー\n' + CHOKI + ':チョキ\n' + PA + ':パー');
hum = parseInt(hum, 10);

// 入力値のチェック
if (hum !== GU && hum !== CHOKI && hum !== PA) {
	// 入力値が不適切な場合
	alert('入力値をうまく認識できませんでした。ブラウザを再読み込みすると、もう一度挑戦できます。');
} else {

	// コンピュータの手を決める
	var com = Math.floor(Math.random() * 3) + 1;

	// コンピュータの手の名前
	var comHandName = '';
	switch (com) {
		case GU:
			comHandName = 'グー';
			break;
		case CHOKI:
			comHandName = 'チョキ';
			break;
		case PA:
			comHandName = 'パー';
			break;
	}

	// 結果の判定
	var msgResult = '';
	if (com === hum) {
		msgResult = '結果はあいこでした。';
	} else if ((com == GU && hum === PA) || (com == CHOKI && hum === GU) || (com == PA && hum === CHOKI)) {
		msgResult = '勝ちました。';
	} else {
		msgResult = '負けました。';
	}
	// 最終的な結果の表示
	msgResult = msgResult + 'コンピュータの出した手は「' + comHandName + '」でした';
	alert(msgResult);
}


```
参考　[いちばんやさしいJavaScriptの教本](https://book.impress.co.jp/books/1116101117)
OpenVPNの接続・切断をSlackに通知する

## はじめに
OpenVPNに接続あるいは切断された際に、以下のようにSlackへ通知する仕組みを追加してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/3e590d7a-ea48-a246-4e20-2ca6c5e6a18d.png)
## 手順
### 1. SlackのIncoming Webhooksを用意する
下記URLの手順に従い、Incoming Webhooksを用意します。あわせて、投稿先のワークスペースとチャンネルも用意します。
https://api.slack.com/incoming-webhooks
### 2. 接続・切断通知用のスクリプトを作成する
``` /opt/scripts/send-slack-connected-message.sh
SCRIPT_DIR=`echo $(cd $(dirname $0) && pwd)`
/bin/sh ${SCRIPT_DIR}/send-slack-message.sh connect $common_name $untrusted_ip $ifconfig_pool_remote_ip
```
``` /opt/scripts/send-slack-disconnected-message.sh
SCRIPT_DIR=`echo $(cd $(dirname $0) && pwd)`
/bin/sh ${SCRIPT_DIR}/send-slack-message.sh disconnect $common_name $untrusted_ip $ifconfig_pool_remote_ip
```
```
URL="<Incomming WebhooksのURL>"
#BGCOLOR="gray"
MESSAGE=""
if [ "$1" = "connect" ]; then
        #BGCOLOR="yellow"
        MESSAGE="VPN: $2 is connected.\nClient-IP: $3\nVPN-IP: $4"
fi
if [ "$1" = "disconnect" ]; then
        #BGCOLOR="green"
        MESSAGE="VPN: $2 is disconnected.\nClient-IP: $3\nVPN-IP: $4"
fi
curl -H "Content-Type: application/json" \
     -X POST \
     -m 5 \
     -d "{\"text\": \"$MESSAGE\" }" \
     $URL &
```
### 3. server.confに設定を追加する
```/etc/openvpn/server.conf``` に以下の設定を追加します。
```
client-connect /opt/scripts/send-slack-connected-message.sh
client-disconnect /opt/scripts/send-slack-disconnected-message.sh
```
WPF の Text Box に Hint Text を付ける方法

余計なコントロールを使用しない、シンプルな方法。
「How can I add a hint text to WPF textbox?」
https://stackoverflow.com/questions/7425618/how-can-i-add-a-hint-text-to-wpf-textbox

```C#
<TextBox>
    <TextBox.Style>
        <Style TargetType="TextBox" xmlns:sys="clr-namespace:System;assembly=mscorlib">
            <Style.Resources>
                <VisualBrush x:Key="CueBannerBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
                    <VisualBrush.Visual>
                        <Label Content="Search" Foreground="LightGray" />
                    </VisualBrush.Visual>
                </VisualBrush>
            </Style.Resources>
            <Style.Triggers>
                <Trigger Property="Text" Value="{x:Static sys:String.Empty}">
                    <Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
                </Trigger>
                <Trigger Property="Text" Value="{x:Null}">
                    <Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
                </Trigger>
                <Trigger Property="IsKeyboardFocused" Value="True">
                    <Setter Property="Background" Value="White" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </TextBox.Style>
</TextBox>
```
Amazonをスクレイピング、マーケティング効率をパワーアップ！

　[Webスクレイピング](https://www.scrapestorm.com/jp/)と言えば、思わずWeb内容をスクレイピングして偽オリジナルに発表するとか、個人アカウントをスクレイピングしてネットマーケティングするなどを連想しています。実際、これまでデータ収集技術の開発が適用されてきましたが、多くの企業の概念は依然として最も原始的な印象にとどまっています。古い概念は、データ収集技術に対する非常に大きな誤解があるため、データ収集の価値は常に過小評価されています。
　今回はAmazonを例として、経営者にとってデータ収集とビッグデータ適用の意味を紹介します。
###1.消費者の好みを掘り起こす
　ユーザさんの好みを調査するため、ほどんどの経営者は一部のサンプルを抽出して分析します。サンプルの抽出にはデータ数が足りないの原因で、偶に消費者の好みを完全に表現できない場合があリます。また、現在、情報は非常に急速に普及されており、サンプルデータがリアルタイムであるかどうかも経営者が考慮する重要なポイントです。
　[ScrapeStorm](https://www.scrapestorm.com/jp/)を通じて、より多くのデータ収集及びデータ分析して、消費者の好みをより深く了解できます。消費者のニーズを知ることによってのみ、経営者は市場の方向性をよりよく把握できます。
　例えば、Amazonの商品レビュアー、買主の地域などの公開情報を分析して、自分の商品の理想的な販売エリア、商品の不足などを把握でき、目安を付けて、消費者に正確な情報を提供します。マーケティング効率を大幅に改善します。
Amazonをスクレイピングの詳細については、[ここをクリック](https://www.scrapestorm.com/jp/tutorial/how-to-scrape-data-from-amazon-2/)してください。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/e635556a-6e31-c865-54f0-526bf2bdaeba.png)

###2.相手の情報を把握する
　敵を知り己を知らば、百戦危うからずということわざがあります。只今、各業界の競争は段々激しくになります。ビッグデータの収集と分析には、相手の動きを把握すれば先制できます。広告配信、市場シェアの配分などに役立ち、優れたデータ分析は、業界を導くことができます。
Amazonで同類商品情報を収集して、商品の価格、デザインなどによって、経営している商品を改善できます。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/b752e7d9-4c0f-90a7-cdf1-b92c73fd75c0.png)

###3.人気のホットトピックスをマスターする
　流行りを乗るのは非常に有効的なマーケティング手段です。但し、ニュースを見るだけのは全然足りないでしょう。Twitterなどのソーシャルメディアをスクレイピングして、人々は今何を夢中しているのがさっぱり分かります。現在の流行りをつかむことは、会社の宣伝に大きく助けることができます。

　Amazonのマーケティングにはデータの把握が欠かせないです。ScrapeStormは、人工知能を基づき、プログラミングしなくても、ほとんどのWebサイトからデータを抽出できると言うWebスクレイピングツールとして必ずデータ収集に役立ちます。
【tomcat】tomcatをインストール&起動させ、コマンドファイルを作成する(.command) for Mac

# 概要
macでtomcatをインストールして起動するに2種類を試した。
1)Apache Tomcatからダウンロード
2)Homebrewを使用してインストール

1)だと環境設定がめんどくさくなったので
2)でインストール試した。

インストール後、起動コマンド作成した。

# Homebrew を使用して tomcat をインストールして起動する
ターミナルを開き以下のコマンドを打つ

``` ruby:ターミナル
// インストール
brew install tomcat

// tomcatの起動
brew services start tomcat
```

http://localhost:8080/ で起動されているか確認。
画像のように開けば完了！
![Screenshot_2019-10-15 Apache Tomcat 9 0 27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197404/8f0c73bc-a445-af51-3af6-ca07e75fb453.png)

# tomcat起動 コマンド作成
毎回コマンド打つのが面倒くさいので、
コマンドファイルを作成して、ワンタップで起動させる。
※ ``cd 任意のファイル``で移動して、``sh tomcat.command``でも起動する

``tomcat.command``のファイルを作成する
以下の内容を記載する

``` ruby:tomcat.command
#!/bin/sh
echo '==== 実行結果 ===='
brew services start tomcat
echo '==== 実行完了 ===='
```


## ＠参考
- [【tomcat - macで設定する方法】](https://qiita.com/okapie/items/f3d66552bc1533e7af44)
- [Homebrewを使ってMacにtomcatをインストール&起動する](https://reasonable-code.com/homebrew-tomcat/)
Vagrant + VisualStudioCode + PHPでデバッグ環境構築

類似する記事はゴロゴロしてますが仮想環境をかましてるお陰でけっこうハマったので備忘に...
詳しい仕組みは[こちら](https://qiita.com/xanagi/items/b127ed3e5476cfd8eda7)がとても参考になります。

# 環境
MacOS　10.12.6
VirtualBox　6.0.12 
Vagrant　2.2.5
PHP　7.1.32
VSCode　1.38.1
PHP Debug　1.13.0

# 手順
- VSCodeにPHP Debugをインストール
- Vagrant側のXdebugを設定
 - sshでログインし、Xdebugをインストールする
 - 自分の場合、 `/etc/php.d/15-xdebug.ini`に以下を設定

```
xdebug.default_enable = 1
xdebug.remote_autostart = 1
xdebug.remote_connect_back = 0 // 無効にする
xdebug.remote_enable = 1
xdebug.remote_host = "10.0.2.2" // VagrantのNATアダプタのデフォルトゲートウェイ
xdebug.remote_port = 9000
```
- VSCode側のデバッガの設定
 - `vscode/launch.json`は以下のようにした

```
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for XDebug",
            "type": "php",
            "request": "launch",
            "port": 9000,
            "log":true,
            "pathMappings": {
                "/var/www/html/HogeProject": "${workspaceRoot}"  // 左：ゲストOSのパス、右：ホストOSのパス（VSCodeを開いてるプロジェクトルート）を一致させる
            }
        },
        {
            "name": "Launch currently open script",  // こっちは今回関係ない
            "type": "php",
            "request": "launch",
            "program": "${file}",
            "cwd": "${fileDirname}",
            "port": 9000
        }
    ]
}
```

以上！
VS CodeでJupyter Notebookを扱う方法（インストール + 使用方法 + 便利機能）

# はじめに
先日、VS CodeからJupyter Notebookが扱えるようになりましたので、その方法を記載しています。

Working with Jupyter Notebooks in Visual Studio Code
https://code.visualstudio.com/docs/python/jupyter-support

# 準備
Pythonエクステンションのインストールが必要です。
左側のExtensionsアイコンを選択し、検索ボックスに`python`と入力し、Microsoftが提供している`Python`を選択し、Installを押します。
（私の場合はインストール済みなので画面上はUninstallと表示されていますが、インストールされていない方はここがInstallになっています）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402872/4269b4c3-1365-f220-d67d-861c3c37c0c5.png)

# 既存のipynbを開く
ipynbファイルを開くだけです。
これでJupyter Notebookと同じ操作ができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402872/fd59af5e-8794-e638-839a-de9dc83cf223.png)

# 新規にipynbを作成する
VS Code上からNew Fileを選択し、ファイルの拡張子を`ipynb`にするだけです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402872/ac94d9ff-fd34-13fa-06b5-86fe11ea3e57.png)

# 便利な機能
## 変数の中身の表示
セルを実行後に、変数の中身を表示することができます。
表示方法は、セルを実行したあと、画面上部の赤枠をクリックするだけです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402872/d62d563d-ada7-8cb2-415c-df78fce31a0c.png)

## デバッグ
デバッグもできますが、Pythonファイルとしてエクスポートする必要があるのでちょっと面倒です。
まず画面上部の赤枠をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402872/f7fddc51-f9c7-8741-8331-1216655869c9.png)

Pythonファイルとしてエクスポートされた画面が表示されます。
この画面で、Command Palette (⇧⌘P) からPython: Debug Current File in Python Interactive Windowを選択してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402872/032f9aa2-303d-02df-4994-c34b3c541406.png)

ファイル保存を求めるポップアップが表示されますので適当な名前で保存してください。
その後、以下の画面が表示されます。
画面上部の赤枠（Disconnect）をクリックしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402872/ac89e410-edb9-b264-e6d3-1569932130d6.png)

次に適当なところにブレークポイントを設定します。
そして画面上部の赤枠をクリックしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402872/cac2e379-4dff-875f-963d-4a088c1b9087.png)

あとはいつも通りのデバッグができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402872/39ac45ab-1516-bdc7-4bb7-1c2299516b36.png)

## ショートカットキー
ざっと試したところJupyter Notebookでよく使うようなショートカットキーも使えますし、もちろんマークダウン表記もできました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402872/8767b667-3d4e-980a-3352-b1d5586dddc4.png)

## グラフ描画
もちろんグラフも描画できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402872/d09fa7ca-74b7-a6cc-d3a1-5c9dc9918894.png)
CentOS7のeasy-rsaが3.0.6にバージョンアップされてからbuild-client-fullができなくなった場合の対応方法

## はじめに
OpenVPNのために、久しぶりにeasy-rsaでクライアント証明書を作成しようとしたら、次のエラーが出ました。

```
# ./easyrsa --ns-cert=YES build-client-full hoge.fuga nopass

Easy-RSA error:

EASYRSA_PKI does not exist (perhaps you need to run init-pki)?
Expected to find the EASYRSA_PKI at: /usr/share/easy-rsa/3/pki
Run easyrsa without commands for usage and command help.
```

このメッセージが表示される理由は、```/usr/share/easy-rsa/3/pki``` ディレクトリ（シンボリックリンクを含む）が存在しないことが原因です。実際にlsしてみると、pkiディレクトリが無いことがわかります。

```
# ls -la
合計 56
drwxr-xr-x 3 root root    77 10月 15 10:37 .
drwxr-xr-x 5 root root    63  8月 31 09:22 ..
-rwxr-xr-x 1 root root 48730  2月  2  2019 easyrsa
-rw-r--r-- 1 root root  4651  2月  2  2019 openssl-easyrsa.cnf
drwxr-xr-x 2 root root    98  8月 31 09:22 x509-types
```

しかし、これまでOpenVPNを運用していた場合、pkiディレクトリが無いということはありえません（どこかにあります）。したがって、復旧することは可能ですので、焦る必要はありません。とりあえず復旧を進めることにします。

※ **間違っても```easyrsa init-pki```はしないように！！** pkiディレクトリが存在しない状態では無害＆pkiディレクトリが存在している状態で間違って実行してもWARNINGが出ますので、そこで踏みとどまれば実害ありませんが、それを無視して実行すると、pkiディレクトリの内容（これまで発行した証明書等）が初期化されます。


## 手順
### 1.pkiディレクトリをバックアップする
pkiディレクトリは、```/etc/openvpn/pki```に存在するものとします。

```
# cd /etc/openvpn/pki
# cp -Rfp pki pki.bak
```

### 2.以下のディレクトリへ移動する
なお、以後の手順では、特記無い限り、同じディレクトリで作業を進めることとします。

```
# cd /usr/share/easy-rsa/3/
```

### 3.pkiディレクトリへのシンボリックリンクを作成する

CentOS7の場合、easy-rsaがバージョンアップされると、```/usr/share/easy-rsa/```以下に新たなバージョン用のディレクトリが作成されます。

```
# ls -la
合計 4
drwxr-xr-x   5 root root   63  8月 31 09:22 .
drwxr-xr-x. 98 root root 4096  9月 19 05:09 ..
drwxr-xr-x   3 root root   83  1月 26  2018 2.0
lrwxrwxrwx   1 root root    5  8月 31 09:22 3 -> 3.0.6
lrwxrwxrwx   1 root root    5  8月 31 09:22 3.0 -> 3.0.6
drwxr-xr-x   3 root root   29  8月 31 09:22 3.0.3
drwxr-xr-x   3 root root   77 10月 15 10:37 3.0.6
```

しかし、旧バージョンのディレクトリ上に作成されたファイルやディレクトリ、シンボリックリンクは引き継がれません。

私の場合は、/etc/openvpn/pkiへのシンボリックリンクを作成していましたので、新しいディレクトリへシンボリックリンクを作成しました。

```
# ln -s /etc/openvpn/pki
```

### 4. openssl-easyrsa.cnfをpkiディレクトリへコピーする

```
# cp -p /usr/share/easy-rsa/3/openvpn-easyrsa.cnf .
```

### 5. pkiディレクトリ以下にディレクトリを作成する

revokedディレクトリを作成し、その階層下にcerts_by_serial, private_by_serial, reqs_by_serial ディレクトリを作成します。また、revokedと同じ構成のディレクトリとして、renewedディレクトリを作成します。

```
# mkdir revoked
# chmod 700 revoked
# cd revoked
# mkdir certs_by_serial
# mkdir private_by_serial
# mkdir reqs_by_serial
# chmod 700 *
# cd ..
# cp -Rp revoked renewed
```

### 6.easy-rsa build-client-fullを実行する

```/usr/share/easyrsa/3``` ディレクトリへ移動し、```easyrsa build-client-full```を実行すると、以下のようにエラーなく進むようになります。以後は、

```
./easyrsa --ns-cert=YES build-client-full hoge.fuga nopass

Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017
Generating a 2048 bit RSA private key
...............................................................................
.....
writing new private key to '/usr/share/easy-rsa/3/pki/private/hoge.fuga.key.xxxxxxx'
-----
Using configuration from /usr/share/easy-rsa/3/pki/safessl-easyrsa.cnf
Enter pass phrase for /usr/share/easy-rsa/3/pki/private/ca.key:
```

## 参考

- https://bbs.archlinux.org/viewtopic.php?id=244380
Linux基礎(システム時刻の維持)

#ハードウェアクロックとシステムクロック
##ハードウェアクロック
ハードウェアとして内蔵された時計のことで、システム停止にしてもハードウェア状の内蔵バッテリーで動作する。
##システムウェアクロック
メモリ状で動作する時計のことを指す。電源がONになる度にハードウェアクロックから現在の日時を取得して値を設定する。`date`ではシステムクロックを参照し、現在の日時を表示する。

#クロック確認コマンド


システムクロック
date [MMDDhhmmCCYY.ss]

|書式|コマンド|
|MM|月|
|DD|日|
|hh|時|
|mm|分|
|CC|西暦上2桁|
|YY|西暦下2桁|
|SS|秒|

ハードウェアクロック
hwclock [オプション]

|オプション|説明|
|---|---|
|-r|ハードウェアクロックの表示|
|-s (--hctosys)|ハードウェアクロックの時刻をシステムクロックに反映|
|-w (--systohc)|システムクロックの時刻をハードウェアクロックに反映|
|-u|UTC(Universal Coordiated Time)として反映|

#NTPによる時刻設定
ハードウェアクロック、システムクロック共に完全に正確な時刻情報という訳ではない。正確な時刻を取得するためにはインターネットなどのIPネットワーク経由でクロック同期を行うプロトコルであるNTP(network time protocol)を使用して正確な情報を得る。NTPは階層構造になっており、最上位は原子時計やGPSなどが位置して、その直下にあるNTPサーバをStratum1、その下をStratum2と呼ぶ。

![](https://www.infraeye.com/study/gif/lpic67.gif)

ntpdateを使用してNTPサーバーから正確な時刻情報を取得する。
構文：ntpdate [NTPサーバー名]

```shell
# NTPサーバー(ntp.nict.jp)から時刻を取得する
ntpdate ntp.nict.jp

# LinuxサーバーをNTPサーバーとして構築するためには、以下コマンドでNTPサーバーを起動できる。
/etc/init.d/ntpd start

# NTPサーバーの設定は、/etc/ntp.confで行う
more /etc/ntp.conf
server 0.centos.pool.ntp.org
server 1.centos.pool.ntp.org
server 2.centos.pool.ntp.org
```
firebase HostingへReactアプリをビルドしてデプロイするまでを1クリックで

## 経緯

`create-react-app`から作成したWebアプリをFirebase Hostingにデプロイして公開しています。
ビルドせずにデプロイしてあれおかしいと時間を浪費することが多々あったので表題の件、考えました。

## 解決策
package.jsonの`scripts`に下記を追加するだけ。

```json:package.json
  "scripts": {
    "deploy": "npm run build && firebase deploy",
    ...
  },
```

VSCodeだと左下にnpmコマンドを1クリックで実行するショートカットが用意されているので、これでデプロイのためにシェルを開くことも必要なくなります。

![npmcommand-on-vscode.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299625/5f0a55db-ade2-e3fc-ff82-740c97c46c1b.png)

Github Actionsでも利用できるので、package.jsonの`scripts`は積極的に有効活用していきたい！
ローマ字の種類

タイピングシステムを開発時に日本語をローマ字に変換する必要があり、手順を調べているとローマ字の種類というものに遭遇。

どの変換方式を取るかで、ローマ字の綴りが変わるのでメモしておく。

厳密にはも他にも種類があるが、システム開発において使用されるであろうローマ字の種類に焦点を絞っています。

## 代表的なローマ字の種類
- 訓令式
    - 国際標準化機構（ISO）が正式に採用した日本語のローマ字、ISO3602
    - 日本の小学校で教えられている形式は訓令式
- ヘボン式
    - パスポートなど公的な身分証明書で使われる日本語のローマ字

### 変換のちがい
訓令式

```
メロン
meron
メロンパン
meronpan
あんぱん
anpan
```

ヘボン式

```
メロン
meron
メロンパン
merompan
あんぱん
ampam
```

日本人にはヘボン式は違和感があるかも。
新人向けチートシート: git

##自分のcommitをpull requestするまで
```
git pull #ローカルリポジトリを最新化
git checkout -b <branchName> #ブランチの作成と移動
#ファイルを編集

git status #編集したファイルを確認
git add . #"."はカレントディレクトリ以下のファイルを全てadd
#git add -p ファイル名 #改変範囲が多い場合はpオプションでブロック単位でステージング
git commit -v
git push -u origin <newRemoteBranchName>
#GUIでファイル差分をもう一度確認してからプルリクエスト
```

# コミットの差分を確認したい
```
git diff #差分を確認
git diff --word-diff-regex="\w+" #文字単位での差分を確認
```

##リモートのBranchをローカルにcheck outする
```
git checkout -b <newLocalBranchName> <remoteBranchName>
```

##間違えてaddした
```
git status #addしたファイルを確認
git reset HEAD <fileName>
```

##間違えてcommitした
###commitを取り消す
####ファイルの変更を取り消す
```
git status #commitを確認

git reset --hard HEAD^
```
####ファイルの変更を取り消さない
```
git status #commitを確認
git reset --soft HEAD^
```
###コミットを上書きする
```
git status #commitを確認
#ファイルを編集
git add <filename>
git commit --amend #push済みのcommitには実施しない
```

##間違えてpushした
###自分しか作業しないBranchの場合
```
git reset --hard HEAD^
git push -f #commitを強制的に上書きするので、他の人も作業している場合commit履歴がバグる可能性があるので実施しない
```

###他の人もいるBranchの場合
```
git log #commit idを確認
git revert <commitId> #打ち消しcommitを作成
```

##pull requestが競合した
```
git checkout <yourWorkingBranchName> #作業中のBranchに移動
git pull #ローカルリポジトリの最新化
git rebase master #マスターブランチの最新commitに、作業ブランチの派生commitを植え替え
git status #競合状況を確認
#ファイルを編集
git add <fixedFileName> #競合ファイルを編集
git rebase --continue #rebaseを進める。コマンドの指示に従い、addとrebaseを繰り返す
git push #remoteにpushする
```

##Branchで作業中に別のBranchでの作業を頼まれた
```
git stash save <yourComment> #変更内容を一時保存
git stash list #保存されたか確認
git checkout <otherBranchName> #別のBranchに移動
#別のブランチでの作業完了
git checkout <originalBranchName> #元のBranchに戻る
git stash pop #変更内容を戻す
```

##コミットを整理したい(上級者向け)
```
git rebase -i #表示される画面をよく読んでから使いましょう
```

###新人向けチートシート
* [vim](https://qiita.com/taisukek/items/37dac57fd3332fa2beb1)
* [terminal](https://qiita.com/taisukek/items/673103c19cec398e81bc)
GCPのファイアーウォールは

###Fｘｘｘ

・ファイアーウォールの設定ページが深い場所にある
・デフォルト[すべてに適用]とかやめてほしい
・ファイアーウォールの名前にもルール名にも大文字、ハイフンが使えず、視認性の良いルール名がつけられない
　名前とルール名2ついるか？わけたらごちゃごちゃなるだろ
・ファイアーウォールにディスクリプション書けるけど、VMIから見えない
・ターゲットタグはプルダウンにしろや
・一覧にソースフィルタ表示しろや
・ソースタグは内部のインスタンスだけ。なんで作れないんだよ。動的IPの変更つらいだろ。

### DBにしても
・DB(SQL)のプライベート接続がごちゃごちゃ書いてて初心者には、なんのこっちゃわからずパブリック接続を選択させていることが多い!

### といやいやいってもしょうがないので、

①命名ルールは、%action%-from-%source name%-%protocol%にする。
例えば、allow-from-tokyo-branch-ssh

名前からルールがわかるようにして、VMIからみたときにルールがわかるようにする。
なお、toがないのは、無駄にルールを増やさない為と、VMIから見ればそれがtoになる為。
	
②複数のルールをまとめない。1ルール、1フロー(from source protocol)を定義する。
	理由1: まとめてしまうと、細かい修正がしずらい。切り離なす場合、サービス停止が必要となる場合が考えられる為。
	理由2: 編集ミスを低減する為
	理由3: 複数のルールをまとめると名前も抽象的な名前にせざるを得ない。それによりVMIからルールの内容が見えずらくなり、必要ないルールが放置される可能性を低減する為。
	
	
②名前とターゲット名は同じ名前とする
これが、わけられているのは複数のルールを、1つのターゲットにまとめる為と思われる。
これも①の理由から排除したい為、そのような利用はさけること。
Linux基礎(ネットワーク基礎)


#基本的なプロトコルを理解するためのリンク
[ネットワーク｜TCP/IP](https://qiita.com/kakkie/items/ac201ecd642d2e3a7b99)
[ネットワーク｜ICMP](https://qiita.com/kakkie/items/e3ba32c13d10b1346ad6)
[ネットワーク｜IPv4/IPv6](https://qiita.com/kakkie/items/72b6317b07637896b8e2)

#一般的なTCP・UDPポート番号

|ポート番号|プロトコル|サービス|説明|
|---|---|---|---|
|20|TCP|FTP|FTP:データ伝送|
|21|TCP/UDP|FTP|FTP:制御情報|
|22|TCP|ssh|ssh接続|
|23|TCP|telnet|telnet接続|
|25|TCP/UDP|SMTP|電子メール(送信)|
|53|TCP/UDP|DNS|名前解決|
|80|TCP|http|Web接続|
|110|TCP|POP3|電子メール(受信)|
|119|TCP|NNTP|ネットニュース|
|139|TCP/UDP|NetBIOS|Microsoftネットワーク|
|143|TCP|IMAP|電子メール(受信)|
|161|TCP|SNMP|ネットワーク監視|
|443|TCP|https|SSLによるHTTP接続|
|465|TCP|SMTPS|SSLによるSMTP接続|
|993|TCP|IMAPS|SSLによるIMAP接続|
|995|TCP|POP3S|SSLによるPOP3接続|
外部データ連携用のスクリプトで考慮すべき点

#外部データ連携用のスクリプト
外部のサブシステムとデータ連携する際に、SFTP、FTPといった方式でよくデータファイルの授受を行うことがあるため、こういった類のスクリプト（プログラム)を組み際に入れ込んでおいた方がよいと思われるロジックや設計上の考慮点をまとめる。

##Case別

###受信時&他の場所に退避時

- __引数チェック処理__
 - スクリプトに渡す引数の数のチェック
 - スクリプトに渡す引数の妥当性のチェック

- __ディレクトリの存在チェック処理__
 - 受け取り先になるディレクトリがローカルに存在するかどうかのチェック

- __連携ファイルの有無確認__
 - whileループで暫くファイル連携されているかどうかを確認する。

- __連携ファイルの個数確認__
 - 連携ファイルの個数確認。0個だとwhileループ継続。1個だとOKのような。2個以上はNG。

- __連携ファイルのサイズの固定化確認__
 - 連携ファイルのサイズが直前のループと同じであることを確認し、送信中でないことの担保を取る。
  
- __送達確認ファイルの有無確認__
 - whileループで暫く送達確認が連携されているかどうかを確認する。

- __送達確認ファイルの個数確認__
 - 送達確認ファイルの個数確認。0個だとwhileループ継続。1個だとOKのような。2個以上はNG。

- __送達確認ファイルのサイズの固定化確認__
 - 送達確認ファイルのサイズが直前のループと同じであることを確認し、送信中でないことの担保を取る。

- __退避先での上書きNG確認__
 - 退避先をlsするなどしてファイルが上書きされないことを確認する。

- __退避先へとファイルをmoveする__
 - 退避先へ連携ファイル・エンドファイルをmove

- __受信先からファイルが削除されているかどうかを確認する__
 - ファイルの有無確認。moveされて無い想定のため無ければOK

###送信時




##方式別
###FTP




###SFTP






###Tips: SCPとSFTPの違い
【jQuery】様々な用語についてまとめてみた(jQueryオブジェクト編)

# はじめに
jQueryの学習を始めると必ずといっていいほどでてくる理解が深まらない単語の山。
「なんとなくはわかるけど説明できるほど理解が・・・」という方も多いはず。

私もその一人です・・・。

しかしアウトプットしないと自分の頭に定着しないので
あえて説明させてください！

その中で今回はよく出てくる単語**『jQueryオブジェクト編』**で進めていきます。

# jQueryオブジェクトとは？
jQueryオブジェクトとは簡単に言いますと

**jQueryメソッドをつかえるようにしたDOM要素**

はい出てきましたまた新しい用語。
jQueryメソッドとかDOM要素ってなんですか・・・

参考書とかだとこの新しい用語が当たり前のように使われるので
初心者の僕にはきつかった。

jQueryメソッドとDOM要素についてはまた違う記事でまとめようと思いますが、
軽く説明だけさせてもらいます。

----

###jQueryメソッド
例えば

**HTML**

```html

<p>背景の色を変えます</p>
```
**jQuery**

```javascript
$(function(){
 $('p').css("background-color", "red")
});
```

上の処理はp要素の背景の色を変えるコードです。
実際に処理を加えるのは.cssの部分です。

このように、あるものに対して操作を行うものがメソッドです。

--------

###DOM要素
HTMLの要素はそのままではJavaScript内で使うことができません。
なのでJavaScriptで直接操作ができるように変換したものを
DOM要素と言います。

--------

さて本筋にもどりますが、先ほどにも書いていた通りjQueryオブジェクトとは
『jQueryメソッドを使えるようにしたDOM要素』

言い換えると
**『DOM要素に対して.cssや.textなどのjQuery独自のメソッドを使うには
jQueryオブジェクトに変換しないと使えないよー』**
ということになります。

# 実際どうやって使うの?
jQueryについてある程度わかってもらえたら幸いです。

さて次はどう使っていくかなんですが、
これはとても簡単です。
先ほどのコードを例に挙げると・・・

**HTML**

```html

<p>背景の色を変えます</p>
```
**jQuery**

```javascript
$(function(){
 $('p').css("background-color", "red")
});
```
先ほどと同じようにp要素の背景色を赤色に変えるコードです。

jQueryオブジェクトは$(セレクター)の部分になります。

今回はp要素に対して.cssメソッドを使いたいので
$('p')という形になります。

IDを指定する場合、クラスを指定する場合も同じです。

-------

###IDを指定する場合

**HTML**

```html

<p id="red">背景の色を変えます</p>
```
**jQuery**

```javascript
$(function(){
 $('#red').css("background-color", "red")
});
```

------

###クラスを指定する場合
**HTML**

```html

<p class="red">背景の色を変えます</p>
```
**jQuery**

```javascript
$(function(){
 $('.red').css("background-color", "red")
});
```

-----

今回は.cssメソッドだけを例に挙げましたが他にもjQuery独自のメソッドは多数ありますので
その度にjQueryオブジェクトに変換する必要があります。

#最後に
jQueryに限らずプログラミング学習を続けているとどんどん新しい用語が出てくるかと思います。
最初の内は全然言っている意味がわからないとも思います。

しかしとりあえず先に進めて大体の使い方がわかれば
もう一度最初に戻り用語の意味を読み解くと結構すんなり入るものです。
(私自身も結構そういう事があります。)

ですので復習などをする時にこの記事が少しでもお役に立てればと思います。

誤情報・補足情報などございましたらコメントでどんどんご指摘の方よろしくお願いします！
[chromedriver] Chromeのバージョンを自動取得

# Chromeのバージョンを自動取得

## 背景

* Seleniumでブラウザ操作をするためにchromedriver-binaryを使用したかったが、  
ローカルのGoogleChromeのバージョンによってchromedriver-binaryのバージョンを変える必要があるので  
自動でバージョン判別してインストールできるようにしたのでメモです

## スクリプト

* Windows bat

```
@rem python activate
python -m venv venv
call "venv\Scripts\activate"

@rem find Chrome Version
FOR /F %%i in ('dir /B /O-N "C:\Program Files (x86)\Google\Chrome\Application" ^| findstr "^[0-9].*\>"') do set VERSION=%%i

echo %VERSION%
@if "%VERSION%" EQU "" (
    echo;
    echo Chrome Version Not Found
    PAUSE
    exit /b
)

@ ↓ マイナーバージョンまで一致すれば動くみたいなのでそれ以外切り捨てしてインストール
pip install chromedriver-binary~=%VERSION:~0,4%
```

* bash

```
#!/usr/bin/env bash

# python activate
python3 -m venv venv
source venv/bin/activate

# find Chrome Version
#  ↓ マイナーバージョンまで一致すれば動くみたいなのでそれ以外切り捨て
version=$(ls /Applications/Google\ Chrome.app/Contents/Frameworks/Google\ Chrome\ Framework.framework/Versions/ | sort | grep -v "Current" | tail -n 1 | sed -E 's/(^[0-9]+.[0-9]+).*/\1/g')

if [ -z "$version" ]; then
  echo "Chrome Version Not Found"
  exit 1
fi

# インストール
pip install chromedriver-binary~="$version"
```
Amazon Linuxのdockerイメージで日本語ロケールを有効にする

# まずは結論から

現状Amazon Linux 2とAmazon Linux 1があり、それぞれで日本語ロケールを有効にする方法が異なる。

## Amazon Linux 2

```shell
yum install -y glibc-langpack-ja
```

## Amazon Linux 1

```shell
localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
```

# 検証してみる


## Amazon Linux 2

```shell
$ docker run --rm -it amazonlinux:2 bash
bash-4.2# date
Tue Oct 15 01:10:51 UTC 2019
bash-4.2# yum install -y glibc-langpack-ja > /dev/null
bash-4.2# LANG=ja_JP.UTF-8 date
2019年 10月 15日 火曜日 01:11:02 UTC
```

## Amazon Linux 1

```shell
$ docker run --rm -it amazonlinux:1 bash
bash-4.2# date
Tue Oct 15 01:06:31 UTC 2019
bash-4.2# localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
bash-4.2# LANG=ja_JP.UTF-8 date
2019年 10月 15日 火曜日 01:06:44 UTC
```

# 補足

実際にDockerfileで日本語ロケールに固定したい場合は環境変数の指定も忘れずに

```Dockerfile
ENV LANG ja_JP.UTF-8
ENV LC_ALL ja_JP.UTF-8
```
python venv セットアップメモ

# python venvを自動設定するためのスクリプトを作成したのでメモ

* 既存のプロジェクトを読み込むときに使用する目的で作成しました。
* pythonコマンドでpython3が動くことを前提としている

## Windows bat

* venv作成とpip install

```
cd /d %~dp0

@rem python activate
echo;
python -V
echo;
python -m venv venv
call "venv\Scripts\activate"

@rem dependency
pip install -r requirements.txt
```

## bash

* venv作成とpip install

```
#!/usr/bin/env bash

cd $(dirname $0)

# python activate
python -m venv venv
source venv/bin/activate

# dependency
pip install -r requirements.txt
```
bash におけるSyntax error: Bad for loop variableの改善

## エラーの原因

次のような表記でfor文を書いた場合、上記のエラーが発生する。

```
for (( i=1; i<=$n; i++ ))
do
    ...
    ...
done
```
## 解決策

以下のように変更する。

```
for i in `seq 1 $n`
do
    ...
    ...
done
```
ERROR: error while removing network: network {{NAME}} id {{ID}} has active endpoints

レアケースかとは思いますが、私のようなせっかちな人なら経験あるのではないでしょうか。。。
`docker-compose stop` または`docker-compose down` などしてからプロジェクトファイルを物削しましょ。
でないと、

## dockerのコンテナが上手いこと止めれない
コンテナ止めようかなーなんて軽い気持ちでコマンドを叩きます。

```
$ docker-compose down
WARNING: Found orphan containers {{CONTAINER_NAME}} for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up.
Removing network {{NAME}}
ERROR: error while removing network: network {{NAME}} id {{ID}} has active endpoints
``` 

すぅごい怒られる。

## 結論
`--remove-orphans` オプションを付与してお掃除したらOKでした。

```
$ docker-compose down --remove-orphans
Removing orphan container "{{CONTAINER_NAME}}"
Removing network {{NAME}}
```

## 他にもあるみたいです
私の場合、以下の記事では上手くいきませんでしたが、参考にさせて頂いたサイト様です。
こんな方法もあるみたいなのでまずはこちらを参考にしてみてください。

[docker network rmコマンドの使い方（実例付）CE対応](https://www.memotansu.jp/docker/889/)
AnsibleをPython2.xからPython3.xに対応させる手順とトラブルシューティング

# 概要

いよいよ[Python2.7のサポートが2020.1.1で終了します](https://pythonclock.org/)
このタイミングでAnsibleの実行環境も3.x系に移行いくことになりますので、その手順を残したいと思います

# 手順

1. Python3.xをインストール  
  - 各プラットフォームにあわせてインストールしてください
  
    ```shell:例(Centos)
    > yum install -y python36 python36-pip python36-devel
    ```
  - pip3が使用できることを確認し、pipをアップグレードします  
    pip3ではなく、`pip-3.x`しかない場合は、以下のupgradeコマンドを実行後に`pip3`が使用できるようになります

    ```shell
    > pip-3.x install --upgrade pip
    ```

2. Python3.xのAnsibleをインストール
  - すでにAnsible利用している場合は、まずはPython2.xのAnsibleを削除し、Python3.xのAnsibleをインストールします
  
    ```shell
    > pip uninstall ansible
    > pip3 install ansible
    ```
  - 新規でAnsibleを導入する場合

    ```shell
    > pip3 install ansible
    ```
4. バージョン確認
   下記のように`python version = 3.x`になっていることを確認します

    ```shell
    > ansible --version

      ansible 2.8.5
        config file = /root/.ansible.cfg
        configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
        ansible python module location = /usr/local/lib/python3.6/site-packages/ansible
        executable location = /usr/local/bin/ansible
        python version = 3.6.8 (default, Aug  2 2019, 17:42:44) [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)]
    ```
5. Ansibleが使用するPythonを指定する
   python3は`whereis python3`でpython3コマンドの所在で探しておきましょう
   以下の3つの方法があります
   - `ansible.cfg`の`[defaults]`セクションに`interpreter_python=/usr/bin/python3`を設定します
   - 変数`ansible_python_interpreter=/usr/bin/python3`を設定します
   - 環境変数`INTERPRETER_PYTHON=/usr/bin/python3`を設定します
 
　　以上の設定を行うと**Ansibleが操作するホストもpython3が使用されるようになります**
　　Ansibleの実行環境のみにPython3を適用したい場合は、host_varsもしくはgroup_varsにlocal.ymlを作成し、`ansible_python_interpreter: /usr/bin/python3`を設定しましょう

# トラブルシューティング

以下のエラーが発生した際の対処法を紹介します
また、下記にないエラー等がございましたら、共有して頂ければ追記します！

## AttributeError: module 'enum' has no attribute 'IntFlag'

https://blog.goo.ne.jp/field_light/e/1d6e42b4e9322b5f5546ca89a4e7a7a6

```
> pip3 uninstall enum34
```

# Ansible TowerとAWX

Python3.x用の仮想環境を作成し、AnsibleやそのほかTower/AWXに必要なモジュールなどをインストールしなければならない
デフォルトのパスは`/var/lib/awx/venv/xxx`

[公式手順](https://docs.ansible.com/ansible-tower/latest/html/upgrade-migration-guide/virtualenv.html)と同様に操作していきます

## AWX 6.1.0

AWX6.1.0では上記の公式手順ではうまく設定できなかった。。。

仮想環境のパスは`/var/lib/awx/venv`で、`/var/lib/awx/venv/ansible(python2.x)`、`/var/lib/awx/venv/awx(python3.x)`がそれぞれ設定済みの状態。
AWXのデフォルトの設定では、`/var/lib/awx/venv/ansible`を使用している。
設定画面の`Custom virtual environment paths`に`/var/lib/awx/venv`を設定したが、`/var/lib/awx/venv/awx`(api/v2/config/custom_virtualenvsで確認できる)が検出されず、PATCHしても

```
/var/lib/awx/venv/awx is not a valid virtualenv in /var/lib/awx/venv
```
とエラーが返された。。。

おそらく`/var/lib/awx/venv`以外でvenvを作らないと認識しないのかも？


# 参考

- [Ansible2.8の新機能1 - Interpreter Discovery](https://rheb.hatenablog.com/entry/ansible_interpreter_discovery)
- [[Ansible] 利用する Python をタスクごとに切り替える方法（ansible_python_interpreter をタスク変数で指定）](https://tekunabe.hatenablog.jp/entry/2019/10/04/ansible_python_interpreter)
- [python_3_support](https://docs.ansible.com/ansible/2.4/python_3_support.html)
mtoolsについてのメモ

#mtoolsについてのメモ

###利用環境
>
VirtualBox 6.0.12 platform packages
CentOS-7-x86_64-DVD-1908.iso
>

30日でできるOS自作入門 という本を買って勉強している
[環境の構築(CentOSへNASMインストールはこちら)](https://qiita.com/code2545Light/items/784510f7808c76b55e21)

これの途中で、FATタイプのディスクイメージを作る際、ちょっと調べたメモ

###mtoolsとは
UNIX上でマウントせずにMS-DOSのファイルにアクセスするためのツール郡
 主な情報
  - [Mtools - Wikipedia](https://en.wikipedia.org/wiki/Mtools)
  - [2.2 Drive letters - Mtools 4.0.23](https://www.gnu.org/software/mtools/manual/mtools.html#drive-letters)
  - [mtoolsの使い方が知りたい - ITmedia エンタープライズ](http://www.itmedia.co.jp/help/tips/linux/l0317.html)
  - [mformatのオプション](https://tech.nikkeibp.co.jp/it/article/COLUMN/20060227/230828/)

###主要な使い方
 mformat --helpにて
 -Bがブートセクタの指定
 -f ファイルサイズ
 -C 	MS-DOSファイル・システムを作成する
 -i The drive letter : (colon) has a special meaning. It is used to access image files which are directly specified on the command line using the -i options.
      Example: mcopy -i my-image-file.bin ::file1 ::file2 .

###使用例
以下のような記述をmakefileに記述する。
 FATフォーマットのイメージファイルを作成する。(MayBoot.binの512バイトがブートセクタ)
	mformat -f 1440 -C -B MayBoot.bin -i $@ ::
	
 OS本体をイメージに書き込む
	mcopy -i $@ ${OSNAME}.sys ::
聴牌と不聴の手牌を主成分分析する

# ※この記事は2020年に作成しました
#概要
下記を参考にして、聴牌とそうでない手牌を主成分分析した。
https://qiita.com/maskot1977/items/082557fcda78c4cdb41f

データは、tehai1～tehai13の13個の手牌で、0~33の数字で牌を表している。
データ数は、聴牌の手牌が1855個、不聴の手牌が69097個である。

データの中身の一部
<img width="832" alt="figure6.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436155/951df16c-8725-57d6-f601-ed481dba42a2.png">


#結果・考察
さすがに聴牌のデータ数が少なすぎるので聴牌の特徴はほとんど捉えらえていない。
ただ、第一主成分と第二主成分における観測変数の寄与度をプロットしたものは綺麗な弓形になっているので気持ちが良い。

#散布図行列
![Figure_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436155/a0dfeb6c-00ae-fbdf-21f8-cfdffa2633de.png)

#第一主成分と第二主成分の散布図
![Figure_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436155/68029b62-f968-b474-b10b-ca02238d08be.png)

#各主成分の散布図行列
![Figure_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436155/a5e4e062-0a53-e69f-43b9-75ff48b2afe5.png)

#累積寄与率をプロット
![Figure_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436155/d1baddf6-7c9f-8c8f-2205-06ca19b8e02c.png)

#第一主成分と第二主成分における観測変数の寄与度をプロット
![Figure_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436155/374fe4e7-c255-bc5f-49fd-b04bf95a18a7.png)

#作成したプログラム

```python
import numpy as np
import pandas as pd
import urllib.request 
import matplotlib.pyplot as plt
import sklearn #機械学習のライブラリ
from sklearn.decomposition import PCA #主成分分析器
from pandas import plotting 
import matplotlib.ticker as ticker

df = pd.read_csv("C:/sqlite/PCA_tenpai.csv", sep=",")
#print(df.head())
#print(df.index)
"""散布図行列
plotting.scatter_matrix(df.iloc[:, 1:], figsize=(8, 8), c=list(df.iloc[:, 0]), alpha=0.5)
plt.show()
"""

# 行列の標準化
dfs = df.iloc[:, 1:].apply(lambda x: (x-x.mean())/x.std(), axis=0)

#主成分分析の実行
pca = PCA()
feature = pca.fit(dfs)
# データを主成分空間に写像
feature = pca.transform(dfs)
#主成分得点
pd.DataFrame(feature, columns=["PC{}".format(x + 1) for x in range(len(dfs.columns))]).head()

"""# 第一主成分と第二主成分でプロットする
plt.figure(figsize=(6, 6))
plt.scatter(feature[:, 0], feature[:, 1], alpha=0.8, c=list(df.iloc[:, 0]))
plt.grid()
plt.xlabel("PC1")
plt.ylabel("PC2")
plt.show()
"""

"""各主成分の散布図行列
plotting.scatter_matrix(pd.DataFrame(feature, 
                        columns=["PC{}".format(x + 1) for x in range(len(dfs.columns))]), 
                        figsize=(8, 8), c=list(df.iloc[:, 0]), alpha=0.5) 
plt.show()
"""

"""累積寄与率
plt.gca().get_xaxis().set_major_locator(ticker.MaxNLocator(integer=True))
plt.plot([0] + list( np.cumsum(pca.explained_variance_ratio_)), "-o")
plt.xlabel("Number of principal components")
plt.ylabel("Cumulative contribution rate")
plt.grid()
plt.show()
"""

"""# 第一主成分と第二主成分における観測変数の寄与度をプロットする
plt.figure(figsize=(6, 6))
for x, y, name in zip(pca.components_[0], pca.components_[1], df.columns[1:]):
    plt.text(x, y, name)
plt.scatter(pca.components_[0], pca.components_[1], alpha=0.8)
plt.grid()
plt.xlabel("PC1")
plt.ylabel("PC2")
plt.show()
"""
```