OmniAICreator/Qiita-1.07M huggingface dataset:
サーバーサイドGoogleタグマネージャーについて調べた時にみたリンク集

# 背景
- ITP対策の一環でサーバーサイドGoogleタグマネージャーについて調べた
- そもそも、Googleタグマネージャーについてよくわかっていないのでそこから調べた
- リンク集め的な

# そもそもタグマネージャーってなに？

### [[Google公式]タグマネージャーヘルプ](https://support.google.com/tagmanager/answer/6102821)
- そもそもタグマネージャーって何っていう概要が掴める

### [【Google タグマネージャー解説①】Google Tag Manager とは？](https://www.youtube.com/watch?v=6yli7TCCGUQ)
- タグマネージャーの使用イメージが掴める

# ハンズオンで仲良くなる

### [[GoogleAnalyticsAcademy]Google Tag Manager Fundamentals](https://analytics.google.com/analytics/academy/course/5)
- ハンズオンしながらタグマネージャーの設定の雰囲気掴める

# サーバーサイドタグマネージャーって何？
![スクリーンショット 2021-11-02 19.00.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20307/0f2605f8-dc7e-aa9a-d1dd-cf2c6cd4fa23.png)


https://developers.google.com/tag-manager/serverside?hl=ja

- サーバーサイドタグマネージャーの概要が掴める
- 実際にサーバーサイドGTMを構築して実際に動かしてみるとよりイメージ沸く
  - 例えば、cloud functionでentrypoint作っておいて、サーバーサイドGTMからGA4とcloud function両方に送る
