OmniAICreator/Qiita-1.07M huggingface dataset:
Linuxの学習ログ

# 学習教材
udemyで[「もう怖くないLinuxコマンド。手を動かしながらLinuxコマンドラインを5日間で身に付けよう」](https://www.udemy.com/course/unscared_linux/)という講座を受講。
セール中だったので、1300円で購入できた。（定価1万1000円）
初心者の私にもわかりやすい内容で、Linuxの基礎を理解することができた。
[<img width = 800 src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2674841/227df299-b860-2e0f-fc7a-d3ad65786f7c.png">](https://www.udemy.com/course/unscared_linux/)

# 学習範囲
## Linuxの概要
Linuxの誕生から現在に至るまでの経過や、Linux構造の概要を学び、サーバ利用時などにおいて、必須の知識であることを確認した。
実際にVirtualBoxをインストールした。
## ディレクトリ操作
ディレクトリ操作コマンドのcd,pwd,ls,mkdir,rmdirを理解した。
## ファイル操作
ファイル操作コマンドのcat,less,touch,rm,mv,cp,ln,findを理解した。
## 標準入出力とパーミッション
標準入出力とリダイレクト、パイプラインを理解した。
ファイルのオーナーとグループ、パーミッション、chmod、スーパーユーザーを理解した。
## プロセス・ジョブ管理
プロセスコマンドのps、ジョブコマンドのfg,bg,killコマンドを理解した。
# 受講を終えて
動画で説明を受けて、実際にVirtualBoxで入力することにより、効果的に学習をすることができた。
また講師の山浦先生の説明が大変分かりやすく、Linuxの基礎を理解することができた。
LaravelにてMQTTメッセージを発行する方法の話

phpでmqttを利用するにはどうすれば良いでしょうか？
さまざまな方法がありますが、
今回はLaravelでのMQTTメッセージの発行方法を調査しました。

# はじめに
前回([MQTT(Mosquitto)サーバの構築の話 2022/05/28](https://qiita.com/wataru775/items/2bb2c7adedc5fd93c936))、MQTTサーバのインストールと動作検証を行いました。
最終的な動作環境は下図の様になっております。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2481837/a6bc340e-32b6-4c80-ff15-0d21f7f2955f.png)

この図のメッセージの発行側（送信側）をLaravelへと置き換える方法をまとめます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2481837/afa88503-6d6f-3cf6-4a32-eaee62dd5ea4.png)


ホスト
1 : 開発PC (Laravel動作 MQTTメッセージ発行)
201 : MQTTサーバ
220 : MQTTメッセージ購読

# LaravelでMQTTメッセージを発行するライブラリ
LaravelでMQTTメッセージを発行するにはさまざまなライブラリがあります。
今回はphp-mqttにlaravel-clientというのを見つけたのでそれで実装します

php-mqtt laravel-client : https://github.com/php-mqtt/laravel-client

# php-mqtt(laravel-client)をインストールする
php-mqtt laravel-clientのインストールはcomposerを用いれば簡単に入ります。

実装プロジェクトのルートに入って、Terminalで以下を実行してください。

```bash
composer require php-mqtt/laravel-client
```

雛形コンフィグをコピーする
```bash
cp ./vendor/php-mqtt/laravel-client/config/mqtt-client.php ./config/
```
これでphp-mqtt laravel-clientを使う準備は完了しました。

# MQTTサーバの指定
php-mqtt laravel-clientの設定ファイル(./config/mqtt-client.php)を直接いじっても良いですが、
環境変数:MQTT_HOSTに指定すれば採用してくれますので環境設定ファイル(.env)にてしています。
MQTTサーバは192.168.1.201を指定します。
.envで指定する理由は… .env.testingとか実行環境で分けられるので便利です

```
MQTT_HOST=192.168.1.201
```

# メッセージ発行プログラムの記述
MQTTサーバの指定まで終わると、
プログラムにメッセージ発行命令を記述すればメッセージは発行されます。

```php
MQTT::publish('test', 'hello php-mqtt!');
```
例では、
topicを”test”
メッセージ本文は”hello php-mqtt”

今回はメッセージの発行を確認するだけなのでLaravelのデフォルトのwelcomeページを表示するタイミングで発行してみます。
routes/web.php

```php
Route::get('/', function () {
    MQTT::publish('test', 'hello php-mqtt!');
    return view('welcome');
});
```
serveして
```bash
$ php artisan serve --host 192.168.1.1
```

ページアクセス : http://192.168.1.1:8000/

これでTOPページにアクセスすると普通にWelcomeページが表示されます。
そのタイミングで今回追記したMQTTサーバへとMQTTメッセージが発行処理がされます

# 購読端末での動作検証
購読端末(raspberrypi)に入りmosquittoを購読状態とします。
その後に、LaravelのWelcomeページにアクセスします。
すると以下の様にメッセージが購読できることを確認できます。

```bash
pi@raspberrypi:~ $ mosquitto_sub -h 192.168.1.201 -t test -d
Client mosqsub|12840-raspberry sending CONNECT
Client mosqsub|12840-raspberry received CONNACK (0)
Client mosqsub|12840-raspberry sending SUBSCRIBE (Mid: 1, Topic: test, QoS: 0)
Client mosqsub|12840-raspberry received SUBACK
Subscribed (mid: 1): 0
Client mosqsub|12840-raspberry received PUBLISH (d0, q0, r0, m0, 'test', ... (15 bytes))
hello php-mqtt!
```
購読できました！

# 終いに
今回はLaravelでのMQTTメッセージ発行方法を書きました。

購読は？と思いましたが…
Laravelでは私は発行しか使わないので調べません！
時間があったら調査するかもしれませんが…

次回の記事は…
もちろん購読側をどうするのかですね。

今までの購読側端末をRaspberry piで行なっています。
なのでそのまま購読するプログラムの実装もRaspberry piで調査とします。

ソース : https://www.mmpp.org/archives/2919
macbook 歴代のサイズと重さ

最軽量は12インチmacbookです。
![94E8E789-F99B-447B-AB35-592D150CF7D9-1024x451.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282788/ebffdbf1-06e2-bf04-f418-b9b52a7842e6.jpeg)
![640D1CA9-9881-4B76-AC7B-476D1AD1EC63-1024x423.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282788/d524b561-7537-da86-aa6e-675499da7100.jpeg)
VScodeのリモート接続時に追加したい拡張機能のIDを調べる(Docker)

## 概要
Dockerを使用してVScodeでリモート環境を作る際に拡張機能IDの調べ方がわからなかったので備忘録として残しておく
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633008/3c671e64-8ef2-2336-58d0-9e5718b34fc3.png)

### 調べ方
追加したい拡張機能のページを開いて歯車マークの「拡張機能IDのコピー」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633008/0df75866-2af9-68b5-0e8e-20bafbc447cb.png)



所定の場所へ貼り付ければ完了です
```devcontainer.json
  "extensions": [
    "xdebug.php-debug",
  ],
```

リモートで繋いだDockerコンテナに拡張機能がインストールされていることが確認できます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633008/e4935528-380d-f7a1-4538-3aba008b9720.png)
download twitter space audio

## Requirements

