OmniAICreator/Qiita-1.07M huggingface dataset:
ローカルで動画からGIF画像作成をもっと簡単に

最近、技術記事を書くとき、特にフロントエンドについて書くときはGIF画像を必ず貼るようにしています。

それで必要になるのが、動画をGIF画像に変換するためのツールでした。

昔はGyazoを使っていたのですが、フリープランで使いまくっていたら上限に達して使えなくなったため、別の方法を検討していました。

そこで以下の記事を発見。

https://qiita.com/i-to-to-to-mi/items/e73eb0a5899f111d0e64

これでいくらでもGIFが生成できるようになりました。

ただ、如何せん叩くコマンドが３つもあるし、
当然ですが動画が長ければ長いほど１つ１つのコマンドの完了までに時間がかかります。

５回目にしてそろそろ面倒になってきたので、一発でGIFまで生成できるようにしました。

## 前提

この記事は、参考にした記事↑に書いてある
**「3,ffmpegとimagemagickをインストール（ターミナルへコード入力）」までをやった上での話**になります。

なので、そちらをみたことがない方は、まずそっちをご確認ください。

## できたもの

**参考させていただいた記事とできるものは、最終的に全く同じ**です。
GIF生成の過程で生まれたpngファイルはいらないので、それらは最後に削除しているくらいですね。

処理中なのかなんなのか分かるようにすればよかったが省略。
GIF内では手動ローディング？ということでカーソルがぐるぐるしてます。笑

動画はこちらにあります。

https://github.com/kamimi01/assets_for_articles/issues/2#issuecomment-1024841810

## やったこと

まあほんとちょっとした工夫って感じです。
記事にする必要すらあるかって感じですが、まあ自分のメモ程度なのでいいでしょう。

エラーハンドリングとかしてません。

```shell
#!/bin/sh

# 現時点ではmp4とmov拡張子に対応しているよう
echo '変換するファイル名は？（拡張子付きで）：'
read targetFileName

echo 'いくつにリサイズする？（1~100の数字で）：'
read resizeSize

echo '作成するファイル名は？（gif拡張子なしで）：'
read createdFileName

ffmpeg -i $targetFileName -an -r 10 %04d.png && \
convert *.png -resize $resizeSize% output_%04d.png && \
convert output_*.png $createdFileName.gif && \
find . -not -name '*.gif' -not -name '*.mov' -not -name '*.mp4' | xargs rm -rf
```

ほんとはpng系はtmpディレクトリでも作っといてそこに入れとき、
tmpディレクトリを最後に削除したかったが、なんかconvertコマンドのところでコケてできなかった・・・

このshellスクリプトを実行するコマンドを、
aliasに設定して使っています。

```shell
sh <上記のshellファイルがあるフルパス>
```

aliasを設定した場合は、以下を忘れずに

```shell
source ~/.zshrc
```

## さいごに

久しぶりにshell書きました。
まあ全然大したことはないので、書いたと言えないんじゃないかレベルですが。

とりあえず３回コマンド打つ必要なくなったのでちょっと楽になりました。:blush:
2022年：流行技術予想

<h1>2022年：流行技術予想</h1>
<h2>はじめに</h2>
仕事をしている中での肌で感じたことを伝えます。
（※鵜呑みに注意（笑））

また、開発者目線で書いています。
「この辺の技術が要求される仕事が今後は増えるのかなぁ？」
と受け取っていただけますと幸いです。

<h2>目次</h2><ul><li>企業では Salesforce</li>
<li>UI/UX は TypeScript</li>
<li>AWS はもう、できないとダメ</li>
<li>個人的に気になる Rust</li></ul>

<h2>企業では Salesforce</h2>
昨今のウィルスの影響により、在宅での仕事が中心となり、
今まで、通勤や出向など移動にかけていた時間が大きく削減されたことと思います。

その時間が空く分、打ち合わせをするお客様が増えたり、連絡することそのもの、
および利用する連絡媒体が多種多様（Slack, Teams, Zoom, Cisco, Skype, メールなど）
になっているのかなと考えています。
（私も、お客様のご都合（環境）に合わせるため、
　上記のような感じでコミュニケーションツールが増えてます。）

より戦略的に連絡をしていかないといけない今の時代で、営業の大きな味方になり得るのがこのSalesforce。

Salesforceは営業支援のツールとして第一線級であり、私の知る中でも多くの企業様で利用されています。
珍しいのは、大企業・中小企業問わず導入されることがあることです。
（ITツールは利用する組織が小さいと、機能的にToo Muchである傾向がある印象。
　Salesforceにはそれがない。）


Salesforceは、営業支援の用途だけではなく、
業務アプリケーションを開発するプラットフォームが内包されています。

聞いたことがある人がいるかもしれません、Javaに近いとされるApexと
SQLに近いとされるSOQLという独自の言語を使って業務ロジックを記述することができます。
（GUIを使ってノーコードでロジックを実装するフローという機能もあります。）

プログラムの開発経験のない一般の営業職の方が、これらを使った業務効率化を行うのは非常に難しいと思われます。
ここで技術者が求められるのかなと、そう考えています。

実際、その辺の開発をして、どんなメリットがあるの？
というところまで書いてしまうと、本筋から逸れますので、
一旦Salesforceの話はここまでとさせていただきます。

<h2>UI/UX は TypeScript</h2>
さんざんWeb界隈では言われていることと思います、React, Vue, Angularと。
ここ最近のUI/UX開発ではこれらの言語が主流ですね。

私はUI/UX開発ではAngularを好んで使います。理由は特にありません。
それを使って、お客様の要望を叶えられるから使っています。

自在に使えればとてつもない武器になることは間違いないです。

本当に学ぶのに時間を要するので、社内で一度でも「彼はAngularの案件をスムーズに仕上げたらしい」と評判が広まると
ガンガンUI/UX関係の仕事が回ってくる来るようになりますね。

サクッと社内のWebシステム組めたりするので、できるようになって間違いなく得しかないです。
きらびやかな資格とかがあるわけではないですけど、学ぶならTypeScriptですね。


<h2>AWS はもう、できないとダメ</h2>
できない人、「え、できないの」って感じです。
（ここで言っているできない・できるはクラウド環境の構築ではなく、環境の立ち上げやアプリケーションをリリースしていくうえで、構成を考えたりできることを言っています。）

インフラ的な知識が要求されるため、慣れていない人にとってはついていくのに時間がかかる人もいると思います。
逆に、基本情報技術者や応用情報技術者の資格保持者であれば、あまり業務で携わってなくても、イメージが付きやすく学びやすいと思います。

AWSが絡むプログラムも少し独特なところがあるので、そういった点も含めてカバーできると、活躍しやすいのかなと思います。

基本情報や応用情報を学び、言葉や知識が分かったら、
サーバーサイドに慣れるためにRaspberry pi を買うか、VagrantなどでLinuxを触りサービスを立ち上げてみるといいのかなと思います。

リモートでも資格試験が受けられるようですので、目指してみるのもありですね。


<h2>個人的に気になる Rust</h2>
新しい技術大好きエンジニアなら、知らない人はいないかなと思っています。
私はプロフィールのところでも挙げているように、業務アプリケーションを構築する機会があります。
ひと昔前なら.Netで、今は場合によってはJavaで組んだりするものですね。

Rustは言語特性上、上記に似た使い方や何かのツールの中身で使うとよさそうな雰囲気を感じています。

もういい加減pythonは流行りきったのかなと思うので、
エンジニアの中で話題になっていく言語はこれなのかなって、特に理由なく思っています。
（UI/UX関連の人は選ばないように感じますが。。。(笑)）
[Flutter] DecorationImageのColorFilterで画像加工する


Flutterのアプリ開発で実装したことを記事にしました。
ColorFilterは、DecorationImageの画像の色味を変化させたいときに使います。

具体的には、下の画像の様にすることができます。

![スクリーンショット.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1435645/c889ebd3-b03e-a798-26eb-f569519d6764.jpeg)

## DecorationImageの画像にColorFilterを追加する

```dart
Container(
            decoration: BoxDecoration(
              image: DecorationImage(
                image: AssetImage('assets/images/test_image.jpg'),
                fit: BoxFit.cover,
                colorFilter: ColorFilter.mode(
                  Colors.white.withOpacity(0.2),
                  BlendMode.srcATop,
                ), // colorFilterを追加
              ),
            ),
          ),
```

`ColorFilter.mode( Color color, BlendMode blendMode )`

を変更すれば、画像に様々なフィルターをかけることをできますが、

`BlendMode`はバリエーションが多く、全ては理解できませんでした。

画像に指定した色を重ねるなら、`BlendMode.srcATop`がわかりやすと思います。

白黒写真の様にするには、

`ColorFilter.mode(Colors.grey, BlendMode.saturation)`

が使えます。

![スクリーンショット 2022-01-29 14.44.50.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1435645/be0a70de-7195-f186-ade3-b610e87f5edb.jpeg)



## 参考にしたサイト

https://api.flutter.dev/flutter/dart-ui/ColorFilter/ColorFilter.mode.html

https://api.flutter.dev/flutter/dart-ui/BlendMode.html
集合ってすげぇ〜〜〜 Atcoder abc236 C

## 結論

set()は今まで重複したものを確認するためだけに使ってたけど
処理速度を意識した上でも使える素晴らしい技術なんだなぁって思い知りました！

