OmniAICreator/Qiita-1.07M huggingface dataset:
JW_CAD使い方の覚書 #1

　ちょっとした図面を書きたいときに、JW_CADは無料だし、高機能なので助かります。しかし、操作方法が非常に癖があり、しばらく使わないと使い方が思い出せなくて大変。とりあえず、１回やったことを覚えておくためにメモ目的で書いていきます。

# 1. 「設定」→「基本設定」
## 一般(1)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/0d2cef37-1572-3716-7193-7db78904427b.png)

## 一般(2)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/4f900a04-c4f7-91f8-3bb1-d52e00f18445.png)

# 2. 「表示」→「ツールバー」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/9e776c2d-8d17-5104-6993-f4c7532f5fea.png)

# 3. マウス左右同時押し操作

## マウスを移動せずに離す
　マウスの位置が中央になるよう表示される

## 押したままマウスを移動して離す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/2fb8c1fa-e723-8bf4-50ee-4de1a3b287ba.png)


# 4. 線の消し方
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/c1e0dcf7-dbe8-45ed-0683-3e5f7f866783.png)

## 消し
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/a60c14db-4430-607a-7d9f-243a4e8e5a5b.png)

## 節間消し
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/a58f8026-5508-33da-2181-235f5e94c91b.png)

# 5. 線色と線種
## 線の色と印刷幅
　JW_CADでは、印刷時の線の太さを画面上の線の色で示しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/8a500ff2-cc68-7a00-78ff-3fc2c7867c84.png)
　線の太さは、太線、中線、細線の３種類を使い分けることになります。

## 点線と実線
　外から見えない隠れ線は、点線１～３を使います。
　通り芯や敷地境界線には一点鎖線を使います。
　二点鎖線は、扉の軌跡に使います。

# 6. 複線コマンド
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/8f2897a6-8494-375e-c326-b7eb0bee9ff6.png)

## 連続線選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/564d1684-705b-0f06-41eb-7d97aa3a9490.png)

# 7. コーナーコマンド
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/5f4b1b1e-a0eb-8528-a631-a75ae7d44c97.png)

# 8. 距離コマンド
　指定した距離の場所に仮点をつける
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/484e6d0a-366c-3abb-d9d5-cf8b564519af.png)

## 連続仮点作成
　作成した仮点に続けて仮点をつける場合は、距離を修正して「連続」ボタンを押すと、先の仮点に続けて指定した距離に仮点が作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/f9e32a99-ddec-c6f9-bc60-b0fe24ae0c3f.png)

## 仮点の消去
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/d564495e-843c-123d-ac3f-896740be8630.png)

# 9. 塗りつぶし
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/90059a4b-caec-8092-9b05-146ea3672dc3.png)

## 塗りつぶしの削除
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/091c41d8-7c2f-b42b-1bd0-aca0cfccac17.png)
カスタムドメインを設定する(Heroku)

これまでHerokuのデフォルトで設定されるドメインを使っていたので変更した。
今回変更したアプリケーションは、フロントとバックエンド2つのアプリから成り立っているが、ユーザーから見えるフロント側のみドメインを変更した。

# 手順

1. ドメインを購入する
2. Heroku側と、ドメイン管理画面（購入したサイトの管理画面）で設定する

## ドメインを購入する
ムームードメインで購入した。（¥500）
https://muumuu-domain.com/

## Heroku側と、ドメイン管理画面（購入したサイトの管理画面）で設定する

アプリケーションのルートディレクトリに移動する
```
$ cd ~/myapp
```
example.comのところは購入したドメインに変更
```
$ heroku domains:add www.example.com
```
追加できたか確認
```
$ heroku domains
```
DNS Targetをコピー（XXX-XXX-XXX.herokudns.com）

```
===== my-app Custom Domains
Domain Name     DNS Record Type    DNS Target

www.example.com  CNAME             XXX-XXX-XXX.herokudns.com 
```

### ムームードメインでカスタム設定
ログインして、コントロールパネル→ドメイン操作→ムームーDNS→購入したドメインの欄の'変更'をクリック

設定２の場所から、サブドメインに"www"、　種別に"CNAME"、内容に先ほどコピーした"DNS Target"を入力して、完了ボタンをおす。

これで少し待てば新しいURLでアクセスできるはず！

## configの設定
フロントとバックエンド分けているので
バックエンド側からフロントに接続するためのドメインを忘れずに変更
```
$ heroku config:set 
```
## SSL化
有料プラン
Herokuのwebサイトから変更したいアプリ画面に行き、月7ドルのhobbyプランに変更して、settingからSSL Certificatesの"Configure SSL"ボタンを押す。Automatic Certificate Management を選んで完了すれば自動的に変更されてる！
Git Credential ManagerでGitHubの認証情報をキャッシュする

# Git Credential Manager
最近はGithubへpushしたりするときに認証が必要．前はトークンを発行したりしていたが，MacではGit Credential Managerを使うのは手っ取り早くで便利なので今回はこれを使う．