- 確認用のサイトはblogger(カスタムドメイン機能)が便利
  - [Bloggerで独自ドメインを設定する](https://www.howtonote.jp/blogger/domain/index1.html)
- safariにexpireが2年のcookieが入るのを確認する(ITP対応)

# カスタムテンプレートって何？

### [GTMにてカスタムテンプレート機能でオリジナルのタグ・変数が作成可能になりました](https://ayudante.jp/column/2019-05-24/18-04/)
- カスタムテンプレートが何をしているのか、何が嬉しいのかがイメージ掴みやすい

##### ポイント
- 自由度の高いタグや変数を定義できる
- カスタムテンプレート用のAPIを使って実装する必要があり、開発慣れている人じゃないとつらい
- [サーバーサイドタグ設定API](https://developers.google.com/tag-manager/serverside/api?hl=ja)を使って実装
- 「GTMへ登録されている変数」をカスタムテンプレート内で参照したい場合は、別途「項目」としてユーザーに変数を入れられる入力項目を用意しないといけない

### [[Google公式]カスタム テンプレートのクイック スタートガイド](https://developers.google.com/tag-manager/templates)
- カスタムテンプレート使ってタグを作成するイメージが掴める

# カスタムテンプレートクライアントとは？

### [BUILD A CUSTOM UNIVERSAL ANALYTICS CLIENT FOR SERVER-SIDE TAGGING](https://www.simoahava.com/gtm-tips/build-custom-universal-analytics-client-server-side-tagging/)
- サーバーサイドタグマネージャーのコンテナのみ、カスタムテンプレートでクライアントが作成できるもの
- この記事絵はカスタムクライアントでsafariの7日間のクッキーを2年間に焼き直す方法を紹介してくれる
    - http通信のset-cookieを行えるため可能
- この方GTM使って色々記事書いているので今後とてもお世話になりそう
【Vue.js】v-else-if

#はじめに
こんにちは！
今回は【Vue.js】v-else-ifについてアウトプットしていきます！

#v-else-ifとは
`v-if`→`v-else-if`→`v-else`といった感じで使われます。
`v-if`でない時は`v-else-if`が表示される。そうでもない時は`v-else`というイメージです。
Javascriptでいうところの`else if`に相当します。


#書き方・解説
例題として信号機の色の示す意味を出力するプログラムを書いていきます。

```HTML:HTML
  <p v-if="color === 'red'">
    Stop
  </p>
  <p v-else-if="color === 'yellow'">
    Caution
  </p>
  <p v-else-if="color === 'blue'">
    Go
  </p>
  <p v-else>
    Not red/yellow/blue
  </p>
```
```Vue.js
 var app = new Vue({
   el: "#app",
   data: {
     color:'red'
   }
 })
```
![スクリーンショット 2021-10-24 15.11.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2114750/0dc3c152-0cbb-a36f-bfab-2e5d08086cf9.png)

Pタグの中に「もしcolorの中身がredだったら、Stopを表示する。」
といったように、「もしcoolorの中がredではなくyellowだったらCautionと表示する。」
`v-if`→`v-else-if`→`v-else`を使っていきます。
また、`v-else-if`の場合は複数回使用可能です。
Vue.jsのdata内にcolorプロパティを設置し値を入力することで表示されます。
最後に、`v-if`→`v-else-if`どちらでもない場合は`v-else`が表示されるようになります。

#まとめ
記述の順番は`v-if`→`v-else-if`→`v-else`。
`v-else-if`は複数回使用可能。


#最後に
今回はv-else-ifについてアウトプットしました。
今回の記事を読んで質問、間違い等あればコメント等頂けると幸いです。

今後ともQiitaにてアウトプットしていきます！

最後までご愛読ありがとうございました！
R.swiftとSwiftLintを導入する(cocoaPods編)

## はじめに
毎回忘れるので、よく使用する二つのライブラリの導入手順を一つの記事にまとめます。

## R .swiftとは
Storyboardや画像、カラーが簡単に取得できるライブラリです。


## SwiftLintとは
勝手にコードのチェックを行ってくれるライブラリです。
可読性の向上や小さなミスがなくなります。
例：ネストが深すぎる、空行、キャメルケースになってないなど、、、


## R.swiftの導入手順(CocoaPods編)
開発環境
xcode12.4


#### 1.Podfileに以下を追記

```
pod 'R.swift'
```
※SwiftLintも一緒に導入する場合は以下のように記述します。

```
pod 'R.swift'
pod 'SwiftLint'
```

#### 2.`com + S` でPodfileを保存

#### 3.ターミナルで`pod install`を実行

#### 4.scriptを追加
##### `New Run Script Phase` からRun Scriptを追加する。
![スクリーンショット 2021-11-02 17.46.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692883/f0419e04-4975-8350-24bd-f457dd832e60.png)

##### Run Scriptを追加したら、以下をスクリプトに記述。

```
"$PODS_ROOT/R.swift/rswift" generate "$SRCROOT/R.generated.swift"
```

##### Input Files の + を選択し以下を記述。

```
$TEMP_DIR/rswift-lastrun
```

##### Output Files の + を選択し以下を記述。

```
$SRCROOT/R.generated.swift
```

##### 以下のようになっていればOK！
※わかりやすいように「Run Script」から「Run Script(R.swift)」に修正してます。
![スクリーンショット 2021-11-02 17.49.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692883/6390f551-e46e-666e-f1cf-be575691d773.png)

#### 5.Run Scriptを移動させる(大事！！！！)
Run Scriptは`[CP] Check Pods Manifest.lock`と`Compile Sources`の間に
移動させる。
![スクリーンショット 2021-11-02 18.56.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692883/1ba38afe-5e69-5da5-03fe-5d9cf2c2cb24.png)


#### 6.`com + B` でビルド

#### 7.最後に`R.generated.swift`ファイルをxcodeに追加
ビルドすると`R.generated.swift`ファイルが、
Finderの`アプリ名App`フォルダに追加されます。
「R.generated.swift」ファイルをxcodeプロジェクトにドラッグ&ドロップで追加。
※AddFileからでもOK


以上でR.swiftの導入は完了です。

## SwiftLintの導入手順(cocoaPods編)
開発環境
xcode12.4

#### 1.Podfileに以下を追記
※R .Swift導入時に追記して`pod install`まで完了している場合は1~3までは不要

```
pod 'SwiftLint'
```

#### 2.`com + S` でPodfileを保存

#### 3.ターミナルで`pod install`を実行

#### 4.scriptを追加
`New Run Script Phase` からRun Scriptを追加する。
![スクリーンショット 2021-11-02 17.46.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692883/f0419e04-4975-8350-24bd-f457dd832e60.png)

Run Scriptを追加したら、以下をスクリプトに記述。

```
"${PODS_ROOT}/SwiftLint/swiftlint"
```

以下のようになっていればOK！
![スクリーンショット 2021-11-02 18.35.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692883/4de5447f-ded4-6a1b-7a9a-c7957a268c22.png)

#### 5.「.swiftlint.yml」ファイルの作成 ( 必須ではない )
このファイルではSwiftLintのルールをカスタムします。
ターミナルで以下を実行。

```
touch .swiftlint.yml
```

ファイルを開く。

```
open .swiftlint
```

中身の例です。

```
disabled_rules:
- notification_center_detachment
- force_cast
- force_try
- todo
- trailing_whitespace
- type_body_length
- file_length
excluded:
- Pods
- R.generated.swift
line_length:
 warning: 300
 error: 400
 ignores_comments: true
function_body_length:
- 150 # warning
- 300 # error
identifier_name:
 min_length: 1
 max_length: 70
type_name:
 min_length: 1
 max_length: 50
nesting:
 type_level: 3
function_parameter_count: 7
```



以上でSwiftLintの導入も完了です！
ビルドして、警告が出ていればOKです！


## 注意点
最後に、今回はCocoaPodsで導入しましたが、
他の方法で導入する場合はScriptに記載する内容が変わってくるので注意が必要です。
AWS VPCをプライベートサブネットか判定して作成するスクリプト


#普通にVPC作成すると、プライベートサブネットかどうかをバリデーションしてくれない
Amazon VPCはAWS上に構築するプライベートなネットワーク空間のことです。
ですが作成時にプライベートサブネットかどうかをバリデーションしてくれません。:weary:
意図せずパブリックなIPレンジでもVPCを作れてしまいます。
そのためプライベートサブネットか判定して作成するスクリプトを作成してみました。

python3の標準モジュールであるipaddressモジュールが凄く便利です！

# 開発環境
Python3.8.7
#実装 
（IAMユーザー作成、aws configureは割愛します）
例：VPCのCIDR 172.32.0.0/24　をboto3testのNameタグで作成しようとするとき

```python
import boto3
import ipaddress

CIDR = '172.32.0.0/24'

def create_vpc(CIDR):
    client = boto3.client('ec2')
    response = client.create_vpc(
    CidrBlock=CIDR
    )
    client.create_tags(
    Resources=[response['Vpc']['VpcId']],
    Tags=[{'Key': 'Name', 'Value': 'boto3test'}])

if ipaddress.ip_network(CIDR).is_private:
    create_vpc(CIDR)
else:
    print("VPCレンジがパブリックIPです。作成を中止します")
```
#終わりに
実際にコンソール作業でパブリックIPのCIDRでVPCを作成してしまう事がありました
その後VPCやEC2再構築が必要になりました:scream:
気をつける、だと難しいかと思いスクリプト化しました。
Eclipse EGit で「変更なしを想定」したファイルを「変更なしを想定しない」状態に戻す

## まえがき
「変更なしを想定」したけどやっぱり戻したい！場合の設定
検索したところ解除設定はあまり見つからなかったので残します。

## 環境
Eclipse (4.21)
EGit (5.13)

## 設定
1. 戻したいファイルを右クリック
1. 「チーム」→「拡張」→「変更なしを想定しない」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108113/89871edb-83f8-4b56-0157-302954079698.png)

以上、お疲れさまでした！
AfterEffects  エクスプレッション　wiggle()

#■エスクプレッションとは
プログラミング言語を用いて
キーフレームを打つ事。

メリット：たくさんキーフレームを打ったりするのをコードで代用できる。

###▼wiggle()
エクスプレッションのコードの一つ
ランダム

``` swift
//wiggle(1秒間に何回,広げたい数値の幅)
wiggle(10,100)
```
上記で位置にエクスプレッションかけた場合1秒間に10回,数値100までの数字ランダムで動くになる。

![スクリーンショット 2021-11-02 18.30.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558142/558e1494-4269-963e-905d-6a02b443de39.png)
エクスプレッションを扱う場合タイマーマークでoption+クリック

####■完成
![wiggle.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558142/7996b970-0d89-e78e-6861-a037632f7891.gif)

■参考Youtube動画
https://www.youtube.com/watch?v=72HJo5azam0
exists

- existsの引数は行の集合である。
- existsは二階の述語である。
- existsはsqlで存在量化子を使うための述語である。
- 全称量化子を存在量化子の否定で書くことができる。

条件Pを満たさない、あるx(の集合？)を取得するクエリ

```
select DISTINCT m1.meeting,m2.person
from Meetings m1 CROSS join meetings m2
WHERE not EXISTS(
    SELECT *
    from meetings m3
    WHERE m1.meeting = m3.meeting
    and m2.person = m3.person
)

```

「すべての教科が50点以上であるようなx」をとるクエリを書く。全称命題と存在命題を考えてみる。前提は以下の通りです(※数学記号の使い方が間違っていると思うので、ご指摘歓迎です、特にP(x)のなかでiを動かせるようにしているのですが、ここが微妙)。


```math

一人の生徒に絞って考える。

\begin{flalign}
&X = \{iの点数 \}_{i={国語、算数、英語、理科}} ,x \in X \\
&P(x)= xの要素xiは50以上である(i=...)

\text すべての教科が50点以上である
&\lceil\forall xi \in X, P(xi)_{i=...}\rfloor \text { の否定は }\\
&\text すべての教科が50点以上でないxが存在しない\lceil\neg\exists xi \in X, \neg P(xi)_{i=...}\rfloor

\end{flalign}

```

ということになる。これを実装する。





例2
ある乗客のすべての行について(バインドに対応、この例では各乗客一行だが)
男性ならば年齢が60歳以上,女性ならば年齢が20歳以上である行の集合を取得
ポイント
・passengeridでバインド
・and で式を使用して真理値の判定を使用することで条件分岐可能

```
SELECT passengerid,sex,age
FROM train TS1
WHERE sex IN ('male', 'female')
AND NOT EXISTS
    (SELECT *
        FROM train TS2
        WHERE TS2.passengerid = TS1.passengerid
        AND 1 = CASE WHEN sex = 'male' AND age < 60 THEN 1
                        WHEN sex = 'female' AND age < 20 THEN 1
                        ELSE 0 END)
-- GROUP BY passengerid
-- HAVING COUNT(*) = 1
order by passengerid asc;
```

・existsはhavingと比較して
・パフォーマンスが良い
・平の行をとってこれる
の2点で優れている
PostgreSQLにおけるNULLの挙動

#### PostgreSQLにおけるNULLのソートでは、NULLは常に一番最後に配置

```sql
SELECT
*
FROM class_b
ORDER BY age ASC;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1347377/18f7eadf-7129-b661-201e-f721af489d24.png)

#### NULLと文字列の連結の結果は常にNULL

```sql
-- PostgreSQLにおけるNULLとの文字列連結
SELECT
*,
name || CAST(age AS VARCHAR(10)) AS hoge
FROM class_b;
```
```
GitHubCopilotをつかってわかったこと

## はじめに

先日 GitHubでウェイトリストに登録した

GitHubCopilotが利用可能になりましたが、

実際に使ってみて使い方が分からず、

Qiitaで調べてもそれについての記事が少ないため、

仕方なくYouTubeで英語の紹介動画を翻訳して見てみました。

そして使ってみると、以外にも凄かったので紹介します。

## 構文をソースコードから自動補完

これが1番嬉しかったです。

例えば 自作サービス **[プロフセンド](https://prof.gumieprof.com)** 開発中、

Copilotが**JavaScriptのイベント処理**や**CSSのデザイン**を

コードから**自動で補完**してくれました。

これは 作業がはかどりそうです。

## 関数名から処理を補完

これはたまに使う可能性がありそうです。

**関数の名前**から簡単な処理を**補完**してくれる。

例えば、関数名を｢random｣にすると

引数に入れた数字からランダムな数字を出力します。

**シンプルでちょっと難しい**機能です。

## コメントから処理を補完する

これはちょっと分からりません。

**コメント**から処理を**補完**してくれるようですが、

英語も簡単なものしか分からず、

翻訳サービスを使っても 簡単に上手くいきません。

わかる方はコメントください。

## まとめ

改良ポイントが沢山ある、希望のサービスでした。

とくに 最後のところ。コメントが日本語に対応すれば、日本人でも使えそうです。

GitHubさん、OpenAIさん、頑張ってください。
SlackアプリをHerokuで運用中

Slackのアドベントカレンダーでも紹介したのですが


https://qiita.com/geeorgey/private/a8dceb57f9d122e20893

現在5つのSlackアプリをHeroku上で運用しています。

Herokuでのアプリ運用にはHeroku特有の癖みたいなのがあるので、それをクリアしたテンプレートみたいなものがあると便利なのですが、こちらに作ってあります。

https://github.com/geeorgey/vue_flask_template

フロントエンドをVue.js
バックエンドをFlask(python)にして、すぐにWebアプリを立ち上げることができるようになっています。

お試しされる場合は最初のこちらを御覧ください。

https://qiita.com/geeorgey/items/ace37bd92841c9d1a378

こちらも参考になると思います

https://qiita.com/geeorgey/private/fb99637d4024cbaf0d37

## SlackアプリをHerokuで運用する
もともとなぜHerokuで作ったのかというと、Slackの中の人が提供するサンプルがHerokuにデプロイできるように作られていたからなのですが、今では手放せなくなりました。
今日は、なぜ手放せなくなったのかという話です。

### デプロイが簡単
先の記事にも書いたと思うのですが、Heroku特有の癖さえ乗り越えてしまえばあとはとても簡単です。
ローカル環境
→Githubにデプロイ
→HerokuとGithubをコネクトして、オートデプロイ設定をONにしておくことで、テスト環境のHerokuに更新が自動的に反映される

加えて、Heroku パイプラインという機能を使ってステージングとプロダクション環境を接続してあるのですが、これをやっておくと、ステージング環境をクリアした場合に、ボタンクリックでプロダクション環境にプロモート出来てしまうのです。

![lnest-timelines_·_Pipeline___Heroku.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/0f966de9-c727-ed70-39ef-b66b980748e7.png)

Githubからオートデプロイされる所では、ビルドに時間がかかるのですが、これをクリアしてしまえば、ボタンを押してほぼ瞬間的に本番環境が切り替わります。これが本当に楽。素晴らしいですね。
パイプラインの詳細はこちら

https://devcenter.heroku.com/ja/articles/pipelines

### ドメインの設定が楽
CNAMEに設定するだけでとても簡単。
SSL化もボタン一つでやってくれます。
*注意　CloudFlare経由の場合、キャッシュしてるとSSL化に失敗します。DNSのみにして設定しましょう。

![slack-all-timeline_·_Settings___Heroku.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/c3b1e7a1-5557-5b5c-9e73-bc48a3f832ca.png)

## 障害がほぼ無い
3年ほどWebサービスを運用していますが、障害でアクセス不能になったことがほぼありません。
これは良いですね。

## まとめ
ということで、簡単な紹介ではあるのですがHerokuで全然インフラまかなえちゃうぞというご紹介でした。
Slackアプリも稼働中です。是非見ていってください

- OYASUMI bot https://lne.st/oyasumilink
- TIPS https://lne.st/tips
- TimeLine for Slack https://lne.st/wr21
- YOKOKU for Slack https://lne.st/4cdy
- TASUKARU-TaskALL- https://lne.st/3x1u

### OYASUMI bot
Googleカレンダーのスケジュールに「休み」等の、休暇判定キーワードが入っていた場合に、自動的にSlackをスヌーズ状態に変更します。
メンションがあった場合に、メンションした相手にその日は休暇ですというレスを付けます。
スタッフの休暇を気持ちよく過ごしてもらう為のアプリです。

### TIPS
Slack用のリマインダーアプリです。
デフォルト機能のリマインダーは、一つのスケジュールに一つのメッセージの設定しか出来ません。
このアプリでは、一つのスケジュールに複数のメッセージを登録し、ランダムで指定された時間にpostします。
チャンネル特有のノウハウ等をスケジュール登録しておくことで、自然と情報が浸透する状態を作ります。


### TimeLine for Slack
全ての公開チャンネルのpostを一つのチャンネルにまとめるタイムラインチャンネルを生成するアプリです。
一部のチャンネルのみを集めたミックスチャンネルを作成すると、自分が必要なチャンネルだけのタイムラインを作り出すことが出来ます。
オプション機能として、メッセージ転送時にDeepL翻訳を挟むことが出来ます。

### YOKOKU for Slack
OYASUMI botの応用です。
例えば「営業」というキーワードが入った予定だけを抽出したいと思ったことはありませんか？
カレンダーをいちいち検索するのは手間がかかります。
このアプリを用いれば、特定のキーワードが入った予定を、特定のチャンネルに流すことが出来ます。

### TASUKARU 
Slackで色々な人からメンションをもらって混乱したことはありませんか？
何か頼まれていたはずだけど思い出せない…　そんな状態からあなたを救います。
TASUKARUはSlack専用のタスクマネージャーです。
デフォルトのスレッドやメンション画面では、処理が終わったpostをアーカイブすることが出来ませんが、TASUKARUならそれが出来ます。
今アクションが必要なものだけに集中することができる、それがTASUKARUです。
SQLの内部評価ステップ

### NOT INの内部評価ステップ

```
not in
not in → not と in の同値変換
not と in → not (( = ) OR..( = ) OR ... )の同値変換
not (( = ) OR..( = ) OR ... )→ (not( = ) AND not( = ) AND not( = ))の同値変換(ドモルガンの法則)
(not( = ) AND not( = ) AND not( = ))→(( <> ) AND ( <> ) AND ( <> ))の同値変換
個々の評価式の中にnullが入ると TRUE and NULL and FALSE...
となり絶対にこれはTRUEを返さない。


col not in (value1,value2,value3)
not col in (value1,value2,value3)
not ((col=value1) OR (col=value2) OR (col=value3))
not(col=value1) AND not(col=value2) AND not(col=value3)
(col<>value1) AND (col<>value2) AND (col<>value3)

-- このステップで評価された値にnullが入っていると
-- 例えばラリーの行は
(age<>22) AND (age<>23) AND (age<>NULL)
(19<>22) AND (19<>23) AND (19<>NULL)
TRUE AND TRUE AND unknown
(TRUE AND TRUE AND unknown)=unknown
-- となり、andで評価されるのでtrueは絶対に返ってこない。
-- よってクエリの結果は空になる。


```

### ALLの内部評価ステップ

```
SELECT *
FROM hoge
WHERE age < all(22,23,null)

andで同値変換
SELECT *
FROM hoge
WHERE age<22 AND age<23 AND age<null

andの複数条件ではfalse>unknown>trueであるから、
この命題がtrueを返すことはない。

例えば10歳のレコードがあっても、
10<22 AND 10<23 AND 10<null
ture and true and unknown

となるので、条件式がtrueとなるレコードは一行もない。
```

関数の内部ステップでandに同値変換が行われる関数は、Nullが紛れてしまうと正しい実行結果が得られない。
Unityで他のクラスのコルーチンを呼ぶ

ステートマシンで遊んでて、状態を管理するクラスと実際の処理を行うクラスを分けたかったので、他のクラスのコルーチンを呼び出す方法を探してみました。

## 想定

以下のような呼び出しをしたくて、更に呼び出し先コルーチンはインスペクタ上から設定できるようにする方法を考えました。

```
class ClassA
{
  void Start()
  {
    なんらかの方法でここから ClassB の TestCoroutine を呼びたい
  }
}

class ClassB
{
  public IEnumerator TestCoroutine()
  {
    呼ばれたいー
  }
}
```


## やってみたこと（そして諦めたこと）

delegate でできそうに見えたのですが、インスペクタ上から設定する方法を考え出せず断念。
Action やら何やら考えてみたけど思いつきませんでした。

## ぐぐった

ずばり正解を書いてくださっている方がおりました。(外部サイト)
[【Unity】Invoke、StartCoroutineを別スクリプトのメソッドへ使う](https://www.zkn0hr.com/unity-otherscript-invoke-startcoroutine/)
地面に頭こすりつける程感謝。

言われてみればそのとおりで、`StartCoroutineって何者よ？` というのを冷静に考えればよかったのですね。。

## 作ってみた

```csharp:ClassA.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ClassA : MonoBehaviour
{
    [SerializeField]
    private GameObject otherObject;
    [SerializeField]
    private string coroutineName;

    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("Start");
        var otherInstance = otherObject.GetComponent<ClassB>();
        otherInstance.StartCoroutine(coroutineName, new Dictionary<string, string>(){
            {"foo", "hello"},
            {"bar", "world"}
        });
        Debug.Log("Coroutine Started");
    }

}
```

```csharp:ClassB.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ClassB : MonoBehaviour
{
    IEnumerator TestCoroutine(Dictionary<string, string> param)
    {
        Debug.Log(param["foo"]);
        yield return new WaitForSeconds(3.0f);
        Debug.Log(param["bar"]);
        yield return new WaitForSeconds(3.0f);
        Debug.Log("Coroutine Finished");
        yield break;
    }
}
```

それぞれのスクリプトを適当なGameObjectにそれぞれアタッチして、
インスペクタから ClassA の `otherObject` に ClassB の参照を、`coroutineName` に `TestCoroutine` と文字列で入力し実行しました。

ついでにパラメータを複数渡す実験も雑にやってみました。
うまく動いて良かったです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39401/ee0a174b-7d4f-9b9a-c63d-0df030d5c3d0.png)
↑実行ログ
Nexus + Prisma で Query の返却値の生成時に関連テーブルの内容も一緒に Where する

例えば、
- `user` というテーブルは `company` という所属会社の情報を関連として持っている。
- GraphQL の query からは、引数に所属会社名も含めて検索したい。
みたいなケース。

想定する input (query) は以下のような感じ。

```graphql:クエリ
query users ($input: UserWhereManyInput) {
  users (input: $input) {
    id
    name
    company {
      id
      name
    }
  }
}
```

```json:引数
{
  "companyName": "テスト株式会社"
}
```

これを実現します。

```typescript:Query.ts
import { arg, list, queryType } from "@nexus/schema";
import { User } from "./path/to/model";

export const Query = queryType({
  definition(t) {
    t.field("users", {
      type: list(User),
      args: {
        input: arg({
          type: "UserWhereManyInput",
        }),
      },
      async resolve(_, args, context) {
        const id = args.input?.id;
        const companyName = args.input?.companyName;

        const user = await context.prisma.user.findMany({
          where: {
            id,
            // company.name から検索
            company: {
              name: {
                contains: companyName,
              },
            },
          },
        });

        return user;
      },
    });
  },
});
```

Prisma の検索系メソッドの引数のオプションを、上記のようにネスト表現することで関連テーブルの Where 検索もできるようです。
Nexus の context には Prisma が注入されていることを前提としています。

ちなみに `UserWhereManyInput` は以下のようなイメージ。
引数は平で受け取らずにちゃんと型をつくっておくと後々嬉しいことが多い気がするのでオススメです。

```typescript:UserWhereManyInput.ts
import { inputObjectType } from "@nexus/schema";

export const UserWhereManyInput = inputObjectType({
  name: "UserWhereManyInput",
  definition(t) {
    t.nullable.int("id");
    t.nullable.string("companyName");
  },
});
```

これでいけると思います。
就活生・転職志望者のための模擬面接100本ノック（Streamlit）

# はじめに
筆者は先月まで通信会社で働いていましたが、無事に転職活動を成功させ、12月からネット広告会社のデータアナリストとして働くことになりました。今回は転職活動を通じて感じていた、**「模擬面接サービスがあったらいいのに」**という思いをアプリにしてみました。百聞は一見にしかずですので、初めに模擬面接アプリのURLとデモ動画を貼っておきます。

#### 模擬面接100本ノック

https://mensetsu-100knocks.herokuapp.com/

**（PC閲覧推奨、スマホからだと音声が出ません）**

<br>
<iframe width="560" height="450" src="https://www.youtube.com/embed/5bunXONYmbM" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

# 作成の動機
一般的に転職活動では、自分がこれまでどういった業務を経験してきたか、どういうスタンスで業務に取り組んできたを面接官に分かりやすく伝えることがとても重要になってくるかと思います。そのため、転職志望者は徹底的に自己分析をし、面接の練習をしたりするかと思いますが、**私はわりと物事をじっくり考えるタイプで、質問に対して即座に回答するような瞬発力があまりないため、面接がとにかく苦手でした。**そこで、Jupyter Notebook上で想定質問をランダム表示して回答の練習をするといった対策をしてきましたが、淡々とし過ぎており、もっと臨場感のある面接練習ができれば良いのにと感じていました。今回は、転職活動中に感じていたこのような思いを解決すべく模擬面接アプリを作ってみました。
![Hnet-image.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692165/b3da1acd-cedd-335c-9601-d3302082791c.gif)


# アプリの概要
今回作成した模擬面接アプリは、画面上での面接質問文の表示と同時に問題文を合成音声で読み上げてくれるアプリとなっています。画面に表示される面接官の画像等についてはフリー素材を使用しました。また、**合成音声の作成には[VOICEVOX](https://voicevox.hiroshiba.jp/)という合成音声作成サービスを利用いたしました**（このような高品質な音声作成サービスが無償で利用できるのはとても良い時代になったなと感じます）。

**アプリ作成はPython WebフレームワークのStreamlitを使用、本番環境へのデプロイはHerokuにて実施**しました。Streamlitの概要については以前の記事をご参考下さい。
<Br>

https://qiita.com/kunishou/items/68d676410f4878c568aa

<Br>
Streamlitのデプロイについては**Streamlit SharingというSteramlit公式のデプロイサービスもありますが、デプロイしたコードがパブリックなものになってしまう**ため選択から除外、Github上のプライベートレポジトリをデプロイできる**Streamlit Teamsという有料プランもありますが月額3万円ほどかかる**ためこれも選択から除外しました。以上のことから、今回はHerokuをデプロイ先として選定しました。

#### 使用方法
PCからURLにアクセスすると左側に面接設定バーがあります。そこから各種項目を設定していきます。項目選択が完了後に「面接開始」ボタンを押下することで模擬面接が開始します。

#### 各種項目
* 転職/新卒：転職か新卒かで出題する質問内容が変化
* 質問数：7問、12問、17問の3パターンを選択可能
* 質問パターン：定番中心か質問のランダム出題かの2パターンを選択可能
* 志望職種・分野：4つの職種から選択可能、選択した職種に応じて数個ほど専門的な質問が加わる
* 音声：音声あり、なしを選択可能
* 質問文表示：質問文の表示・非表示を選択可能

# 作成において苦労した点
#### 合成音声の作成
今回使用した合成音声はVOICEVOXを用いて作成しました。VOICEVOXに文章を入力すると自動でイントネーションも概ね良い感じに調整された音声が作成されますがどうしても多少の調整が必要になります。**今回の模擬面接アプリにおいてはおよそ100種類程度の合成音声を作成しましたが、これら1個1個の音声のイントネーション調整にかなり時間がかかりました**（物好きな人じゃないとやらないと思います）。

#### 音声の自動再生
今回の模擬面接アプリはStreamlitを用いて作成しましたが、Streamlitにて使用できる標準の音声再生ウィジェット(st.audio)が再生ボタンを押下することで音声再生する仕様となっており、自動再生に対応しておらず、アプリ上で音声を自動再生させるための検討に苦慮しました。サードパーティ製の音声再生モジュール（playsound、simpleaudio等）の使用も試しましたが、本番環境においてStreamlitがこれらの音声再生モジュールに対応してないためデプロイエラーとなり使えませんでした。結果として、別の方法によって自動再生を実現しました（詳細は **[こちらの記事](https://qiita.com/kunishou/items/a0a1a26449293634b7a0)** にて書いております）。

# 最後に
以上、模擬面接アプリ作成についての記事でした。知人に模擬面接相手になってもらうのもなかなか難しいと思いますので、就活生や転職志望者で面接練習をもっと効率的にやりたいと思っている方がいましたら是非このアプリを活用してみて下さい。
Ubuntu18.04が突然起動できなくなった話と対処法

#**Failed to start NVIDIA persistence daemon**
**Failed to start NVIDIA persistence daemon** に対する解決策の記事です。
検索しても英語でふんわりとした記事が無かったので、日本語で学部2年生あたりでも分かるように書きます。

#環境

・Ubuntu18.04
・CPU core-i7
・GPU RTX2080 super

#直し方(結論)
GPUドライバーのバグです。

①リカバリーモードでUbuntuに入る

②NVIDIAドライバーと関連品の一括削除
```sudo apt purge nvidia-*```

③nouveauとnvidiafbをブラックリスト登録
```nano /etc/modprobe.d/blacklist.conf```
ファイル内に 【blacklist nvidiafb】 と追記。

```nano /etc/modprobe.d/blacklist-nouveau.conf```
ファイル内に 【blacklist nouveau】　と追記。

④再起動

⑤CPUのみでUbuntuが起動し、普通に画面が動く

⑥NVIDIA driverの入れ直し
```sudo apt install nvidia-driver-470```


⑤再起動

⑥全て復帰！

以下、バグに遭遇した過程を日記程度に忘れないよう記載しておく。
ほぼ自分用&身内用です、駄文失礼。

#第一話  Ubuntu、死す。


いつもの昼下がり。プログラミングをしていました。
ちょっと休憩して何気なく「最近apt updateしてないな〜」と思ったので、
```sudo apt update```
```sudo apt upgrade```
をしました。(脳死)
何が更新されたかは細かく見てませんでした。(バカ)
多分NVIDIAドライバー辺りが更新されたのかな。


約10分後、色々タブを開いて作業していると突然PCがフリーズ。
グラフィック系に重い処理をさせ過ぎたのかな。
月に1~2回程度あるので、特に驚くこともなくリセットボタンを押して再起動。(物理)


そう、ここで冥界の門が開いた。

#第2話　起動しないUbuntu

PCが再起動したはいいものの、何故かUbuntuが起動しない。
こんな感じ↓の黒い画面で固まってしまう。(写真は拾い物です)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103136/dc6175a6-5c38-5e79-c29d-6c5fd4bd55dc.png)


今回に限らず、Ubuntuやコンパイルで困った時はエラーメッセージでググりましょう。
(よく研究室の後輩君が困ったらスクショを送ってくれますが、まず自分でエラーメッセージをググりましょう)
(人に聞くのも大事だけどね。)

#第3話 ググった先は専門英語。

すると英語でぼんやりとした記事が沢山出てきた。
話の流れを汲むに、どうやらGPUドライバーを入れ直すと直るらしい。(7年前の話ですがセンター英語196点でした)

しかし具体的なコマンドが書いてない。圧倒的初心者殺し。
そこで本記事は実際に私が使ったLinuxコマンドを全て書き出す。


パソコンをリセットボタンで強制的に切ってから、再起動の初期タイミングでキーボードの上下キーをガチャガチャしておくと、下のような紫色の画面で止まります。(拾い物)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103136/ad0dc363-6fbe-48d6-b80c-731c251bd99b.png)

上から二番目の項目"advanced options for Ubuntu"を選択。
すると、↓こうなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103136/fcff423e-8ab8-9a32-3725-00b3ec7114ff.png)

上から二番目の**リカバリーモード**で起動します。
すると、更に紫色の画面が来ます↓



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103136/bff6f20e-59ae-1194-931c-4abb1577b8c1.png)