[ffmpeg](https://ffmpeg.org/)

## Install

```
pip3 install twspace-dl

twspace_dl -i "https://twitter.com/i/spaces/1eaKbNVRlVeKX?s=20"
```

## command line

```
usage: twspace_dl [-h] [-v] [-s] [-k] [-l] [--input-cookie-file COOKIE_FILE]
                  [--username USERNAME] [--password PASSWORD]
                  [--output-cookie-file OUTPUT_COOKIE_FILE]
                  [-i SPACE_URL | -U USER_URL] [-d DYN_URL] [-f URL] [-M PATH]
                  [-o FORMAT_STR] [-m] [-p] [-u] [--write-url URL_OUTPUT]

Script designed to help download twitter spaces

optional arguments:
  -h, --help            show this help message and exit
  -v, --verbose
  -s, --skip-download
  -k, --keep-files
  -l, --log             create logfile
  --input-cookie-file COOKIE_FILE

input:
  -i SPACE_URL, --input-url SPACE_URL
  -U USER_URL, --user-url USER_URL
  -d DYN_URL, --from-dynamic-url DYN_URL
                        use the dynamic url for the processes(useful for ended
                        spaces) example: https://prod-fastly-ap-northeast-1.vi
                        deo.pscp.tv/Transcoding/v1/hls/zUUpEgiM0M18jCGxo2eSZs9
                        9p49hfyFQr1l4cdze-Sp4T-DQOMMoZpkbdyetgfwscfvvUkAdeF-I5
                        hPI4bGoYg/non_transcode/ap-northeast-1/periscope-
                        replay-direct-prod-ap-northeast-1-public/audio-
                        space/dynamic_playlist.m3u8?type=live
  -f URL, --from-master-url URL
                        use the master url for the processes(useful for ended
                        spaces) example: https://prod-fastly-ap-northeast-1.vi
                        deo.pscp.tv/Transcoding/v1/hls/YRSsw6_P5xUZHMualK5-ihv
                        ePR6o4QmoZVOBGicKvmkL_KB9IQYtxVqm3P_vpZ2HnFkoRfar4_uJO
                        jqC8OCo5A/non_transcode/ap-northeast-1/periscope-
                        replay-direct-prod-ap-northeast-1-public/audio-
                        space/master_playlist.m3u8
  -M PATH, --input-metadata PATH
                        use a metadata json file instead of input url (useful
                        for very old ended spaces)

output:
  -o FORMAT_STR, --output FORMAT_STR
  -m, --write-metadata  write the full metadata json to a file
  -p, --write-playlist  write the m3u8 used to download the stream(e.g. if you
                        want to use another downloader)
  -u, --url             display the master url
  --write-url URL_OUTPUT
                        write master url to file

login:
  --username USERNAME
  --password PASSWORD
  --output-cookie-file OUTPUT_COOKIE_FILE
```

---

Ref:

https://github.com/HoloArchivists/twspace-dl/

https://github.com/HoloArchivists/twspace-dl/issues/56
MySQL初心者　備忘録

## ●ERROR:三角連続
mysql> --
　　　>
　　　>

後ろに；をつける
mysql> --;
Query OK,

## ●ERROR:your password does not satisfy the current policy requirements sql(パスワードがポリシーを満たしてないです)


```
mysql> show global variables like '%validate%';
```
で以下のようなテーブルを確認

| Variable_name |Value  |
|---|---|
| innodb_validate_tablespace_paths |ON |
| validate_password.check_user_name    | ON     |
| validate_password.dictionary_file    |        |
| validate_password.length             | 8      |
| validate_password.mixed_case_count   | 1      |
| validate_password.number_count       | 0      |
| validate_password.policy             | MEDIUM |
| validate_password.special_char_count | 1 
#
次にパスワードのポリシーを変更する
たとえば、うえの表では　validate_password.length　が 8となっているので8文字以上のパスワードでないと設定できない状態。
```
mysql> SET GLOBAL validate_password.length = 4;
```
などとすれば、４文字のパスワードを設定できる。

# 参考
https://qiita.com/keisukeYamagishi/items/d897e5c52fe9fd8d9273
要素数の異なる配列を長い方の要素数だけzipでループする実装 

カードゲームを実装する際、異なる配列を同時にループさせて要素を比較するということがあるかと思います。
そういった場合、pythonでは異なる要素を同時にループさせるzipを用いて実装することを最初のうちは考えるかと思います。
しかし、以下のようにzipは短い方の配列に合わせて、長い方をスライスしてしまいますので要素数が多い方が勝ちみたいなケースには対応できません。
```Python
a_array = [4, 3, 2]
b_array = [4, 3, 2, 1]

for a, b in zip(a_array, b_array):
    print(f'{a}:{b}')

==== 出力 ====
4:4
3:3
2:2
```

そういった場合は以下のように短い方の配列に仮の値を埋めるような実装を行うかと思います。

```Python
a_array = [4, 3, 2]
b_array = [4, 3, 2, 1]
lenDiff = len(a_array) - len(b_array)
if lenDiff > 0:
    b_array += [-1] * lenDiff
if lenDiff < 0:
    a_array += [-1] * -lenDiff

for a, b in zip(a_array, b_array):
    print(f'{a}:{b}')

==== 出力 ====
4:4
3:3
2:2
-1:1
```

pythonではitertoolsというパッケージにzip_longestという関数においてfillvalueという引数に任意の値を指定すればその値で埋めてくれるようになっているので、こちらを使うといいと思います。

```Python
from itertools import zip_longest

a_array = [4, 3, 2]
b_array = [4, 3, 2, 1]

lenDiff = len(a_array) - len(b_array)

for a, b in zip_longest(a_array, b_array, fillvalue=-1):
    print(f'{a}:{b}')

==== 出力 ====
4:4
3:3
2:2
-1:1
```
参考：[python.org itertools](https://docs.python.org/ja/3/library/itertools.html#itertools.zip_longest "python.org itertools")
初心者が3日で貨物列車の時刻表botをつくりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2697447/44cc093a-4258-8c85-a04c-33fcc918c317.png)

# １　この記事の対象の方と完成品
#### 1-1　この記事の対象の方
- 非エンジニアから情シスへ異動された方
- コードも業界知識もまだ勉強中の方
- 一人DXに取り組んでいる方
- 「あれっ？物流業界の問題ってデジタルとITの組み合わせで結構解決できるんじゃね？」と思った方
私も新米ですがアイデアを形にしようと思いノーコード開発へ挑戦しました。よろしくお願いいたします。
![貨物列車.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2697447/0d504f89-a9ea-dd87-18c2-e74ab1457575.jpeg)


#### 1-2　完成品（と使用したツール）
・<b>使用したツール</b>
#Line Deveropers #Make #SSSAPI
・Make登録方法
https://zenn.dev/protoout/articles/12-integromat-signup
・LINE BOT登録方法
https://zenn.dev/protoout/articles/16-line-bot-setup
・SSSAPI登録方法は、個人で記事を書かれている方が多いのでQiitaの検索窓から検索をお願いいたします。
＊所要時間　各ユーザー登録～制作まで、合計18H程度（この記事書いてる時間や調整にかかった時間は除く）
↓完成品（貨物列車時刻表Bot（試作版））はこちら
![貨物列車.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2697447/a4af098e-f402-bf9c-72d1-eea49dcd4d1d.gif)



# ２　旅客じゃないんや・。欲しいのは「貨物列車」の時刻表アプリなんや・・・・。
#### 2-1  背中で語る男たちと脱昭和
世の中には旅客向けの時刻表アプリは数多く存在していますが、実は「「貨物列車」の時刻表アプリ」は存在を確認できていません。

　そう！需要無いですからね。

この状態、我々物流の人からすると
- 「残貨が発生した」（いろいろな事情から荷物を残したまま発車せざるを得ない状態の事）
- 「大雪」（事故）で迂回ルートを取った
-といった事態が発生するたびに分厚い「貨物列車時刻表」と畳一畳ほどの「経路図」（通称　あやとり）を机の上に広げてにらめっこが始まることを意味します。

<b>我々が欲しいのは旅客じゃない、「貨物列車」の時刻表アプリなんや・・・・</b>

そう語るUさん（物流実務責任者）

その姿は昭和の名優たちが熱演した刑事ドラマのワンシーンにそっくりです。
（↓物流マンの命綱「貨物時刻表」）
![画像 -20220527-071754-6aeef85f.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2697447/d224dd66-b3b6-29c6-d8c3-61d0d6532772.jpeg)

しかし、旅客列車と比べて変則的な動きをする貨物列車は「次の列車がいつ出るか？」紙の時刻表をみてもすぐにわからないのが現実です。

ですので作成に挑戦しました！
貨物列車時刻表BOT

# 3 要件定義～ローコード開発～ユーザーテスト（内製開発の魅力)



#### 3-1 要件定義
「思い付きで作ってしまったITシステム」
これ、避けたいですよね。

ですのでどんな機能を求めているのか？
どんな使い方をしているのか？
聞いてみました。
結果、
- 実務では列車番号をキーに業務を組み立てている
- 見ている情報は、経路と時間

が判明。
上記から問い合わせキーは<b>「列車番号」</b>
返す内容は<b>「出発地点・時間」「終着地点・時間」</B>の4項目と決定
同時に仮の納期まで3日しかないので「アプリ」ではなく必要な機能を狙って実装できる「LINE　BOT」と手段も決定

　要件定義の際、普段は聞かれる方だったけど聞く方に回ると「ユーザーのイメージ」をどのように機能に実装するか、インタビュー技術が必要だと実感。
<font color="DeepPink">SEの皆さん、いままでワガママ言ってゴメンナサイ</font>


####  3-2　開発開始
爆速一人案件だからWBSとかいらないよなー、と思いつつやることを書き出していたらいつものWBSになってました。恐るべし先人の知恵。
ノーコード開発だと詳細設計フェーズの工数が減るんだと実感。
まずは*Line Divelopers*
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2697447/eeef95e1-abdb-8790-cdab-3ddcac6968e0.png)


お次は*MAKE*
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2697447/22e1eb53-558a-75fe-90e2-fa18822949a0.png)


＊SSSAPIは50行までしかデータを登録できないので注意

#### 3-3　ユーザーテスト
・10行ほどデータを入れた状態をモックとし、実際に使用してもらい使用感や情報に抜け漏れがないかチェック
・問題が無かったのでデータ登録開始

