OmniAICreator/Qiita-1.07M huggingface dataset:
ハンバーガーメニュー

#はじめに
サイトのレスポンシブに伴ってハンバーガーメニューを実装してみました。
#コード
```js
$(function(){
	$(".btn-gnavi").on("click", function(){
		var rightVal = 0;
		if($(this).hasClass("open")) {
			rightVal = -300;
			$(this).removeClass("open");
		} else {
			$(this).addClass("open");
		}

		$("#global-navi").stop().animate({
			right: rightVal
		}, 200);
	});
});
```
JavaScript

```css
.btn-gnavi {
    position: fixed;
    top: 3vw;
    right: 4vw;
    width: 30px;
    height: 24px;
    z-index: 3;
    box-sizing: border-box;
    cursor: pointer;
    -webkit-transition: all 400ms;
    transition: all 400ms;
}

.btn-gnavi span {
    position: absolute;
    width: 30px;
    height: 4px;
    background: black;
    border-radius: 10px;
    -webkit-transition: all 400ms;
    transition: all 400ms
}

.btn-gnavi span:nth-child(1) {
    top: 0;
	margin-left: 5px;
}

.btn-gnavi span:nth-child(2) {
    top: 10px;
	margin-left: 5px;
}

.btn-gnavi span:nth-child(3) {
    top: 20px;
	margin-left: 5px;
}
.btn-gnavi span:nth-child(4) {
	display: inline-block;
    top: 20px;
	position: absolute;
    width: 0;
    height: 0;
    transition: all 400ms;
	white-space: nowrap;
	color: #ad9258;
}
.btn-gnavi.open {
    -webkit-transform: rotate(180deg);
    transform: rotate(180deg)
}
.btn-gnavi.open span:nth-child(4) {
    display: none;
}
.btn-gnavi.open span {
    background: #fff;
}
.btn-gnavi.open span:nth-child(1) {
    width: 24px;
    -webkit-transform: translate(-7px,17px) rotate(45deg);
    transform: translate(-7px,17px) rotate(45deg)
}

.btn-gnavi.open span:nth-child(3) {
    width: 24px;
    -webkit-transform: translate(-7px,-17px) rotate(-45deg);
    transform: translate(-7px,-17px) rotate(-45deg)
}
```
css

#まとめ
ハンバーガーメニューを実装することで、スマホ画面のように
小さい画面でも見せたいメニューの表示場所を十分に確保できることがわかりました。
また、三本線だけだとわかりずらいので、三本線の下に『menu』と表示させ、メニューが収納されていることがユーザーに伝わるように工夫してみました。
Next.jsでfirebaseのinitializeAppを実行する方法

#必要なモジュールをインストールする

firebaseとdotenvをインストールします。
dotenv関連の設定方法は[こちら](https://qiita.com/MASA-JAPAN/items/7ea7c88eb89d92a92eed)

```
npm i firebase dotenv-webpack
```
#.envファイルを作成し、firebaseの認証情報を入力

以下のような感じになります。

```env:.env
  FIREBASE_API_KEY=************************************
  FIREBASE_AUTH_DOMAIN=**********************
  FIREBASE_DATABASE_URL=*********************************
  FIREBASE_PROJECT_ID=*****************
  FIREBASE_STORAGE_BUCKET=*************************
  FIREBASE_MESSAGEING_SENDER_ID=***********
  FIREBASE_APP_ID=***********************************************
```
#initializeApp実行処理を書く

libフォルダを作成し、その中にfirebaseInit.js（処理用ファイル）を作成すれば良いと思います。

```JavaScript:firebaseInit.js
import firebase from "firebase";

const firebaseConfig = {
  apiKey: process.env.FIREBASE_API_KEY,
  authDomain: process.env.FIREBASE_AUTH_DOMAIN,
  databaseURL: process.env.FIREBASE_DATABASE_URL,
  projectId: process.env.FIREBASE_PROJECT_ID,
  storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.FIREBASE_MESSAGEING_SENDER_ID,
  appId: process.env.FIREBASE_APP_ID
};

if (!firebase.apps.length) {
  firebase.initializeApp(firebaseConfig);
} else {
  firebase.app();
}

export default firebase;
```
#使いたいファイルでインポートする

あとは、firebaseInit.jsをインポートしてくるだけです。
これでfirestoreなどの機能が使えます。

```JavaScript:index.js
import firebase from "../lib/firebaseInit";

firebase
  .firestore()
  .collection("hogehoge")
  .get();

export default () => (
  <div>
    <div>Hello World</div>
  </div>
);

```
Firebase Hostingでデプロイする際の事故を防ぐ

# TL;DR  
firebaseのhostingで`firebase deploy`をするとそのままデプロイされるのを防ぐためにシェルを噛ませる。  

# やりたかったこと  
一つのfirebaseプロジェクトで、ステージング、プロダクションの２環境へホスティングしたい。  
この際`firebase deploy`を実行するとステージング、プロダクション両方にファイルが上がってしまうため、念の為一度確認をさせてから実行させる。  

# やったこと  
`firebase.json`を以下のようにそれぞれ設定します。
https://firebase.google.com/docs/hosting/multisites を参考に連想配列で定義。  

```firebase.json  
hosting: {[
  {
    "public": "public",
    "site": "staging",
    ...
  },
  {
    "public": "public",
    "site": "production",
    ...
  },
]}
```  

`package.json`にそれぞれデプロイコマンドを定義します。  

```package.json  
{
  "scripts": {
    "deploy" : "firebase deploy --only hosting:production",
    "deploy-stg" : "firebase deploy --only hosting:staging"
  }  
}
```  

本来npmコマンドを忠実に実行すれば両方のサイトにファイルが上がることはないのですが、`firebase deploy`を実行すれば両方の環境にファイルが上がってしまいます。  
なんとなく事故る可能性を感じたので先程のfirebase.jsonに一工夫加えます。  

```firebase.json  
hosting: {[
  {
    "public": "public",
    "site": "staging"
    ...
  },
  {
    "public": "public",
    "site": "production",
    "predeploy" : "sh ./shell/confirm.sh"
    ...
  },
]}
```  

hostingにはデプロイ前とデプロイ後のトリガーがあるので、production環境のみshellを実行させるようにします。  
  
```./shell/confirm.sh  
read -n1 -p "本番環境にデプロイしますが、よろしいですか? (y/N): " yn
if [[ $yn = [yY] ]]; then
  exit 0
else
  exit 1
fi
```  

こうすることで、`firebase deploy`や`npm run deploy`時に確認を促されるようになり、本番環境に誤ってファイルを上げてしまうことを防ぐことが出来ます!


# まとめ  
プロジェクト分けたほうが、もしかしたら早いかもですが１プロジェクトでサクッと終わらせたいときにはおすすめかなと。
Dockerで構築したUbuntu18.04でip系のコマンドが実行できない場合の対処


Dockerで起動したUbuntuでrootユーザーであるにも関わらず、ip系コマンドを入力して、以下のように実行できない場合。。。

```terminal
root@d7a6f6a495dd:/# ip netns add helloworld
mount --make-shared /var/run/netns failed: Operation not permitted
```

docker runのオプションである`--privileged`を付与すると権限が与えられる

```terminal
docker run --privileged -it -d --name ubuntu-test ubuntu:18.04
```

これでOK

```terminal
root@d7a6f6a495dd:/# ip netns add helloworld
root@d7a6f6a495dd:/# ip netns list
helloworld
```
超絶簡単にテキストコーパスを作ってザクザク自然言語処理できてしまう。

# あらすじ

テキストコーパスを作ろうとしたけどネット記事やブログ、youtubeにネタが散在してて
スクレイピングがめんどい。ネタ元がAPI対応してなかったりでどうしよっか。。

あと根性で抜き出しても精度があんまりだったら嫌だな。サクっと確認もできないものか。

**あ、やりたいのに合わせて作ってしまえばいい！**


# 作ったもの

*クリップボードを監視してテキストが来たら自動で分かち書きに変換して出力します。
ショートカットキーでモデル作って、選択したテキストで試しに予測精度見れます。*

**そんだけですが超絶楽です**:grin:

![demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189193/b84b6686-5eaf-5c2d-0b6e-6429711ab981.gif)

**youtubeの文字起こしからも抜けます！**

![regexp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189193/4a9be542-e529-cadb-a91a-0991a086e787.png)


# コード

[ここです](https://github.com/yasutakatou/texsc)


# fasttextじゃなくてもっと最近のツール使えないの？

すみません、貧弱な大昔ノートPCなもので。。

というかこういうの既にありそうな気がする。ちゃんとしたのもうあったら申し訳ない。。
FlutterでFirebase Authを利用したログイン処理

## メアド、パスワードを画面から入力
メアドとパスワードの入力欄と、ログインボタンを配置します。

入力時にstateを更新しています。

```dart:login.dart
class LoginPage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Consumer <LoginStore>(
        builder: (context, loginStore, _) {
          return Scaffold(
              body: Container(margin: EdgeInsets.symmetric(
                  vertical: 80.0, horizontal: 30.0),
                  child: Column(children: <Widget>[
                    TextFormField(
                      decoration: InputDecoration(
                        hintText: "メアド",
                      ),
                      onChanged: (text) => loginStore.changeEmail(text),
                    ),
                    TextFormField(
                      decoration: InputDecoration(
                        hintText: "パスワード",
                      ),
                      onChanged: (text) =>
                          loginStore.changePassword(text),
                    ),
                    RaisedButton(
                        child: Text("Login")
                        ,
                        onPressed: () {
                          loginStore.tapLoginButton();
                        }),
                  ],)
              ));
        });
  }
}
```

## 認証処理
`signInWithEmailAndPassword` で認証を行います。

```Dart:login.dart
class LoginStore with ChangeNotifier {
  var email = "";
  var password = "";

  void changeEmail(String text) {
    email = text;
  }

  void changePassword(String text) {
    password = text;
  }

  void tapLoginButton() async {
    AuthResult result = await _signIn(email, password);
  }

  Future<AuthResult> _signIn(String email, String password) async {
    try {
      final AuthResult result = await FirebaseAuth.instance
          .signInWithEmailAndPassword(
          email: email, password: password);
      return result;
    } catch (e) {
      return null;
    }
  }
}
```
RaspberryPi3でゼビウス魔の二千機攻撃を動かす

#RaspberryPi3にAndroid Thingsをインストールする
ここの記事等みていただければですが、「iot_rpi3.img」がダウンロードできれば、あとはRaspbianのインストール等と同様に「balenaEtcher」等でmicroSDに書き込んで起動するだけです。
※ロケール設定がマウスでうまくいきませんが、キーボードのカーソルキーで選択してエンターで決定で設定すればよいです。

https://qiita.com/norihiko_tokudaiji/items/cdf10ff9de6d72b257e8

#SDK Platform-Toolsのインストール
adbコマンドを使用するためにSDK Platform-Toolsをインストールします。

https://developer.android.com/studio/releases/platform-tools.html

#xapkファイルの取得
「apkpure」でダウンロードしました。
https://apkpure.com/
「ゼビウス魔の二千機攻撃」で検索すれば見つかると思います。

#apkファイルの抽出
xapkファイルではインストールできないので、apkファイルを抽出します。
といっても～.xapkを～.zipにリネームして展開するだけです。

#ラズパイ３のAndroid Thingsへの接続
事前にIPアドレスを確認しておき、
「adb connect ～」で接続します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93459/4fc6e774-80d6-f067-61bd-943eb10c591e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93459/e5c1ba63-068f-ebd3-11d0-9ff07f6f0b93.png)


接続後は接続中のデバイスを「adb devices」で確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93459/872b2e89-dc96-95d6-2b04-b237213e31d3.png)