ここでrootを選択してコマンドラインに入ります。
管理者権限なので、ここから少しの間sudoは不要です。

```apt purge nvidia*```

でnvidia関連を一気にアンインストールします。
もしドライバー以外にもnvidia系を使っている人は、巻き込んで一緒に消えちゃう可能性があるのでご注意！！
もしかしたら```apt purge nvidia-driver*```の方が削除するソフトをGPUドライバーに限定できるから良いかも…(未検証)


更に、modprobeのブラックリストに2種類のソフトウェアを書き加えておきます。
(modprobeはUbuntu起動時に色々なソフトを自動起動してくれる便利なシステムなのですが、このブラックリストに入っていると起動しません)
(バグのあるソフトや怪しい挙動をするソフトはblacklistに登録しておきましょう)


```nano /etc/modprobe.d/blacklist.conf```
ファイル内に 【blacklist nvidiafb】 と追記。

```nano /etc/modprobe.d/blacklist-nouveau.conf```
ファイル内に 【blacklist nouveau】　と追記。


ここまで来たら、コマンドで```reboot```と打って再起動。

#第4話  見慣れた画面

なんと再起動したら、いつものUbuntu画面が映りました。
***GPUドライバーを消したためGPUは動きません。モニターをGPUに繋いでる人はCPUからのHDMI出力を試してみてね***