<b>納期もさることながらその場でユーザーの意見を聞きながら、修正できるのが内製開発の強みですよね。<b>

# 4  　完成
無事に納品できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2697447/ba2bf240-a775-f7a6-fdd6-66a04e679b36.png)



# 5　反省と振り返り
#### 5-1　時間配分
・パソコンとにらめっこしてる時間が18H程度
・関係者へヒアリングしたり調整する時間が２H程度
これを通常業務や別件を抱えながら3日（72H）でやりきるのはかなりタイトでした。

#### 5-2　技術的な問題
・LINE BOT何それ？状態からスタート。身近に教えてくれる人がいたり、質問できる環境は必須です。

#### 5-3　タスク進行
・「一人プロジェクト」状態でしたがPM-BOKといったプロジェクト進行の知識は有効でした。


このような感じでしょうか。
私なりに3日間で経験した事を書き出してみました。
同じような新米情シスの方の参考になればとてもうれしいです。
laravel auth 管理者権限追加

備忘録です。
laravel 6 + auth で特定ユーザーに何らかの権限（例えば管理者）を与えて区別したい場合
usersテーブルに例えば admin(boolean)とかの列を加えて、特定ユーザーは true その他は falseとしておいて
Auth::user()->admin で真偽値が戻ります。
Auth::user() が何をやっているのか分かっている方には既知なのでしょうけど。
user()->なんとか　はそのuser のその列を返すのですね。
あまりに簡単にカスタマイズできるので驚いてしまいました。
【自分用メモ】Laravel 環境構築してみた

# Composerのインストール
https://getcomposer.org/

1. Donwloadを選択
1. Composer-Setup.exeをダウンロード&インストール
# Laravelの環境構築
ターミナルで、`composer create-project laravel/laravel (プロジェクト名）`を実行。
# 作成したプロジェクトディレクトリに移動
`cd (プロジェクト名)`を実行。
# 簡易サーバーの確認
1. `php artisan serve`を実行
1. URLを開く。トップページが表示されればOK。
# node.jsのダウンロード&インストール
https://nodejs.org/ja/

1. バージョン確認`node -v`
1. エラーが出る場合はVS Codeを再起動してみる。
# タイムゾーン設定と言語設定
config\app.phpで以下の通り変更。
'timezone' => 'Asia/Tokyo',
'locale' => 'ja',
# デバッグバーのインストール
`composer require barryvdh/laravel-debugbar`を実行。
# laravel/uiパッケージインストール
`composer require laravel/ui`を実行。
# ログイン認証機能の追加(Bootstrap scaffolding)
`php artisan ui bootstrap --auth`を実行。
# css, jsを追加
`npm install`を実行。
# ビルドコマンドおよび環境構築完了
1. `npm run dev`を実行。node modulesディレクトリが追加された。
1. `npm run development`を実行。これで一通り環境構築完了。
初学者によるアトミックデザインとの戦い

### はじめに

はじめまして、1年半ほど前からプログラミングを学習しているものです。
現在開発中のWebアプリでアトミックデザインを採用して進めていましたが、作り直しに近い形でリファクタリングを始めることにしました。
今回はなぜそう思い立ったのかと今後の方向性について書いていこうと思います。

### これまでの経緯

Reactを最初に学んだときに知ったのが、アトミックデザインであり、これがディレクトリ構成の基本なんだと思い、あまり自分の頭で考えることなく、これに従って進めていきました。

厳密に言えば、atomsはchakraUIを用いていたため使ってはおらず、chakraUIで成り立つ複数コンポーネントを取りまとめたものをmoleculesとし、それをimportして使っていました。

templateとmoleculesを当初分けていましたがそれぞれの違いがよくわからなくなってしまったので、画面を構成する汎用的なコンポーネントの集まりをmoleculesとしてtemplateは使わずに進めていきました。

顧客の新規登録など1ページを構成するものをorganismsとして進めました。

以下がディレクトリ構成のイメージです。
```
src/
├─ components/
│  ├─ molecules/
│  │  ├─ Input/
│  │  │  ├─ InputArea/
│  │  │  ├─ Form/
│  │  │  │  ├─ InputText/
│  │  │  │  ├─ InputNumber/
│  ├─ organisms/
│  │  ├─ Input/
│  │  │  ├─ PartnerInput/
│  │  │  ├─ ItemInput/
├─ hooks/
├─ functions/

```




### よかった点


organismsは機能が担うコンポーネント、moleculesは見た目だけを担うと分けて実装ができました。
そのためなにかロジック周りで不具合があった際には、organismsをまず見にいけばいいという整理ができていました。



### 反省点


#### 1つのコンポーネントで共通化しようとしすぎた
当初すべてのコンポーネントがバラバラであり、フォームの実装において、大量のuseStateを用いており、パフォーマンスも悪い状態でした。

もう少し共通化したほうがいいよという指摘を先輩エンジニアから受け、react hook formを導入するタイミングで、フォームに関わるコンポーネントをその後、がっつり共通化を進めました。

その際、フォームに関するカード・タイトル・ボタンまでをも、1つのコンポーネントとしてすべて共通化してしまったため、
新規登録画面に出したい「新規登録ボタン」と「キャンセルボタン」と、
編集画面に出したい「保存ボタン」と「キャンセルボタン」と「削除ボタン」ををすべて三項演算子を用いて出し分けを行っていきました。

フォームの種類は依頼主・お届け先・商品・注文・送状・まとめて登録と6通りあり、これをなるべく共通化するようにしてしまったことで、条件分岐だらけになってしまい、とてもわかりづらいコードになってしまいました。


#### ロジックを外に出さずに直接書いてしまった
organismsにロジックを直接書いてしまったことで、前半100行くらいCRUD処理に関わるコードが埋め尽くすようになっていました。
これもコードが見づらくなってしまった要因となっており、リファクタリングしようにも、各organismsのコンポーネント内で各々が書いたロジックがコンポーネントにへばりついているため、この状態でコンポーネントから切り離すのは骨の折れる作業となり断念しました。

さらに、organismsに書くとまずそうだなと気づき、開発終盤に追加が必要になったものはfunctionやhooksディレクトリを作って外に切り出しました。
これにより、organismsにロジックと外に切り出したロジックは時間経過以外の違いを持たず、これもなんとも分かりづらい要因となりました。


### 解決したいこと


そのため、整理すると以下のようなことを解決していきたいと思いました。

- 画面それぞれで微妙に異なる表示の出しわけをなるべくわかりやすく書いていきたい。
- コンポーネントから関数やhooksを分離させ、見通しをよくしたい
- 単体テストを導入しやすい単位にコンポーネントのサイズを最適化したい。



### 本来どうあるべきなのかを調べてみる


上記の課題を解決するために、改めてアトミックデザインでディレクトリ構成を考えるのならば、どのような形がよかったのかを調べ始めました。

さっそくググって最新の記事を探しているとアトミックデザインを辞めた発信が多いのに気づきました。

https://note.com/tabelog_frontend/n/n07b4077f5cf3

コードの稚拙さはあるものの、
アトミックデザインで苦労しているのは自分だけではないことがわかり、少し安心しました。笑

ハードルの高そうなアトミックデザインは一旦置いておき、改めてどのようなディレクトリ構成がメンテナンスしやすいのか情報を集めてみることにしました。

記事を探しても、なかなかうまく理解できなかったため、
すでにエンジニアとして働いている仲間に相談をしてみると、コロケーションというなるべく近くに配置する考え方があることを教えてもらいました。

https://zenn.dev/sakito/articles/af87061a5016e6

https://ja.reactjs.org/docs/faq-structure.html#grouping-by-features-or-routes

存在する機能やドメイン単位でディレクトリを分けていき、その機能に関わるhooksなどは近くに置くというものでした。

イメージとしては以下のようなものです。

```
src/
├─ features/
│  ├─ items/
│  │  ├─ components/
│  │  │  ├─ ItemCreate/
│  │  │  ├─ ItemEdit/
│  │  ├─ hooks/
│  │  ├─ functions/
│  ├─ partners/
├─ components/
│  ├─ button/
│  ├─ form/
├─ hooks/
├─ functions/

```


実際に書き始めましたが、対象範囲が限定されることで、types.tsから対象の型定義を見つける場合に、億劫になっていた気持ちや、対象のロジックを切り出すときに、名前や配置場所に悩むことが減りました。

これにより、少しだけコードが書きやすくなったような気がします。笑


まだまだ書き直し始めたばかりのため、やってみての振り返りはあまりできませんが、
いったんこれで進めてみて、しばらく進んだらまた振り返りをしてみようと思います。
RTX830にPuTTYを使ってログインする RTX830で遊ぼう その2

