OmniAICreator/Qiita-1.07M huggingface dataset:
MySQLのホストを範囲指定（サブネット単位）する際に気を付けること


# はじめに
MySQLにユーザを登録する際に、ホストを範囲指定したい（192.168.1.0 ~ 192.168.1.255など)

# 前提
CentOS7
MySQL5.6

# 問題
/27 (/255.255.255.224)のホストで登録したユーザがアクセス拒否になる。
*例*
`192.168.XXX.XXX/255.255.255.224`
（ちなみにCIDR形式では登録できません）

# 対応
公式のドキュメントを確認すると、以下のサブネットマスク以外は正常に機能しないようです。

- /255.0.0.0 (/8)
- /255.255.0.0 (/16)
- /255.255.255.0 (/24)
- /255.255.255.255 (/32)

/24に修正したら、正常にユーザがアクセスできました。
*例*
`192.168.XXX.XXX/255.255.255.0`

参考
[MySQL 5.6 リファレンスマニュアル 6.2.3 アカウント名の指定](https://dev.mysql.com/doc/refman/5.6/ja/account-names.html)
Vue CLIプロジェクトでコンパイル時にコードフォーマットをかける

# 前提
```
@vue/cli 4.4.1
vue create <projectName>
```
で作成したプロジェクト

- `Manually select features`
- `Linter/Formatter` にチェック
- `Pick a linter / formatter config > ESLint + Prettier`
- `Pick additional lint features > Lint on save`

lintエラーがある場合コンソールにメッセージが出るだけで
手動での修正が面倒なので、ファイル保存時に自動修正したいです。

ググればVScodeの設定でやる方法がわんさかあるのですが、
今回はエディターに依存したくなかったのでwebpack経由で自動修正をします。

なので、ファイル保存時ではなくコンパイル時ということになります。
また、どこからもimportされていないファイルや設定系ファイルなど、
webpackを通らないファイルに関しては自動修正されません。

# 設定方法

## vue.config.js
Vue CLIでは `vue.config.js`の`configureWebpack`でwebpackの設定をマージできます。
[Configuration Reference | Vue CLI](https://cli.vuejs.org/config/#configurewebpack)

ということでプロジェクトルートに `vue.config.js` ファイルを作成して以下を記述。

```vue.config.js
module.exports = {
  configureWebpack: {
    module: {
      rules: [
        {
          enforce: 'pre',
          test: /\.(jsx?|tsx?|vue)$/,
          exclude: /node_modules/,
          loader: 'eslint-loader',
          options: {
            fix: true
          }
        }
      ]
    }
  }
}
```

## .eslintrc.js
デフォルトのママ

```.eslintrc.js
module.exports = {
  root: true,
  env: {
    node: true
  },
  extends: [
    'plugin:vue/essential',
    'eslint:recommended',
    '@vue/typescript/recommended',
    '@vue/prettier',
    '@vue/prettier/@typescript-eslint'
  ],
  parserOptions: {
    ecmaVersion: 2020
  },
  rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
  }
}

```

## .prettierrc
プロジェクトルートに `.prettierrc` ファイルを作成してお好みの設定を記述

```..prettierrc
{
  "semi": false,
  "arrowParens": "always",
  "singleQuote": true
}

```

## おしまいける
以上で設定完了です。

```保存前.vue
<script lang="ts">
// 略
  private hoge = "hoge";
// 略
</script>
```

```保存後.vue
<script lang="ts">
// 略
  private hoge = 'hoge'
// 略
</script>
```

これで`npm run serve`でサーバを立ち上げてる間、ファイル保存時に自動フォーマットが効いてくれます。
もちろん `npm run serve`, `npm run build` 実行時にも効きます。

冒頭にも記載した通りwebpackを経由しないファイルは修正されないので、
lintコマンドを活用しましょう


# 参考
[Configuration Reference | Vue CLI](https://cli.vuejs.org/config/#configurewebpack)
Flutter の Android Studio でデバッグ中に Exception で止まらないようにする

なかなか設定場所を見つけられなかったのでメモ。
# 概要
Flutterの開発で、Android Studioを使っています。APIを叩いたときに認証エラー等で401が戻ってきたとき、Exceptionが発生します。
Android Studio？では、Exceptionが発生すると、デバッグ中は強制的にストップし、該当場所を開いてくれるのですが、毎回うっとおしいので止めたいのです。
私は、http通信でDioモジュールを使っているので、DioErrorが発生していました。

# やったこと
1. View Breakpoints を開く  
![Screen Shot 2020-05-29 at 16.45.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315258/856a673b-2c7e-23fc-3e72-f9efbe84948d.png)
2. Break on exceptions の Suspend のチェックを外す  
![Screen Shot 2020-05-29 at 16.39.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315258/1585de7c-2315-6dc5-d999-8afae0eb177d.png)

これでExceptionが発生しても止まりません！
WP ACF Selectで返り値Bothの出力

返り値BothでValueもlabelもとりたいとき。
例えばValueをクラス名として、labelはそのまま表示みたいな。

公式docにあるものがなんかうまくいかなかったから備忘録。


#方法

`value : label`

`:`の前後に半角スペース忘れない。
Valueは半角英数字のみ。

1. カスタムフィールドで、値とラベルを入れてSelectを作る。返り値をBothにする。
2. 出力するテンプレートでこう書く

```templete.php

<?php //ループ内 ?>

<?php 
  $field = get_field('select', $post->ID); 
?>
<div class="<?php echo $field['value']; ?>">
  <?php echo $field['label']; ?>
</div>

```


これだけのことなんだけど苦労した・・・。
【SEO】【構造化データ】LocalBusiness

##LocalBusiness
以下の実装をしたケースの紹介です。
https://developers.google.com/search/docs/data-types/local-business?hl=ja

##コード
今回は[こちらのページ](https://evsmart.net/spot/tokyo/l131024/v923/)に実装した例です。
このページは電気自動車の充電スポット情報のページになります。
テンプレート側で変数をechoしています。

```structuredData.template
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "LocalBusiness",
  "image": [
    "<?php echo $point_img; ?>"
  ],
  "@id": "<?php echo $point_pageUrl; ?>#LocalBusiness",
  "name": "<?php echo str_replace('"', '\"', $point_name); ?> EV電気自動車 充電スタンド",
  "address":
  {
    "streetAddress":"<?php echo $point_postal; ?>"
  },
  "description":"<?php echo str_replace('"', '\"', $point_name); ?>の充電スタンド情報ページです。利用可能時間や料金、プラグ形状、そしてユーザーの口コミなど情報満載！",
  "geo": {
    "@type": "GeoCoordinates",
    "latitude": <?php echo $point_latitude; ?>,
    "longitude": <?php echo $point_longitude; ?>
  },
  "url": "<?php echo $point_pageUrl; ?>",
  "telephone": "<?php echo $point_phoneNumber; ?>",
  "openingHours": ["Mo-Fr <?php echo $point_openingTimeWkStr; ?>", "Sa <?php echo $point_openingTimeSaStr; ?>", "Su <?php echo $point_openingTimeSuStr; ?>"]
}
</script>
```

テストツールで見ると[こんな感じ](https://search.google.com/structured-data/testing-tool/u/0/?hl=ja#url=https%3A%2F%2Fevsmart.net%2Fspot%2Ftokyo%2Fl131024%2Fv923%2F)です。
AndroidStudio 3.6.3を日本語化する

#はじめに
Android Studioを日本語化するところまで確認したいと思います。

#環境と前提条件
- windows10
- Android Studio 3.6.3(64bit)

Android Studioがインストールされていることが前提です。
インストール方法は[こちら](https://qiita.com/kepin/items/cccb27d5ba4857d46bb2)を参考にしてみてください。

#プラグインをダウンロードする

[こちら](https://mergedoc.osdn.jp/)からプラグインをダウンロードします。

リンクを開いたら、 Pleiades プラグイン・ダウンロードのwindowsボタンを押下します。
あと、7-zipで解凍云々と書かれていますね。公式に従い、インストールしていない場合は7-zipもインストールします。後ほど使います。
![2020-05-28 (34).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645318/dfcd4194-bcef-5639-389a-372b1ddd56d3.png)

続いて、リンクを押下します。ダウンロードされるまでしばし待ちましょう。。。
![2020-05-28 (36).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645318/da65cc1d-0aad-4dbe-035a-609532c234fb.png)

ダウンロードが完了したら7-zipで解凍します。
（展開されたファイルはひとつのフォルダにまとめました。）
![2020-05-28 (10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645318/fe824b53-e77a-4bc0-17e0-2bbe5e43d73e.png)

#日本語化する
続いて、setup.exeを起動します。
![2020-05-28 (35).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645318/6b77893b-4947-48f3-8c59-b975a8b25cdb.png)

日本語化するアプリケーションを選択します。
デフォルトであればC:\Program Files\Android\Android Studio\bin\studio64.exeです。
![2020-05-28 (12).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645318/164fb300-f498-159d-52a2-780c81e62901.png)

日本語化します。これはすぐに終わります。
![2020-05-28 (14).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645318/ce134383-a47a-446b-1de1-d2c87074fa61.png)

次にAndroid Studioが日本語化されているか、確認します。
![2020-05-29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645318/c9efc3a6-3251-1979-07d8-aded46361f9d.png)
できました！

#さいごに
Android Studio 3.6.3を日本語化できることを確認しました。

#参考にしたサイト
https://neet-rookie.hatenablog.com/entry/2019/04/27/104248
msys2でbash環境を簡単に整えた話

# はじめに
大学でmacやubuntuのようなlinux系のbashを使って作業することが多かったのでwindowsでもその環境を実現したいと思いました．

# Msys2の導入

Msys2とはwindows上でUnixシェルなどのツールを統合したパッケージでこちらを導入することでUnixライクなBash環境を整えることができます．Cygwinやgitbashなどもありますが今回はこちらを使っていこうと思います.
[msys2の64bit版をこちらからダウンロードしてください](https://www.msys2.org/)

インストール場所はデフォルトではCドライブ直下となっていますが，お好みで大丈夫です．<br>ただProgram Filesのようなスペースが空いているフォルダ名がpathに入りますとmakeなどする時に失敗することがあったのでやめたほうがいいでしょう.


## packageのインストールと更新

msys2をインストールしたらまずmsys2.exeまたはmingw64.exeを開きましょう．
試しにtreeコマンドをインストールしてみましょうtreeはディレクトリを階層別に表示してくれるコマンドです．便利なので覚えておくと良いと思います.<br>macを使っている人なら`brew install`, linuxなら`apt-get install`と同じようにmsys2では`pacman -S` でパッケージのインストールが行えます.


```bash:packageのインストール
pacman -S tree
```

```bash:treeコマンドの実行
tree -L 2
## ２階層分表示します
```

c言語を使う人であればよく使うであろうgccもこれで導入が終わります.


以下のコマンドを打ち込むと内部のパッケージのアップデートが行えます.

```bash:packageの更新
pacman -Syu
```

# システム環境変数が使えない場合
msys2では環境変数にMSYS2_PATH，値をinheritで追加してmingw32.ini,mingw64.ini msys2.iniの4行目のコメントアウトを取るとmsys2上でシステム環境変数が使えるようになります.<br>パスが通っているかの確認にはwhichコマンドなどを使うといいでしょう.

# vscodeでmsys2のbashを使うには
vscodeならterminalの拡張機能をインストールして参照するファイル名を(自分の環境のpath)/msys2/usr/bin/bash.exeに書き換えましょう．JetbrainsのIDEでも同じようにしてbashの変更が可能です.
shell実行時のエラー出力を評価する

bq loadする際に特定のエラー時に処理やらせたいとかがあって、エラー出力でifとか書く方法を探した際のメモ。

```sh
#!/bin/sh

message=$(ls /no/file 2>& 1)
exit_code=$?

if [ "$(echo ${message} | grep 'No such file or directory')" ]; then
  echo "error happened(${exit_code})"
fi
```
Catalina で git svn コマンドが効かない時

Catalina で git svn clone ができなかったのでメモ。


```
% git svn 
git: 'svn' is not a git command. See 'git --help'.

The most similar commands are
    fsck
    mv
    show
```

Catalina は Subversion をデフォルトではサポートしなくなったらしく、コマンドラインツールを入れ直す必要があるとのこと。
https://developer.apple.com/documentation/macos_release_notes/macos_catalina_10_15_release_notes?language=objc#3318263

```
 % rm -Rf /Library/Developer/CommandLineTools
 % xcode-select --install
```

それでも git svn のコマンドがないよと言われたら初歩的な部分を見直し。

Subversion と Git が入っているか確認。なければHomebrewで入れる。

```
% svn help

%　git --version
git version 2.20.0 (Apple Git-117)
　
% brew install svn
% brew install git
```
apple の git が優先になっていれば入れた git を優先させる

```
% echo 'export PATH="/usr/local/opt/git/bin:$PATH"' >> ~/.zshrc
% source ~/.zshrc
% which git
 /usr/local/opt/git/bin/git
```
今回解決に時間がかかったのは入れたgitを使うようにパス指定したつもりが、
apple の git が優先され続けていたからでした。

追記
MBP を初期化をおこなった際に、clone ができなくなったので追記します。

1.Perl に問題があるようなので Perl をインストール、足りない物を追加。

```
% sudo cpan SVN::Core
% brew install perl
% exec $SHELL -l
% sudo mkdir /Library/Perl/5.18/auto
% sudo ln -s /Applications/Xcode.app/Contents/Developer/Library/Perl/5.18/darwin-thread-multi\u200c-2level/SVN /Library/Perl/5.18/darwin-thread-multi-2level
% sudo ln -s /Applications/Xcode.app/Contents/Developer/Library/Perl/5.18/darwin-thread-multi\u200c-2level/auto/SVN /Library/Perl/5.18/auto/
exec $SHELL -l
```
2.Perl 内のパス変更をおこなう

パス変更
ファイル`/usr/local/opt/git/libexec/git-core/git-svn`
`#!/usr/bin/perl` から `#!/usr/local/bin/perl`へ

3.checkout し直す

```
% svn checkout --username SampleName --password SamplePassword https://sample.co.jp
% git svn clone https://sample.co.jp
```
SampleName と SamplePassword に自分のユーザーネームとパスワードを入力。
【SEO】【構造化データ】Product

##Product
以下の実装をしたケースの紹介です。
https://developers.google.com/search/docs/data-types/product?hl=ja

今回のページの場合は売り物ではなく全国の車のカタログのため推奨フィールドは空が多いです。
ただこのようなケースでも必須フィールドを埋めれば適用することができます。

##コード
製品が1つしかなかったのでテンプレート側で変数をechoする対応にしました。
今回は[こちらのページ](https://evsmart.net/carMaker/Tesla/ModelS/LongRange/)に実装した例です。

製品が複数の場合の実装は[こちら](https://qiita.com/bubbles/items/09d3d021dae4624e3964)をご参照ください。

```structuredData.template
<script type="application/ld+json">
[
  {
    "@context" : "https://schema.org",
    "@type" : "Product",
    "name" : "<?php echo $name;?>",
    "image" : "<?php echo $imagePath;?>",
    "url" : "<?php echo $url;?>",
    "brand" : {
      "@type" : "Brand",
      "name" : "<?php echo str_replace('"', '\"', $brand);?>"
    },
    "offers": {
      "@type" : "Offer",
      "price" : "<?php echo $price;?>",
      "priceCurrency" : "JPY"
    }
  }
]
</script>
```

テストツールで見ると[こんな感じ](https://search.google.com/structured-data/testing-tool/u/0/?hl=ja#url=https%3A%2F%2Fevsmart.net%2FcarMaker%2FTesla%2FModelS%2FLongRange%2F)です。
Objective-Cで三項演算子のYESの場合を省略する

## 背景
案件のコード見てたらすごく簡潔に書かれた三項演算子があった！
まさかこんな書き方ができるとは知らなかったので、メモしておきます。

## コード
```objc

NSDictionary *dic = @{@"a": @"AAA", @"b": @"BBB"};

NSString *str = dic[@"b"] ? : @"";
NSLOG(@"str: %@", str);
// str: BBB

str = dic[@"c"] ? : @"";
NSLOG(@"str: %@", str);
// str: 
```

## Swift だったら...
Swiftならデフォルト値入れるだけで🙆‍♀️
Swift便利だな〜

```swift
let dic = ["a": "AAA", "b": "BBB"]
var str = dic["b"] ?? ""
// str : BBB
print("str : \(str)")

str = dic["c"] ?? ""
print("str : \(str)")
// str :
```

## まとめ
Objective-Cでは三項演算子の第2項は省略できる👍
Swiftはデフォルト値入れるだけで、nilの場合の値が決めれる👍

## 参考
- [３項演算子の第２項は省略できる。](https://qiita.com/KatagiriSo/items/e4138c4e550473e6e96d) @KatagiriSo
SF symbolsの使い方

#iOSでよく使われる画像を使いたい
![clip_image.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/7a2dd745-34fc-c4d4-8cf8-49e2ad24ee18.jpeg)   ![test1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/97df25ef-55ce-adea-008f-c0f6dec6fd14.png)    ![test2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/5b5a078d-9b78-ccbd-7bf3-c9bff84e3ae6.png)


上のような画像が使いたい時、あると思います。
これらの画像はそれぞれ
`Image(systemName: "paperclip")`
`Image(systemName: "folder.fill")`
`Image(systemName: "square.and.arrow.up")`
で表示することができます。(SwiftUIを想定しています)


[App公式サイト](https://developer.apple.com/design/human-interface-guidelines/sf-symbols/overview/)にある download the SF Symbols app をクリックしダウンロードをし表示される手続きに従うと、Launchpadにアプリが追加されます。
<img width="141" alt="スクリーンショット 2020-05-29 16.11.15.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/fddef459-1866-9678-e4c0-6e7859c6c462.jpeg">

このアプリでは上で表示したpaperclipなどの名前とその画像が表示されます。
<img width="796" alt="スクリーンショット 2020-05-29 16.14.42.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/2cb42362-b297-b1a4-9ad1-7d96a8ba477c.jpeg">

あとは使いたい画像を選択し、Image(systemName: "")のようにすれば、画像を表示することができます。
Ruby ビンゴカード作成問題　解いてみた(解答例あり)

# はじめに
『プロを目指す人のためのRuby入門』通称チェリー本を学習後のプログラミング初心者です。
インプットしたものを手を動かして実践してみたいなと思ったら、作者の記事を見つけました。
[「アウトプットのネタに困ったらこれ！？Ruby初心者向けのプログラミング問題を集めてみた（全10問）」](https://blog.jnito.com/entry/2019/05/03/121235)

この3つ目の問題を解いてみました。

他の問題はこちら
[一問目](https://qiita.com/u_nayama/items/389b229bd569fdfc1874)：カレンダー作成問題（たのしいRuby　練習問題）
[二問目](https://qiita.com/u_nayama/items/6009dcfe148e15ad9e1b)：カラオケマシン作成問題
[三問目](https://qiita.com/u_nayama/items/7be7e6c5661d93272de8)：ビンゴカード作成問題
[四問目](https://qiita.com/u_nayama/items/82edf9500c0cdfc263f7)：ボーナスドリンク問題
[五問目](https://qiita.com/u_nayama/items/53c2a4b58840dbccaaf9)：電話帳作成問題

#　問題
詳細は[ここから](https://blog.jnito.com/entry/2015/02/09/101018)
>B：1～15のどれか
I：16～30のどれか
N：31～45のどれか
G：46～60のどれか
O：61～75のどれか
というルールで次のようなビンゴカードを作ります。

>```ruby
 B |  I |  N |  G |  O
13 | 22 | 32 | 48 | 61
 3 | 23 | 43 | 53 | 63
 4 | 19 |    | 60 | 65
12 | 16 | 44 | 50 | 75
 2 | 28 | 33 | 56 | 68
```
>Bingo.generate_card メソッドの出力結果は上で述べた数字のルールのほかに、以下の仕様を満たす必要があります。
 - 毎回異なるカードを生成します。
 - 各列はパイプ（|）で区切ります。
 - 数字や"BINGO"の文字は右寄せで出力します。
 - 真ん中（FREEになる場所）はスペースを出力します。



# 解答例
こんな感じになりました。

```ruby
class Bingo
  def self.generate_card
    title = "BINGO".split("").map{|bingo| sprintf("%2s",bingo)}.join(" | ")

    numbers = [*1..75].each_slice(15).to_a.map{|b| b.sample(5)}
    numbers[2][2] = "  "
    body = []
    for i in 0..4
      body << numbers.map{|number| sprintf("%2s",number[i])}.join(' | ')
    end

    [title,body].join("\n")
  end
end
```

# さいごに

下記リンクに他の方の解答も掲載されていました。
[Ruby -「ビンゴカード作成問題」の優秀作品ベスト3を発表します！](https://blog.jnito.com/entry/2015/03/06/085433)

`transposeメソッド`など、知らなかったので使いませんでしたが他の方の解答をみるに、まだまだリファクタリングの余地はありそうです。

ご意見等あればコメントで教えてください。
よろしくお願いします。
【SEO】【構造化データ】Product（複数）

##Product
以下の実装をしたケースの紹介です。
https://developers.google.com/search/docs/data-types/product?hl=ja

今回のページの場合は売り物ではなく全国の車のカタログのため推奨フィールドは空が多いです。
ただこのようなケースでも必須フィールドを埋めれば適用することができます。

##コード
テンプレート側にベタ書きでも良かったのですがテンプレートはなるべくスッキリさせたいのと元々裏側でforeachしていたのでそこに入れ込みたく、値を変数に入れてテンプレート側で表示するようにしました。

今回は[こちらのページ](https://evsmart.net/carMaker/Tesla/ModelS/)に実装した例です。

```structuredData.php

foreach($cars as $key=>$car){
  $structuredData[] = array(
    "@context" => "https://schema.org",
    "@type" => "Product",
    "name" => $car['Name'],
    "image" => $car['ImagePath'],
    "url" => $car['PageUrl'],
    "brand" => array(
      "@type" => "Brand",
      "name" => $car['BrandName']
    ),
    "offers" => array(
      "@type" => "Offer",
      "price" => $car['Price'],
      "priceCurrency" => "JPY"
    ),
  );
}
$structuredData = json_encode($structuredData);
```

```structuredData.template
<script type="application/ld+json">
<?php
if(isset($structuredData) && !empty($structuredData)){
    if($structuredData != '[]'){
        echo $structuredData;
    }
}
?>
</script>
```

テストツールで見ると[こんな感じ](https://search.google.com/structured-data/testing-tool/u/0/?hl=ja#url=https%3A%2F%2Fevsmart.net%2FcarMaker%2FTesla%2FModelS%2F)です。
LinuxでDeepL翻訳

# LinuxでDeepL翻訳

DeepLを論文読みなどに使ってらっしゃる方多いですよね．
[公式アプリケーション](https://www.deepl.com/ja/app/)を使えば，`Ctrl(Cmd) + C`を2回押すことによりポップアップが表示され，DeepLで翻訳してくれます．改行なども取り除いてくれます．
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">DeepLの場合、専用のアプリをインストール（無料）すると、<br><br>①翻訳したいテキストをハイライト（5000文字まで）<br><br>②「Command+C」（Windowsは Ctrl+C）を２回押す<br><br>③ポップアップの画面が現れ、翻訳の結果が見れる<br><br>この一連の流れがとても便利。同画面では原文を参照しながら翻訳を直すことも可📝。 <a href="https://t.co/x5o2Rb6xJI">pic.twitter.com/x5o2Rb6xJI</a></p>&mdash; Sangmin @ChoimiraiSchool (@gijigae) <a href="https://twitter.com/gijigae/status/1265231960927924224?ref_src=twsrc%5Etfw">May 26, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

しかしこのアプリケーション，WindowsとMacでしか動きません．そこで，Linuxで同じ機能を実現するシェルスクリプトを作ったので紹介します．
![deepl-clip.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638807/dd596bd0-b956-8ede-9eda-957a0341641a.gif)

## インストール(簡単)
Ubuntu (Debian系) なら

```shell
sudo apt install xclip nkf
curl -OL https://github.com/masan4444/deepl-clip/releases/latest/download/deepl-clip.sh
chmod u+x deepl-clip.sh
```
CentOS (RedHat系) なら

```shell
yum install epel-release
yum install xclip nkf
curl -OL https://github.com/masan4444/deepl-clip/releases/latest/download/deepl-clip.sh
chmod u+x deepl-clip.sh
```

## 使い方
使い方も簡単で

```shell
sh deepl-clip.sh
```
ブラウザでDeepLのサイトを開いて，クリップボードの中身を貼り付けてくれます．

しかし，この機能が便利なのは，ショートカットを設定してからです．
Ubuntu18.04なら`設定 > デバイス > キーボード > 独自のショートカット`からショートカットを設定することで，公式アプリのような機能を実現します．

その際，スクリプトのフルパスを指定しないといけません． 
(`/full/path/to/`の部分をご自身の環境に合わせて変えてくだい)
![deepl-clip_shortcut.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638807/e80b311f-b6c2-bf31-4841-e7ee8c426707.png)

あとは`Ctrl+C`x2が設定できれば完璧なのですが．．
基本的には

1. `Ctrl+C`でクリップボードにコピー
2. `Ctrl+?`でスクリプトを起動

という使い方をします．

## 最後に
バグ報告，要望などがあれば[Issues](https://github.com/masan4444/deepl-clip/issues)やこの記事のコメントに投稿してただけると幸いです．
ホロジュールをスクレイピングしてCLIで表示する

ホロライブの配信スケジュールであるホロジュールをスクレイピングして内容を簡易的にCLIで表示するプログラムを作りました。　
# ソースコード
[GitHub](https://github.com/TeepaBlue/holo-schedule-CLI)

## 利用上の注意
このツールは外部ライブラリとしてrequestsを使っています。pipをすでにインストールしている場合
<b>pip install requests</b> で対応できます

また、このツールはホロライブ公式と全く関係がありません。必要以上の実行でサーバーに負担をかけないようにしてください。

###使い方
リポジトリ内のmain.pyを実行することで以下のような内容を表示できます。
![alt](https://user-images.githubusercontent.com/42367122/79976625-e26f4700-84d7-11ea-9e36-e5262e317fbd.png)

また、実行時にオプションをつけることができ、--helpでその内容を確認することができます。例として、

- --all ホロスターズなどを含む、Bilibili動画以外のすべてのスケジュールを表示
- --eng メンバーの名前を英語で表示
- --tomorrow 明日のスケジュールを表示

などが使えます。これらのオプションは同時に設定して実行することができます。

####Notes 
製作にあたり、自分が詰まったところをメモします。

まず、スクレイピングで得られたデータの中から、どのようにホロライブメンバーとそれ以外を分けるか悩みました。対応として、

```python:scraping.py
def delete_exception(time_list, stream_members_list, stream_url_list, is_all):

    EXCEPTION_LIST = {'Yogiri', 'Civia', 'SpadeEcho', 'Doris', 'Artia', 'Rosalyn'}

    if not is_all:
        #Slice to get only non-hololive members (e.g. holostars hololive-ID)
        EXCEPTION_LIST =  EXCEPTION_LIST | set(get_member_list()[29:])

    for i in range(len(time_list)):

        if stream_members_list[i] in EXCEPTION_LIST:
            time_list[i] = None
            stream_members_list[i] = None
            stream_url_list[i] = None

    time_list = [i for i in time_list if not i is None]
    stream_members_list = [i for i in stream_members_list if not i is None]
    stream_url_list = [i for i in stream_url_list if not i is None]

    return time_list, stream_members_list, stream_url_list
```
ホロライブのYoutube配信のメンバーと、Bilibili配信のメンバーの集合を予め用意しておき、
オプションなどから、除外するメンバーの集合を作り、それに属するスクレイピングした要素をNoneに置き換え、最後にまとめて内包表記で削除するようにしました。

ちなみに、リストでも同じように実装できますが、要素の番号がいらない場合、リストよりも集合を使ったほうが何倍も早いです。

<hr>
もう一つ困ったこととして、名前が英語のメンバーと日本語のメンバーがいることで、半角全角の違いから列をきれいに揃えて表示できないという問題がありました。これを解決するために、標準ライブラリの<b>unicodedata</b>を使いました。

```python:unicode
if unicodedata.east_asian_width(stream_members_list[i][0]) == 'W': 
    m_space = ' ' * ( (-2 * len(stream_members_list[i]) + 18))               

else:
    m_space = ' ' * ( (-1 * len(stream_members_list[i]) ) + 18)
```

unicodedataのeast_asian_widthは引数の文字(Charであるため一文字)が全角日本語の文字の場合Wを返してくれます。これによって、名前の文字数なども考慮しつつ、スペースを用いて揃った行で表示させることができました。

#####最後に
すでに何人かにクローンされていて嬉しく感じます。今後もこのリポジトリの改善に努めたいと思います。
node-addon-apiについて

# Node-addon-api について

node.jsから、CやC++のAPIを直接実行するためには、
[N-API](https://nodejs.org/api/n-api.html) を使用することになるが、非常に複雑で、コーディングが面倒になるので、
C++でN-APIをラップした[node-addon-api](https://github.com/nodejs/node-addon-api)を使用したほうが良い。

ただ、Javascriptの知識と、C++の知識（メモリ管理等）が必要となりますが、
基本的に細かい制御はクラスライブラリがやってくれるので、
実装に集中できます。

## ビルド方法

### package.jsonの準備

まずは、package.json を準備する。
bindingsとnode-addon-apiをインストールします。

```shell
npm init # 初期設定
npm install bindings node-addon-api
```

### binding.gypファイル

binding.gypファイルを作成して、C++のビルト環境を作成します。

```JSON
{
"targets": [ 
     { 
       "target_name": "hello", 
       "cflags!": [ "-fno-exceptions" ], 
       "cflags_cc!": [ "-fno-exceptions" ], 
       "sources": [ "hello.cpp" ], 
       "include_dirs": [ 
         "<!@(node -p \"require('node-addon-api').include\")" 
       ], 
       'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ], 
     } 
   ] 
 } 

```

### hello.cpp

cpp ファイルを作成します。

```cpp
#include <napi.h>

Napi::String Method(const Napi::CallbackInfo& info) {
  Napi::Env env = info.Env();
  return Napi::String::New(env, "world");
}

Napi::Object Init(Napi::Env env, Napi::Object exports) {
  exports.Set(Napi::String::New(env, "hello"),
              Napi::Function::New(env, Method));
  return exports;
}

NODE_API_MODULE(hello, Init)
```



#### C++の説明

NODE_API_MODULE(hello, Init) 
 
javascriptとの接続するためのマクロ
Init　関数内でエクスポートするファンクションを定義する。
exports.SetでhelloというjavascriptのメソッドをMethodというC++関数に割り当てている。

Method関数内で、worldという文字列を返している。


### hello.js

```Javascript
var addon = require('bindings')('hello');

console.log(addon.hello()); // 'world'
```

bindingsモジュールをロードして,
helloを呼び出します。

## ビルド

```
npm install
```

を実行すると、C++のコンパイラが実行され、ビルドされます。


## 実行

```
node hello.js
```

を実行するとworldという文字列が表示されると思います。


# 終わりに

以下の例は、ほぼ　node-addon-apiの[サンプル](https://github.com/nodejs/node-addon-examples/tree/master/1_hello_world/node-addon-api)を元にしました。

https://github.com/fore-vision/node-addon-api　
上にサンプルとドキュメントがあるので、色々できると思います。
GitのPackfileの容量が増えすぎて、パソコンが身動き取れなくなった日

## はじめに
先日、パソコンの容量が埋まってしまい作業ができる状態ではなくなった。不要なファイルやアプリをとことん消したが解決には至らなかった為、より探ってみた。

<br>

```
No space left on device
```
コマンドも打てない...


## 原因
- 大量のバイナリファイルを抱えていたので、`.git/oblects/pack/`が肥大化していた。



<br>

## `Packfile`とは
- そもそもgitでは`git init`をしたとき、objectsファイル内に`pack`ファイルが作られる。そしてcommitをした際に新しいobjectファイルとして`.git/oblects/pack/`に圧縮するらしい。



## パソコンの容量を空けた手順
- 容量を確認。

```
du -sh .git/objects
```

- 何がパックされているか、ファイルの中身を見ることができる。

```
git verify-pack -v .git/objects/pack/パックファイル
```


- `.git/objects/pack/`の`tmp_pack_オブジェクトID`のファイルを削除。

- 今回はとりあえず、リモートはそのままにローカルの容量を空けたいだけなので、commit履歴自体は消さず、歴史の改変も行わない。


## 終わりに
- 200GBも開けることができた。
- 不要なファイルとしてコミット履歴やリモートからも消したいのであれば、下の`参考`などを元に進める必要がある。
- pushする際に`git gc`コマンドで、何がパックされているか確認することもできる。
- バイナリをgitで管理するのはあまり得策ではないように思う...

 

## 参考
- [Gitリポジトリをメンテナンスして軽量化する](https://qiita.com/kaneshin/items/0d19fc1cd86f931dc855)
- [gitリポジトリに入れた巨大なファイルの履歴を削除する](https://livingdead0812.hatenablog.com/entry/2019/10/18/180033)
- [HowTo completely remove a file from Git history](https://www.ducea.com/2012/02/07/howto-completely-remove-a-file-from-git-history/)
- [10.2 Gitの内側 - Gitオブジェクト](https://git-scm.com/book/ja/v2/Git%E3%81%AE%E5%86%85%E5%81%B4-Git%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88)
- [Gitの.git/objectsの中身を追ってみる](https://note.gosyujin.com/2013/12/14/git-dotgit-objects/)
- [Gitの驚愕の真実：1億行のファイルに1行追記するとレポジトリ容量が200MB増える[※補足あり]](http://dqn.sakusakutto.jp/2013/09/git_add_very_large_file.html)
- [A3.11 Appendix C: Git Commands - Administration](https://git-scm.com/book/en/v2/Appendix-C%3A-Git-Commands-Administration)
- [gitのレポジトリ容量の削減に失敗しないためのチェックポイント](https://qiita.com/knknkn1162/items/5055daf197c3e751377f)
- [git filter-branchで過去の全てのcommitから画像ファイルの追加/変更をなかったことにしてリポジトリを軽量化する](https://dskd.jp/archives/46.html)
RustでUniversalRobotsの向けのCLIツールを作ってみた

RustでUniversal Robots社のロボットURシリーズを動かすためのツールを作ったので自慢したい。

## 対象とする読者

この記事はRustでUniversalRobotsのロボットを使う必要が出てきたプログラマ向けに書いています。

## 環境

- コントロールボックス eシリーズ v5.8
- ロボット UR16e(URSimで動作確認)
- 言語 Rust 1.42.0
- 使用ライブラリ clap(CLIパーサとして使用)

## 何を作ったか

以下の操作を行うツールを作成しました。

- スクリプトを記述したテキストファイル読み込みソケットでロボットに送信する
- DashboardServerのload/playを操作

[この記事](https://qiita.com/MrBearing/items/a09ab5751be9333cddc5)で解説しましたが、
Universal Robotsのロボットはスクリプトを受信するためのTCPポートを持っています。

このツールは、[この記事](https://qiita.com/MrBearing/items/3d1cbc7fe268888d9500)で書いた内容をRustで書き直しただけです。
DashboardServer周りの機能を追加しcrate.ioで公開しました。

## インストール方法

```shell
cargo install rur
```

## 操作方法

スクリプトファイルを送信する

```shell
rur send_script -r ur_ip_address test.script
```

Dashboard Severにtest.urpをロードして実行させる

```shell
$ rur ds load test.urp
$ rur ds play
start program...
```

## 今後やること
- サブコマンドをもう少し充実させる
- テスト環境をDockerで構築できるようにする(Dockerの勉強先か。。)
PDFテキストコンテンツを抽出するJava

日常の作業では、巨大なPDFドキュメントに含まれているテキストコンテンツを抽出する必要がある場合があります。そして、Free Spire.PDF for Javaは、便利で高速なテキスト抽出方法を提供します、次に、プロセスで使用されるJavaコードを紹介します。

**基本的な手順：**
**1.** [Free Spire.PDF for Java](https://www.e-iceblue.com/Download/pdf-for-java-free.html)パッケージをダウンロードして解凍します。
**2.** libフォルダーのSpire.Pdf.jarパッケージを依存関係としてJavaアプリケーションにインポートするか、MavenリポジトリーからJARパッケージをインストールします（pom.xmlファイルを構成するコードについては、以下を参照してください）。
**3.** Javaアプリケーションで、新しいJava Class（ここではExtractTextという名前）を作成し、対応するJavaコードを入力して実行します。

**pom.xmlファイルを構成します：**

```java
<repositories>
   <repository>
      <id>com.e-iceblue</id>
      <name>e-iceblue</name>
      <url>http://repo.e-iceblue.com/nexus/content/groups/public/</url>
   </repository>
</repositories>
<dependencies>
   <dependency>
      <groupId>e-iceblue</groupId>
      <artifactId>spire.pdf.free</artifactId>
      <version>2.6.3</version>
   </dependency>
</dependencies>
```


**PDFソースドキュメントは次のとおりです：**
![sample.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/50fa36b1-4ccf-b4b5-7bf7-09ecb32ff584.jpeg)


**Javaコード：**

```java

import com.spire.pdf.PdfDocument;
import com.spire.pdf.PdfPageBase;
import java.io.*;

public class ExtractText {

    public static void main(String[] args) {

        //PdfDocumentインスタンスを作成する
        PdfDocument doc = new PdfDocument();
        //PDFファイルをロード
        doc.loadFromFile("雪.pdf");

        //StringBuilderインスタンスを作成する
        StringBuilder sb = new StringBuilder();

        PdfPageBase page;
        //PDFページをトラバースし、各ページのテキストを取得して、StringBuilderオブジェクトに追加します
        for(int i= 0;i<doc.getPages().getCount();i++){
            page = doc.getPages().get(i);
            sb.append(page.extractText(true));
        }
        FileWriter writer;
        try {
            //StringBuilderオブジェクトのテキストをテキストファイルに書き込みます
            writer = new FileWriter("ExtractText.txt");
            writer.write(sb.toString());
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }

        doc.close();
    }
}
```


**結果を抽出する：**
![text.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/a996ceaa-4fcf-6947-29d8-4b2a27100046.jpeg)
AWS Migration Hub とは?

#AWS Migration Hub とは?
> AWS Migration Hub を使用すると、1 か所で既存のサーバーを検出し、移行を計画して、各アプリケーションの移行ステータスを追跡できます。AWS Migration Hub は、アプリケーションポートフォリオを可視化し、計画と追跡を簡素化します。使用している移行ツールに関係なく、移行する各アプリケーションを構成するサーバーとデータベースのステータスを確認できます。

> AWS Migration Hub では、移行をすぐに開始し、移行中にサーバーをグループ化するか、最初にサーバーを検出してからアプリケーションにグループ化するかを選択できます。どちらの方法でも、アプリケーション内の各サーバーを移行し、AWS Migration Hub の各ツールから進行状況を追跡できます。ネイティブの AWS のサービス AWS Database Migration Service、AWS Server Migration Service、および CloudEndure 移行、およびパートナーツールの ATADATA ATAmotion および RiverMeadow 移行 SaaS からの移行をサポートします。

##2 つの使用開始方法
* 検出を実行してから移行する
* 検出を実行せずに移行する

###検出を実行してから移行する
> 移行を追跡するためにサーバーとアプリケーションに関するデータを AWS Migration Hub コンソールに取得するには、Migration Hub インポート、AWS Agentless Discovery Connector、および AWS Application Discovery Agent の 3 つの方法があります。

* Migration Hub インポート
    * Migration Hub では、オンプレミスのサーバーおよびアプリケーションに関する情報（例: サーバーの仕様および使用状況のデータ）を Migration Hub にインポートできます。このデータを使用して、アプリケーション移行のステータスを追跡することもできます。
* AWS Agentless Discovery Connector
    * 検出コネクタ は、VMware 仮想マシン (VM) に関する情報のみを収集できる VMware アプライアンスです。Open Virtualization Archive (OVA) ファイルを使用して VMware vCenter Server 環境に VM として Discovery Connector をインストールします。 を使用すると、初期オンプレミスのインフラストラクチャ評価に必要な時間を最小限に抑えることができます。
* AWS Application Discovery Agent
    * 検出エージェント は、システム構成、システムパフォーマンス、実行中のプロセス、およびシステム間のネットワーク接続の詳細をキャプチャするために、オンプレミスのサーバーと VM にインストールする AWS ソフトウェアです。エージェントは、ほとんどの Linux および Windows オペレーティングシステムをサポートし、オンプレミスの物理サーバー、Amazon EC2 インスタンス、仮想マシンにデプロイできます。

####フェーズ 1: 検出
> 検出フェーズには、次のステップがあります。

* AWS 検出ツールを選択してデプロイする。

* View Discovered Servers。

* サーバーをアプリケーションとしてグループ化する。

####フェーズ 2: 移行
> 移行フェーズには、次のステップがあります。

* Migration Hub に移行ツールを接続する。

<img width="449" alt="スクリーンショット 2020-05-30 20.21.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321923/8bf761f1-19d5-3d70-da4e-5d602a023c9d.png">


* 接続された移行ツールを使用して移行する。

####フェーズ 3: 追跡
> 追跡フェーズでは、移行のステータスを追跡します。

* 移行のステータスを追跡する。

###検出を実行せずに移行する
> AWS 検出ツールで検出を実行せずに、統合 AWS 移行ツールまたは統合パートナーの移行ツールを直接使用して、移行を開始するワークフローを示します。移行は、これらの統合移行ツールを使用して移行ハブ外で行われます。


#AWS Migration Hub の制限
**AWS Migration Hub のインポートの制限**

> 次に示すのは、AWS Migration Hub のインポートの制限です。

* 各インポートファイルの最大サイズは 10 MB です。

* アカウントあたり 25,000 のインポートレコード。この制限の引き上げをリクエストすることができます。

* アカウントあたり 5,000 のインポートサーバー。この制限の引き上げをリクエストすることができます。

* 毎日 00:00 UTC に開始して、24 時間あたりに 25,000 のインポートレコードの削除。この制限の引き上げをリクエストすることができます。

* アプリケーションあたり 400 サーバー。この制限の引き上げをリクエストすることができます。
Angular+Rest(Java)でCORS対応

Angularクライアントからドメインの異なるRestサーバー(Java)へアクセスしようとするとCORS問題によってエラーとなります。
その対策を以下に記述します。
(サーバー側のRest API処理は通常と変わらないため省略します)

Angular側のサーバーへリクエストする処理

```
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class ClientService {
  url = "http://XXXXX:XXXX/XXXXX"; // アクセス先

  returnModel : ReturnModel; // サーバーからの戻り値

  // コンストラクタ
  constructor(private http: HttpClient) {}

  // 送信メソッド
  request(): void {
    // Httpヘッダー(CORS対応でAccess-Control-Allow-Originを指定する)
    const httpOptions = {
      headers: new HttpHeaders({
        'Access-Control-Allow-Origin': '*',
      })
     };

    // 送信データ
    const data = new HttpParam({
      fromObject: {
        value: '1000"
      }
    });

    // サーバーへPOST
    this.http.post<ReturnModel>(this.url , data, httpOptions).subscribe(h => this.returnModel = h);
  }
}
```

サーバー側のServlet Filter

```
package sample.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;

// サーブレットフィルタ
@WebFilter(filterName = "CorsFilter", urlPatterns = { "/*" })
public class CorsFilter implements Filter {
  @Override
  public void init(FilterConfig config) {
  }

  // フィルター処理
  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    if (response instanceof HttpServletResponse) {
      // 以下の通りCORS対応のためHeaderwo指定する
      HttpServletResponse http = (HttpServletResponse) response;
      http.addHeader("Access-Control-Allow-Origin", "*");
      http.addHeader("Access-Control-Allow-Headers", "*");
      http.addHeader("Access-Control-Allow-Credentials", "true");
      http.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
    }
    chain.doFilter(request, response);
  }

  @Override
  public void destroy() {
  }
}
```
[rails]AWS 課金にならないように各機能を削除する方法

下記、AWS公式ページのリンクです。

Elastic IPアドレスを解放する方法
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html#using-instance-addressing-eips-releasing

S3バケットを削除する方法
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/user-guide/delete-bucket.html

インスタンスの停止と起動
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/Stop_Start.html
[Vue.js]Object.assignの配列コピーで地味にハマったメモ[追記]

リアクティブに配列をコピーしたくて使用。
「空の配列」ひとつに対し、値を格納した配列を複数用意。
タブ切り替え時、コピーする配列を変更。

```vue.js:test.vue
let a = [1, 2, 3, 4, 5];
let b = [6, 7, 8];
let c = [9, 10];

タブ切り替え時、コピーする配列（target部分)を変える。
Object.assign(this.array, target);
```

その配列の要素数をviewで表示するというような実装を行ったところ、
正しい要素数が表示されずに困った。

```vue.js:表示結果
<p>{{array.length}}</P>
　　　　↓　↓　↓
一番要素数が多いaの配列を格納すると、
それ以降はどのタブに切り替えても、aの要素数から変更されない
```

## 原因
[参考資料](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)にもある通り、
Object.assign()メソッドはコピーを行うので、
今ある要素に上書きされる形になる。
そりゃ、要素数に変更がないわけだ・・・

```vue.js:test.vue
let a = [1, 2, 3, 4, 5];
let b = [6, 7, 8];
let c = [9, 10];

①aをarryにコピーする
Object.assign(this.array, a);
  → this.arry[ 1, 2, 3, 4, 5];

②次はbをコピーする
Object.assign(this.array, b);
  → this.arry[ 6, 7, 8, 4, 5]; //上書きされているため、要素数は変わらない
```

## 対策
配列に格納する前に、初期化処理を入れるようにした。
これで正しい要素数を表示できるようになった。

```vue.js:test.vue

// 配列初期化
this.array.splice(-this.arry.length);
//コピー
Object.assign(this.array, target);
```

## 最後に
実際は格納した配列を子に渡すなど、処理が複雑になっているため、
こんな簡単なことに気付くのが遅れてしまいました・・・
勉強あるのみですね！！

## 追記
コメントよりご指摘いただきました下記の方法でなら、
初期化処理不要で、配列のコピーができました！！
こちらの方がコードがスッキリしていいですね:relaxed:
[slice()の参考資料](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/slice)

```vue.js:追記
let a = [1, 2, 3, 4, 5];
let b = [6, 7, 8];
let c = [9, 10];

①配列aのコピーをする
this.array = a.slice()；
→this.array[1, 2, 3, 4, 5]

②①の後、this.arrayに配列bを再度格納する
this.array = b.slice()；
→this.array[6, 7, 8] 　
//上書きではなく、コピー元の配列全体を切り出して新しく配列を生成してくれた！

```
TypeORM をシングルトンで使う

TypeORM のメソッドそのままでDBに接続すると状態管理がごちゃっとするので、ラッパークラスを作って、そこでコネクションの管理を行うようにしていきます。

# コネクション管理用のクラスを作成する

- `get()` で `Connection` が取得できる
- `get()` を呼び出した時にコネクションが開いて場合は、同時に作成する
- `close()` で `Connection` を閉じる
- `close()` を呼び出した時にコネクションが閉じていた場合は、何もせず、エラーも起こさない

## dbconnection.ts

```ts
import {
  Connection,
  createConnection,
  EntityManager,
  getConnection,
  ConnectionOptions,
} from 'typeorm';

export class DBConnection {
  private static con?: Connection;
  static getManager = (): Promise<EntityManager> =>
    DBConnection.get().then(con => con.manager);
  static get = async (): Promise<Connection> => {
    if (DBConnection.con && DBConnection.con.isConnected)
      return DBConnection.con;
    if (DBConnection.con instanceof Connection)
      return DBConnection.con.connect();
    return DBConnection.create();
  };
  private static create = async (): Promise<Connection> => {
    DBConnection.con = await createConnection(DBConnection.options).catch(() =>
      getConnection(),
    );
    if (!DBConnection.con.isConnected) await DBConnection.con.connect();
    return DBConnection.con;
  };
  static close = async (): Promise<void> => {
    if (!DBConnection.con) return;
    if (DBConnection.con && DBConnection.con.isConnected)
      DBConnection.con.close();
    DBConnection.con = undefined;
  };
}
export namespace DBConnection {
  export const options: ConnectionOptions = {
    type: 'postgres',
    host: process.env.DB_HOST,
    port: Number.parseInt(process.env.DB_PORT!),
    username: process.env.DB_USER,
    password: process.env.DB_PASSWORD,
    database: process.env.DB_DATABASE_NAME,
    synchronize: false,
    logging: process.env.NODE_ENV === 'production' ? ['error'] : 'all',
  };
}
```

テスト

<details><summary>dbconnection.spec.ts</summary><div>

```ts
import { Connection, EntityManager } from 'typeorm';
import { DBConnection } from 'src/infrastructure/dbconnection';

describe('DBConnection', () => {
  let connection: Connection;

  beforeEach(async () => {
    connection = await DBConnection.get();
  });
  it('should be defined', () => {
    expect(connection).toBeDefined();
  });
  it('isConnected', () => {
    expect(connection.name).toBe('default');
    expect(connection.isConnected).toBeTruthy();
  });
  it('isConnected2', () => {
    expect(connection.name).toBe('default');
    expect(connection.isConnected).toBeTruthy();
  });
  it('close', async () => {
    await DBConnection.close();
  });
  it('getManager', async () => {
    const manager = await DBConnection.getManager();
    expect(manager instanceof EntityManager).toBeTruthy();
  });
  afterEach(async () => {
    await DBConnection.close();
  });
});
```

</div></details>


# 使ってみる

あとは通常通り Connection をつかってなんやかんや

```ts
import { Connection } from 'typeorm';

const connection: Connection = await DBConnection.get();
const result: Promise<any> = connection.transaction(manager => {
    return manager.query(`select * from users;`);
});
```

# 最後に
TypeORM の createConnection 等のメソッドが他のところからも勝手に呼べしまうのが難点。
何か制限をかけられる方法をご存知の方がいれば教えていただきたいですm(_ _)m
RailsのWebサーバーからMySQLのCLIに繋ぎたい

## この記事について

自分用メモです。

## メモ

```sh
# RAILS_ENVには環境名を入れる
# dbはdbconsoleでも可。
RAILS_ENV=production bundle exec rails db
> passwordを入力

# デフォルトの出力だと見にくいのでlessで結果を見る
mysql> pager less -n -i -S

# 見たいdatabaseに切り替える
mysql> use `hoge-database`;

# 見たい結果を得るためのクエリ
mysql> select * from hoge_table;
```
git submodule --init --recursive で特定の submodule を無視する

# 背景

* project が submodule している repo が, さらに submodule で馬鹿でかい git repo を登録している
* project 自体では, その submodule が submodule している repo は使っていない(ビルドでは利用されない)ので無視したい

 
IREE 

https://github.com/google/iree

でやってみます. 

問題なのは, IREE が submodule 登録している swiftshader が submodule で追加している PowerVR_Examples です. 普通に clone すると 2 GB くらいあります(`--depth 1` でも 700 MB くらい)


## 方法

https://stackoverflow.com/questions/52179463/how-to-exclude-a-specific-git-submodule-from-update

ありがとうございます.

`-c submodule."REPO".update=none` を追加でいけました.

ただ,

```
# NG
$ git -c submodule."third_party/swiftshader/third_party/PowerVR_Examples".update=none submodule update --init --recursive 
```

とすれば行けそうですが, 親プロジェクトからのパス指定はできないようでした.

```
# OK
$ git -c submodule."third_party/PowerVR_Examples".update=none submodule update --init --recursive 
```

のようにします.

`third_party/PowerVR_Examples` を無視するのを, それぞれの submodule repo で実行する感じになっています.

## 懸念点

git -c で設定を追加すると, submodule 処理が直列化するっぽい?ようです
(通常は submodules は並列に git clone される)


## TODO

* [ ] 同名の submodule repo path が, 複数の submodule repo にあるとうまく行かない(すべて無視されてしまう)ので, 特定の submodule ごとに設定できるようにする(うまく grep 的なのが使えればよいが... shell script を書くことになるかな?)
【JavaScript】forループ内でawaitする方法

#経緯
forループ内で同期処理を行いたかったので調べてみたら **for await...of** というものがあることを知りました。

#結論
このように `async` のなかに `for await...of` を書くことで forループ内で `await` を宣言できます。

```index.js
// 対象の反復オブジェクト
const targetArr = [1, 2, 3];

// 実行する関数
const sampleFunc = (value) => {
// asyncの効果は各functionブロックで切れるので逐一指定が必要
    return new Promise(resolve => { 
        // 2秒待ってから計算結果をresolveする
        setTimeout(() => {
            console.log('Calculating...');
            resolve(value * 2);
        }, 2000);
    })
}

// for await...of文は必ずasyncの中で
(async () => {
  for await (num of targetArr) {
    // 関数の実行結果を格納して表示
    const result = await sampleFunc(num);
    console.log(result);
  }
})();
```

#for await...of とは
>for await...of 文は非同期（と同期）の反復オブジェクトを繰り返して処理するループを作ります。対象の反復オブジェクトは、ビルトインの String、Array、配列様オブジェクト（ arguments、NodeList 等)、TypedArray、Map、Set、さらに、ユーザーが定義した非同期・同期の反復オブジェクトが含まれます。オブジェクトの各プロパティの値に対して実行されるステートメントを使用してカスタム反復フックを呼び出します。

簡単に言うと
**反復オブジェクト（ArrayやObjectなど）の中で同期処理を行う事ができる文です。**

#ESLintでは非推奨
便利な構文ですが、ESLintでは設計思想的な意味で推奨されていません。

[https://eslint.org/docs/rules/no-await-in-loop](https://eslint.org/docs/rules/no-await-in-loop)
>Performing an operation on each element of an iterable is a common task. However, performing an await as part of each operation is an indication that the program is not taking full advantage of the parallelization benefits of async/await.
Usually, the code should be refactored to create all the promises at once, then get access to the results using Promise.all(). Otherwise, each successive operation will not start until the previous one has completed.
Concretely, the following function should be refactored as shown:

反復の各要素に対して操作を行うことは一般的な作業です。
しかしながら、各段階の操作で `await` を実行すると `async/await` による並列化の利点を十分に活用できません。
一般にこのようなコードは、全てのプロミスを一度に作成し `Promise.all()` を用いて結果を得るようにするべきです。
RSpecでsession not created: This version of ChromeDriver only supports Chrome version 81

# どのようなエラーか
systemspecで使用しているブラウザであるchromeと、クロームでテストする際に必要なchromedriverのバージョンが合ってない。

現在使用しているchromedriverはバージョン81のchromeしかサポートしていないと言われている。

chromedriverのバージョンをchromeに合わせるか、chromeのバージョンをdriverに合わせるかをすればいい。

# 解決法

## chromedriverをchromeに合わせる

chromeのバージョンを調べたら83になってた。

なのでdriverも83に合わせる。

### chromedriverのインストール

https://chromedriver.storage.googleapis.com/index.html?path=83.0.4103.39/

mac windows linuxいずれかによって適切な物をダウンロードする。


### chromedriverを置き換える

chromedriverは自分の環境の場合、webdriversの中にある

```
$ ~/.webdrivers/chromedriver -v

=> 81.0.4044.138
```

このchromedriverを消して、先ほどダウンロードしたchromedriverをこの中に置いたらエラーが出なくなった。

もしもっと適切なやり方がある場合、コメントしていただけたら嬉しいです。
Laravel で値がない時にカスタムバリデーションがうまく効かない問題への対策

## 結構ハマったので、メモ。


## 前提

* 特定条件のときだけ必須にしたかった。（return が trueの時だけ、第１引数のプロパティに、第２引数のバリデーションルールを追加する）

```php
$validator->sometimes('fuga', ['nullable', new RequiredIfHoge($status)], function ($input) {
            return $input->piyopiyo == true;
        });
```

## 原因

```php
class RequiredIfHoge implements Rule
```

で値がないときに動かなかった

## 対応

```php
class RequiredIfHoge implements ImplicitRule
```

で、nullの時でも入力チェックが発動するようになった。
GPGコマンドで暗号化・復号

LPIC102を学習中にGPGコマンドを初めて知ったので、実際に使用して理解を深めることにした。

#環境
~~~
[ec2-user@ip-172-31-33-30 ~]$ cat /etc/os-release
NAME="Amazon Linux"
VERSION="2"
ID="amzn"
ID_LIKE="centos rhel fedora"
VERSION_ID="2"
PRETTY_NAME="Amazon Linux 2"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
HOME_URL="https://amazonlinux.com/"
~~~

#鍵ペアの作成

`gpg --gen-key`コマンドで以下のように対話形式でキーペアを作成する。
鍵の種類：デフォルトのままにする
鍵長：鍵長は長いほどセキュリティが強いので、最大にしておく。
鍵の有効期間：流出した時に、有効期限を過ぎると無効になるので設定しておく。


~~~
[ec2-user@ip-172-31-33-30 ~]$ gpg --gen-key
gpg (GnuPG) 2.0.22; Copyright (C) 2013 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

ご希望の鍵の種類を選択してください:
   (1) RSA と RSA (デフォルト)
   (2) DSA と Elgamal
   (3) DSA (署名のみ)
   (4) RSA (署名のみ)
あなたの選択は? 1
RSA 鍵は 1024 から 4096 ビットの長さで可能です。
鍵長は? (2048) 4096
要求された鍵長は4096ビット
鍵の有効期限を指定してください。
         0 = 鍵は無期限
      <n>  = 鍵は n 日間で期限切れ
      <n>w = 鍵は n 週間で期限切れ
      <n>m = 鍵は n か月間で期限切れ
      <n>y = 鍵は n 年間で期限切れ
鍵の有効期間は? (0)2y
鍵は2022年05月29日 03時48分32秒 UTCで期限切れとなります
これで正しいですか? (y/N) y

GnuPGはあなたの鍵を識別するためにユーザIDを構成する必要があります。

本名: r_saiki
電子メール・アドレス: r_saiki@example.com
コメント: 
次のユーザIDを選択しました:
    "r_saiki <r_saiki@example.com>"

名前(N)、コメント(C)、電子メール(E)の変更、またはOK(O)か終了(Q)? o
秘密鍵を保護するためにパスフレーズがいります。
~~~

パスフレーズを要求される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558865/f6aa7ab3-c61b-a46a-7418-77d436dccfa5.png)

作成した鍵の確認。
公開鍵の確認オプション：--list-public-keysもしくは-k
秘密鍵の確認オプション：--list-secret-keysもしくは-K

~~~
[ec2-user@ip-172-31-33-30 ~]$ gpg --list-public-keys
/home/ec2-user/.gnupg/pubring.gpg
---------------------------------
pub   4096R/0C8FB274 2020-05-29 [有効期限: 2022-05-29]
uid                  r_saiki <r_saiki@example.com>
sub   4096R/038BE8AA 2020-05-29 [有効期限: 2022-05-29]

[ec2-user@ip-172-31-33-30 ~]$ gpg --list-secret-keys
/home/ec2-user/.gnupg/secring.gpg
---------------------------------
sec   4096R/0C8FB274 2020-05-29 [有効期限: 2022-05-29]
uid                  r_saiki <r_saiki@example.com>
ssb   4096R/038BE8AA 2020-05-29
~~~

#ファイルの暗号化
ファイルを暗号化する。
暗号化：--encryptもしくは-e
受取人の公開鍵情報を指定：--recipientもしくは-r <今回はメールアドレス>

~~~
[ec2-user@ip-172-31-33-30 ~]$ cat file
TEST

[ec2-user@ip-172-31-33-30 ~]$ gpg --encrypt --recipient r_saiki@example.com file
[ec2-user@ip-172-31-33-30 ~]$ ls
file  file.gpg
~~~

#ファイルの複合
pgpに暗号化ファイル名で複合する。

~~~
[ec2-user@ip-172-31-33-30 ~]$ gpg file.gpg

次のユーザの秘密鍵のロックを解除するには
パスフレーズがいります:"r_saiki <r_saiki@example.com>"
4096ビットRSA鍵, ID 038BE8AA作成日付は2020-05-29 (主鍵ID 0C8FB274)

gpg: 4096-ビットRSA鍵, ID 038BE8AA, 日付2020-05-29に暗号化されました
      "r_saiki <r_saiki@example.com>"
ファイル「file」は既に存在します。上書きしますか? (y/N) y
[ec2-user@ip-172-31-33-30 ~]$ cat file
TEST

~~~

途中パスフレーズを求められる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558865/9d8dd1b3-1f93-47b3-70c6-b0dc45412347.png)

#終わりに
今回はファイルの暗号化・復号のみやってみた。深堀するとlpic受験前に息切れしそうなので、詳しく知りたい場合は以下を参考。
[GPG でファイルを暗号化, 復号化, 署名, 検証する方法](https://yu8mada.com/2018/04/03/how-to-encrypt-decrypt-sign-and-or-verify-files-in-gpg/)
最近覚えた便利なショートカットキー一覧

在宅勤務になり、デスクの狭さからマウスを使わないようになりました。
慣れたらマウスなしのほうが楽ですね。

##　タブ関係
* Ctrl+Wでタブを閉じる
* Ctrl+Shift+Tで閉じたタブの復活
* Ctrl+Tabで一つ右のタブへ移動
* Ctrl+Shift+Tabで一つ左のタブへ移動
* Alt+←で一つ前のページへ戻る
* Alt+→で一つ後のページへ進む
* Ctrl+Tで新規タブを開く
* F6で検索窓を選択

##　ウィンドウ関係
* windows+↑でwindowを一段階大きくする
* windows+↓でwindowを一段階小さくする
* windows+Tabで開いているwindowの一覧
* Alt＋F4で開いているウィンドウを閉じる
* Ctrl+Nで新規タブを開く
* windows+Dでデスクトップを開く

##　その他
* Shift+スペースで半角スペース
* windows+Eでエクスプローラーを開く
* windows+Vでクリップボード履歴を開く
* windows+Shift+Sで範囲選択してスクリーンショット
eclipseショートカット表

##はじめに
OSはWindows10
基本はsts4で動作確認していますが、EclipseやPleiadesでも動くはず。
ショートカットは調べればいくらでも出てくるけど、個人的にパッと見られるいい感じのサイトがなかったので雑に表を作っただけ。
確証はないけどmacOSならCtrlをcommand、Altをoptionに換えればほとんどは動くはず。

そもそも自分が使ってよかったものを載せているけど、個人的に特に使い勝手が良かったもの、使用頻度が高いものは★つけたので参考になれば嬉しいです。

##エディタ内
####コピペと削除

|　ショートカット　|　　　キー　　　| 　　　補足　　　 |
|:-----------------|------------------:|:------------------:|
|全選択|Ctrl + A||
|コピー|Ctrl + C|任意の箇所を選択|
|ペースト|Ctrl + V|任意の箇所を選択|
|カット|Ctrl + X|任意の箇所を選択|
|★行コピペ|Ctrl + Alt + ↓|１行下にペーストされる|
|★行削除|Ctrl + D||
|キャレットのから行末まで削除|Ctrl + Shift + Delete||

####コードの見た目を整える

|　ショートカット　|　　　キー　　　| 　　　補足　　　 |
|:-----------------|------------------:|:------------------:|
|行ごと上/下移動|Alt + ↑/↓||
|★インデント整理|Ctrl + Shift + F||
|右にインデント|tab|複数行選択も可能|
|左にインデント|Shift + tab|複数行選択も可能|

####作業効率向上

|　ショートカット　|　　　キー　　　| 　　　補足　　　 |
|:-----------------|------------------:|:------------------:|
|テンプレート・プロポーザル|Ctrl + space|コード記述補助。ググるの推奨|
|直近に記述したクラスをimport|Ctrl + Shift + M||
|import編成|Ctrl + Shift + O|複数クラスをimport、不要import削除|
|★quick fixes表示|Ctrl + １|コンパイルエラーの修正|
|★次の警告・エラーに移動|Ctrl + .||
|メソッドの型変更|Shift + Alt + C|参照元なども勝手に変わる|
|メソッドの呼び出し階層を開く|Ctrl + Alt + H|定義の中や宣言の上で押す。コードの解読に◎|
|名前変更|Shift + Alt + R|変数・メソッド両方可。呼び出し先も変わる|
|★キャレット移動|Ctrl + ←/→|単語ごと等に移動。Shiftと組み合わせると◎|
|★コメントにする/戻す|Ctrl + /|任意の箇所を選択|
|★対応する括弧行き来|Ctrl + Shift + P||
|★選択範囲の拡大/縮小|Shift + Alt + ↑/↓|まとまりごとに自動選択してくれる|




##エディタ外
####ファイル・タブ
|　ショートカット　|　　　キー　　　| 　　　補足　　　 |
|:-----------------|------------------:|:------------------:|
|★元に戻す|Ctrl + Z||
|やり直し|Ctrl + Y|戻しすぎたものを進める|
|★ファイル保存|Ctrl + S||
|全ファイルを保存|Ctrl + Shift + S||
|ファイルを閉じる|Ctrl + W||
|全ファイルを閉じる|Ctrl + Shift + W||
|★編集タブを戻る/進む|Alt + ←/→||

####検索

|　ショートカット　|　　　キー　　　| 　　　補足　　　 |
|:-----------------|------------------:|:------------------:|
|ファイル検索|Alt + Aを押してF||
|Javaファイル検索|Alt + H||
|★編集タブを検索して移動|Ctrl + E|タブのリストが出てくるので選択して移動|
|文字列検索|Shift + F||
|型検索|Ctrl + Shift + F||
【WBF】Windows Biometric Framework関連のポリシー状態確認

# WinBioGetEnabledSetting
https://docs.microsoft.com/ja-jp/windows/win32/api/winbio/nf-winbio-winbiogetenabledsetting
Windows Biometric Frameworkが有効になっているかどうかを確認します。

#### サンプルコード
```C++
BOOLEAN Value = FALSE;
WINBIO_SETTING_SOURCE_TYPE Source = 0;
WinBioGetEnabledSetting( &Value, &Source );
wprintf_s( L"Value [%d] Source [%d]\n", Value, Source );
```

#### WINBIO_SETTING_SOURCE_TYPEに対応する設定先

・ WINBIO_SETTING_SOURCE_LOCAL : レジストリ
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WinBio
名前 : Enabled

・ WINBIO_SETTING_SOURCE_POLICY : グループポリシー
[コンピューターの構成]→[管理用テンプレート]→[Windowsコンポーネント]→[生体認証]
設定 : [生体認証の使用を許可する]

# WinBioGetLogonSetting
https://docs.microsoft.com/ja-jp/windows/win32/api/winbio/nf-winbio-winbiogetlogonsetting
ユーザーが生体認証情報を使用してログオンできるかどうかを確認します。

#### サンプルコード
```C++
BOOLEAN Value = FALSE;
WINBIO_SETTING_SOURCE_TYPE Source = 0;
WinBioGetLogonSetting( &Value, &Source );
wprintf_s( L"Value [%d] Source [%d]\n", Value, Source );
```

#### WINBIO_SETTING_SOURCE_TYPEに対応する設定先

・ WINBIO_SETTING_SOURCE_LOCAL : レジストリ
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WinBio\Credential Provider
名前 : Enabled

・ WINBIO_SETTING_SOURCE_POLICY : グループポリシー
[コンピューターの構成]→[管理用テンプレート]→[Windowsコンポーネント]→[生体認証]
設定 : [ユーザーによる生体認証を使用したログオンを許可する]

# WinBioGetDomainLogonSetting
https://docs.microsoft.com/ja-jp/windows/win32/api/winbio/nf-winbio-winbiogetdomainlogonsetting
ユーザーが生体認証情報を使用してドメインにログオンできるかどうかを確認します。

#### サンプルコード
```C++
BOOLEAN Value = FALSE;
WINBIO_SETTING_SOURCE_TYPE Source = 0;
WinBioGetDomainLogonSetting( &Value, &Source );
wprintf_s( L"Value [%d] Source [%d]\n", Value, Source );
```

#### WINBIO_SETTING_SOURCE_TYPEに対応する設定先

・ WINBIO_SETTING_SOURCE_LOCAL : レジストリ
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WinBio\Credential Provider
名前 : Domain Accounts

・ WINBIO_SETTING_SOURCE_POLICY : グループポリシー
[コンピューターの構成]→[管理用テンプレート]→[Windowsコンポーネント]→[生体認証]
設定 : [ドメイン ユーザーによる生体認証を使用したログオンを許可する]