ここまで至ればあとはこっちのもの。
削除したGPUドライバーを再インストールしましょう。

```sudo apt install nvidia-driver-470```

そして再起動。

すると。マルチディスプレイ全てが点灯し、いつものUbuntuが帰ってきました！

#第5話　感想と愚痴

復帰してみて、aptに若干依存関係のエラーが見れました。
一番危惧していたROS環境周りは綺麗に無事で、開発中のものも変更無くそのまま動きました。良かった…

NVIDiAドライバーはなんか不安定で、aptで入れても上手く動かず、OSを入れ直した経験があります。
マジで頻発します。
NVIDIA許すまじ。


そもそもRTX2080 superが若干珍しいGPUのためか、ドライバーのサポートが薄い気がします。
皆さんはより一般的なRTX2080(無印)や3000系列を買いましょうね。

質問やミス指摘など、ツイッターのDMに頂けると反応早いです。
Qiitaのコメント欄は気づかない事が多いので。
pytnonでMoodleの出席を自動化させてみた

#はじめに
今更ではありますが、一年前に書いたコードを紹介したいと思います。
経緯は察してください...

#環境
ソフトウェア
　　anaconda3 64-bit
　　Visual Studio Code
実行環境
　　Chrome

#ソースコード
anaconda prompt

~~~
conda install selenium
~~~