# PuTTYでRTX830につながるようにしてファームウェアも更新してみた
前回の記事はこちらからどうぞ

https://qiita.com/Motoki_Wada/items/1eea57a60222fc34dbf5

次回の記事

https://qiita.com/Motoki_Wada/items/d9ebfaad5c62de2ce5e6

では、早速本題に移っていこうと思います。。
準備としてまずPuTTYを下記のサイトからダウンロード。上が製作者のページで、下がダウンロードサイト。

https://www.putty.org/

https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html

インストールが終了したら、次はRTX830にTELNETで接続する設定をPuTTYに保存する。
まずはRTX830自身のIPアドレスを入力。
`192.168.100.254`を自分で設定したIPアドレスに読み替えて作業をしてください。

Host Nameの欄にIPアドレスを入力。
![WS000001.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271862/19a448af-e2de-1fd0-5a30-e27b5e9759b9.jpeg)

Portを`TELNET`のポート番号である`23`に変更する。
![WS000003.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271862/76275f74-404a-2407-a5fa-456975f24e2d.jpeg)

Saved Sessionsに任意の名前を入力。ここでは`RTX830`を入力しています。
入力後にSaveボタンを押す
![WS000004.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271862/579746ee-ccb8-93ca-421f-3f2ab7d43505.jpeg)

Default Settingsに先程入れた名前が出ていれば保存完了です。
![WS000006.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271862/91343b0b-8d30-3c2e-7be2-9f8b173145c2.jpeg)

次回以降は`RTX830`をダブルクリックすればRTX830にログインすることができるようになります。

## ターミナルの日本語表記の文字化けを直そう。
ただこの状態だと、RTX830とPuTTYの文字コードがSJISとUTF8で違いがあるため、日本語表記が文字化けを起こします。それをログインして修正します。
PuTTYのエンコード設定をSJISに変えたり、RTX830のエンコード設定をASCIIに変えたりすることでも直るようなのですが、今回は今後接続していくつもりのRaspberryPiやLINUXサーバで主流のエンコードであるUTF-8で文字化けを修正することにしました。
### 実際どういう設定をするのか？
まずは接続後に、ログインパスワードで認証を完了させる。
`Password:`の後ろにログインパスワードを入力してエンター。
![WS000002.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271862/9501df45-589b-c8ec-9218-bc8241b0c554.jpeg)
![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271862/95e8d561-9a27-16c3-799d-814b3c93a0a6.jpeg)

ログイン完了後に`administrator`とコンソールに入力し管理用パスワードを入力してエンター。
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271862/25903169-1127-2555-bcb2-f512b9b0f2de.jpeg)

`＞`マークが`＃`に変化したら`console character ja.utf8`と入力してエンター。
ちなみにコマンドをサイトからコピーした後、PuTTYのコンソール上で左クリックをすると、コピーした文章をペーストできます。
![4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271862/60bb888a-a89e-fd26-75a3-71818c019a1a.jpeg)


`save`でConfigを保存する。
![WS000048.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271862/a4383b50-9d41-a0c3-e449-92f8656c91be.jpeg)
以上で日本語表記で文字化けを起こさずにTELNETでログインできるようになりました。

次回はLAN上とは言え、平文でコンソールに接続し続けるのもセキュリティ上よろしくないのでRTX830にSSHで接続する設定を施そうと思います。
【朗報】Google Apps Script(GAS)のスクリプトエディタのサービスからGoogle Analytics Data APIを追加してGA4のデータが取得できるようになった件

うれしいお知らせです。グーグルアナリティクスの次世代版GA4のAPIを、Google Apps Script(GAS)でとても簡単に利用できるようになりました！

# GA4のAPI

GA4のデータをプログラミングなどで取得したい場合には、「Google Analytics Data API」から取得できます。

![20210418_auto_001.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365005/1f293895-b90a-534b-995f-eb9d250c1e4b.jpeg)


従来版GAのユニバーサルアナリティクス(UA)とは設計思想など大きく異なっている面もあり、まったく別物のAPIを利用する必要があります。

# 元々GCPからAPI有効化や権限設定が煩雑

GA4のAPIは、Google Cloud Platfrom(GCP)で設定必須でした。

Google Apps Script(GAS)から実行したい場合、GCP側の設定に加え、GASのプロジェクト紐づけやマニュフェストファイル(appsscript.json)を直接書き換えるなど、かなり面倒でした。

https://auto-worker.com/blog/?p=3250

※ユニバーサルアナリティクスのAPIはGASサービスから追加すれば、すぐに利用可能。

# GASのサービスにGA4のAPIが追加

あるとき、GASのエディタのサービスに、GA4のAPIが追加されているのを発見しました！

![20220525_auto_002.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365005/45d01f1f-0d13-cf8d-7584-e49b64f76db9.jpeg)


これで、UAと同じように超簡単にGASでAPIが実行できます。

# 3分でGASからGA4のデータを取得

GASからGA4のAPIにリクエストして、データを取得する手順を動画にしてみました。

<iframe width="560" height="315" src="https://www.youtube.com/embed/Yd1997LhYQ8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

サンプルコードの実行含め、**たった3分**でGA4からカンタンにデータが取得できます。

もうGCPでAPIの設定は必要ありません。

GAS側でのプロジェクト紐づけやマニフェストファイル書き換えも不要です。

GA4のデータをGASで取得したい方は、動画を参考にして実行してみてください。

**※ブログ記事でも解説しています↓**
https://auto-worker.com/blog/?p=5905

# 残念ながらAPIで取れない数値も多い…

GA4のAPIをGASからリクエストしやすくなったものの、取得できない指標・ディメンションも多いです。

これは、β版ということもありますが、GA4の開発スピードはUAに比べて遅め(リリース延期多発してた)です。

Googleのエンジニアが実装していくのを気長に待ちましょう。

# UAでのGASツールをGA4に置き換え準備

従来版UAではGASでAPIリクエストして、アクセスデータを取得していた方は多いと思います。

残念ながら、ユニバーサルアナリティクスはすでに来年2023年にサービス終了がアナウンス済みです。

残る猶予が1年となったため、GA4でも同様にGASから利用できるよう、置き換えを始めておきましょう。

# 参考リンク(再掲)

https://www.youtube.com/watch?v=Yd1997LhYQ8

https://auto-worker.com/blog/?p=5905

https://auto-worker.com/blog/?p=3250
野獣先輩を英語、中国語、韓国語に多言語化、グローバル淫夢

# 英語
Beast Senior

# 中国語 繁体字
野兽先辈

# 中国語 簡体字
野獸先辈

# 韓国語
야수 선배

メモ用。追加していきます。
RockyLinuxにRStudioServerをインストールする時にエラー->修復

## はじめに
rstudio-serverをRockyLinuxにインストールするときに、ちらっとはまったので記録。素人ながら調べてなんとかしましたが、これでいいのかはよくわかっていません。

こちらの記事を参考にインストールしました。素人の私には貴重な情報でしたありがとうございます。

https://qiita.com/purple_jp/items/e9e0fb5d72a33200da91

## RとRstudio-serverのインストール
```
# dnf install epel-release
# dnf config-manager --set-enabled powertools
sudo yum install R
```
powertoolsを入れないと、うまくいかないようでした。
そのあとは無事にRが動いてくれました。
Rstudio-serverのインストールはこちらのとおりで、

https://www.rstudio.com/products/rstudio/download-server/redhat-centos/

```
wget https://download2.rstudio.org/server/centos7/x86_64/rstudio-server-rhel-2022.02.2-485-x86_64.rpm
sudo yum install rstudio-server-rhel-2022.02.2-485-x86_64.rpm
```
これですんなり、かと思ったら、
/usr/lib/rstudio-server/bin/rserver: error while loading shared libraries: libssl.so.10: cannot open shared object file: No such file or directory
というよくわからないものが目に入りました。

まあでも、とりあえず行ってしまえとそのまま一番上の記事の通りに、firewallに8787のポートを開いてrstudio-serverの動作確認
```
sudo systemctl status rstudio-server
→
● rstudio-server.service - RStudio Server
   Loaded: loaded (/usr/lib/systemd/system/rstudio-server.service; enabled; vendor preset: disabled)
   Active: inactive (dead)
```
やっぱり動きませんね、さっきのエラーメッセージが出ます。

## 右往左往
こまったなと思って、右往左往していたら、rstudioのサポートページにたどり着いてみました。

https://support.rstudio.com/hc/en-us/articles/4412312023063-Error-While-Loading-Shared-Libraries

これでosのバージョンとrstudioのバージョンを調べなさいということでしたが、
```
grep PRETTY_NAME /etc/os-release
→PRETTY_NAME="Rocky Linux 8.6 (Green Obsidian)"
rstudio-server version
→2022.02.2+485 (Prairie Trillium) for CentOS 7
```
このサポートページには、違ったらだめじゃん、くらいな意味しかありませんでした...

