OmniAICreator/Qiita-1.07M huggingface dataset:
apollo-clientと@apollo/clientは型が違う


# はじめに

GraphQLをフロントから使用するとなると、Apolloを使用することが多いのかなと思います。
https://www.apollographql.com/


現在参画しているプロジェクトでは、NuxtとTypeScriptをメインに開発しており、
データ取得時はGraphQLを使用しております。

GraphQLを扱うため、ライブラリとしてApollo Client（@nuxtjs/apollo）を使用しております。

今回のプロジェクトではApolloClientを使用するためにクラスを作成しており、
型定義のためApolloClientの型を使用しております。

```typescript
import { ApolloClient } from 'apollo-client'
```

が、、、

その際、import元が'apollo-client'か'@apollo/client'かによって、型の中身が若干異なることに気づきました。
そのことについて今回まとめてみようと思います。

```typescript
// この二つは中身が異なる
import { ApolloClient } from 'apollo-client'
import { ApolloClient } from '@apollo/client'
```


# ことの経緯

NuxtでApolloを使用するにあたり、nuxtコミュニティのモジュール（@nuxtjs/apollo）を使用していました。
https://github.com/nuxt-community/apollo-module

ApolloClientを使用するためのクラスでは、
プロジェクトの関係でclientConfigs内に定義したエンドポイントを使い分けるために、
clientConfig内のどちらかのエンドポイントを使用するか引数で渡す設計となっていました。

```typescript
new HogehogeProvider(this.$apolloProvider.clients.hoge)
```

$apolloProvider.clientsに合わせてこの引数には、ApolloClient型を指定しております。
![スクリーンショット 2022-02-11 17.12.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/697823/121f4625-d975-ea82-6a95-fc888431132f.png)

しかし、なぜか起こる型エラー

```
型 'ApolloClient<any>' には 型 'ApolloClient<any>' からの次のプロパティがありません: store, writeData, initQueryManager
```

ApolloClient型でちゃんと渡しているのになぜなん、、、というのがきっかけ。

# 結論

ApolloClientを'apollo-client'からimportするか、'@apollo/client'からimportするかによって型が若干異なるためでした。

https://stackoverflow.com/questions/63005568/property-setlink-is-missing-in-type-apolloclientnormalizedcacheobject-but

実は、この対応の前にApolloClientのimport元を@apollo/clientからに変えておりました。

理由としては、ApolloClient 3.0では@apollo/clientを使用されるようになったと記載があったためです。
https://www.apollographql.com/docs/react/migrating/apollo-client-3-migration/#apollo-client

開発初期のプロジェクトのため、このタイミングで@apollo/clientにしてみようと思い変えておりました。

が、、、

@nuxtjs/apolloのgithubを見にいくと、clientsの型はApolloProvider型に含まれており、
ApolloProvider型はvue-apolloからimportされています。
https://github.com/nuxt-community/apollo-module/blob/83e46428540ca57dd84c99453a5e454dbc40946b/types/nuxt.d.ts#L6

2022/02月現在の@nuxtjs/apollo(4.0.1-rc.5)では、
vue-apolloのバージョンが3.0.5であり、このバージョンではapollo-clientからimportされているようです。

型の名前は同じものの、import元が異なりさらに型の中身も若干異なるため型エラーが起きておりました。

# さいごに

公式ドキュメントを参考にすると良い、というのはよく聞いておりましたが、githubも同時に良いのかなあと思いました。
最初はとても、読めるかなあ、、わかるかなあ、、という気持ちも強かったですが、型を見るだけでも得られるものがあったので今後も調べる時には参考にしようと思っています。

これは個人的な意見ですが、調べるときは以下のように切り分けています。

---
【新しく使う技術で、まだ何も知らないとき】
**→ブログ記事をメインに参考にする。**
理由：深く知るよりは、ざっくり概要を理解して調べやすくすることがこの段階では重要と思うため

【ある程度慣れてきて、エラー解決や自分がやりたいことを実現したいとき】
**公式ドキュメント系をメインに参考にする。**
理由：より深く知るために、より正確な情報がこの段階では重要と思うため

---

公式ドキュメントなどは英語の記事も多いので、⌘ + c + cで簡単に翻訳できるDeepLを使いつつ、
一旦深呼吸して「よっしゃやったる。」と内心思ってから始めることがマイルーティンです。

# 参考