[GitHub DocsのGit Credential Manager](https://docs.github.com/ja/get-started/getting-started-with-git/caching-your-github-credentials-in-git)

## Homebrew

homebrewで入れるだけ．上記のGitHub Docsには brew installの際に--caskと書いてあるが，今のhomebrewにはおそらく必要ない．

``` zsh
$ brew install git
$ brew tap microsoft/git
$ brew install git-credential-manager-core
```

これで次回，pushとかしたときに自動で認証が始まる．ブラウザで認証みたいなのを選んで普通にやれば良い．これは1回だけやればMacのキーチェーンに保存されるので次回以降は何もやらなくて良い．`.gitconfig`も自動で書き換えてくれる．
【Rails】ログアウトしてる状態でホーム画面にアクセスしたら、ログイン画面に遷移してしまう問題とその解決方法

# 経緯
- アプリ制作時にログアウト画面を作ってない事に気付いて実装。しかしログアウト状態だとホーム画面にアクセスしたらログイン画面に遷移されてしまうので、解決を試みた。

# 開発環境
ruby 2.7.2
rails 6.0.4.6

<a id="#Chapter0"></a>
# 原因はどこか
まずはアプリの動作を司ってるapplication_controller.rbに目星をつけた.
その時のコードは以下の通り
``` ruby application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

    def configure_permitted_parameters
      devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
      devise_parameter_sanitizer.permit(:account_update, keys: [:name])
    end
end

```
``` ruby
  protect_from_forgery with: :exception
```
に関してはCSRF対策(クロスサイトリクエストフォージェリ)であり、要はセキュリティ関係であるので今回は関係ない事が分かった。

次は
``` ruby
  before_action :configure_permitted_parameters, if: :devise_controller?
```
まずはbefore actionというのはあらゆるコンローラのフィルタリングするものである。
そしてあるゆるアクションより先に読み込まれるものである。
当然これを設定するならば、その読み込まれる定義自体もセットでないとダメ。
例えばbefore_actionがご飯の献立とするなら、そのご飯自体が作られないとおかしいよねって感じかな。つまりセットで初めて意味を成すもの。
下で記述されてる
``` ruby
 def configure_permitted_parameters
      devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
```
がまさにそれ
ちなみにpermitはストロングパラメータ
これがないとダメですよっていうもの
これでいうとsign_up( つまり登録時は)、nameがないとダメですよって意味。
となると今回の問題とこれらは関係ないっぽい



# 別の角度から考える
逆にどうしたら非ログイン時にログイン画面を遷移させられるのか考えた。その為には以下の記述をすればいいらしい。でもapplication_controller.rb今回は別にそれないんだよな。そう思ってposts_controller.rbの方を見てみたらしっかり記述があった。これを消す
```ruby
class PostsController < ApplicationController
  before_action :authenticate_user!
  before_action :set_post, only: %i(show destroy)
```

# 新たなエラー

これを消したところ以下のエラー
![スクリーンショット 2022-03-07 3.09.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381701/c7203289-b387-56f0-66f0-1a2ec2ed9a54.png)
要は投稿とユーザーは結びつきがある設定のことを言われてる。
投稿ボタン押したらこうなるのは分かるけどルートに設定してるposts/indexを表示するだけなら関係なさそうだけどな。。

# なぜこのエラーが出ているか
ポイント①ログイン状態ならきちんとposts/indexのルート画面を開く
ポイント②非ログインだとログイン画面に遷移されてしまう
ルーティングが影響しているという仮説を立てた
``` ruby
Rails.application.routes.draw do
  devise_for :users,
    controllers: { registrations: 'registrations' }
    root 'posts#index'
    get "users/index" => "users#index"
    get '/users/:id', to: 'users#show', as: 'user'

  resources :posts, only: %i(index new create show destroy) do
    resources :photos, only: %i(create)
    resources :likes, only: %i(create destroy)
    resources :comments, only: %i(create destroy)
  end
end
```
以下の記述のような,currentを使ったものいくつかあったが、それを消したらログアウト状態でも表示できた。
でもそれだとログイン状態との分岐が出来てないから、２つ記述すればいいのかな。記述増えるけど。後ほど追記します。
```ruby
<% if post.user_id == current_user.id %>
```
運用中のAWS ParallelClusterのSlurm Partition (SlurmQueue)を変更する方法

# ParallelClusterのSlurmのQueueを変更する

## 概要

### SlurmQueuesのupdateポリシーの確認

[SlurmQueues](https://docs.aws.amazon.com/parallelcluster/latest/ug/Scheduling-v3.html#Scheduling-v3-SlurmQueues)のupdateポリシーを確認すると、以下のように記載されている。

> Update policy: The compute fleet must be stopped for this setting to be changed for an update.

### 設定変更の概要

Update Policyの内容から、以下の3ステップでSlurmQueues, つまりSlurmのPartitionを更新することができる。

1. コンピュートフリートを停止:`pcluster update-compute-fleet`を使用
2. アップデートの実施: `pcluster update-cluster`を使用
3. 最後に新しいコンピュートフリートを作成: `pcluster update-compute-fleet`


## 具体的な操作方法

### STEP0: 対象クラスタ名と使用するconfigファイルの明示

起動中のParallelClusterを確認します。

```bash:command
pcluster list-clusters
```

対象となるクラスタ名と使用するCONFIGをあらかじめ定義します。

```bash:command
CLUSTER_NAME=<'sample cluster'>
NEW_CONFIG=<'変更後のCONFIG名'>
```


### STEP1 コンピュートフリートを停止する

```bash:command
pcluster update-compute-fleet --cluster-name ${CLUSTER_NAME} \
                              --status STOP_REQUESTED \
                              --debug
```

### STEP2 アップデートの実施

```bash:command
pcluster update-cluster --cluster-name ${CLUSTER_NAME} \
                        --cluster-configuration ${NEW_CONFIG} \
                        --debug
```

Updateが完了したことを以下のコマンドを用いて確認します。
`UPDATE_COMPLETE` と表示されれば完了です。

```bash:command
pcluster describe-cluster --cluster-name ${CLUSTER_NAME} | jq -r .clusterStatus
```

### STEP3 コンピュートフリートを開始する

```bash:command
pcluster update-compute-fleet --cluster-name ${CLUSTER_NAME} \
                              --status START_REQUESTED \
                              --debug
```

しばらく待って、`RUNNING`と表示されればOKです。

```bash:command
pcluster describe-cluster --cluster-name ${CLUSTER_NAME} | jq -r .computeFleetStatus
```

### 注意点

Slurmdbdを一度止めて、Updateしたほうがよい。
もし、反応が無いときは`kill` でSlurmdbdを止めて、再度起動すること。

# 参考

- [Using pcluster update-cluster](https://docs.aws.amazon.com/parallelcluster/latest/ug/using-pcluster-update-cluster-v3.html)
- [Configuration files](https://docs.aws.amazon.com/ja_jp/parallelcluster/latest/ug/configuration-v3.html)
- [AWS ParallelCluster CLI commands](https://docs.aws.amazon.com/ja_jp/parallelcluster/latest/ug/commands-v3.html)
Kotlinで個人的にそこそこ使うボイラーテンプレート

# はじめに
- 毎回忘れて記憶の彼方から呼び起こしてるので自分用に覚書
- 気が向いたら増えるかもしれない

# クラスの生成を制限したい
## できること
- 特定のメソッドからしかクラスの生成をできなくする

## 書き方

```kotlin:Profile.kt

interface Profile {
   val id: String
   val name: String
   ...

   companion object {
      fun createByResponse(response: ProfileResponse) {
          return ProfileData(response.id, response.name, ...)
      }
   }
}

private data class ProfileData(override val id: String, override val name: String): Profile
```

```kotlin: UsedSample.kt
val profile:Profile = Profile.createByResponse(response)
```

**補足**

- この例だと、Profileを生成するには`createByResponse`メソッドを使うしかなくなる
- `ProfileData`クラスがprivateで宣言されているので、別クラスからは生成できなくしている
- 使う側はinterfaceとしての`Profile`しか見えない
- 使い所としては例えばAPIのレスポンスからしか生成できないようにする、など
WSH/JScript は Underscore.js で関数プログラミングの夢を見るか？

WSH/JScript + Underscore.js の環境で、オブジェクトが Recordset オブジェクト (ADO) かどうかをテストすることになった。

とりあえず一番最初に書いたバージョン

``` isAdoRecordset_take1.js
function isAdoRecordset( o ) {
	if( _.isUndefined( o.CursorType ) ) return false;
	if( _.isUndefined( o.LockType ) ) return false;
	if( _.isUndefined( o.BOF ) ) return false;
	if( _.isUndefined( o.EOF ) ) return false;
	if( _.isUndefined( o.Fields ) ) return false;
	return true;
}
```

```typeof(o.CursorType)==='undefined'```
の代わりに```_.isUndefined``` 使っただけ。

まあこれはこれで悪くない。でももっとアンスコの機能を使おうよ。ってことで ```_.every``` ってのを使ってみることにした。そのために、テストするプロパティのキーを文字列のリストにする必要がある。配列リテラル書くのが面倒くさいので、perl の qw を再発明した。

``` perlQw.js
function perlQw(str){return str.split(' ')};
```

perlQw と  _.every で実質ワンライナー化した第2版。

``` isAdoRecordset_take2.js
function isAdoRecordset( o ) {
	return _.every(perlQw('CursorType LockType BOF EOF Fields'),
	function($_){return ! _.isUndefined(o[$_])} );
}
```

これって「オブジェクトがリストのプロパティ／メソッドを持つか？」ということなので、一般化する。

``` hasProperties_take1.js
function hasProperties( o, props ) {
	return _.every(props,function($_){return ! _.isUndefined(o[$_])} );
}
```
hasPropatyes を使った第3版。

``` isAdoRecordset_take3.js
function isAdoRecordset( o ) {
	return hasProperties( o, perlQw('CursorType LockType BOF EOF Fields') );
}
```

やってることは同じだが関数化して名前を付けたことによってわかりやすくなった。気がする。
普段の自分ならここで一応完成なんだが、アンスコの「関数に引数を固定する」_.partial ってのを使ってみることにする。

_.partial は _.partial(function, *arguments) こんな感じの仕様で、関数に引数を部分適用した関数を返す。関数を返す関数だから「高階関数」(higher-order function)ってやつだな。

あ。俺の hasProperties、引数が「オブジェクト」「プロパティ」の順じゃないか。これはこれで自分的には正しいので、 _.partial 使うためだけに逆にしたくはない。
じゃあ、こうしよう。

``` isAdoRecordset_take4.js
var isAdoRecordset = _.partial( function(p,o){return hasProperties(o,p)}, perlQw('CursorType LockType BOF EOF Fields') );
```

ダッセー。_.partial が先頭の引数しか部分適用できないからだ。
だれか拡張とかしてないかな。誰もやってなさげなら自分でやるしか。
仕方ないのでコード読んでみる。
あ。
コメントに「`_` acts as a placeholder by default」とか書いてある。どういうことだ？！
あ…

``` isAdoRecordset_final.js
var isAdoRecordset = _.partial( hasProperties, _, perlQw('CursorType LockType BOF EOF Fields') );
```

なるほどねー。うまいことできてる。
「_.partial が先頭の引数しか部分適用できない」はデマです。ごめんなさい。
作業用の変数や無名関数・引数を一掃したのでスッキリした。
とりあえずこれで完成としよう。

さてここで、hasProperties 初版をもう一度。

``` hasProperties_take1.js
function hasProperties( o, props ) {
	return _.every(props,function($_){return ! _.isUndefined(o[$_])} );
}
```

はいはい、作業用の無名関数や ! による論理反転とかがあるのが気になってきた。
まずは論理反転から。「プロパティ参照の結果が undefined ではない」じゃなくストレートに「オブジェクトのプロパティか」にすれば正論理だ。

てなわけで第2版。

``` hasProperties_take2.js
function hasProperties( o, props ) {
	return _.every(props,function($_){return $_ in o} );
}
```

ああ、待てよ？「オブジェクトのプロパティか」とかアンスコにあるんじゃねえか？
…あった。_.has(object, key)
_.every から呼べるように第1引数を部分適用すれば無名関数を無くせる。

``` hasProperties_final.js
var hasProperties = function( o, props ) {return _.every( props, _.partial( _.has, o ) )};
```

こちらもこれで完成だ。わざわざ _.partial 使うのはやりすぎのような気もするが、今回はまあ Underscore.js の活用演習ってことなので。

これでいいのだ。
RustでBERT！？rust-bertで遊んでみた (前半)

最近、勉強を始めたRust初心者の「よこ」です。
Rustには [rust-bert](https://docs.rs/rust-bert/latest/rust_bert/) なるクレートがあるんですよ！！！期待しか無いですよね。
実際に、 [rust-bert](https://docs.rs/rust-bert/latest/rust_bert/) でHuggingface上のモデルを使ってみたいなと思い、
いろいろ触ってみました。

## 流れ

- この記事→　環境構築＆準備(モデルの変換)
- [次の記事](https://qiita.com/Yokohide/items/104c9ae39bb3939ccc36)→　GPT-2でTextGenerationタスク

:::note info
今回、PyTorch用→Rust用への変換から解説しています。
モデルの変換をせず、推論だけ試してみたい方は、
- **libtorchのインストール**
- **Rust用に変換**
を飛ばしてください！
:::

## 使用環境
OS: Pop!_OS 21.10（Ubuntu）
CUDA: 11.3
Python: 3.8.9
torch: 1.10.2+cu113
(CPU用で書いてます！)

## Rust環境の準備

Rustの日本語ドキュメント通りに進めて、`cargo`が使えるようにします。
（割愛します）
[https://doc.rust-jp.rs/book-ja/ch01-01-installation.html](https://doc.rust-jp.rs/book-ja/ch01-01-installation.html)


## libtorchのインストール
PyTorchのダウンロードページから、LibTorchをダウンロードしてきます。
![Screen Shot 2022-03-07 at 11.20.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550844/2f3c64c6-68f3-6ab1-3219-df0278dc9a1b.png)
[https://pytorch.org/](https://pytorch.org/)

`Download here (cxx11 ABI):`のURLをコピーして、wgetで取ってきました。
```bash:bash
wget https://download.pytorch.org/libtorch/cu113/libtorch-xxx.zip
unzip libtorch-xxx.zip
sudo cp -r libtorch/include/* /usr/local/include/
sudo cp -r libtorch/lib/* /usr/local/lib/
sudo cp -r libtorch/share/* /usr/local/share/
sudo ldconfig
sudo reboot now
```

※こちらの記事を参考にさせていただきました。
[pythonで学習したDNNモデルをC++から利用する（PyTorch & libtorch版）](https://qiita.com/nmatsui/items/1f6daee53669976f9bd0)

## 変換用モデルの準備
(自前のモデル + vocabファイルなどが準備出来ている方はスキップしてください。)
今回はHugging Faceに上がっている、gpt2をRust用に変換してみました。
※既に`rust_model.ot`が準備されていますが、練習用ということで...

```:bash
// git-lfsが入っていない人用
sudo apt install git-lfs

// モデルのダウンロード
git lfs install
git clone https://huggingface.co/gpt2
```

## Rust用に変換
PyTorch用の`pytorch_model.bin`はそのままでは使えないので、Rust用の`rust_model.ot`に変換する必要があります。
参照
[Loading pretrained and custom model weights](https://docs.rs/rust-bert/latest/rust_bert/#loading-pretrained-and-custom-model-weights)

まずはrust-bertのリポジトリを取ってきます。
```bash:bash
git clone https://github.com/guillaume-be/rust-bert.git
```
このようなディレクトリ構造を想定しています。
```bash:bash
workspace
    ├── gpt2/(もしくは自前のmodel)
    │    └──...
    └── rust-bert/
            ├──...
            ├──utils/
            ├──...
```
さっそく変換していきます。
(torchなどのモジュールが足りないなどは各自インストールしてください。)

```bash:bash
python ./rust-bert/utils/convert_model.py ./gpt2/pytorch_model.bin
```

`convert_model.py`の中を見たらわかりますが、`cargo run`が実行されており、必要なクレートのダウンロード + ビルドが自動で行われてます。

```bash:bash
ls gpt2/
... ... ... rust_model.ot ... ... ...
```
やったー！！！(gpt2には既に用意されてたので、上書きしただけですが。)

## まとめ
今回はHugginfaceの`gpt2`を変換してみましたが、rinna社の`japanese-gpt2-small`も同様に変換できました。

次の記事では実際にTextGenerationタスクをしてみます。

後半は[こちら](https://qiita.com/Yokohide/items/104c9ae39bb3939ccc36)から
特定のファイルをlint-stagedの対象から除外する

## この記事のゴール

以下の理解が得られることを本記事のゴールとします

- `.eslintignore`で該当するファイルをpre-commit時の対象から除外する方法が理解できること

## 自動生成したファイルをlint-stagedが検知してエラーが出た

筆者の所属しているプロジェクトではNestJSで作ったAPIをNext.jsでも呼び出せるように`openapi-generator-cli`を利用しているのですが、その過程で自動生成されたファイルがlint-stagedで検知されエラーが吐かれてコミットできないという問題が発生していました。

元々、自分が書いたコードをきれいにしてリモートにあるコードをきれいに保つ目的が、その目的外のところで動作していてそれを避けたかったというのがこの記事を書こうと思った背景です。

## `.eslintignore`の設定をlint-stagedに反映させる

と思ったらREADMEのFAQにしっかり書いてありました。

[https://github.com/okonet/lint-staged#how-can-i-ignore-files-from-eslintignore](https://github.com/okonet/lint-staged#how-can-i-ignore-files-from-eslintignore)

lint-stagedが走るタイミングで.eslintignoreファイルを読み込んで、該当するディレクトリやファイルを除外するようです。

## 手順

筆者は以下のケースで設定したのでケースに応じて書き換えてください

- ESLint: v7.32.0
- pre-commitで`.eslintignore`に該当するファイルを除外したい

また、筆者と同様の環境はこちらの記事で作成できます。

https://qiita.com/mu-suke08/items/43a492fda5cd71a31506

### 1. `.lintstagedrc.js`を作成する


::: note warn
注意：Eslintのバージョンによって記載する内容が異なるので注意してください。
:::

****ESLint < 7****

```jsx
import { CLIEngine } from 'eslint'

export default {
  '*.js': (files) => {
    const cli = new CLIEngine({})
    return 'eslint --max-warnings=0 ' + files.filter((file) => !cli.isPathIgnored(file)).join(' ')
  },
}
```

****ESLint >= 7****

```jsx
const { ESLint } = require('eslint')

const removeIgnoredFiles = async files => {
  const eslint = new ESLint()
  const isIgnored = await Promise.all(
    files.map(file => {
      return eslint.isPathIgnored(file)
    })
  )
  const filteredFiles = files.filter((_, i) => !isIgnored[i])
  return filteredFiles.join(' ')
}

module.exports = {
  '**/*.{ts,tsx,js,jsx}': async files => {
    const filesToLint = await removeIgnoredFiles(files)
    return [`eslint --max-warnings=0 ${filesToLint}`]
  },
}
```

### 2. `.husky/pre-commit`のコマンドを変更する

次に手順1で設定したファイルを動作するタイミングで呼び出すように以下のように書き換えます。

```bash
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx lint-staged --config .lintstagedrc.js
```

これで`.eslintignore`に設定したパスはlint-stagedの対象から除外されるようになりました。

## 余談

この記事で少しでも「husky導入してみようかな？」と思ったら導入記事も書いているのでぜひ読んでみてください！

https://qiita.com/mu-suke08/items/43a492fda5cd71a31506

ではまた！

## 参考記事

https://github.com/okonet/lint-staged

https://zenn.dev/wattanx/articles/lint-staged-eslint-max

https://qiita.com/mu-suke08/items/43a492fda5cd71a31506
VSCode UIの拡大率を固定。永久に固定する！！

# はじめに

Ctrl + "何か" のキーバインドを多用しているため、ミスタッチで拡大縮小のショートカットキーであるctrl+=とctrl+-キーを押してしまうことがあり、UIの拡大率が変わってしまうことが頻発していた。この拡大縮小のショートカットキーは0.1単位で設定することができないので、自分のような0.1単位でUIの倍率を変更している人間にとって邪魔以外の何物でもない。

# 開発環境

Windows10
モニタ解像度　2560x1440
Displayのzoom倍率　125%

# 設定

keybindings.jsonに以下を追記。

```json:keybindings.json
{
  	{
		"key": "ctrl+oem_plus",
		"command": "-workbench.action.zoomIn"
	},
	{
		"key": "ctrl+oem_minus",
		"command": "-workbench.action.zoomOut"
	}
} 
```

自分のsettings.jsonのUI拡大率は-0.7

ちなみに開発環境は、Windows10でモニタ解像度2560x1440でDisplayのzoom倍率は125%です

```json:settings.json
{
	"window.zoomLevel": -0.7, // UIの拡大率 (誤入力により設定値が変わらないように、必ず、拡大縮小キーを無効化しておくe.g)keybbindings.jsonに Ctrl + =, Ctrl + - を追記)
}
```
【PHP】__construct(コンストラクタ)の練習

# コード
```PHP
<?php
class Dog {
    private $name;
    private $weight;
    private $height;

    public function __construct($name, $weight,$height){
        $this->name = $name;
        $this->weight = $weight;
        $this->height = $height;
    }

    public function introduce(){
          $this->introduce_name();
          $this->introduce_weight();
          $this->introduce_height();
    }
    private function introduce_name(){
        echo '僕の名前は'. $this->name. 'だワン!'.PHP_EOL;
    }
    private function introduce_weight(){
        echo '僕の体重は'. $this->weight.'kgだワン!'.PHP_EOL;
        echo ($this->weight < 10 ? '小型犬だワン!' : '中型犬以上だワン!').PHP_EOL;
    }
    private function introduce_height(){
      echo '僕の体長は'. $this->height.'cmだワン!'.PHP_EOL;
    }
}
$hati = new Dog('ハチ', 9,70);
$hati->introduce();
```

# 結果
```
僕の名前はハチだワン!
僕の体重は9kgだワン!
小型犬だワン!
僕の体長は70cmだワン!
```
未経験からインフラエンジニアを目指して④

## フリースペース(好きに書かせて貰いますのコーナー)
新たなチャレンジを開始して初めての週末でした。
参考書を読んだりWebで情報を探したり、復習を兼ねて問題集に取り組んだりして
有意義に過ごしました。

**<font color="blue">ですが！リフレッシュも必要！！</font>**

と言う事で、小学生の頃からのライフワーク(？)でもある、サッカー観戦に行ってきました。
あぁ、愛しの埼玉スタジアム、私を迎え入れてくれてありがとう。
(お金払ってチケット買ってるんで当たり前ですが)
こんなご時世ですので、大きな歓声を上げる事は出来なかったですが、それでも十分に
リフレッシュする事が出来ました、これでまた1週間頑張れそうです。

**＜お知らせ＞**
当面の目標については目的意識がブレないように、毎回記載しています。
無事達成して次の目標を定める時には随時更新していきます。
## 取り組み内容(当面の目標)
- ネットワークについての知識を会得し、理解を深める
- 頭で覚えただけでなく、きちんと専門用語を用いて説明出来るようになる
- 資格取得(CCNA)する

**<font color="Red">資格取得はスタートライン！実際の作業で滞りなく行えるようになる！！</font>**
## 今回行った学習
**1. CCNAの問題集への取り組み**
- **ネットワークの基礎**
基礎部分なので｢覚えている事は結構あるだろう｣と想定していましたが、私の考えは
甘い事をいきなり痛感させられました。
初回は思ったよりも出来ず、正答率40%程度でしたが、50%は最低でも超えたかった。。。
改めて本やWebから情報を得て整理し、再度テストを行って80%程度まで改善しましたが
繰り返し問題に取り組んでいきます。

- **TCP/IP**
ここは必要な用語や情報の収集が足りていませんでした。
OSI参照モデルについては学習しましたが、TCP/IPプロトコルスタックについては
全く学習していなかった為に知識を得ておらず。
また、以前にも｢この部分で苦戦｣と書きましたが、サブネット関連の問題が壊滅的に。。。
でも慌てないで、もう一度情報を得た上で整理して、必ず理解させます。

- **Ciscoデバイスの導入**
Cisco製機器の知識が必要でしたが、全く学習していなかった為、ほぼ回答できず。
先週やった内容だけでは、当然ですが足りてないですね。
とはいえ、やるべき内容がはっきりしてきたので、ポジティブに受け止めて
効率的な学習をしていきます。

- **VLANとVLAN間ルーティング**
｢Ciscoデバイスの導入｣と同様、まだまだ知らない用語、コマンドがあります。
これまで学んだ用語も、うる覚えが多い為に答えられず。

立て続けに強敵な問題が出現してきて、なかなか精神力を削られましたが、私は諦めが悪く
負けず嫌いなのでまだまだ頑張ります！

**明日も学習した事を書いていきたいと思います。**
React Hookを使ってないのにHookのエラーが出た

## 概要

タイトルの通り。
yarn startしたら以下のようなエラーが表示された。

```
React Hook "" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function
```

環境は以下の通り
React: 16.2.0


## 原因と解決策

__原因__：「use」から始まる名前のメソッドを作った
__解決策__：メソッド名を「use」から始まらないものに変える

今回引っかかったメソッド名は「useDateCheck」。
この名前にしたのは「利用日の確認」がしたかったからである。

## 感想

Hooksを使えるようなバージョンでもないので、エラーが出たときは頭の中が疑問符でいっぱいでした。
こうゆうこともあるんだな、と一つ学びました。
ACDLを提唱します。その3

# 概要

ACDLとは、アプリは、クラウド、大切なデータは、ローカルです。
plunkerで、jsonを読み込み、書き込みしてみた。
vuetify使ってみた。

# サンプルコード

```
new Vue({
  el: '#app',
  vuetify: new Vuetify(),
  data() {
    return {
      search: '',
      logJson: [],
      items: []
    }
  },
  methods: {
    async loadLog(event) {
	    const files = event.target.files || event.dataTransfer.files;
   	  const file = files[0]
	    if (!this.checkFile(file)) 
	    {
		    alert("ファイルを読み込めませんでした")
		    return
	    }
	    const logData = await this.getFileData(file)
      alert(logData);
	    logJson = JSON.parse(logData)
    }, 
    getFileData(file) {
	    return new Promise((resolve, reject) => {
		    const reader = new FileReader()
		    reader.readAsText(file)
		    reader.onload = () => resolve(reader.result)
		    reader.onerror = error => reject(error)
	    })
    },
    checkFile(file) {
	    if (!file) 
	    { 
		    return false
	    }
	    if (file.type !== 'application/json') 
	    {
		    return false
	    }
	    const SIZE_LIMIT = 5000000 
      if (file.size > SIZE_LIMIT) 
	    {
		    return false
	    }
	    return true
    },
    saveLog() {
      //alert("ok1");


      var url = URL.createObjectURL(new Blob([logJson]) , { 
        type: "text/json" 
      });
      var a = document.createElement('A');
      a.download = 'data.json';
      a.href = url;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);


    },
  }
})




```

# 成果物

https://embed.plnkr.co/plunk/KjR1RiE8fOUqp2hE

以上。
【bottle】Pandasで生成したExcelをダウンロードさせるサンプル

# 環境
・Python3
・bottle 0.12.19
・pandas 1.4.1

# サンプル

Python

```
import datetime
from bottle import run, template, route,response
from io import BytesIO
from pandas import ExcelWriter
import pandas as pd

# TOP画面
@route('/')
def hello():
    return template('temp_download')

# ダウンロード機能
@route('/download')
def download():
    output = BytesIO()
    writer = ExcelWriter(output, engine='xlsxwriter')

    # Excel書き込みデータの準備
    # 書き込みデータはサンプル
    data_list = [["One",1],["Two",2],["Three",3]] 
    df = pd.DataFrame(data_list)
    
    # Excel出力
    df.to_excel(writer, sheet_name='Sheet1')
    writer.save()

    # 書き込みファイル名は時間を使用
    dt_now = datetime.datetime.now()
    name = 'test_{date}.xlsx'.format(date=dt_now.strftime('%Y%m%d%H%M%S'))
    
    # ダウンロード処理
    response.contet_type = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
    response.add_header('Content-Disposition', 'attachment; filename="{name}"'.format(name=name))
    return output.getvalue()


# メイン起動
if __name__ == "__main__":

    # IPの指定、ポートの指定
    run(host='localhost', port=8080)
```

HTML

```
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Excelダウンロードページ</title>
</head>
<body>
    <button type=“button” onclick="location.href='/download'">ダウンロード</button>
    
</body>
</html>
```

# 出力結果
![スクリーンショット 2022-02-28 15.45.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504099/b507b4e7-4f33-de64-f9dd-ee88c0766746.png)
【Webを支える技術】を読んで

こちらの記事は随時更新中

# はじめに
ネット上でエンジニア初心者に対してよく勧められている本だったので随分前から気になっていましたが中々重い腰が上がらず。業務でHTTP通信を取り扱うことが徐々に増え、どういったレスポンス、リクエストを行うのが望ましいのか
設計する上で気になったので重い腰を上げて我慢して読んでみました。

# 目次
* 1, [WebのアーキテクチャスタイルとしてのREST](#1-webのアーキテクチャスタイルとしてのrest)
    * 1-1, [REST](#1-1-rest)
    * 1-2, [リソース](#1-2-リソース)
    * 1-3, [RESTの構成](#1-3-restの構成)

* 2, [URIの設計](#2-uriの設計)
    * 2-1, [クールURIは変わらない](#2-1-クールuriは変わらない)
    * 2-2, [URIの不透明性](#2-2-uriの不透明性)
 
# 1, WebのアーキテクチャスタイルとしてのREST

### 1-1, REST
REST とは クライアント/サーバ から派生したアーキテクチャスタイルのこと。
クライアント/サーバ とはサービスやリソースを要求するクライアントとそれに応えるサーバーが通信を行うアーキテクチャのことらしい。
サーバーの実例で私に馴染み深いところをあげると、、、

・Webサーバー (Apache HTTP Server, nginx等)
・データベースサーバ(MySQL, PostgreSQL等)

がある。他にもメールサーバーやFTPサーバーがあるがここでは割愛。

こういったサーバーとクライアントのやりとりに様々な制約を加えていくことでRESTというアーキテクチャが形作られていくようだ。

### 1-2, リソース
REST における重要な概念の一つにリソースがある。
リソースを簡潔に表すと「`Web上に存在するありとあらゆる名前を持った情報`」とのこと。

以下、リソースの例

・東京の天気予報
・ある学術論文
・ブックマーク 

そしてこれらのWeb上に存在する情報が持つ名前というのが、`URI`を指す。
これらの名前は世界で一意である。
URIを使用することによってリソースに簡単にアクセスできる性質のことを「アドレス可能性」という。

### 1-3, RESTの構成
1-1でクライアント/サーバーアーキテクチャに様々な制約を追加していくことでRESTを作っていくと伝えたが下記で
その追加する制約について述べていく。

(1)`ステートレス`
> クライアントアプリケーションの状態(セッション状態)をサーバー側で管理しないこと。各通信は独立した情報を持っておりサーバー側は今まで行った通信と全く関係のないものとして処理する。よってサーバー側の実装はリクエストに対する処理に集中でき、実装が簡潔になる。

(2)`キャッシュ`
>一度サーバーから取得したリソース(サイトの画像など)をクライアント側で使い回すのに役立つ。通信回数が減るのでパフォーマンス的にメリットはあるが古いリソース情報を使いまわさないように注意。

(3)`統一インターフェース`
>→ HTTPメソッドに見られるように通信方法を制限することでアーキテクチャがシンプルに。また通信方法を統一することでよりクライアント、サーバーの独立性が増し、クライアントの種類に依存せずにサーバー側はリソースを提供できる。
逆にクライアント側は統合インターフェースさえ守っていれば様々なサーバーと通信が可能になる。


(4)`階層化システム`
>統一インターフェースによって実現ができる。各クライアントやサーバーは統一インターフェースで定められた方法で通信を行うため、クライアントとサーバーの間にプロキシサーバーを挟んだり、統一インターフェースを実現していないレガシーなシステムの前に統一インターフェースを実現したアプリケーションを挟むことでクライアントからレガシーシステムに通信が可能になる。

(5)`コードオンデマンド`
> プログラムコードをサーバーからダウンロードしてクライアント側で実行するアーキテクチャスタイル。JavascriptやFlash, Javaアプレット」が該当する。


# 2, URIの設計
### 2-1, クールURIは変わらない
・プログラミング言語に依存した拡張子はURIに使用しない。プログラミング言語の選定が切り替わった際にURIを変更せざるをえないので。

・メソッド名やセッションIDを含めない。リファクタリングした際にメソッド名が変わったり処理内容が変更になる恐れがある。またセッションIDを使用することでURIはログインの度に切り替わってしまう。

もしURIを変更したい場合は古いURIにリクエストが飛ばされたら新しい変更後のURIにリダイレクトさせると良い。

### 2-2, URIの不透明性
ユーザーが直接URIを叩かないようにするべき。
例えばPDFリソースを提供するURIが下記の通りあった場合、ユーザーはPDF以外にHtmlリソースがあるかも、と推測し
拡張子を.pdfから.htmlに書き換えて直接叩くかもしれない。

・PDFリソースを返すURI
`http://example.jp/press.pdf` → `http://example.jp/press.html`

このような操作が行われるのはシステムの停止につながる恐れがあるため、あまり好ましくない。ユーザーからはリソース構成を推測しにくいURI設計を心がけるべき。
AWS Amazon Linux2にアプリケーションインストールする時どれをインストールすればいいの？

# 概要

- Amazon Linux2にMySQLなどをインストールするときにどのLinux向けのパッケージをインストールすれば良いのかメモ的にまとめてみる。

# 結論

- Red Hat Enterprise Linux(RHEL)7/CentOS7 系のものを選んでおけば大丈夫そう。

# 結論に至った経緯

- 結論の記載がふわっとしているのはどこにも「RHEL7/CentOS7系なら絶対大丈夫です！ AmazonLinux2は互換があります！」とは記載されていない。
- 下記のEC2の概要やQ&Aにも明示的に記載されていなかった。
    - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/amazon-linux-ami-basics.html
    - https://aws.amazon.com/jp/amazon-linux-2/faqs/
- 30分くらいネットの海を漂ったが、自分の力不足で下記のような「確からしい情報」を掴むのが精一杯だった。
    - https://www.acrovision.jp/service/aws/?p=653
    - 一部抜粋

        ```
        RHEL7 / CentOS7 をベースとしていると言われております。Systemd が採用されていることからも、実際の操作は RHEL7/CentOS7 に近いです。
        ```

- そして下記の記事でも紹介している様にRHEL7系のyumリポジトリでMySQLをインストールして問題なく動作しているのでこちらで結論に至った。
    - [AWS EC2 AmazonLinux2 MySQLをインストールする](https://qiita.com/miriwo/items/eb09c065ee9bb7e8fe06)

        ![MySQL____Download_MySQL_Yum_Repository.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/fe61ca88-859f-023b-ab84-756cb3551182.png)
WebRTCでリモートワーク用コールセンターを作る

# リモートワークとコールセンターは相性が良くない

「コールセンターは」とひとくくりにするのは乱暴かもしれません。
しかし「一人でリモートワークを行い、電話業務を続ける」のは難易度が高い作業です。
様々なお客様を相手にストレスをためずに仕事する、可能ならリモートワークを実現する、そんなことが可能でしょうか？
***
# コールセンターをリモートワークベースにする上での課題
- エージェント（オペレーター）のリモート環境の整備が難しい
- エスカレーションできない
- SV（いわゆるグループリーダー）が通話をモニタリングできない。メンバーを観察できない
- チームとして助け合えない、コミュニケーションが取りにくい
***
# バーチャルオフィスという潮流

リモートワーク一般に関しては「バーチャルオフィス」というWebサービスが色々と誕生しました。
- ブラウザを開くだけでその中に仮想のオフィスが準備されている
- 仮想のオフィス内を動き回ると同僚を見つけることができる
- 相手に近寄っていくと雑談ができたり、他の人の会話に加わったりできる
- 仮想のオフィスの中で同じ動画やサイトを視聴したり、会議したりできる
- 外部のお客様がオフィスに訪ねてくることができる
***
# バーチャルコールセンター、アバターコールセンター？
弊社はコールセンターの技術を研究している会社なので、
「バーチャルオフィスとコールセンターを合わせた製品を企画できないか」
と考えました。
***
# リモートワーク用コールセンター
当初は「バーチャルオフィスの中に “バーチャルソフトフォン”を置き、仮想のコールセンター拠点をミニチュア的に作れば良いのではないか」と考えました。オープンソースで公開されているバーチャルオフィスソフトもありますし時間をかければ作り込めるかもしれません。（実は結構、作り込むという線で色々と動きました。）
ただこういう製品はそれぞれの製品ごとに「思想と文化」がありますので、どんなジャンルの職場にもフィットする、というよりは「それぞれの業種や職場に合った、コールセンターごとに異なる多種多様な機能が必要になりそう」でした。
それで次に考えたのが「既存のバーチャルオフィスサービスとコールセンター機能を組み合わせてみる」ことでした。
***
# WebRTCの技術と組み合わせてみる
試しに「Webブラウザの中にWebRTCを使ってコールセンターの機能を組み込むと同時にバーチャルオフィスもiframeで入れてみる」ということを試してみました。すると製品によっては思った以上にうまく組み合わせることができました。
WebRTC系のSDKであればオープンソースのものでもプロプライエタリなものでも使用可能。
***
![MicrosoftTeams-image (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114744/ef958440-481f-e5e8-d7de-cc2d8968cdd0.png)
***
## 動きは？
- WebやチャットLINE経由のお客様とオペレーターが通話できる
- AvayaやCiscoその他のPBXからの着信を受ける
- オペレーターは同時にバーチャルオフィスにも存在しているので、SVは近寄っていくだけで会話の様子をモニタリングできる
- 必要があればリモートワーカー同士がサポートしあえる
- WebRTCのSDKが対応していれば3者通話やエスカレーションも可能になる
- iFrameで任意のバーチャルオフィスのサービスを組み込めるので、自分のコールセンターに適合した仮想オフィスを導入可能
- iFrameで入れた場合には複数のサービスで同一のマイク・スピーカーデバイスを共用できる
***
# さらに近未来は
Meta Quest(Oculous)などを使ったアバターコールセンター、AIがアバターとして活躍するコールセンターも実用化まできているのではないでしょうか。
コールセンターはお客様に安心感を与えるものですので、お客様の年齢層、業種によっては今でも、電話による昔ながらの音声通話が最適な場合もまだまだあります。
しかし、お客様との距離を解消する技術は次々と誕生しています。
Nodejsサーバーのファイル監視と自動再起動


初投稿です。
foreverを使う選択肢もありますがsystemdでやります。

# 目的
gitで自動デプロイしているNodeサーバーがあり、それをデプロイ後に自動で再起動させたい。

# 方法
- systemdでサーバーをデーモン化
- systemd.pathを使ってファイル監視して更新されたら再起動

## デーモン化
まずサーバーのデーモン化
``` /home/user_name/systemd/my_server.service
[Unit]
Description=hogehoge

[Service]
User=user_name
WorkingDirectory=/{サーバーまでのパス}/
ExecStart=/{nodeのパス}/node server.js
Restart=always

[Install]
WantedBy=multi-user.target
```
シンボリックリンクをsystemdのディレクトリに作成しサービスを有効化、起動
```
ln -s /home/user_name/systemd/my_server.service /etc/systemd/system/my_server.service
systemctl enable my_service.service
systemctl restart my_service.service
```
ファイルは`/etc/systemd/system/`に直接置いても良いが、root権限をあまり使いたくないため今回はホームに置いた。

これでNodejsサーバーはデーモン化され、止まっても自動再起動するようになった。
次は`server.js`を監視して自動再起動するように設定する。

## ファイルの監視

ファイルの監視は`{サービス名}.path`で行うことが出来る。指定したpathに変更があれば`{サービス名}.service`を起動してくれる。
が、ここにハマりポイントがあった。

```my_server.path
[Unit]
Description=hogehoge

[Path]
PathChanged=/{サーバーまでのパス}/server.js

[Install]
WantedBy=multi-user.target
```
これを有効化、起動した。これで`my_server.service`が再起動すると思ったのだが、`server.js`をいくら変更しても反映されない。
調べたところ、ファイルの変更に反応して「起動」するのであって「再起動する」のではなく、`my_server.service`は既にactiveなので起動できず反映されていない模様。

### 解決策
再起動を行うサービスを別で用意する。
```/home/user_name/systemd/my_server-watcher.service
[Unit]
Description=hogehoge

[Service]
Type=oneshot
ExecStart=/usr/bin/systemctl restart my_server.service

[Install]
WantedBy=multi-user.target
```
このサービスが起動すると`my_server.service`を再起動してくれる。あとはこれをファイル監視で起動させる。
```/home/user_name/systemd/my_server-watcher.path
[Unit]
Description=hogehoge

[Path]
PathChanged=/{サーバーまでのパス}/server.js

[Install]
WantedBy=multi-user.target
```
同様にシンボリックリンクの作成、有効化、起動を行う。

# 結論
反映された。

# 感想
実用にはここにログの設定などをするべきなのだと思います。
理解が浅いのでまさかりお待ちしています。

# 参考
https://qiita.com/fernet/items/2bce98291b05a9d30386

https://superuser.com/questions/1171751/restart-systemd-service-automatically-whenever-a-directory-changes-any-file-ins
【docker】dockerコマンドが効かずエラーが出た時の対処法

ubuntu(WSL2)でdockerコマンドを実行したらエラーが発生したので対処法についてメモしておく。

# 問題
ubuntu(WSL2)の起動時にdockerコマンドを実行したら下記のエラーが発生した。

```
$ docker images
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? 
```

# 解決策
このエラーは、dockerが起動していないことが原因らしい。
そのため、下記のコマンドでdockerを起動させることで、エラーは解消される。【参考:[Docker docs](https://docs.docker.com/config/daemon/systemd/#start-the-docker-daemon)】
```
$ service docker start

// 確認
$ service docker status
* Docker is running
```
しかし、dockerの起動はシステムの起動時に毎回行う必要があるらしい。
【MATLAB】it appears to be corrupt？変数をファイルに保存できないときの解決策

## 状況：ファイルに保存できない
MATLAB でワークスペース変数をファイルに保存しようとすると．．
```matlab
save('/卒論/a.mat', 'A')
```
以下のようなエラーが出てしまいました
```matlab
Error using save
Unable to write to file '/卒論/a.mat' because it appears to be corrupt.
```
## 解決策：ファイルのパスに日本語を含めるな！！
ファイルのパスに日本語を含まないようにすると，上手く保存できるようになりました！分かってしまえば簡単なことなのですが，このことに気づくのに半日くらいかかってしまいました．．

もし同じようなエラーに直面した方がいらっしゃいましたら，参考にしていただけると嬉しいです！
初心者ブロックチェーンに挑戦する　5

# 仕切り直し

## なにもムダにはならない

　実在のブロックチェーンに同期するという大冒険に失敗したあと、マイナーの友だちが同期しても大丈夫だよといってはくれたのだが、けっきょく各種2019年情報はいったん放棄して、新しい試みに挑戦することにした。２月に申し込んであった[UNCHAIN](https://app.shiftbase.xyz)は、５日スタートの第一陣にこそ入れなかったものの、今日、待望の招待状が来て、いざ、スタート。

　クローズな課題なので詳しく書くわけにはいかないけれど、ともかく、これまでの環境構築は全て役に立って、いきなり課題を始めることができて、ラッキーだった。本物のブロックチェーンに同期するかわりに、自分で20ものアカウントを持って、ダミーのコインを送ったり送られたりしながらチェーンをつくっていく。だから、本物の世界では望むべくものない「チェーンの先頭のブロック」が自分のもの。full同期の、あの長い長いブロックの羅列を眺めていたのに比べて、この超短いチェーンが手の内にあるのが、なんとも嬉しい。

　五つの課題をクリアしたら、最後、自主制作になる。なにがつくれるようになるのか、まださっぱりだけれど、ともかく第一の課題を終えて、ちょっといい気分。
Jetpack Compose で背景画像を repeat させる

Android で背景画像を repeat させるには、以下のように実装します。[^1]

```xml:tile_background.xml
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:antialias="true"
    android:dither="false"
    android:filter="false"
    android:gravity="fill"
    android:src="@android:drawable/alert_dark_frame"
    android:tileMode="repeat" />
```

```xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/tile_background" />
```

ビルド結果は以下のようになります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93963/116e794c-f89e-94d4-d843-bce5e42eaf05.png" width="400" />

ですが、これを Jetpack Compose でやるとなった場合、残念ながら対応する Composable は用意されていません（2022 年 3 月 4 日時点）。

# 解決策

以下のように `AndroidView` を用意して、その中で背景画像を repeat させるようにします。

```kotlin:TiledImage.kt
@Composable
fun TiledImage(
    modifier: Modifier = Modifier,
    @DrawableRes id: Int,
    contentDescription: String? = null
) {
    AndroidView(
        modifier = modifier
            .semantics {
                contentDescription?.let {
                    this.contentDescription = it
                }
            },
        factory = {
            val bitmapDrawable = BitmapDrawable(it.resources, BitmapFactory.decodeResource(it.resources, id)).apply {
                tileModeX = Shader.TileMode.REPEAT
                tileModeY = Shader.TileMode.REPEAT
            }
            View(it).apply {
                background = bitmapDrawable
            }
        }
    )
}

@Preview(showBackground = true)
@Composable
private fun Preview() {
    TiledImage(id = R.drawable.alert_dark_frame)
}
```

ポイントとしては、`BitmapDrawable` を生成し、`tileModeX` および `tileModeY` に `Shader.TileMode.REPEAT` を設定することです。

```kotlin
factory = {
    val bitmapDrawable = BitmapDrawable(it.resources, BitmapFactory.decodeResource(it.resources, id)).apply {
        tileModeX = Shader.TileMode.REPEAT
        tileModeY = Shader.TileMode.REPEAT
    }
    View(it).apply {
        background = bitmapDrawable
    }
}
```

こちらは任意ですが、`contentDescription` を設定してテストしやすいように実装するのがおすすめです。

```kotlin
// contentDescriptionを設定してテストしやすいように
modifier = modifier
    .semantics {
        contentDescription?.let {
            this.contentDescription = it
        }
    }
```

プレビュー結果は以下のようになります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93963/6269f0ab-f4ca-ccba-e8de-b8301d268661.png" width="400" />

もっとより良い方法がありましたらご指摘ください。

[^1]: [Y.A.M の 雑記帳: Android　背景画像を repeat させる](http://y-anz-m.blogspot.com/2010/10/android-repeat.html) より引用。
AWS EC2 2種類のAmazonLinux2 AMIの差分 個人メモ

# 概要

- Amazon Linux 2には2種類のAMI（Kernel 5.10 と Kernel 4.14）があり、差分が気になったため調べてみた。

# やること

- 下記2種類のAMIの差分を調べてみる。

    ![インスタンスウィザードを起動___EC2_Management_Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/8e1cdc22-bf0b-20c2-63be-47d0d51948f4.png)

# 書いてあった

- AWSの公式Q&Aに当該の質問の答えがあった。
    - [https://aws.amazon.com/jp/amazon-linux-2/faqs/](https://aws.amazon.com/jp/amazon-linux-2/faqs/)
    - 下記は抜粋

        ```
        Q:カーネル 5.10 はカーネル 4.14 とどう違うのですか?
        カーネル 5.10 は、インテル Ice Lake プロセッサの最適化や最新世代の EC2 インスタンスに電力を供給する Graviton 2 など、多くの機能とパフォーマンスの向上をもたらします。 
        セキュリティの観点から、顧客は WireGuard VPN の恩恵を受けています。これは攻撃対象領域が少なく、オーバーヘッドが少ない暗号化を可能にする効果的な仮想プライベートネットワークのセットアップに役立ちます。カーネル 5.10 には、カーネルイメージの不正な変更を防ぐためのカーネルロックダウン機能と、CO-RE (Compile Once - Run Everywhere) を含む多くの BPF の改善も含まれています。
        入出力オペレーションを多用するお客様には、書き込みパフォーマンスの向上、入出力オペレーションの高速化のためのプロセス間での io_uring リングの安全な共有、ストレージデバイスとの互換性を高める新しい exFAT システムのサポートなどの利点があります。MPTCP (MultiPath TCP) を追加することで、複数のネットワークインターフェースを持つお客様は、利用可能なすべてのネットワークパスを組み合わせて、スループットの向上やネットワーク障害の低減を図ることができます。
        ```

- どうやら5.10のほうがパフォーマンスに優れているらしい、セキュリティ的にも5.10のほうが良さそう。
- 特段理由がない限り5.10を選べば問題なさそう。
Unityで「ここは自由文言で20文字が入力できる」と言われた時に考えることの全て

# 概要
もしあなたがタイトルのような指示を受けた時、この記事にある事例を挙げつつ、それぞれの事例でどういう挙動になるかの合意をとっておきましょう。

先に結論から言うと、Unityで文字数制限のある自由文言を受け付ける、はどこかで不完全な対応になります。どこまでは妥協するかを確認しましょう。

**この記事は不完全なので他のエッジケースをコメントで教えてください**

# 絵文字

https://light11.hatenadiary.com/entry/2019/11/18/221847
https://www.wojtekmt.com/entry/2019/05/18/200000

まずはこれです。そもそもuGUIの標準InputFieldは絵文字を入力できます。 
自由文言の中に絵文字があった場合はどうするべきか、対応方針を決めましょう。

- 絵文字は削除する
- 頑張る

## 絵文字における文字数
| 絵文字 | コードポイント | char数 | 意味 |
| -- | -- | -- | -- |
| 🏴󠁧󠁢󠁥󠁮󠁧󠁿 | 1f3f4-e0067-e0062-e0065-e006e-e0067-e007f | 14 | 旗 + イングランド |
| 🙋🏻‍♀️ | 1f64b-1f3fb-200d-2640-fe0f | 7 | 手を上げる女 + 薄い肌色 |

もし、上の対応方針で頑張ることを決めた場合「文字数制限」との兼ね合いが発生します。
もし20文字制限のInputFieldに対して「🏴󠁧󠁢󠁥󠁮󠁧󠁿🏴󠁧󠁢󠁥󠁮󠁧󠁿🏴󠁧󠁢󠁥󠁮󠁧󠁿」という文字が入力された時にあなたのアプリはどうなっていてほしいですか？

## 絵文字合字
👨‍👩‍👧‍👧 はあなたのUIではどう表示されていて欲しいですか？また、何文字と判定されていて欲しいですか？
👩‍❤️‍👩はZero Width Joinerを使った合字です。どう表示されていて欲しいですか？また、何文字と判定されていて欲しいですか？

# アラビア文字
右から左に表示されるInputFieldはあなたのUIの中ではどう見えていて欲しいですか？

## ﷽
﷽は「慈悲あまねく慈愛深きアッラーの御名において」という一文字です。
もし20文字制限のInputFieldに対して「﷽」という文字が20個入力された時にあなたのアプリはどうなっていてほしいですか？

# 𝑩𝑰𝑮𝑳𝑶𝑽𝑬
ℒℴѵℯ が入力された時にあなたのアプリはどうなっていてほしいですか？
ユーザからの𝑩𝑰𝑮𝑳𝑶𝑽𝑬をあなたはどう受け止めますか？

# 𩸽
𩸽も4バイトになります。あなたのアプリの20文字の文字数入力制限は𩸽を何文字入力できるようにしますか？
https://www.softel.co.jp/blogs/tech/archives/596

# uGUIのTextタグをどこまで受け付けるか
`<b>ボールド</b>`や`<size=99>でかい文字</size>`や`<color=red>色付き文字</color>`が入力された時にあなたのアプリはどうなっていてほしいですか？

# 禁止文字列はどう置き換えるか
ユーザが入力した文字が公序良俗に反していた場合のチェックはどこで行いますか？また多言語それぞれの禁止文字辞書はどうしますか？いままで出てきたさまざまなエッジケースを組み合わせた判定しにくい禁止文字に対してあなたのアプリはどこまで対応しますか？

# 結論
Unityの文字入力がもっとよくなるとうれしいな…
Webの勉強はじめてみた その35 〜Sequelizeを使った実装〜

N予備校「プログラミング入門Webアプリ」を受講しています。
今回は第4章18,19節です。

## UUID
:::note
任意のIDを作る。全世界で同じ値を持つことがない一意な識別子。
:::

データベースのデータ型として、UUIDが用意されている。

Node.jsで使う場合はライブラリをインストールする。
```
yarn add uuid@3.3.2
```

## データモデルの作成
```javascript:models/schedule.js
'use strict';
const {sequelize, DataTypes} = require('./sequelize-loader');

const Schedule = sequelize.define(
  'schedules',
  {
    scheduleId: {
      type: DataTypes.UUID,
      primaryKey: true,
      allowNull: false
    },
    scheduleName: {
      type: DataTypes.STRING,
      allowNull: false
    },
    memo: {
      type: DataTypes.TEXT,
      allowNull: false
    },
    createdBy: {
      type: DataTypes.INTEGER,
      allowNull: false
    },
    updatedAt: {
      type: DataTypes.DATE,
      allowNull: false
    }
  },
  {
    freezeTableName: true,
    timestamps: false,
    indexes: [
      {
        fields: ['createdBy']
      }
    ]
  }
);

module.exports = Schedule;
```

`indexes`
`CREATE INDEX`と同じ。あらかじめインデックスを作れる。

## データテーブル作成
```javascript:app.js
// Read DB Model
const User = require('./models/user');
const Schedule = require('./models/schedule');
const Availability = require('./models/availability');
const Candidate = require('./models/candidate');
const Comment = require('./models/comment');
User.sync().then(() => {
  Schedule.belongsTo(User, {foreignKey: 'createdBy'});
  Schedule.sync();
  Comment.belongsTo(User, {foreingKey: 'userId'});
  Comment.sync();
  Availability.belongsTo(User, {foreignKey: 'userId'});
  Candidate.sync().then(() =>{
    Availability.belongsTo(Candidate, {foreignKey: 'candidateId'});
    Availability.sync();
  })
})
```

`sync`
データモデルに合わせて、データテーブルを作成する。
データモデルを使ってエンティティ同士の関係を定義することで、後で自動的に `RDB`上でテーブルの結合をしてデータを取得できる。

`Schedule.blongsTo(User, {foreignKey:'createdBy'})`
`Schedule`は`User`に所属しているという意味。
`Schedule`の`createdBy`と`User`の主キーを結合する。

JOIN操作を前もって定義してるという認識。

### JOIN
```javascript
Schedule.findOne({
  include: [
    {
      model: User,
      attributes: ['userId', 'userName']
    }
  ],
  where: {
    scheduleId: req.params.scheduleId
  },
  order: [['updatedAt', 'DESC']]
})
```

`findOne`
データモデルに対応するデータを1件取得する。

`include`
JOIN操作

`model`
JOINするデータモデル

`attributes`
取得してくる値

### bulkCreate
 配列を渡して、複数のデータを登録する。

```javascript
function createCandidatesAndRedirect(candidateNames, scheduleId, res){
  const candidates = candidateNames.map((c) => {
    return {
      candidateName: c,
      scheduleId: scheduleId
    };
  });
  // candidateテーブルに 複数データを Insert
  Candidate.bulkCreate(candidates).then(() => {
    // 作成したスケジュールIDへリダイレクト
    res.redirect(`/schedules/${scheduleId}`);
  });
}
```

## まとめ
以前は`VB.NET`にしろ`PHP`にしろ、SQLを直接プログラムに書いてたクチなので、こういう`Sequelize`を使っての実装は、SQLが見えない分ちょっとわかりにくい印象。
`belongsTo`はちょっと違うと思うけど`view`を前もって定義するようなイメージでいます。
Excelおかじり講座

# 目次
- はじめに
- 関数の応用
- ピポットテーブル
- まとめ

# はじめに 
　MicrosoftOfficeの表計算ソフトとして知られているExcelを、楽に効率よく利用する方法をご存知でしょうか。
　皆さん、Excelをなんとなく利用してはいないでしょうか？もっと効率よく、速くなる時短技をこれから紹介したいと思います。
# 関数の応用
　皆さんはExcelが表計算ソフトといわれていることから、計算させるために「関数」を用いることはご存じかと思います。
　足し算をしたいときには、セル内に「=SUM(○○足し算させたいところ指定)」と書くことで、足し算がされたり、「=AVERAGE(○○平均させたいところ指定)」と書くことで、平均がされたりします。
　これを手動で入力するとなると少々手間がかかりませんか？
　しかし、もっといい方法があることを知りました。

![特別制作1 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533985/9bf3b17c-edb5-3274-5838-165d96021d7b.png)
この画像の場合、B4を選択した状態で左上のFXを押すと下記のウインドがでます。
![制作2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533985/33f5e7bd-8c3a-52fa-a2e7-4015b4e95e79.png)
今回は足し算なのでsumを選択し、ＯＫを押して次のウインドもＯＫで結果がでます。


# ピポットテーブル
　使い始めの人にとっては馴染みのない言葉だと思います。
　ピポットテーブルとは大量のデータを集計、条件を設定し絞り込んだり項目を組み換えることが可能です。

　あらかじめ下記の表を用意しました。2020年ゲームソフトランキングを作成しました。
![制作3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533985/b5271c3a-387e-e0eb-cae9-08b880787c82.png)
　まずセル範囲を選択して挿入タブのピポットテーブルを押すと下記のウインドがでます。このままＯＫで大丈夫です。![スクリーンショット (39).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533985/7523d7b1-9722-717e-224e-aaa3f4e1cce7.png)
　下記の画面が出てきます。次に右側のフィールドから表示したいものを２枚目の画像のようにドロップアウトします。
![スクリーンショット (42).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533985/94ea33d1-60d1-2426-1e37-6f674a6fa918.png)
![スクリーンショット (43).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533985/0e169e36-1db2-9c0c-8e64-6be65d354758.png)

　するとこのようになります。![スクリーンショット (44).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533985/9b074ebd-0390-9f0c-7b98-1c4edf46cd38.png)
これで完了です。

# まとめ
　・関数を忘れたり、手動で入力する
必要がないため作業効率が上がる

　・ピボットテーブルを使用することで、
ジャンル別などの集計が楽になる。

# 最後に
　当ブログの閲覧して頂きありがとうございました。
【Rails7】annotateのrouterが動かない

# 初めに

Rails の便利な Gem で annotate というものがあります。
データベースのスキーマと rotuer をファイルにコメントとして記述してくれる Gem です。
これのおかげで、確認のするための時間が減ります。
しかし、ここ最近更新がなく Rails7 に対応していない状態です。

## やりたい事

Rails7 でも annotate の router が動くように修正する

## 環境

- Ruby 3.1.1
- Rails 7.0.2.2
- annotate 3.2.0

# 解消法

## 原因

Rails6 から rake routes が廃止され、rails routes でルート一覧が出るようになりました。
Gem の内部のコードで rake routes が使われているので、そこを書き換えると動くようになります。

## Gem のソースコード

annotate のソースを見るために

`$ gem which annotate`

を実行し、コードの場所を特定します。

```console:コンソール
/rails # gem which annotate

/usr/local/bundle/gems/annotate-3.2.0/lib/annotate.rb

/rails # cd /usr/local/bundle/gems/annotate-3.2.0/lib/annotate/annotate_routes

/usr/local/bundle/gems/annotate-3.2.0/lib/annotate/annotate_routes  # cat header_generator.rb

```

ソースコードの`rake routes`を `rails routes` に書き換えると `annotate -routes` が動くようになります。

```ruby:header_generator.rb
require_relative './helpers'

module AnnotateRoutes
  class HeaderGenerator
    class << self
      # 省略

      def routes_map(options)
        #result = `rake routes`.chomp("\n").split(/\n/, -1)
        result = `rails routes`.chomp("\n").split(/\n/, -1) #ここのrakeをrailsに書き換えるだけ

        # In old versions of Rake, the first line of output was the cwd.  Not so
        # much in newer ones.  We ditch that line if it exists, and if not, we
        # keep the line around.
        result.shift if result.first =~ %r{^\(in \/}

        ignore_routes = options[:ignore_routes]
        regexp_for_ignoring_routes = ignore_routes ? /#{ignore_routes}/ : nil

        # Skip routes which match given regex
        # Note: it matches the complete line (route_name, path, controller/action)
        if regexp_for_ignoring_routes
          result.reject { |line| line =~ regexp_for_ignoring_routes }
        else
          result
        end
      end
    end

  end
end

```

# 参考

修正のプルリクエストがあるのだが、未だマージされていない便利なジェムなのでこのまま無くなるのは惜しい。

[プルリクエスト](https://github.com/ctran/annotate_models/pull/843)
transformersのサンプルをオフライン環境で動かしてみる

# 初めに
最近の深層学習のライブラリは親切でサンプルコードがgithubに公開されています。
私もよく利用させてもらっているのですが、サンプルコードではインターネット上にデータを取得しに行くなどしているため、
重要データを扱うような隔離された環境では実行できません。
今回は隔離された環境でもサンプルのコードを実行できるようにtransformersの1サンプルの実行例を紹介したいと思います。


# コードとデータの準備
本記事ではhuggingfaceのtransformersというフレームワークを使用してテキスト分類のサンプルを実行します。
実験コードとデータの事前準備はインターネットにつながるマシンで行ってください。

### 学習コード準備
学習するコードは[transformersのgithub](https://github.com/huggingface/transformers)から取得します。
```
$ git clone https://github.com/huggingface/transformers.git
```
本記事ではクローンしたコードの「transformers/examples/pytorch/text-classification/」を使用します。
以下の記事では「transformers/examples/pytorch/text-classification/」内にファイルを配置すること前提です。

### 事前学習モデルクローン
事前学習モデルは[huggingface](https://huggingface.co/bert-base-uncased)からダウンロードします。
サイズが大きいモデルが保存されているためgit-lfsを使用してクローンしましょう。
```
$ git-lfs clone https://huggingface.co/bert-base-uncased
```

### 学習データダウンロード
本来はコード内でうまいことやってくれていますが、オフライン環境前提なのでデータを手動でダウンロードします。
下記の3ファイルダウンロードして適当なディレクトリに格納してください。
※本記事では「data」ディレクトリを作成しその中に格納しています。

* https://dl.fbaipublicfiles.com/glue/data/mrpc_dev_ids.tsv
* https://dl.fbaipublicfiles.com/senteval/senteval_data/msr_paraphrase_train.txt
* https://dl.fbaipublicfiles.com/senteval/senteval_data/msr_paraphrase_test.txt


### 不足スクリプトダウンロード
こちらもインターネットに接続されていれば自動でダウンロードされるスクリプトですが、オフライン環境では事前にダウンロードしておきます。
glue.pyはデータを扱うためのコードで、accuracy.pyは精度計算用のコードです。
※本記事ではaccuracy.pyは「module」ディレクトリを新たに作成しその中に格納しています。
* https://huggingface.co/datasets/glue/raw/main/glue.py
* https://raw.githubusercontent.com/huggingface/datasets/master/metrics/accuracy/accuracy.py


必要なファイルをダウンロード後のフォルダ構成例です。
```
text-classification
├── bert-base-uncased
│  ├── README.md
│  ├── config.json
│  ├── flax_model.msgpack
│  ├── pytorch_model.bin
│  ├── rust_model.ot
│  ├── tf_model.h5
│  ├── tokenizer.json
│  ├── tokenizer_config.json
│  └── vocab.txt
├── data
│  ├── mrpc_dev_ids.tsv
│  ├── msr_paraphrase_test.txt
│  └── msr_paraphrase_train.txt
├── glue.py
├── module
│  └── accuracy.py
└── run_glue.py
```


# オフライン環境に合わせてコードを修正
必要なファイル、データの準備が終わったら次はコードを修正します。
取得したコードはインターネット上に接続されていることが前提で書かれているため、オフライン環境に合わせて一部修正します。

```glue.py(L428~L487付近)　オリジナルコード
mrpc_files = dl_manager.download(
                {
                    "dev_ids": _MRPC_DEV_IDS,
                    "train": _MRPC_TRAIN,
                    "test": _MRPC_TEST,
                }
            )
```

```glue.py 修正後
mrpc_files = {"dev_ids":"cache/data/mrpc_dev_ids.tsv",
              "test":"cache/data/msr_paraphrase_test.txt",
              "train":"cache/data/msr_paraphrase_train.txt"}
```

本来は使用するデータの名前などを指定すると自動でダウンロードしてくれるようなコードになっていますが、今回はデータは手動でダウンロードしているのでデータのパスをキーとともにdictで設定します。


# 実行
githubにあるサンプルの実行コマンドをコピペして走らせます。
```
$ export TASK_NAME=mrpc
$ python run_glue.py \
 --model_name_or_pathbert-base-cased \
 --task_name $TASK_NAME \
 --do_train \
 --do_eval \
 --max_seq_length 128 \
 --per_device_train_batch_size 32 \
 --learning_rate 2e-5 \
 --num_train_epochs 3 \
 --output_dir /tmp/$TASK_NAME/
```

こちらで実行できました。
ターミナルに学習状況が流れていれば成功です！



# 終わりに
機械学習、深層学習の記事は多いですがオフライン環境下という点に絞っての記事はあまりなかったので書いてみました！
本記事に対する意見や修正などコメントいただけると嬉しいです！