## 修復へ

要はlibssl.so.10というライブラリが入っていないのが問題なのだろうと言うことで、どこかにあるんだろうかと探してみたら、

https://pkgs.org/download/libssl.so.10

というところにおいてあったので、そのままこのページのRockyLinuxのところをたどって、指示通りにインストール
```
 dnf install compat-openssl10
```
とインストールしてから
```
rstudio-server start
```


これで、とりあえず動きました。動くときに一度認証を求められます。
ブラウザにrstudioの画面が出るとうれしいですね。
素人なのでなにか間違いや危ないことをしていたら教えてください。

### 環境
VPS上の
NAME="Rocky Linux"
VERSION="8.6 (Green Obsidian)"

先人達の情報に感謝！
AutoScaling 使用時に暗号化ボリュームから作成したAMIイメージを使用した時の嵌り

いままでEBSボリュームを暗号化していませんでしたが、今回、暗号化してみました。

AutoScaling が AMI からインスタンスを起動しようとすると、起動はするものの、すぐに Terminate されてしまいます。
今回も、KMS 関連で嵌りました。

KMS のキーポリシーに以下を追記したら、直りました。

```
        {
            "Sid": "Allow service-linked role use of the customer managed key",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::<ACCOUNT_ID>:role/aws-service-role/autoscaling.amazonaws.com/AWSServiceRoleForAutoScaling"
            },
            "Action": [
                "kms:Encrypt",
                "kms:Decrypt",
                "kms:ReEncrypt*",
                "kms:GenerateDataKey*",
                "kms:DescribeKey"
            ],
            "Resource": "*"
        }
```

こちらは、ARN を追加しただけで大丈夫でした。

```
        {
            "Sid": "Allow attachment of persistent resources",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::<ACCOUNT_ID>:role/aws-service-role/autoscaling.amazonaws.com/AWSServiceRoleForAutoScaling",
                    ...(snip)...
                ]
            },
```

（参考）
https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/key-policy-requirements-EBS-encryption.html
ダイアログで日付設定

### 概要
パイソン初心者です。
処理を自動化する際に、日付をインプットに作業したいことがあったので、
日付入力をするダイアログを作成。
デフォルトで前営業日（祝日は考慮しない）を設定します。

```
import tkinter.simpledialog as simpledialog
import datetime

def pre_business_day(date):
    """ 前営業日を取得(祝日は考慮しない) """
    # 月曜日の場合
    if datetime.date.weekday(date) == 0 :
        pre = date - datetime.timedelta(days=3)
    # 日曜日の場合
    elif datetime.date.weekday(date) == 6 :
        pre = date - datetime.timedelta(days=2)
    else:
        pre = date-datetime.timedelta(days=1)
    return pre

initDate = pre_business_day(datetime.datetime.now())
inputDateText = simpledialog.askstring('日付入力', '入力日', initialvalue=format(initDate, '%Y/%m/%d'))
inputDate = datetime.datetime.strptime(inputDateText, '%Y/%m/%d')
print(inputDate)

```
RでEDAする際に、書き捨ての関数をGlobal環境ではなくPackage環境下にロードするようにする


# 目的

RでEDAをしていく中で、書き捨ての関数を書いていくと毎回実行するのが面倒になってくる。
また、Global環境も汚れてしまい、変数の表示が見づらくなる。
これらの問題について、作成した関数をpackage環境下にロードできるようにして解決する。

# 流れ

## パッケージ作成コマンド実行

```r
devtools::create(".")
```

以下のように怒られるが、パッケージを作るわけではないのですべてyesで。

```
New project '現在のフォルダ名' is nested inside an existing project './', which is rarely a good idea.
If this is unexpected, the here package has a function, `here::dr_here()` that reveals why './' is regarded as a project.
Do you want to create anyway?

1: Not now
2: Nope
3: Yes

Selection: 3
√ Setting active project to 'C:/Users/kyusque/Desktop/amex'
√ Creating 'R/'
√ Writing 'DESCRIPTION'
Package: amex
Title: What the Package Does (One Line, Title Case)
Version: 0.0.0.9000
Authors@R (parsed):
    * First Last <first.last@example.com> [aut, cre] (YOUR-ORCID-ID)
Description: What the package does (one paragraph).
License: `use_mit_license()`, `use_gpl3_license()` or friends to
    pick a license
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.1.2
√ Writing 'NAMESPACE'
Overwrite pre-existing file 'amex.Rproj'?

1: No way
2: Not now
3: Yup

Selection: 3
√ Writing 'amex.Rproj'
√ Adding '^amex\\.Rproj$' to '.Rbuildignore'
√ Adding '^\\.Rproj\\.user$' to '.Rbuildignore'
√ Setting active project to '<no active project>'
```

## Rフォルダにzzz.Rファイルを作成後、.onLoad(libname, pkgname)関数を追加

パッケージ作成の観点からはあまりよくないが、.onLoad(libname, pkgname)関数を作成して、よく使うパッケージをインポートしておくと、書き捨ての解析の際に便利。

```r:R/zzz.R
.onLoad <- function(libname, pkgname){
  pacman::p_load(
    tidyverse
    , caret
    , summarytools
    , data.table
    , RSQLite
    , DBI
    , dbplyr
    , doParallel
    , tictoc
  )
}

my_function_1 <- function(...){
...
}
```
## main.Rの先頭にdevtools::load_all(".")を追加

devtools::load_all(".")を実行すると、Rフォルダ内のファイルがすべて実行され、package環境内でロードされる。

```r:main.R
devtools::load_all(".")

...解析

my_function_1(...)

```

以上で、Global環境を汚さずに書き捨ての関数をロードできるようになる。
この後は、利用目的に合わせて適宜Rフォルダ内にファイルを作って関数を追記していくことで、main.Rをよりシンプルな形で書けるようになる。



# 参考

https://r-pkgs.org/index.html
【Tableau Data Saber挑戦記】3. Tableau Publicで使えるショートカットキーについて

command押しながらピルをドラッグ＆ドロップするとピルを複製できることを今日知りました。

まだ全然把握できてないですがtableauで使えるショートカットキーたくさんありますね。
便利だなと思ったので共有させていただきます。
ちなみに自分の環境はTableau Publicですので、Tableau Publicで使えるものを記載します。あと、Macです。

# 結構使うショートカットキー

- opt（alt） + shift + C/R →選択した項目を列/行に追加
- command + T →新しいシートの追加
- command + shift + P →パラメータの追加
- command + shift + A →アクションの追加
- opt押しながらピルを追加　→ピルのフィールドをその場で選べる（あとで選択しなくて済む）
- command押しながらピルをドラッグ＆ドロップ →ピルを複製

個人的にはcommand押しながらピルをドラッグ＆ドロップが最初何度やってもできずになんでなんだろうってずっと思ってました。
ポイントはドロップするまえに若干早くcommandボタンから指を動かしてしまっていたからでした。
ドロップし終わるまでcommand押し続けたらちゃんとできました。

# おしまい
ドラッグ＆ドロップで直感的に詳細な分析ができちゃうのがtableauのすごいところと思っていたのですが、ドラッグ＆ドロップすらしなくて色々できちゃうんだなと思うと本当に便利だなって思いました。
あまりtableauのショートカットキーってネットに記事が無いようで、あってもpublicでは使えないようだったりします。
自分が見た記事では計算フィールドを追加するショートカットキーがpublicだとできないっぽいので今後調べたいと思っています。

みなさんの使っている便利なショートカットキー、よかったら教えて下さい！

## 参考
自分が見た記事↓
https://note.com/h_yoshida/n/nde050d6c8207
https://help.tableau.com/current/pro/desktop/ja-jp/shortcut.htm
Chrome拡張機能 マニフェスト Ver.3 調査


# マニフェスト書き方
## 参考
https://qiita.com/shiro1212/items/12f0a767494a7b2ab0b3

## 実例
下記で一応動いたが
バックグランドに複数JSファイルが指定できない。つまり"jquery"が使えない
importScriptsも試してみたがエラーになる

```json
{  
    // Ver2
    //  "background": {
    //     "persistent": true,
    //     "scripts": ["js/jquery-3.2.1.min.js","js/background.js"]
    //  },

    "background": {
        "service_worker": "js/background.js",
        //　オプション
        "type": "module"
    },

    // Ver2
    // "browser_action": { 
    //     "default_icon": "img/stchan.jpg",
    //     "default_title": "すとすと", 
    //     "default_popup": "popup.html" 
    // },

    "action": {
        "default_icon": "img/stchan.jpg",
        "default_title": "すとすと", 
        "default_popup": "popup.html"
    },

    "content_scripts": [{
        "all_frames": true,
        "js": ["js/jquery-3.2.1.min.js","js/index.js"],
        "matches": [ "https://www.showroom-live.com/*" ],
        "run_at": "document_end"
    }],
    "icons": {
        "128": "img/stchan.jpg",
        "16": "img/stchan.jpg",
        "48": "img/stchan.jpg"
    }, 
    "description": "SHOWROOM便利ツール", 

    // "manifest_version": 2,
    "manifest_version": 3,

    "permissions": [ "storage", "notifications", "alarms", "tabs", "background" ],
    "name":"SHOWROOM すとすとツール",
    "short_name":"すとすと",
    "version":"2.3"
}
```
## 