[@nuxtjs/apollo github](https://github.com/nuxt-community/apollo-module)
[stackoverflow(apollo-clientと@apollo/clientの違いを知るきっかけとなった記事)](https://stackoverflow.com/questions/63005568/property-setlink-is-missing-in-type-apolloclientnormalizedcacheobject-but)
[ApolloClient 3.0](https://www.apollographql.com/docs/react/migrating/apollo-client-3-migration/#apollo-client)
[DeepL](https://www.deepl.com/ja/app/)
筋トレ記録を散布図で可視化する(色分け散布図)

#はじめに

筋トレ界の皆様はトレーニングノートを取っていると思いますが、、、、

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">トレーニングノートはマジで取った方がいい！<br>俺が本当に仲良い人とか大切な人にはトレーニング教えたりアドバイスしたりするんだけどその時必ずノートとりな！っていうくらいほんとに大切🙋‍♂️<br>絶対レベルアップできるから！<br>あとは根性と気合い！<br>取ってみ！肥大するぞ！！<br><br>筋肉教祖。</p>&mdash; 横川尚隆 (@YokokawaNaotaka) <a href="https://twitter.com/YokokawaNaotaka/status/1491019790705901569?ref_src=twsrc%5Etfw">February 8, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


その日のトレーニングをスプシに転記していらっしゃいますでしょうか！？(してますよね？しないはずないですよね？)

というわけで、スプシにデータが溜まってきたときに、どういう風にしたら成長を可視化できるか調べてみました。
方法は①散布図、②バブルチャートの2つありますが、どちらにもメリット・デメリットがあるので要検討です。

##目標制作物
x軸y軸に重量と回数、色が濃いほど最新のデータになるようにしたい
<img width="600" alt="不明.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526447/e0484e40-6266-f635-2cf2-0203200fe9ac.png">


￼

##準備:データ加工
週に1回同じ部位を筋トレすると、1年で50個くらいのデータになります。
多くの人の重量と回数は整数データなので、50回分の筋トレ記録も、半分以下の数のユニークデータになってしまうことが多いです。停滞しているみたいなことがわかりやすいように(重なって消えちゃうデータがもったいないし見栄えが悪いので)データを加工して微妙にずらしましょう。

補正比率:時系列データが散布図では重なってしまうため、
過去の記録を割り引くことにした。
割引率=補正比率*(今日-トレーニング日)/(今日-最古のトレーニング日)
データ*(1-割引率)
でデータを補正しましょう。補正比率は3~5%で十分です。
<img width="300" alt="Pasted Graphic 42.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526447/9dd24e7b-6aaf-ebd0-cad3-66860f34a20d.jpeg">


こんな感じです。元データと見比べるとほとんど差はないですが、散布図がきれいになります。
￼

##方法① 散布図

参考文献
[色分けされた散布図をGoogleスプレッドシートでサラッと描きたい](https://qiita.com/PpJZ28dZke7RKK/items/7d77f147483c5ca8d923)
￼
1つ目は上記リンクの散布図を使う方法です。
たとえば時系列トレーニングデータを時間で分類し、4列でならべればグラデーションができるので上記グラフが作成でき、成長が可視化できます。
<img width="600" alt="Pasted Graphic 38.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526447/8780eafa-6cf6-ecad-cc6b-3de7b3d4503d.jpeg">


散布図にするとこんな感じ

<img width="600" alt="不明.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526447/5d2b4c10-a33e-9210-c5d0-b9efa7448746.png">


##方法② バブルチャート
2つ目はバブルチャートを使う方法です。

￼
元データの1行目の補正重量を最小値の半分くらいで書き加えておきます。またバブルサイズをサイズ列で定義し、1行目だけ大きくしておきます。
<img width="300" alt="Pasted Graphic 39.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526447/81261ac0-3fef-2742-7edf-ceec6a71e967.jpeg">

バブルチャートにするとこんな感じ
<img width="600" alt="18.00 20.00.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526447/e3f22edf-772a-48fe-17b5-e80d89cb70d9.jpeg">
￼
左下に大きな白い丸、0の凡例ができますがそれ以外は完璧です。横軸の最小値を設定すれば散布図と同様のグラフになります。
<img width="600" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526447/5f650a41-33b9-de74-b234-b9a491593d5b.png">

###散布図のメリット
・通常の散布図なので自由度が高い(丸を星とか✗とかにもできる。サイズもいじりやすい)
###散布図のデメリット
・特に無いけど、分類の数だけ列が増える。3年分のデータを30個のグラデーションで...とかやっちゃうと列の数が膨大、ミスも増えそう。

###バブルチャートのメリット
・生データ直書きですぐグラフにできる。グラデーションの数が増えても対応が容易
・バブルはバブルの円周に異なる色の枠線がつけられるので散布図より見やすいケースがある。
<img width="600" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526447/56c1834a-aa8e-76a2-1eeb-22e82e775846.png">
枠線をつけるとこんな感じ。

###バブルチャートのデメリット
・1行目のデータ書き加えがめんどい
・バブルチャートベースなので自由度が低い(丸のサイズの下限アリ)
・0という凡例ができてしまう(1行目のデータ)

#終わりに

スプシ大好きマンなのできれいに可視化できてハッピーです。主要メニューを継続して取り組むモチベーションになります。
【Ruby】末尾の文字列を3回出力するプログラム　extra_endメソッド

※初心者向け
※アウトプット練習の為

開発環境
rails 6.0.4.4
ruby 2.6.5

**概要**
対象の文字列の末尾に位置する文字を取得し、それらを任意の回数繰り返して出力するプログラムを実装します。

##問題内容
以下の要件を満たすextra_endメソッドを実装しましょう。

・対象の文字列から末尾にある2文字を取得すること
・取得した2文字を3回繰り返して出力すること

**雛形**

```ruby
def extra_end(str)
  # 処理を記述
end

# 呼び出し例
extra_end('Hello')
```

**出力例：**
extra_end('Hello') → 'lololo'


**ヒント**
sliceメソッドを使いましょう。

**sliceメソッド**
sliceメソッドとは、配列や文字列から指定した要素を取り出すことができるメソッドです。

```ruby
# 配列を作成します
array = [0,1,2,3,4,5,6]

# 配列から引数で指定した要素を取得します
ele1 = array.slice(1)
puts ele1
#=> 1

# 配列番号-4から4つ分の要素をsliceします
ele2 = array.slice(-4,4)
puts ele2
#=> 3, 4, 5, 6

# 配列はもとのままです
puts array 
#=> [0,1,2,3,4,5,6]
```

##解答
```ruby
def extra_end(str)
  char_num = str.length
  right2 = str.slice(char_num - 2, 2)
  puts right2 * 3
end

# 呼び出し例
extra_end('Hello') 
```
**解説**
extra_end('Hello')でメソッドを呼び出した場合の解説をします。

まず、1行目のextra_endメソッドの仮引数strには対象の文字列’Hello’が格納されます。
そして、2行目ではstrに対してsliceメソッドを使用し、指定した要素を取り出しています。

sliceメソッドの1つ目の引数では、文字列（Hello）の後ろから2番目の要素を基準点としています。
そして、2つ目の引数により、基準点から2つ分の要素を取り出しています。
今回の場合、「H,e,l,l,o」の後ろから2番目の要素は「l」です。そして、基準点「l」から2つ分の要素である「lo」が取り出されるので、end_str = loとなります。

最後に、2 * 3と記述することによって、「lololo」と出力されます。
PHP7.4をインストールしたAmazonLinux2にLaravel8をインストールする

## 概要
以下のページで構築した環境にLaravel8をインストールする。
[AmazonLinux2にamazon-linux-extrasでPHP7.4をインストールしてみた](https://qiita.com/wwwqedhtakanori/items/a0d665f0123ef0f13046)

## Composerをインストール
まずはComposerをインストールする。

composerをダウンロード

```
$ curl -sS https://getcomposer.org/installer | php
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1790108/2bc38067-53d6-e0ee-c06f-f09d11f14741.png)

ダウンロードしたcomposerモジュールをパスの通っているところに配置

```
sudo mv composer.phar /usr/local/bin/composer
```

composerのインストールを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1790108/3436e77d-7cc9-f151-a91b-c7815aa7e6f7.png)

## プロジェクトの作成とアプリ起動
以下のコマンドを実行し、myappフォルダにlaravelプロジェクトを作成
```
$ composer create-project laravel/laravel ./myapp --prefer-dist
```

以下のように表示されればプロジェクト作成成功。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1790108/c1f9435f-f2eb-fe72-d365-4b54e9def871.png)

プロジェクトディレクトリに移動後、アプリを起動させる。

```
$ cd myapp
$ php artisan serve --port=8080
```

以下のように表示されればOK


Cloud9の「Preview」→「Preview Running Application」を実行する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1790108/47fc676f-da10-2655-37b9-2ea0db0cabea.png)

以下の画面が表示されればOK

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1790108/c8b832ef-a2bb-0743-2886-b325f669bfda.png)

## 最後に
以上でLaravelの開発環境が整った。
このアプリをいろいろと触っていきたい。
macOS Montereyにアップデートしたら、ユーザー辞書が勝手に消される(初期化される)問題について

Big Sur以前では、こういうことは無かったように思いますが、Montereyにして以来、OSアップデートを実施して再起動すると、ユーザー辞書に登録していた単語が消されて、初期状態の「きららざか：雲母坂」だけにされてしまいます。
ググってみると、かなり前からこういう不具合があるという話がネットのあちこちに上がっているけど、今日アップデートしたMonterey12.2.1でも直されていない。

アタマに来たので、自力であちこち設定ファイルを探索して、ついに回避方法を突き止めたので、共有しますねw

```
/Users/＜あなたのユーザー名＞/Library/KeyboardServices/TextReplacements.db-wal
```
このファイルを、`⌘I`（情報を見る)で情報表示させて「ロック」のチェックボックスをONにしてください。
![スクリーンショット 2022-02-11 16.59.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1263633/d59e50f2-6d9d-c5df-0a53-57244f56be90.png)
これで、ユーザー辞書が勝手に消されることはなくなります。
でも、`システム環境設定→キーボード→ユーザ辞書` の画面に新しい単語を登録したり、削除したりができなくなります。辞書を変更追加したい時には、上記の「ロック」を外してください。


ちなみに、ユーザーのホームフォルダにあるLibrary（ライブラリ)フォルダは、Finderでは通常見えないようになってると思うので、ターミナルを使って、

```
 open ~/Library/
```
のようにコマンドを打つと、Finderのウィンドウで開けるハズです。


ちなみに２、いつもMacをシャットダウンせず、使用しない時はずっとスリープさせて、ソフトウェアアップデートのときだけ再起動してたので、そのタイミングでだけ「ユーザー辞書が初期化」されたと思ってましたが、ログアウトしてログインし直すだけでも、ユーザー辞書が消されてました。
どうやら、ログインする瞬間に、上記の`TextReplacements.db-wal`ファイルに何か書き込みに行って、ぶっ壊しているようです。ファイルサイズは、なぜかログインするたび増えているw
iCloudで、iPhoneやiPadとユーザー辞書を同期する機能とかが、どっかおかしいのかな？
自分はiPhoneもiPadも使ってないので、iCloudも使ってないしサインインしてないのですが...
githubに25M以上のファイルをアップロードする

![SS 192.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565043/a41cd967-f549-8677-1efa-2e99bf69518d.png) 毎回忘れるマン

#シチュエーション

githubを使うときにサイトからアップロードをする派（複数の環境からリポジトリを使っているのでその方がラク）の自分が、ごくまれに25M以上の大きいファイルをアップロードをしなくてはならぬ必要にせまられ、全然更新してないローカルリポジトリとターミナルを使わざるを得ないことになったときの手順。

#手順

### 古いローカルリポジトリはクリアしちゃう

使い方を忘れるほど使っていなかったリポジトリなので一旦消します。
ターミナルでローカルリポジトリを作ったgitディレクトリにcdコマンドで入り、
gitディレクトリの中で以下を実行してクリア後、gitを再設定します。

```
$ cd ＜該当のgitディレクトリ＞
$ rm -rf .git 
$ git init
```

### git clone する
改めて最新のリポジトリをローカルにコピーします。

```
$ git clone ＜ファイルをアップロードしたいリポジトリ＞
```

### アップロードしたいファイルをセットする

ファイルをローカルリポジトリの該当のディレクトリにおきます。

### ファイルを追加してコミットする

```
$ git add . 
$ git commit -m "first commitなど"  
```

さっき置いたファイルがコミットされます。

### トークンをつくる

[GitHubがパスワード認証を廃止するらしいので]
(https://qiita.com/shiro01/items/e886aa1e4beb404f9038)
を参考に、トークンを取得します。

### ファイルを追加してコミットする

```
$ git push
```

リモートリポジトリのUsernameとPasswordを尋ねられます。
Passwordには先ほど取得したトークンを入力します。

# これでうまくいくはず

うまくいかなかったら次の機会に修正手順を更新。
rails d modelは要注意

開発中のアプリケーションでいらないモデルを削除しようとなったときに、rails d modelをしてしまい（もちろんpushはしてない）「そのやり方は100%ダメだ」と言われることがあったので自戒の念を込めて記事を作成します。

## rails newで実験用アプリを用意する

```markdown
rails new migration_experiment
cd migration_experiment
rails db:create
```

## User modelを作成する

```markdown
rails g model User name:string
rails db:migrate
```

## Task modelを作成する

```markdown
rails g model Task name:text description:text
rails db:migrate
```

## User modelにemailカラムを追加する

アプリを作成中User modelに新しくemailカラムを追加することになったと仮定してemailカラムを追加するmigrationファイルを作成します。

```markdown
rails g migration add_email_to_users
```

```20220211072145_add_email_to_users.rb
class AddEmailToUsers < ActiveRecord::Migration[6.1]
  def change
    add_column :users, :email, :string
  end
end
```

```markdown
rails db:migrate
```

この時点でのmigrationファイルの状態が以下です。

```markdown
20220211071814_create_users.rb
20220211071830_create_tasks.rb
20220211072145_add_email_to_users.rb
```

## rails d model を実行する

さて、ここからが問題のrails d modelの実行です。

```
rails d model User
```

こちらを実行すると、migrationファイルの状態がこのようになります。

```
20220211071830_create_tasks.rb
20220211072145_add_email_to_users.rb
```

raisl d model前には存在していたUser modelを作成した際のmigrationファイルがなくなっています。この状態でrails db:migrate:resetを実行するとどうなるでしょうか？

```md
== 20220211071830 CreateTasks: migrating ======================================
-- create_table(:tasks)
   -> 0.0022s
== 20220211071830 CreateTasks: migrated (0.0023s) =============================

== 20220211072145 AddEmailToUsers: migrating ==================================
-- add_column(:users, :email, :string)
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:

SQLite3::SQLException: no such table: users
```

User modelを削除してしまったので、emailカラムを追加するmigrationファイルが適用できずエラーが出てしまっています。

なぜこのようなことが起こってしまうかというと、「rails d model」では、

```md
remove  db/migrate/20220211073521_create_users.rb
remove  app/models/user.rb

<!--その他の削除されるファイルは割愛-->
```

の様にmodel自体とmodelを作成したmigrationファイルのみを削除し、そのモデルに新しいカラムを追加したファイルは削除されません。なのでmigrationファイルの整合性が取れなくなるためエラーが発生してしまうことになります。

今は実験のため3つのmigration fileを一人でいじっているだけなので他のmaigrationファイルを全て削除し、新しくモデルを作成（新しいmigrationファイルの作成）後、migrate:resetをかければ元通りの状態までは簡単に持っていけます。しかしチーム開発や、model数が多くなってきた場合そういった作業をするわけにはいきません。

では、不要になったmodelを削除する場合はどうすればいいのでしょうか？

## モデルを削除するmigrationファイルを作成する

安全にモデルを削除するにはそのモデルを削除することを宣言するmigrationファイルを作成します。

```ruby
rails g migration drop_table_users
```

ファイルを編集します。

```20220211080417_drop_table_users.rb
class DropTableUsers < ActiveRecord::Migration[6.1]
  def change
    drop_table :users do |t|
      t.string :name
      t.string :email
      t.timestamps null: false
    end
  end
end
```

```
rails db:migrate
```

このような作業を経ることによってmigrationファイルの整合性が保たれ、後に新しいmodel作成をしたmigrationファイルが積み上がってきたり、rails db:migrate:resetを実行したときにもエラーを起こさず進めていくことができます。

## おまけ

今回モデルを綺麗に削除してmigrationファイルの整合性を保つような作業をしましたが、一度modelを削除したり、rails db:migrate:resetをかけると当然の様にDBにあるデータは戻ってきません。一度dumpしたファイルの内容を全て消してしまいとてもめんどくさいことになったことがあるので皆さんご注意を。
Flashforge Dreamer 静音化（TMC2209）

中古の3Dプリンタを手に入れてしまったので、しばらくレーザーカッターは放置してました（笑）
（FluidNCのバグフィックスでバージョンが上がり続けてたのでしばらく待ちだった合間に）

枯れた機種ですが、まだまだ使えるFlashforge Dreamerを中古で入手。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664748/7ec6b86b-e1af-d196-794d-92f75881233f.png)

古い機種なのでステッピングモーターにtrinamicを使っていないのでピロリロってうるさい。
夜中にプリントすると、同居人からうるさいとクレームがついてしまいました。

では、最新のAdventure4や最近のreprapのトレンドに遅れないように
ステッピングモータードライバをTMC2209に変えてみましょう　ということでやってみました。

ネットを調べると、どうもBIGTREETECHのTMC2209モジュールを反転してモーターを逆回転にすればすぐ使えるらしい。

アリエクで買ったTMC2209
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664748/b2ff5ba2-aca6-9310-de73-b3dd4e0febee.png)

DreamerについているドライバA4988
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664748/15807a9a-2e80-99a1-4e7b-b5db4b3d3385.png)

書いてあるとおり反転しちゃってるので、ピンヘッダーを撤去して裏返す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664748/b15ca249-373e-5756-35be-9abf06285c8b.png)

反対側にしてピンヘッダーをハンダ付け
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664748/4563efea-ee4a-ca0a-5d79-2512e4ba8e7e.png)

完成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664748/8789d019-3ebf-5feb-f034-78c575801928.png)

本体をひっくり返し底カバーを外して
Dreamerのドライバ基板のステッピングモーター配線を外し、A相とB相を入れ替える
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664748/090c59f0-6ba8-45e6-191a-fe6fbb5e5ec7.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664748/bfa9e47c-faf1-a27f-ac28-0d2a71a54f0a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664748/f62a8170-c45e-9e2e-fa8d-dea8e02da8f8.png)

X軸、Y軸、Z軸をすべて同じく入れ替えて、TMC2209に載せ替え
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664748/20cb5c28-b4c8-ab97-ebb9-3daee57b655d.png)

TMC2209基板のGNDと電流チェックポイントをテスターで測定して、電流値を合わせる。
（0.9Vくらい？調整はいちいち外して裏のトリマーを回すので面倒ですが）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664748/85d5058f-4d82-c419-ae85-238287e48315.png)

これで完成。
モーターは大変静かになりました。
ファンがうるさい。
「ドメイン駆動設計入門」を読んで_その6

## この記事は

「ドメイン駆動設計入門」を読んでまとめている第6弾

前回記事は[こちら](https://qiita.com/t13801206/items/80c88f13747b8c221777)

今回は[仕様](#仕様)についてまとめる

## 仕様

> 仕様はオブジェクトの評価を行うオブジェクトです(P293)

簡単な評価はメソッドに記述される
たとえば `user.Age < 20` で成人であるか評価をする、など。

**評価はドメインにとどめておくべきルールである**にもかかわらず
複雑な評価の手順が**アプリケーションサービスに記述される**ことがある
（ドメインオブジェクトを束ねているアプリケーションサービスはできることが多いので、放っておくと自然とそこにルールが書かれがち）
ドメインのルールがアプリケーションに漏れ出る、これは避けねばならない

そんなときには**仕様**オブジェクトをつかう
仕様オブジェクトは、自分ではないオブジェクトを評価する

### エンティティはリポジトリを操作したくない

評価：`Circle`はプレミアム`User`数によってサークル人数上限を決めたい

- エンティティの`Circle`は`UserRepository`を持つべきではない。ドメインの表現に徹するべきである
- `Circle`はリポジトリの操作を可能な限り避ける必要がある

- かといって、`UserRepository`を[コンストラクタで受け取る](https://github.com/nrslib/itddd/blob/master/Layered_UsingInternal/SnsApplication/Application/Circles/CircleApplicationService.cs)`CircleApplicationService`が評価をすべきではない。ルールはドメインにとどめておくべきである

### 仕様が代わりにリポジトリを操作する

仕様の実例は[こちら](https://github.com/nrslib/itddd/blob/master/Layered_UsingInternal/SnsApplication/Domain/Models/Circles/CircleFullSpecification.cs)

仕様はオブジェクトの評価のみを行う
実例ではサークルが満員であるかどうかの評価だけを行っている

#### 評価まみれになったオブジェクト

評価が増えると依存が増えて、変更に伴う痛みも増加する
積極的に仕様として切り出すことで事態を避ける

```plantuml
class Circle
{
    + IsFull()
    + IsPopular()
    + IsAnniversary(Datetime)
    + IsSustainable()
    + Join(User)
}
note right: サークル自体の評価メソッドにまみれている\n評価にあたって他オブジェクトへの依存も増える
```

### リポジトリの使用を避ける

実は仕様もれっきとしたドメインオブジェクトである（ルールが書かれている）
ドメインオブジェクトは入出力（リポジトリの操作）はしたくないというのが本音

**ファーストクラスコレクション**をつかってリポジトリの使用を避けることができる

```plantuml
class CircleMemberCollection
{
    - List<User> members
    + CountMembers()
    + CountPremiumMembers()
}
note right: クラスがメンバー数を保持しているので、リポジトリへの問い合わせが不要
```

だれがリポジトリを操作するか？→アプリケーションサービスが操作する
アプリケーションサービスで**ファーストクラスコレクションへデータの詰め替え作業が発生**する

ドメインオブジェクトから入出力（リポジトリの操作）を排除するために
ファーストクラスコレクションは有力な解決方法となり得る

### リポジトリに仕様をわたす

「おすすめサークル」の評価を実装であるリポジトリに書くべきではない
ドメインのルールはインフラに漏れないよう常に注意する

```plantuml
package アプケーション
{
    class AppService
    {

    }
}
package ドメイン
{
    interface ISpecification
    {
        + bool IsSatisfiedBy<T value>
    }
    class CircleRecommendSpec
    note bottom: おすすめサークル評価 
    class CircleFullSpec
    note bottom: サークル満員評価
    ISpecification <|.. CircleRecommendSpec 
    ISpecification <|.. CircleFullSpec 
    
    interface ICircleRepository
    {
        + List<Circle> Find(ISpecification)
    }
}
package インフラ
{
    class CircleRepository
    {

    }
    class CircleRepositoryInMemory
    {

    }
}
AppService --> ICircleRepository : リポジトリからおすすめサークルを取得する
ISpecification <. ICircleRepository : おすすめサークルの定義は\n仕様に書かれている
ICircleRepository <|.. CircleRepository 
ICircleRepository <|.. CircleRepositoryInMemory
```

#### リポジトリに仕様をわたすデメリット

リポジトリに仕様をわたして、仕様を満たすレコードを取得するためには、**全件検索**が必要になる
件数によってはシステム利用者が求める性能を満たせなくなる可能性がある

```cs
var result = repository.Find(/*仕様*/).Take(10).ToList();
```

##### C#のLinq

C#のLinqをつかえば、`.ToList()`でコレクションを確定するまでは遅延実行ができるので、パフォーマンスとリポジトリの使用を両立できる

```cs
var allRecords = repository.FindAll(); // この時点ではデータを取得してはない
var result = allRecords.Skip().Take().ToList(); // skipされてtakeされたあと初めてデータが確定する
```
[React] useEffectとaddEventListenerの代わりにuseEventを使ってみた


Webの開発をしている時に`useEvent`というHookがあることを知ったので、
まとめるために記事にしました。
誰かのお役に立てれば、幸いです。

参考サイトのnpmには、

This hook cleans up your listeners automatically when it unmounts.

アンマウント時に自動でリスナーをクリーンナップをしてくれるようで、
少しはスッキリと書けるようになるみたいです。

## 書き比べてみる

画面をスクロールすると表示が変わるフックを書き換えてみたいと思います。

```javascript
  const [isVisible, setIsVisible] = useState(true);
  const toggleVisibility = () => {
    window.scrollY > 300 ? setIsVisible(false) : setIsVisible(true);
  };

  useEffect(() => {
    window.addEventListener("scroll", toggleVisibility);
    return () => window.removeEventListener("scroll", toggleVisibility);
  }, []);
```

これを`useEvent` で書き換えてみます。

```javascript
  import useEvent from "@react-hook/event";

  const [isVisible, setIsVisible] = useState(true);
  const toggleVisibility = () => {
    globalThis.scrollY > 300 ? setIsVisible(false) : setIsVisible(true);
  };

  useEvent(globalThis, "scroll", toggleVisibility);
```

スッキリと書くことができました。

書き換えた時に、target となるところに、window だとエラーが出ました。
解決策は参考サイトにもありますが、クライアント側でwindow にあたる`globalThis`を使うことで
エラーを回避しています。


## 参考にしたサイト

https://www.npmjs.com/package/@react-hook/event

https://stackoverflow.com/questions/66412291/nextjs-how-to-use-window-in-custom-hook
AWSを触らずに「AWS認定ソリューションアーキテクト アソシエイト」に合格した話

# はじめに
この記事では、**AWSを触ったことが無い**方でも資格取得できる方法を紹介いたします。
ほとんどAWSやネットワークの知識がない私でも取得できたので、気楽に取り組んでみてください！
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2286023/60d8fe71-23c1-da05-4541-1ad812a76466.png" width="80%">

(受験申込に関しては、[こちら](https://hackers-high.com/aws/how-to-take-aws-certification-exam/)を参考にしてみてください。)

## AWS認定ソリューションアーキテクト アソシエイトについて

https://aws.amazon.com/jp/certification/certified-solutions-architect-associate/

### 概要
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2286023/68b05dfa-357f-3cd0-e261-69aea8420772.png" width="80%">
「AWS認定ソリューションアーキテクト アソシエイト」はAWS認定資格の中でも
**1年間**以上の実務経験が求められる試験です。(以下、公式より引用）
>AWS Certified Solutions Architect – Associate は、AWS における、可用性があり、コスト効率が高く、高耐障害性で、スケーラブルな分散システムの設計に関する 1 年以上の実務経験を持つ方を対象としています。この試験を受ける前に、以下のことをお勧めします。

### 必要な知識
AWSのさまざまなサービスの知識に加えて、AWSが掲げているベストプラクティスについての知識が求められます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2286023/7c038610-a34f-c90f-0eba-da7fdf15450a.png" width="70%">

https://aws.amazon.com/jp/builders-flash/202101/awsgeek-well-architected/?awsf.filter-name=*all

### 試験要項

- 試験時間
    - 130分
- 受験料
    - 16500円
- 合格ライン
    - 72%(65問なので47問で合格)



## 勉強方法
### 使用教材(4000円程)
1. [AWS認定資格試験テキスト AWS認定ソリューションアーキテクト - アソシエイト 改訂第2版](https://www.amazon.co.jp/dp/4815607389)
    1. 第2版と第1版でテスト範囲が変わっているため、**第2版**をご準備ください。
    <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2286023/60962af8-e8f2-0349-4dbc-785c0493352d.png" width="50%">
1. [【2022年版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（6回分390問）](https://www.udemy.com/course/aws-knan/)
    1. セールで購入すれば、2000円程です！

### 勉強期間・時間
年末から年明けにかけて勉強して、資格取得いたしました！

- 期間
    - 約2週間
- 時間
    - 計70時間ほど
        - 平日3時間
        - 休日6時間

### 勉強方法
#### テキスト(計30時間)
まずはテキストからがおすすめです！
テキストでは、ソリューションアーキテクトアソシエイトの説明から始まり、
**試験範囲の全体像**を掴みやすい構成となっています。

1章ごとに以下の方法で読み進めていました。

1. 小テストを解く
1. 解説を読む
1. 疑問を持った状態でテキストの説明を読む
1. 小テストを解き直す

復習は、前日にやった小テストを解きなおしてから、
新しい問題に取り組む程度で、先に進むことを優先していました。

#### Udemy模擬試験(40時間)
こちらはテキストの模擬試験に比べて、かなり難しい内容となっていますが、
**本番とほとんど変わらない**難易度となっているため、
80パーセント近くは取れるようになる必要があります。

全部で6個模擬試験があり、それぞれ以下の方法で進めていました。

1. 模擬試験を解く(1時間ほど)
    1. 私の場合、初見では全ての試験で55~60パーセントしか取れませんでした。
1. 間違った箇所・不安な箇所のみ解説を読む。(2時間ほど)
1. 設問の番号を記録し、翌日に復習(1時間ほど)

解きなおしている時間を取れなかったので、
チェックした問題の解説を読んだり、テキストを見返し理解を深めていました。
テキストで、全体像をつかんでおく事で、解説の理解難度が下がっている実感がありました。

## 最後に
「AWS認定ソリューションアーキテクト アソシエイト」の試験勉強では、
ハンズオンを行いませんでしたが、どのサービスで何ができるか知ることができた為、
現在は、個人でAWSを使用することができています！

また、本番では慣れないテストセンターで、長い問題文を読むことになりますが、必要な知識は
テキストと模擬試験で足りているので、安心して試験に臨んでください！
皆様の合格を祈っております。
VSCodeにFlaskを導入する方法～忘備録～

Flask：PythonのWebアプリケーションフレームワークの１つ。他にもDjnagoなどがある。
Webフレームワーク：ウェブサイトやウェブアプリケーションを作るための機能を提供。容易にWebアプリケーションを作ることができる。

+ 手順１
ターミナルに pip install flask と入力。

※pip の version について
最初は pip の version が古いのでアップデートせよと表示された。
表示されている結果に従ってアップデートすればよい。

+ 手順２
ターミナルに pip freeze と入力。

これで何がどういう version でインストールされているか確認できる。
自分の場合、次のように表示された。

```
astroid==2.9.3
click==8.0.3
colorama==0.4.4
Flask==2.0.2
isort==5.10.1
itsdangerous==2.0.1
Jinja2==3.0.3
lazy-object-proxy==1.7.1
MarkupSafe==2.0.1
mccabe==0.6.1
platformdirs==2.5.0
pylint==2.12.2
toml==0.10.2
Werkzeug==2.0.3
wrapt==1.13.3
```

このclick==8.0.3、Flask==2.0.2、Jinja2==3.0.3、Werkzeug==2.0.3などが入っていることが確認できれば良い。

+ 手順３
hogehoge.py ファイルを作り保存する。

ここでは以下のモノを試した。

```python:hogehoge.py
from flask import Flask
app = Flask(__name__)

@app.route("/") #当然ここでの app は2行目の app を受けて。2行目が hoge = Flask... であれば @hoge.route(...) とする。
def hello_world():
    return"<p>Hello, World!</p>"
```

コード説明
1行目：flask という**パッケージ**から Flask という**クラス**を improt
2行目：Flask クラスの**インスタンス** app を作成
3行目：ルーティング、つまり URL と処理を対応づける。URL と funciton を紐付け。route() を用いる。
ここでは、http://xxx 以降のURLパスを "/" と指定
4行目：その URL がリクエストされたときに、それを処理する関数 hello_world を定義
5行目：関数の中身

https://www.bold.ne.jp/engineer-club/instance#:~:text=%E3%81%BE%E3%81%A8%E3%82%81-,%EF%BC%91%EF%BC%8E%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E3%81%A8%E3%81%AF%E3%81%A9%E3%81%93%E3%81%8B%E3%81%A7%E5%AE%9F%E4%BD%93,%E3%81%A6%E3%81%84%E3%82%8B%E3%83%A2%E3%83%8E%E3%81%AE%E3%81%93%E3%81%A8&text=%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E3%81%AF%E3%80%81%E8%8B%B1%E8%AA%9E%E3%81%A0%E3%81%A8,%E6%9C%80%E3%82%82%E8%BF%91%E3%81%84%E3%81%A8%E6%84%9F%E3%81%98%E3%81%BE%E3%81%99%E3%80%82

+ 手順４
ターミナルに $env:FLASK_APP="hogehoge.py" と入力後 flask run と入力。

**※使用環境 Windows + PowerShell**
その他の環境に関してはflask公式サイト https://flask-docs-ja.readthedocs.io/en/latest/quickstart/ を参照。

出力結果

```
 * Serving Flask app 'hogehoge.py' (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
```
この http: ... をクリックして立ち上がったブラウザに Hello, World! と表示されていればOK！

次は [VSCode での Flask のデバッグについて](https://qiita.com/Euphysics/items/30de74648e4a43ffbc67)。
pythonで作成したファイルを実行ファイルに変更する

## 仮想環境を構築
```
python -m venv exe
exe\Scripts\activate
```
## ライブラリインストール
```
pip install pyinstaller
```
## サンプルスクリプトを用意
以下内容のファイルsample.pyを用意しました。
```
print('sample')
```
## 実行ファイルを作成
```
pyinstaller sample.py
```
上記コマンドで作成したときは以下ファイルが作成されます。
- pycache
- build
- dist
- sample.spec

### 一つのファイルでまとめたいとき
dist内の複数ファイルを纏めて一つのファイルとして扱うときは、
--onefileを付与します。
```
pyinstaller sample.py --onefile
```

### コンソール画面を非表示
コンソール画面を表示しない場合は、--noconsoleを付与します。
```
pyinstaller sample.py --noconsole
```

### ライブラリを指定
何も指定せず実行ファイルを作成すると、インストールされているライブラリ全てが同梱されているため、実行ファイルが肥大化する可能性があります。実行ファイルを圧縮するために、利用するライブラリのみ--hidden-importで指定して実行ファイルに返還しましょう。
```
pyinstaller sample.py --hidden-import=pandas
```

## 検証動画
<iframe width="560" height="315" src="https://www.youtube.com/embed/4IbA14BPQTI" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
svelteに触ってみる①

# 初めに
最近、要件定義や設計ばかりやっている

年齢的に求められるのはそこだしね
それは理解しているけどね・・・

でもやっぱり作るのが好きじゃん
っていうことで日曜大工的に新しい言語に触ってみる

今React使っているけど、ちょっと似ているsvelteってやつを見つけたのでやってみるよ

---
# 自分の経験値
* JQueryくらいまではWEBアプリ作れる
    * WEB入門編はこの辺で習得
* PHPのZendFrameworkは使ったことある
    * これでMVCモデルは理解出来た

---
# 他の言語との違い
ちょっと調べたイメージ

* React
    * 今業務で使っている
    * クラスを作ってその中でHTMLを生成するイメージ
    * がっちりオブジェクト指向って感じするよね
* Vue
    * ネットで調べたレベル
    * HTMLファイルとScriptファイルが分かれてて、この2つがBindされてHTMLが成形されるイメージ
* svelt
    * HTMLとScriptを2つのファイルに記述する。
    * コンパイラでここからHTMLを生成する

---
# 所感
* HPに載っているのでサクッとインストール
    * https://svelte.jp/
* あとは現在お試し中
【Laravel】【Livewire】Webアプリ制作メモ。

こんにちは。ariponです。
プログラムスクールでPHPを勉強しながら、
自分による自分のための盛大なWebアプリを作成いています。

ド初心者のため すぐGoogle先生にお世話になっているのですが
自分はエラー⇒検索を繰り返しすぎて調べたことを片っ端から忘れていく天才だと気づいたため
ここにどんどんメモしていきます。

##【LivewireでCSSを変更したい】
###「AlpineJS」を使用する
<head></head>内に下記のコードを読み込む。

```ruby:cdn
 <script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
```

…が、エラーがでる。なんでじゃ。

```ruby:cdn
<script defer src="https://unpkg.com/alpinejs@3.9.0/dist/cdn.min.js"></script>
```

こちらにしたら、エラー解消。

参考サイト
[https://www.mitsue.co.jp/knowledge/blog/frontend/202002/21_1253.html](https://www.mitsue.co.jp/knowledge/blog/frontend/202002/21_1253.html)
[https://qiita.com/kohashi/items/ae8b1186567ec34b2a75]
(https://qiita.com/kohashi/items/ae8b1186567ec34b2a75)


###ドロワーメニューの設置

試行錯誤中。全然うまくいかない…。
draft-js draftjs-to-htmlを使って、HTMLからフォントカラーを復元したテキストを表示する

# はじめに
convertFromHTMLでは一部のインラインスタイルにしか対応しておらず、フォントカラーが復元されないという問題があります。
[html-to-draftjs](https://www.npmjs.com/package/html-to-draftjs)がフォントカラーなどのInlineStylesの復元に対応しているので軽く使ってみようと思います。

行程は以下の通りです。
1. htmlToDraftを使ってhtmlを変換し、editorStateを作成する
2. color-〇〇の名前でInlineStyleを作成、styleMapに追加する
3. 1と2で作成したeditorStateとstyleMapをEditorにセットする


## 1.htmlToDraftを使ってhtmlを変換し、editorStateを作成する

```js
const html = `<span style="color:rgb(0,128,0)">te</span><span style="color:red">st</span>`;

const htmlToEState = (html:string) =>{

    const blockArray = htmlToDraft(html);
    const contentState = ContentState.createFromBlockArray(blockArray.contentBlocks, blockArray.entityMap);
    const editorState = EditorState.createWithContent(contentState);

    return editorState;
}
```

## 2.color-〇〇の名前でInlineStyleを作成、styleMapに追加する
htmlToDraftでは'color-'とhtmlElementのcolorにある値を結合して、InlineStyleをセットします。colorには'red'で値がはいるので'color-Red'と定義したら色が変わらなくなるので注意してください。rgbでの定義にも対応しています。

```js
const styleMap = {
    'color-red':{ 'color':'red'},
    'color-rgb(0,128,0)':{ 'color':'rgb(0,128,0)'}
}

```
## 3. 1と2で作成したeditorStateとstyleMapをEditorにセットする

```js

const RichTextEditor = () => {
    const [ editorState, setEditorState ] = useState(htmlToEState(html));

    return(
        <Editor customStyleMap={styleMap} editorState={editorState} onChange={setEditorState}/>
    );
}
```
## テキストの表示
下図のように表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2296091/d6f9af44-3b06-cd2a-a2fd-ad475bacc51f.png)


# 最後に
htmltodraftでは背景色、フォントサイズ、フォントファミリーにも対応しているので使ってみてください。
InlineStyle名はそれぞれ、bgcolor-〇〇、fontsize-〇〇(例：smallもしくは12)、fontfamily-(例: MS PGothic)

styleMap例

```js
const styleMap = {
    'fontfamily-MS Mincho':{ 'fontFamily':'MS Mincho'},
    'bgcolor-red':{ 'backgroundColor':'red'},
    'fontsize-32':{'fontSize':'32px'}
}

```
conda base環境上でvenv仮想環境を作るとjupyterのカーネル追加がうまくいかなかい

# 起きたこと
condaのbase環境が起動している状態（下写真）でvenvを利用して仮想環境test_envを作成、起動し、必要なライブラリをインストールした。その後、jupyter でも使えるように、`pip install ipykernel`と`ipython kernel install --user --name=test_env`をして、jupyter上にカーネルを追加した。
その後、jupyter notebookを起動し、カーネルをtest_envに選択し、`import ライブラリ名`を実行すると（ここではtorchinfo）`Module not found: torchinfo`と出た。

![スクリーンショット 2022-02-11 15.57.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1754777/3ab0f905-eeb2-515f-a74f-3d4ba329e48d.png)

# 原因と解消方法

いろいろ検証してみると、torchがbase環境上にあるバージョンのものを指定していたので、おそらく追加したカーネルがbase環境で覆われてしまっているのではないかと考えた。さらに検証した結果、以下のような回避方法があることがわかった。

- 最初の仮想環境作成前に、`conda deactivate base`か何かでbase環境を終了させた上で、コンピュータ上にある別のpythonにあるvenvで仮想環境を作成する
    - こうした場合は、base環境上が起動している状態で起動して、上記の手順を踏んだとしても（また後者の手順を踏んだとしても）、jupyter 上で正しくカーネルが認識された

- 仮想環境作成時に、base環境が起動している状態で作成してしまった場合、仮想環境上で、base環境を終了させた上で`ipython kernel install --user --name=test_env`を実行する。
    - こうした場合は仮にbase環境が起動している状態で作成してしまったとしてもjupyter 上で正しくカーネルが認識された。今回はこちらで解決させた

# 結論
base環境上でvenvするな
Chrome拡張機能の申請手順

# はじめに
Chrome拡張機能の申請手順についてまとめます。

# 手順
## 1.ChromeWebStoreの登録
ChromeWebStoreに登録する際、初回のみ5ドルの登録料がかかります。

[Chrome ウェブストアのデベロッパー登録](https://chrome.google.com/webstore/devconsole/register)

以下の確認、支払いをする。

 - デベロッパー契約とプライバシーポリシーに同意
 - 5ドルの登録料を払う（初回のみ）

登録料の支払いが完了すると、デベロッパーダッシュボードに遷移できます。

## 2.拡張機能のファイルアップロードと必要情報の記入
ダッシュボードの右上にある「新しいアイテム」より、拡張機能のzipファイルをアップロードします。
![スクリーンショット 2022-02-11 14.14.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381376/b9a306bb-b666-0713-176f-7e1e50076c53.png)


アップロードするとストアへの掲載情報を入力するフォームが表示されます。

![chrome.google.com_webstore_devconsole.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381376/3d240e09-c50d-f9c9-c67c-e6e1474cc282.png)

左部分に表示されている項目は以下の通り

 - ステータス：審査の状態が確認できる
 - パッケージ：拡張機能のパッケージ情報が確認できる
 - ストアの掲載情報：ここで掲載情報を入力する
 - プライバシーへの取り組み：用途や権限が必要な理由はここで入力する
 - 決済と配布地域：決済方法や公開設定、販売地域を設定できる


ストアへの掲載情報の入力項目は以下の通り

 - 商品の詳細（アイテムの説明、カテゴリ、言語）
 - 画像アセット（ショップアイコン、プロモーション動画、スクリーンショット等）
 - 追加フィールド（公式URL、ホームページURL、サポートURL、GoogleアナリティクスID等）

画像アセットに関しては、画像サイズが指定されているため調整する必要があります。
Macであれば、画像プレビューよりサイズの変更ができます。

![スクリーンショット 2022-02-11 14.47.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381376/24e3c52f-7568-9e64-b3ab-f684f67d2add.png)


不足項目がある場合は、上部に「送信できない理由」が表示されるので、確認し不足分を入力します。以下は、私が指摘された項目例です。

 - アカウントの連絡先の指定
 - storageの権限を要求する理由の説明
 - デベロッパーポリシーに準拠していることの表明
 - 拡張機能のmanifest.jsonのバージョンを3にする

アカウントの連絡先は、メインメニュー > アカウントより「連絡先メールアドレスを追加」から追加できます。

権限周りの説明は、「プライバシーへの取り組み」より入力できます。

私の場合manifest.jsonのバージョン2で開発していたため、バージョン3に変更する必要がありました。公式ドキュメントを参考に変更点を修正しました。

[マニフェストV3への移行](https://developer.chrome.com/docs/extensions/mv3/intro/mv3-migration/)


## 3.審査
必要項目の入力が全て完了すると、右上の「審査のための送信」が押せるようになるので、そちらから送信します。審査時間に関しては、結果が分かり次第こちらに記載します。

※追記
2022年2月11日（金）の午後に申請し、2022年2月14(月)には審査が完了していました！

# おわり
今回はChrome拡張機能をリリース手順についてまとめました。
費用は初回のみ5ドルと安く、申請までの手順も思いのほか簡単でした。

AppleStoreの場合年に1万円ほどかかるため、それと比較すると一度5ドル支払えばアプリを登録できるのでとてもありがたいです。
Chrome拡張機能はちょっとしたものであればすぐに作ることができるため、勉強にももってこいです。

リリースできたら、その時にまたQiitaにまとめたいと思います。

以上。
ワンライナーとrake task

ワンライナーとは一行で書かれたコードや、一行で書かれたコマンドの組み合わせのことです。

例えばif分などを使わず、三項演算子で書くなど一行で収まるようにしたコードや、

rake db:migrate など一行で書かれたコマンド等のことを言います。

以下ではRails のrakeタスクに自分が行いたいタスクを登録しておきconsoleからコマンドを叩くだけで実行する流れを説明します。

## Rakefileを作成する

railsではrakeコマンドを実行した場合、Rakefileと言う名前で登録されているファイルを参照しにいきます。（-fオプションをつけ明示的に違う名前のファイルを参照させることもできます。）

```ruby
mkdir test
cd test
touch Rakefile
```

## Rakefileの編集

Rakefaileの中では「desc」「task」と言う記述が出てきます。

「desc」にはタスクの一覧(次の項目で説明)を表示させた際、タスクがどのような役割を持っているかを説明する文を記述します。

「task」はrake taskで実際に実行するタスクの名称を記述します。

```ruby
desc 'rakeタスクのテスト' # タスクの説明
task :test do         # 実行する際の名称
  puts 'これはテストです'
end
```

## rakeコマンドで -T オプションをつけどんなタスクが登録されているのかを確認する

実際にタスクが登録されているのかを確認してみます。

```
rake -T
```

コマンド実行時の表示（#に続く文字列は実際に表示される文字列となります）

```ruby
rake test # rakeタスクのテスト
```

## rakeタスクの実行

それでは最後に作成したrakeタスクを実行してみます。

```ruby
rake test
```

```md
これはテストです
```

「これはテストです」と表示が出ればOKです。
WSL + VSCode でSpringBootをやりたい

# WSLからVSCodeが使えることを確認する。

たぶん、普通にWindowsにVSCodeをいれていれば、WSLからでも起動できる。

```
$ code
```

起動できない婆はDNSの設定ができていないかもしれない

https://qiita.com/kkato233/items/1fc71bde5a6d94f1b982

# JavaをWSLにインストールする

```
sudo apt install openjdk-11-jdk
```

# VSCodeに拡張機能をインストールする

この2つをインストールする

* Java Extension Pack
* Spring Boot Extension Pack

あとはこちらの手順通りにできる。

https://qiita.com/yama9112/items/ff829561238440437b99
日本語の大規模言語モデル作成PJを引き継いでくれる方を探しています

AIによる自然言語処理では、Transformerという種類のモデルが使用されます。

「GPT-3」等のAIが、掲示板でAIと気づかれないまま人間と対話していた、などのニュースを聞いた方もいるかと思います。

GPT-3の登場以降、世界的にはTransformerモデルのパラメーター数競争が始まっており、数千億パラメーターのモデルを事前学習して公開する事が、当たり前のように行われるようになりました。

代表的な超大規模Transformerモデルとしては、

「[GPT-3](https://github.com/openai/gpt-3)」（英語、1780億パラメーター）
「[悟道2.0](https://wudaoai.cn/)」（中国語、1兆6000億パラメーター）
「[Megatron-LM](https://github.com/NVIDIA/Megatron-LM)」（英語、1兆パラメーター）
「[HyperCLOVA](https://www.navercorp.com/promotion/pressReleasesView/30546)」（韓国語、2400億パラメーター）
「[PanGu-α](https://arxiv.org/abs/2104.12369)」（中国語、2000億パラメーター）
「[Jurassic-1](https://www.ai21.com/blog/announcing-ai21-studio-and-jurassic-1)」（英語、1780億パラメーター

等があります。

お隣の韓国ですら、NAVERが作成した[2400億パラメーターのモデル](https://www.navercorp.com/promotion/pressReleasesView/30546)があるのですが、日本語の大規模言語モデルとしては、今のところ私が知る限り、小説に特化したモデルの「[AIモデリスト](https://ai-novel.com/)（73億パラメーター）」と、株式会社りんなが公開した[GPT-2](https://huggingface.co/rinna/japanese-gpt-1b) 「13億パラメーター」くらいしか、めぼしいものはありません。（私の知らないモデルがあったらごめんなさい、コメント欄で教えてください）

このような状況ではまずい、と危機感を感じた私は、汎用大規模日本語言語モデルの作成プロジェクトを立ち上げ、[ソースコードを公開しました](https://github.com/tanreinama/GPTSAN)。

現在、500GiBほどのコーパスを教師データとして用意して、あとは学習するだけ、というステータスです。
ソースコードの方は、28億パラメーターのモデルを1TPUで学習出来るところまで確認しています。
モデル並列を使用したSwich Transformerなので、さらなるパラメーター数のスケールアップも容易で、スーパーコンピュータがあれば1000億パラメータークラスのモデルも現実的に作成可能な筈です。

ですが、どうやら資金調達的に力尽きようとしており、28億パラメーターのモデルすら学習がおぼつかない状況にあります。

そこで、AIベンチャー企業などを念頭に、本プロジェクト全体を引き継いで頂ける方を募集しています。

200万円くらいの予算があれば、りんなが公開しているモデルの2倍以上のパラメーターのモデルを作成出来ますよ？AI技術で投資を受けたり上場したい企業とか興味を持ってくれませんか？ついでに学習の技術サポートも無料で行います（28億パラメーターのモデルの学習のみ）。

自分はSNSとかやっていないので、共感頂けたら、Twitter等で拡散して頂けると大変に助かります。
terraformでobject型の特定の要素でフィルタリングする


## やりかた
- `for`をつかって、その中の`if`でフィルタリングする


```tf
locals {
  projects = {
    user01 = {
      domain = "vampire.local"
      id     = 1
    }
    user02 = {
      domain = "vampire.com"
      id     = 1
    }
    user03 = {
      domain = "vampire.jp"
      id     = 2
    }
  }
}

# idが1の要素のみを抽出したい場合
output "projects_1" {
  value = [for i, v in local.projects : v.domain if v.id == 1]
}

output "projects_2" {
  value = [for i, v in local.projects : v.domain if v.id == 2]
}

```


出力

```
projects_1 = [
  "vampire.local",
  "vampire.com",
]
projects_2 = [
  "vampire.jp",
]
```
CardViewの影をxmlで消す

#初めに一言

CardViewではを使うと指定もしていないのに、デフォルトでViewに影が付きます
その影を消す方法をGoogleで、「CardView　影　消す」などと調べてみましたが、
(デフォで付いてるはずだが)特定の条件での影が付かない場合の対処や別のViewについてが出てきて
探すのに苦労したので　自分の備忘録として残しておきます。

#早速

```
app:cardElevation="0dp"
```
この一文を影を消したい対象のCardViewに追加するだけです。

#説明
簡単に説明をしておきます
CardViewに影が付いているのは、立体的に見たときに高さがあるためです。
なので、その高さ(Elevation)を0に設定してあげれば影がなくなります。
JSONデータのアクセスキー情報を認証ファイル形式に変換するコマンド

先日、[JAWS-UG CLI専門支部](https://jawsug-cli.connpass.com/)に参加しました。
参加したのは「IAMユーザー基礎（ユーザー）」の会で、AWS CLIでIAMユーザーの作成を行うという内容です。

CLI専門支部では、講師の[波多野さん](https://twitter.com/tcsh?s=20&t=0b2mDD03rceirW5RpWHtAg)が作成した手順書をもとに、ゴリゴリハンズオンを進めています。

その手順書の中で「？？？」となったコマンドがあったので、個人的なメモとして残しておきます。

先に記載しておくと、以下のコマンドはJSON表記になっているAWSアクセスキーデータを、認証ファイルの形式に変換するためのコマンドです。

```
echo "[${IAM_USER_NAME}]" > ${FILE_USER_CREDENTIAL}

cat "${FILE_ACCESS_KEY}" \
  | jp.py 'AccessKey' \
  | sed '/[{}]/d' | sed 's/[\" ,]//g' | sed 's/:/=/' \
  | sed 's/AccessKeyId/aws_access_key_id/' \
  | sed 's/SecretAccessKey/aws_secret_access_key/' \
  | grep '^aws_' \
  >> ${FILE_USER_CREDENTIAL} \
    && cat ${FILE_USER_CREDENTIAL}
```


# この記事に書いてあること
 - jp.pyとは何か
 - sedコマンドの使用例
 - grepコマンドの使用例

（すべてメモ書き程度の内容ですのでご了承ください）

# jp.pyってなんぞ？？？

まずは2行目

```
jp.py 'AccessKey'
```

調べてみると、どうやらjp.pyというのはJSON用のクエリ言語らしい
なので上記コマンドを入力すると、'AccessKey'オブジェクトに対してクエリを実行することができる


ちなみに、jp.pyはAWS CLIをインストールすると自動でくっついてくるらしい
AWSとJSONは切っても切れない存在ですし、これは覚えておくとかなり使えそうです

https://qiita.com/tt2004d/items/22026bdc15b5cddd1bd2

# sedコマンドの嵐

次はsedが連続している3行目

```
  | sed '/[{}]/d' | sed 's/[\" ,]//g' | sed 's/:/=/' \
```

## sed '/[{}]/d'

sedコマンドは``/``で置き換える文字を区切っています
また、``d``をつけると行の削除を行います
加えて、``[]``は「囲まれているもののいずれか」という意味です

なので、最初のsedはこういう意味

 - 対象の文字は``{``、``}``のいずれか
 - 対象の文字が含まれる行を丸ごと削除


## sed 's/[\" ,]//g'
``s``は置換を意味する
デフォルトだと各行で一番最初にヒットした対象文字しか置換しないので、``g``をつけることで各行の対象文字をすべて置換することができる
なので、2つ目のsedはこういう意味

 - 対象の文字は``"``、`` ``（半角スペース）、``,``のいずれか
 - ``"``は特殊文字なので``\``でエスケープ処理
 - 置換後の文字を指定していないため、結果的には対象文字を削除する
 

## sed 's/:/=/'
これも``s``がついているので、``:``を``=``に置換するだけ
同様に、4-5行目も単純な置換を行っている

```
  | sed 's/AccessKeyId/aws_access_key_id/' \
  | sed 's/SecretAccessKey/aws_secret_access_key/' \
```


https://hana-shin.hatenablog.com/entry/2022/02/13/225121

# grepと正規表現

最後に正規表現を含んだgrepコマンド

```
  | grep '^aws_' \
```

まず、grepは ``''``で囲んだ文字列に一致する行を抽出するコマンド
そしてgrepは正規表現を使用でき、今回は``^``を使用している
``^``は行の先頭であることを指定しているので、以下のような意味になる

 - 行の先頭に``aws_``がある行だけを抽出

https://bi.biopapyrus.jp/os/linux/grep.html

# まとめ

最後に上記のコマンドを実行した結果どうなるのか、例を示しておきます

## before
元となる、JSON表記のアクセスキー情報

```json:${FILE_ACCESS_KEY}
{
  "AccessKey": {
    "UserName": "handson-cli-basic-user",
    "Status": "Active",
    "CreateDate": "2021-07-27T01:23:45.678Z",
    "SecretAccessKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "AccessKeyId": "xxxxxxxxxxxxxxxxxxxx"
  }
}
```

## after
以下のような新しい認証ファイルが作成される

```ini:${FILE_USER_CREDENTIAL}
[handson-cli-basic-user]
aws_access_key_id=xxxxxxxxxxxxxxxxxxxx
aws_secret_access_key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
```


# おわりに
勢いで調べたことをまとめているので、「ここ違うよ！」とか突っ込んでいただけると大変うれしいです

また、JAWS-UG CLI専門支部はAWSの勉強になるだけでなく、シェルスクリプトやLinuxコマンドの勉強になるのでとても楽しいです。
まだ参加して日が浅いですが、まずは一年間通してじっくり勉強させていただこうと思います！


# 補足
Twitterにて、講師の波多野さんから直々にご指摘をいただいております。

https://twitter.com/hatake_book/status/1492024709759729664?s=20&t=S3xsLFqFVOYCISVlHG0CLw

波多野さんありがとうございます！
Udemyの「メモを残しています」を削除する（Chrome拡張機能）

# 「〇〇人がメモを残しています」にイライラ

Udemy利用者なら、一度は経験したことがあると思います。

<img width="600" alt="qiita-square" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1504052/861dda4f-8126-631d-b2f1-2e57a5819b47.png">
<img width="600" alt="qiita-square" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1504052/bf846a93-14ff-a4cf-5ced-3b14d06b6d79.png">

メモの箇所をクリックしてしまうと、「〇〇人がメモを残しています」と表示され、ずっと画面に残り続けます（勝手に「メモトラップ」と呼んでいます）。

日本語の動画でも、メモトラップの影響でプログラムが見切れてイライラする事がありましたが、
最近英語の動画を見るようになってから、以下の事象からストレス指数が高くなりました。

* 英語の字幕が見切れる
* 英語のものは課題形式（問題を画面に表示してから、「問題が解けるまで動画をストップしてね」形式）が多い
    * 解説を飛ばすためにスキップを多用する→メモトラップに引っ掛かる確率が上がる

自分はメモ機能を利用する機会が全く無いので、
Chrome拡張機能を利用して、ページ読み込み時にメモトラップを削除するようにします。

##目次

* [メモトラップを消す方法について](#メモトラップを消す方法について)
* [ファイル構成とコード](#ファイル構成とコード)
* [利用方法](#利用方法)
* [参考記事](#参考記事)

## メモトラップを消す方法について

一応ブラウザバックやリロードを行うことで、メモトラップを消すことができますが、間違える度行うのはかなり面倒です（メモトラップは残っている状態のためクリックすると、また表示されます）。

だだ、メモトラップもHTML/CSSで描写されているので消すことができます。
デベロッパーツールで該当のコードを確認すると、以下のように記述されていました。

```.html
<textarea id="bookmark-title--〇〇" disabled="" rows="1" style="overflow: hidden; overflow-wrap: break-word; height: 32px;">△△人がここにメモを残しています。</textarea>
```

毎回デベロッパーツールで該当する要素を削除するのは面倒なので、
Chrome拡張機能を使用して、ページ呼び込み後にメモトラップの要素を削除するようにします。

## ファイル構成とコード

```ファイル構成.txt
.
└── src
     ├── content.js
     └── manifest.json
```

```content.js
// 動画の読み込み後に処理を走らせるために遅延させている
let deleteMemoElement = setInterval(function () {
  // idが「bookmark-title--」に前方一致する要素を配列で取得
  const SEARCH_ELEMENT = [].slice.call(
    document.querySelectorAll('[id^="bookmark-title--"]')
  );
  if (SEARCH_ELEMENT.length > 0) {
    let eachElementId;
    // 配列を取り出し、要素を削除
    for (let i = 0; i < SEARCH_ELEMENT.length; i++) {
      eachElementId = document.getElementById(SEARCH_ELEMENT[i].id);
      eachElementId.remove();
    }
  }
}, 10000);

window.onload = function () {
  deleteMemoElement;
};
```

```manifest.json
{
  "manifest_version": 2,
  "name": "UdemyMemoDelete",
  "version": "1.0",
  "description": "Udemyの「~人がここにメモを残しています。」を削除する",
  "icons": {},
  "content_scripts": [
    {
      "matches": ["https://www.udemy.com/course/*"],
      "js": ["content.js"]
    }
  ]
}
```

該当の要素を削除するだけなので、処理や構成は単純で、JSとmanifest.jsonのみの必要最低限の作りとなっています。
（デザインを変更したり、設定画面を表示する場合にはCSSやHTMLのファイルが必要）

manifest.jsonは設定ファイル（利用するファイルの名前や、オプションの利用、拡張機能の説明などを記述）です。
manifest.jsonを知りたい方は、[参考](#参考) の記事に詳しく記述されていたので、そちらをご参照下さい。

## 利用方法

以下の手順で設定することで、メモトラップの削除が適用されるようになります。
（Chromeウェブストアで公開するためにはアプリを登録する必要があり、現在申請を行い、審査待ちの状況です。）

1. [ファイル構成とコード](#ファイル構成とコード) に記述したコードをコピーして、同様のファイル構成で作成します。
1. Google Chromeのアドレスバーに「 chrome://extensions/ 」と入力して、拡張機能の設定画面を開いてください。
1. 右上の「デベロッパーモード」がONになっていることを確認します。
1. 画面上部の「パッケージ化されていない拡張機能を読み込む」をクリックして、先ほど作成した「src」フォルダを選択します。

## 参考記事

https://qiita.com/RyBB/items/32b2a7b879f21b3edefc

https://qiita.com/mdstoy/items/9866544e37987337dc79
Material-UI のTypographyで文字を枠内に収める [メモ]


## Typography が枠内に収まらない


`
<Typography component='p'>{message}</Typography>
`

propsとして component='p'を渡してパラグラフ要素して使用。

動作の確認で下記の左側のように'aaaa'のように入力していたため、枠に収まらない理由がわからなかった...

しかし、日本語や'Hello world'のようにちゃんと文字を入力すれば普通に改行してくれて、枠内に収まってくれた...(勉強不足)


![スクリーンショット 2022-02-11 15.13.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748980/cded4fc2-72cc-d313-1fdd-5d91ffdcd29b.png)

### すべての文字を表示したくない場合 nowrap を使う

`
<Typography nowrap component='p'>{message}</Typography>
`


nowrapを使うと 文字列の最後に'...'と表示できる。
しかも枠の大きさに合わせて'...'を表示してくれるので使い勝手はよさそう。

＊ただ、文字数を指定しないと下記の写真のように1行のみしか表示されないので注意が必要。

![スクリーンショット 2022-02-11 15.23.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748980/6991786a-f6b6-4874-528f-2a856edfe1b5.png)
【新人エンジニアが在宅ワークで心がけている5つの方法】

こんにちは。
入社2年目の文系出身エンジニアです。
昨今新型コロナウィルスが蔓延しており、
なかなか外に出れず、悶々と在宅ワークを続けています。
私が会社に入社した当時からコロナウィルスが猛威を振るっており、
新人研修から在宅ワークはスタートしていました。
そんな在宅ワーク2年目の私(?)が在宅ワークでどのように社員と
コミュニケーションをとり、作業をこなしているのか
5つに分けてご紹介したいと思います。

#### 1.自分の中で課題を見つける
PCを開いてからまず今日のタスクは何があるのか、どこまでできるのか明確にします。
私は毎週月曜定期的に行わないといけない作業があるため、
優先順位を明確にしながら作業していきます。

#### 2.分からない箇所はスクショ画像で添付
分からない箇所がある場合、分からない箇所をスクショし
画像を添付しながらここが分からないとよく言います。
私は、説明するのが下手なため、言葉だけだとなかなか相手に伝わらないことが多く、
「言っている意味がよく分からない」と言われます(悲しい。。)
ただ画像(設計書の画像・UT内容など)を添付することで、
ここが分からないんだなと相手にも納得してもらうことが多く、
ツールだけで解決することがあります。
説明下手な方は良かったら、試してみてください！

#### 3.進捗確認は正直に伝えるようにする！できなかったらできないと言う！
当たり前なことだと思います。
今となれば恥ずかしいですが、入社1年目の時、できなかったと言うことが、
当時の私にとって非常に恥ずかしく、今思えばプライドが高かったのだと思います。
PMの方はできないと言っても、その後の対策等どのように進めればいいのか、
相談してくれるはずです。なので、進捗は正直に言う方が吉です。

#### 4.煮詰まった時、息抜きで読書もしくは身体動かす!PCやスマホを見ない!
煮詰まってしまった時、泥沼にはまってしまい、
できていることもできなくなってしまいます。
そんな時、私は長めの休憩を取ります(15～20分程度)
その後、頭がさえ分かったかも！って思うことが増えます。
また、目が疲れるため、スマホやPCをなるべく見ないようにします。

#### 5.どんな状況であっても笑いながらコミュニケーションをとる
在宅ワークをしている時って、相手の顔がよく分からないから、
どんな表情で受け答えしているか不安になるときありませんか？
私は、相手を不安にさせないようにするため、1日1笑いするようにしています。
出社している時、相手の顔が分かった状態で話すので、
顔の表情や心情が少しですけど、読み取れるので問題ないと思います。
しかし、電話だけで受け答えするとなると、どうしても重い空気になりがちというか、冷たく感じてしまいます。
進捗話す時とか、ちょっとした雑談の時とかは笑うようにして
相手の気分を和ますように心がけています。
そうすることで、向こうも安心して会話できる＋笑っている自分も
相乗効果で少し？楽しくなるかと思います。
1人だけで黙々と作業をしていると、厳しい顔つきになることが多くなるため、
リフレッシュしたい時にもおすすめかと思います。

#### 最後に
ここまで読んでくださり、ありがとうございました！
大変な時期に社会人になってしまったなぁとつくづく思います笑
と同時に、多種多様な働き方ができたことは、大きなメリットだなと感じます。
コロナが収まった時は、在宅＋出社という形で
バランスよく働けるようにしていきたいですね。
Synology NASのDocker上に速度計測サイト(LibreSpeed)を構築

[LibreSpeed](https://github.com/librespeed/speedtest)というOSSを使い、Synology NAS DS220+上にオンプレの速度計測サイトを構築したいと思います。
リモートアクセス時の速度計測の利用できるのでは（？）と思ってます。

# LibreSpeedとは

[LibreSpeed](https://github.com/librespeed/speedtest)とはオンプレ環境に[Fast.com](https://fast.com/)のような速度計測サイトを構築できるOSSです。バックエンドはPHPで作られているようです。DBに計測履歴を残したり、計測画面や計測に使うデータ量などのカスタマイズも可能です。
Docker Hubに公式イメージが提供されているので、今回はそれを利用していきます。

# 構築手順

Dockerが利用可能なSynology NASを用意します。

### Dockerイメージのダウンロード

LibreSpeedのgithubにリンクがある`adolfintel/speedtest`というイメージを使います。
https://registry.hub.docker.com/r/adolfintel/speedtest

![レジストリ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524454/d2bc4fd4-46a4-e463-a43d-971ace492614.png)

### コンテナの設定・起動

コンテナを作成します。適当に名前とメモリ制限を設定しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524454/bbc1699f-1174-8533-672b-4eb261db2327.png)

詳細設定から環境変数の設定を行います。
ポート設定のタブで適当なローカルポートを指定し、適用を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524454/1fcc2681-4577-394a-8d50-0779e0083b41.png)

次へを押し、完了を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524454/3db74146-d87e-077c-b7d2-c699ff54a235.png)

### 起動確認
`http://<NASのIPアドレス>:8088(先ほど指定したポート)/`にアクセスし、サイトが表示されていることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524454/a0886d0b-f9bb-963c-a021-c8dddd8ae8d8.png)

# おわりに

実際に計測してみました。NASとPCとは1GbEのスイッチンハブでつないでいるだけなので、しっかり1000Mbpsでています。(誤差なのか少し高くでてますね…）
リソース使用量も低く、1人で利用する場合はもう少しメモリ制限を低くしてもよかったですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524454/5613542e-b1cc-7103-9f62-aaf33dd8eb9b.png)

Wifi経由でスマホからの計測結果です。
![スマホ計測_縮小.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524454/6d02c6bc-224e-66c1-900c-ad84b27eb62d.png)


# 参考文献

LibreSpeed/GitHub
https://github.com/librespeed/speedtest
MacでA5M2を使いたい（2022年Ver.）

# 環境

MacBook Air　2020
macOS Mnterey 12.0.1


# 用意するもの

### 1.XQuartz
https://www.xquartz.org/index.html
（今回はver2.8.1）

### 2.Homebrew
https://brew.sh/index_ja

(分からない人はググってね）


# WINEのインストール

公式サイトからダウンロードしようとしたものの、起動すると３２ビットだから使えませんとMacBookに怒られてしまう。
https://dl.winehq.org/wine-builds/macosx/download.html

色々調べてみるとbrewでインストールできるらしい。

https://github.com/Gcenx/homebrew-wine

```
$ brew install --cask --no-quarantine gcenx/wine/wine-crossover
```
wine-6.0をインストール。

アプリケーションにWine Ceossoverが！！

![スクリーンショット 2022-02-11 14.46.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1783158/b7acd55c-c46c-e74a-7676-e7b1d4ce2744.png)


#A5M2を起動

言うまでもなくインストール
https://a5m2.mmatsubara.com/


![スクリーンショット 2022-02-11 14.49.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1783158/6410efcb-f593-53ec-fc14-20145995043e.png)

ダウンロードしてきた.exeから右クリックでWineで開く（ダブルクリックでも開く）

そうすると...




![スクリーンショット 2022-02-11 11.54.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1783158/24aab223-892f-7875-cb96-7e5aa638dd75.png)

お、お豆腐！！！泣


どうやら文字化けするらしい。。。



#文字化け解消

ターミナルで`$ brew install wget`を入力し、wgetをインストール。

~/Downloads ディレクトリに移動し、wgetコマンドでwinetricksを取得。
https://github.com/Winetricks/winetricks

```
$ wget https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks
```

参考にさせてもらった記事ではここでwinetricksと入力すれば起動すると書いてあったが、起動せず、、、。
試しにBrewでインストールしてみた。

```
$ brew install winetricks
```

そうする`winetricks`コマンドの使用が可能になった！
最後にフォントの設定。
以下どちらかのコマンドを入力。（今回自分が入れたのはcjkfontsの方）

```
$ winetricks fakejapanese_ipamona
```


```
$ winetricks cjkfonts
```


そして改めてA5M2を起動すると。。。

![スクリーンショット 2022-02-11 14.17.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1783158/778f71af-510b-078d-ade2-0a28217e5bdf.png)


文字化けしなくなってた！！



#ハマった点
A5M2が起動するまではスイスイできたが、文字化けを治す方がかなり時間がかかった。
winetricksのコマンドを打つ時に以下のエラーが出て起動せず。
 `please retest in a clean 32-bit WINEPREFIX before reporting a bug`
調べてみるとバージョンんが〜とか、WINEPREFIXが〜と難しいことが色々書いてあった。
Wineの仮想Cドライブやレジストリは、通常[ホームディレクトリ]/.wine/というディレクトリの中に一緒に格納されているらしく、最初にインストローラーで入れた際
の３２bit版の同名ファイルが存在していたのが原因ぽく、該当フォルダの名前を変更したら動いた。

何はともあれ、これで私用のMacBookでも使い慣れたA5M2を使用できる様になったので、開発が捗りますなあ。


#参考にさせて頂いたサイト

https://qiita.com/jibril/items/5041cf8921df996cca17
https://bigmoro.cocolog-nifty.com/blog/2021/04/post-2f6bff.html
https://kakurasan.blogspot.com/2015/06/manage-winapps-using-wineprefixes.html