OmniAICreator/Qiita-1.07M huggingface dataset:
エンジニアがこんなIT企業に就職してはいけない７つのルール

<h1>はじめに</h1>

この数年で感染症等の外的環境の変化で働き方、会社と社員の関わり方が大幅に変化した中、皆さんはどのような働き方をされておりますか？
一度は在宅になったり、今も継続している会社や、元に戻ったり等色々なパターンがあると思います。
どのパターンでも各々の背景があるわけで一概に良い悪いを判断できるものではありません。
しかし、それは企業の論理や、経営の論理を一方通行で押し付けてたりしていないでしょうか？

<h3>経営層の75％「テレワークやめたい」　従業員のオフィス勤務希望は？</h3>
https://www.itmedia.co.jp/business/articles/2111/18/news126.html

<h3>在宅勤務を広げるかはこれから　どうなる働き方改革</h3>
https://www.sankei.com/article/20211204-5T4OLAQYGRLOFN77UB5X7ZB6UQ/

そもそも会社に出社したとしても、パソコンの前から動かないで業務するのであれば<b>出社が必要なのか</b>、と。FAXでさえメール受信できる今の時代一部の作業だけが現地作業となるのではないしょうか。

そんな今後の働き方も踏まえた上で入社時に気にかける７つのルールをご紹介します。


<h1>１.出社はするものだからという前提のみで出社を強要されている</h1>
物理作業等でオフィスや現地での作業をあるのは致し方無いですが、出社し、オンラインの中で終日働くのであれば
それは疑義があると思います。次にセキュリティの都合という話も多々お聞きしますが、それは現状維持であればの言い訳に過ぎません。<b>ルールやシステム、仕組み等を再整備すれば可能になる</b>ことも多々あると思います。
自宅でエンジニアリングをしWeb会議で済ますことができれば会議室の問題もクリアできますし、通勤の時間的負担（個人）、金銭的負担（会社）が共になくなるのです。
課題はマネジメント（管理職）にあることを直視しないで他のルールにしている企業を本当によく見かけます。

<h1>2.事実上、派遣である</h1>
SES（システムエンジニアリングサービス）の企業によくみられる光景です。特にこちらの契約形態では派遣ではないので、場所の制限はないものの、客先常駐となるケースが多いです。
現地に上長がいるならマシですが、現地に頼れる上長がいないと、派遣よりメンタル的に厳しい場合があります。
この手の企業は30－50人のエンジニアに一人の営業がついている場合が多く、その方がメンタルケアもする場合も多い印象です。


<h1>3.会社が学ぶことを勧奨していない、そもそも推奨もしていない</h1>
企業の考え方がはっきりと出るのこちらの項目。業務時間中は労務（サービス）を提供すべきであって、就業中に学ぶことなど一切認めずそれ自体は業務外（よーは、給与払わないわよ）でやりなさいと言っているケースです。
その中でも資格（IPAや各種ベンダー資格）を取得すると一時金や手当が増えるケースはまだましかもしれません。
業界団体でのイベントや、業務時間中の勉強会への参加などを業務事情を互いに考慮しながら学べる環境はエンジニア生活の中でも重要になってくるのではないでしょうか？


<h1>4.各種エンジニアリングを作業として見なしている </h1>
エンジニアリング＝クリエイティブな仕事と見なしているか、工場ロボットのオペレーターのように一定の費用（給与）で一定の作業をお願いするかという点は働く側にとって重要です。
タスクが振ってもらるより、イシューを投げかけられ、それをどのように解決するかが経営と現場が互いに成長するのではないでしょうか？それには<b>お互いの信頼関係を築くことが重要</b>です。


<h1>5.メールと電話が社内コミュニケーションの基本になっている </h1>
コミュニケーション環境についてもここ5－10年の変化が著しい分野です。
まず電話は同期型コミュニケーションで、互いの時間を同時にロックインするものであり、且つ文字データに残りづらいので速報性が必要か、ハイコンテキストのやり取りに絞るべきなのが私個人の持論です。
また、メールについては非同期コミュニケーションとしては良いものの、リアルタイム性や、情報の整理の点でメールサーバや、メーラーに依存するものが多く、工夫で乗り切っている印象です。
チャットシステム（Slack,Line,Teams等）を導入し、<b>情報をできるだけオープン</b>にそして、その業務に関わるメンバー間での良質なコミュニケーションプラットフォームになるようにすべきです。
いまだにお客様とのやり取りは先方都合もあるので仕方ないとしても社内はチャットシステムに変えるべきです。


<h1>6.エンドユーザの様子が全く見えず、何のために誰のお役に立てるかを理解できる環境ではない </h1>
システムが大型化や、機能部分を割ってしまい、その説明もないまま、エンジニアリングを行う環境にあることはお客様にとってもエンジニアにとっても不幸でしかありません。
データのI/Oだけこなせばいいみたいな話は今後は開発環境の高度化で作業量が減る一方ですし、工夫する余地が限られます。やはりお客様の課題を一緒に受け入れ、<b>課題をエンジニアリングで解決する事</b>が重要なのではないでしょうか。


<h1>7.ロートルが若いエンジニアの活躍を喜ばない </h1>
テクノロジーの進歩が速い業界にあるあるですが、新しいテクノロジーの獲得が年齢と共に劣ってきます。
本来的には年齢は関係ないはずなのですが、少なからず本人が意識しないと置いていかれるのも事実です。
事実をそのまま受け入れ、ロートルなりにできる事を増やすという事もありですし、若手に負けず切磋琢磨するのも素晴らしいことだと思います。
その一方で、若手の意見を受け入れないであったり、赤ん坊扱いしていたり、そもそも自分の立場を維持するためにマウントを取ったりしている企業は要注意です。若いエンジニアリングの挑戦や学びの場を提供していこうとしている会社であることは確認すべきです。

<h1> さいごに </h1>
以上、７つのルール（ポイント）について解説をしました。
<b>エンジニアのクリエイティブ性を解放させることがIT経営では非常に重要</b>でそのために会社は何ができるか、エンジニアはその良質な環境の元に個人キャリアとお客様の成功を共に実現し会社に還元することが重要ではないでしょうか？

尚、当社では社員を募集しております！７つのルールを実現できる様に日々精進しておりますのでご興味あればご応募ください！
https://recruit.bitstar.jp/
FlutterのLint警告を非表示にする(name source files using lowercase with underscores)


#はじめに
AndroidStudioのFlutterで公式Lintが変更されて、
dartファイル名はlowercase_with_underscoresでなければ警告が出るようになった。
（2021.11前後に変更が行われた？）
（name source files using lowercase with underscores）

ファイル内のソース全てが警告対象として、黄色波線が表示されて非常に邪魔になった。
まっとうな解決方法としては、dartファイル名をLint警告にしたがって変更すればよい。
しかし、開発中の既存ソースファイル名を直すのは手間であるため、警告を非表示にすることにした。

https://dart-lang.github.io/linter/lints/file_names.html


#解決策
1.pubspec.yamlと同じ階層にanalysis_options.yamlを追加する。（無ければ）

2.analysis_options.yamlに無視対象を設定する。

```analysis_options.yaml
include: package:flutter_lints/flutter.yaml

linter:
  rules:
    #追加
    file_names: false

```
[py2rb] issubset

# はじめに
移植やってます
# issubset (Python)
```python
set.issubset(other)
```
`set`の全ての要素が`other`に含まれるか判定します。

https://docs.python.org/ja/3.7/library/stdtypes.html#frozenset.issubset
# subset? (Ruby)
```ruby
self.subset?(set)
```
`self`が集合`set`の部分集合である場合に true を返します。

https://docs.ruby-lang.org/ja/latest/method/Set/i/proper_subset=3f.html
# メモ
+ Python の issubset を学習した
+ 道のりは遠そう
【Rails】マイグレーションのGeneratorから学ぶ命名規則

# はじめに

マグレーションファイルは以下のようにGeneratorで生成することができます。

`$ rails generate migration AddPartNumberToProducts`

参考: https://railsguides.jp/active_record_migrations.html

このGeneratorは特定のファイル名が与えられたとき、よしなにテンプレートファイルを出力します。
ここでは、Railsが用意しているパターンを調査し、マイグレーションファイルにどのような名前をつけるのがRails Wayに沿っているかを調査します。

## add_X_to_Y

カラムやインデックスなどを追加するマイグレーションファイルを生成します。

```
$ rails g migration add_token_to_user auth_token:token
```

↓

```ruby
class AddTokenToUser < ActiveRecord::Migration[7.0]
  def change
    add_column :users, :auth_token, :string
    add_index :users, :auth_token, unique: true
  end
end
```

## remove_X_from_Y

カラムやインデックスなどを削除するマイグレーションファイルを生成します。

```
$ rails g migration remove_user_ref_from_products user:references
```

↓

```ruby
class RemoveUserRefFromProducts < ActiveRecord::Migration[7.0]
  def change
    remove_reference :products, :user, null: false, foreign_key: true
  end
end
```

## join_table