## 問題

> AtCoder 鉄道のとある路線には N 個の駅が存在し、始点から終点に向かって i(1≤i≤N) 番目の駅の名前は$S_{i}$です。
普通列車は全ての駅に止まりますが、急行列車は全ての駅に止まるとは限りません。
具体的には、急行列車は M(M≤N) 個の駅にのみ止まり、j(1≤j≤M) 番目に止まる駅の名前は$T_{j}$です。
ただし、 $S_{1}$=$T_{1}$ かつ $S_{n}$=$T_{n}$ 	​
 、すなわち急行列車は始点と終点の両方に止まることが保証されます。
N 個の駅それぞれについて、その駅に急行列車が止まるかどうか判定してください。


## 俺の回答

```C.py
n,m = map(int,input().split())
 
normal_train = list(input().split())
express_train = list(input().split())
 
for i in normal_train :
    ans = 'Yes' if i in express_train else 'No'
    print(ans)
n,m = map(int,input().split())

normal_train = list(input().split())
express_train = list(input().split())

for i in normal_train :
    ans = 'Yes' if i in express_train else 'No'
    print(ans)

```

C問題にしても簡単すぎひん？ってなりながら提出ボタン押したら
LTEになって「はぁ？？？」ってなった

まぁ処理量考えたら確かに全回しではダメなんかなぁとかよくわからず考えてて、とはいえこれ以外の回答を思いつかなかったので渋々答えを確認

##　解答

``` python
n, m = map(int, input().split())
s = input().split()
t = set(input().split())
for x in s:
    print("Yes" if x in t else "No")
```


?????

ほぼ俺の答えと一緒やんけ！ってなった。
唯一違うところは``set()``の部分くらい

実際自分の``express_train = list(input().split())``をsetに変えたらLTEにならず速攻処理が終わった。


## 検証

あんまり意味もよくわかってないので、一旦自分で処理を書いて動かしてみる

```extra.py
import time

def check_test_func(s,group) :
    ans = []
    for i in s :
        if i in group :
            ans.append('a')

s = [ i for i in range(100) if i % 2 == 0]

list_t = [ i for i in range(10000000)]
set_t = set([ i for i in range(10000000)])

start = time.time()
check_test_func(s,list_t)
elapsed_time = time.time() - start
print("{:.03} ms in {}".format(elapsed_time * 1000, 'list_t'))

start = time.time()
check_test_func(s,set_t)
elapsed_time = time.time() - start
print("{:.03} ms in {}".format(elapsed_time * 1000, 'set_t'))
```

結果
```
0.125 ms in list_t
0.041 ms in set_t
```

集合って存在判定するの圧倒的に爆速なんやなぁ
理由はわからん


## 理由調べた

答えはいたってシンプルでPythonのsetはハッシュテーブルで実装されているから。らしい

ハッシュテーブルの俺のイメージは、ハッシュ値をキーにしてバリューを持っている感じ
なのでキー検索を行えるので、listで全探索して検索するより爆速なんだね…

集合は重複排除と論理演算系でしか今まで使ってなかったけど、
これからは探索時に上手いこと使える時があれば使っていくようにします！
AppScriptでトラックパッドとマウス環境を切り替える

MacBookを自宅はマウス・外はトラックパッドを使うときにスクロール方向が違う:japanese_goblin:
(Logicoolなんかはソフトウェアで対応してる)
で，スクロール方向を切り替えるために[システム環境設定]->[トラックパッド]->[スクロールの方向：　ナチュラル]とやっていた訳だが，`AppScript`で自動化出来そうだということがわかった．

### 環境
macOS Monterey 12.2

### 手順
1. AppScriptでスクロール方向を切り替えるスクリプトを記述する
1. コードをアプリケーションとして書き出す
1. ワンクリックで実行させるために「ショートカット.app」で書き出したアプリケーションを起動するプログラムを組む

### スクロール方向を切り替えるスクリプト