python

~~~python
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import chromedriver_binary
import time
# ブラウザを開く(Chrome)
driver = webdriver.Chrome()
#TOP画面を開く
driver.get("Moodelのリンク")
time.sleep(3)
# ログインボタンをクリック
login_btn = driver.find_element_by_xpath('//*[@id="region-main"]/div/div[2]/div/div/div/div/div/div[2]/div[3]/div/a')
login_btn.click()
#登録してるグーグルメールアドレスを入力
login_id = driver.find_element_by_id("identifierId")
time.sleep(1)
login_id.send_keys("メールアドレス") 
time.sleep(1)
#次へ
element0 = driver.find_element_by_class_name("VfPpkd-RLmnJb")
element0.click()
time.sleep(1)
#パスワード入力
login_pw = driver.find_element_by_name('password')
time.sleep(1)
login_pw.send_keys("パスワード")
#次へ
element0 = driver.find_element_by_class_name("VfPpkd-RLmnJb")
element0.click()
time.sleep(20)
# ブラウザを終了
driver.close()
~~~

参考資料
https://aiacademy.jp/media/?p=346
Github ActionsでROSのrostestを実行する

# 概要

Github Actionsを使ってROSのテスト実行をCIで行う。
rostestの例だけど、catkin_makeでビルドしたり、パッケージ作ったりもできる。

# 環境

* ubuntu-18.04
* ROS melodic

# workflowを用意する

```test.yaml
name: ROS test workflow

on: [push]

jobs:
  test:
    runs-on: ubuntu-18.04
    env:
      CATKIN_WS: /home/runner/work/catkin_ws
    steps:
    - uses: actions/checkout@v2

    - name: Setup ROS
      uses: ros-tooling/setup-ros@v0.2
      with:
        required-ros-distributions: melodic

    - name: Init workspace
      run: |
        source /opt/ros/melodic/setup.bash
        mkdir -p ${CATKIN_WS}/src && cd ${CATKIN_WS} && catkin_make
        ln -s ${GITHUB_WORKSPACE} ${CATKIN_WS}/src/

    - name: Run tests
      run: |
        source ${CATKIN_WS}/devel/setup.bash
        rostest <package> <node.test>
```

`.github/workflows/` に配置する

## 解説

### ROS環境のセットアップ

`ros-tooling/setup-ros@v0.2` を使ってROS環境のセットアップをする。
ubuntuのバージョンは使用するディストリに合わせる。

### catkin_wsの初期化

インストールした環境ファイルを `source` してros環境にパスを通す。
`/home/runner/work` に `catkin_ws` を作成して、リポジトリのリンクを張る。

### 作成したcatkin_wsにパスを通す

コマンド実行前に作成した `catkin_ws` にパスを通す。
【備忘録】REST Client

#はじめに
VSCodeでリクエストの送信、確認ができるプラグインがあるとのことで触ってみました
備忘録として書いてます

#目次
- REST Clientとは
    - 基本的な書き方
        - GET
        - POST
- SendGridでメールの確認
- 終わり
- 参考

##REST Clientとは
VSCodeの拡張機能です
PostmanのようなことがVSCode上でできます