# ソース修正
chrome.tabs.getAllInWindow が 使えなくなっているのでchrome.tabs.querに変更

```js
var tabOpen = function(openInfo){
	// console.log(openInfo);
	console.log('--tabOpen--');
	// chrome.tabs.getAllInWindow(function(t){
	// 	//現在tabの取得
	// 	for (var i = 0,len = t.length; i < len; i++) {
	// 		var d = t[i];
	// 		if (d.active) {
	// 			GVTB.tid = d.id;
	// 			// console.log('active');
	// 		}
	// 	}

	// 	//tabオープン
	// 	//2021GW対策
	// 	for (var i = 0; i < openInfo.length; i++) {chrome.tabs.create({url:openInfo[i]});}
	// 	// for (var i = 0; i < openInfo.length; i++) {chrome.tabs.create({url:openInfo[i].room_url_key});}

	// 	//actioveをもとに戻す
	// 	try {chrome.tabs.update(GVTB.tid, {active: true});} catch (e) {console.log('tabオープン時のactiveを戻す処理失敗');}
	// });

    chrome.tabs.query({},function(tabs){
        for (var i = 0,len = tabs.length; i < len; i++) {
			var d = tabs[i];
			if (d.active) {
				GVTB.tid = d.id;
			}
		}
		for (var i = 0; i < openInfo.length; i++) {chrome.tabs.create({url:openInfo[i]});}
		try {chrome.tabs.update(GVTB.tid, {active: true});} catch (e) {console.log('tabオープン時のactiveを戻す処理失敗');}

    })
```

## DOMParserがつかえない

```js
new DOMParser()
```


# いろいろ問題ある様子
https://retrorocket.biz/archives/manifest-v3

https://yamakisso.hatenablog.com/entry/2022/02/23/080234#service_worker%E3%81%8C%E5%8B%95%E4%BD%9C%E3%81%97%E3%81%AA%E3%81%84%E5%8E%9F%E5%9B%A0%E3%81%8C%E3%82%8F%E3%81%8B%E3%82%89%E3%81%9A%E3%83%87%E3%83%90%E3%83%83%E3%82%B0%E3%82%82%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84

# タイマーを使わない
[【Chrome拡張機能】Sevice Workerとは](https://www.satoshiiiblog.com/2022/05/07/%E3%80%90chrome%E6%8B%A1%E5%BC%B5%E6%A9%9F%E8%83%BD%E3%80%91sevice-worker%E3%81%A8%E3%81%AF%EF%BC%9F/)
UbuntuでWifiアダプターが認識されない

ubuntuを入れてデュアルブートできるようにした際、wifiのドライバが認識されない問題に遭遇した。
# 解決
### 1．windowsをシャットダウンする
windowsを使用している状態からパソコンを放置し、休止状態(≠スリープ)になってからlinuxを起動するとwifiのエラー発生するようです。
### 2．windows側の高速起動をoffにする
高速起動は、パソコンの周辺機器の情報を記録しておくことによって、次回の起動にかかる時間を短縮しているようです。このことがlinuxがwifiドライバを認識する際の妨げになっているのだと考えられます。
Web3.pyでThe field extraData is 97 bytes, but should be 32

どうやら、ミドルウェアをインストールしなければならない。

``` python:add
from web3.middleware import geth_poa_middleware
self.web3.middleware_onion.inject(geth_poa_middleware, layer=0)
```

``` python:sample.py
from web3 import Web3
from web3.middleware import geth_poa_middleware

url = "https://sample.com" #Infura、Alchemy、QuickNodeなどから取得
web3 = Web3(Web3.HTTPProvider(url))
web3.middleware_onion.inject(geth_poa_middleware, layer=0)
print(web3.eth.get_block('latest'))
```

https://web3py.readthedocs.io/en/stable/quickstart.html

https://zenn.dev/syucchin/articles/53ad44cb4d2458

https://www.alchemy.com/

https://github.com/blockchain-etl/ethereum-etl/issues/178
【Laravel】クラスが見つからないとエラーが出た時

## エラー内容

新しくクラスを作成したけど見つからないとエラーが出ました。

```
Class 'App\Services\DataExport' not found …（略）
```

名前空間、ファイル名を再確認してみたけど合ってる・・。

## 結論
以下のコマンドを実行することでエラー解消しました。

```
composer dump-autoload
```

composer dump-autoloadについて調べてたら長くなりそうなので
機会があれば記事にします。
swap領域の使用量が増える理由 

先日、あるLinuxサーバでメモリには空きがあるのにswap領域の使用量が徐々に増加して
いることに気づきました。
原因を調べるため、swapについて改めて勉強したのでその内容をここに残しておきます。

swap領域とは
--
そもそもswap領域とは何のために存在しているのか？
それは**メモリ不足を防いだり、メモリを有効に使うため**です。

仮想サーバの仮想メモリは実際の物理メモリ以上の容量をアプリに提供出来ます。
そうなれば当然、物理メモリ以上にメモリを使用する場合が出てきても不思議では
ありません。
そのような場合でもメモリ不足が起こらないように、メモリの内容をディスクに
移してメモリに空きを作る、この時ディスク上に作られる領域がswap領域です。

OSは仮想メモリが不足しそうになると、使用頻度の低いデータをディスクに書き出して
再び必要になれば読み込みます。
swap領域によりメモリ不足エラーを解消出来ますが、再度メモリに読み込む時は
当然ディスクからの読み込みなので処理に時間がかかってしまいます。

:::note warn
仮想メモリの仕様はOS毎に異なります。
swap領域を予約※せずにメモリを割り当てる仕様のものもありますが、swap領域が
確保出来ない場合もあります。
（※OSが予めswap領域に対して空きスペースを予約しておくこと）
実際に割り当てを行う場合は、しっかり確認の上で行ってください。
:::

メモリに空きがあるのにswap領域の使用量が増えている？
--
swap領域がメモリが不足しないための避難場所みたいな場所ということは分かりました。
では、メモリに空きがあるにも関わらずswap領域を使うのはなぜなのでしょう？

結論は、使われていない使用頻度の低いデータをswap領域に移動させるからです。

swap領域の説明で**メモリ不足を防ぐこと**と**メモリを有効に使うこと**の2つを記載しました。
今回は後者であるメモリの有効活用のための動きだったのです。


メモリを有効に使うとは何なのか。
頻繁に使うデータをメモリ上に乗せて処理を高速化させること、つまり**キャッシュ**です。
メモリに空きがあるからといって、いつまでも使われないデータをメモリに乗せているのは
容量の無駄遣いにしかなりません。
それならばswap領域に移してしまい、キャッシュとして使う領域をより大きく確保した方が
処理を高速化できるという訳です。

まとめ
--
swap領域は退避先です。
ですが、メモリ不足の時以外にも使われていることを覚えておきましょう。

※記載に誤りがある場合はご指摘をお願いします。

[参考]http://www.math.kobe-u.ac.jp/HOME/kodama/tips-free-memory.html

Linuxのswapパラメータについては下記が分かりやすかったです。
[参考]https://qiita.com/ikuwow/items/f0b4d1f509a0b83b5d7e
モトローラのケーブルモデム

某ケーブルテレビのモデムですが、なぜか設定画面がブラウザで開けてしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/0e4fc438-7fa9-9a50-1e02-12b8b5f62a5c.png)

ここにありますが、INTERNETにアクセスできない状態だと、DHCPでアドレスを配るので気がつきました。

どうも頻繁にルーターとモデムをリセットすると一定期間BANされて、ネット接続が切れてDHCPでプライベートアドレスを配るようです。

また我が家はブースターが入っていて、それの電源が入っていない状態で、モデムを上げちゃうとDHCPでプライベートアドレスが降ってきちゃいます。

自宅の口でVPNとかやってると、プライベートになっちゃうともちろん使えなくなるので、困りものです。
Haskell でプロジェクトを作成する方法（ stack を利用 ）

Haskell のプロジェクト作成を stack で行いました
Haskell のビルドツールは cabal との2択のようでしたが stack の方が後発とのことで stack を選びました

プロジェクトの作成とユニットテストができるところまでやっています

## 環境