名前の一部に `join_table` が含まれているとテーブル結合を作成するマイグレーションファイルを生成します。

```
rails g migration create_join_table_customer_product customer product
```

↓

```ruby
class CreateJoinTableCustomerProduct < ActiveRecord::Migration[7.0]
  def change
    create_join_table :customers, :products do |t|
      # t.index [:customer_id, :product_id]
      # t.index [:product_id, :customer_id]
    end
  end
end
```

## create_X

テーブルを作成するマイグレーションファイルを生成します。

```
rails generate migration create_products name:string part_number:string
```

↓

```ruby
class CreateProducts < ActiveRecord::Migration[7.0]
  def change
    create_table :products do |t|
      t.string :name
      t.string :part_number

      t.timestamps
    end
  end
end

```


## Railsのソースコード

メモとして残しておきます。

- `/lib/rails/generators/active_record/migration/migration_generator.rb`
- `/lib/ruby/gems/2.7.0/gems/railties-7.0.0/lib/rails/generators/generated_attribute.rb`
- `/lib/rails/generators/active_record/migration/templates/migration.rb.tt`
VS CodeでWindows環境変数のPATHが反映されないときは

#結論
以下のように「新しいターミナル」を選択して、ターミナルインスタンスを作成する。
![スクリーンショット (10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2351428/eaa2a0b2-8160-d6ff-a574-63d816508781.png)

リストから新規作成されたインスタンスを選択する。
![スクリーンショット (14).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2351428/4764d4ea-c582-6cd9-ec1e-a6e0a2dca4d4.png)

#環境
VS Code 1.63.2

#経緯

Windowsの環境変数Pathに追加したパスがVS Codeのターミナル上でなぜか反映されない。

VS Codeのターミナル上で
用語 'xxx' は、コマンドレット、関数、スクリプト ファイル、または操作可能なプログラムの名前として認識されません。と表示される。

だけど、Windows10にビルトインされているPowerShellではパスが通っていて、正常に動く。

VS codeを再起動しても変わらず悩んでいたが、

上記のように試したところ、すんなりパスが通った。
VSCode ターミナル上で CTRL + n, CTRL + p を有効にする

何番煎じかわからないですが、自分が使っている設定を📝しておきます。
VS Code のターミナル上のキーバインドを設定して、いい感じにターミナルを操作するやり方です。

## 設定方法
1. VSCode上で、コマンドパレットを開く (CTRL + Shift + P)
2. key json と入力するとメニューが絞り込まれる。 基本設定:キーボードショートカットを開く(JSON) を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1982/4a05cc76-c5c5-48da-c898-52df6bd15f5c.png)


## 設定内容
以下の設定内容を記載します。

```json
// 既定値を上書きするには、このファイル内にキー バインドを挿入します
[
    {
        "key": "ctrl+p",
        "command": "cursorUp",
        "when": "terminalFocus"
    },
    {
        "key": "ctrl+n",
        "command": "cursorDown",
        "when": "terminalFocus"
    },
    {
        "key": "ctrl+f",
        "command": "cursorRight",
        "when": "terminalFocus"
    },
    {
        "key": "ctrl+b",
        "command": "cursorLeft",
        "when": "terminalFocus"
    },
    {
        "key": "ctrl+a",
        "command": "cursorHome",
        "when": "terminalFocus"
    },
    {
        "key": "ctrl+e",
        "command": "cursorEnd",
        "when": "terminalFocus"
    },
    {
        "key": "ctrl+d",
        "command": "deleteRight",
        "when": "terminalFocus"
    },
    {
        "key": "ctrl+h",
        "command": "deleteLeft",
        "when": "terminalFocus"
    },
    {
        "key": "ctrl+k",
        "command": "deleteAllRight",
        "when": "terminalFocus"
    },
    {
        "key": "ctrl+m",
        "command": "type",
        "args": { "text": "\n"},
        "when": "terminalFocus",
    }
]
```
CoderDojoに参加して（2021）

社会活動の一環として、また楽しいので、気が向いた時にCoderDojoのメンターとして参加している。
（主宰の方は大変だと思うが、気ままに参加できる環境に感謝・・）
![PXL_20211113_025642564.PORTRAIT (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61550/85fb5fe0-c2c2-c1ff-c0b6-9701122eeac9.jpeg)


#CoderDojoとは

https://coderdojo.jp/

全世界に広がるプログラミング道場である。
「日曜日はプログラミング教室のボランティアでーー」と話すことがあるが、厳密に言うとプログラミング教室ではない。
CoderDojoの説明スライドにある、「公園のようなプログラミングを楽しむコミュニティ」という表現がしっくりくる。
公園で自由に遊んでいる子供に「逆上がり教えるから1列に並べ！！」と言ったらヒエー！ヤバい人！であるが、子供から「お姉さん、逆上がり教えてー」と言われたら喜んで教える。
そんな雰囲気である。（？）

#やっていること

基本的にはScratchでプログラムしているが、「公園」なのでなんでもいい。
エディタでガシガシプログラムしてもいいし、
行っているDojoには３Dプリンタもあるので３Dモデリングをしたって良い。
ずっと💻でイラストを描いている子なんかもいる。

と、説明したところで、
にわかメンターなのでたまに行っては自分の作業をしたりして楽しい時間を過ごしているのだが、久しぶりに行ったところ、小学生のレベルが進化していた。

---初心者---
###マインクラフトのプログラム（2年生）
当ブリゲードでは、「初心者で来てみました。まだ作りたいものはない。」という方にはアワーオブコードのマインクラフトのプログラムに挑戦してもらっている。
繰り返し（for）や分岐（if）について理解できたら💯
というか、2年生でプログラムを理解できるのがびっくりである。

https://hourofcode.com/jp/learn

---スクラッチマスター---

###ハエたたきゲーム（5年生）
猫逃げを応用して作成しているようだった。
叩いたときの処理をこうしてみては？という意見が他の小学生から出ていて、
アイディアが湧いて楽しい感じだった。

###鬼から逃げるゲーム（5年生）
鬼のキャラクターがとてつもなくおっかなかった。

###クリーパー爆発（5年生）
クリーパーが爆発するらしい。
「猫逃げ」を応用して自分の世界観をつくっていた。

---やばい---

###遺伝的アルゴリズム（6年生）
スクラッチの猫の遺伝子を作成し、それに沿って増える遺伝的アルゴリズムである。
すごすぎてここまでくると作ろうとしているものの理解が大変になってくる。
一応、お手本のプログラムはあるようだが、これに挑戦しようとする知的好奇心が素晴らしい。

###顔認識プログラム（3年生）
AI（！）を使って表情を認識し、キャラクター（そばっち）が悲しい表情だったら「元気だして」とか言ってくれるプログラムである。小学3年生でこれを作れるなんて、エンジニアの端くれとしては震えて眠る日々である。
（追記）こちらの作品は岩手日報プログラミングコンテストで優勝したらしい！おめでとう！👏

![PXL_20211113_030126002.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61550/9c6a9a31-718a-6474-c8c9-85891717a23c.jpeg)


さて、Scratchで私も作ってみた。
「借り物競走」
猫が指示するものをクリックして借りてくるというものである。
永遠にできてしまうので、時間制限や点数などもつけてみたい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61550/812a5721-a023-64e0-4878-09af543c3aa5.png)


<iframe src="https://scratch.mit.edu/projects/613227492/embed" allowtransparency="true" width="485" height="402" frameborder="0" scrolling="no" allowfullscreen></iframe>


https://scratch.mit.edu/projects/613227492

<iframe src="https://scratch.mit.edu/projects/613227492/embed" allowtransparency="true" width="485" height="402" frameborder="0" scrolling="no" allowfullscreen></iframe>



高校生や大学生もたまに来てもくもくとなにか作っているので、ぜひ来てほしい。

https://www.kokuchpro.com/event/f41e0e1b0eb81cacf27bd36b1ed96407/

こんな感じ↓（CoderDojo公式サイトより）

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

enjoy programing!
Rust のビルドを rust-lld で速くしてみる