#アプリのインストール
展開後に作成される「info.tohokuitnews.xevious2000ki.apk」がアプリのファイルなので、これをインストールします。
「adb install ～.apk」でインストールできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93459/fee036eb-ec64-b233-b8c6-daf985918570.png)

#パッケージ名およびActivity名の確認
パッケージ名を調べます。
「adb shell pm list package」の結果を見るとapkファイル名と同じ「info.tohokuitnews.xevious2000ki」のようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93459/e3e75dc9-8900-a978-164d-ed35e98da3ba.png)

Activityクラスの名称がわからないと起動できないので、Android SDKの「aapt.exe」を使用して調べます。

「aapt dump badging ～.apt」で確認すると「MainActivity」のようでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93459/7e3f8020-aed7-e98a-c406-02c032b15918.png)

#アプリの起動
「adb shell」でシェルを起動後「am start -n info.tohokuitnews.xevious2000ki/.MainActivity」で起動できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93459/88b5038b-b28b-29ed-7872-a506e41ee644.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93459/56780866-348f-264c-2db9-9cad3fd61d40.png)
hello,worldsのみで覚えるpython

# はじめに
職場柄、アウトプットがしにくい環境にいる中、技術力を高めるのと理解の再確認のために記事を書くことにしてみた。
とはいえpythonの記事などありふれているわけで、特異性を見出すための手段として誰しも通る道であるhello,worldsのみでpythonを理解していこうではないかと思う。
馬鹿げてるくらいが読み物として丁度いいことだろう。

# 本記事の対象者
・pythonの勉強を始めた人
・pythonの経験値が足りないと感じる人
・物好き

# 注意点
・本記事はpython3系を前提として記載していく。当人が3.7を使用しているので3.8に対する知識が現時点で浅い

# 本題
## 1.文字列出力
hello,worldsを語る上では避けては通れない文字列出力である。
ここでは様々なアプローチでhello,worldsをしていく。

```
print('hello,worlds)
print('hello,' + 'worlds')
print({}.format('hello,worlds'))
hoge = 'hello,worlds'
print('%s' % hoge)
```

これら全てはhello,worldsである。
作者のやる気次第でこのノリかずっと続くことだろう

## 2.条件分岐
条件分岐さえできれば、もうプログラマとして一人前である。大抵の処理は0と1の羅列を覚えるかifを覚えればできてしまう。

### if文
```
hello_worlds = 'hello_worlds'
if hello_worlds == 'hello_worlds':
    print(hello_worlds)
else:
    print('goodbye worlds')
```
これでif文は完璧である。
十分であると思うが念のため、少し詳しく解説していく。
if文で用いられる演算子には not や is といった文字を用いる演算子と == や < といった記号を用いる演算子がある。
文字や記号を見ればその演算子が持つ意味を理解できると思うが、つまづくとしたらisと==の違いだろう。
この二つは似ているが比較するものが違うので注意が必要だ。

#### == は値が同じか判定する
これはわかりやすい。

```
'hello_worlds' == 'hello_worlds' # True
'goobye_world' == 'hello_worlds' # False
```

#### is はオブジェクトが同じか判定する
オブジェクトってなんだよと言いたい気持ちもわかる。

```
a = 'hello worlds'
b = a
c = 'hello worlds'
a is b # True
a is c # False
```

同じhello worldsでも違うと言われる理不尽さこそプログラミングだ。
オブジェクトを簡単に説明するなら、棚に陳列されている商品とでも思えばよい。
見た目は一緒だが、中身の内容まで同じとは限らないということだ。
aとcは見た目は一緒だが、同一でないためFalseになる。
詳しく知りたいならidentityやid関数を調べることをお勧めする。
DB::select で作られる中途半端な Array を完全な Array にする

DB::select を使ったときは以下ように、配列の中にオブジェクトが存在します。

```php
>>> $a = DB::select("select id, name from companies limit 2");
=> [
     {#4090
       +"id": 1,
       +"name": "Hoge",
     },
     {#4091
       +"id": 2,
       +"name": "Piyo",
     },
   ]
```

これを完全な配列にする方法は２つあります。

# 方法1

```php
>>> json_decode(json_encode($a), true);
=> [
     [
       "id" => 1,
       "name" => "Hoge",
     ],
     [
       "id" => 2,
       "name" => "Piyo",
     ],
   ]
```

# 方法2

```php
>>> foreach($a as &$v){$v = collect($v)->toArray();}
>>> $a;
=> [
     [
       "id" => 1,
       "name" => "Hoge",
     ],
     [
       "id" => 2,
       "name" => "Piyo",
     ],
   ]
```

以上です。
HTMLの基本である文字サイズ変更、改行、文字の色について

#HTML
PCで文章を書くにあたってHTMLに突き当たったのでちょっとまとめてみようというモチベーションで記事を書きます。基本的に困ったら見直せる程度のレベルです。

##対象者
HTML初心者の人

##前提条件
PCを使える
atom他エディタを使いこなせる
(atomの使い方についてはまた後日まとめていきます)

##章立て
・改行
・文字サイズ変更
・文字の色変更

#改行について
brタグを改行したい文末に入れることで改行することができます。<>で囲われたものをタグと呼びます。