- macOS 11.6
- zsh 5.8
- stack 2.7.5

## stack のインストール

stack はクロスプラットフォームの Haskell のビルドツールです
Haskell のコンパイラである GHC のダウンロードも stack がやってくれます

macOS の場合は brew を使って`brew install haskell-stack`でインストールできます
（他の OS や方法は[公式](https://docs.haskellstack.org/en/stable/install_and_upgrade/)を参照）



## プロジェクトの作成


インストールしたらプロジェクトを作成します

```zsh
stack new my-project
cd my-project
stack setup # 必要に応じて Haskell のコンパイラである GHC をダウンロードします
```

ここまででビルド、プログラムの実行ができるようになっています

```zsh
stack build
stack exec my-project-exe
# stack 2.7.5 では someFunc と表示される
```

`my-project-exe`というのは`stack new`で作られる`package.yaml`で設定されている名前です

```package.yaml
executables:
  my-project-exe: # ここの名前。このブロックを増やすことで実行コマンドを増やすことができる
    main:                Main.hs
    source-dirs:         app
```

## ユニットテストの作成

今回は hspec でテストを作成してみました
hunit というものもあるようですがなんとなく hspec の方が情報量が多い気がしました

まずは依存関係を追加します

```package.yaml
# 途中は省略しています
tests:
  my-project-test:
    dependencies:
    - hspec # これを追加
```

これでテストを書いて実行できるようになります

### stack が初期化したテストのソースに追記する場合

```test/Spec.hs
import Lib -- src/Lib.hs で hello 関数を export している場合
import Test.Hspec

main :: IO ()
main = hspec $ do
    describe "hoge" $ do
        it "fuga" $ do
            hello "world" `shouldBe` "hello world"
```

実行は`stack test`です

### モジュール毎にテストを書く場合

開発を進めていくとモジュール毎にファイル／フォルダを分けていくと思いますが
そのような時はこのように書けます

例として`src/Lib.hs`のテストをする`test/LibSpec.hs`を作った場合

```test/Spec.hs
import Test.Hspec
import qualified LibSpec

main = hspec spec

spec :: Spec
spec = do
    describe "LibSpec" LibSpec.spec -- 作ったモジュールのテストを実行
```

```test/LibSpec.hs
module LibSpec where

import Test.Hspec
import Lib

spec :: Spec
spec = do
    describe "hello world" $ do
        it "return hello with name" $ do
            hello "world" `shouldBe` "hello world"
```

`test/Spec.hs`が テストスイートになるイメージです
ただし、この場合モジュールが増える度に`test/Spec.hs`を更新する必要があります
hspec はこの部分が楽になるように[Automatic spec discovery](https://hspec.github.io/hspec-discover.html)という仕組みが準備されています

### Automatic spec discovery を使う場合

`test/Spec.hs`をこのように書いておくと hspec が自動でテストを探して実行してくれるようになります

```test/Spec.hs
{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
```

## テスト実行の tips

その他、テスト実行について次のことを知っていると便利だと思いました

- 更新を監視して自動でテスト実行したい
    - stack の`--file-watch`オプションをつける
    - 例：`stack test --file-watch`
- 修正中のモジュールだけをテスト実行したい
    - stack の`--test-arguments`オプション経由で hspec の`--match`オプションをつける
    - 例：`stack test --test-arguments "--match SomeLib"`

## 感想

プロジェクト作成してとりあえず実行まではそんなに苦労しなかったですが
テスト作ってサードパーティのライブラリインストールしてとかまでやろうとすると
haskell 初心者には難しかったと思います
特に情報を探すのに他の言語と比べて苦労があったと思います

最近の言語であったり利用者が多い言語はそういうところが簡単になってたり
情報がすぐ見つかってありがたいですね
（ go や python など）

## 参考文献

- [Stack](https://docs.haskellstack.org/en/stable/README/)
- [Hspec](https://hspec.github.io)
mrubyでoverflow

Ethernet switchのmibをbsnmpで監視していてmrubyで処理しているのですが、overflowすることがあったので、確認してみました。

ターゲットは32BitのFreeBSD/mipsで、mrubyは3.1です。

```
# /usr/local/bin/mruby
p 2147483648
codegen error:-:1: integer overflow
# /usr/local/bin/mruby
p 2147483647
2147483647
```

31ビット目は使えないようです。

適当な値でリセット(0)するか、30bitくらいでマスクするのが良さそうです。
2022/5/29主にITとかセキュリティの記事

【Excel中級者向け】マクロを覚えてデータ領域へキャリアアップ！6/14（火）無料セミナー「Excelで学ぶデータ集計～マクロ～」
https://prtimes.jp/main/html/rd/p/000002469.000003670.html

【オンデマンド視聴のご案内】 国内最大級の情報セキュリティ カンファレンス「Xpand Digital Japan 2022」(6/30まで)
https://www.kyodo.co.jp/pr/2022-05-27_3692686/

SOMPOが脆弱性対策に本腰　リスクを経営陣と早期共有(5/26)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020800017/051900721/

ライオンが歯磨き粉開発にMI活用　チューブへの充填性能をAIが予測(5/26)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020800017/051900723/

ショールーム型店舗閉店ラッシュ　隠れたアマゾンの深謀(5/25)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/052100111/051200074/

三井化学がDX人材育成を加速　研修に自社保有データを生かす(5/26)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020800017/051900722/

NTT海外事業は子会社主導へ　親が「認めた」NTTデータの実力(5/26)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020800017/051900720/

「霞が関流を脱した組織に」　デジタル庁に平井前大臣が提言(5/26)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020800017/051900719/

IT大手4社、22年3月期は明暗　3社減益もNTTデータは最高益(5/26)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020800017/051900718/

「認証時につながらない」「Web会議が途切れる」、iPhoneのWi-Fiトラブル対策(5/27)
https://xtech.nikkei.com/atcl/nxt/column/18/02072/052200003/
Docker + Next.js + Remote-Containers【VSCode】

## Docker + Next.js + Remote-Containers

```.devcontainer/devcontainer.json
{
  "name": "myapp-frontend",
  "dockerComposeFile": [
    "../docker-compose.yml",
    "./docker-compose.extend.yml"
  ],
  "service": "frontend",
  "workspaceFolder": "/myapp-frontend",
  "customizations": {
    "vscode": {
      "extensions": [
        "EditorConfig.EditorConfig",
        "dbaeumer.vscode-eslint",
        "esbenp.prettier-vscode",
        "VisualStudioExptTeam.vscodeintellicode",
        "arcanis.vscode-zipfs",
        "bradlc.vscode-tailwindcss"
      ]
    }
  }
}
```
```.devcontainer/Dockerfile
FROM node:16.15.0

ENV TZ=Asia/Tokyo
ARG USERNAME=node

RUN corepack enable npm
RUN SNIPPET="export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" \
  && mkdir /commandhistory \
  && touch /commandhistory/.bash_history \
  && chown -R ${USERNAME} /commandhistory \
  && echo ${SNIPPET} >> "/home/${USERNAME}/.bashrc"

USER ${USERNAME}
RUN mkdir -p /home/${USERNAME}/.vscode-server/extensions
WORKDIR /myapp-frontend

EXPOSE 3000
```
```.devcontainer/docker-compose.extend.yml
version: '3.9'
services:
  frontend:
    build:
      context: .
      dockerfile: ./.devcontainer/Dockerfile
    volumes:
      - sources:/myapp-frontend
      - bashlog:/bashlog
      - vscode-extensions:/home/node/.vscode-server/extensions
    command: /bin/sh -c "while sleep 1000; do :; done"
volumes:
  sources:
  bashlog:
  vscode-extensions:
```
```Dockerfile:/Dockerfile
FROM node:16.15.0

ENV TZ=Asia/Tokyo

WORKDIR /myapp-frontend
RUN corepack enable npm
USER node

EXPOSE 3000
CMD ["yarn", "dev"]

```

```/docker-compose.yml
version: '3.9'
services:
  frontend:
    build: .
    volumes:
      - .:/myapp-frontend
    environment:
      NODE_ENV: development
    ports:
      - 3000:3000
      - 9229:9229
```
特定のリストから別のリストに存在する要素を全て取り除いた

# 課題
リストAからリストBに含まれる要素を除きたい

# 検索結果
リスト中の重複削除のみだった

# 検索ワード
list 重複削除

# 参考資料
https://codechacha.com/ja/python-list-remove-duplicates/
https://note.nkmk.me/python-list-unique-duplicate/

# コード
```python:delete_reject_list.py
def unique_list_make(input_base_list, input_reject_list):
    # リストA中の重複削除
    # set()を使うと高速化できるが、リストの順番が変わるためdictを使用した
    base_list = list(dict.fromkeys(input_base_list))
    # リストB中の重複削除
    reject_list = list(dict.fromkeys(input_reject_list))

    # リストAからリストBをfor文で削除
    result = []

    for i in base_list:
        if i not in reject_list:
            result.append(i)
    
    return result

```

# 実行結果
```python:
#入力
a = [1,2,3]
b = [3,4,5]

unique_list_make(a,b)

#出力
[1,2]
```
MacでうっかりデフォルトのメールアプリがOutlook on the Web になってしまったので復旧した話

# 状況
* macOS Montery(12.4)での話題
* Mail.appにて maito: なリンクをクリックすると、Mail.appではなく、Chromeで[OutLook on the Web](https://outlook.office.com/)が開くようになった
* 直前に[Microsoft 365](https://portal.office.com/)にてOutlookを試して時に、たしかに何か関連するメッセージが出ていた。その時は「設定が可能になった」と思い込んでいた。まさか設定されているとは...。
* macOS上ではOutlookはアプリは使っていない

# 確認事項
* macOS上で mailto: のリンクをクリックした時の挙動は設定しているのか? (今回はChromeが起動した)
* Chrome 上で mailto: のリンクの設定はどこなのか?

# 設定
## macOS上で mailto: のリンクの設定
macOSでのデフォルトのメールアプリの設定ということですが、次のWebページに情報がありました。

* [Mac でデフォルトの Web ブラウザやメール App を変更する](https://support.apple.com/ja-jp/HT201607)

引用すると、以下のように書いてありました。

> 1. 使いたいメール App がインストールされていることを確認します。Web ブラウザを使ってメールをチェックすることもできますが (Web メール)、Web ブラウザはメール App ではありません。
> 2. メール App を開きます。
> 3. 「メール」>「環境設定」の順に選択し、「一般」をクリックします。
> 4. 「デフォルトメールソフト」メニューから、使いたいメール App を選択します。

確認すると、「デフォルトメールソフト」が以下のように「Google Chrome」が設定されていました。
![mailの環境設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9432/f3e7f829-4f4c-9887-3a2c-282936752e51.png)

これでChromeが起動する理由がわかりました。
この「デフォルトメールソフト」の設定を、macOS標準の「メール」に選択しなおせば解決です。

しかし、ChromeではどのようにOutlook(OutLook on the Web)が起動したかが気になります。

##  Chrome 上で mailto: のリンクの設定
[Gmail をデフォルトのメール プログラムとして設定する](https://support.google.com/a/users/answer/9308783?hl=ja)
によると、以下の手順でGmailの設定はできるようです。

> 1. Chrome ブラウザを開き、その他アイコン 次に [設定] をクリックします。
> 2. [プライバシーとセキュリティ] に移動します。
> 3. [サイトの設定] で右矢印アイコン  をクリックします。
> 4. [その他の権限] までスクロールして、展開アイコン をクリックします。
> 5. [ハンドラ] の横にある右矢印アイコン  をクリックします。
> 6. 上部にある [サイトからのプロトコルのデフォルト ハンドラとしての登録要求を許可する（推奨）] がオンになっていることを確認します。
> 注: [ブロック中] までスクロールし、mail.google.com がリストにないことを確認します。
> 7. Chrome ブラウザのアドレスバーに「mail.google.com」と入力します。
> 8. サービス ハンドラ アイコン サービス ハンドラ をクリックします。
> 9. [許可] 次に [完了] をクリックします。

以上を参考にOutlookの設定がされていないか確認してみました。
実際には、上記の手順3の「その他の極限」で、「プロトコルハンドラ」の設定項目を発見しました。

![chromeの設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9432/52cc957b-d997-d8fa-66c4-aab92983322a.png)

確かに「outlook.office.com」が設定されていました。
こちらを削除すれば Outlook へはアクセスしなくなります。

今回はChrome上ではgmailへアクセスして欲しいので、上記の手順6以降を改めて設定し直しました。
Oracle-LinuxでApacheを使えるようにする

# サーバの設定
前回まででインフラ部分は完成したので次にサーバの中身を設定していきます。
## Linuxのバージョン確認
まず、Linuxのバージョンを確認してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367692/21f86bc2-7dd4-6cb4-e7cd-ea16d7bbf242.png)
Oracle-Linux8はRHEL8.5なんですね。
## ストレージ容量
次にAmpereシェイプデフォルトのストレージ47GBのうちユーザーが使えるのがどれくらいのサイズか確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367692/4a039160-9bf9-64b7-655d-1651cfc823a5.png)
/（ルート）にマウントされているストレージとして28GB使えるようです。
私に取っては十分です。

## ツール
使いやすいようにいくつかツールとかを入れていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367692/6c3d7816-26f5-7db5-ba23-fbbc2c9332b6.png)
私は最初にUNIXを触ったときにNEmacsから入っているのでviよりもemacs派ですｗ
あと、tcshも入れました。
この辺は好みの問題なので使わなくても全く問題ありません。
## タイムゾーンの設定
Oracle-LinuxはデフォルトでUTCになっているようです。
そこでJSTに変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367692/cd400317-57d2-8e9a-f553-b8d6123da061.png)
これで無事にJSTになりました。
1行目はオリジナルファイルのバックアップです。
運用の経験のある方は必ずこのように切り戻しができるようにバックアップを作成すると思いますが、プライベートで触るときもバックアップを取る癖がつきました。

## selinuxの無効化
いろいろとやっかいなselinuxは無効化しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367692/b29c9fbc-daad-5429-f19a-42569aacd97e.png)
　#4で設定状況を確認し、エディタで設定ファイルを開いて設定変更しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367692/0c4c877a-3a13-cac8-ee47-318131c4fba2.png)
「SELINUX=disabled」に変更しました。
再起動で設定が反映されるので再起動します。

```
# reboot
```
再起動後に設定を確認してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367692/1ce2cf81-a729-da67-ccca-557c880e79f5.png)
**Disabled**に変わっていますね。

## Firewallの無効化
Firewallを無効化するのに抵抗のある方もいるかも知れませんが、まずはサービスにアクセスできるのを確認するために無効化します。
```
　# systemctl stop firewall
```

## Apacheのインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367692/ff3d768d-9a00-5fcb-e015-94c3f886843c.png)
yumって簡単でいいですよね。
昔はmakeするのにIMakeFileをいじったりCCのバージョンはどれを使えば良いのかわからなかったりして結構大変でしたが、今は一発で入ってとても便利です。

Apacheはデフォルトで/var/www/htmlがDocumentRootになっていますが、cgiは使えないようになっていたと思いますので設定を一部変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367692/bfb8e6ce-b371-5fb2-3dea-bbbfb8386d3f.png)
この部分のコメントを外します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367692/712d8859-8c41-d65a-3427-a82839479597.png)
あとは対象のディレクトリを指定してExecCGI属性を指定してあげる必要がありますが、そこはcgiを移行する時に設定しようと思います。

