OmniAICreator/Qiita-1.07M huggingface dataset:
firestoreを使ったswiftのCodableを作る時に使う@DocumentIdに隠された便利機能を見つけてしまった

こんにちは。[virapture株式会社](https://virapture.com)でCEOしながら[ラグナロク株式会社](https://ragna-rock.com)でもCKOとして働いている[もぐめっと](https://mogmet.com)です。

本日はswiftとFirestoreで使う@DocumentIdについて皆が知らないであろう機能を発見したので共有します。

## @DocumentIDとは？

そもそも@DocumentIDってなんやねんというお話をすると、Decodeするときに自動的にidを付加するという便利機能になります。

```swift
import FirebaseFirestoreSwift

struct UserModel: Codable {
    @DocumentID var documentID: String?
    let username: String
}

```

```swift
Firestore.firestore().document("users/mogmet").getDocument { snapshot, error in
    let user = try? snapshot?.data(as: UserModel.self, with: .estimate)
    //これだけでuser.documentIDにdocumentIdが入っている
}
```

参考↓

https://qiita.com/jyu0414/items/bf4661e2027fc30a29d0

## 隠された便利機能ってなに？

もぐめっとは、名前からして**DocumentID**とあるのでIDしか付与できないと思ってました。
しかし、DocumentIDの処理をみると、DocumentReferenceを値として持ってるように見えました。

そのため、ためしにこう書いてみました。

```swift
import FirebaseFirestoreSwift

struct UserModel: Codable {
    @DocumentID var documentID: String?
    @DocumentID var reference: DocumentReference?
    let username: String
}
```

すると、**DocumentReferenceの値もちゃんと保管されていることを確認できました！！！**
これはすごい！便利！！！

### 補足

ちなみにこういう書き方もできます。

```swift
Firestore.firestore().document("users/mogmet").getDocument { snapshot, error in
    let user = try? Firestore.Decoder().decode(UserModel.self, from: snapshot.data(with: .estimate), in: snapshot.reference)
}
```

この場合はin句でreferenceを入れてあげないと@DocumentIDが動かないので注意ください。
（でも最初の書き方のほうがシンプルなのでconverterを指定しないかぎりはこっちの書き方は使わなそう）

## まとめ

@DocumentIDはDocumentReferenceもいい感じに保管してくれる便利機能でした！！

最後に、[ワンナイト人狼オンライン](https://online.1nite-jinro.com/link/blog)というゲームを作ってます！よかったら遊んでね！

https://online.1nite-jinro.com/link/blog

他にも[Camecon](https://camecon.me/)や[Offcha](https://offcha.com/)といったサービスも作ってるのでよかったら使ってね！

https://camecon.me/

https://offcha.com/

また、チームビルディングや技術顧問、Firebaseの設計やアドバイスといったお話も受け付けてますので御用の方は弊社までお問い合わせください。

https://virapture.com/

ラグナロクでもエンジニアやデザイナーのメンバーを募集しています！！楽しくぶち上げたい人はぜひお話ししましょう！！

https://ragna-rock.com
ちゃんとしたリモートワークで生きていく


## はじめに

コロナ禍になってから週1、週2は出社していましたが、フルリモート可になってから1年6ヶ月ほど出社していないことに気が付きました。
リモートワークの良いところや悪いところなど色々と身を持って体験したので、ここで自分なりの「ちゃんとしたリモートワークの生き方」を定義しておきます。
リモートワークをサバイブする方々、自分はこうしてるとか意見があったらコメントください。

## ちゃんと朝起きる
めちゃくちゃ普通のことですが、**毎朝決まった時間に起きる**ようにしています。
リモート当初は朝起きる時間がやや遅くなりがちでしたが、今まで出社することに使っていた時間を二度寝に使うのってなんだか勿体無いと思うようになりました。
リモートだからこそ早く起きて、仕事までの時間を有意義に過ごすようにしています。

## 服を着替える
これも普通のことですが、ちゃんと朝起きたら**まず服を着替えます。**
あるあるだとは思いますが、リモートだと服装緩くなりませんか..？笑
部屋着すぎると逆にオンからオフへの切り替えが難しいなと感じることがありました。
出社する時と同じ感覚でそのまま外へ出かけていけるような服装を心がけてます。

## 身なりを整える
**伸びる髪、髭、眉毛、鼻毛。**
圧倒的に人と会うことが少なくなるので、身なりに対しての意識が低下していきます。
定期的に身なりを整える習慣をつけないとヤバイと感じるようになりました。
ヘアカットなどタスク化してカレンダーに登録するなどして対処しています。

## 朝活する
出社する時間が浮くので、何かしらの朝活をしています。
朝は一番脳が元気なので、インプットよりはアウトプット寄りになるように意識しています。
今一番興味のある技術や、仕事をしている中でわからんってなったものを調べたり、何かしらコードを書いたりしています。
ただそこまでルールは設けていなくて、朝起きて何かしら学習して1ミリでも強くなればそれでいいと思っています。人と比べない。けど昨日の自分とは比べる。継続が大事。
社内Slackに朝活チャンネルを爆誕させ、朝活仲間と朝活報告しあうことで良い刺激になっています。

## WEBカメラを買う
WEBカメラはリモートで唯一ビジュアルを表現できるツールです。
PC内蔵のカメラだと、目線が見下ろす形になるのと、画質もあんまり良くありません。
PC内蔵のカメラよりも見た目が良く写りますし、外部ディスプレイにつけると目線的にも自然な感じになるのでオススメです。
個人的にはAnker PowerConf C300を購入して満足しています。

https://www.ankerjapan.com/products/a3361

## ミーティングではマイクを使う
ミーティングではWEBカメラとマイクが相手に情報を与える全てなので、品質は高めておきたいです。
PCやWEBカメラの内蔵マイクだと、誰かが話している最中の声を拾って出力してしまうことが結構多いです。
個人的にはAirPods Proを使用しています。

https://www.apple.com/jp/airpods-pro/

## 通信環境を整える
リモートは**通信環境が命**です。
通信速度が遅いとミーティングの会話でディレイしたり、フリーズしたり、別の世界線に吸い込まれたりしてしまいます。
個人的にはIPv6対応のプロバイダと契約し、Wi-Fi6対応ルーターを使うことで速度と安定性が向上しました。（子機もWi-Fi6に対応している必要があります）
IPv6とWi-Fiの通信規格について話すと長くなるので割愛しますが、これからリモートする方はポケットWi-Fiは使わない、古いルーターは買い換える、ネット無料物件はやめておくのがオススメです。

## 快適なリモート環境に妥協しない

ディスプレイ、デスク、椅子など、一生終わらないリモート環境構築沼が待っています。
特に椅子は健康面に直結するので、自己投資だと思って10万クラスの物を買ってもいいと思います。
リモート環境構築は結構沼なので「デスク狭いな..」とか「椅子に座ると腰痛い..」などストレスを感じる部分を解消していく感じでいいと思います。
デスクは「かなでもの」の160cmx70cm、チェアはエルゴヒューマンプロを使っていますが、調子良いです。（高かった...）

https://kanademono.design/collections/kanademono-table-desk/products/tbl-k03-bk

https://www.ergohuman.jp/product/ergohuman_pro.php

## ジムに行って筋トレする
とんでもないくらい運動量が落ちるので体型維持のためには必須になってきます。
ジムに行くと筋トレするしかないので、仕事が終わったらとりあえずウェアに着替えます。
「ジム行くの面倒くさいな..」と脳が感じる前に家を出ます。
筋トレすると全身の血流が良くなるので肩こり解消にも効果があるみたいです（実体験）
さらに筋肉がつくと基礎代謝が上がるので、たくさん食べても太りにくいバディーもGETできます。筋トレ最強。
筋トレや食事などの知識はSho Fitnessで吸収しています。

https://www.youtube.com/c/ShoFitnessch

## 散歩する
散歩は脳のリフレッシュに加えて、シンプルに歩くという動作が健康的で体に良いです。
リモートだと家にいる時間が増えるので、気分転換にもなります。
朝に太陽を浴びながら散歩すると気持ちが良いですし、セロトニンが分泌されて睡眠の質が向上するのでオススメです。

## まとめ

- 朝決まった時間に起きる
- 服を着替える
- 身なりを整える
- 朝活する
- WEBカメラを買う
- イヤホンマイクを買う
- 通信環境を整える
- リモート環境に妥協しない
- ジムに行って筋トレする
- 散歩する
【AWS】HomebrewにAWSCLIをインストールするには？

# はじめに
実際の業務でHomebrewにAWSCLIを準備する機会がありました。
その準備をする際にやっていた手順について書きたいと思います。

# AWSCLIとは？
AWSCLIとは、AWSサービスをコマンドラインで管理するためのツールになります。

以下の各OSにインストールをして、使用することが可能です。

- Linux
- macOS
- Windows

今回は、macOSのHomebrewにAWSCLIをインストールする手順についてご紹介します。

# 前提

|  項目 |  内容  |
| ---- | ---- |
|  OS  |  macOS Monterey バージョン 12.3.1  |
|  Homebrew  |  3.4.10  |

```zsh:Homebrew
ma-sato@satsuton ~ % brew -v
Homebrew 3.4.10
Homebrew/homebrew-core (git revision e657c47b69a; last commit 2022-05-05)
Homebrew/homebrew-cask (git revision fabc7c09d9; last commit 2022-05-06)
ma-sato@satsuton ~ %
```

:::note info
今回は、Homebrewが入っている前提の手順になります。
また、事前に`brew update`も実施していることも前提です。
:::

# 作業手順

## 1.AWSCLIインストール

- awscliのパッケージが存在するか確認

```zsh:コマンド
brew search awscli
```

```zsh:実行例
ma-sato@satsuton ~ % brew search awscli
==> Formulae
awscli                     awscli@1                   ascii
ma-sato@satsuton ~ %
```
→`awscli`が存在することを確認。

- 以下のコマンドを用いて、AWSCLIをインストールする。

```zsh:コマンド
brew install awscli
```

```zsh:実行例
ma-sato@satsuton ~ % brew install awscli
==> Downloading https://ghcr.io/v2/homebrew/core/awscli/manifests/2.6.3
Already downloaded: /Users/ma-sato/Library/Caches/Homebrew/downloads/0f84bd36c7765fa5625cc1bf05d30c8e9f90c22d73ba8e33d574a1dbcc143958--awscli-2.6.3.bottle_manifest.json
==> Downloading https://ghcr.io/v2/homebrew/core/awscli/blobs/sha256:1c1a7f7b3ad
Already downloaded: /Users/ma-sato/Library/Caches/Homebrew/downloads/1df020e2e07522c7baf14daa664d23943d3110883fdf569811fa6b3636748aa3--awscli--2.6.3.monterey.bottle.tar.gz
==> Pouring awscli--2.6.3.monterey.bottle.tar.gz
==> Caveats
The "examples" directory has been installed to:
  /usr/local/share/awscli/examples

zsh completions and functions have been installed to:
  /usr/local/share/zsh/site-functions
==> Summary
🍺  /usr/local/Cellar/awscli/2.6.3: 12,628 files, 101.4MB
==> Running `brew cleanup awscli`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
ma-sato@satsuton ~ %
```

- バージョン確認

```zsh:コマンド
aws --version
```

```zsh:実行例
ma-sato@satsuton ~ % aws --version
aws-cli/2.6.3 Python/3.9.12 Darwin/21.4.0 source/x86_64 prompt/off
ma-sato@satsuton ~ %
```

- パス確認

```zsh:コマンド
which aws-cli
```

```zsh:実行例
ma-sato@satsuton ~ % which aws
/usr/local/bin/aws
ma-sato@satsuton ~ %
```

# さいごに
かなり基礎的な内容になってしましましたが、今後はAWSCLIを使用して業務で実際にやったことについてもしっかり記事を書いていきます。

# 参考記事
https://aws.amazon.com/jp/cli/

https://skume.net/entry/2021/10/03/173329
【備忘録】Ardupilot で障害物検出を行う（その2）


Ardupilot (rover)でGY-US42（ソナー）を用いて障害物検出の機能を追加したのでその方法を記載する。
その1で障害物検知⇒停止ができたので回避行動の設定を行った。

前回の記事
https://qiita.com/Fumi_Saito/items/c9c2f735dc9351b5e5e7

## 検出条件
・　検出距離　：　1m
・　回避方法　：　シンプルモード(回避)

## パラメータ設定
センサーの種類を距離計（RangeFinder）に、センサーの方向を前方に設定する。
回避行動を取るときの最高速、加速度を入れる。

※ 220523 追記
【注意】
　・AVOID_ACCEL_MAX は停止時の加速度を調整するパラメータなので値が小さいと反応が鈍くなります
　・AVOID_MARGIN は停止時に慣性で障害物と衝突しない距離を設定してください

|パラメータ|値|解説|
|-|-|-|
|AVOID_ENABLE|7|回避入力ソース ⇒ すべて使う|
|AVOID_MARGIN|1|回避距離マージン ⇒ 1m|
|AVOID_BACKUP_SPD|0.3|障害物から離れる最高速 ⇒ 0.3m/s（1km/h）|
|AVOID_ACCEL_MAX|3 ~~0.3~~|障害物から離れる際の加速度 ⇒ 3 ~~0.3~~ m/s/s（ ~~1~~ km/h/s）|
|PRX_TYPE|4|接続されている近接センサーの種類 ⇒ RangeFinder|
|RNGFND1_TYPE|2|接続している距離計の種類 ⇒ MaxbotixI2C|
|RNGFND1_ORIENT|0|接続している距離計の方向 ⇒ 前方|
|RNGFND1_MAX_CM|400|接続している距離計の最大距離 ⇒ 4m|
|RNGFND1_MIN_CM|0.2|接続している距離計の最小距離 ⇒ 0.2ｍ|

## 動作確認
車輪が回転しないようにしてセンサーに障害物を接近させ、後退したら遠ざける。
以下の様になっていればOK

① 障害物検知⇒停止
Sonar Range が 1.0ｍ以下になるとCH3 OUT  が 1500.00 になる
![Snapshot_16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064722/f6f293a6-e328-a847-0aad-368ad96b0605.png)

② 後退
停止状態から数秒後にバック開始 CH3 OUT  が 1500.00 以上に変化
![Snapshot_17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064722/0eacb2c3-f240-a351-3dc8-c45752a1716a.png)

③ 距離マージン確保⇒停止
Sonar Range が 1.0ｍ以上になった時に停止
![Snapshot_18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064722/ca9a5e16-193a-6fd6-a8b0-2c86a479a22c.png)

④ 前進
停止状態から数秒後前進開始 CH3 OUT  が 1500.00 以下に変化 
![Snapshot_21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064722/26d8083d-34f3-3b37-1054-2ac794ca3952.png)

## 参考
https://ardupilot.org/rover/docs/common-simple-object-avoidance.html
https://qiita.com/srs/items/eb50af277a29a129a5f9
100日後くらいに個人開発するぞ！day024

## 今日からHTML＆CSS中級編を復習してみた！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2632394/9e1bcfc0-909d-9430-2a0e-44c9aaec5875.png)

## 今日のアウトプット

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2632394/94e9c34e-bf9f-4c92-da45-bc7988ad5d22.png)



## 今日の備忘録

### ヘッダータグとフッタータグ
 - ヘッダーとフッターのタグは非常によく使われるためHTMLには`<header>`タグと`<footer>`タグが存在する
 - `<header>`タグと`<footer>`タグを使うことで`<div>`とクラス名を用いる方法は不要になる
    - 例：`<div>`とクラス名を用いる方法
        - `<input type="submit">`
        - `<div class="header"></div>`
        - `<div class="main"></div>`
        - `<div class="footer"></div>`
    - 例：`<header>`タグと`<footer>`タグを用いる方法
        - `<header></header>`
        - `<div class="main"></div>`
        - `<footer></footer>`



### 背景画像を指定する方法
- CSSで背景画像を指定するにはbackground-imageプロパティを用いる
    - 定型文：`background-image: url(画像のURL);`

### 背景画像の大きさを指定する方法
- `background-image`で指定された背景画像は表示範囲を埋め尽くすまで繰り返し表示される性質がある
- `background-size: cover;`を指定すると1枚の画像で表示範囲を埋め尽くすように画像の大きさが拡大縮小する


### 要素を中央に配置する方法
- 中央に配置するためにはmarginの左右にautoを指定する必要がある
    - 例：`margin:0 auto;`
- marginにautoを指定する場合は必ずwidthを併せて指定する
- 上下のmarginにautoを指定することはできない

### 要素を透過させる方法
- 要素を透明にするにはopacityプロパティを使う
    - 例：`opacity:0.5;`
- 透明度は完全に透明「0.0」から完全に不透明「1.0」の間で指定します。


### 文字の間隔を指定する方法
- letter-spacingプロパティを用いることで文字の間隔を指定できる
    - 例：`letter-spacing：10px；`

### インライン要素でwidthやheightを指定する方法
- `<a>`タグなどインライン要素はwidth/height/marginを指定できない
- インラインブロック要素を用いるとインライン要素でもwidth/height/marginを指定できる
- displayプロパティを使うとインラインブロック要素に変更できる
    - 例：`display:inline-block;`
- displayプロパティでは他の要素を指定することができる
    - block（ブロック要素）
    - inline-block（インラインブロック要素）
    - inline（インライン要素）

### 複数のクラスを指定する方法
- 複数のクラスを細かく指定したい場合はクラス名を半角スペースで区切ることで指定することができる
    - 例：クラス名を半角スペースで区切る（HTML）
        - `<div class="button blue"></div>`
        - `<div class="button red"></div>`
    - 例：区切られたクラス名を一部だけ指定する（CSS）
        - `.button{font-size:10px;}`
        - `.blue{color:blue;}`
        - `.red{color:red;}`
【rails】ゲストユーザー機能の実装

ポートフォリオ作成したけど、なんか忘れてる・・
そうだ、ゲストユーザー機能！
ということで備忘録として簡単に実装方法を記載します。

# 前提
・ユーザー登録機能（devise）が実装されている

# ルーティングの設定
`guest_sign_in`アクションはこのあとコントローラーで定義します。
```config/routes.rb
post 'homes/guest_sign_in', to: 'homes#new_guest'
```

# アクションの定義
以下にて`guest_sign_in`を定義します。

１.`find_or_create_by`でゲストユーザーがあれば取り出す、無ければ作成する　にする
2. パスワードはセキュリティの関係で`SecureRandom.urlsafe_base64`のランダムで作成できるよう設定
3. railsが用意してる`sign_in`メソッドを利用して、先ほど定義した`user`をログインさせる

```controllers/homes_controller.rb
class HomesController < ApplicationController
  def new_guest
    user = User.find_or_create_by(email: 'guest@example.com') do |user|
        user.password = SecureRandom.urlsafe_base64 
    end
    sign_in user
    redirect_to root_path, notice: 'ゲストユーザーとしてログインしました。'
  end
end
```

# リンクボタンの作成
あとはviewでボタンを作成すれば完成。
```views/homes/index.html.haml
%p= link_to 'ゲストログイン（閲覧用）', homes_guest_sign_in_path, method: :post
```

# 参考資料
・[deviseの公式GitHub](https://github.com/heartcombo/devise)
・[Railsドキュメント（find_create_by）](https://railsdoc.com/page/find_or_create_by)
・[簡単ログイン・ゲストログイン機能の実装方法（ポートフォリオ用）](https://qiita.com/take18k_tech/items/35f9b5883f5be4c6e104)
Rustのtokio-postgresでストアードプロシージャのデバッグが楽になる方法

# はじめに
ストアードプロシージャの開発をしていると、実行時に変数の内容などをプリントしたくなることがあります。
PostgreSQLではRAISEを使うことでプリントすることができます。

しかしpsqlでは簡単にみられるRAISEですがRustで実行時に見るためには一工夫が必要になります。

# ストアードプロシージャ
```sql
DROP TYPE IF EXISTS type_my_get_test CASCADE;
CREATE TYPE type_my_get_test AS (
  id BIGINT
);

CREATE OR REPLACE FUNCTION my_get_test (
) RETURNS SETOF type_my_get_test AS $FUNCTION$
DECLARE
BEGIN
  RAISE INFO SQLSTATE 'U0001' USING MESSAGE = 'aaa,bbb,ccc';
  RETURN QUERY SELECT
    10::BIGINT
  ;
END;
$FUNCTION$ LANGUAGE plpgsql;
```

# Rust
```rust:Cargo.toml
[package]
name = "playground"
version = "0.1.0"
edition = "2021"

[dependencies]
tokio = { version = "1", features = ["full"] }
tokio-postgres = "0.7.6"
env_logger = "0.9.0"

```

```rust:main.rs
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    env_logger::init();

    let (client, connection) = tokio_postgres::connect(
        "host=db user=user password=pass dbname=web",
        tokio_postgres::NoTls,
    )
    .await?;

    tokio::spawn(async move {
        if let Err(e) = connection.await {
            eprintln!("connection error: {}", e);
        }
    });

    let res = client.query("select * from my_get_test()", &[]).await?;
    println!("{:?}", res);

    Ok(())
}
```

# 結果
```
RUST_LOG=info cargo run
[2022-05-12T23:10:21Z INFO  tokio_postgres::connection] INFO: aaa,bbb,ccc
[Row { columns: [Column { name: "id", type: Int8 }] }]
```

# まとめ
一工夫とはenv_logger::init();を入れることです。
なんとかRAISEの内容が見られないかと、tokio-postgresのソースを眺めていたら[connection.rs](https://github.com/sfackler/rust-postgres/blob/master/tokio-postgres/src/connection.rs)でログを書きだしていることに気が付きました。

deadpool_postgresのようなコネクションプールでも動作することを確認しました。
neosでlogix その77

# 概要
neosでlogixやってみる。
key heldノード、使ってみた。

# 写真

![2022-05-12 23.15.34.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/a29a8778-1e6c-6fad-22fd-0dd07669d55a.jpeg)


# Key Held

```
Inputs
 	Key	Key
Outputs
 	Bool	*
```

# 手順

- logixtooltipを装着。
- Input Devices>Keyboard>Key Heldをスポーン。
- つなぐ


以上。
neosでlogix その76

# 概要
neosでlogixやってみる。
AvatarAnchorコンポーネント
AvatarAnchorLocomotionReleaseコンポーネント
AvatarAnchorTouchTriggerコンポーネント、使ってみた。

# 写真

![2022-05-12 21.57.02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/549e3f82-a166-d99d-75f6-34f8be911853.jpeg)


# 手順

- devtooltipを装着。
- 新規>3d>box
- Users>Anchors>AvatarAnchorコンポーネントを追加
- Users>Anchors>AvatarAnchorLocomotionReleaseコンポーネントを追加
- Users>Anchors>AvatarAnchorTouchTriggerコンポーネントを追加
- つなぐ


以上。
neosでlogix その75

# 概要
neosでlogixやってみる。
三人称視点、使ってみた。

# 写真

![2022-05-12 22.00.10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/e254fb28-6282-513d-c33a-4a584471011d.jpeg)

# 手順

- f5キーを押す。


以上。
if文使いたくない２４時間表記の時間の計算

### if文書きたくないんじゃー

```sample.js
let startTime = '22:30'
let elapsedTime = '01:40'
let [sh, sm] = startTime.split(':')
let [eh, em] = elapsedTime.split(':')

let hh = Number(sh) + Number(eh)
let mm = Number(sm) + Number(em)

hh = (hh + Math.floor(mm / 60)) % 24
mm = mm % 60

let rh = ('0' + hh).slice(-2)
let rm = ('0' + mm).slice(-2)

console.log(rh + ':' + rm) // "00:10"
```

％て割れない数字だとそのまま返してくれるのね。（今更）
Python: List(配列)要素の一括置換(辞書使用)

非常に基本的なことですがPythonでList(配列)要素を一括置換したいときに、やり方に迷い時間をかけてしまうことが多いです。
単純なコードですが、ググって全然見つからなかったので記事にしておきます(見つけ方が悪いのでしょうが)。

```python
subs = {1: '1 replaced', 
        2: '2 replaced'} 
ls = [0, 1, 2]
new_ls = [subs.get(element, element)  for element in ls]
print(new_ls)
```

```:結果
[0, '1 replaced', '2 replaced']
```

多分、もっと早い方法もあるのでしょうが、小さい配列ならこれで十分です。
githubにSSH接続ができなくなったら

## エラー内容
githubにpushしようとした時に下記のエラーが出てpushができなくなった。
```
ERROR: You're using an RSA key with SHA-1, which is no longer allowed. Please use a newer client or a different key type.
Please see https://github.blog/2021-09-01-improving-git-protocol-security-github/ for more information.

fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
```

どうやら、SHA-1を使用したRSA署名というものが使えなくなっている様子。
## 新しい公開キーの生成
下記のコマンドで生成した公開キーならssh接続ができるようになるみたい。
```
$ssh-keygen -t ecdsa -b 521 -C "hoge@example.com"
```
この時のメールアドレスはgithubに登録してあるメールアドレスを入力。
3回何か聞かれる。
* 保存するファイル名
* パスワード
* 再度パスワード

特に設定しなくても大丈夫なので3回EnterKey連打でOK。
今回はファイル名だけ「hoge」と入力。
## githubに公開キーを登録
公開キーの中身を確認する。
```
$cat ~/.ssh/hoge.pub
```
```
ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAEoOapWnd/
tZLoqDt6SnNVNargRHLl6nLYEeUyTuXaiw3s3CRp/qOXH5+Mb/qIY9OWuSAtyAqQPTHJXSvC2I4v6bACujP
3UHcdhA2aLy9gxjgWyrHIYErPmiq/78aBxkvTaIB5i3efGTtDmdGb6eR82eKXB/88v1mwKBkVc1/Qn2X/xd
g== hoge@example.com
```

生成した公開キーのメールアドレス以外をコピーして、
https://github.com/settings/keys
の 「New SSH key」 ボタンから登録してあげる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325724/4b14589b-a17e-7db5-b5b4-f0db87ec5f21.png)
Titleの欄には「自宅用PC」等任意の名前を入力してあげる。
Keyの欄に先ほどコピーした公開キーを張り付けて「Add SSH key」ボタンをクリックしてOK。

## SSH接続確認
configファイルに下記を記述する。
```~/.ssh/config
Host github github.com
  HostName github.com
  IdentityFile ~/.ssh/hoge
  User git
```
下記のコマンドを実行する。
```
ssh -T github
```
```
Hi githubのユーザー名! You've successfully authenticated, but GitHub does not provide shell access.
```
と出たらSSH接続成功。
## githubにpushしてみる
```
D:\test> git push
Counting objects: 2, done.
~
   ed7a30d..14a6f16  master -> master
```
できた。
Pythonで暗号文を作る

ふと、暗号文を作りたくなったので調べながらやってみました。
特にライブラリは使用していません。
ファイル名に関してはわかりやすくango.pyとします。
(ソースコード全文)
```python:ango.py
def ango(bun,mode):
    al = 'abcbdefghijklmnopqrstuvwxyz'
    al2 = list(al)
    el = []
    el_ = []
    for i in range(len(al)):
        el.append(' '+str(i)+',')
    al_ = str.upper(al)
    al_2 = list(al)
    for i in range(len(al)):
        el_.append(str(i)+'_')
    if mode == 0:
        bun = bun[::-1]
        for i in al2:
            bun = bun.replace(i,el[al2.index(i)])
        return bun
    if mode == 1:
        bun = bun.replace('.',', ')
        for i in el:
            k = el.index(i)
            bun = bun.replace(i,al2[k])
        bun = bun[::-1]
        return bun
```
では解説に移ります。
まず一番最初の行ではdef ango(bun,mode)とすることで関数化をしています。
次に変数alにアルファベットを定義してそれをal2で一文字ごとのlistにしています。
elには0から26までの数字の後ろにコンマ、前にスペースを付け足したものをlistにしています。
そして第一引数modeで暗号を解読するのか文字列を暗号化するのかで分岐させます。
暗号化の場合は0、解読の場合は1にしてあります。
暗号化では入力された文字列(bun)の向きを反対にすることでより安全性を強めています
```python:ango.py
bun = bun[::-1]#これでより難しくなる
```
次にbunからa~zまでのアルファベットを数字に置換することで暗号化しています
最後にreturnで暗号化した文字列を返しています。
次に解読ではさっきとは逆に数字をアルファベットに置換した後に向きを反対にすることで元の文字列に戻します。
では試してみましょう
```python:ango.py
print(ango('hello world',0))
-->' 4, 12, 18, 15, 23,  15, 12, 12, 5, 8,'
```
これを解読します
```python:ango.py
print(ango(' 4, 12, 18, 15, 23,  15, 12, 12, 5, 8,',1))
-->'hello world'
```
成功しましたね。
実をいうと大文字も判別できるようにしたかったんですが面倒くさかったのでやめました。
どなたか大文字も使えるように改善出来たら教えていただけるとありがたいです。
実用性は全くありませんが何かワクワクしますよね。
2022/5/13主にITとかセキュリティの記事

ブラザー会員サイトで不正ログイン、P交換被害も - 3月末からアクセス急増
https://www.security-next.com/136422

一部Facebook連携で別人より個人情報が閲覧可能に - アート販売サイト
https://www.security-next.com/136426

宇都宮CATV運営の通販サイトがサイバー被害、カード情報流出か(5/11)
https://cybersecurity-jp.com/news/66493

F5 BIG-IPの脆弱性を利用するサイバー攻撃を確認　直ちにアップデートを(5/11)
https://www.itmedia.co.jp/enterprise/spv/2205/11/news038.html

しまむら、システム障害　大型連休中にサイバー攻撃(5/11)
https://www.nikkei.com/article/DGXZQOUC10CD00Q2A510C2000000/

海外グループ会社サーバーへの不正アクセスに関するお知らせ(5/11)
https://www.ryobi-group.co.jp/news/newsrelease/007331.html

「しまむら」にサイバー攻撃…グループ全２２００店で商品取り寄せできず(5/11)
https://www.yomiuri.co.jp/economy/20220511-OYT1T50129/

海外子会社への不正アクセスに関する調査結果について　コニカミノルタ(5/11)
https://www.konicaminolta.com/jp-ja/newsroom/topics/2022/0511-01-01.html

Microsoft Windows においてコールバック関数による Window オブジェクトの型検証不備により権限昇格が可能となる脆弱性（Scan Tech Report）(5/11)
https://s.netsecurity.ne.jp/article/2022/05/11/47575.html

中国ハッカーが仕掛けた米人事管理局ハッキング　6300万ドルで和解(5/11)
https://mb.epochtimes.jp/2022/05/105764.html

GitHubが2要素認証のデフォルト化を発表　度重なるサイバー攻撃に対抗(5/10)
https://www.itmedia.co.jp/enterprise/spv/2205/10/news032.html

2022年3月のモバイルマルウェアレビュー ― 仮想通貨を盗むトロイの木馬、Google Play上の新たな脅威等(5/11)
https://japan.cnet.com/release/30682348/?ref=rss

「朝日新聞がチェーンメールの拡散性を検証中」不審メールに注意(5/11)
https://www.itmedia.co.jp/news/spv/2205/11/news133.html

ウクライナCERT、Jester Stealerマルウェア配布する新しいサイバー攻撃に警告(5/11)
https://news.mynavi.jp/techplus/article/20220511-2342572/?gpt=newspicks&utm_source=newspicks&utm_medium=rss

英国の女王演説、仮想通貨関連の法案2点を打ち出す(5/11)
https://coinpost.jp/?p=349128

Qtで開発されたWindowsアプリケーションに権限昇格の脆弱性(5/11)
https://gunosy.com/articles/e86oc

環境団体、米政府に仮想通貨マイニング業者への対策を要請(5/11)
https://jp.cointelegraph.com/news/environmental-groups-urge-us-government-to-take-action-on-crypto-miners

EU一般データ保護規則の施行によってスマホアプリの3分の1が消えたという指摘(5/11)
https://gigazine.net/news/20220511-gdpr-mobile-app/

1コードでWeb、Windows、Mac、iPhone、Androidにネイティブ展開
Microsoft、WebGPUをフルサポートする3Dレンダリングエンジン「Babylon.js 5.0」を公開(5/11)
https://atmarkit.itmedia.co.jp/ait/spv/2205/11/news050.html#_ga=2.197893103.1577816359.1652380911-467045693.1606180964

個人を推定されたくない、氏名丸出しのメールアドレスをペット名に変えたい(5/11)
https://xtech.nikkei.com/atcl/nxt/column/18/00084/00213/

パラダイムシフトの中でも「誰一人、取り残さない」　LINEが描くWeb3の未来(5/11)
https://www.coindeskjapan.com/147374/

[参加費無料セミナー]イーサリアムの仕組みと、ファンエコノミーにおけるNFT・WEB 3.0の実用的な展望について(5/27開催)
https://news.nicovideo.jp/watch/nw10906321

米中央情報局、Tor経由でロシアからの情報提供求める(5/11)
https://www.zaikei.co.jp/article/20220511/671507.html

実行するとキューに入るWindowsタスクの謎を解け(5/11)
https://atmarkit.itmedia.co.jp/ait/spv/2205/11/news002.html

どこへ向かうデジタル庁　デジタル監交代で2つの疑問(5/12)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020800017/050600711/

まずはNECとコムシスが受注　デジ庁調達に1者応札の課題(5/12)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020800017/050600712/

カシオが「即日」脱PPAP　3年前からの布石が奏功(5/12)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020800017/050600715/

声が聞こえない・謎のノイズ、Web会議にまつわる音のトラブルを一気に解決(5/12)
https://xtech.nikkei.com/atcl/nxt/column/18/02046/051000004/

どうなる日本のV2X通信、新たな通信方式を導入か(5/12)
https://xtech.nikkei.com/atcl/nxt/column/18/00001/06810/
VirtualboxでMX Linux(Xfce版)の永続Live USBを作成する - 1

# はじめに
[Distrowatch](https://distrowatch.com/)でも一番人気のMX LinuxのLive USBをVirtualbox上で作成し、ついでに永続化(書き込み可能)する手順のメモです。なお、他サイト様で既に紹介されている情報は参考文献として記載し、詳細な説明を割愛します。
# こんな人向け
+ 会社や学校、パパの部屋にメインのPCがある
+ このPCは極力汚したくない
+ このPCにVirtualbox(以降VBox)などの仮想マシンをインストールできる
+ 仮想マシンのスナップショット機能(バックアップ機能)は便利だと思っている
+ でも仮想マシンの重さに嫌気が指しているので物理PCがほしい
+ **お金はありません　←重要**
# 材料
+ メインPC x1
+ USBメモリ x1（USB 3.1推奨）
+ [Virtualbox x1](https://www.virtualbox.org/)
+ [MX Linux x1](https://mxlinux.org/)
:::note info
<strong>なんでMX Linux?</strong>
* Ubuntuはちょっと重い
* 必要なリソースと操作性のバランスがちょうどいい
* (海外がメインだが)情報が比較的多い
* 標準機能でLive USBを作成できるため、余計なツールをインストールする必要がない
* 標準機能でISOのスナップショットを作成できるため、バックアップ＆リカバリーが容易
:::
# 作り方
以下、メインPCで操作
1. VBoxインストール
2. MX LinuxのISOファイルをダウンロード
3. ↑のISOファイルをLive CDモードで起動

VBoxのインストールなどの詳細な説明は他に委ねるとし、要点のみを示します。
+ 仮想マシンの新規作成時、Type="Linux", Version="Debian (32-bitまたは64-bit)"
![0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662892/30eaa806-62f9-857b-a572-3bc05c4d1d18.png)
+ [Settings]-[Storage]で"Live CD/DVD"をチェック
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662892/148c1351-cee3-deea-8d82-16e2393ab71e.png)
+ (USBメモリをメインPCに挿入した上で)書き込み先のUSBメモリを選択
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662892/643a0ce1-982e-2f09-4160-1fb26e524502.png)

以下、VBox上のMX Linuxで操作(英語版でスミマセン)
4. ISOを格納するストレージを共有フォルダとしてマウント
5. MX live USB Makerを起動
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662892/b04f7370-f79e-06a3-b295-d7c01f8e3e60.png)
6. 以下の設定を参考にしてください
+ Select Target USB Device=書き込み先のUSBメモリ
+ Select ISO file=これから書き込むMX LinuxのISOファイル
+ Mode=Full-featured modeで書き込み可能のLive USBとする
+ Percent of USB-device to use=MX LinuxのOSが占有する領域のサイズ(%)を指定
+ Label ext partition=お好みで
![77.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662892/1bd94378-961e-f55b-001c-cb72361c4d8c.png)

あとはNext, Next...でLive USBができるはずです。

:::note info
手順4は任意です。手順5でISOファイルの場所を仮想マシン上から参照できるようにすることが目的。
VBoxの共有ドライブを使用する場合、マウントポイントを指定した上で仮想マシン側からマウントします。
+ WindowsのCドライブを共有フォルダにする場合
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662892/87394778-1854-bdcc-de27-71913da43cd2.png)
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662892/442ec774-b51e-36bd-09ce-15f815b8b95d.png)
+ 上記の例の場合、MX linux側で以下のコマンドを実行することにより、Cドライブを共有フォルダとしてマウントできます。
```shell
$ sudo mkdir -p /mnt/mxlinux
$ sudo mount -t vboxsf C_DRIVE /mnt/mxlinux
```
:::

:::note warn
USB3.0およびVBoxの共有フォルダ機能を使用する場合、VBoxのExtention Packをインストールする必要があります。MX Linux 21.1 x64版には標準でインストールされていると思います。

MX Linux上で以下のコマンドを実行し、パスが表示されることを確認してください。見つからない場合、VBoxのExtension Packをインストールしてください。
```shell
$ which VBoxClient 
/usr/bin/VBoxClient
```
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2662892/b0e37302-d7fb-9d6e-1746-4c351cbdaaac.png)
:::

疲れたので次回に続きます。。。
Kakuyomu のスクレイピング

### Kakuyomuって pdf 作れないよね...

「なろう」じゃ作れるのになんでだろう...。
Kakuyomuの方が絶対に金かけているのに...。
ロードバランサーとか冗長処理とか4IP×4種類も用意して、絶対接続させるマンなのに...。
とりあえず、テキストデータだけでもスクレイピングしたかった...。

# 作ってみました。やりかたは、[以前の記事](https://qiita.com/KayaTakashiro/items/6ae0cd0d1d6f640cb531)を参考

github(https://github.com/blackpopo/QiitaLaboratory)

早速

```kakuyomu_scraper.py
import requests
from bs4 import BeautifulSoup
from sklearn.neighbors import VALID_METRICS
from tqdm import tqdm
from time import sleep

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.76 Safari/537.36'}
url_header = 'https://kakuyomu.jp/works'

def get_text(url, gyokan=False):
    print(f'Start each page at {url}')
    response = requests.get(url, headers=headers)
    soup = BeautifulSoup(response.content, 'html.parser')
    # print(soup)
    text = soup.find(class_='widget-episode-inner')
    texts = [line.text for line in text.find_all('p')]
    texts = [line.replace('\u3000', '') for line in texts]
    if not gyokan:
        texts = [line for line in texts if line != '']
    return texts

def get_page(code, gyokan=False):
    url =  url_header+ '/' + code 
    print(f'url : {url}')
    response = requests.get(url, headers=headers)
    soup = BeautifulSoup(response.content, 'html.parser')

    title = soup.find(id="workTitle")
    title = title.get_text()
    author = soup.find(id="workAuthor")
    author = author.get_text()
    indices = soup.find(class_='widget-toc-main')
    if indices == None:
        raise ValueError(f"Indices not found... at {url}")
    else:
        hrefs = ['/'.join(a['href'].split('/')[-3:]) for a in indices.find_all('a')]
        #hrefs = sorted(hrefs, key=lambda x: int(x.split('/')[-1]))
        print(f'length of hrefs {len(hrefs)}')
        for href in tqdm(hrefs):
            url = url_header + '/' + href
            lines = get_text(url, gyokan)
            sleep(1.0)
            with open(code + '.txt', 'a', encoding='utf-8') as f:
                f.write('\n'.join(lines))
    rename_file(code, title, author)

import os
import re
invalid_string = re.compile(r'[\\/:*?"<<>|]+')
def rename_file(code, title, author):
    title = invalid_string.sub('', title)
    author = author.split('\n')[-2]
    author = invalid_string.sub('', author)
    os.rename(code + '.txt', f'{title}_{author}.txt')

import argparse

if __name__=='__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--url', type=str)

    args = parser.parse_args()
    code = args.url.split('/')[-1]
    print(f'code {code}')
    get_page(code, gyokan=False)
```

### 使い方

```console
python kakuyomu_scraper.py --url https://kakuyomu.jp/works/ここに数字
```

これをすると**タイトル_著者.txt**というファイルができます。

以上！
Pythonのdict()が特定の入力に対し非常に遅い件について

# 初めに

これは競技プログラミングのために書かれた記事です。あくまでも特定の恣意的な入力に対し起こることであり、現実世界のデータを扱う際にこの事象が問題になることはほとんどないと思います。

この記事は、[Codeforces Round #790 (Div. 4) の F 問題](https://codeforces.com/contest/1676/problem/F) で Python / PyPy による提出のほとんどすべてが Hack されたのをきっかけとして書かれました。
間違い等あれば気軽にコメントしていただけると助かります。

# 前提知識

## Python の dict について
Python の dict は、以下のようなコンテナ（データを収納するための構造）です。

* 整数や文字列、タプル等の hashable なオブジェクトを key として、それぞれに value を割り当てることができる。（value は key と異なり任意のオブジェクトが格納可能。例えば配列を value とすることもできる。） key を指定して、 value が割り当てられているか判定したり value の値を求めたりできる。

今回は、key は非負整数であるものとします。

## dict の内部挙動
value は結局のところ dict の中にある配列に格納されます。 key と配列の添え字とを何らかの規則に基づいて関連付けることで、 key から高速に value を求めることが可能になるというわけです。

dict に $(key, value)$ のペアが与えられた時、以下のようなアルゴリズムで対応する添え字を決定します。:
1.  ある関数 $f$ を用いて、 $f(key)$ を求める。
1.  もしまだ配列の $f(key)$ 番目に何も割り当てられていないなら、 $f(key)$ に $value$ を収納して、終了
1.  もし $f(key)$ にすでに割り当てられているものがあるなら、 $key \leftarrow f(key)$ として、1.に戻る。


# Python の dict における Hashing 
dict 内の配列の長さを $size$ 、最初の hash（入力された key です）を $x_0$ とすると、 $x_{i + 1} = f(x_i)$ で 定める $x_{i + 1}$ は以下のようになります。
```math
x_{i + 1} = f(x_i) = \left(5x_{i} + 1 + \left\lfloor\frac{x_0}{32^i} \right\rfloor\right) \mod size
```


つまり、 dict に $key = x_0$ を指定したとき、内部では $(x_0, x_1, x_2, x_3, x_4, \dots)$ を前から順に計算して確認し、空いてるか確認する、という挙動をします。そのため、あらかじめこれらの番地を順番に埋めてしまえば、 $key$ を呼ぶたびに大量の $f(x)$ の計算を行うことになり実行時間が非常に遅くなります。よって、$x$ を順番に dict に入れさせ、その後 $x_0$ を呼び出しまくるような入力を与えれば、Python の dict に対する hack ケースになるというわけです。

# 具体例
```Python dicthack.py
size = 2 ** 32
d = {}
d[size + 1] = 1
x = 6
for i in range(2 * 10 ** 5):
    d[x] = 1
    x = 5 * x + 1
    x %= size

for i in range(2 * 10 ** 5):
    d[1] = 1

print("Done")
```

このシンプルなプログラムをAtCoderのコードテスト(PyPy3)で実行すると、10秒の制限時間を超過します。普通 dict の処理は $O(1)$ であると考えられているので、かなり意外な結果に感じられます。また、dict に対する hackケースは AtCoderでもあり得そうな範囲の大きさで、また生成が簡単なケースであることもわかると思います。

【5/13 追記】set に対する　hack ケースを見つけました。

```python sethack.py
size = 2 ** 32
s = set()

for j in range(10):
    s.add(size + 1 + j)
x = 6
for i in range(10 ** 6):
    for j in range(10):
        s.add(x + j)
    x = 5 * x + 1
    x %= size

for i in range(10 ** 5):
    1 in s

print("Done")
```

$10^7$ 程度のループで set に数値を加えていくプログラムです。 AtCoder コードテストで実行すると、10 秒の時間制限を超過しました。

set については、 10 個程度の hash を並列してチェックしているそうですが、詳しい仕様や条件についてはよくわかっていません。わかる方いれば教えてください。

# 他のコンテナについて

defaultdict や Counter は dict のサブクラスとして実装されているため、同様の問題はこれらでも発生します。

# 対処法

上で述べたような仕組みはハッシュテーブルというデータ構造で、他に C++ の unordered_map やJava の HashMap が同様の構造をしています。よって、これらで起こる問題と同様のものが Python の dict でも起こりうるというわけです。
Codeforces において C++ の unordered_map をそのまま使うことは推奨されません。（ほぼ確実に Hack されるため）今までは Python の dict に対する Hack ケースは C++ のそれに比べ知名度が低かったですが、今後情報が広まるにつれて対策の必要が生じてきます。

C++ と違ってPython には任意の hashing を設定する方法がないので、 dict 単体をいじることでどうにかすることはできません。

要は「特定の数が特定の順番で埋まっていく」ことに問題があるので、それを防げればよいです。あらかじめ入力をソートする、入力に適当な数で xor をする（後で戻す）などの対処法があるでしょう。自作の hash 関数を作って、dict に入れる時にそれを噛ませるようにしてもいいです。

# 参考文献
* [Anti-hash-table test in Python](https://codeforces.com/blog/entry/101817)  この記事はほとんどここを参考にして書きました。

* [Python の dict の実装詳解](http://dsas.blog.klab.org/archives/python-dict-internal.html) 関数 $f$ の挙動を調べました。
游ゴシック Mediumの疑似ボールド体を游ゴシック BoldにするVBA

# 背景
游ゴシック MediumはPowerPoint上で太字(ボールド体)にしても疑似ボールド体にしかならず，游ゴシック Boldになってくれません．[^1] いちいちフォントを手作業で変えるのは面倒なので自動で置換してくれるVBAを作りました．

[^1]: 游ゴシックにはウェイトがLight，Regular，Medium，Boldとあり，PowerPointではRegularの状態で太字にすると自動的にBoldになります．しかし，Light，Mediumの状態で太字にしてもPowerPointが機械的に太くした疑似ボールド体になってしまいます．
また，Windowsでは游ゴシック(無印)，Light，Mediumしか表示されませんが，無印がRegular，無印を太字にしたときがBoldになっています．

# コード

VBAを書くの初めてなので，コードが汚いのはご容赦ください．バグ等ありましたら報告お願いします．

```VB
Public Const FROM_FONT As String = "游ゴシック Medium"
Public Const TO_FONT As String = "游ゴシック"

Public Sub YuGothicMediumBoldReplacer()
    Dim shps As Collection
    Dim shp As Shape
    
    Set shps = New Collection
    
    Call searchShapesFromPresentation(shps)
    
    For Each shp In shps
        Call searchTextFrame(shp)
    Next
End Sub

Private Sub searchShapesFromPresentation(ByRef shps As Collection)
    Dim sld As Slide
    Dim shp As Shape
    For Each sld In ActivePresentation.Slides
        For Each shp In sld.Shapes
            Call putShapeRecursive(shp, shps)
        Next
    Next
End Sub

Private Sub putShapeRecursive(ByRef shp As Shape, ByRef shps As Collection)
    Dim s As Shape
    If shp.Type <> msoGroup Then
        shps.Add shp
    Else
        For Each s In shp.GroupItems
            Call putShapeRecursive(s, shps)
        Next
    End If
End Sub

Private Sub searchTextFrame(ByRef shp As Shape)
    Dim s As Shape
    
    With shp
        
        ' テキストフレームがあり，テキストがある
        If .HasTextFrame And .TextFrame.HasText Then
            Call checkTextRange(.TextFrame.TextRange)
        ' 表がある
        ElseIf .HasTable Then
            Dim c As Cell
            Dim r As Row
            For Each r In shp.Table.Rows
                For Each c In r.Cells
                    Call searchTextFrame(c.Shape)
                Next
            Next
        End If
        
    End With
End Sub

Private Sub checkTextRange(ByRef range As TextRange)
    With range
        
        ' 一部だけフォントが違ったり，一部だけボールドな場合
        If .Font.Name = "" Or .Font.NameFarEast = "" Or .Font.Bold = msoTriStateMixed Then
            ' 1文字ずつ調べる
            Dim i As Integer
            For i = 1 To .Length
                Call updateFont(.Characters(i, 1).Font)
            Next
        ' すべて同じフォントかつ全体がボールド
        ElseIf .Font.Bold = msoTrue Then
            Call updateFont(.Font)
        End If
        
    End With
End Sub

Private Sub updateFont(ByRef f As Font)
    With f
        
        ' ボールドだったら
        If .Bold Then
            ' 英数字用，日本語用それぞれ別に変更
            If .Name = FROM_FONT Then
                .Name = TO_FONT
            End If
            If .NameFarEast = FROM_FONT Then
                .NameFarEast = TO_FONT
            End If
        End If
        
    End With
End Sub
```

# 参考文献
PowerPointのFontをすべて変更するVBA (グループ化されていても!)
https://qiita.com/Umaremin/items/7270a65b72debb17bba2

グループ化と表への対応を参考にさせていただきました．
vue3で郵便番号の自動入力をする

# はじめに
この記事ではvue3で郵便番号の自動入力をする方法を紹介します。
[実装例](https://qiita.com/kamikita/items/85a1ffdd75846929f14c#%E5%AE%9F%E8%A3%85%E4%BE%8B)で、フォーカスが外れたときに郵便番号を自動入力するサンプルコードを載せています。
![81at8-ojhkw.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/761132/6cd4a409-8dac-190c-4ad0-97f83d443c4d.gif)

# 環境
- Vue.js: 3.0.5
- Node.js: 14.17.0
- npm: 7.16.0
- Bootstrap: 5.1.3

# ライブラリのインストール
yubinbango-core2というライブラリを使用します。
https://www.npmjs.com/package/yubinbango-core2
ターミナルで以下を実行

```
npm i yubinbango-core2
```

:::note warn
補足
本家の```yubinbango-core```はmoduleがエクスポートされていないため、そのままだとvueで使えません。
そのため、moduleエクスポート済みの```yubinbango-core2```をインストールしています。
（https://github.com/yubinbango/yubinbango-core/issues/4 yubinbango-coreのissuesを参照）
:::

# 実装例
```v-on:blur="fetchAddress()"```でフォーカスが外れた時に郵便番号から住所を取得する関数を呼び出しています。
```sample.vue
<template>
  <div class="container">
    <form>
      <div class="my-3">
        <label class="form-label" for="postal-code">郵便番号</label>
        <input
          class="form-control"
          type="text"
          id="postal-code"
          v-model="form.postalCode"
          v-on:blur="fetchAddress()"
        >
      </div>
      <div class="mb-3">
        <label class="form-label" for="address">住所</label>
        <input class="form-control" type="text" id="address" v-model="form.address">
      </div>
    </form>
  </div>
</template>

<script>
import { reactive } from 'vue'
import { Core as YubinBangoCore } from 'yubinbango-core2'

export default {
  components: {
    YubinBangoCore,
  },

  setup () {
    const form = reactive({
      postalCode: '',
      address: '',
    })

    // 郵便番号から住所を取得する関数
    function fetchAddress() {
      new YubinBangoCore(form.postalCode, function(addr) {
        // region=都道府県, locality=市区町村, street=町域
        const address = addr.region + addr.locality + addr.street

        form.address = address
      })
    }

    return { form, fetchAddress }
  }
}
</script>

```
【ESLint】import文を自動で並べ替える【Next.js】

## import文を自動で並べ替える方法
importを自動で並べ替えるには`eslint-plugin-import`を使用します。

### `eslint-plugin-import`の設定
`.eslintrc.json`に以下のように記述することで並べ替えができます。
```.eslintrc.json
{
  "extends": [
    "plugin:import/recommended",
    "next/core-web-vitals",
    "prettier"
  ],
{
  "rules": {
    "import/order": [
      "error",
      {
        // グループごとの並び順
        "groups": [
          "builtin",  // node "builtin" のモジュール 
          "external",  // npm install したパッケージ
          "internal", // パス設定したモジュール
          ["parent", "sibling"], // 親階層と子階層のファイル
          "object",  // object-imports
          "type",  // 型だけをインポートする
          "index" // 同階層のファイル
        ],
        // グループごとに改行を入れるか
        "newlines-between": "always", 
        // アルファベット順・大文字小文字を区別なし
       "alphabetize": {
          "order": "asc",
          "caseInsensitive": true
        }
      }
    ]
  }
}

```
なんにもできない人がUnityのワールドを作ってみる話

# ことの始まり
今、私は今後の仕事について悩んでる。
事務仕事を地味にやっていくか、昔から興味があったIT系（とここでは広く言っておく）に頑張って行くか。
そんな話をしている中で、色々（この中身は割愛）あって、今後もしそちら方面に頑張って行くという選択肢をとるならば、今はVRChatのワールドを作れるようになろうということにした。
と、いうわけで、調べたことや必要だったこと、やったことなどを書き留めていく。

# はじめにしたこと
知ってることから必要そうと思ってる情報の整理をした。
以前にもVRChatのアバターとやらの作り方を調べたのだが、その時に知った流れはこう。

　1.Blenderとかでモデルを作る
　2.モデルをUnityに持ってきて、動きとかライトとかの設定やらをする。

加えて知っていた重要なことがこれ。
　**VRChatのSDKにはバージョンがあること**
　**そのSDKのバージョンに合わせて、Unityのバージョンを選ばないといけないこと**

以上の知識の状態から、ワールドを作れるようになるために、調べ物から開始。
少し前にSDK3がでたという情報はおぼろげに入っていたので、それをベースに**ググった**。

# わかったこと
1. SDKはVRChatのWEBにログインしてDLできること。
2. 現在の対応Unityバージョンは、「Unity2019.4.31f1」というものであること。
3. これらは[ドキュメント](https://docs.vrchat.com/)に書いてあること。

1は、ただただログインしてダウンロードからダウンロードすればいい。
ただし、今回はワールドを作りたいため、フレーバー（何用的な）はワールドを選んだ。

2は、どうにもドキュメントに書いてある通り、現在のSDK3を使ってやるには、この2019.4.31f1というバージョンのUnityをインストールする必要があるらしい。
というわけで次にやることは、**Unity2019.4.31f1のインストール**。

3を読みながら頑張っていこう。

# Unity2019.4.31f1のインストール
かつて私が触っていたときのUnityは当然（？）バージョンがぴったり合うわけないので、インストールから。
といってもHUBが入っているのでおそらくここからできるだろう。
1. HUBを開いて、インストールタブへ
2. インストールをクリックして、2019.4.31f1を選んｄ・・・**なかった**

ないので、案内通り、ダウンロードアーカイブへ。
2019.4.31f1を探して、Unity HUBで開いて、インストール。
モジュールはいらなくない？とか思いながらスルー。これが正しいのかは知らない。
インストールを待ちながら、次にするであろう、**SDKの導入**の方法を調べる。

# SDKの導入

インストールが無事終わったら、新しい3Dプロジェクトを作って、開くらしい。
開けたら、タイトルバー（ウィンドウの名前）が、「PC, Mac & Linux Standalone <DX11>」とあるかを確認しろとのことらしいので確認。
大丈夫そうなので、SDKをインポートしてみる。

といっても、ダウンロードしたSDKをUnityプロジェクトを開いた状態で開けば良いらしい。
開いたら待ってればおｋ。

無事SDKが導入できたら、**ログイン**が必要らしい。
ファイル、編集・・・などと並んでるメニューから、**VRChat SDK > Show Control Panel > Authentication**と進んで、あとはVRChatのアカウントでログインすればおｋ。

＊これはアバターにしろワールドにしろのようだが、ユーザーランクが上がってないとだめらしいので、上がってなかったら頑張って遊ぼうね。

ここまででやっとこさ作る準備ができたらしいです。
続きはまた別なときに書きます。
forEachについて完全に理解した()

javascriptを触ってはや１年ほど経つが、先日callback関数について見直した後に、forEachを見直したら世界が変わった
というか、今までなんとなくのイメージで書いていたことがようやく完全に理解できた()。

# 従来のイメージ
今までforEachってなんとなく、配列の要素を１つずつ取り出して、要素を使って処理をするものってイメージだった。
例えば、配列の中身をすべて２倍にするみたい感じ↓
```sample.js
const arry = [1, 2, 3, 4, 5];

arry.forEach((ary) => {
  console.log(ary * 2);
});
```
実行結果
```
2
4
6
8
10
```
ここでいうaryの中にarryの要素が順番に入ってくるから、その処理を以降で書いてる。なんでarryの要素が入ってくるのかは魔法。そんなイメージだった。

# 現在のイメージ
forEachは引数として、callback関数を取る。
callback関数については[先日の記事](https://qiita.com/TakehiroKATO/items/97bee8971dd9de31ded8)に書いているが、簡単に言うと、関数に渡す関数で、渡すcallback関数によってその関数の処理を変更するというもの。
forEachもcallback関数を引数に取るので、渡すcallback関数で処理を決定している。
となると、今まで魔法だと思っていたaryの中にarryの要素が順番に入ってくるということにも納得が言った。詳しい中身まではわからないが、forEachでは恐らく配列の要素１つ１つを取り出して、渡ってきたcallback関数に渡すという処理をしているのだろう。コードにすると以下みたいな感じ(本来はArrayクラスのメソッドだと思う)
```forEach.js
const arry = [1, 2, 3, 4, 5];

const forEach = (ary, callbackFn) => {
  for (const v of ary) {
    callbackFn(v);
  }
};

const callbackFn = (v) => {
  console.log(v * 2);
};

forEach(arry, callbackFn);
```
実行結果
```
2
4
6
8
10
```
# なんで違ったイメージをしていたか
完全に個人的な意見だが、アロー関数で書いていたからだと思う。。。
たとえば、forEachをアロー関数と無名関数で書いてみる
```compareForEach.js
const arry = [1, 2, 3, 4, 5];

arry.forEach((ary) => {
  console.log(ary * 2);
});

arry.forEach(function (ary) {
  console.log(ary * 2);
});
```
どちらのforEachも同じ処理を書いているのだが、アロー関数で書いている方が簡単な分、forEachさんがaryに１つずつ値を渡しますよ感が強い気がする。
逆に無名関数だと、しっかりと引数を取る関数を渡していることが理解でき、引数はforEachメソッドの中で渡すんだなということが理解できる気がする。
あえて簡略化しすぎずに書いたほうが理解が深まるなと感じたし、魔法じゃなくて内部でどんな処理がされているかまで想像できると楽しいなと思えた。
MoNK で Modelica クラスのアイコンを編集する

# 経緯
OpenModelicaで1Dシミュレーションをはじめた．
さっそくモデルを自作し，アイコンを作成しようとした．annotation セクションに直接記述するか，OpenModelicaのGUIであるOMEdit（OpenModelica Connection Editor）でアイコンを編集することができる．ただし編集機能の自由度が低いので，ちょっと複雑な画像編集には苦労する．

なにかいい方法はないものかと調べると "MoNK" なるツールを見つけた．
まだ使い始めの段階ではあるけれど，日本語の解説が見当たらなかったので備忘録がてら記事を書くことにした．

# MoNK
- ベクター画像編集ソフトウェア[Inkscape](https://inkscape.org/ja/)の拡張機能．
- Inkscape の SVG 画像から Modelica の annotation 文字列を生成する．
- 名称は "A **MO**delica i**NK**scape extension" より．
- 詳細は[GitHubのリポジトリ](https://github.com/THM-MoTE/MoNK)を参照のこと．

### インストール方法
PCにPythonがインストールされていれば，GitHub から setup.py をダウンロード．つぎのコマンドでインストールされる（と思うが未確認）．
`python setup.py install_ink`

または[こちら](https://github.com/THM-MoTE/MoNK/releases)からスクリプトファイル（たとえば "MoNK-0.2.0.zip"）をダウンロードして解凍し，中身を Inkscape の拡張機能フォルダに置く方法もある．Windows の場合はつぎのフォルダになる．
`%userprofile%\AppData\Roaming\inkscape\extensions`

インストールができていれば，名前を付けて保存のファイルの種類に "Modelica annotaion (*.mo)" が追加される．

### 使い方
Inkscapeでつぎのような図形を作成する．
<img width="250" alt="Inkscapeで描いたアキュムレータ.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444897/b7e8b9ce-d89c-8d94-28ee-76935a970aa9.gif">
名前を付けて保存から "Modelica annotaion (*.mo)" を選択して保存．
![Inksapeのダイアログ.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444897/ff239537-9aa4-8a64-9d8a-c2a4acc08012.gif)
つぎのダイアログが開く．とくに問題がなければ，そのまま "OK" を選択．Modelica annotation ファイルが出力される．
![SVG_to_modelica_annotations.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444897/eac37600-f0ca-04ef-5cbc-d434f245cab6.gif)
Modelica annotation ファイルをテキストエディタで開くと，下記の annotation 文字列が表示される．
```Modelica
model ModelName
  annotation(
    Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = false), graphics = {Rectangle(origin = {-100, 100}, lineThickness = 1.5, extent = {{50, 0}, {150, -200}}, radius = 50), Line(origin = {-100, 100}, points = {{50, -100}, {150, -100}}, thickness = 2), Polygon(origin = {-100, 100}, lineThickness = 2.16, points = {{111.42, -80.14}, {100, -99.92}, {88.58, -80.14}, {111.42, -80.14}})}));
end ModelName;
```
OMEdit から対象のModelicaクラスのテキストビューを開く．annotation セクションにこの文字列を貼り付ける．
アイコンビューを開くと下図がアイコンとして表示される．
<img width="250" alt="OMEdit上のアイコン.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2444897/674b4cfb-0356-1ff7-8bb0-095ca0b83a7d.gif">

### 注意点
- Modelica annotation ファイルは InkScape で読み込めない．再編集が必要になった場合に備えて別途 Inkscape SVG ファイルとして保存しておく．
- 完全に互換性があるわけではない．どの要素を変換できるかは[GitHub](https://github.com/THM-MoTE/MoNK)の "Features" 参照のこと．
- Modelica annotation ファイルを OMEdit で開くと annotation 文字列が書き換わって図形が崩れる．テキストエディタで開いて annotation 文字列を OMEdit のテキストビューに貼り付けたほうが無難．

# 補足
### 環境
- OS は Windows10 を使用．
- OpenModelica は v1.18.0-dev.beta1(64-bit) を使用．
- Inkscape は Inkscape 1.1.1 (3bf5ae0d25, 2021-09-20) を使用．
- MoNK は v0.2.0 を使用．

### MoVE
- MoNKと同じく Modelica の annotation 文字列を生成する画像編集ソフトらしい．
- Mac でしか動かない？
- 開発終了して MoNK に引き継がれたらしい．
- 詳細は[GitHubのリポジトリ](https://github.com/THM-MoTE/MoVE)を参照のこと．
Unity:S3から複数の動画を選択しストリーミング再生する方法

# S3に置いた動画データを選択して配信する
S3に置いた複数の動画データから配信する動画を選択する方法についてまとめます。

## 実装したもの
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">AWSのS3上の動画ファイルを動画を選択してストリーミング再生する実装に成功！<br>GWにやったAWSの勉強がさっそく生きて嬉しい。<br>動画は当院のInstagramとTikTok(<a href="https://twitter.com/dr_teru_ortho?ref_src=twsrc%5Etfw">@dr_teru_ortho</a>)に載せている、当院スタッフが作成した動画。<a href="https://twitter.com/hashtag/protoout?src=hash&amp;ref_src=twsrc%5Etfw">#protoout</a><a href="https://twitter.com/hashtag/%E3%82%B9%E3%82%BF%E3%82%B8%E3%82%AA%E3%81%97%E3%81%BE%E3%81%A5?src=hash&amp;ref_src=twsrc%5Etfw">#スタジオしまづ</a> <a href="https://t.co/p3SCTzUbnf">https://t.co/p3SCTzUbnf</a> <a href="https://t.co/e0v5uMIa8G">pic.twitter.com/e0v5uMIa8G</a></p>&mdash; Dr.Teru:プログラミングとサーフィンが好きな整形外科医 (@teru3_kitashiro) <a href="https://twitter.com/teru3_kitashiro/status/1524768615765061637?ref_src=twsrc%5Etfw">May 12, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
ボタンで選択することで流れる動画が切り替わるように実装しました。

## S3のバケットに動画を置く
まずはS3のバケット内に動画を置きます。
[Try #078 – Amazon S3の公開設定を色々とためしてみた](https://day-journal.com/memo/try-078/)
の記事を参考にして、公開されたURLを取得します。

##  Script
```C#:VideoDownloader.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Video;

public class VideoDownloader : MonoBehaviour
{
    bool canPlay = false;
    VideoPlayer video;
    string[] videoURL = new string[5];
    
    void Start()
    {
        VideoPlay();

    }

    public void VideoPlay()
    {
        video = gameObject.GetComponent<VideoPlayer>();
        video.playOnAwake = false;
        video.waitForFirstFrame = true;
        video.source = VideoSource.Url;
        videoURL[0] = "https://バケット名.s3.リージョン.amazonaws.com/ファイル名/動画ファイル名";
        videoURL[1] = "https://バケット名.s3.リージョン.amazonaws.com/ファイル名/動画ファイル名";
        video.url = videoURL[0];
        
        video.prepareCompleted += VideoPlayerOnPrepareCompleted;
        video.Prepare();
    }

    private void VideoPlayerOnPrepareCompleted(VideoPlayer source)
    {
        canPlay = true;
    }

    public void OnClickVideoPlay0()
    {
        if(canPlay == true)
        {
            video.url = videoURL[0];
            video.Play();
            Debug.Log("0");
        }
        
    }

    public void OnClickVideoPlay1()
    {
        if (canPlay == true)
        {
            video.url = videoURL[1];
            video.Play();
            Debug.Log("1");
        }

    }
}

```
SPIKEプライムの軌跡をPythonで描画する

# 目次
1.SPIKEプライムとは？
2.プログラミング
3.ロボットを動かす
  　 ジャイロセンサーから情報取得
4.Pythonで描画
5.最後に

<a id="anchor1"></a>
# SPIKEプライムとは？
[LEGO公式ページより](https://education.lego.com/ja-jp/products/-spike-/45678#spike%E3%83%97%E3%83%A9%E3%82%A4%E3%83%A0)
>レゴ**®エデュケーション SPIKE™** プライムは、小学校高学年から中高生向けのSTEAM学習セットです。カラフルなブロックパーツや、使いやすいハードウェアとScratchベースの直感的なプログラミングを融合し、問題解決型のプロジェクトを通して楽しみながら実社会で役立つスキルを育くむことを可能にします。また、SPIKEプライムは、人気の高いプログラミング言語Pythonを使ったテキストコーディングにも対応し、学習ニーズに応じてアプリ上で、ワードブロック(Scratch ベース)または、Python(テキストベース)を選択することが可能です。SPIKEプライムは、児童・生徒が、AI、IoT社会で輝くために必要なSTEAM科目への自信と21世紀型スキルの習得をサポートします。遊び心も大切にしながら！

簡単に言うと、中高生向けの、"プログラミング教育を目的としたロボット"です。前代のEV3よりカラフルで、ポートがわかりやすい場所にあるなど、初心者にとって取り組みやすくなっている印象です。
# プログラミング
SPIKEプライムの動かし方は、ICONブロック、WORDブロックそしてPythonの3種類があります。
![スクリーンショット 2022-05-08 12.48.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2060176/9a570a1f-b935-a8a8-d6ab-e74eed4bfc7e.png)

今回は細かい情報を取得したいため、Pythonで動かしました。

# ロボットを動かす
今回はSPIKEロボットをあらかじめ作っておいたコースの上を辿らせました。ライントレースと呼ばれるものです。どうやら競技もあるみたいですね。
![673670119.396973 (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2060176/33ad40e7-1cce-6bb4-1afc-dd10f9fe114e.gif)
ロボット制御の細かい話は今回の目的とずれているのでおいておきます。
簡単に説明すると、
１.カラーセンサーで下の地面の色を取得
2.特定の条件を満たしたとき線の上に戻るように回転
3.それ以外の場合１cm進む
この３つの処理を繰り返してます。
## ジャイロセンサーから情報取得
SPIKEプライムのPythonライブラリはとても充実しています。色々な機能があるので是非触ってみてください。
今回はSPIKE本体に当たるハブに内蔵されているジャイロセンサーからの情報を取得します。
```Python
hub.motion_sensor.get_yaw_angle()
```
この関数を使うとyaw angle（垂直方向の軸を中心とした回転角度）を取得することができます。
これをwhile文で取得していく感じです。
# Pythonで描画
センサーで取得したyaw angleたちを使って描画してみます！　描画するにはx,y座標が必要なのでこの角度たちから座標を出しました。
毎度１cm動いているので単位円を描き続けている感じをイメージすればこの角度だけで座標が取得できると考えました。
<img width="400" alt="16075434001697.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2060176/db524e5a-36e5-fbe9-c319-a8236e655814.jpeg">
（日本語が難しかったので作図しました。）
最後にそれぞれのsinθ、cosθをx、yとおけば座標が取得できるはず！
早速試してみました。今回matplotlibで描画してます。
結果:
左:SPIKEの通ったコース            右:Pythonでの出力結果
<img width="800" alt="16075459072506.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2060176/86775755-d30b-7fdf-d041-40df023532ef.png">

正直なところ想像以上の精度でした！　まだまだ改善の余地はあると思うのですが、思いつきの簡単なアイデアでここまでの精度を出せたのはびっくりしました。
もう１コースあったので試してみました:
<img width="800" alt="16075459072506.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2060176/8e230c42-046c-8a78-08d1-92772ac87a6f.png">

こちらもしっかりトレースできてますね！

# 最後に
Qiitaに何かしら投稿したいなと思って、今回書いてみました。以上、ひいらぎでした。