```html:kaigyou
あいうえお<br>あいうえお
```
![2020-03-13 (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403932/57c86e85-e4d1-18c8-3c11-91cb90c6f9a6.png)

#文字サイズ変更について
fontタグを使用してフォントのサイズと色を変更することができます。フォントサイズは1から7までの7段階です。

```html:fontsize1
<font size='1'>あいうえお</font><br>
<font size='2'>あいうえお</font><br>
<font size='3'>あいうえお</font><br>
<font size='4'>あいうえお</font><br>
<font size='5'>あいうえお</font><br>
<font size='6'>あいうえお</font><br>
<font size='7'>あいうえお</font>
```
![2020-03-13 (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403932/3e407811-9a40-a397-6a2a-9780efa79405.png)

また、違う方法として、デフォルトの文字サイズ(size='3')から拡大することもできます。

```html:fontsize2
<font size='+1'>あいうえお</font><br>
<font size='+2'>あいうえお</font>
```



#文字色の変更について
fontタグのcolorを利用して色の変更ができます。

```html:fontcolor
<font color='blue'>あいうえお</font><br>
<font color='#0000ff'>あいうえお</font>
```

![2020-03-14 (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403932/aed6b7eb-63f2-d495-49ae-999961f708d3.png)

2行目の#から始まる数字は16進数の表記で、以下のURLにhtmlの色見本を載せさせていただくので気になった方は見てみてください。
https://www.colordic.org/
ポートフォリオを作り始めて1ヶ月、感じたこと。


プログラミング初学者が、ポートフォリオを作り始めて1ヶ月程度経って感じていることを書きます。
ポートフォリオの内容はゲームの紹介ウェブページ？のようなものです。
色々書きたいことはありますが、ざっくり下記３つにまとめました。

(1)計画を組んでも抜けが多くて見通しの甘さを痛感する

始めにDB設計をしてその後、必要なビュー、テーブルの作成などやりましたが、
作業の途中に「これ、この機能が必要じゃないのか？でもやり方わからん＼(^^)／」とか
とにかく抜けが多くてやり直しが多いです。まぁ初めてやることだから
見通しがしにくいというのはあるのでしょうが...

(2)本、カリキュラムなどと違って全て自分の頭でやるから迷うことが多い

これも当たり前ですが、他の人が作ったカリキュラムをやるのと違って正解がないため
進んでいるのかどうかを感じにくく、全て自分の頭で考えないといけないので
普段こういう思考法？をしていない僕にとっては非常に辛いんですね(今まで自分の頭で考えないゴキブリですみませんでした( ；∀；)

(3)自分のセンスのなさ、頭の悪さで潰れそうになる

皆さんもそうかもしれませんが、やっていくとデザインとかを考えたり
学習したところを何度も忘れり、大したことない問題で何時間も時間を使ったりなど
壁に何度もぶつかる訳ですが、その度に心が折れそうになるわけですね。
しかも誰もそれをフォローするわけでもないので、(環境次第ですが)
これはみんなやめてくやろなぁと実感します。
ちなみに僕の心は元々メンタル豆腐で既にグチャグチャに潰れて
豆腐だったか何かに変わっています＼(^^)／
こけるのはもう慣れてしまったので、いかにすぐに立ち直るかが重要だと思っているので
とにかく死ぬ気で毎日体力が持つ限り続けていってます(｀・∀・´)
...一人だとサボるので友人の監視付きですが( ´ ▽ ` )


大体こんなところです...要領の良さとかもあるのでしょうが、
いかに継続して毎日取り組めるかに全てがかかっているのかもしれません。
そのためにも目標を持つこと、体調管理、メンタル管理、環境構築などは欠かせません。

皆さんもどうか僕みたいに豆腐だったか何かにならないよう気をつけてくださいね！ヾ(๑╹◡╹)ﾉ"
Pythonで毎日AtCoder #5

### はじめに
[前回](https://qiita.com/taxfree_python/items/9c2a9213f132abd2aef8)
5日目です。今日はコンテストがあります。[今日のコンテスト](https://atcoder.jp/contests/panasonic2020)

### #5
[問題](https://atcoder.jp/contests/arc022/tasks/arc022_1)

**考えたこと**
1WAしました。
与えられる文字列に'ict'が含まれているかを判断する問題です。いくつかの文字を除いて'ict'になればいいというのが大事で、'ict'のどれかを除いてもいいのです。
最初は、この条件を見落していたのでWAしました。それを改善して順番通りに変換していくようにしました。

```python
import re
s = str(input())
s = s.lower()
l = 'ict'
step = 0
for i in range(len(s)):
    if s[i] == l[step]:
        step += 1
    if step == 3:
        print('YES')
        quit()

print('NO')
```
stepでindexを指定することで、順番通りに探してくれます。
s.lower()は、sを全て小文字にします。

### まとめ
A問題なのにWAしてしまったのが悔しいです。今日のコンテストがんばりましょう!
では、また
CentOS8 インストール後の設定メモ

## SSH Rootログインを制限

```
# vi /etc/ssh/sshd_config
PermitRootLogin no に変更

# systemctl enable sshd
# systemctl start sshd
# systemctl restart sshd
```

## ログイン設定

```
確認
# systemctl get-default
multi-user.target

グラフィカルログインをやめる
# systemctl set-default multi-user.target

# systemctl get-default
multi-user.target
```

## 開発用ライブラリ

```
# dnf install git wget gcc gcc-c++ bzip2 openssl-devel libffi-devel readline-devel zlib-devel gdbm-devel ncurses-devel
```

## PHP

```
# dnf install php php-mbstring php-xml php-xmlrpc php-gd php-pdo php-mysqlnd php-json
```

# Apache

```
インストール
# dnf -y install httpd httpd-tools httpd-devel httpd-manual
# which httpd
# systemctl start httpd

確認
# systemctl status httpd

# httpd -V | head -n 1
Server version: Apache/2.4.37 (centos)

FireWall 設定
# firewall-cmd --add-service=http --permanent
# firewall-cmd --reload
```

## DNS設定
必要な場合のみ

```
# nmcli c mod ens160 ipv4.dns 8.8.8.8,8.8.4.4

ens160 はネットワークの設定名

# vi /etc/resolv.conf
nameserver 8.8.8.8
```

## node.js

```
# curl -sL https://rpm.nodesource.com/setup_12.x | bash -
# dnf install -y nodejs

# curl -sL https://dl.yarnpkg.com/rpm/yarn.repo | sudo tee /etc/yum.repos.d/yarn.repo
# dnf install -y yarn
```
適当にansibleでrootパスワードを変えようとしたらアクセスできなくなった件

下記のような適当なtaskを書いたら、rootにログインできなくなり、
ほかのユーザを作成していなかった為、何もできなくなってしまいました。。。

ansible:2.9.3
ターゲットノードOS：CentOS7.7


```root_passwd_change.yml
---
- hosts: test
  become: true
  tasks:
    - name: passwd change
      user:
        name: root
        password: newpassword
```

これを実行すると、

```
[root@ansible test]# ansible-playbook -i host root_passwd_change.yml

PLAY [test] *********************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.1.136]

TASK [passwd change] ***********************************************************
[WARNING]: The input password appears not to have been hashed. The 'password'
argument must be encrypted for this module to work properly.

changed: [192.168.1.136]

PLAY RECAP *********************************************************************
192.168.1.136              : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
```

>[WARNING]: The input password appears not to have been hashed. The 'password'
argument must be encrypted for this module to work properly.

で怒られますが、OKの記述がでて、変更できたように見えます。
ですが実際は
想定しているパスワードだとsshできなくなり、コンソールからのログインもできなくなります。
playbook再度実行しても変更できなくなるので、レスキューモードでパスワードの再設定などが必要になります。

```
[root@ansible test]# ansible-playbook -i host root_passwd_change.yml

PLAY [test] *********************************************************************

TASK [Gathering Facts] *********************************************************
fatal: [192.168.1.136]: UNREACHABLE! => {"changed": false, "msg": "Invalid/incorrect password: Permission denied, please try again.", "unreachable": true}

PLAY RECAP *********************************************************************
192.168.1.136              : ok=0    changed=0    unreachable=1    failed=0    skipped=0    rescued=0    ignored=0
```

#原因
>[WARNING]: The input password appears not to have been hashed. The 'password'
argument must be encrypted for this module to work properly.

で怒られている通りパスワードがhashされないでべた書きされているからです。
以下のように書けば想定通りに変更できます。

```root_passwd_change.yml
---
- hosts: test
  become: true
  tasks:
    - name: passwd change
      user:
        name: root
        password:  "{{ 'newpassword' | password_hash('sha512') }}"
```
下記ドキュメントに記載の通りにhash化して書いてあげないといけませんでした。
※Linuxの/etc/shadowはsha512形式の暗号化してあげないといけない

https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#hashing-filters

上記を実行すると、

```
[root@ansible test]# ansible-playbook -i host root_passwd_change_fixed.yml

PLAY [test] *********************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.1.136]

TASK [passwd change] ***********************************************************
changed: [192.168.1.136]

PLAY RECAP *********************************************************************
192.168.1.136              : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

```

想定していた通りに変更できました。
AsyncTaskをTHREAD_POOL_EXECUTORで実行した際のPoolサイズ

AsyncTaskをexecuteOnExecutor(THREAD_POOL_EXECUTOR)で実行した際のPoolサイズについて調べました。

# 結果
THREAD_POOL_EXECUTORのPoolサイズはCPUの数で決まり、Poolサイズは**Math.max(2, Math.min(CPU_COUNT - 1, 4))**となります。

### 詳細
THREAD_POOL_EXECUTORは、AsyncTaskで生成されたThreadPoolExecutorで、生成時のパラメータは下記の通りです。

CcorePoolSize：Math.max(2, Math.min(CPU_COUNT - 1, 4))
maximumPoolSize：CPU_COUNT * 2 + 1
※ workQueuのサイズは１２８

```java:AsyncTask.java
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    // We want at least 2 threads and at most 4 threads in the core pool,
    // preferring to have 1 less than the CPU count to avoid saturating
    // the CPU with background work
    private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int KEEP_ALIVE_SECONDS = 30;

    private static final BlockingQueue<Runnable> sPoolWorkQueue =
            new LinkedBlockingQueue<Runnable>(128);

    public static final Executor THREAD_POOL_EXECUTOR;
    static {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
                sPoolWorkQueue, sThreadFactory);
        threadPoolExecutor.allowCoreThreadTimeOut(true);
        THREAD_POOL_EXECUTOR = threadPoolExecutor;
    }
```

# ThreadPoolExecutorのmaximumPoolSize
ThreadPoolExecutorのPoolサイズは、corePoolSizeおよびmaximumPoolSizeによって設定された境界に従って、自動的に調整されます。
corePoolSizeを超えているが、maximumPoolSizeスレッドが実行されていない場合、キューがいっぱいの場合にのみ新しいスレッドが作成されます。
※ THREAD_POOL_EXECUTORのworkQueuのサイズは１２８
ブラウザ経由のPHPスクリプトでcURLが実行されなかった


#概要
PHPスクリプトからWeb APIを実行するためにcURLを使おうとしていたが、下記の現象が発生した。
- cURLをシェルで直接実行したら動作する
- シェルからPHPスクリプトを実行すると動作する
- ブラウザでPHPスクリプトにアクセスすると、スクリプトは実行されるが、cURLが動作しない

原因はSELinuxがhttpdからのネットワーク接続を遮断していたためであり、SELinuxの設定変更で解決できた。


#現象
##確認した環境
- CentOS 8.1
- Apache 2.4
- PHP 7.2
- cURL 7.61


##確認用コード
``` test.php
<?php
$url=(送信先URL);
$data=(json_encodeされた送信したいデータ);

$ch=curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json'));
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_exec($ch);

echo 'http_code:' . curl_getinfo($ch, CURLINFO_HTTP_CODE) . "\n";
echo 'curl_errno:' . curl_errno($ch)  . "\n";

curl_close($ch);
?>
```

##実行結果
シェルで`php test.php`を実行すると…

```
http_code:200
curl_errno:0
```
APIも正常に実行された。

ブラウザから`https://example.com/test.php`にアクセスすると…

```
http_code:0
curl_errno:7
```


##原因
SELinuxのデフォルト設定で、httpdからのネットワーク接続が遮断されてしまっていたため。


#解決方法
下記コマンドを実行するだけ！
`sudo setsebool -P httpd_can_network_connect 1`


#参考
[php - CURL permission denied via browser, works on ssh - Stack Overflow](https://stackoverflow.com/questions/16622967/curl-permission-denied-via-browser-works-on-ssh)
🔰UIPath 初心者のボクがハマった点 備忘録 (随時更新)

UIPath初心者のボクが使っててハマった点をメモしておくよ😰😰😰

# エクセル関係

### 同じようなアクティビティが2系統ある！
**問題:**
たとえば「セルを読み込み」を見てみると、2種類あるよ😱😱😱 どっちを使えばいいのー❗❓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500776/67101be0-5e16-d8f3-34ba-c5a0e7ac2966.png)


**対処方法:**
「ワークブック」の下にある「[セルを読み込み (ReadCell)](https://docs.uipath.com/activities/lang-ja/docs/read-cell)」は、エクセルがインストールされていない環境でも使えるようだよ📗📊 一方、「Excel」の下にある「[セルを読み込み (ExcelReadCell)](https://docs.uipath.com/activities/lang-ja/docs/excel-read-cell)」は、エクセルのインストールが必要だよ📇📝 通常の利用であれば、アクティビティの英語名の頭に「Excel」がついている方を使おう👌😘✨

### 開いたエクセルは必ず閉じてしまう！
**問題:**
「[Excelアプリケーションスコープ (ExcelApplicationScope)](https://docs.uipath.com/activities/lang-ja/docs/excel-application-scope)」で開いたエクセルファイルは、スコープが終わると必ず閉じてしまい開いたままにできない😰😰💦💦
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500776/0eff582e-0e6e-898b-f96e-e66fec60d0f8.png)

**対処方法:**
あらかじめ「プロセスを開始」で引数に同じエクセルファイルを指定して開いた状態で、さらに「Excelアプリケーションスコープ」を使ってエクセルファイルを開いておくと、「Excelアプリケーションスコープ」が終了してもファイルが閉じないよ👌😘✨


### フツーにセルを読むとエラーが出る！
**問題:**
「[セルを読み込み (ExcelReadCell)](https://docs.uipath.com/activities/lang-ja/docs/excel-read-cell)」でセルを読み込んで変数に出力しようとすると、以下のエラーが出てしばらくハマった😰
<b><font color="Red">セルを読み込み: StringConverter を System.Double から変換できません。</font></b>
原因は、出力結果を文字列変数に出力していて、読もうとしていたセルが表向きは整数だったけど中身の値に端数が含まれていたこと💦💦

**対処方法:**
「セルを読み込み (ExcelReadCell)」の「表示形式を保持」のオプションをONにしておくと、常にセルに表示される書式そのままで文字列として変数に出力されるので、エラーが出ない👌😘✨
もしくは格納する変数型をGenericValueにする🤔🤔
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500776/0abfd122-3726-e5d9-cd63-f6b807190d8b.png)

### セルに小数を書き込んでもセル上では整数になってしまう
**問題:**
「[セルに書き込み (ExcelWriteCell)](https://docs.uipath.com/activities/lang-ja/docs/excel-write-cell)」で小数「1.1」を書き込んでも、エクセルのセル上では
「1」と表示されてしまう🤔🤔💦

**対処方法:**
これはエクセルに書き込んだセルの表示形式に沿った見え方になってしまうせいだよ💦💦 エクセルの表示形式を操るUIPathのアクティビティはないので、必要であればあらかじめ手で設定しておくか、キーボードショートカット等で表示形式を設定してね👌😘✨

### 置換が意外とメンドウ！あいまい検索も！
Excelブック内での文字列検索は「[範囲内で検索 (ExcelLookUpRange)](https://docs.uipath.com/activities/lang-ja/docs/excel-look-up-range)」を使うんだけど、このアクティビティは指定した「範囲」 (省略可能)で指定した「値」を検索して、最初のセルのアドレスを「結果」に文字列として返すよ🤔🤔
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500776/37368196-eaa3-08b1-5915-1437c1ba179d.png)
ただ、そうすると指定した範囲内のすべての値を検索/置換するのに、このアクティビティだけでは対応できないんだ😰💦

そうすると、たとえば「A1:G10」の範囲で検索置換をしようとすると、行と列のループ (「[繰り返し (While)](https://docs.uipath.com/studio/lang-ja/docs/the-while-activity)」)を2重に回して、行数を1から10まで、列名をAからGまで、とかで繰り返し処理を作る必要があるネ🤔🤔 プログラミングができないと難しい...😰😰😰😰😰

あと、エクセル本体では「大文字と小文字を区別する」「セル内容が完全に同一であるものを検索する」「半角と全角を区別する」があるけど、これを「範囲内で検索 (ExcelLookUpRange)」で使いたい場合はメンドウ...😰😰😰😰😰「範囲内で検索 (ExcelLookUpRange)」は、表示形式で表示されている文字ではなく、エクセルのセル内の「真の値」(セルを選択したときに数式バーに表示される値)に部分一致する最初のセル(大文字小文字を区別しない、半角/全角は区別する)を返すのだけれど、それ以外の方法を試そうとするとプログラミングが必要だネ🤔🤔
Label Encoding

#Label Encoding
 Label Encoding and One-Hot Encoding
 大事な方針
　２つのカテゴリーはLabel Encodingで
　それ以上のカテゴリーは One-Hot Encoding
　でわけること

label encodingにはScikit-Learn LabelEncoder
one-hot encoding　には、pandasの　get_dummies(df) functionを使う
音声データを投稿するだけで自動で文字起こししてくれるSlackBotをOSS化しました！

## 始めに
こんにちは、Webエンジニアのかずまと申します。

**自分は１年前にエンジニアになったのですが、その中で作り上げた知の結晶をオープンソースとして公開しみんなで開発・保守していくOSSという文化にとても感激しました。**

自分もいつかコントリビュートしたり（チャレンジしていますが、中々難しい！笑）、OSSを公開して少しでも役に立てればと思っていました。

**今回自分が休日に作っていたSlackbotが完成したので、文字起こし等で困っている方の力になれればと思いOSSとして公開します。**（色んなサービスの繋ぎ合わせなので、これをOSSと呼べるのか分かりませんが。。。）

リポジトリURL：https://github.com/creamstew/transcribe-slack-bot

## 何を作ったか
タイトルの通り、**投稿された音声データを自動で文字起こししてくれるSlackBotです。**

**Botが参加しているチャンネルに音声ファイル（mp4等も可）を投稿すると、その音声が文字起こしされたテキストファイルが返ってきます。**

<img width="1306" alt="スクリーンショット 2020-03-13 18.51.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298182/4486ad2b-f98a-2102-4497-efec2444a18e.png">

このように非エンジニアでも簡単に使うことができます。

## なぜ作ったか
自分の今勤めている企業は一つの柱としてメディア事業を行っています。

**その中でインタビューした音声を文字起こししたり、編集した動画に文字テロップを入れるために動画内容を文字起こしするケースが結構ありました。10分の音声も全て文字起こしするとなると1時間くらいかかるので、これが結構大変そうでした。**

人数も多くない会社なので文字起こしするという作業だけで時間を消耗しているのはもったいないなと思い、勉強も兼ねてちょっと個人的に作ってみようと思ったのがきっかけです。

## 構成
![アーキテクチャ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298182/c8710cc3-deef-7492-f200-d7f74d78ac97.png)
基本的には**SlackのAPIとAWSのサービスを連携させておりサーバーレス運用、デプロイもサーバーレスフレームワークによりコマンド一発でできるようにしています。**

今の会社はSlackでコミュニケーションを取っているので、非エンジニアでもSlack上で簡単にシステムが使えるようにこの構成にしました。

### 文字起こしまでの流れ

1. SlackAPIがチャンネルへの投稿を検知して、API Gatewayにその情報を渡す
2. API GatewayをトリガーにLambdaが起動し、音声ファイルをS3に保管する
3. S3をトリガーにLambdaが起動し、保管した音声ファイルをAWS Transcribeで文字起こしする
4. 文字起こしされた情報がJSONファイルとしてS3に保管される
5. 保管されたJSONファイルをトリガーにLambdaが起動し、JSONファイルから文字起こしされた情報のみをテキストファイル化して、Slackに投稿

### 使用技術・サービス

 - Serverless Framework
 - AWS(Amazon Transcribe, S3, Lambda(Ruby2.5), Lambda Layer, API Gateway, S3)
 - Slack API

## 肝心の文字起こしの精度は？

今回文字起こしには、**2019年の11月ごろに日本語対応されたAWSのTranscribe**というサービスを使っています。

ざっくりいうと、**60分の音声だったら20分150円で文字起こししてくれる優れものです。**

肝心の精度についてはすでに別記事で書いていまして、

- [イチロー引退会見の冒頭挨拶をAmazonTranscribeで文字起こしして精度を確かめてみた](https://qiita.com/bSRATulen2N90kL/items/bfc15c18872751bc4794)

結論、**インタビュー形式であればかなりの高精度で文字起こししてくれるので、ライターのインタビューの文字起こしや動画編集者のテロップを入れるための動画の文字起こしなどの用途ではかなり活用できると思います。**


詳しい説明は公式サイトや他の記事をご覧ください。

- [Amazon Transcribe](https://aws.amazon.com/jp/transcribe/)
- [Amazon Transcribeを調べてみた](https://qiita.com/Hachi_0601/items/57cde062e3b415afa43e)

## 作ってみて

こちらの**Slackbotを社内で使ってもらったところ、結構評判が良くて嬉しかったです。**

ほとんどコードも書いていなくてサービスを繋ぎ合わせただけなのですが、ちょっとしたことでも社内の課題を解決できるんだと思える良い経験になりました。

下記がSlackbotのGitbubになります。まだまだ改善点もあるのですが、同じように社内で困っている人などいらっしゃればぜひ使ってみていただけると嬉しいです！

リポジトリURL：https://github.com/creamstew/transcribe-slack-bot
StringIOを使ったCSVファイル作成

StringIOを使用することでCSVファイルの作成を簡単に行うことができます。
以下簡単なサンプルです。

settingsに関しては[こちら](https://docs.python.org/ja/3/library/csv.html#dialects-and-formatting-parameters)を参照

```python
from typing import List
import csv
from io import StringIO


def create_csv_from_associative_array(data: List[list], **settings) -> str:
    file = StringIO()
    writer = csv.writer(file, **settings)
    writer.writerows(data)
    csv_data = file.getvalue()
    StringIO().close()

    return csv_data


settings = {
    'delimiter': ',',
    'doublequote': True,
    'lineterminator': '\r\n',
    'quotechar': '"',
    'skipinitialspace': True,
    'quoting': csv.QUOTE_MINIMAL,
    'strict': True
}

data = [['名前', '年齢', '性別'], ['tester1', 23, 'man'], ['tester2', 19, 'woman']]

cav_data = create_csv_from_associative_array(data=data, **settings)

print(cav_data)

```
【GAS×スプレッドシート】アクティブなセルへの移動について

# 概要
アクティブなセルへ移動させる動きを実装しようとしてハマってしまったので備忘録として記載。

# 達成したいこと
・スプレッドシート上に設置したボタンを押したら現在のアクティブなセルに画面を移動させる

##達成したいことのイメージ動画
![ezgif.com-video-to-gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250548/da62bfc6-d21c-95e8-aa4e-b6db1150997c.gif)


#スクリプト
## 期待した出力にならないスクリプト
```main.gs
function moveActiveCell(){
  var spreadSheet  = SpreadsheetApp.getActiveSpreadsheet();
  var ss           = spreadSheet.getActiveSheet();
  var activeCell   = ss.getActiveCell();
  var activeColumn = activeCell.getColumn();
  var activeRow    = activeCell.getRow();
  ss.getRange(activeRow , activeColumn).activate();
}
```
上記のコードはスクリプトとしては正しいコードであるが、
**現在のアクティブセルを取得して、そのセルをアクティブにしているだけなので
画面をアクティブなセルに移動させることはできない。**

今回は厳密に特定のセルをアクティブにしたいという要件ではなく
画面を移動させれば良いという要件であったため下記のように実装した。

## 期待した出力のスクリプト(1例)
```main.gs
function moveActiveCell(){
  var spreadSheet  = SpreadsheetApp.getActiveSpreadsheet();
  var ss           = spreadSheet.getActiveSheet();
  var activeCell   = ss.getActiveCell();
  var activeColumn = activeCell.getColumn();
  var activeRow    = activeCell.getRow();
  ss.getRange(activeRow + 1 , activeColumn).activate();
}
```
上記のように実装すれば期待通りにアクティブなセル(の近くに)画面が移動するようになる。

以上
【VisualStudio】VisualStudio2019で自動コードフォーマット

プロジェクトごとにコードフォーマット意識するのめんどくさいですよね
editorconfig使いましょう
特にチーム制作の場合は自動化して俺ルールは排除しましょう

以前は手動でファイルを作成してたんですが
VisualStudio2019からはローカルのフォーマット設定（.editorconfig）を出力できるようになりました

# 手順
## 作成
VS上部のメニューから
「ツール > オプション」
![editorconfig.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216261/67acc245-e71c-b795-30c9-7fe2310a9bdc.png)
コードスタイルの各項目を設定して生成ボタンをポチるだけ
現状C#とか一部の言語設定にしか生成ボタンないようだけど
生成後に対応ファイルや設定を書き換えればどの言語でも使用できるかと思います

```c#:.editorconfig
[*.cs,*.cpp,*.h]
```
こんな感じで

## ファイルの配置について
ちなみに
このファイルを配置した階層以下に適用されるわけですが
一部のフォルダ以下は適用したくないなどあれば（たとえばプラグインのコードは更新時に差分でるからそのままにしたいとか）

```c#:.editorconfig
root = true
```
これだけ記載したファイルを適用したくないフォルダに配置すればその階層以下は自動化されなくなります

あと.editorconfig作成時や内容を編集した時はVSを再起動しないと反映されなかったと思います

## 保存した時に自動化したい
VSのデフォルトでは保存時（ctrl+S）に自動化が反映されません
拡張機能を入れる必要があります
いくつかあるんですが勝手に他の設定とかも書き換わったりするものもあるので個人的にはシンプルな設定のみの下記の拡張機能を使用してます

拡張機能を追加する場合は
「拡張機能 > 拡張機能の管理」
![format.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216261/df228c44-fe9b-c181-f27e-dd029bbe534a.png)
インストール後、適用するにはVSの再起動が必要です

やっぱこの拡張機能いらねってなったら
同じく「拡張機能の管理」の「インストール済み」の一覧から無効化やアンインストールができます


# 詳細
editorconfigについてはVSのドキュメントがあります
https://docs.microsoft.com/ja-jp/visualstudio/ide/code-styles-and-code-cleanup?view=vs-2019#code-styles-in-editorconfig-files
Java JAR 基礎

 java初心者。
javaでjarファイルを作り、実行するまで。

##＜概要＞
①適当なディレクトリ作成
②適当なjavaファイル作成
③JARファイルの作成
④マニフェストファイルをいじる
⑤実行

##＜詳細＞
###①適当なディレクトリ作成
~/sample/

###②適当なjavaファイル作成
作業ディレクトリ：~/sample/Sample.java

```
package sample;
public class Sample{
  public static void main(String[]args){
      System.out.println("実行できた");
  }
}
```
一回、コンパイルと実行してみる。
作業ディレクトリ：~

```
> javac sample/Sample.java
> java sample.Sample
実行できた
```

###③JARファイルの作成
作業ディレクトリ：~

```
>jar -cvf Sample.jar sample/
マニフェストが追加されました
sample/を追加中です(入=0)(出=0)(0%格納されました)
sample/Sample.classを追加中です(入=428)(出=305)(28%収縮されました)
sample/Sample.javaを追加中です(入=137)(出=120)(12%収縮されました)
```

**JARファイルの中身確認**

```
> jar -tvf Sample.jar
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
     0 Sat Mar 14 12:19:02 JST 2020 META-INF/
    66 Sat Mar 14 12:19:02 JST 2020 META-INF/MANIFEST.MF
     0 Sat Mar 14 12:15:34 JST 2020 sample/

   428 Sat Mar 14 12:15:34 JST 2020 sample/Sample.class
   137 Sat Mar 14 12:09:48 JST 2020 sample/Sample.java
```



###④マニフェストファイルをいじる
作業ディレクトリ：~
META-INF/MANIFEST.MFの中身

```META-INF/MANIFEST.MF
Manifest-Version: 1.0
Created-By: 13.0.2 (Oracle Corporation)
```
**マニフェストファイルの作成**

```Sample.mani
Main-Class: sample.Sample
```
**メイン・マニフェスト属性の追加**

```
>jar -uvfm Sample.jar Sample.mani
マニフェストが更新されました
```

実行後のMETA-INF/MANIFEST.MFの中身

```META-INF/MANIFEST.MF
Manifest-Version: 1.0
Created-By: 13.0.2 (Oracle Corporation)
Main-Class: sample.Sample
```
直接MANIFEST.MFにMain-Classを書き込んだが、それでは実行できなかった。



###⑤実行
作業ディレクトリ：~

```
> java -jar Sample.jar
実行できた
```

**他の実行方法**

```
> java -cp Sample.jar sample.Sample

Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
実行できた
```
Debian 10 (buster) のpython3でmkvirtualenvを使う

## 準備する

aptでpipとvirtualenvをインストールする。

```
$ apt-get install python3-pip python3-virtualenv
```

pipでvirtualenvwrapperをインストールする。`~/.local/bin/`配下にインストールされる。python3用のvirtualenvwrapperのdebianパッケージはない。

```
$ pip3 install virtualenvwrapper
```

以下を`~/.bashrc`に追加し、一度ログアウトする。

``` bash:~/.bashrc
export WORKON_HOME=$HOME/.virtualenvs
export PROJECT_HOME=$HOME/devel
export VIRTUALENV_PYTHON=/usr/bin/python3
export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
export VIRTUALENVWRAPPER_VIRTUALENV=/usr/bin/virtualenv
source ~/.local/bin/virtualenvwrapper.sh
```

## 利用する

再度ログイン後、mkvirtualenvが使える。

```
$ mkvirtualenv myenv
```

`mkdir $PROJECT_HOME`しておけば、プロジェクト（仮想環境と開発用ディレクトリのセット）も作れる。

```
$ mkproject mypj
```

参考: [virtualenvwrapperコマンドリファレンス](https://virtualenvwrapper-docs-ja.readthedocs.io/en/latest/command_ref.html)
Mac Catalina Audacity(オーダシティ) 音声入力を受け取ってくれない不具合を解決した話

# 目的

- 最新OSでAudacityが音声入力に対応してくれない不具合が発生して解決した話をまとめる

# 環境

| 項目 | 情報 |
| --- | --- |
| OS | macOS Catalina(10.15.3) |
| ハードウェア | MacBook Pro (16-inch ,2019) |
| プロセッサ | 2.6 GHz 6コアIntel Core i7 |
| メモリ | 16 GB 2667 MHz DDR4 |
| グラフィックス | AMD Radeon Pro 5300M 4 GB Intel UHD Graphics 630 1536 MB |

# 問題

- インストール直後にインプットデバイスを内蔵マイク設定しているけど音声を受け付けてくれない。
- 録音を始めても全く音の波形が入らない。

   ![20200312111718.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/9e81647c-8328-b682-f32e-73e5ffc1729c.png)
 

# 解決方法

- 下記を参考に解決策を模索した。
    - [Audacityフォーラム](https://forum.audacityteam.org/viewtopic.php?f=47&t=107162&p=378694)

1. ターミナルを起動して下記コマンドを実行し管理者になった。

    ```terminal
    $ sudo su
    ```

1. 下記コマンドを実行してターミナル経由でAudacityを起動した。

    ```terminal
    # open /Applications/Audacity.app/Contents/MacOS/Audacity
    ```

1. Audacityのアプリが起動した。

    <img width="1904" alt="スクリーンショット 2020-03-14 12.26.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/bae8cfa8-69c4-3317-88c4-9f3087cc8555.png">

1. 左上の録音ボタンをクリックしたところ下記のウインドウが開いたので「許可」をクリックした。

    <img width="532" alt="スクリーンショット 2020-03-14 12.20.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/7a3b6450-9527-bb4e-e50d-8ca34128e0b7.png">

1. 再度録音を行ったら正常に録音している音波の波形が確認された。

<img width="1904" alt="スクリーンショット 2020-03-14 12.20.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/69d5149f-9990-881e-b378-fcf5f8ad3afd.png">
【abc158-D】 string

※注意
この記事は、主に自分用に執筆したものです。ので、各所にお気持ちが伝わりづらい(伝わらない)言い回しやコードが散見されるかもしれませんがご了承ください。

#まえがき
[AtCoder Beginner Contest 158](https://atcoder.jp/contests/abc158)(後解き)。
D解いててまあいつものごとく少しつまづいたりしたので、`string`を少しいじいじしてみた。その記録。まあ全然難しくはない。
※abc158-D(String Formation).Difficulty: 597

#本編
##安直なコード のち実験
```abc158/d.cpp
#include <bits/stdc++.h>
using namespace std;

int main() {
  string s;
  int q;
  cin>>s>>q;

  int time = 1;
  while(time<=q) {
    int t;
    cin>>t;
    if(t==1) reverse(s.begin(), s.end());
    else {
      int f;
      char c;
      cin>>f>>c;
      if(f==1) s = c+s;
      else s = s+c;
    }
    time++;
  }

  cout<<s<<endl;

  return 0;
}
```

愚直に操作するならまあこうだよねって感じだけど、(割と案の定)TLE。原因は明確で、`reverse` の計算量が $O(N)$ だからってそれだけ。

だと思ってた。そこだけじゃ通りませんでした。色々試してみた結果、どうも**文字列の連結は実行速度が遅い**っぽい。

```free.cpp
  string s="";
  int now=0;
  int time=1000000000;
  while(now<time) {
    //s = s+'a';
    s.push_back('a');
    now++;
  }

  cout<<s<<endl;
```

こんな感じで色々試してみた結果、先頭追加でも末尾追加でも、連結で書くと遅い。具体的にはtime=10^6くらいでもう目に見えて時間がかかる。一方の`push_back`さん、time=10^9でもそれなりに早い(出力するのに多少時間はかかるけどそれは許容)。

ただそこそこ調べたんだけど、文字列連結が内部でどんな動きしてるのか、とか、計算量とかは分からずじまいでしたごめんなさい。ただこの問題の感じ、10^5回連結すると惜しくも間に合わない、くらいな気がする。あんまり乱用するものじゃないのかもね。

↑コメント頂いたのでメモっておきます。
文字列の連結は、さっきでいうsとは別の領域を確保するってステップが入るから、処理が遅いっぽいです。一方の`s.push_back(a)` とか `s += 'a'` は、新たな領域を確保したりはしないから処理が早い。実験してもそうなった。確かに言われてみればそんな気もするなあ。

##ACコード
というわけで通ったコードがこれ。

```abc158/d3.cpp
#include <bits/stdc++.h>
using namespace std;

int main() {
  string s;
  int q;
  cin>>s>>q;

  int time = 1;
  bool rev = false;
  string front;
  while(time<=q) {
    int t;
    cin>>t;
    if(t==1) rev = !rev;
    else {
      int f;
      char c;
      cin>>f>>c;
      if((!rev && f==1) || (rev && f==2)) front.push_back(c);
      else s.push_back(c);  //この一行でめっちゃ実行速度変わった
    }
    time++;
  }

  string ans;
  if(rev) {
    reverse(s.begin(), s.end());
    ans = s+front;
  }

  else {
    reverse(front.begin(), front.end());
    ans = front+s;
  }

  cout<<ans<<endl;

  return 0;
}
```

bool型変数を導入してリバースの判定を行い、基本は`push_back`で文字を追加、最後に1回だけ`reverse`や連結を行うようにした。これで時間余裕。真ん中らへんにコメントで残したけど、あの1行連結にすると途端に1秒くらいかかってギリになる。目に見えてわかる。面白い。

あと地味にboolは「！」つけると反転させられるの初めて使った。bool便利。


#おしまい
コード縦に細長い印象受けたけど、インデントをspace2個分に設定し直したのがあるかも。まあ冗長気味な自覚もあるけど。

とりあえず高速バスの中でPC酔う。強くなりたい
LGTM反対

# 概要
 LGTMってわかんないです。

# 文句の観点
 * Look Good To Meって、日本人は言いません。感覚が分かりません
 * せっかく日本語で数学までできる文化を創ってきたのに、ITが英語だからといって安直に導入しないでください。
 * いいじゃん？でもいいですけど、いいね！とどこが違うんでしょうね？
 * 英語版ではLGTMでもいいですけど、あくまでqiitaは日本語が主です。
 * 日本語で発信するというのも、もう、戦略です。
 * 日本語でしか考えられないアイデアが、今後、オリジナリティを作っていくと思います
 * qiitaが好きでいっています。英語をググってqiitaに答えがあったときの感動はなかなかなもんです

# 言いたいこと
　* 日本語で頑張りましょうよ
CheckboxSelectMultipleを使うとinput:clicked + labelが効かなくなる/

Djangoのフォームフィールドでwidget引数にCheckboxSelectMultipleを設定すると、テンプレートで複数選択可能なtype=checkboxのinputを生成してくれます。

forms.py

```python
class ExampleForm(forms.ModelForm):
    choice = forms.ModelMultipleChoiceField(required=False, queryset=ChoiceTag.objects, widget=forms.CheckboxSelectMultiple)
    class Meta:
        model = Example
        fields = ['choice']
```

  
views.py

```python
from .forms import ExampleForm
...
class ProfileEdit(LoginRequiredMixin, CreateView):
    def post(self, request, *args, **kwargs):
        form = ExampleForm()
        return render(request, "app/index.html", { "form" : form })
```

template(index.html)

```html
{{ form.choice }}
```

html

```html
<ul>
 <li>
   <label for="id_example">
     <input type="checkbox" name="example" id="id_example">
   </label>
 </li>
  ...
</ul>
```
<br>
<div style="text-align: center;">
＼すごく簡単／
</div>

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315096/147ac1d0-1985-078c-8559-cb49ba2359bd.png">


でもlabelの中にinputが入ってしまってlnput:clicked +　labelが効かなくなってしまいます。

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315096/cfce2d5c-9ca0-5733-e563-eeda6bb2dad0.png">

そんな時は{{ form.choice }}部分のテンプレートを以下のように修正してみてください。

```html
<ul>
{% for i in form.choice %}
  <li>
    {{ i.tag }}
    <label for="{{ i.id_for_label }}">{{ i.choice_label }}</label>
  </il>
{% endfor %}
</ul>
```

{{ i.tag }}部分にinputのタグが、{ i.id_for_label }}にinputのid名が、{{ i.choice_label }}にそれぞれの選択肢の名前が入ります。
【CSS3】hoverしたら左から色を変更するアニメーション付きボタン

# 【CSS3】hoverしたら左から色を変更するアニメーション付きボタン
### hoverしたら空のspanタグが移動してくる動作でアニメーションを表現。
#### ※今回の記事はudemyの動画を参考に書き、備忘録的な動機で投稿しています。

```html:index.html
<div id="container">
  <button class="btn slide-bg"><span></span>Button</button>
</div>
```
```css:style.css
#container {
  text-align: center;
}

.btn {
  background-color: #ffff;
  color: black;
  border: 1px solid black;
  padding: 10px 40px;
  margin: 50px 0;
  font-weight: 600;
  cursor: pointer;
  -webkit-transition: all 0.3s;
  transition: all 0.3s;
  z-index: 1;
}

.btn.slide-bg {
  position: relative;
  overflow: hidden;
}

.btn.slide-bg:hover {
  color: #ffff;
}

.btn.slide-bg:hover span {
  -webkit-transform: none;
          transform: none;
  z-index: -1;
}

.btn.slide-bg span {
  display: inline-block;
  width: 100%;
  height: 100%;
  background-color: #000;
  position: absolute;
  top: 0;
  left: 0;
  -webkit-transform: translateX(-100%);
          transform: translateX(-100%);
  -webkit-transition: -webkit-transform 0.3s;
  transition: -webkit-transform 0.3s;
  transition: transform 0.3s;
  transition: transform 0.3s, -webkit-transform 0.3s;
}
```

## 疑似要素を使う場合
```html:index.html
<div id="container">
  <button class="btn slide-bg">Button</button>
</div>
```

```css:style.css
#container {
  text-align: center;
}

.btn {
  background-color: #ffff;
  color: black;
  border: 1px solid black;
  padding: 10px 40px;
  margin: 50px 0;
  font-weight: 600;
  cursor: pointer;
  -webkit-transition: all 0.3s;
  transition: all 0.3s;
  z-index: 1;
}

.btn.slide-bg {
  position: relative;
  overflow: hidden;
}

.btn.slide-bg:hover {
  color: #ffff;
}

.btn.slide-bg:hover::before {
  -webkit-transform: none;
          transform: none;
  z-index: -1;
}

.btn.slide-bg::before {
  content: '';
  display: inline-block;
  width: 100%;
  height: 100%;
  background-color: #000;
  position: absolute;
  top: 0;
  left: 0;
  -webkit-transform: translateX(-100%);
          transform: translateX(-100%);
  -webkit-transition: -webkit-transform 0.3s;
  transition: -webkit-transform 0.3s;
  transition: transform 0.3s;
  transition: transform 0.3s, -webkit-transform 0.3s;
}
```
PCR検査を全員にしたらいいのか？そんな馬鹿な。

#はじめに
**「コロナウイルスに対してなぜ希望者全員にPCR検査をしないのか？」**ということが話題になっています。
大学院に進学したときにはじめて聞いた講演がまさにこの内容だった気がします。
理系なら医療系でなくても知っている話とおもっていて退屈でしたが、
世間の今の反応を見ると常識じゃないんですね。
関連する記事は随所に出ていますが、ここでも検証してみます。

#検査の精度
どのようなものでも100%のものはない。
病気なのに病気でないと検査結果が出たり、病気でないのに病気と検査結果が出たり。

| ウイルス\検査結果  |    陽性　 |    陰性    |
|:-----------------|:------------------:|:------------------:|
| ウイルスあり      |    a 人 |        b　人        |
| ウイルスなし      |    c 人 |        d  人     |

###感度
ウイルスありを正しく陽性と検査できる確率
P(感度)   = a / (a+b)
###特異度
ウイルスなしを正しく陰性と検査できる確率
P(特異度) = d / (c+d)
###感染率
母集団の中の感染率。
P(感染率) = (a+b) / (a+b+c+d)

http://canscreen.ncc.go.jp/yougo/11.html
https://www.cresco.co.jp/blog/entry/5987/

#特異度の違いによる陽性的中率の変化
感度を95%
特異度を99% ~ 95%　とすると

```python:sample.py
import numpy as np
import matplotlib.pyplot as plt
import itertools

p_kando_list   = [0.95]
p_tokuido_list = [0.99,0.98,0.95,0.9]
p_kansen  = 10.**np.arange(-3,0,0.01)

for p_kando, p_tokuido in itertools.product(p_kando_list,p_tokuido_list):
    p_yousei_tekityu = p_kando * p_kansen / ( p_kando * p_kansen + (1-p_tokuido) * (1-p_kansen) )
    plt.plot(p_kansen*100,p_yousei_tekityu*100,"-",label=str(p_tokuido))
plt.grid()
plt.xscale("log")
plt.title("tokuido dependence")
plt.xlabel("Kansen Rate[%]")
plt.ylabel("tekityu Rate[%]")
plt.legend()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538705/48048afd-7095-1815-35c0-99743471b855.png)

母集団の感染率が1%のとき、99%の特異度でも50%の陽性的中率。
陽性と判断されたとき二人に一人は濡れ布を着せられている。
これは陽性者にたいする風評被害がひどいらしい今、大変なこと。

#感度の違いによる陽性的中率の変化
感度を70% ~ 99%
特異度を98%　とすると

```python:sample.py
p_kando_list   = [0.7,0.8,0.9,0.95,0.99]
p_tokuido_list = [0.98] 
p_kansen  = 10.**np.arange(-3,0,0.01)
for p_kando, p_tokuido in itertools.product(p_kando_list,p_tokuido_list):
    p_yousei_tekityu = p_kando * p_kansen / ( p_kando * p_kansen + (1-p_tokuido) * (1-p_kansen) )
    plt.plot(p_kansen*100,p_yousei_tekityu*100,"-",label=str(p_kando))
plt.grid()
plt.xscale("log")
plt.title("kando dependence")
plt.xlabel("Kansen Rate[%]")
plt.ylabel("tekityu Rate[%]")
plt.legend()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538705/6f119b09-951d-e93e-1c8a-5ed9b8add718.png)

感度が高くなってもあまり陽性的中率は変わらない。
特異度が大切ですね。

#現在(3/13)の状況からの考察
データは厚労省のサイトから。
https://www.mhlw.go.jp/stf/newpage_10187.html
検査対象者 11,231人
検査陽性者 　 659人
つまり感染率は　6%弱

先ほどのグラフを見ると、感度を95%,特異度を98%だとして、
陽性的中率は80~90%ぐらいでしょう。
10人に1人ぐらいは健康なのに、入院しているのかもしれない。
無症状者が68人ってことは陽性の10%ですが、偶然の一致でしょうか。

現在濃厚接触者や有症状者など、感染が疑われる人が検査対象との話ですので、
感染率が6%ですが、気楽に無症状の人が検査を受けられるようになったら
（検査を受けた母集団の）感染率は下がるので、
偽陽性の割合がみるみる増えていきます。

無症状や濃厚接触者でもない人が、
検査を受ければ、偽陽性になる確率的には(1-特異度)×(1-陽性的中率)ですから、
特異度を98%, 陽性的中率90%として、
(1-0.98)*(1-0.9) = 0.2%　で濡れ衣。

~~(0.2%のSSRガチャか、ドロップか。余裕だな)~~

不思議なことに母集団の感染率が下がると濡れ衣率が高まります。
デマでも陽性と疑われたら会社が傾きかねないこの世の中よく考えた方がいいです。

また陰性的中率は0.06/(1-0.06)*(1-0.95)/0.98 = 0.3%。
陰性がでたとしても、
自分が6%の可能性でウイルス持っているかもしれないという状況から、
0.3%の可能性でウイルス持っているかもしれないという状況に変わることが出来ます。

個人的には不安な状況には変わりなさそうですが、どうでしょうか。

#感想
社会問題として医療崩壊の危険が言われている中、個人の視点で考えてみました。
簡易キッドが開発中とのこと。特異度に注意してニュースを見ましょう。
簡易検査受けることで不幸になる人が増えないか心配です。

#おわりに
陰性的中率の方が、話としては深刻だと思いますが、ここまでにします。
医学は全くの素人ですので、数字上の話です。なにか間違っていたら教えてください。
ビルド時に GULSceneDelegateSwizzler.h not found が発生したときの対処

`pubspec.yaml` に以下の記述を追加して、ビルドした。

```
dependencies:

  firebase_core: ^0.4.4+3
  firebase_auth: ^0.15.5+2
  cloud_firestore: ^0.13.4+2
```

すると、iOS Simulator で実行しようとした際にビルドエラーが発生。


```
#import <GoogleUtilities/GULSceneDelegateSwizzler.h>

Pods/FirebaseAuth/Firebase/Auth/Source/Auth/FIRAuth.m:32:9: 'GoogleUtilities/GULSceneDelegateSwizzler.h' file not found
```

以下のコマンドを実行

```
pod update
```

するとこんなエラーが。

```
Analyzing dependencies
[!] CocoaPods could not find compatible versions for pod "Flutter":
  In Podfile:
    Flutter (from `Flutter`)

    sqflite (from `.symlinks/plugins/sqflite/ios`) was resolved to 0.0.1, which depends on
      Flutter

Specs satisfying the `Flutter (from `Flutter`), Flutter` dependency were found, but they required a higher minimum deployment target.
```

`Flutter` をあげるために、deployment target を `11.4` に変更。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30620/9ca8c68e-3eb2-85ec-bf6a-c57928654946.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30620/c957ca74-ad8b-fa1a-07ed-668e9a640026.png)

そして

```
flutter clean
```


これでiOS Simulatorで無事実行できた。
不正なメール送信が疑われるときの対処

# 1. 送信サーバーの停止
被害を広げないため、関係者に連絡したのち送信サーバーを停止します。


# 2. ログから状況を把握

## 送信できたか、できなかったのかを調べる
ログ内のstatus項目を参照する
#### 送信できた（ただし相手がスパム判定したか不明）
```shell
cat /var/log/maillog | grep "status=sent"
```

#### 送信できなかった
```shell
cat /var/log/maillog | grep "status=deferred"
```

#### 送信で戻ってきたので再送信
```shell
cat /var/log/maillog | grep "status=bounced"
```

## ログイン状況を調べる

#### SASLを利用したログイン認証

```shell
cat /var/log/maillog | grep "sasl_method=LOGIN, sasl_username="
cat /var/log/maillog | grep "sasl_method=PLAIN, sasl_username"
```

#### POP3のログイン認証
```shell
cat /var/log/maillog | grep "pop3-login: Login: user="
```

# 3. 乗っ取られている可能性があるアカウントのパスワードを変更します
関係者に連絡したのちパスワードを変更します

# 4. 残っているメールキューを確認します
パスワード変更しただけでは、再起動時にキューに残っているメールを送信してしまいますので不正な送信キューを削除しておきます。
#### キュー数を確認
```shell
mailq | wc -l
```

#### キューの詳細を確認
誰から誰に送ろうとしているのかがわかります

```shell
mailq 
```

#### キューをすべて削除
```shell
# postsuper -d ALL
```

# 5. 送信サーバーを起動します


# 6. 送受信のテストを行います

# 7. スパムフィルタの判定状況を調べます
サーバーのIPアドレスなどを入力しチェックします。ブラックリストに入っていた場合は解除申請を行います。*Googleは解除まで時間がかかる
### proofpoint
https://ipcheck.proofpoint.com/

### TrendMicro
https://www.ers.trendmicro.com/reputations

### FortiGate
https://fortiguard.com/learnmore#as

### Google Postmaster Tools
https://postmaster.google.com/managedomains