[参考にさせて頂いたサイト](https://qiita.com/satosystems/items/8fff5b2313ecd6f81af3)

```applescript
set didRunSystemPreferences to get running of application "System Preferences"

tell application "System Preferences"
	set current pane to pane "com.apple.preference.trackpad"
	tell application "System Events" to tell tab group 1 of window "トラックパッド" of application process "System Preferences"
		click checkbox 1
	end tell
end tell

if not didRunSystemPreferences then
	quit application "System Preferences"
end if
```
![スクリーンショット 2022-01-29 14.07.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/5c35b460-4b68-1b72-e0ea-504f88f645c3.png)
Spotlightを開いて「スクリプトエディタ」と入力しEnter．
新規資料作成で上記のコードをペースト．
![スクリーンショット 2022-01-29 14.06.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/7c80b2c5-d0a8-05e5-9a49-6cdf866905f2.png)


### 書き出し

メニューバーの[ファイル]->[書き出す]をクリック
![スクリーンショット 2022-01-29 14.06.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/574f5ad7-45b6-c2d0-8dcc-03aadd6cfc6f.png)
表示されたダイアログから***保存先(場所)***を[アプリケーション]に指定し，[ファイルフォーマット]を`アプリケーション`にし[保存]
![スクリーンショット 2022-01-29 14.06.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/558f00bd-fb52-b48d-22ee-b93db9013ce1.png)

### 権限設定

[システム環境設定]->[セキュリティとプライバシー]->[アクセシビリティ]に移動し`＋`ボタンを押して先ほど書き出したアプリケーションを追加します．
![スクリーンショット 2022-01-29 14.07.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/e06591b9-02ea-1676-a5b9-a737ac98a36a.png)
### ワンクリックで起動
`ショートカット.app`を開いて[メニューバー]から`+`を押します
![スクリーンショット 2022-01-29 14.08.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/01d9e575-e1de-13a8-892b-04375267fe8b.png)
右側の[スクリプティング]をクリックして[AppScriptを実行]をドロップします．
![スクリーンショット 2022-01-29 14.08.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/9922175d-c5c5-32b9-750b-d8bfb90bbf83.png)
以下のコードを貼り付ける(`"toggleTrackpad"`は書き出したアプリケーション名です)

```applescript
tell application "toggleTrackpad"
	activate
end tell
```
![スクリーンショット 2022-01-29 14.09.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/c433b151-91b4-a1d6-1994-7cea6c8747db.png)

### 確認
メニューバーに追加されていれば成功です．
![スクリーンショット 2022-01-29 14.09.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/a9c5c874-6bae-b950-e3f6-168999cd03cc.png)
### 最後に
快適なMacBookライフを

#### 参考にさせて頂いたサイト
https://qiita.com/satosystems/items/8fff5b2313ecd6f81af3
https://zenn.dev/rot1024/articles/mac_keyboard_layout_monterey
vscode上でgit 2.25で変更ファイルの削除ができない

# 経緯
vscodeでgitをガッツリ使っていて、色々インストールしたりした結果、変更ファイルが数千個となった。

そこでこれらのファイルを一括で削除しようとしたのだが、これが何度やっても完了しない。

①削除前
![スクリーンショット 2022-01-26 午前7.00.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487834/77f1cf05-81c1-60b9-4b3c-6e32768f043d.png)
②削除ボタン押下
![スクリーンショット 2022-01-26 午前7.01.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487834/ae6ece45-51fb-e450-f072-de6855a3c2de.png)
③更新中
![スクリーンショット 2022-01-26 午前7.01.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487834/b440e876-4faf-9999-eb28-0d6f1e95c132.png)
④ダメ....!?!?!?!?!?
![スクリーンショット 2022-01-26 午前7.01.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487834/8dc9cd89-4194-edf9-e573-23aed882e003.png)


日本語の記事が見つからず途方に暮れていたが、普通にgithub issue見るとあったので他に困った人ように執筆する。

# 解決策
GITのバージョンを3.35(latest)に変更した。
# 環境
git: 2.25
vscode: 1.61.1
# 具体的に
## 現在利用しているgitのバージョンを確認する。

```
$ git --version
git version 2.25.0
```
[gitのissue](https://github.com/microsoft/vscode/issues/91080)によるとgit 2.25の場合は変更ファイルが削除できない問題が起きるようだ。
ついでなので最新版(3.35)にしてしまおうと思う。

## git 2.25.0をunlinkする

```
$ brew unlink git
```

## 最新版のgitをインストールする
```
$ brew install git
```

# まとめ
日本語で検索しても全く記事が見つからず途方に暮れて英語で検索すると一瞬でgithubのissueにたどり着けたのでおすすめ。
正直、この変更ファイルの問題がここ数日かなりの悩みになっていたので、解決できて本当に嬉しい。号泣中だ。

# 参考

https://github.com/microsoft/vscode/issues/91080#issuecomment-593824961
Ubuntuで使えるツールで便利なものを少しづつ紹介していく



### google-drive-ocamlfuse
グーグルドライブをマウントする
https://github.com/astrada/google-drive-ocamlfuse

### clasp
GASをローカルのエディターで編集する
https://github.com/google/clasp

### ngrok
ローカルホストを外部にポート開放する

```sh
$ sudo snap install ngrok
```
PHP mb_strlen(), strlen()の違い

現在、転職のために「PHP」を学習しているのでそこで学んだことを書いています。
間違い等もあると思いますがご了承ください。

####mb_strlenとstrlenの違い
mb_strlen() = 引数に指定した<font color="Red">文字列の長さ</font>を取得する。
strlen() = 引数に指定した<font color="Red">文字列の長さをバイト数</font>で取得する。
実際にコードを書いてみると下記のような結果になります。

```
$a = "おーい、お茶";
$b = "abcdef";

echo mb_strlen($a); // 出力：6
echo strlen($a); // 出力：18

echo mb_strlen($b); // 出力：6
echo strlen($b); // 出力：6

```

strlen(#array1)が18を出力するのは「エンコーディング」によるものだそうです。(日本語は2バイトだと思っていました。)
エンコーディングについてはこちらのサイトに書いてありましたので下記サイトを参考にしてみてください。
参考：https://www.morisawa.co.jp/culture/dictionary/1902

まだまだ知らないことばかりで「バイト数」を調べるのはどんな時に使うのかわからないので、
mb_strlen()を使う機会の方が多いのかなと思いました。
【随時更新予定】macOS 12.2 Monterey上のpyenvで環境構築可能なPythonのバージョンの備忘録

筆者のMacはmacOS 12.2 Montereyがインストールされています。pyenvと言えばPythonのバージョン管理アプリケーションであり、数年前から筆者も愛用しています。Montereyはリリースされて間も無いためか、pyenvで環境構築出来るバージョンと、ビルドエラーが発生してしまうバージョンが有ります。環境構築時にビルドエラーで詰まってしまうと困るため、備忘録メモとしてまとめておこうと思います。

# 2022年1月現在の状況
macOS 12.2 Monterey上のpyenvで`pyenv install x.x.x`を実行して環境構築出来たバージョンは以下の通りです。但し、dev版やcondaシリーズ等のバージョンは試しておらず、素のPythonのみです。

環境構築可能なバージョン

* 3.10.2
* 3.10.1
* 3.10.0
* 3.9.10
* 3.9.9
* 3.9.8

# 3.9.7以前のバージョンを環境構築しようとした場合
以下の様にエラー終了[^exit1]します。

```bash
$ pyenv install 3.9.7
python-build: use openssl@1.1 from homebrew
python-build: use readline from homebrew
Downloading Python-3.9.7.tar.xz...
-> https://www.python.org/ftp/python/3.9.7/Python-3.9.7.tar.xz
Installing Python-3.9.7...
python-build: use readline from homebrew
python-build: use zlib from xcode sdk

BUILD FAILED (OS X 12.2 using python-build 2.2.4)

Inspect or clean up the working tree at /var/folders/7c/6xh3jhtj0pg15z13c49kmych0000gn/T/python-build.20220129135718.47549
Results logged to /var/folders/7c/6xh3jhtj0pg15z13c49kmych0000gn/T/python-build.20220129135718.47549.log

Last 10 log lines:
checking for a sed that does not truncate output... /usr/local/opt/gnu-sed/libexec/gnubin/sed
checking for --with-cxx-main=<compiler>... no
checking for clang++... no
configure:

  By default, distutils will build C++ extension modules with "clang++".
  If this is not intended, then set CXX on the configure command line.
  
checking for the platform triplet based on compiler characteristics... darwin
configure: error: internal configure error for the platform triplet, please file a bug report
```

# まとめ
pyenvを用いてmacOS Monterey上に環境構築するときのための備忘録をまとめました。Montereyは昨年12月にリリースされたばかりのため、まだまだ各種アプリケーションの更新が追い付いていない様に思います。Pythonは利用者が多いので、今後更新が進んでいくのではと思います。

[^exit1]: clang++がnoになていますが、実際にはclang++やgccはインストール済の環境です。
brewコマンドが見つかりませんcommand not foundとなるときの解決策

#背景

MacOSのターミナルにて、「brew　○○」というコマンドを実行したときに、「command not found」エラーになったときの解決方法のメモ。

#解決策

ターミナルにて以下のコマンドを実行して、brewをインストールすればOK。
インストールの途中で「継続しますか？」と聞かれるのでYesを選択する。

```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```

#参考

https://lanchesters.site/brew-commnad-not-found/
ITSS とは

## 勉強前イメージ

ITのレベル？とかの基準だった気がする

## 調査

### ITSS とは

IT Skill Standard の略で、ITスキル標準と日本語では呼ばれています。
経済産業省が策定したIT系のスキル体系のことを指します。

2002年に策定・公表され、2004年移行はIPAのITスキル標準センターが管理を行っています。
IT領域の職種を11種類の分類、38種類の専門分野に分けて定義を行い、
能力や実績に基づいや7段階のレベルを設定します。

### レベル、職種について

#### レベル

まずレベルは1-7の7段階あります。

- レベル1 : 最低限必要な基礎知識を有する。
- レベル2 : 基本的知識・技能を有する。指導者のもとで要求された作業を担当する。
- レベル3 : 要求された作業を全て独力で遂行する。応用知識・技術を有する。
- レベル4 : プロフェッショナルとしての専門分野が確率し、独自で課題の発見と解決をリード。
- レベル5 : 社内でテクノロジ、ビジネスを創造してリード。社内のハイエンドプレイヤーとして認められる。
- レベル6 : 社内外でテクノロジ、ビジネスを創造してリード。国内のハイエンドプレイヤーとして認められる。
- レベル7 : 市場全体で見てサービスの開拓やリードの経験を有する。世界のハイエンドプレイヤーとして認められる。

#### 職種

分類されている職種は11種類あります。

- マーケティング : 顧客ニーズと市場動向を予測、戦略を立てる。
- セールス : 顧客の課題に対する提案を行い、顧客満足度を高める。
- コンサルタント : 顧客のビジネスに対するアドバイスなどを行い、経営判断を支援する。
- ITアーキテクト : HW/SW関連技術を活用し、設計を行う。
- プロジェクトマネジメント : PJの提案実行、管理を行う。
- ITスペシャリスト : HW/SW関連技術を活用し、顧客に最適な基盤の設計導入まで行う。
- アプリケーションスペシャリスト : アプリケーションの設計開発、保守まで行う。
- ソフトウェアデベロップメント : マーケティングに基づいた製品の企画開発を行う。
- カスタマーサービス	 : 専門技術を元に、顧客へのHW/SWの導入、保守を行う。
- ITサービスマネジメント : 運用の技術を活用し、システム全体の安定のため運用を行う。
- エデュケーション : 研修などの設計、計画評価を行う。


### 他にもUISS・ETSS・CCSFがあるがこれは？

- UISS

ITシステムを活用する組織においてスキルを整理した指標。
ITSSとの異なる点は、ユーザを対象としてるため、
組織の機能とその業務、すなわちシステムの企画開発から廃棄までのサイクルのプロセスによって体系化しています。

- ETSS

組み込みソフトウェアの開発に必要となるスキルを整理した指標で、
組み込みエンジニアに絞られています。

- CCSF

スキル標準を使用するにあたっての課題やビジネスモデルに対応するスキルの変化に柔軟に解決するために考えられました。
ITSS・UISS・ETSSなどのスキル標準を参照しながらす作られています。
この3つでいうとこれだけ毛色が違いますね。

## 勉強後イメージ

マーケティングもこれに入ってるのか・・・

## 参考

- [ITSS（ITスキル標準）とは？ 実務に活かせるスキルの種類とレベル指標](https://www.kaonavi.jp/dictionary/itss/)
- [「ITSS（ITスキル標準）」とは？社内で運用を進めるコツを紹介|社員のスキル・教育訓練・資格・力量を一元管理、スキル管理クラウドSKILL NOTE(スキルノート)](https://www.skillnote.jp/knowledge/skillmap_itss/)
[Solved] truffle : Could not find a compiler version matching 0.8.xx



> Error: Could not find a compiler version matching 0.8.xx. Please ensure you are specifying a valid version, constraint or build in the truffle config. Run \`truffle compile --list\` to see available versions.

This will happen once you have installed truffle using sudo or different version.

Delete the following temporary folder and compile it to solve the problem.

- Mac: ~/Library/Preferences/truffle-nodejs
- Ubuntu: ~/.config/truffle-nodejs
pandasチュートリアル on Jupyter Notebook

pandsチュートリアルWebサイトの内容を翻訳し<font color=blue>Jupyter Notebookで実際に動かしながら学習できる</font>ように編集しました。

元にしたWebサイトはこちら

https://pandas.pydata.org/pandas-docs/stable/getting_started/intro_tutorials/index.html

&nbsp;
オリジナルのサイトに加え、<font color=blue>わかりにくいと思われる箇所の補足説明</font>や、基本的に<font color=blue>全てのコードが実行できる</font>ようにしています。

<font color=blue>pandsの学習ツールとして活用ください。チュートリアル記載以外の事項を自由にコードを変更・追加しながら確認することで理解が進みやすいかと思います。</font>

:arrow_down: <b>下記のGithubのサイトからファイルをダウンロードして、Jupyter notebook環境、またはGoogleコラボ上で実行してください。</b>

https://github.com/DeepAelurus/pandas_Learnng

+ Pandas.ipynb : pandasチュートリアル

---

pandasチュートリアルの翻訳のみは下記で記事を投稿しています。

https://qiita.com/DeepTama/items/983dcee3d522f4e9f07a

&nbsp;
また、pythonチュートリアル及びnumpyチュートリアルを同様に動かしながら確認できるように下記のGItHUBで公開していますので合わせて活用ください。

https://github.com/DeepAelurus/Python_Leraning

&nbsp;

https://github.com/DeepAelurus/numpy_Learning


# サンプルイメージ

上記コンテンツのサンプルイメージです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1413278/b62a1ec3-8f5e-37ad-bf0c-90a3d5a64249.png)


・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1413278/092b5ec3-ebe2-5f92-36e9-bb9687a340bc.png)


# 参考

## Googleコラボをまだ使ったことがない方は下記を参考にしてください。

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


## Googleコラボのインストールは、以下の手順で簡単に行えます。

- Googleアカウトを作成（まだ持っていない場合）
- Googleドライブ上で左上のメニューから「アプリで開く」->「アプリを追加」で、Googleコラボ　　を選んでインストール

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1413278/5da58c21-830f-4628-08ca-c01eaff6c0fa.png)

- Githubからアップロードしたファイルを実行するとGoogleコラボで起動します

誤りや不足、加筆修正すべきところがありましたらぜひご指摘ください。継続してブラッシュアップしていきます。
© 2022 [NPO法人AI開発推進協会](https://sites.google.com/deepaelurus.com/aboutus/home)
argumentsを使いactivityからfragmentにオブジェクトを渡す【Android】【kotlin】

フラグメントに値を渡すやり方を備忘録として残します。

activityからactivityへの値の受け渡しはintentを使いました
fragmentに値を渡すときにはargumentsというfragmentが持つプロパティをつかいます。

argumentsはBundleという型のプロパティです。
値を渡すにはBundleのインスタンスを作り、BundleにputIntなどで値を渡します。

オブジェクトを渡す方法は、、、
main.Activity内でfragmentクラス、Bundleクラスをインスタンス化する
インスタンス化したbundleにputParceLable(キー,　オブジェクト)
fragmentクラス.arguments = bundle
と繋ぐことで対象のfragmentへオブジェクトを渡すことができる。

前提としてデータクラスを使い@Parcelizeを実装してるとする。

```main.Activity
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        //インスタンス
        val myNum = MyNum()

        //フラグメントを表示させる
        numFragment = NumFragment()
        val bundle = Bundle()
        bundle.putParcelable("NUM", nyNum)
        standardFragment.arguments = bundle
        supportFragmentManager.beginTransaction().apply {
            replace(R.id.container, standardFragment)
            commit()
        }
    }
}
```

受け取り側

```Num.Fragment
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //本来はgetArgumentsメソッドだがKotlinはargumentsプロパティを使用できる
        arguments?.let {
            //argumentsに保存したものをbmiBodyに保存する
            bmiBody = it.getParcelable<MyNum>("NUM")
        }
    }
```

以上でargumentsを使ったオブジェクト渡しになります。
インテントを使ったものと基本的には同じような流れになると思います。
QRコードでシークレットを渡してワンタイムパスワード認証する（Google AuthenticatorとかAuthyみたいな）やつがやりたい

# 自前のシステムでも多要素認証やりたい

画面に表示されたQRコードをスマホアプリにぴっと読み込み。
すると、30秒ごとにワンタイムパスワードが生成されるようになります。
あれを自前のシステムでもやりたいです。


# QRコードの内容

QRコードの内容は **otpauth://** で始まるURIになっています。
まずはこれを作れればスマホアプリで読み込めますね。

# otpauth URI スキームの構造

こういうものの仕様は、RFCにあるかと思えば見つかりません。[stackexchangeに質問](https://softwareengineering.stackexchange.com/questions/210597/who-invented-the-otpauth-uri-scheme)がありました。回答によると、otpauth URIはBlackberryのソースコードに由来するようです。


URIの一般構造（引用元 RFC 3986）を眺めながらソースを追ってみます。

```
   foo://example.com:8042/over/there?name=ferret#nose
   \_/   \______________/\_________/ \_________/ \__/
    |           |            |            |        |
 scheme     authority       path        query   fragment
```

ソースによると **otpauth** と **totp** の2つのスキームと、普通のURLが使えます。

それぞれのスキームごとにURIの使い道をまとめてみます。

| scheme | authority | path | query | fragment |
|:-:|:-:|:-:|:-:|:-:|
| **otpauth**  | **totp**  | ユーザ名  | シークレット(**secret**キー)  | - |
| **otpauth**  | **hotp**  | ユーザ名  | カウンター(**counter**キー)、シークレット(**secret**キー)  | - |
| **totp**  | ユーザ名  | -  | -  | シークレット  |
| 上記以外| - | - | ユーザ名(**user**キー) | シークレット |

シークレットはBase32エンコードされた文字列です。

## サンプルURI

こんなURIを作ればよさそうです。

otpauth://totp/anonymous@example.com?secret=NFWG65TFPFXXK===
otpauth://hotp/anonymous@example.com?counter=100&secret=NFWG65TFPFXXK===
totp://anonymous@example.com#NFWG65TFPFXXK===
http://example.com/?user=anonymous@example.com#NFWG65TFPFXXK===

QRコードにしてみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59475/6b072e00-8f46-dfd4-fc4f-d68561dd3eaa.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59475/9d0c3d17-8c93-09a9-7533-8ee313004087.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59475/4ad0929c-702f-a7ff-c351-24f6097b566c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59475/9288a7f3-14d7-2512-73f6-b58003cb2bc6.png)

（QRコードは https://www.cman.jp/QRcode/qr_make/ で生成しました。感謝！）

読み込めますか？
Authyアプリでは、otpauthスキーマのtotpしか読み込めませんでした。


# ここまでくれば

あとは、以下のことをすれば実装できそうです。

* QRコード発行時
  * 暗号論的にランダムなシークレットを生成
  * シークレットを保管
* ログイン時
  * Unix timeとシークレットからワンタイムパスワードを生成
  * ユーザが入力したワンタイムパスワードと、生成したワンタイムパスワードを比較して認証

# 気になること

シークレットを生のまま保管しておくのって、なんかパスワードを生のまま保管するみたいで気になります。

# 追記

さらに探したら、otpauth URIのフォーマットありました。

https://github.com/google/google-authenticator/wiki/Key-Uri-Format

こんなフォーマットです。

```
otpauth://TYPE/LABEL?PARAMETERS
```

PARAMETERSには以下の項目があります。

| パラメータ | 必須？ | 既定値 | 説明 |
|:-:|:-:|:-:|:--|
| secret  | 必須  | -  | シークレット |
| issuer  | 強く推奨 | -  | シークレットの発行者 |
| algorithm  | オプション  | SHA1  | SHA1、SHA256、SHA512のいずれか |
| digits  | オプション  | 6  | OTPの桁数 |
| counter  | hotpの時必須  | - | カウンター  |
| period | totpのときオプション | 30 | totpの生成間隔（秒） |

全部入りだとこんなURIになります。

otpauth://totp/anonymous@example.com?secret=NFWG65TFPFXXK===&issuer=example&algorithm=sha256&digits=8&period=15

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59475/55da255e-4641-57de-70dd-bb59d1f997ba.png)
Laravel8とBreezeとDebugbar インストール(メモ)

https://kaiblo.com/laravel8%e3%81%a8breeze%e3%81%a8debugbar-%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab%e3%83%a1%e3%83%a2/

に移動しました
[aspect-ratio]Youtube動画などのiframeタグの中身を縦横比を維持したままレスポンシブにする

## 概要

Youtube動画を埋め込んだ時に`width`と`height`が固定になっていて、スマホで表示した時に横幅が画面からはみ出していました。

メモとして、変更点のみ記載します。

## 修正前

```
<iframe width="560" height="315"></iframe>
```

## 修正後

```
<div style="aspect-ratio: 560/315;">
  <iframe width="560" height="315"></iframe>
<div>
```

下記でもOKみたい。

```
<iframe width="100%" height="100%" style="aspect-ratio: 560/315;"></iframe>
```

`aspect-ratio`は便利ですね😀

※Mac Safari(14.1.2)で`aspect-ratio`が効いてないから調べてみたら、対応してるバージョンは15(2021.9リリース)からなのか...
まだしばらく`padding-top: ~%`使った方がいいのかな。
[Can I use](https://caniuse.com/?search=aspect-ratio)
[Rails]ActiveJobのテスト方法[Rspec]

# はじめに
RspecでのJobのテスト方法を書いていきます。

# やること
今回はユーザー作成した際に、Slack通知がされるJobのテストを実装します。

# 実装

```ruby
require "rails_helper"

RSpec.describe SlackNotification::UserCreatedJob do
  # テストの対象
  describe "#perform" do
    # Job作成のコマンドを変数に入れる
    subject { SlackNotification::UserCreatedJob.new.perform(user.id) }

    # ユーザーを作成する(FactoryBotを使用する)
    let(:user) { create(:user) }
    
    #Jobがエンキューされたとき
    it "enqueues SlackNotificationJob" do
      # SlackNotificationJobの数が1個増えることを期待する
      expect { subject }.to change { SlackNotificationJob.jobs.count }.by(1)
    end
  end
end
```

# 説明
今回はJobを実行したときに、1つエンキューしたJobが増えるので、その増えた数でテストをしています。

# さいごに
Jobのテストって、何をテストしたら良いのか分かりづらかったです、、
re:Invent 2021 セキュリティ関連の新サービス、アップデートまとめ

re:Invent2021で発表されたセキュリティ関連サービスのアップデートをまとめてみました。

1/29 20:00 から [JAWS-UG横浜 #43 AWS re:Invent 2021 Recap Security](https://jawsug-yokohama.connpass.com/event/237168/) でこのあたりをキャッチアップしますので是非ご参加ください

## Amaozn Inspector の刷新を発表
https://aws.amazon.com/jp/blogs/news/improved-automated-vulnerability-management-for-cloud-workloads-with-a-new-amazon-inspector/

 - **継続的な自動評価スキャン** – 定期的な手動スキャンに取って代わります。

 - **自動リソース検出** – 有効にすると、新しい Amazon Inspector は、実行中のすべての Amazon Elastic Compute Cloud (Amazon EC2) インスタンスと Amazon Elastic Container Registry リポジトリを自動的に検出します。

 - **コンテナベースのワークロード**の新しいサポート – EC2 とコンテナインフラストラクチャの両方でワークロードが評価されるようになりました。

 - AWS Organizations との統合 – セキュリティチームとコンプライアンスチームが、組織内のすべてのアカウントで Amazon Inspector を有効にして活用できるようにします。

 - スタンドアロン Amazon Inspector スキャンエージェントの廃止 – **評価スキャンでは、広くデプロイされている AWS Systems Manager エージェントが使用される**ようになりました。これにより、エージェントを個別にインストールする必要がなくなりました。

 - 改善されたリスクスコアリング – CVE (Common Vulnerability and Exposures) のメタデータを、ネットワークアクセシビリティなどのリソースの環境要因と相関させることで、各検出結果について高度にコンテキスト化されたリスクスコアが生成されるようになりました。これにより、優先して対処すべき最も重大な脆弱性を特定しやすくなります。

 - **Amazon EventBridge** との統合 – Splunk や Jira などのイベント管理およびワークフローシステムと統合します。また、Systems Manager を使用したシステムのパッチ適用や、EC2 Image Builder を使用した仮想マシンイメージの再構築など、自動修復をトリガーできます。
 - AWS Security Hub との統合 – 重大な脆弱性のあるリソースやセキュリティのベストプラクティスからの逸脱をチームがより簡単に特定できるようにします。

## AWS RAMがグローバルリソースタイプに対応
https://aws.amazon.com/jp/about-aws/whats-new/2021/12/aws-resource-access-manager-global-resource-types/

- RAM は、組織内の個人の AWS アカウント間または AWS Organizations 内の組織単位 (OU) 間で、ならびにサポートされているリソースタイプの AWS Identity and Access Management (IAM) ロールおよびユーザーとの間で、リソースを安全に共有するのに役立ちます。

- グローバルリソースは、複数の AWS リージョンで使用できるリソース

- 今回、AWS Resource Access Manager (RAM) が、グローバルリソースタイプをサポート
    - 例えば、AWS とオンプレミスネットワークを含むマネージドネットワークである AWS Cloud WAN コアネットワークと RAM リソース共有を作成し、組織全体で共有できるようになりました。その結果、クラウド WAN コアネットワークを使用して、リージョン間およびアカウント間で統合されたグローバルネットワークを一元的に運用できます


## AWS managed Microsoft ADでCloudWatch対応を強化
https://aws.amazon.com/jp/about-aws/whats-new/2021/12/aws-managed-microsoft-ad-amazon-cloudwatch/

 - ドメインコントローラとディレクトリの使用率についてのメトリクスをCloudWatchで監視可能に
 - Amazon CloudWatch アラームを使って、追加のドメインコントローラーのデプロイを自動化することが可能
【pythonメモ】回数指定のfor文(for .. in range)の使い方


#1.はじめに

様々なプログラミング言語で使われるforループ。
pythonでは回数指定のforが３種類ある。
今更だけど、どうにも使いずらいので自分用のメモとしてまとめてみた。

#2.実行環境
OS:windows10
Python 3.8.10(jupyter notebook上で実行)
PHPはpaiza.ioで実行

#3.for .. in range

###`パターン１）for 繰り返し変数 in range(N1)`
N1:指定回数
指定回数だけある処理を実行したい場合使える。

```python
for i in range(5):
  print("Loto6")
```
```:出力結果
Loto6
Loto6
Loto6
Loto6
Loto6
```
ただし繰り返し変数も利用したい場合は、その値は__0～N1-1__となることに注意が必要になる。

```python
for i in range (5):
  print("Loto6トライ:"+str(i)+"回目")
```

```:出力結果
Loto6トライ:0回目
Loto6トライ:1回目
Loto6トライ:2回目
Loto6トライ:3回目
Loto6トライ:4回目
```

###`パターン２）for 繰り返し変数 in range(N1,N2)`

__開始値を0以外にしたい__ときに使う。
N1:開始値,N2:終了値
ここでは、繰り返し変数は__N1～N2-1__の値をとる。

```python
def print_nstar(n1):
  retstr=''
  if n1<= 0:
    return retstr
  for i in range(n1):
      retstr=retstr+'*'
  return retstr

for i in range (-1,5):
  print("Loto6:"+print_nstar(i))  
```

```:出力結果
Loto6:
Loto6:
Loto6:*
Loto6:**
Loto6:***
Loto6:****
```

###`パターン３）for 繰り返し変数 in range(N1,N2,Nst)`

N1:開始値,N2:終了値,Nst:増減間隔
__繰り返し変数の増減間隔を1以外にする__場合、
このパターンを使う。
繰り返し変数は__N1～N2-Nst__をとる。

__(1)増減値が正の時__

```python
#増減値が2
for i in range (-1,5,2):
  print("Loto6:"+str(i)+':'+print_nstar(i))
```

```:出力結果
Loto6:-1:
Loto6:1:*
Loto6:3:***
```
__(2)増減値が負の時__

```python
#増減値が負
for i in range (5,1,-1):
  print("Loto6:"+str(i)+':'+print_nstar(i))
```

```:出力結果
Loto6:5:*****
Loto6:4:****
Loto6:3:***
Loto6:2:**
```

#4.PHPでのfor
###`パターン）for(繰り返し変数=N1;繰り返し変数 演算子 N2;繰り返し変数 演算子 Nst)`

N1:開始値,N2:終了値,Nst:増減間隔
PHPのforは上記で指定できる。
どんな場合も1本で済む。
__終了値での〇〇以上、〇〇以下の指定ができる__のが大きい
__指定するものが多くて面倒くさい分、自由度が高い__

```php
<?php
// Your code here!
function getstar($n){
  $str0="";
  for($i=0;$i<$n;$i++){
    $str0=$str0."*";
  }
  $str0=$str0."\n";
  return $str0;
}
for($i=5;$i>=1;$i+=-1){
  print($i);
  print(getstar($i));
}
?>
```
__終了値の1*がポイント__

```:出力結果
5*****
4****
3***
2**
1*

```

#5.さいごに

同じ繰り返し処理でも、単純にある回数だけ実行したいとか、
細かい条件を決めて実行したいとかあるだろう。
__`pythonのfor rangeには最小限のコードでやりたいことを実現できる`__ようにしたい
との意図が見えるような気がした。
ただし、__終了値の指定には気を付ける必要がある__
ggplotでプロット内へのラベル出力を効率的に（directlabels）

Rで、`directlabels`ライブラリを使うと、折れ線や散布図、等高線などのプロットに対して、簡単に、かつ、もろもろ取りまとめて良い感じに？ラベルを出力することができる。

```R:R
# install.packages("directlabels")
library(directlabels)
```

プロットオブジェクトを作成したら、それをdirectlabelsの関数へ渡すだけでラベル付けしてくれる。
なお、ラベル化される変数は、fillやcolourに指定したもの。
引数の`positioning methods`に、「ラベル位置の決め方」を指定することで、良きにレイアウトしてくれる。

```R:R
p <- ggplot(…, aex(colour = [label's value])
direct.label(p, [positioning methods])
```

下記では、プロット種別ごとに`positioning methods`（ラベル位置）をいくつかピックアップした。

# 散布図
ラベル位置に"smart.grid"を指定することで、グループの中心に（探索して）ラベルを出力する。

```R:R
p <- ggplot(iris,aes(x=Sepal.Length, y=Sepal.Width, color=Species)) +
  geom_point()
direct.label(p, "smart.grid")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254095/6d336502-324f-c827-eadb-ccbdbc577b29.png)

ラベル位置に"extreme.grid"を指定することで、グループの端（四隅のどこか？）にラベルを出力する。

```R:R
direct.label(p, "extreme.grid")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254095/6b2ab022-1800-4240-fd19-dbe9892a45a9.png)


数値をラベルに指定した場合も、問題なく動作する。
ポイント描画のじゃまにならない程度にラベルを配置してくれるイメージ。
（ただ、処理時間は比較的長い）

```R:R
p <- ggplot(iris,aes(x=Sepal.Length, y=Sepal.Width, color=Sepal.Width)) +
  geom_point()
direct.label(p, "smart.grid")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254095/e7772717-621a-252b-6e84-b2aa885f9437.png)

# 折れ線グラフ

```R:R
# 描画用データ準備
df <- data.frame(WorldPhones) %>%
  tibble::rownames_to_column("Year") %>%
  gather(key="Country", value="Users", -Year) %>%
  mutate(Year=as.integer(Year))

# （下のような形式であればデータは何でもよい）
> head(df)
  Year Country Users
1 1951  N.Amer 45939
2 1956  N.Amer 60423
3 1957  N.Amer 64721
4 1958  N.Amer 68484
5 1959  N.Amer 71799
6 1960  N.Amer 76036
```

ラベル位置に"first.qp"を指定することで、折れ線の先頭にラベルを出力する。

```R:R
p <- ggplot(df, aes(x=Year, y=Users, colour=Country)) + 
  geom_line()
directlabels::direct.label(p, method="first.qp")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254095/55232a8b-a8c6-dc23-e8ba-d595b9abfd66.png)

ラベル位置に"last.qp"を指定することで、折れ線の末尾にラベルを出力する。

```R:R
directlabels::direct.label(p, method="last.qp")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254095/c7a6a958-54fb-576c-390b-6e7b92f98005.png)

ラベル位置に"angled.boxes"を指定することで、折れ線の適当な位置に矩形のラベルを出力する。

```R:R
directlabels::direct.label(p, method="angled.boxes")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254095/9927fe87-e986-b2eb-50da-41ee279d512f.png)

# 等高線図
ラベル位置に"top.pieces"を指定することで、各レベルの等高線の上側にラベルを出力する。

```R:R
p <- ggplot(faithfuld, aes(waiting, eruptions, z = density)) +
  geom_contour(aes(colour=..level..))
direct.label(p, "top.pieces")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254095/1650ae08-2987-2311-ec0a-c0b3ef433ac7.png)

ラベル位置に"top.pieces"を指定することで、各レベルの等高線の下側にラベルを出力する。

```R:R
direct.label(p, "bottom.pieces")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254095/dfa84e3d-ca0c-0584-b4a3-fe7e26aff9aa.png)
ActiveSupport::Concernの解説してみた

最近、実務をしていく中で、ActiveSupport::Concernというものが現れて、よく分からなかったので、自分で調べて多くのことを学んだのでシェアしようとおもいます。

##ActiveSupport::Concernって何がいいの？
結論からいうと、
**共通している処理をまとめることでDRY(Don't repeat yourself) にコードをかける**
ことがメリットなんです。
具体的には、2個使い方があるとおもいます。

論より証拠、ということで実際にコードを見ていきましょう

##1個目の使い方
1つ目の使い方は、ルーティングを設定する際に使います。
例えば、以下のようなコードを見てください

```
 concern :importable do
   collection do
     post 'import'
   end
 end

 resources :admins do
   concerns :importable
 end

 resources :users do
   concerns :importable
 end

=> /admins/import
=> /users/import
```

このように書くことによって、/importというURLがあるパスをスッキリと書くことができるんです。
もし、concernを使わずに書くとしたら、以下のような書き方になります。

```
 resources :admins do
   collection do
     post 'import'
   end
 end

 resources :users do
   collection do
     post 'import'
   end
 end

=> /admins/import
=> /users/import
```

今回は、collectionブロック内では、「post 'import'」しか指定していませんが、3つくらい指定していたら、行数が長くなるので、可読性がなくなってしまいます。
でも、concernをつかえば、スッキリ書くことができるんです。

これが1つ目のconcernを使うメリットです。

##2つ目のconcernの使い方
例えば、

```hoge.rb
 puts 'hoge'
 puts 'fuga'
```

```fuga.rb
 puts 'hoge'
 puts 'fuga'
```
この2つのファイルをみたとき、「あー、DRYじゃないなぁ」って思いませんか？
実際に書いてみると、下記のような書き方をします。

```app/models/concerns/example_concern.rb
module Example
  extend ActiveSupport::Concern

  included do
    scope :hoge, -> {puts 'hoge'}
    scope :fuga, -> {puts 'fuga'}
  end
end
```

このように書くと、先ほどの、hoge.rbとfuga.rbは下記のように書けることができます。

```hoge.rb
class Hoge < ApplicationRecord
  include Example
end
```

```fuga.rb
class Fuga < ApplicationRecord
  include Example
end
```
こうすることで、コードの修正がしやすくなるなど、色々なメリットがあるのでconcernの使い道は多いです！

以上です。
何か間違いがございましたら、ご教示いただけますと幸いです。


【参考資料】

https://railsguides.jp/routing.html#%E3%83%AB%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%81%AE%E3%80%8Cconcern%E3%80%8D%E6%A9%9F%E8%83%BD

https://qiita.com/ren0826jam/items/5e69db4da6020d0c4442

https://qiita.com/h-shima/items/d772b4cbe7368ddb8255
TypeScriptで宣言と定義を分けずに拡張メソッドを書く

ググって見つかる記事を参考にすると、interface + prototypeでメソッドの宣言と定義を2回に分けなければならず面倒。
けど、こんな感じでかけば定義と宣言を同時にできて楽。

### 適当なファイルにmixin関数を用意する
``` ts
function mixin(base: { prototype: any[] }, derived: object) {
    Object.getOwnPropertyNames(derived).forEach((propertyName) => {
        Object.defineProperty(base.prototype, propertyName as (keyof (typeof derived)), {
            // @ts-ignore
            value: derived[propertyName],
            writable: true
        });
    });
}
```

## 拡張部分

Arrayクラスに対してget, head, lastを定義する例。

``` prototype.ts
export {}

type Super<T> = Array<T>;
type ArrayExClass = typeof ArrayEx;
declare global {
    interface Array<T> extends ArrayExClass {}
}

const ArrayEx = {
    get: function <T>(this: Super<T>, index: number): T {
        return this[index];
    },
    head: function <T>(this: Super<T>): T {
        return this.get(0);
    },
    last: function <T>(this: Super<T>): T {
        return this.get(this.length - 1);
    },
}
mixin(Array, ArrayEx)
```

- prototypeに1個1個代入していくパターンに比べて、使いまわしが聞く。そのためmixinのような動きに近いこともできる。
- self type annotationみたいな制限もthisの型を調整すればできそう。
rinnaの日本語GPT-2モデルを Google Colab で実行してみる

# 公開ページなど

## りんな公式ページ
https://rinna.co.jp

## huggingface
https://huggingface.co/rinna/japanese-gpt-1b

# Google Colab で推論を試す

- 自然言語処理のライブラリとして [HuggingFace Transformers](https://github.com/huggingface/transformers) を使う。
- テキストをトークンに分割する際にtransformers.T5Tokenizerを利用するので [sentencepiece](https://github.com/google/sentencepiece) をインストールする。

```
!pip install transformers==4.4.2
!pip install sentencepiece==0.1.91
```

実際に推論を実行してみる。
テキストは、[にじさんじ非公式wiki](https://wikiwiki.jp/nijisanji/%E7%AC%B9%E6%9C%A8%E5%92%B2) からもらったもの。

```
from transformers import T5Tokenizer, AutoModelForCausalLM

# transformers.T5Tokenizer をトークンの分割に使用する
tokenizer = T5Tokenizer.from_pretrained("rinna/japanese-gpt2-medium")
# transformers.AutoModelForCausalLM でりんなの学習済みモデルを指定する
model = AutoModelForCausalLM.from_pretrained("rinna/japanese-gpt2-medium")

# 推論の実行
input = tokenizer.encode("2018年7月6日、にじさんじゲーマーズに追加された3名(いわゆる『ゲーマーズ2期生』)のうちの1人。パンダのパーカーとチラリと見える八重歯が", return_tensors="pt")
output = model.generate(input, do_sample=True, max_length=100, num_return_sequences=3)
print(tokenizer.batch_decode(output))
```

## 推論の結果
```
[
'2018年7月6日、にじさんじゲーマーズに追加された3名(いわゆる『ゲーマーズ2期生』)のうちの1人。パンダのパーカーとチラリと見える八重歯が
 よく似合う。 にじさんじのオンラインショップから、にじちゃん2期生が配信される。 2015年10月、ブログにて、「このたび、私の地元である岡山の地に来れなくなりました」と記述。 ブログとツイッターが1ヶ月ほど', 

'2018年7月6日、にじさんじゲーマーズに追加された3名(いわゆる『ゲーマーズ2期生』)のうちの1人。パンダのパーカーとチラリと見える八重歯が
 特徴。 このゲームには、2人のキャラクターをセットした『a・ab・ab』という「おやつタイム」なるものが存在する。 このゲームでは、同じキャラクターをセットした『a・ab』という「おやつタイム」というものが存在する。このa', 

'2018年7月6日、にじさんじゲーマーズに追加された3名(いわゆる『ゲーマーズ2期生』)のうちの1人。パンダのパーカーとチラリと見える八重歯が
 由来とされる。 a子さん、2年3組で副リーダーに立候補して、今年3年生になった。 a子「(私)はa子がリーダーになって、他の3人もそのまんま。 あ、私だけじゃなくて。 bさんとcくん'
]
```
やっぱり難しい日付のカスタムフォーマット

# はじめに
最近、たてつづけにAutomation360で日付の表示がうまくいかないという相談を受けました。例えば、2022/01/29という表示をしたいのにうまくいかないという現象です。
これは、Automation360に限った話ではありませんし、あちこちに書かれていますが、それでも間違ってしまう人が多いのです。
ネタの重複になるかもしれませんが、情報が目にふれる機会を増やす意味でここでも書いてみます。

#  日付のカスタムフォーマット（大文字・小文字に注意）
先に書いた「2022/01/29という表示」をしたい場合は、yyyy/MM/ddです。
yyyyとddは小文字。
MMは大文字。

yyyy/mm/ddやYYYY/MM/DDと書くとハマります。

![yyyymmdd2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632535/c1fe50da-0f36-4d42-a034-02a2ce874bfc.png)

#  大文字小文字ってどんな意味があるの？
これもあちこちに情報ありますが、例えば以下。
https://docs.oracle.com/javase/jp/8/docs/api/java/text/SimpleDateFormat.html

Mが月で、mは分というのは、間違っても気づきやすくて救われます。

でも、
yは年で、Yは暦週の基準年
dは年における日で、Dは月における日
って意味わからないですよね。

1月にYYYY/MM/DDって書いたら悲惨です。
すぐに間違いに気付きません。

1月は上手く行ってたけど2月に日付が変になる。
あわててDDを直して、一安心。
そのまま1年近くたった年末にサブマリン不良YYYY発動！になるかもしれません。

DDに比べると、YYYYはあまり知られていない感じがします。

#  まとめ
日付フォーマット文字列の詳細は、あちこちに書かれているのでここでは割愛します。
が、ここでお伝えしたいのは、ただ一言。
<font color="red" >**大文字・小文字の違いに注意しましょう！！**</font>
<br>
<br>
<br>


**詳しく知りたい人むけ参考サイト**
(1) yyyyとYYYYの話

https://qiita.com/Buzzword111/items/6a77ae48aeabad63d98c

https://sysrigar.com/2018/12/31/%E6%9A%A6%E9%80%B1%E3%81%AE%E5%9F%BA%E6%BA%96%E5%B9%B4%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/

https://nakamura001.hatenablog.com/entry/20150102/1420213850

http://muchoprogramingdiary.blog.jp/archives/78794279.html

<br>

(2) mmとMMの話

https://glassonion.hatenablog.com/entry/20050706/1120636290

<br>

(3) ddとDDの話も含んだ、とっても詳しいページ

https://qiita.com/tasogarei/items/df9e43ac36bde55aa928
【Nuxtでjsonをimport】Consider using '--resolveJsonModule' to import module with '.json' extension. の解決法

#はじめに
Nuxtでローカルに設置したjsonファイルをimportしようとすると・・・・
![スクリーンショット 2022-01-29 11.40.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/9d8a7eaa-b62c-e183-c228-d6e504edc784.png)

```console
Consider using '--resolveJsonModule' to import module with '.json' extension.
```

エラー発生！！！！

#`tsconfig.json`を編集
` "resolveJsonModule": true,`を`compilerOptions`に追加します。
これで解決！

```json:tsconfig.json
{
  "compilerOptions": {
    "target": "ES2018",
    "module": "ESNext",
    "noImplicitAny": false,
    "resolveJsonModule": true,
    "moduleResolution": "Node",
    "lib": [
      "ESNext",
      "ESNext.AsyncIterable",
      "DOM"
    ],
    "esModuleInterop": true,
    "allowJs": true,
    "sourceMap": true,
    "strict": true,
    "noEmit": true,
    "experimentalDecorators": true,
    "baseUrl": ".",
    "paths": {
      "~/*": [
        "./*"
      ],
      "@/*": [
        "./*"
      ]
    },
    "types": [
      "@nuxt/types",
      "@nuxtjs/axios",
      "@types/node"
    ]
  },
```


#参考

https://stackoverflow.com/questions/54476994/how-do-you-import-a-json-file-with-vuejs-typescript
rinnaの日本語GPTモデルの推論時間をCPUとGPUで測ってみた

npakaさんのrinnaの日本語GPTモデルの記事を読んで、自分でも動かしてみたかったのと、GPUとCPUでどのくらい推論時間に差があるのか知りたかったので試してみました。

https://note.com/npaka/n/nb8e38763ea30?fbclid=IwAR0BSRmB4KqzmibPQ9fUWB2ivJtNsAxpoGjfxmLd1L9bpeSi8Y84z8eh3sI

# 環境の準備
Windows 11の環境なので、以前の記事で紹介しているDocker環境を使います。

https://qiita.com/kekekekenta/items/d0d64688c889b860beba

PyTorchで動くようですので、NVIDIAのnvcr.io/nvidia/pytorch:21.12-py3コンテナイメージを使います。

```
docker run --gpus all -it -p 8888:8888 -v D:\work\rinna:/rinna nvcr.io/nvidia/pytorch:21.12-py3 bash
```

起動したら、トークン化を行うSentencePieceと、Transformersをインストール。

```
pip install sentencepiece==0.1.96
pip install transformers==4.16.1
```

# CPU実行とGPU実行の速度を比較してみる
CPUは、Intel Core i9-10850K。GPUは、NVIDIA RTX3090。
以下のコードに、実行時間を測定するコードを追加。

https://huggingface.co/rinna/japanese-gpt-1b

## GPU
GPUを使ってサンプルコードの設定（100文字）だと、zero-shotのタスクで7.5秒～15秒ぐらいでした。

「数学の勉強には、」　8.01272964477539(sec)

:::note info
数学の勉強には、問題の効果的な取り組み方と出題傾向の把握が重要になります。たとえば、中学受験を目指す場合、ただ学校の授業を真面目に聞いておればよいというわけではありません。学校の方針に
基づいて、学校の授業で出てきた問題から入試で出題されると予想される問題に取り組むことが必須なのです。入試問題に精通したプロの家庭教師であれば、そのような受験に適した指導が可能になります 。生徒さんは学校でただただ授業を聞いているだけでも、たとえ学校の授業はつまらなくても、入試問題で問われるような問題の傾向を把握することが可能です。そういう意味では、学校や
:::

「昔あるところに、」　7.435275077819824(sec)

:::note info
昔あるところに、パグシャという家がありました。この家はいつも貧乏だったので、誰も近づくことなく、家に引きこもっている状態でした。貧乏であるぶん、天からの恵みはいつも豊富にあるのですが、
めったにない機会に家のなかに入ることもありませんでした。ある日、パシャは、それまで見たこともないものを見てしまいました。それは、広い世界を通り抜けて来た長い立派な角のあるものだったので す。パシャは目が離せなくなって、毎日その家をのぞいてみました。すると、そこの子ども達が行列
:::

「今回のニュースは、」　14.761165142059326(sec)

:::note info
今回のニュースは、その「1枚の写真」をわざわざ報道したというものでした。内容としては、「1ヶ月ほど前に、山の中で小さなコオロギを偶然見つけた中国人女性。」と伝えています。それが「すごくか
わいいコオロギだった。見た瞬間、写真に撮りたいと思った。でも、誰も撮った人はいないみたいだったので、1枚を撮るしかないと思った。」とのことです。もちろん、そのコオロギは中国語で中国語が書かれている「珍奇珍念昆虫図鑑」という本で紹介されているようです。ちょっと切り取った
:::

## CPU
CPUをでサンプルコードの設定（100文字）だと、zero-shotのタスクで22.5秒～46秒ぐらいでした。

「数学の勉強には、」　22.76529622077942(sec)

:::note info
数学の勉強には、数学がなんのためにあるのかを説明してあげることが大事。だからまずは数学のはじまりである「算術」について、先生お薦めの教科書で基礎を勉強しよう。大切なのは問題を解くことで
はなく、「なぜそうなるのか」を説明すること。この、説明するための ステップ は、いわゆる解法の理解の補助 に充ててもいい。数学を勉強していて、どうしてこの解法をとったのだろうという疑問を持ったときは、問題を数多く解くだけでなく、その問題の図に書いた式を読み解いて、「なんで
:::

「昔あるところに、」　22.51263451576233(sec)

:::note info
昔あるところに、長屋井勇という人がいた。 非常な商売人で、品物を売るのが好きだった。 あるとき、宝石を二三集め、数珠を二十点ばかり作った。 それを買いに来たのは、美しい顔をした行商人だつた。 「どういうものです。御注文をお受けいたしますよ」 と長井勇は言つた。 行商人は、さもいやらしい顔をして、「それでいゝ、こんな物を幾つに切ってある、五つ丸に切つて
:::

「今回のニュースは、」　45.724703550338745(sec)

:::note info
今回のニュースは、この実験で、ビタミンDによる被験者の痛みが和らいだという結果が得られ、論文として出版されたというもの。論文には以下のように記載されております。ちなみにこちらは、ビタミンDの「快力戦隊メテオス」CMソング「ビタミンDー陽射しを求めてー」のギター・バージョンです。いい歌だ。ちなみに、「ビタミンDー陽射しを求めてー」は、ネット上にアップされていた動画だそう。You tube 動画レビュー ビタミンD (初音
:::

# さいごに
CPUで推論させても全然我慢できる時間でした。あと、SentencePieceを使っているからなのか、日本語に特化しているからなのか理由はわかりませんが、日本語の文章がきれいですね。
[Power BI] データリネージュと TREATAS

# はじめに

2022/01/29 

https://powerbi.connpass.com/event/234925/

PBIJP DAX Boot Camp #17 での発表内容です。

---

## なにするの

https://www.daxpatterns.com/semi-additive-calculations/

この記事内ででてくる`TREATAS`関数がよくわからないので調べてみた。

---

## そもそもデータリネージュとは

https://eow.alc.co.jp/search?q=lineage

リネージュ＝血統・血筋

データの血統。テーブル間のリレーションシップがどう引き継がれているか・・ってことかな。

---
## 実験１

区分名と西暦でクロスジョインしたテーブルを作り、受注額のカラムを追加します。

```datastudio
EVALUATE
FILTER (
    ADDCOLUMNS (
        CROSSJOIN (
            VALUES ( Products[区分名] ),
            VALUES ( Calender[年] )
        ),
        "Amt", [受注額]
    ),
    [Amt] > 0
)
```

---

### 結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/81432540-903e-9314-28b2-c0bda1015d4b.png)

期待した通りの値が出ています。

---

## 実験２

同じカテゴリー名を手動で定義したテーブルを作成し、売上列を追加する。

```datastudio
EVALUATE
VAR Categories = {
    "飲料",
    "調味料",
    "菓子類",
    "乳製品",
    "穀類/シリアル",
    "肉類",
    "加工食品",
    "魚介類"
}
RETURN
    ADDCOLUMNS (
        Categories,
        "Amt", [受注額]
    )
```

---

### 結果

カテゴリー名は同じものを定義していても、
データリネージュが失われているため売上金額は期待した値を集計してくれない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/517716ad-3de8-0899-e702-cc4cba7d8e97.png)

---

## 実験３

列名を新たに定義しなおして、集計がどうなるか確認します。

```datastudio
EVALUATE
ADDCOLUMNS (
    SELECTCOLUMNS (
        VALUES ( Products[区分名] ),
        "新しいカテゴリー名", Products[区分名]
    ),
    "Amt", [受注額]
)
```

---

### 結果

列名は関係がなく、売上額は期待通り集計されています。
エンジンはデータリネージュを保持しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/35dd3834-c09b-dc4e-0542-5f60cbbbf35d.png)

---

## 実験４

ほぼ同じDAX式ですが、区分名に `＆` を使用して、
`hoge` を追加して新しい区分名をつくります。

```datastudio
EVALUATE
ADDCOLUMNS (
    SELECTCOLUMNS (
        VALUES ( Products[区分名] ),
        "新しいカテゴリー名", Products[区分名] & "hoge"
    ),
    "Amt", [受注額]
)
```

---

### 結果

集計はうまく働きません。式を使用するとデータリネージュは失われます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/0b0e9b30-4695-1dd0-d087-08fd3cf40d76.png)

---

## TREATAS関数

>Applies the result of a table expression as filters to columns from an unrelated table.
>テーブル式の結果をフィルタとして、無関係なテーブルのカラムに適用する。

https://docs.microsoft.com/ja-jp/dax/treatas-function

---

## 実験４

`TREATAS`関数を使用して、自分で定義をした`Categories`の
データリネージュを変更する。

※存在しない列名は無視される。（この場合は`プロテイン`列）

```datastudio
EVALUATE
VAR Categories = {
    "飲料",
    "調味料",
    "菓子類",
    "乳製品",
    "穀類/シリアル",
    "プロテイン", --元のテーブルにはない項目を追加
    "肉類",
    "加工食品",
    "魚介類"
}
RETURN
    ADDCOLUMNS (
        TREATAS (
            Categories,
            Products[区分名]
        ),
        "Amt", [受注額]
    )
```

---

### 結果

データリネージュが変更され、集計が機能している。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/dc81db37-5550-e693-4f02-53a566622c39.png)

---

## まとめ

データリネージュとは、テーブル間のリレーションを意味している。データリネージュが維持されるときと、失われるときは正しく理解しておかないと、思わぬ集計ミスを招くこともありそうだ。

`TREATAS`の使い所については別記事に。

むずい :thinking_face:
Firebase Storageの使用量が勝手に増えていく件 → Firebase Functionsの影響ってマ？

# 問題発覚

修正してデプロイ。修正してデプロイ。

ふとFirebaseの課金額を確認してみるとStorageの使用量が日に日に増えている。なぜ？

特にストレージを使った記憶はない。Hostingのバックアップは設定しているのでHostingの影響でもなさそう。

artifacts *** appspot.comのストレージが増えている。ほんとになぜ？

GCPで確認してみると謎のファイルがたくさん。むむむ？

# Functionsのキャッシュが原因でした

functionsを更新するたびにキャッシュイメージが作成されるとのこと。

functions deployが高速化されるのは嬉しいが、過去のイメージがいつまでも残るのは勿体ない。

キャッシュは計画的に。

# 解決

GCP → Cloud Storage にアクセス。

artifacts *** appspot.comのバケットを選択してライフサイクル設定。

「オブジェクトを削除する」から「年齢」を任意に設定。

すぐにStorageを軽くしたい人は全選択して削除！
Next.jsのgetStaticPropsではnookiesによってcookieのデータを取得できなくて困った話

## 結論
getStaticPropsではなくgetServerSidePropsを利用してcookieのデータを取得した。
（SSGでcookieデータを取得しようと調べすぎたので、SSRで時間をかけずに実装する方が良いと感じた。）

## [nookies](https://www.npmjs.com/package/nookies)とは？
- cookieデータをクライアントで取得することが可能なJsライブラリ

コンポーネントの中でcookieの取り出し操作が簡単に行える。

## なぜgetStaticPropsだと取得できないのかを考える

### 今回やりたかったこと
getStaticPropsでcookie情報を取得したい

- 記事を探すものの・・・
  - getStaticPropsで取得する記事やドキュメントに情報がなかった。😭


あるのは[SSR、getServerSidePropsでの取得の方法](https://github.com/maticzav/nookies)のみ。

SSGで変更したかったがなくなくSSRでの実装となった。
(SSGで統一したかったという個人的な意志が崩されただけ)

```
import { parseCookies } from "nookies";

// nookiesによりcookieからデータを取得するメソッド
const getCookie = (context?: any) => {
  const cookie = parseCookies(context);
  return cookie.userId;
};
export default getCookie;


// SSRでフォロワーリストを取得
export const getServerSideProps: GetServerSideProps = async (context) => {
  // cookieに存在するユーザーIDを取得
  const userId = Number(getCookie(context));

  //　ユーザーIDをもとにフォロワーリストを取得
  const followerList = await fetchFollowerList(userId);

  return {
    props: {
        followerList: followerList,
    },
  };
};
```
### なぜSSGでcookieの取得ができないのか
[Next.jsの公式](https://nextjs-ja-translation-docs.vercel.app/docs/basic-features/data-fetching)を見ると

```
export async function getStaticProps(context) {
  return {
    props: {} // ページコンポーネントにpropsとして渡されます。
  };
}
```

> getStaticProps（静的生成）
ページから getStaticProps という async 関数をエクスポートすると、Next.js はビルド時に getStaticProps から返される props を使ってプリレンダリングします。



> contextパラメータは次のキーを含むオブジェクトです:
paramsはページが動的ルートを利用するためのルートパラメータを持ちます。たとえば、ページ名が [id].js である時、paramsは { id: ...} のように見えます。詳細は 動的ルーティングのドキュメントをご覧ください。後に説明する getStaticPathsと一緒に使う必要があります。

つまり、引数として渡ってくるcontextの中身はparamsというルートパラメーターしか存在しない
だから、リクエストの中にcookieは含まれないという個人的に衝撃の事実(解釈が違っていたらすみません)がわかった。
***
### 一方、getServerSidePropsは・・・

```
export async function getServerSideProps(context) {
  return {
    props: {} // ページコンポーネントにpropsとして渡されます。
  };
}
```

>getServerSidePropsという async 関数をエクスポートすると Next.js はリクエストごとに getServerSideProps から返されるデータでプリレンダリングします。

>contextパラメータは以下のキーを含むオブジェクトです。

>params: ページが動的ルートを使えば、paramsはルートパラメータを含みます。ページ名が [id].js であれば、paramsは { id: ... } のようになります。詳細は動的ルーティングのドキュメントをご覧ください。

>req: HTTPインカミングメッセージオブジェクト。

>res: HTTPレスポンスオブジェクト。

>query: クエリストリング。

>preview: previewはページがプレビューモードであれば true 、そうでなければ false になります。プレビューモードのドキュメントをご覧ください。

>previewData: プレビューデータは setPreviewData によって設定されます。プレビューモードのドキュメントをご覧ください。

contextにリクエストが送られるため,cookieの情報も送られていることがわかる。
そのため、SSRの記述の中でnookieを取得することが可能になる理由がここにあった。

個人的には名探偵コナンくんなみのひらめきを発揮したので満足。


***

## まとめ

SSGではCookieの情報が取得できない理由はgetStaticPropsが受け取る引数としてそもそもヘッダー情報が存在しないから。
Nextjsを用いたサーバーサイドでcookieを取得したければSSRの取得の仕方を取れば良い。

この記事を書いていて、いま気がついたが、SSRはリクエストを送るのだから方法はサーバー側でcookieを取得するのであればSSRしかない。


思わぬところで躓いたが、SSGとSSRの理解が深まったので良い経験となった。

まだまだ学習中のため、至らないや異なる情報を記載していた場合はご連絡をいただけると助かります。
ES Modulesではないwindows-1252モジュールのインストール

タイトルの通りです。
解決に時間がかかったので共有します。

nodeのwindows-1252モジュールを普通に

~~~
npm i windows-1252
~~~
でインストールするとES Modules版がインストールされるため、node実行時に
**Must use import to load ES Module / require() of ES modules is not supported**
というエラーが発生します。

requireでモジュールを読み込む場合はバージョンを指定してインストールします。

~~~
npm i windows-1252@0.1.0
~~~