下記 κeen さんの記事で [mold](https://github.com/rui314/mold) を教えてもらいました。

https://keens.github.io/blog/2021/12/20/moldwotsukautorustnobirudogahayakunaru/

しかし、Windows 環境では使えないようです。

そこで rust-lld.exe を使ってビルドを高速化してみたいと思います。

## インストロール

下記コマンドで rust-lld.exe がインストロールされます。

```
rustup component add llvm-tools-preview
```

## 設定

各 crate 毎に設定するなら Cargo.toml があるフォルダに .cargo フォルダと、その下に config.toml ファイルを作ります。


```
.
├── .cargo          // New!
│   └── config.toml // New!
├── Cargo.toml
└── src
    └── main.rs
```

config.toml に以下の内容を書きます。

```toml:config.toml
[target.x86_64-pc-windows-msvc]
linker = "rust-lld.exe"
```

`C:\Users\xxxxx\.cargo\config.toml` に書くとすべてのビルドに設定が適用されます。

## 結果

actix-web のサンプルプログラムを私の環境でビルドしてみた結果です。

| msvc    | rust-lld |
|:-------:|:--------:|
| 4.9 sec | 4.4 sec  |

たいして変わんねー:sob:

## WSL

WSL Ubuntu 20.04 環境でも同じく actix-web のサンプルプログラムをビルドして比較してみました。

| gcc      | llvm-lld | mold   |
|:--------:|:--------:|:-------:|
| 11.5 sec | 5.3 sec  | 4.9 sec |

gcc のリンカが遅すぎる？:thinking:
[py2rb] insert

# はじめに
移植やってます
# insert (Python)
```python
parsed_sequence.insert(0, nterm)
```
リストの0番目にntermを挿入します。
今回は先頭に追加の意味になります。

https://docs.python.org/ja/3.7/library/array.html#array.array.insert
# unshift (Ruby)
```ruby
parsed_sequence.unshift(nterm)
```
~~0番目以外だと大変でした。~~
**[追記]**
コメント欄にて教えていただいたのですが、`ruby`にも`insert`ありました。

```ruby
parsed_sequence.insert(0, nterm)
```
https://docs.ruby-lang.org/ja/latest/method/Array/i/insert.html

@obelisk68 さん、ありがとうございました。
# メモ
+ Python の insert を学習した
+ 道のりは遠そう
Salesforceでキャンペーン階層を表示する際に発生するエラーについて

Salesforceのキャンペーンレコードについて、
下記画像のボタンをクリックすればキャンペーン階層の閲覧が可能です

![キャンペーンボタン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/9d4d2a38-4f82-b537-f9c6-973f9792b92e.png)

しかしながら、上記ボタンクリック時に以下のようなエラーが発生する場合があります
![キャンペーン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/82213f19-342d-ad94-bda9-b9acbb4a3ea1.png)

「キャンペーンへのアクセス権がありません」

上記メッセージが出た場合、以下の内容を確認ください

（参考ヘルプ：https://help.salesforce.com/s/articleView?id=sf.campaigns_hierarchy_setup.htm&type=5）


##確認場所1 項目「親キャンペーン」の閲覧権限があるか

キャンペーン項目の「親キャンペーン」の閲覧権限がないユーザはエラーが発生するようです。
下記設定のように親キャンペーン項目で閲覧権限が付与されているか確認ください
![親キャンペーン２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/b94a5b9e-83e9-8b16-cbed-a306d9746f82.png)


##確認場所2 「「階層の列」の新規　を作成」

下記のように「階層の列」から新規をクリックし作成することでエラーが消える場合があるようです
![キャンペーン1220.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/8fc87f0c-3ed6-7ad4-f9ac-65f536c0bfdd.png)

※参考の質問
https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000A8wiHSAR
unityで音響関係の実装についてのまとめ

#unityで音を出し方法
unityでゲーム開発をするとき、重要な要素となる『音』。
今回は、その音の鳴らし方についてまとめます。
その中でも、シーンを跨いでも音が鳴らせるような実装方法についてまとめます。

##音が鳴るのに必要な2つの要素
音が鳴るためには、
音を出すスピーカー（iphoneやラジカセ（もはや死語？？）など）
音源（音源データやカセット・CDなど）
の2つが必要になります。
①に対応するのがAudio Source
②に対応するのがAudio Clip(s)
です。

また、シーンを跨いで音を鳴らすために必要な要素も2つあります。
1つは、Audio SourceとAudio Clip(s)を含み、シングルトン化したSoundManager Scriptを含むオブジェクト。
もう１つは、シングルトン化したSoundManager Scriptから関数を呼び出すためのSceneManager Scriptを含むオブジェクト。

ちなみに、直接SoundManagerから関数を呼び出さない理由は、シングルトン化されているためシーンの移動毎にSoundManager Scriptを含むオブジェクトが破壊と再生されるため、うまく関数を呼び出すことができなくなってしまうからです。

##それぞれのコーディング

```C#:SoundManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class SoundManager : MonoBehaviour
{
　//--シングルトン始まり--
    public static SoundManager instance;

    private void Awake()
    {
        if (instance == null)
        {
            instance = this;
            DontDestroyOnLoad(this.gameObject);
        }
        else
        {
            Destroy(this.gameObject);
        }
    }
    //--シングルトン終わり--

    public AudioSource audioSourceBGM; // BGMのスピーカー
    public AudioClip[] audioClipsBGM;  // BGMの音源

    public AudioSource audioSourceSE; // SEのスピーカー
    public AudioClip[] audioClipsSE;// SEの音源
   
   //シーンに応じたBGMの鳴らす方法
    public void PlayBGM(string sceneName)
    {
        audioSourceBGM.Stop();
        switch (sceneName)
        {
            default:
            case "TitleScene":
                audioSourceBGM.clip = audioClipsBGM[0];
                break;
            case "GameScene":
                audioSourceBGM.clip = audioClipsBGM[1];
                break;
        }
        audioSourceBGM.Play();
    }

　// SEを一度だけならす方法
    public void PlaySE(int index)
    {
        audioSourceSE.PlayOneShot(audioClipsSE[index]); 
    }
}

```

```C#:GameManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class GameManager : MonoBehaviour
{
    //シーンが移動するときに、BGM変更しとSEを鳴らす
　 //シングルトン化しているので、instanceで呼び出す
    public void ToTitle()
    {
        SceneManager.LoadScene("TitleScene");
        SoundManager.instance.PlayBGM(“TitleScene")
　　  SoundManager.instance.PlaySE(0);
    }
}
```


あとは、ヒエラルキー上にからのオブジェクトを設置し、それぞれのscriptをアタッチします。
SoundManager ScriptをアタッチしたオブジェクトにはAudioSurceコンポーネントを2つ設置し、1つはSoundManager ScriptのaudioSourceBGMに貼り付け、もう１つは同じくSoundManager ScriptのaudioSourceSEに貼り付けます。
これによって、音を出すスピーカーが設置されます。

あとはBGMとSEそれぞれの音源データをSoundManager Script上のaudioClipsBGMまたはaudioClipsSEの配列の中に貼り付けていきます。

SoundManager Script上でClipsのindexを変更することで、音源データの変更が可能となり、状況に応じた音を鳴らすことができるようになります。
初心者にはハードルが高い列挙型の使い方まとめ

#初心者にとって難しい列挙型

初めて列挙型を見た時、正直意味がわかりませんでした。
何回か自分でコードを書いていくうちに、なんとなく理解が深まってきたので、まとめようと思います。

##列挙型の意味
列挙型は、⓪ある集合を①条件によって②任意のグループに分類し③そのグループに特定の行動を行わせる、時に利用します。

すっごい抽象的でわかりづらいので、具体的な例で説明します。
⓪ ある学校のクラスメートを、
① 誕生日に応じで、
② 星座によって分類し、
③ それぞれの星座にちなんだポーズをとってもらう。
こんな時に列挙型を使用します。

伝わりましたかw？？

##具体的なコード
今回、Playerの行動を列挙型で表現します。

```c#:PlayerManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerManager : MonoBehaviour
{
  //プレイヤーの動きを分類、上記説明の②の部分
    public enum DIRECTION_TYPE
    {
        STOP,
        LEFT,
        RIGHT,
        UP,
        DOWN,
    }

    DIRECTION_TYPE direction = DIRECTION_TYPE.STOP;
    float speedX , speedY;
    new Rigidbody2D rigidbody2D;


    void Start()
    {
        rigidbody2D = GetComponent<Rigidbody2D>();
    }

　 //プレイヤーの動きを分類するための条件づけ、上記説明の①の部分
    void Update()
    {
 　//方向指示キーの入力を受けている部分
        float x = Input.GetAxis("Horizontal");
        float y = Input.GetAxis("Vertical");
　//方向指示キーの入力に応じて、分類に振り分けている部分
        if (x == 0 && y == 0)
        {
            direction = DIRECTION_TYPE.STOP;
        }
        else if (x > 0)
        {
            direction = DIRECTION_TYPE.RIGHT;
        }
        else if (x < 0)
        {
            direction = DIRECTION_TYPE.LEFT;
        }
        else if (y > 0)
        {
            direction = DIRECTION_TYPE.UP;
        }
    }

 //プレイヤーの動きを分類に応じた行動を指示、上記説明の③の部分
    void FixedUpdate() 
    {
 //それぞれの分類に応じでプレイヤーの座標を変更している
            switch (direction)
            {
                case DIRECTION_TYPE.STOP:
                    speedX = 0;
                    speedY = 0;
                    break;
                case DIRECTION_TYPE.RIGHT:
                    speedX = 3;
                    speedY = 0;
                    break;
                case DIRECTION_TYPE.LEFT:
                    speedX = -3;
                    speedY = 0;
                    break;
                case DIRECTION_TYPE.UP:
                    speedX = 0;
                    speedY = 3;
                    break;
                case DIRECTION_TYPE.DOWN:
                    speedX = 0;
                    speedY = -3;
                    break;
            }
            rigidbody2D.velocity = new Vector2(speedX, speedY);
        
    }
}
```

上記のように、条件に応じて分類分けを行い、その分類に応じて異なった関数を実行したい場合に列挙型は用いられます。
T-DASHを使おうと考えましたが、残念ながら...


普段はSalesforceでゴリゴリカスタム画面を作っています。Apexのコードはテストクラスが書ける（いや書かないとデプロイできない）ので自動化できています。しかしながら画面の方のテストは今一つ自動化が難しい（できるらしいですが、設定が面倒でやる気が全くわきませんでした）

もしかしたら、いいツールが現れたのかもと期待が大きかったのですが....


結果:使っているPCが古い32ビットCPUなので、プログラムを走らせることができず断念....

ちゃんと読んでいたらマシンのスペックが書かれていたかもしれないですがね。

仕方ない潔く諦めよう。手持ちの機材では無理でした。

Salesforceでの開発では開発者コンソールしか使ってないので（この方がどこでも開発できる）、PCはお古でも十分問題ないんですね。
VRChatプレイヤーによるParticle System解説 ～Force over Lifetime, Color/Size/Rotation over Lifetime, by Speed Module編～

:::note warn
この記事はUnity 2019.4.29f1の記事です
:::
[Limit Velocity over Lifetime / Inherit Velocity Module編](https://qiita.com/abcde_kind/items/e502ab41ae26341545b9) <<  ここ  >> [External Forces, Noise Module編](https://qiita.com/abcde_kind/items/f9702c960b3d25db7d35)
# はじめに
この記事は**ちょっとParticle System触れるようになったけどまだまだ知らないパラメーターだらけで抵抗感がある人向け**にじゃあ全項目解説しようという記事です。

**パーティクル？シェーダー？憧れるけどよくわかんない…**という人は最近は[VRCUnity勉強会][link-1]などで初歩の初歩から解説してくれる講座などが解説されているのでそこに参加してみたりするといいでしょう。
[link-1]:https://discord.gg/mtvTTyM
その他にこの記事はアドベントカレンダーにしてParticle Systemの記事を増やしてパーティクルへの抵抗感を減らしてやろうという企みもあります。

##Force over Lifetime, Color/Size/Rotation over Lifetime / by Speed Moduleってどこ？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2386883/2c4a7ae2-2ce7-6a3c-c1ec-f67ea5135c63.png)
ここ
##Force over Lifetime
**パーティクルにかかる力を決めるModule**
スピードではなく力を決めるためその方向に加速し続けることになる
デフォルトでXYZで分かれてる
単位 m/s^2
###Space
デフォルト Local
**座標軸の基準をローカルかワールドにするか決めるパラメーター**
Localはこのオブジェクト基準
###Randomize
<font color=red>Two ConstantsあるいはTwo Curvesモードを使ってるときのみONにできる</font>
**力のかかる方向が毎フレーム変わるようにするパラメーター**
OFFにしているとパーティクルが出た瞬間から変化しない
##Color over Lifetime
###Color
**パーティクルが出てから消えるまでどのように色が変わるかグラデーションで決めるパラメーター**
##Color by Speed
###Color
**パーティクルの速度に応じてパーティクルがどういった色に変わるかグラデーションで決めるパラメーター**
###Speed Range
デフォルト  (0,1)
**上のグラデーションの横軸の範囲を決めるパラメーター**
##Size over Lifetime
Color over Lifetimeの大きさ版みたいな感じ
###Separate Axes
デフォルト OFF
**サイズをXYZに分けて制御するかどうか決めるパラメーター**
###Size
**パーティクルが出てから消えるまでどのようにサイズが変わるかグラフで決めるパラメーター**
##Size by Speed
###Size
**パーティクルの速度に応じてパーティクルがどういった大きさに変わるか決めるパラメーター**
###Speed Range
デフォルト  (0,1)
**上のグラフの横軸の範囲を決めるパラメーター**
##Rotation over Lifetime
###Separate Axes
デフォルト OFF
**サイズをXYZに分けて制御するかどうか決めるパラメーター**
###Angular Velocity
デフォルト 45 (-3.402823e+38~3.402823e+38)
単位 度/s
**1秒間に何度パーティクルが回転するか決めるパラメーター**
##Rotation by Speed
<font color=red>Angular VelocityをConstantにしているとRotation over Lifetimeとほぼ同じ挙動をする</font>
###Angular Velocity
デフォルト 45
単位 度/s
**1秒間に何度パーティクルが回転するか決めるパラメーター**
###Speed Range
<font color=red>Angular VelocityをCurveにすると操作できるようなる</font>
**Curveの横軸を決めるパラメーター**
##おわり
というわけでForce over Lifetime, Color/Size/Rotation over Lifetime, by Speed Moduleの解説でした
似たような項目が続くしまとめちゃえってまとめましたがタイトルが散らかってますね、正規表現とか使えば良いんですがそれも伝わりづらいので苦肉の策です
次はExternal Forces, Noise Moduleです
****
[Limit Velocity over Lifetime / Inherit Velocity Module編](https://qiita.com/abcde_kind/items/e502ab41ae26341545b9) <<  ここ  >> [External Forces, Noise Module編](https://qiita.com/abcde_kind/items/f9702c960b3d25db7d35)
【OpenAI】 GPT-3を試してみる

#GPT-3とは
OpenAIが公開している自然言語処理系のAIモデルです。
文章の生成、文章の要約、質問への回答、翻訳などができます。

#試してみる
https://beta.openai.com/examples
こちらにログイン

## チャット
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/b5180fae-6de2-63e0-ec7a-f30b64765460.png)
人 今何してる？
AI 私は邪悪なエイリアンと戦い、宇宙船を維持しています。

## Q＆A
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/225d8420-7fe2-bfd7-4998-3c1269c1ed1d.png)
GitHub ActionsでGemをリリースする

この記事は[岩手県立大学とか、岩手の人たち Advent Calendar 2021](https://qiita.com/advent-calendar/2021/ipu)の 7 日目の記事です！

https://qiita.com/advent-calendar/2021/ipu

## はじめに

gem のリリースを自動化したいと思い、GitHub Actions でできないかを調査してみました。

gem のリリースの方法は主に 2 つあります。

- `gem push`
- `release`タスク
  - `bundler`にある rake タスク

GitHub Actions の公式ドキュメントには`gem push`の例はありますが、`release`タスクを用いた例はありません。

https://docs.github.com/ja/actions/automating-builds-and-tests/building-and-testing-ruby#publishing-gems

そこで、`release`タスクを用いた場合の方法を記事にしておきます。

## workflow の準備

`release`タスクで gem をリリースする際の workflow は以下のようになります。

```yml
name: Ruby Gem
on:
  workflow_dispatch:
jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: 3.0.0
      - run: bundle install

      - name: Setup git config
        run: |
          git config --global user.email "YOUR_EMAIL"
          git config --global user.name "YOUR_NAME"

      - name: Publish to RubyGems
        run: bundle exec rake release
    env:
      GEM_HOST_API_KEY: ${{ secrets.RUBYGEMS_API_KEY }}
```

Ruby のバージョンや、event、`git config`に関してはお好きなものにどうぞ。

### 解説

[公式の gem push の例](https://docs.github.com/ja/actions/automating-builds-and-tests/building-and-testing-ruby#publishing-gems)と異なる部分の解説です。

```yml
- name: Setup git config
  run: |
    git config --global user.email "YOUR_EMAIL"
    git config --global user.name "YOUR_NAME"
```

`release`タスクは、gem のバージョンに応じた git tag を自動で付与し、push してくれます。
そのため、`gitconfig`を用意してあげる必要があります。

```yml
- name: Publish to RubyGems
  run: bundle exec rake release
```

`release`の rake タスクです。

```yml
env:
  GEM_HOST_API_KEY: ${{ secrets.RUBYGEMS_API_KEY }}
```

`bundler`の`release`タスクの内部では`gem`　（`gem push`の`gem`）が使われています。
そして、`gem`では API Key を`GEM_HOST_API_KEY`環境変数から読むことができます。

> https://guides.rubygems.org/command-reference/
> The push command will use ~/.gem/credentials to authenticate to a server, but you can use the RubyGems environment variable GEM_HOST_API_KEY to set the api key to authenticate.

そのため、`~/.gem/credentials`に API Key を用意しなくても認証できます。

## Secrets に API Key を設定する

GitHub リポジトリの`Settings`から Secrets を設定できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352836/6d06bf34-7afd-6548-f6fe-fd4e64b59534.png)

## 課題

RubyGems へのリリースに OTP 認証を必須とする設定もあります。
`GEM_HOST_OTP_CODE`環境変数に OTP コードを設定してあげると良さそうなのですが、現状試した限りだとうまく読み取ってくれませんでした。
もし、OTP 認証をうまくやれる方法があれば教えていただけると幸いです。
[py2rb] re.findall

# はじめに
移植やってます
# re.findall (Python)
```python
>>> re.findall(re.compile(r'([^A-Z-]*)([A-Z])'),'bAcAab-cdAZa')
[('b', 'A'), ('c', 'A'), ('cd', 'A'), ('', 'Z')]
```
この場合、`A-Z`は単独で`a-z`は先頭/A-Z/-に挟まれた文字列を抽出しています。

https://docs.python.org/ja/3.7/library/re.html#re.findall

https://qiita.com/dmkd3006/items/cadf6943491ea12400db#pattern_01_01
# scan (Ruby)
```ruby
> 'bAcAab-cdAZa'.scan(/([^A-Z-]*)([A-Z])/)
=> [["b", "A"], ["c", "A"], ["cd", "A"], ["", "Z"]]
```
`String#scan`で行けそう。

https://docs.ruby-lang.org/ja/latest/method/String/i/scan.html
# メモ
+ Python の re.findall を学習した
+ 道のりは遠そう
Dockerを基礎理解した-概念編-

#はじめに
実務でFunctionsからCloud Runを入れるかも？という話がチームの中であがり、
その前提知識となるDockerコンテナの基礎知識を学ぼうと思い、Dockerを勉強し始めた。

まずは

- Dockerfile, Docker-compose.yml を使って、ローカルに環境を構築できること


を目標に学習した。
※個人ブログから技術的アウトプットはQiitaへ引っ越ししたので、こちらは過去に書いたブログとなります。

![https://cdn-ak.f.st-hatena.com/images/fotolife/h/hiroism0329/20210321/20210321125054.png](https://cdn-ak.f.st-hatena.com/images/fotolife/h/hiroism0329/20210321/20210321125054.png)

# Dockerとは

いろんな切り取り方で定義が様々あるが、こんな感じで理解

> Dockerとは、Docker社が開発しているコンテナ型の仮想環境を作成、配布、実行するためのプラットフォーム。
> 

その他、以下で理解

- Linuxのコンテナ技術を使ったもの
- ミドルウェアのインストールや各種環境設定をコード化して管理
- ソフトウェア開発で実施されてきた構成管理や自動化などを、サーバーの各種設定やミドルェアのインストールなどにも適用したもの
- 仮想化技術の1つ

# 仮想化とDockerとVM

- **仮想化とは、サーバーの中にあたかも違うOSのサーバーが入っているように見える技術。**
- Docker以前に**VMという仮想化技術が人気に。**

では、DockerとVMは何が異なるのか？？

**一番の違いは**

> サーバー仮想化（VM）では、各OSを立ち上げて各アプリケーションを動かしている のに対し， 
コンテナ仮想化（Docker）では、各仮想マシン毎にOSを立ち上げておらず、各仮想マシンがホストOSのカーネルを共有している。
> 

**結果、Dockerは従来のVM（サーバー仮想化）より軽量で省エネな仮想化を実現できている。**

![https://cdn-ak.f.st-hatena.com/images/fotolife/h/hiroism0329/20210214/20210214230711.png](https://cdn-ak.f.st-hatena.com/images/fotolife/h/hiroism0329/20210214/20210214230711.png)


# コンテナとは

めちゃくちゃ意訳すると

> ある前提となる状態のもとで、あるコマンドを叩いたときに発生する処理の内容を再現するもの
> 

例えば、このコンテナという技術を使えば、環境構築、コードの実行を行うことができる。

結果、下記に詳細を書くが、PCが異なっていてもAさんとBさんはコンテナを共有することで同じ環境でコンテナを立ち上げて、そのコンテナ上で開発ができるようになる。

便利そう...！

### 図イメージ

![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563702/49952dae-5561-c42f-b65f-e28484ae6a38.png)


# Dockerのメリット -できること-

1. コード化されたファイルを共有することで、どこでも誰でも同じ環境が作れる
2. 作成した環境を配布可能

結果、作成したDockerイメージを他の人にも渡して使ってもらうことで、

**各自の環境のバージョンずれ防止**や、**開発環境準備の短縮化**にもつながる。

また、チーム開発では**新規メンバ参画時のコスト削減**や、**環境依存問題**を減らせる。

# Dockerのインストール

こちらで。

[Dockerでの基本操作](https://www.notion.so/Docker-22d610c068994e4eab3c726e506c8523)

# まとめ

- Dockerとは、Linuxのコンテナ技術を使って`コンテナ型`の仮想環境を作成、配布、実行するためのプラットフォーム。
- **仮想化とは、サーバーの中に違うOSのサーバーが入っているように見える技術。**
- Dockerのメリット複数あるが、従来の仮想技術よりも軽量で、作成したDockerイメージを他の人にも渡して使ってもらうことで、各自の環境のバージョンずれ防止や、開発環境準備の短縮化にもつながること。

# 基礎操作verはこちら
https://qiita.com/uehiro22/items/3f99c5f6399288acc7af
GNFA受験記

#はじめに
GNFA（GIAC Network Forensic Analyst）は、ネットワークフォレンジックの資格です。
この資格について日本語で書かれた記事は少ないので、私が受験した際の勉強法について記載します。

#GNFAについて
GREMは50問出題され、制限時間は2時間です。ほとんどの問題は4択です。
合格ラインは70%の正答率です。
ただし、受験後に公式サイトを確認したところ、50 - 66問、2～3時間、実技試験ありの試験に変わっていました。
これから受験する方はご注意ください。
また、（私が受験した際は）休憩は2回取れますが、2回合わせて15分です。15分の休憩が2回ではありませんので注意してください。

試験の内容は以下と公式サイトに記載されています。

Common Network Protocols
Encryption and Encoding
NetFlow Analysis and Attack Visualization
Network Analysis Tool and Usage
Network Architecture
Network Protocol Reverse Engineering
Open Source Network Security Proxies
Security Event and Incident Logging
Wireless Network Analysis

https://www.giac.org/certification/network-forensic-analyst-gnfa


また、GCFA、GREMと同様、紙媒体の資料は持ち込みが可能です。自分なりのメモ、カンニングペーパーを作って持ち込みましょう。

#事前知識
私は各種プロトコルに関する知識や、Squid、各種ログについては実務経験がありましたが、ワイヤレスネットワークフォレンジックや出題範囲に含まれるツールについての知識はあまり深くありませんでした。脆弱性診断やペネトレーションテストでよくでてくるHTTP等のプロトコルの知識はかなり役に立ちましたし、フォレンジック調査でよく目にするWebサーバのアクセスログの調査手法も役に立ちました。

#勉強方法
まず最初にトレーニングの録画ビデオ（オンライントレーニングだったため録画が見られた）をすべて見直し、実際に手を動かして演習を行いました。
一通りの録画ビデオを確認し、演習もこなした後、1回目の模擬試験を受験しました。この時点で74%の正答率だったので、手ごたえは十分でした。
誤答が多かった分野を再度復習し、2回目の模擬試験を受験しました。この時点で82%正答できていました。
これで十分準備が整ったと判断し、簡単に復習した後、本番の試験に挑みました。
ただし、結果としてギリギリ合格でしたので、8割を超えていたからといって油断できないと感じました。

#英語について
GIACの試験はすべて英語で行われ、翻訳ツールは紙の辞書や持ち込んだメモ以外は使うことができません。
模擬試験に比べると本番の試験の方が英語は理解しやすかったです。模擬試験の方が知らない単語が多い印象がありました。
持ち込んだメモにテキストや模擬試験に出てきた知らない英単語の和訳を書いて持ち込むと良いです。
非常に重要な点として、試験問題に回答することが目的であり、和訳が目的ではありません。なんとなく問題や選択肢が理解できたのであれば、それでOKとすべきです。7割くらいの理解度であっても、最も正しいと思われる選択肢を選んで先に進んだほうが良いでしょう。

#これから受験する人へのアドバイス
これから受験する方は、私が受験した時とは問題数、制限時間が異なりますが、私が受験した時点では時間的な余裕があり、残り20分ほど余裕をもって終了できました。実技試験ありになるともう少し時間的に厳しくなると思います。

特に、各種ツールの出力と、WireSharkやtcpdump等のフィルタについて正しく理解しておく必要があると思います。これらは実際に手を動かしておくと良いです。
また、全体として判断問題が多いと感じました。このような問題は持ち込んだメモだけでは回答が難しいように思いました。これも実際に手を動かすことで正答率が上がるものと思います。
一方で、GCFAやGREMと異なり、ある程度経験がないと回答が難しいと思われる問題も見られました。ただ、こういった問題でも、二択までは容易に絞れるので、正答率を上げることは可能だと思われます。

なお、最終的なスコアは70%でギリギリでした。

#次の目標
CISA
CISM
LPIC 300（更新目的）
AWSの資格
を検討中です。
【Git】ブランチを切り替え忘れて作業してしまった時の対処法-コミット前-

#はじめに
> ブランチ切らずに作業してしまった！
> 

Git始めたての頃はよくやってました。

いや、最近でもたまにあります。

そこで、ブランチを切り替えつつ、変更内容も引き継ぐ方法をまとめました。
※個人ブログから技術的アウトプットはQiitaへ引っ越ししたので、こちらは過去に書いたブログとなります。


# コミット前の変更を引き継ぎ、ブランチを変更する

未コミットの場合は、**スタッシュ** でOK

# SouceTreeのコマンドでスタッシュの手順説明

現場ではSouceTreeを使っているので、SouceTreeの手順を記載

### 1. 右上のスタッシュをクリック

![https://cdn-ak.f.st-hatena.com/images/fotolife/h/hiroism0329/20210112/20210112162913.png](https://cdn-ak.f.st-hatena.com/images/fotolife/h/hiroism0329/20210112/20210112162913.png)

### 2. スタッシュをクリック ⇨ メッセージ を記入

![https://cdn-ak.f.st-hatena.com/images/fotolife/h/hiroism0329/20210112/20210112163010.png](https://cdn-ak.f.st-hatena.com/images/fotolife/h/hiroism0329/20210112/20210112163010.png)

### 3. スタッシュされているか確認

![https://cdn-ak.f.st-hatena.com/images/fotolife/h/hiroism0329/20210112/20210112163436.png](https://cdn-ak.f.st-hatena.com/images/fotolife/h/hiroism0329/20210112/20210112163436.png)

### 4. スタッシュを戻す場合

- 戻す場合は「On mytest:bを追加」をダブルクリック。次に「OK」をクリック
- 「適用した変更を削除」にチェックを入れると、一時退避の項目から「On mytest:bを追加」も削除されます
PHPerKaigi 2022のプロポーザルを開始しました。

この素晴らしいカンファレンスにいくつかの講演を提出する

"PHPerKaigi（ペチパーカイギ）は、現在PHPを使用している、過去にPHPを使用していた、これからPHPを使いたいと思っているエンジニアが、技術的なノウハウを共有するためのイベントです。"

https://fortee.jp/phperkaigi-2022
【JavaScript】Dateオブジェクトを使った経過時間の取得

# はじめに
FireStoreのTimestampクラスでフィールドにDateオブジェクト渡すと取得時にTimestampクラスが返ってきますが、ここの経過時間の取得でハマった（というか勘違い）したことがあったので、サクッと振り返ります。
※個人ブログから技術的アウトプットはQiitaへ引っ越ししたので、こちらは過去に書いたブログとなります。


# Dateとは

- 簡単にいうと日時を取得。**ミリ秒単位**
- ミリ秒とは？ ：1秒 = 1000ミリ秒

[Date - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date)

そう、冒頭のここ。

> JavaScript の日時は、基本的に協定世界時 (UTC) の1970年1月1日深夜0時からの経過ミリ秒数で指定されます。
> 

なんで強調しているかというと、ここでハマった。

というか知らずに**秒と勘違いしてた。**

```jsx
 publicationDate: new Date(episode.publicationDate.seconds).toISOString()
```

結果...

```jsx
> "publicationDate": "1970-01-19T08:01:21.660Z"
```

と、1970年の値が返ってきて意図していない経過時間が返ってきている。

ちなみにこの数字は

```jsx
publicationDate: new Date(episode.publicationDate.seconds).toISOString(),
console.log('episode.publicationDate.secondsは？ : ', episode.publicationDate.seconds)

> episode.publicationDate.secondsは？ :  1584081660
```

と、 1970年1月1日深夜0時から1584081660秒（約19日分）経過した時間。

# 解決策

ミリ秒に変換

- Timestampクラス

```jsx
// ミリ秒に変換
Timestamp.toMillis()
```

[firebase.google.com](https://firebase.google.com/docs/reference/js/firebase.firestore.Timestamp?hl=ja#tomillis)

もしくは**求められた秒数に1000を掛ける**とミリ秒数が返ってくる。

```jsx
 publicationDate: new Date(episode.publicationDate.seconds * 1000).toISOString()
```

結果...

```jsx
> "publicationDate": "2020-03-13T06:41:00.000Z"
```

取得したい経過時間がとれた。

その他、Timestampクラスメソッドは...

```jsx
// Dateに変換
Timestamp.toDate()
```

など他にもある。

[Timestamp | JavaScript SDK | Firebase](https://firebase.google.com/docs/reference/js/firebase.firestore.Timestamp?hl=ja#tomillis)

# まとめ

- JavaScriptのDateオブジェクトは基本的に協定世界時 (UTC) の1970年1月1日深夜0時からの経過ミリ秒数で指定。
- FirestoreのTimestampクラスでミリ秒に変換する場合、Timestamp.toMillis()で取得可能。もしくは求められた秒数に1000を掛けるとミリ秒数を求めることができる。
スクロール時にUITableViewのヘッダーの背景を透明にする方法

#問題
UITableViewにて任意のヘッダーが表示されている場合、セルをヘッダーの下に隠れるまでスクロールすると、背景が非透明色に変化するという現象がありました（下図）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655077/53f10e3b-b1cd-9021-b161-7d9cdc8addd0.png)
ヘッダーの`contentView.backgroundColor`を`UIColor.clear`に設定するなどを試みましたが、スクロールすると背景色は非透明になってしまいます。

#解決策
AppDelegateの`application(_:didFinishLaunchingWithOptions:)`内で下記を記述することで、背景が非透明にならないように設定することができます。

```swift
var bgConfig = UIBackgroundConfiguration.listPlainCell()
bgConfig.backgroundColor = UIColor.clear
UITableViewHeaderFooterView.appearance().backgroundConfiguration = bgConfig
```

#おわりに
同じようなことでハマっている方のお役に立てればと思います。
また、認識が間違っているなどのご指摘がありましたら、ご教授いただけますと幸いです。

#環境
- Xcode 13
- iOS 15.0
- Swift 5.0

#参考
- [Stack Overflow - White background in table section header in iOS14](https://stackoverflow.com/questions/64355156/white-background-in-table-section-header-in-ios14)
- [UITableViewのSectionHeaderをカスタムする](https://tokizuoh.dev/posts/btxfpjkx0d7c995t/)
github Pages README.md が表示されるのを防ぐ [VueCLI]


１：vue.config.js を作成

```javascript
module.exports = {
  publicPath: './',
  outputDir: 'docs/',
};
```

中にこれを追加

これで docs ディレクトリの下にビルド生成物ができる

２：.github というフォルダを作成

なかに README.md を移動

３：npm run build

４：github に push

５：公開

↓ を参考にしてね

https://docs.github.com/ja/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site

※サイト内の 5 番の発行元のフォルダは docs を選択

※フォルダの作成は vue.config.js、.github ともに一番上のディレクトリで OK です。
Postman multipart/form-data形式でファイルをPostする方法 個人メモ

## 目的

- Postmanにてmultipart/form-data形式でファイルをPostする方法をメモ的にまとめる。

## 方法

1. 任意のリクエストを作成して「Body」をクリックし「form-data」選択する。

    ![Postman.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/7a4e7eb1-a80b-9795-5d23-ad9be10a21d0.png)

1. 任意のキー名を入力する。

    ![Postman.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/51de0311-c1a8-602f-dc17-f085119d2032.png)

1. 入力したキー名と同じ枠の右側にマウスカーソルを持ってゆくとデフォルトで「Text」と表示されたプルダウンメニューが表示されるのでクリックする。

    ![スクリーンショット_2021-12-20_14_16_34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/6b5e35fc-488a-d2b2-5b34-6e18b92a8ad4.png)

1. 「File」を選択する。

    ![スクリーンショット_2021-12-20_14_15_25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/7a1d3026-d78a-4788-3ab1-c53e0c86f09d.png)

1. 後は「VALUE」の「Select Files」をクリックしてPostしたい任意のファイルを選択してPostするだけ。

    ![Postman.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/1f2dd26b-f85a-ed07-2bd7-d9bd78008dcd.png)
初めてのBigQuery「saving and sharing query」について

***はじめに*** :earth_africa:
Googleが提供するGCPのサービスの一つであるBigQuery。
調べている中でBigQueryに関しての具体的な情報が日本語では特に少ないと感じ、記事を書くことにしました:lifter_tone1:
それでは、本日の題材であるsaving and sharing queryについて初めていきます！


***Query saving and sharing*** :feet:
背景
BiqQueryのプロジェクトで作ったクエリーを保存して、チームメンバー共有しよう〜なんて時に使える機能がsaving and sharingという機能です。
クエリーを保存する際に３つの選択肢があります。詳しくは下記URLの参考資料を見てください:art:
その３つの選択肢の中にPublicという選択肢があり、名前の通りグローバルにクエリーが共有できるんです。しかし、セキュリティー面で間違えて知らない人にうっかりリンクを共有してしまったら大変ですよね。

そこでクエリーを保存する時にPublicの選択肢を権限がある人のみに提供できるような機能がないのかなと探していました。（Publicを選択不可にする）

ネット上で探してもなかな見つからず、、、Googleカスタマーサポートに尋ねたところ「現在、ユーザー側にそのような変更ができる機能はありません。しかし、***google側の開発チームにお願いしてPublicの選択肢を不可にすることができます***」との回答がきました:point_up_tone1:


もともとGoogle内部で使用されていたサービスをGoogle外に製品として出すことで、セキュリティー上で必要となる機能が増えそうですね！


参考資料: [Google BigQuery](https://cloud.google.com/bigquery/docs/saving-sharing-queries)
Tips: ruby -runはオプションじゃない

## この記事は何

皆さんは `ruby -run`というコマンドを使ったことがあるでしょうか？
`ruby -run`を使うと`cp`や`mv`など、Unixコマンドの一部をrubyスクリプト内で利用することができるようになるため、`-e`オプションと一緒に

```bash
ruby -run -e cp hoge.txt hoge2.txt
```
のように、利用することができます。
しかし、https://docs.ruby-lang.org/ja/latest/doc/spec=2frubycmd.html を見ても、`-run`オプションは
存在しません。この理由をこの記事では紹介します。

## -rオプション
`-run`がオプションとして存在しない理由を探る前に、まず`-r`オプションを説明する必要があります。
https://docs.ruby-lang.org/ja/latest/doc/spec=2frubycmd.html
にある通り、`-r`オプションはスクリプト実行前に feature で指定されるライブラリを Kernel.#require するオプションです。
例えば`csv`ライブラリを使用したい場合は、以下のように使うことができます


```bash
ruby -rcsv -e 'CSV.read("hoge.csv")'
```

## unライブラリについて
次に`un`ライブラリについて説明します。
`un`ライブラリは組み込みのライブラリで

https://docs.ruby-lang.org/ja/latest/library/un.html

にある通り、Unix の基本コマンドの代替となるユーティリティを提供します。
このライブラリを`require`することで、以下のメソッドが利用できるようになります。

- Kernel#chmod
- Kernel#cp 
- Kernel#help 
- Kernel#httpd 
- Kernel#install 
- Kernel#ln 
- Kernel#mkdir 
- Kernel#mkmf 
- Kernel#mv 
- Kernel#rm 
- Kernel#rmdir 
- Kernel#touch 
- Kernel#wait_writable




## -runの正体
ここまでの説明で、気づいた方もいるのではないでしょうか？
そう、`-run`とは`un`ライブラリを`-r`オプションで`require`しているだけなのです！
`-run`が`run`と読めてしまうため、オプションと勘違いしやすいというTipsでした。
ApacheでpythonとflaskとSSLな環境を構築する

#前提環境
Apache 2.4.41
Python 3.8.10
Ubuntu 20.04.3
#参考

https://tech-blog.s-yoshiki.com/entry/9

https://gb-j.com/column/ubuntu-flask/

#環境構築
```shell-session
 $ sudo apt-get update
 $ sudo apt -y install python3-pip libapache2-mod-wsgi-py3
 $ sudo a2enmod wsgi
 $ sudo pip3 install flask
```

:::note
Web Server Gateway Interface (WSGI; ウィスキー) は、プログラミング言語Pythonにおいて、WebサーバとWebアプリケーション（あるいはWebアプリケーションフレームワーク）を接続するための、標準化されたインタフェース定義である。また、WSGIから着想を得て、他の言語でも同様のインタフェースが作られた。
引用：<a href="https://ja.wikipedia.org/wiki/Web_Server_Gateway_Interface">Wikipedia「Web Server Gateway Interface」2021年3月20日 (土) 12:13版</a>
:::
#Apache上の準備
##ディレクトリの作成
今回は `/var/www/app/` に作業ファイルを配置することとします。
権限の設定についてはこちらを参照(www-dataに自身を追加しているのであれば対策不要)

https://qiita.com/yuu1111main/items/77976d7ece0ecfb35157

```shell-session
 $ sudo mkdir /var/www/app
 $ sudo chown -R www-data:www-data /var/www/app
 $ sudo chmod 775 -R /var/www/app
```
##VirtualHostの設定
CloudflareのSSLを登録する方法についてはこちらの記事にて詳しく解説しています。（無料）

https://qiita.com/yuu1111main/items/2ab2b86f9fa4e24a0a8b#cloudflare%E3%81%AEssl%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B

```shell-session
 $ sudo vim /etc/apache2/sites-available/ドメイン名.conf
```
次の内容でファイルを作成します

```conf:ドメイン名.conf
<VirtualHost *:80>
    ServerAdmin 管理者メールアドレス
    ServerName ドメイン
    ServerAlias www.ドメイン
    DocumentRoot /var/www/app/
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    RewriteEngine on
    RewriteCond %{SERVER_NAME} =ドメイン [OR]
    RewriteCond %{SERVER_NAME} =www.ドメイン
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]

</VirtualHost>

<VirtualHost *:443>

    ServerAdmin 管理者メールアドレス
    ServerName ドメイン
    ServerAlias www.ドメイン
    DocumentRoot /var/www/app/
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    SSLEngine on
    SSLCertificateFile pemの場所
    SSLCertificateKeyFile keyの場所

    WSGIDaemonProcess app2 user=www-data group=www-data threads=5
    WSGIScriptAlias / /var/www/app/project/index.wsgi
</VirtualHost>
```
ファイルを保存したら次のコマンドを実行します

```shell-session
 $ sudo a2ensite ドメイン名.conf
 $ sudo systemctl restart apache2
```
その後、自分のドメインにアクセスして404が表示されたら成功です。

##ファイルの設置
そうしましたら、こちらを参考にファイルを置いていきます。

```shell-session
 $ cd /var/www/app/
 $ mkdir ./{project,project/app,project/app/controller}
```
###index.wsgi
```shell-session
 $ vim project/index.wsgi
```
```wsgi:index.wsgi
import sys, os
sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
from app.controller.index import app as application
```
###index.py
```shell-session
 $ vim project/app/controller/index.py
```
```py:index.py
from flask import Flask

app = Flask(__name__)

@app.route("/", methods=['GET'])
def index():
    return "Hello World!"

if __name__ == "__main__":
    app.run()
```
###完成系
```tree
project
|-- app
|   `-- controller
|       `-- index.py
`-- index.wsgi
```
その後、自分のサイトにアクセスしてHello world!と表示されれば成功です。
ちなみに、エラーログは`sudo cat /var/log/apache2/error.log`にて確認できます。
FreeBSDでBluetooth SPP

FreeBSDのBluetoothを試してみました。FreeBSDのBluetoothサポートはnetgraph(ng)というフレームワークの上に構築されています。BluetoothのUSBドングルを刺すといろいろなngのカーネルモジュールがロードされるのがkldstatで確認できます。

Bluetoothの中でもシリアル通信のためのプロファイルのSerial Port Profile(SPP)を確認します。すべてPINなどは使わない設定なので、hcsecdは使ってません。

確認したのは以下の三つのモジュールです。

# ESP32

EPS32には以下のプログラムを[PlatformIO](https://qiita.com/yamori813/items/e157190517f700badcce)でビルドして焼いておきます。

```c:test.ino
#include "BluetoothSerial.h"

BluetoothSerial SerialBT;

void setup() {
  SerialBT.begin("ESP32test"); //Bluetooth device name
}

void loop() {
  SerialBT.println("Hello World!");
  delay(1000);
}
```

Bluetooth USBドングルをつないだFreeBSD/amd64 13Rでスキャンしてみます。CSRの2.xなUSBモジュールを使いました。

```
% sudo hccontrol -n ubt0hci inquiry
Inquiry result, num_responses=1
Inquiry result #0
	BD_ADDR: 30:ae:a4:12:34:56
	Page Scan Rep. Mode: 0x1
	Page Scan Period Mode: 0x2
	Page Scan Mode: 00
	Class: 02:c1:10
	Clock offset: 0x6a57
Inquiry complete. Status: No error [00]
```

SPPのデーモンを上げます。

```
% sudo rfcomm_sppd -a 30:ae:a4:12:34:56 -t
rfcomm_sppd 1877 - - Starting on /dev/pts/1...
/dev/pts/1
```

距離などの問題で、電波が届かないのか、時々つながらないこともあります。

```
rfcomm_sppd: Could not obtain RFCOMM channel: Host is down
```

別のターミナルで、cuしてみます。

```
% sudo cu -l /dev/pts/1
Connected
Hello World!
Hello World!
Hello World!
```

# PIC32MX自作モジール

以前portしたsmalltoothのモジュールでも確認してみます。このモジュールは文字を受信するとACKの文字列を返します。

https://github.com/yamori813/smalltooth

スキャンしてみます。

```
% sudo hccontrol -n ubt0hci inquiry
Inquiry result, num_responses=1
Inquiry result #0
	BD_ADDR: 00:09:dd:12:34:56
	Page Scan Rep. Mode: 0x1
	Page Scan Period Mode: 0x2
	Page Scan Mode: 00
	Class: 18:01:04
	Clock offset: 0x6b3c
Inquiry complete. Status: No error [00]
```

SPPデーモンを上げます。

```
% sudo rfcomm_sppd -a 00:09:dd:12:34:56 -t
rfcomm_sppd: Could not obtain RFCOMM channel: Attribute not found
```

MacOS Xでは接続できるのですが、PIC32MXのSPPの実装が不完全なのだと思われます。

# HC-05

HC-05は小さなSPP専用モジュールなのですが、なぜかSPPで接続できません。

```
% sudo rfcomm_sppd -a 20:15:07:12:34:56 -t
rfcomm_sppd: Could not connect socket: Connection refused
```

HC-05の設定によるものか、FreeBSDのバグかもしれません。
Overleafを使ってSATySFiファイルを共同編集しましょう！

[SATySFi Advent Calendar 2021 2日目](https://adventar.org/calendars/6336)の記事です。

まずは、以下のツイートを見てください。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">そういえば <a href="https://twitter.com/hashtag/Overleaf?src=hash&amp;ref_src=twsrc%5Etfw">#Overleaf</a> って <a href="https://twitter.com/hashtag/SATySFi?src=hash&amp;ref_src=twsrc%5Etfw">#SATySFi</a> に対応しているんですね。 <a href="https://t.co/Vx1tXclDVU">pic.twitter.com/Vx1tXclDVU</a></p>&mdash; yasuo_ozu@量子コンピュータエンジニア (@yasuo_ozu) <a href="https://twitter.com/yasuo_ozu/status/1420990499243003910?ref_src=twsrc%5Etfw">July 30, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

Overleafを使えば、**Web上でSATySFiファイルを共同編集できます！！**

# どういうこと？

というのは半分ネタなのですが、以下真面目にいきます。

Overleafは、主にLaTeXで書かれた原稿を共同編集できるWebアプリです。
登録だけで手軽に使えるSaaS版が有名ですが、今回使うのは**オープンソース版**のOverleaf。これにSATySFiでも使えるように簡単な改造を施しました。
ここで説明する方法では、アプリをDockerを使って手動で起動して使う必要があり、また共同編集するためにはインターネットからアクセスできるような設定が別途必要になります。

# 起動

- **改造版のOverleaf**を入手します。
- **Docker**をインストールし有効化します。
- **docker-compose**をインストールします。
- 改造版Overleafのディレクトリで`docker-compose up -d`を実行します。

# アカウント作成

以下のページを参考に作業します。

https://github.com/overleaf/overleaf/wiki/Quick-Start-Guide

```
docker exec sharelatex /bin/bash -c "cd /var/www/sharelatex; grunt user:create-admin --email=joe@example.com"
```

上記コマンド実行中にパスワード入力用URLが表示されます。

# 画面操作

- http://localhost:80/ にアクセスしログインします。
- 「Create First Project」から「Blank Project」を選択しプロジェクトを作成します。
- すると下のような画面になります

![overleaf-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153096/6cade13a-2f0e-6976-32e4-67d1dc5c8a98.png)

左上の「新規ファイル作成」アイコンから「latexmkrc」ファイル(拡張子は無し)を作成し以下の内容を入力します。

```
`satysfi test.saty -o output.pdf 2>&1 > output.log`;
exit(0);
```

![overleaf-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153096/de0a977a-a4ad-45a6-d9e0-aa598db377ae.png)


左上の「新規ファイル作成」アイコンから「test.saty」ファイルを作成し以下の内容を入力します。

```
@require: stdjareport
document (|
  title = {test};
  author = {yasuo-ozu};
|) '<
    +p {hello}
>
```

緑色の「Recompile」を押すと、コンパイル結果が右側の画面に表示されます！

![overleaf-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153096/59a28e1e-c0ca-3797-ae8b-7c1d904cec0b.png)


# パッケージの追加について

SATySFiをさらに活用するためにパッケージをインストールしたくなると思います。その場合、現在のところWeb画面上でパッケージを追加することができないため、プロジェクト直下の`Dockerfile`を編集することになります。
現在制作中のパッケージマネージャ兼仮想環境`satyst`ができれば、`latexmkrc`のみの変更でパッケージを追加できるようになると思います。

# さいごに

OverleafはGit経由でも使える(http認証ですが)ので便利に活用できるのではないでしょうか。
classにfinalを付ける基準(Swift)

## はじめに

本記事は [Swift/Kotlin愛好会 Advent Calendar 2021](https://qiita.com/advent-calendar/2021/love_swift_kotlin) の20日目の記事です。

Swiftで `class` に `final` キーワードを付ける基準を考察します。

## 環境

- OS：macOS Big Sur 11.6
- Swift：5.5.2
- Xcode：13.2 (13C90)

## 「finalキーワード」とは？

`class` に `final` キーワードを付けると、そのクラスを継承できなくなります。

以下のように `final` キーワードが付いたクラスを継承しようとすると、 `inheritance from a final class 'Foo'` のようにビルドエラーが発生します。

```swift
final class Foo {}

class Bar: Foo // !!!: ビルドエラー
```

詳細は以下の記事がわかりやすいです。

https://qiita.com/shtnkgm/items/c985ab4b314b8572eccd

## 結論

先に結論を述べます。
大きく2パターンの結論があると考えました。

結論1

- 継承されていないクラスに目印を付けたい
- とにかくパフォーマンスを優先したい
- `final` を使っていなく、プロジェクトで `final` に関する方針もない

→ 継承されていない全クラスに `final` を付ける

結論2

- 継承できるかどうかを考えてクラスを設計していて、それをわかるようにしたい

→ 継承できる設計になっていないクラスにのみ `final` を付ける

追記

そもそもSwiftでクラスの継承はアンチパターンで、UIKitの都合などどうしても必要な場合のみ継承すべきなので、無条件で継承されていない全クラスに `final` を付けるのがベターだと思います。

https://twitter.com/koher/status/1497029134484082690?s=20&t=iJZEva2wMHzDT3H55joXeA

## 考察

結論だけ見てもわかりづらいので、詳細に考察していきます。

### 継承されていないクラスに目印を付けたい

今まで私はこの考えしかありませんでした。
Twitterなどで他にも様々な考えがあると知ったのが、本記事を執筆した理由です。

継承されていない全クラスに `final` を付けることで、クラスを見ただけで継承されているかどうかがわかり、可読性が高くなると考えています。
こうすることで「クラスに `final` が付いていない → このクラスは継承されているんだな」とわかるようになります。

簡潔にまとめると以下となります。

- `final` が付いている → 継承されていない
- `final` が付いていない → 継承されている

もし継承したくなったら `final` を外せばいいだけです。
ただSwiftで継承したいことはあまりないはずです。

### とにかくパフォーマンスを優先したい

6年半前の記事なので今と違うかもしれませんが、Appleの公式ブログで「 `final` や `private` を付けて動的ディスパッチを減らすことで、パフォーマンスが向上する」と明記されています。

https://developer.apple.com/swift/blog/?id=27

本記事で詳細は説明しませんが、とにかくパフォーマンスを優先するプロジェクトでは、継承されていない全クラスに `final` を付けるのがいいと思います。

Twitterを見る限りでは、2022/02/25現在でも `final` を付けてパフォーマンスが向上するケースは多そうです。
特に競プロでSwiftを使うときは `final` を付けるべきだと思いました。

https://twitter.com/takakengo/status/1496997592974389250?s=20&t=iJZEva2wMHzDT3H55joXeA

https://twitter.com/semisagi/status/1497070779405864960?s=20&t=iJZEva2wMHzDT3H55joXeA

### finalを使っていなく、プロジェクトでfinalに関する方針もない

そもそもプロジェクトで `final` キーワードを使っていなく、プロジェクトで特に方針がないパターンです。
まず方針を決めるべきだとは思いますが、特に決めない場合は、パフォーマンスの観点からも継承されていない全クラスに `final` を付けるのがいいと思います。

### 継承できるかどうかを考えてクラスを設計していて、それをわかるようにしたい

「 `final` は継承されているかどうかの目印ではない、継承できない設計になっているクラスにのみ `final` を付けるべきだ」
「クラスを使う側によってクラスの実装が決まるのはおかしい、属性は他に依存せずに決めるべきだ」
このような意見をTwitterなどで確認しました。

どちらも私にはない考えだったので、目から鱗が落ちました。
確かに継承されていない全クラスに `final` を付けると、継承できる設計になっているかどうかはわかりません。

簡潔にまとめると以下となります。

- `final` が付いている → 継承できるように設計されていない
- `final` が付いていない → 継承できるように設計されている

## おまけ: デフォルトで継承できないようにすべき？

Kotlinはデフォルトでクラスが継承できず、 `open` キーワードを付けることで継承できるようになります。

Swiftもデフォルトで継承できないように議論がされていますが、実現には至っていません。

https://forums.swift.org/t/proposal-sealed-classes-by-default/3164/84

## おわりに

どちらの方針を採用するかはプロジェクトごとに決めるのがいいと思います。
私の好みは変わらず「継承されていない全クラスに `final` キーワードを付ける」ですが、他の考えを知れて勉強になりました。

Swift以外の言語でもいいので、 `final` キーワードの使いどころに関する公式ドキュメントや、他の意見がありましたら、教えていただけると嬉しいです :relaxed: 

以上 [Swift/Kotlin愛好会 Advent Calendar 2021](https://qiita.com/advent-calendar/2021/love_swift_kotlin) の20日目の記事でした。
明日は @katopan さんです。

## 参考リンク

- https://twitter.com/the_uhooi/status/1472731613574631431?s=20
- https://twitter.com/uhyo_/status/1472732501038989315?s=20