## Apache起動
この状態でApacheを立ち上げてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367692/fb929ffc-b7eb-0417-cb7d-dad20879cd5f.png)
エラー無く立ち上がったようです。

早速、ブラウザでつなげてみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367692/1a71c090-a45b-43c4-9a54-6d4aa67887b2.png)
無事にApacheにつながりました。

サービスとしても登録しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367692/12736e50-6769-685b-d350-06df9b83ac73.png)

以上、今回はHTTPサーバにつながるところまで出来上がりました。
次回は、実際にホスティングサービスで動いているCGIプログラムをOCIへ移行して動かしてみます。
Gatsbyのディレクトリ構成



プログラミングを始めたばかりの初心者です💭
”React”ベースのフレームワークである<font color="red">**"Gatsby"**</font>を利用して、Webサイトを作成してみました！
ここでは、Gatsbyのディレクトリ構成について、学んだことを書き留めておきます👀💓
# :star2:ディレクトリ構成:star2:

- **.cache**
データを一時的に保存しておく場所。
ビルド時に生成される。特に触らない。

- **package.json**
npmで管理するパッケージ情報を記載したファイル。
特に触らない。

- **package-lock.json**
``package.json``の情報を詳しく記述したファイル。
特に触らない。


- **node_modules**
``npm``や``yarn``を用いてインストールしたパッケージが保存されるディレクトリ先のこと。
ここには、``package.json``で指定した中身が入っている。




- **public**
公開されるディレクトリのこと。
ビルド時に生成される。特に触らない。


- **src**
URLに対応するReactコンポーネントを定義するディレクトリ。
開発時には、ソースコードをここに書いていく。

- **.gitignore**
Gitで管理しないファイルを指定することができるファイル。


- **gatsby_config.js**
Gatsby全体の構成を記述するファイル。
サイトのメタデータ、プラグイン、およびその他の一般的な構成を定義する。
JavaScriptまたはTypeScriptでファイルを作成できる。