使うにはVSCodeの拡張機能からインストールするだけです
[こちらのサイト](https://qiita.com/toshi0607/items/c4440d3fbfa72eac840c)を参考にしました

###基本的な書き方
REST Clientをインストールしたら、HTTP接続の内容を書くための「.http」ファイルを作成します

作成したファイルにGET、POST等書いていき、「Send Request」を押下でリクエストを送信、確認できます
問題なければ200、エラーがあれば400などの表示がでます

また、「###」を挟んで複数のリクエストを一つのファイルに記載することもできます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1733797/0139032a-714d-c3b5-c2d7-81e8880e139d.png)


####GET

```
GET http://localhost:8080/ HTTP/1.1
```
GET　URL　の書き方、もしくはGETを省略してURLだけで記載するとGETできます


```
@hostname = localhost
@port = 8080
@host = {{hostname}}:{{port}}

GET http://{{host}}/
```
上記のように変数を使うこともできます
変数の説明は[こちらのサイト](https://dev.classmethod.jp/articles/vscode-rest-client-is-good/)に詳しく書いてありました

####POST

```
POST http://localhost:8080/sample HTTP/1.1
content-type: application/json

{
    "id": "1000000",
}
```
POSTの場合はPOST　URL、content-typeに一行開けてリクエストボディを記載します
上記例はcontent-typeでJSON形式を指定しているのでこの書き方ですが、
他にもxml形式など指定ができるようです（[こちらのサイト](https://1kara-hajimeru.com/2020/10/1378/)が詳しく書いてあります）


##SendGridでメールの確認
SendGridはクラウドのメール配信サービスです（[公式](https://sendgrid.kke.co.jp/about/)）
テストなど、個人での利用は無料で使うことができます（登録、審査が必要）

このSendGridとREST Clientを用いてAPI呼び出しの確認ができる[記事](https://sendgrid.kke.co.jp/blog/?p=11908)があったので参考にしてやってみました

```
@APIキー=xxxxxxxxxxxxxxxx

POST https://api.sendgrid.com/v3/mail/send HTTP/1.1
Authorization: Bearer {{APIキー}}
Content-Type: application/json

{
  "personalizations": [
    {
      "to": [{"email": "MailSlurpで発行したメールアドレス"}]
    }
  ],
  "from": {"email": "sender@example.com"},
  "subject": "メール件名",
  "content": [
    {
      "type": "text/plain",
      "value": "メール本文"
    }
  ]
}
```

↑↑ほとんど参考サイトそのままです
SendGridに登録、入手できるAPIキーを記載して、JSON形式で書いています

送信先のメースアドレスには[以前触った](https://qiita.com/abe_n/items/32d5a41332d3c1bc4f88)ことがあるMailSlurpのアドレスにしてみました
「Send Request」で200の確認とMailSlurpにメールが届いていることが確認できました


##終わり
まだ使いこなせてはいませんが、使い方の雰囲気は分かったかな、といった具合です

##参考
https://qiita.com/toshi0607/items/c4440d3fbfa72eac840c

https://dev.classmethod.jp/articles/vscode-rest-client-is-good/

https://1kara-hajimeru.com/2020/10/1378/

https://sendgrid.kke.co.jp/blog/?p=11908
IPアドレスについて

#初めに
今回はIPアドレスについて学習したことをアウトプット、備忘録のために記事を作成します。

##IPアドレスとは
IPアドレス（Internet Protocol Address）は、ネットワーク上に接続された機器が持っている番号のこと。いわば、インターネット上の住所
IPアドレスがあることで、ネットワーク上で他のサーバーと情報をやり取りしたり、GoogleやYahoo!などが運用するサーバーとやり取りができる

##IPアドレスの管理
ネットワーク上の住所に当たるIPアドレスは、好きな番号を自由に設定できるわけではなく、IPアドレスは「ICANN」によって全世界的に管理され、世界共通のルールで運用されている。
ICANNの下には、地域（北米地域、欧州地域、アジア太平洋地域など）ごとにIPアドレスの管理を委任されている組織（インターネットレジストリ）があり、各地域のインターネットレジストリが、それぞれの地域内のIPアドレス割り当て業務を行っていて、日本国内のIPアドレスは「JPNIC」（日本ネットワークインフォメーションセンター）が管理している。

##IPアドレスの種類
割り振られているIPアドレスには、以下の2種類がある。

* パブリックIPアドレス（グローバルIPアドレス）
* プライベートIPアドレス

###「パブリックIPアドレス」
インターネットに接続される機器にそれぞれ個別に割り振られる番号。このIPアドレスは、必ず「一意」（ダブりがない）で割り振られる

###「プライベートIPアドレス」
インターネットに直接接続されていないネットワーク機器で利用されるIPアドレス
あなたが利用しているPCはインターネット上に接続されていると思うかもしれませんが、実際はルーターを経由してインターネットに接続されている。なので、ルーターにはパブリックIPアドレスが割り当てられていて、ノートパソコンなどはプライベートIPアドレスが割り当てられている。
すべてがパブリックIPアドレスだけの世界になってしまったら、ネットワークにつなげるあらゆる機器にパブリックIPアドレスを割り振ることになり、IPアドレスが枯渇してしまうため、インターネットに直接接続しない機器は、プライベートIPアドレスを利用している。

##プライベートIPアドレスの範囲

プライベートIPアドレスで利用できる範囲は、以下のとおり。この番号以外では、パブリックIPアドレスとして利用されている。

* 10.0.0.0 ～ 10.255.255.255
* 172.16.0.0 ～ 172.31.255.255
* 192.168.0.0 ～ 192.168.255.255

##IPアドレスのルール

1. IPアドレスは、数字のブロックを「. 」で4つに区切って表される。

2. 数字は10進数で4つの組（オクテット）に分けて表示される。

3. ただし、この10進数はコンピュータ内では2進数で管理されており、IPアドレスは合計で32ビットまでの範囲を数字として持っている。

## 用語

* オクテット　各組のことを「オクテット（octet）」と呼ぶ
* 2進数：数字を「0」と「1」で表す。コンピュータデータの最小単位
* ビット：「1ビット」は、2進数の一桁。1ビットで表せるのは「0」と「1」。2ビットでは「00」、「01」、「10」、「11」の4とおり表せる
* 10進数：わたしたちが日常的に使用している数字
高校時代に数学赤点3回のフリーターがAtcoderで茶色を目指す話#1

はじめまして。赤点フリーターです。

二年前からプログラミングには漠然とした興味がありましたが、特に努力することもなく大学中退後も過ごしていました。
中学までは数学に対する苦手意識がありませんでしたが、高校に入学してから一気に挫折しました。学生時代の冬休みは部活の合宿の合間に赤点補修を受けて、親と部活の顧問と数学担当の先生に怒られながらひっそりと生きていました。
数学アレルギーに対するコンプレックスは深く引きずっています。しかしながら、何か目的がないまま高校数学を勉強してもモチベーションが上がらないので、Twitterでよく見かけていたAtcoderのコンテストを頑張ってみようと思い競技プログラミングを始めたいと思います。

高校数学と競技プログラミングに関係性があるのか、現時点ではあまりよく理解していませんが、必要だったらその都度勉強したりしていこうかなと考えています。

いきなり高望みしても続かないのは目に見えているので、まずは2021年の年末までに茶色になれるように頑張ります。

ネットで調べたら色々と勉強方法が沢山あったので、迷っていますが一つの教材をしっかりやりきることから勉強していく予定です。
C++は学習するのが複雑っぽいのでPythonで勉強していきます。
会津大学が提供しているプログラミングのコースのUIが気に入ったのでこちらを中心にまずはプログラミングを理解していこうと思います。

AIZU Online Judge
https://onlinejudge.u-aizu.ac.jp/home

11月2日から始めるので、丸っと二ヶ月間競技プログラミングに腰を据えて取り組んで、茶色目指すぞ！！あわよくばchokudaiさんに褒めてもらうぞ！！更新頻度は高めにお送りするので、もしよろしければ暖かく見守っていただけると嬉しいです。
Vector2を回転させる

# 概要

平面上の2次元ベクトルを回転させたいときのやり方についてのメモ。
Quaternionを使う方法もあるけど2次元の場合はもっと簡単な方法がある。


## 結論

複素数(Complex)を掛け算するだけでよい

## 用例

Complex構造体は内容的にはVector2と同じものである。
https://docs.microsoft.com/ja-jp/dotnet/api/system.numerics.complex?view=net-5.0
complexインスタンスにおけるRealがVector2のX、ImaginaryがYと考えて問題ない。
complexクラスには * のオーバーロードが実装されており、complex同士を掛けると掛けた分だけcomplexの各要素が反時計回りに回転するという性質がある。
なので、
・まず回転させたいVector2からComplexを作成する
・回転させたい角度のComplexを作成する
・上記２つのcomplexを掛ける
ことで目的のVector2を得られる。

下記がサンプルコード。Unityで利用するためMathfを利用しているが、特にUnityだけで利用するものでもないため適宜Mathなどに読み替えて利用すること。


```C#
    /// <summary>
    /// Vector2を回転させる
    /// </summary>
    /// <param name="from">回転させたいVector2</param>
    /// <param name="angle">回転させる角度</param>
    /// <returns></returns>
    public static Vector2 Rotate(Vector2 from, float angle)
    {
        Complex a = new Complex(from.x, from.y);
        float cos = Mathf.Cos(Mathf.Deg2Rad * angle);
        float sin = Mathf.Sin(Mathf.Deg2Rad * angle);
        Complex b = new Complex(cos, sin);
        Complex result = a * b;
        return new Vector2((float) result.Real, (float) result.Imaginary);
    }
```

以上。
xargsによる連番ファイルの並列化（ワンライナー）

`xargs`で連番ファイルを容易に並列処理できるのでそのメモ。
連番で命名された画像ファイルの一括処理などに利用可能。


ここでは、0001.txt, 0002.txt, ..., 9999.txtを
0001.dat, 0002.dat, ..., 9999.datにリネームする[^1]。

```
for each in {0001..9999}; do echo $each;done | xargs -P 20 -n1 -I{} mv {}.dat {}.txt
```
とすればプロセス数20で並列化されて`mv $each.dat $each.txt`コマンドが動く。
この例ではうまみはないものの、CPU時間を消費するものには並列効果がある。


もう少し実用的な例として、512枚のpdfファイルpngに変換する作業の高速化率を示す。
mogrifyで

```bash
time mogrify -density 300 -format png 300 {001..512}.pdf
```
とすると、1分48秒かかる処理が

```
time for each in {001..512}; do echo $each;done | xargs -P 48 -n1 -I{}  convert -density 300 {}.pdf {}.png
```
では3.7秒で終了し、
30倍程度の速度が出ている[^2]。
1分の処理が2秒に短縮されてもそう嬉しくないが、1時間を2分にできると思えば価値は高い。


なお、`-P`の引数で並列化数を変更でき、`-P 1`とすると
```
time for each in {001..512}; do echo $each;done | xargs -P 1 -n1 -I{}  convert -density 300 {}.pdf {}.png
```
1分53秒かかり、当たり前だが、mogrify と時間はほとんど変わらない。

参考
<https://orebibou.com/ja/home/201507/20150727_001/>
<https://qiita.com/knknkn1162/items/806604341508d32b160e>
<https://qiita.com/shungok/items/f852be01f08568991f18>
<https://qiita.com/SUZUKI_Masaya/items/a58523c4e4c8b3a2958c>

[^1]: この操作であれば、`rename s/txt/dat/ ????.txt`でよい。あくまで例示です。
[^2]: 最適な並列数は環境依存です。CPUのコア数くらいまでしか速度は出ないでしょう。試した環境はハイパースレッディング込みで48コア。
Unityでファイルパス取得したり、c#のファイルパス取得したり、したり。

#初めに
開発していて独自のファイルをセーブしたり、ロードしたりする様な事があると思います。
僕の場合は、josnファイルで独自のデータをセーブして使ったりしてました。
その際にファイルのパスを調べてたり、ファイル名を調べたりする方法調べたものをまとめました。

##シーンデータのパスを知りたい
```c#
    for( int i = 0; i < UnityEngine.SceneManagement.SceneManager.sceneCount; ++i )
    {
        var path = SceneManager.GetSceneAt( i ).path;
        var fileNamepath = System.IO.Path.GetDirectoryName(path);
    }
```
上記でやっているのは読み込まれているシーンのパスを取得してパスのみ取得してます。
Assets\Scenes\hoge.unity
を取得してから
Assets\Scenes\のパスのみ取得する感じです。

### AssetDatabase.GetAssetPath使ってパス取得
https://docs.unity3d.com/ja/current/ScriptReference/AssetDatabase.GetAssetPath.html

unityの機能で取得
自分の環境ではinspectorにTextAssetを指定できる場所を作って、そのファイルのパスを取得するのに使いました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37068/462de2b2-9ad3-0f4b-368d-5ec795e243dc.png)

```c#
    var tex = EditorGUILayout.ObjectField("hoge", null, typeof(TextAsset), true) as TextAsset;
    var path = AssetDatabase.GetAssetPath(tex);
```
hogeにinstanceIDやassetObjectを入れて取得する方法
フルパスで帰ってきます。


#### いつも通り、先人の方がきれいにまとめてくれている

https://qiita.com/oishihiroaki/items/1a082f3bb32f2e3d88a0


CreateInstanceで呼んであげると複数起動できるみたい

##### ついでにsaveの機能も。。きれいにまとまっている

https://kan-kikuchi.hatenablog.com/entry/CopyAsset

###### 最後に
ファイルパスを取得して最後のファイル名を追加して保存しようと思いよくやるのは
ファイルパス
Assets\Scenes
ファイル名
hoge.unity

上の二つをくっつけてやると
Assets\Sceneshoge.unity　と自分が意図した位置にデータを保存すのに失敗します。
ちゃんとファイルパスの最後に"/"が入っていなかったら入れて使ってあげましょ。
iOS15でスクロール時にタブバーが黒くなる問題を解消したい

## 本記事について

iOS15でスクロール時にタブバーが黒くなる問題について、対処法をご紹介します。

### 環境

- Xcode13.0
- iOS15のシミュレータ

## 発生した問題

アプリをビルドした後、スクロール時、以下のようにタブバーが黒に変更されてしまう。
（詳細に言うと、初回起動時は通常の色だが、スクロールすると色が変わってしまう）

ちなみに、iOS14の場合は問題なかった。

![スクリーンショット 2021-11-02 14.57.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477704/f944474f-7857-de34-0172-2998d9ff25a3.png)

## 解決策

iOS15で仕様が変わっているとのこと。
原因は、UITabBarAppearanceの`scrollEdgeAppearance`プロパティを明示的に設定する必要があること。
画面のスクロール中と、スクロールが終端に達した時のタブバーの色を変更できるらしい。
https://developer.apple.com/documentation/uikit/uitabbar/3750912-scrolledgeappearance


今回自分の場合は以下のように修正しました。

```swift
guard let tabBarController = tabBarController else { return }
let tabBarAppearance = UITabBarAppearance()
tabBarAppearance.backgroundColor = .white
tabBarController.tabBar.standardAppearance = tabBarAppearance

if #available(iOS 15.0, *) { // 新たに追加
    tabBarController.tabBar.scrollEdgeAppearance = tabBarAppearance
}

```

## 最後に

バージョンアップ時に[Relase notes](https://developer.apple.com/documentation/xcode-release-notes/xcode-13-release-notes)に目を通すべきでした...

```txt
UITabBar and UIToolbar inspectors now support configuring scrollEdgeAppearance.(71788169)
```

皆さんの参考になれば幸いです。


## 参考記事

- https://moneyforward.com/engineers_blog/2021/09/22/moneyforward-me-ios15/
- https://shtnkgm.com/blog/2021-08-18-ios15.html
Java WordをHTMLに変換

<h1><strong>はじめに</strong></h1>
<p>HyperText Markup Language、略してHTMLは、ハイパーテキストを記述するためのマークアップ言語の1つです。日常の仕事でWordをHTMLに変換する場合がよくあると思います。なので、今回は<strong><a href="https://www.e-iceblue.com/Introduce/doc-for-java.html">Spire.Doc for Java</a></strong>というライブラリを活用して、WordをHTMLに変換する方法を紹介します。</p>
<h1><strong>Spire.Doc for Java</strong><strong>とは？</strong></h1>
<p><strong><a href="https://www.e-iceblue.com/Introduce/doc-for-java.html">Spire. Doc for Java</a></strong>は、Eiceblue社が開発され、開発者が JavaプラットホームでWordのドキュメントを迅速かつ高品質で作成・編集・変換・印刷するために設計された専門的なDoc処理APIです。</p>
<p>中には、商用版と無料版の<strong><a href="https://www.e-iceblue.com/Introduce/free-doc-for-java.html">Free.Spire.Doc for java</a></strong>があります。<strong><a href="https://www.e-iceblue.com/Introduce/doc-for-java.html">Spire.Doc for Java</a></strong>は商用版ではありますが、基本的な機能を搭載しているので、無料試用で日常の仕事にはもう結構だと思います。</p>
<h1><strong>下準備</strong></h1>
<p>1.E-iceblueの公式サイトから<strong><a href="https://www.e-iceblue.com/Download/doc-for-java.html">Spire.Doc for Java</a></strong>をダウンロードしてください。</p>
<p>2.IDEを起動して新規プロジェクトを作成してから、インストールされたファイルにある相応しいSpire.Doc.jarを参照に追加してください。</p>
<h1><strong>Maven</strong><strong>の側なら</strong></h1>
<p>もしMavenの利用者だったら、pom.xmlファイルに下記のようなコードを追加することで、JARを簡単にインポートできます。</p>
```JAVA
<repositories>
    <repository>
        <id>com.e-iceblue</id>
        <url>https://repo.e-iceblue.com/repository/maven-public/</url>
    </repository>
</repositories>
<dependencies>
    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.Doc</artifactId>
        <version>4.9.0</version>
    </dependency>
</dependencies>
```


<p>下記は詳しいステップとコードになります。</p>
<ol>
<li><strong>Document</strong> オブジェクトを作成します。</li>
<li><strong>Document.loadFromFile()</strong>メソッドでファイルをロードします。</li>
<li><strong>Document.saveToFile() </strong>メソッドでHTMLに変換します。</li>
</ol>

```JAVA
import com.spire.doc.*;

public class WordToHtml {
    public static void main(String[] args) {

        //Documentオブジェクトを作成します。
        Document document = new Document();

        // Word ファイルをロードします。
        document.loadFromFile("sample.docx");

        // HTMLで保存します。
        document.saveToFile("output/toHtml.html", FileFormat.Html);
    }
}
```
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20211102/20211102151307.png" alt="f:id:lendoris:20211102151307p:plain" width="554" height="296" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20211102/20211102151317.png" alt="f:id:lendoris:20211102151317p:plain" width="554" height="132" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p>
<h1><strong>最後に</strong></h1>
<p>ここまで読んでくださってありがとうございます！もし<strong><a href="https://www.e-iceblue.com/Introduce/doc-for-java.html">Spire.Doc for Java</a></strong>を利用している時にご不明なところがございましたら、ぜひご連絡ください</p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
Zoom会議を自動文字起こしする新機能を追加 | AI音声文字起こしアプリ『Notta（ノッタ）』

元記事：[https://www.notta.ai/blog/notta-bot-for-zoom-meeting-live-transcription](https://www.notta.ai/blog/notta-bot-for-zoom-meeting-live-transcription)

![banner.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2226142/0b84e6a3-fbbb-6788-e7f1-e52925ffd856.png)

**104言語に対応したAI音声認識文字起こしアプリ『Notta（ノッタ）』に新機能”Notta Bot”を追加しました。”Notta Bot”をZoom会議に追加することで、会議内容を自動で録音し、リアルタイムで文字起こしをします。**
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2226142/591672f0-6be9-7c2a-820a-a3bd73798ddd.png)


議事録を取るのに夢中になって、重要な会議内容を聞き逃してしまう・・・誰もが経験したことのある問題を、Nottaの新機能が解決します。

Zoom会議に”Notta Bot”を追加するだけで、高性能AIが自動で録音&リアルタイム文字起こしを実施。Notta Botはユーザーのパーソナルアシスタントとなり、議事録作成に要する時間と手間を大幅に削減します。ユーザーが会議そのものに集中できる、ストレスフリーなリモートワーク環境へ導きます。



# ■Notta Botでできること


また、Notta既存機能と組み合わせることで、以下のことも可能です。

- 文字起こし内容の編集
- パソコンやスマートフォンで議事録を共有
- 文字起こし内容の翻訳（42言語対応）

# ■Notta Botの利用シーン
Notta Botはあらゆる種類のオンライン会議で活躍。参加者が会議の記録ではなく、会議の内容へ集中できるようサポートします。

- オンライン会議
- オンライン説明会や、経営層から社内へ向けた大規模オンライン会議
- ウェビナー
- インタビュー
- 商談


# ■利用料金
“Notta Bot”は有料会員向け機能の１つです。

有料会員は、Notta Botの利用に加え、文字起こし内容の翻訳（42言語に対応）や、自動文章構成、データのエクスポート、倍速再生など、さまざまな機能を利用することができます。



料金プランは以下の通りです。無料会員と有料会員の違いについての詳細はこちらをご覧ください。
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2226142/3afe9001-1746-b717-a8e7-2b9b9aa67cfc.png)


※2021年8月時点での料金設定です。



# ■Notta Botの利用イメージ
以下のシンプルなステップでZoom会議の自動録音・文字起こしをすることができます。Zoom初心者でも簡単に操作可能です。



1.  Notta Web版にログイン

2.  “Zoomミーティング” 機能から、Notta Botを会議に追加する
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2226142/4e558c96-d1b9-c99c-8471-7ffe207cb4cb.png)


3. 「文字起こしをする」をクリック

4.　接続が完了すると、Notta Botが会議に追加され、自動文字起こしが開始



会議終了後は、必要に応じて文字起こしした内容の編集が可能。また、パソコンやスマートフォンを使って即座に他の参加者と議事録の共有が可能です。翻訳機能を使うことで、海外のメンバーと会議内容を共有することも。翻訳に要する時間を省き、リアルタイムに近いタイミングで情報共有することができます。

さらに、Googleカレンダー登録をすることで、予約したイベントにNotta Botを自動参加させることも可能。更なる効率化が実現できます。



※ご利用時は、会議参加者の方々に、Notta Botを使用すること（録音・文字起こしすること）を事前にお知らせください。




# ■Nottaについて
Nottaは、日本語・英語をはじめとした104言語に対応する、AIによる音声自動テキスト化アプリ。っ言語に合わせて最適なAI音声認識エンジンを用いて、スピーディかつ高精度の文字起こしを実現することで、作業時間の大幅削減に貢献します。PC、スマートフォンやタブレットなど、様々なデバイスで利用可能。場所を選ばずに利用することができます。また、全てのデータは暗号化され、セキュリティ保護されているため、社外秘の議題が含まれる会議でも、安心して利用できます。



2021年7月1日時点でNottaの登録ユーザー数は18万人を突破いたしました。今後もNottaは皆さまの作業効率向上に貢献する機能を追加していきます。

---

Nottaは無料体験できますので、試してみましょう。
‍
‍**Web版**
‍‍Google ChromeやMicrosoft Edgeから[Web版](http://www.notta.ai/)をアクセスできます。（無料）
‍
‍**Chrome拡張機能**
‍Chrome web storeから[Notta拡張機能](https://chrome.google.com/webstore/detail/notta-speech-to-text-tran/kdelkaogljjcbjffjmahedaobfjineig?hl=ja)をインストールできます。（無料）
‍
‍**アプリ版‍**
iOSアプリは[App Store](https://apps.apple.com/jp/app/notta-%E9%9F%B3%E5%A3%B0%E3%81%AE%E9%8C%B2%E9%9F%B3%E3%81%A8%E6%96%87%E5%AD%97%E8%B5%B7%E3%81%93%E3%81%97-ai%E9%9F%B3%E5%A3%B0%E8%AA%8D%E8%AD%98%E3%82%A2%E3%83%97%E3%83%AA/id1480649572)からダウンロードできます。（無料）
Androidアプリは[Google Play](https://play.google.com/store/apps/details?id=com.langogo.transcribe&hl=ja&gl=US)からダウンロードできます。（無料）
SwiftのOptional型に?をつけて代入した時の挙動

# Optional変数への代入
次のstrは何が代入されるでしょうか？

```swift
var str: String? = nil
str = "Hallo"
print(String(describing: str))
```

strにはHalloという文字列が代入されるので、strの結果は `"Hallo"` になります。正確には`Optional("Hallo")`になります。

# ?付きOptional変数への代入
では、次のstrは何が代入されるでしょうか？

```swift
var str: String? = nil
str? = "Hallo" // ←?付き変数に代入する
print(String(describing: str))
```

先程と似たようなコードですが、先程のコードとは違ってstrには`?`をつけて代入しています。
これはちゃんとビルドが通るコードですが、この場合、strの結果は `nil` になります。

## ?付きの値のあるOptional変数へ代入

もう一つ、次のstrは何が代入されるでしょうか？

```swift
var str: String? = "Good Morning"
str? = "Hallo" // ←?付き変数に代入する
print(String(describing: str))
```

このコードも先程と同様、strはOptionalで定義されていますが、strは値を持っています。
この場合、strの結果は `"Hallo"` になります。正確には`Optional("Hallo")`になります。


# まとめ
ということで、?つきOptional変数への代入は、nilの場合は何もせず、値がある場合は代入する、という挙動になります。
`str?.append("World")`のようなコードが、strがnilの場合は何もしないのと一緒の挙動ですね。
?付き変数への代入のコードはビルドできてしまうので、パッと見では気づかない、意図しない挙動を埋め込んでしまう可能性があるので気をつけましょう。
Android 11（API レベル 30）以上をターゲットにする

![Android 11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2156003/32efeea3-3ad2-ac4c-dfbb-dec24d7ed5e0.png)

```
2021 年 11 月 1 日以降に Google Play で配信しているアプリおよびゲームを更新する場合、
Android 11（API レベル 30）以上をターゲットにすることが必須となります。
この日を過ぎると、targetSdkVersion が 30 未満の新しい App Bundle と APK はアップロードできなくなります。

なお、Wear OS アプリには API レベル 30 の要件は適用されません。

アプリのターゲットを最新の API レベルに設定することで、セキュリティとパフォーマンスを大きく改善できます。
もちろん、アプリは古い Android バージョン（minSdkVersion まで）でも引き続き動作します。
```

2021年11月1日からGoogle Playにアップロードする場合はターゲットAPI レベルを30にする必要があるんだって

実際にAPI レベルを30以下でアップロードするとどうなるのか？

```
"Your app currently targets API level 29 and must target at least API level 30."
```
はい。ダメでした。


早速対応しましょう。
![Unity Setting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2156003/21e324b2-6e1b-641b-8fca-70d8108eb22b.png)

```
Target API Level を Android 11.0 (API level 30)
```

Unityでビルドする際には Project Settings > Android > Other Settingsで簡単に設定できます。
この対応で無事にアップロードできました。

終わり。
* d.tsに足せば良いです。がわからなかった私

# 先に結論

**ドキュメントちゃんと読みましょう**
[公式](https://www.typescriptlang.org/docs/handbook/intro.html)

あと個人的にはこちらの記事に救われました。
[https://developer.hatenastaff.com/entry/2016/06/27/140931](https://developer.hatenastaff.com/entry/2016/06/27/140931)

以下ダラダラとポエムですゴメンなさい。

# TypeScriptと私

言語変遷として、PHP → JavaScript/Node.js → Python と辿ってきました。

見ての通りのザ・スクリプト言語達です。

そんな私がはじめて本格的に手を出した静的型付けっぽい言語がTypeScriptでした。

とは言いつつ、実際に使っていたのはAngularだった為、特段TypeScriptっぽい部分をゴリゴリ使い倒していたわけではありません。

せいぜい Class　や Interface が宣言できるのな、程度の感覚で使っていた風です。

そんな状態でもそこまで困ることなく扱えていたのは、偏にAngularさんがうまいことやっていてくれていたんだなと思います。

# Google Maps JavaScript API の罠

順風満帆な?TypeScript生活に終止符を打ったのは、奇しくも同じGoogleさんのMaps Javascript APIでした。

おそらく、もっと早い段階でjQueryとかを使おうとしていたのであれば、ずっと早くに壁にぶち当たっていたと思います（むしろ当たっていた方が良かったのかも…）

今でこそ、TypeScriptフレンドリーになってる Maps Javascript API　ですが、当時はTypeScript何処吹く風状態だった為、ライブラリからの歩み寄りはあまり期待できない状態でした。

**scriptタグでwindowのglobalに生えるタイプのやつです**

なんとかコンパイルを通そうと四苦八苦しました。

とりあえず動かすことが優先されていたため、理解することよりなんとかすることを優先したのもまずかったと思います。

検索すると対応させる方法はそれなりに見つかりました。先のjQueryの様に、当時はまだTypeScriptへ対応するライブラリも今ほど多くなく、わりかし同様のシチュエーションで困っていた人は多かったのかと。

# Declaration space + Open-ended

このあたりの原則を知らずに使い倒そうとしたのがよくなかった。。。
スクリプト言語出身ということもあり、宣言型のscope認識がなく、別ファイルに記載した定義
Interface, namespace, module 等がマージするなどとは夢にも思わなかったです。

これのおかげで、見る記事によって（多くの記事は端的に同モジュール内でのサンプルが多い）
宣言の仕方が違ったりしたので、そこに振り回された感じだったのかなと思います。

# Top level import

**上部にimport/exportの記載があるファイルはmodule**
と、上記Declaration Spaceとが合間って、混乱してしまった。

先の、[TypeScript の型定義ファイルと仲良くなろう](https://developer.hatenastaff.com/entry/2016/06/27/140931#%E3%81%93%E3%81%93%E3%81%BE%E3%81%A7%E3%81%AE%E7%A2%BA%E8%AA%8D) より

```ts
import $ from "jquery";

// interface をマージして window.originalFunction() を使えるようにしたい
interface Window {
    originalFunction(string): void
}

window.originalFunction("test"); // => 使えない…

window: Window; // type annotationしてみる

window.originalFunction("test"); // => 使えるようになった！！
window.alert('hello,world');     // => 元から Window あった定義が使えなくなった……
```
がすごくいいサンプル

# 新しい言語 + フレームワークの同時習得はバカの山に気をつけて

[バカの山](https://togetter.com/li/1783989)

ある程度さわれる様になってしまうので、できてる感を得るまでに短時間でいけますが、
その後に待ち受けるのは、フレームワークがお膳立てしてくれているスキームがあだとなった
言語特性理解への混乱。

スクラッチで狭いスコープから徐々に広げていけば、私が踏んだような轍も少しは回避できるのかなと。

# おわりに

TypeScriptもバージョンアップでだいぶ進化してるので、そろそろ自分の理解にもアップデートをかけないとなと思います。
小話〜djangoのdateフィルターについて

今回のお題
-
今回は、djangoテンプレートのdateフィルターについて取り上げます。

例によって自分用のメモですね。

目次
-

- フィルターとは
- dateフィルターとは
- フォーマットの規定値について

フィルターとは
-
まずはフィルターそのものについての説明を念の為。

フィルターとは、djangoテンプレートの{{}}で囲まれた値を加工するためのものです。

以下のように値とフィルター名を`|`で区切って使います。

```django
<!-- fugaがフィルター名 -->
{{ user.nickname|fuga }}
```

dateフィルターとは
-
dateフィルターは年月日の表示形式を加工するためのものです。

以下のように`|date:"フォーマット形式"`という形で記述します。

```django
{{ user.birthday|date:"Y年n月j日" }}
```

これで`~年~月~日`という形式で表示されるようになりました。

(`n月j日`なので一桁の数字は０詰めになりません。0詰めがよければ`m月d日`表記にしましょう。)

おまけ：フォーマットの規定値について
-
dateフィルターをかけない場合のフォーマットは、基本的に`Y年n月j日`表記になっているかと思います。

この仕組みが気になったので簡単にではありますが調べてみました。

まず、年月日のフォーマットの形式には`DATE_FORMAT`という値が関わっているようです。

そして、公式ドキュメントでは`DATE_FORMAT`について以下のように書かれていました。
>DATE_FORMAT¶
Default: 'N j, Y' (e.g. Feb. 4, 2003)

>The default formatting to use for displaying date fields in any part of the system. Note that if USE_L10N is set to True, then the locale-dictated format has higher precedence and will be applied instead. 

つまり
>基本は`N j, Y`形式だがsettings.pyにおいて`USE_L10N = True`となっていれば代わりに地域設定に応じた値が使われる。

ということですね。

以上をまとめると、
- `USE_L10N = True`であれば年月日は基本的に`Y年n月j日`形式で表示される。
- 表示形式を規定値から変更したい場合は`USE_L10N = False`に変更した上で、settigs.pyで`DATE_FORMAT`の値を設定し直す。
- 個別に変更したい場合は`dateフィルター`を使う。

ということになります。

日付の取り扱いは若干苦手意識があるのですが、早く慣れていきたいですね。