OmniAICreator/Qiita-1.07M huggingface dataset:
【ESP32】Micropythonで始めるESP-NOW

# はじめに
皆さんはESP-NOWを使ったことはありますか？
ESP-NOWはESP32同士で直接通信することが可能な便利な通信プロトコルです．
ネットに転がっている記事を読んだところArduino IDEで実装している人がほとんどだったので，今回はMicroPythonを使った実装方法を紹介しようと思います．
# MicroPythonのESP-NOW
~~MicroPythonではESP-NOWは実はまだ開発段階であり，公式が配布しているファームウェアには残念ながら含まれていません！！！
しかしながら開発中のファームウェアがGitHubに上がっているのでそれを使います．~~
MicroPython1.21.0にてメインブランチに追加されたため，そちらを使ってください
（2024年1月23日追記）
> This module is still under development and its classes, functions, methods and constants are subject to change. This module is not yet included in the main branch of micropython. Until such a time that the code is accepted into the micropython main branch, the following resources are available: Source code | Pre-compiled images | Pull request (PR#6515)


https://github.com/glenn20/micropython-espnow-images
# 環境
バージョンは最近のものを選ぶと良いと思います．
なお今回使用するMicroPythonですが，何かこれといって特別なこともなくESP-NOW以外の機能は一切変わりありません．
- ESP32（DevKitC）：2台
- MicroPython 1.18（上記のGitHubのリポジトリに上がっているもの）
# 実装
MicroPythonの公式リファレンスに載っていたプログラムを実行してみました．
以下sender.pyが送信用プログラム，receiver.pyが受信用のプログラムです．
```sender.py
import network
import espnow

# A WLAN interface must be active to send()/recv()
w0 = network.WLAN(network.STA_IF)  # Or network.AP_IF
w0.active(True)
w0.disconnect()   # For ESP8266

e = espnow.ESPNow()
e.active(True)
peer = b'\xbb\xbb\xbb\xbb\xbb\xbb'   # MAC address of peer's wifi interface
e.add_peer(peer)

e.send("Starting...")       # Send to all peers
for i in range(100):
    e.send(peer, str(i)*20, True)
    e.send(b'end')
```
```receiver.py
import network
import espnow

# A WLAN interface must be active to send()/recv()
w0 = network.WLAN(network.STA_IF)
w0.active(True)
w0.disconnect()   # Because ESP8266 auto-connects to last Access Point

e = espnow.ESPNow()
e.active(True)
peer = b'\xaa\xaa\xaa\xaa\xaa\xaa'   # MAC address of peer's wifi interface
e.add_peer(peer)

while True:
    host, msg = e.recv()
    if msg:             # msg == None if timeout in recv()
        print(host, msg)
        if msg == b'end':
            break
```
### 実行結果
受信したESP32の出力の結果が以下になります．
最初の`b'\xfc\xf5\xc4=;,'`というのは送信したESP32のMACアドレスです．
そのあとのメッセージが受信したもので，バイナリ型で送られてきます．
このプログラムの場合には`b'end'`を受け取った時点で受信を終了しているので，最初に送った20個の0だけが受信されています．
![スクリーンショット 2022-05-11 173841.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/690612/0c73dd6b-518c-d251-fd6b-c92ea1afcd51.png)
# おわりに
簡単なメッセージのやりとりだけであればすぐに実装することができました．
開発途中とはいえほとんど完成に近いと思います．
mainブランチに実装されることを心待ちにしてます．
【社内勉強会用】Python入門

社内python勉強会

[2022/07/11 編集中]

Python初めての人が対象です。pathlibやxlwingsやでエクセルファイルの操作をすることが目標です。

---

## pythonのインストール
Windowsでは「Microsoft Store」からインストールするとPATHの設定もされるので簡単でした

---

## コマンドプロンプトに触れてみる

[Windows 10 のコマンドプロンプトとは？その起動方法と使用例を紹介](https://jp.ext.hp.com/techdevice/windows10sc/27/#:~:text=%E7%B4%B9%E4%BB%8B%E3%81%97%E3%81%BE%E3%81%99%E3%80%82-,1.%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%83%97%E3%83%AD%E3%83%B3%E3%83%97%E3%83%88%E3%81%A3%E3%81%A6%E3%81%9D%E3%82%82%E3%81%9D%E3%82%82%E4%BD%95%EF%BC%9F,-Windows%20%E3%81%AE%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89)

---

コマンドプロンプトはマウスを使わずコマンドと呼ばれる命令でPCを操作できる画面。

---

例えば
```
> mspaint
```
と入力するとペイントアプリが起動する。

---

```
> python
```

---

pythonが起動する

```
Python 3.9.13 (main, May 24 2022, 21:13:51) 
[Clang 13.1.6 (clang-1316.0.21.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
```
---

```
>>> exit()
```
と入力するとpythonが終了します


---

## パッケージ管理ツール Pipをつかう

---

pipはパッケージ管理に使う

[料理の際にピーラーやチョッパーがあると便利なように、Pythonにもプログラミングがはかどるライブラリ（ツール）が無料で多数公開されています。
そのライブラリをインストールしたり管理したりする際に使用する管理ソフトが「pip」です。
](https://camp.trainocate.co.jp/magazine/python-pip/#:~:text=%E6%96%99%E7%90%86%E3%81%AE%E9%9A%9B,%E7%B4%B9%E4%BB%8B%E3%81%97%E3%81%BE%E3%81%99%E3%80%82)

---

pipでxlwingsをインストールしてみよう

コマンドラインから

```
> pip install xlwings
```

---
最小規模のflaskウェブアプリ実行方法。

## はじめに

どうも。pythonで転職ポートフォリオ作成を目指す者です。
ここ3~4日flaskを学習しておりますが、前提知識が皆無な為大変苦戦を強いられております。
そしてようやく一歩先に進めた気がしたので記念がてらペンを取ることにしました。

### 本記事の目的
flaskの最小規模のアプリ作成し実装する。

他
- ライティングスキル向上の為
- アウトプットや理解が足りていない箇所を洗い出す為

### 環境
windows11
vs code

### 対象者
pythonの基礎をひとまず学習した方々。

## 学習

まず初めに今回のコードをシェア致します。


```python

from flask import Flask
app = Flask(__name__) 

@app.route('/')
def hello_world():
    return "Hello Python from Flask"

if __name__ == "__main__":
    app.run()

```

なんのこっちゃですよね。私も同じ気持ちです。解説は後ほど致します。

### 実装

丁寧に解説したつもりですが、ご不明点がございましたらコメント頂けると幸いです。

<details><summary>手順</summary><div>


①　適当な場所にフォルダを作成。(記事ではデスクトップ)

![2022-07-11_05h35_43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2719278/79944ea9-6eef-49d0-b754-83c491e393b3.png)


②　 VSコードを開いてワークスペースにドロップ。
VSコード内でこのフォルダを使用できるようにする。

![2022-07-11_05h38_18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2719278/cf72e395-5d67-5fe0-659b-14e68f9ac590.png)



③　そのフォルダ内で<font color="red">pyファイル(.py)</font>を作成する。

![2022-07-11_05h43_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2719278/d2b4169c-6c19-da39-7d25-536fd1ae6eec.png)

④　そのpyファイルにコードをコピペ｡

⑤　コマンドプロンプトを開く。(windows)

![2022-07-11_05h49_27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2719278/86691d9f-4ad5-1ca0-153b-74f5bb44f29e.png)


⑥　先ほど作成したpyファイルのプロパティから場所をコピー。

![2022-07-11_05h53_26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2719278/f6ba0f63-b41b-f20f-f1c0-015da70af001.png)

:::note warn
右クリック⇒パスのコピーでは動作しないので注意
:::

⑦　cmdで下記を入力
- cd コピーした内容    ⇒ cmd上で指定したパスに移動しております。
- python ファイル名    ⇒ cmd上で

![2022-07-12_11h38_31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2719278/f015b68f-4773-01e1-4de7-eecc080f4bbb.png)

cmd(コマンドプロンプト)をまとめた記事は[こちら](https://qiita.com/The_Boys/items/50d608f139e04f157d19)。是非参考にして頂ければ。

:::note warn

- "cd" を良く忘れるので注意。
- "python"のスペル名を確認。

:::

cd (change directory) : cd パス名

指定したパスに移動する事が出来る。

そして表示されたurlをブラウザで表示。

⑧　結果を確認

![2022-07-12_11h49_34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2719278/60e0fff7-ed8e-cd2b-c37f-36e7ad961554.png)



</div></details>

### コード解説



<details><summary>コードの解説</summary><div>

```python

from flask import Flask # flaskのインポート
app = Flask(__name__)   # flaskクラスのインスタンスを作成、前準備。


#表示させるメインの部分のコード。
@app.route('/')         # デコレータ。
def hello_world():
    return "Hello Python from Flask"


# ターミナルからpythonファイルを実行させるコード　appを実行。
if __name__ == "__main__":
    app.run()
```

- app = Flask(__name__)   :  クラスのインスタンス化。設計書から実際の物(オブジェクト)に昇華(実体化)する為のコード。

- @app.route('/')  :  デコレータ。その下の関数(def)に意味合いを持たせる。　import Flask　で使用できるようになります。　アプリのルーティング情報を保持する。('/')はページのURLを入力して一番最初に帰ってくる部分。その処理が下記の関数です。



</div></details>


## 終わりに。

分からないまま進めている部分も多いですが、ひとまずごく単純な仕組みは組み立てられました。
次回はもう少し凝ったアプリを作成できればと思います。
正直分からない事も多いです。｢いずれ理解する｣というスタンスでとにかくコツコツと。


### 参考サイト


- https://eng-entrance.com/cmd-usage#cd_chdir

- https://www.youtube.com/watch?v=87NUZl9VFJ4&lc=UgxSyezIDDyfXbcAKFZ4AaABAg.9dMX0tAOwoI9dMnRhaSknj

https://www.youtube.com/watch?v=87NUZl9VFJ4&t=1s
GitHub にスライドショーをつくらせた

キャンペーンとのことで参加してみようと
https://qiita.com/official-campaigns/engineer-festa/2022

初めての Github Actions です。
「何ができるか」から始めます。
よろしくお願いします。

# Github Actions でできること
検索して出てくるのは大別して下記2つかと
1. 外部サービスの API をコールして何かさせる
2. Github 内で何か処理をする

### 1. 外部 API 系
これはもう Github Actions がどうのというより、外部サービスがどうのの話と。
それと組み合わせて Github が便利になれば、それが求める結果ではありますが。

### 2. 内部処理系
Github Actions がどうのの話、
今回は Github Actions の学習のため、こちらで何かやってみようと思います。
どのようなフレームで考えればいいかですが、
ファイルの種類別に Action を考えるのが良いかと思いました。

|ファイルの種類  |考えられるAction  |バージョン管理 |
|---|---|---|
|ソースコード  |テスト、ビルド、デプロイなど  |有効 |
|markdown  |H1見出しをページ区切りとして pptx をビルド、<br>SlideShare にデプロイ |有効 |
|複数の画像  |スライドショー動画作成  |不要 |
|動画  |サムネイル画像抽出、コーデック変更 |不要 |
|雑多  |zip、tar 作成 |不要 |

後ほど反省することになりますが、
今回はこの中から複数の画像からスライドショー動画を作成させてみました。

# 画像からスライドショーを作らす
### 設定
学習用と割り切った狭い設定ですが、下記条件で動作する YAML を作成
・画像ファイル：[数字].jpg
・BGMファイル：bgm.mp3
・画像は5秒ごと、よってBGMはファイル数×5秒のものを用意する
・出力ファイル：out.mp4

```create-slideshow.yml
name: create-slideshow
on: [push]
jobs:
  check-bats-version:
    runs-on: ubuntu-latest
    steps:
      - name: checkout
        uses: actions/checkout@v3
      - name: install
        run: sudo apt-get install ffmpeg
      - name: create
        run: ffmpeg -y -r 0.2 -i %d.jpg -i bgm.mp3 -vcodec libx264 -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" -r 30 out.mp4
      - name: push
        run: |
          git config user.name github-actions
          git config user.email github-actions@github.com
          git add .
          git commit -m "generated"
          git push
```

### 結果
動画、できるにはできました。
ミュート解除で音も出るかと思います。
https://github.com/co-labo-hub/slideshow
（あれじゃん、と思ったあなた、子育てご苦労様です）

# 反省
やってる途中に気づいたのですが、
バージョン管理不要のものを Github にやらせるのは余計な手間がかかるだけだなと。
下記に再掲しますが、検討する表にバージョン管理列が必要だったなと。
よって、markdown から pptx は多少、意味があるのかもと。
（そもそもニーズがなさそうですが）

|ファイルの種類  |考えられるAction  |バージョン管理 |
|---|---|---|
|ソースコード  |テスト、ビルド、デプロイなど  |有効 |
|markdown  |H1見出しをページ区切りとして pptx をビルド、<br>SlideShare にデプロイ |有効 |
|複数の画像  |スライドショー動画作成  |不要 |
|動画  |サムネイル画像抽出、コーデック変更 |不要 |
|雑多  |zip、tar 作成 |不要 |

Github、もっと何かできそうだな、と感じさせられますが
具体的に何をやらせると便利なのか、意外と難しいなと思いました。
折を見てまた検討してみたいなと思います。

# 参考
参考にしたサイトです。ありがとうございます。

スライドショー作成方法
https://zenn.dev/tatsuyasusukida/articles/ffmpeg-image-audio

エラー"width not divisible by 2"の対処法
https://qiita.com/genchi-jin/items/90078b6ec751fdacbc9e

画像を拝借
https://www.pakutaso.com/category.html

BGMを拝借
https://dova-s.jp/bgm/play15804.html

スライドショーの構成
https://mitene.us/
Swift WKWebViewでWebViewのTableの行クリックからネイティブへデータを受け取る

Webのテーブルリストの行をクリックしてSwift側でその行の必要なデータをネイティブデータとして取得する例。
```
<script type="text/javascript">
//actvline変数初期値設定
let actvline="line1";

const OnButtonClick = function(ukeid) {
//下記記述でswift側にデータ渡し          
window.webkit.messageHandlers.callbackHandler.postMessage(String(ukeid));
}

//下記関数は
const dispxx= function(oj) {
document.all.item(actvline).style.backgroundColor="#ffffff";
document.all.item(oj.id).style.backgroundColor="#ee82ee";
actvline=oj.id;	
}
</script>


<thead>
    <TR>
      <th class="wid1">検体名称</th>
            <th class="wid3">動物種</th>
            <th class="wid1">受付区分</th>
            <th class="wid3">カルテNO</th>
            <th class="wid3">結果編集</th>
          </TR>    
</thead>
<tbody>
<tr id="line1" bgcolor="#ffffff"  onclick="dispxx(this)">
<td align="left" onclick="OnButtonClick(2531)"><a href="msginp_test_app.php?petid=76595">田中/コロ</a></td>
<td align="center" onclick="OnButtonClick(2531)">犬</td>
<td align="center" onclick="OnButtonClick(2531)">診察受付</td>
<td align="center" onclick="OnButtonClick(2531)">12345X</td>
<td align="center" onclick="OnButtonClick(2531)"><a href="ukeupd2_app.php?calmsgid=2531">編集</a></td>
</tr>
<tr id="line2" bgcolor="#ffffff"  onclick="dispxx(this)">
<td align="left" onclick="OnButtonClick(2530)"><a href="msginp_test_app.php?petid=67861">コバヤシ/ロン</a></td>
<td align="center" onclick="OnButtonClick(2530)">犬</td>
<td align="center" onclick="OnButtonClick(2530)">診察受付</td>
<td align="center" onclick="OnButtonClick(2530)">123</td>
<td align="center" onclick="OnButtonClick(2530)"><a href="ukeupd2_app.php?calmsgid=2530">編集</a></td>
</tr></tbody></table>
<BR>
</section>
```
【React】React Queryでクエリの発行を抑制する考慮

## 概要
React Queryは、APIからデータを取得する際に使用するライブラリで、ローディングやエラー制御やキャッシュなどの機能があります。概要については[初めてReact Queryを使う人のため設定方法と動作の理解](https://reffect.co.jp/react/react-use-query)の記事が参考になると思います。
使用にあたり設定自体は難しくないのですが、あまり考えずに使うとComponentがマウントされる時やブラウザのタブを切り替える時などにクエリが発行されてしまうので、意図しない限りはできるだけ発行されるのを抑えたいです。その際の設定をメモ書きします。

## 対応
React Queryには多数のオプションが設定できるのですが、[Fetch a query only once until page refresh using React Query](https://medium.com/in-the-weeds/fetch-a-query-only-once-until-page-refresh-using-react-query-a333d00b86ff)の記事に、クエリを一度しか発行させないためのオプション設定の例が紹介されています。個人的にはデフォルトのオプションはクエリの発行を抑制するような設定を入れて、[useQuery](https://react-query-v2.tanstack.com/reference/useQuery)で必要に応じて個別に設定する形が良いかなとは感じました。

## 設定サンプル
少し試してみた感触だと`refetchOnWindowFocus`と`refetchOnmount`の設定を`false`にしておけば、そこまで無駄なクエリが発生することは無いかなと思います。
念の為、設定のサンプルを以下に記します。（ReactNativeがベースですがReactでもほぼ同様と思います）

```react:App.js
import { QueryClient, QueryClientProvider } from "react-query";
import { NavigationContainer } from "@react-navigation/native";
import { createStackNavigator } from "@react-navigation/stack";
import TopComponent from "./components/TopComponent";
import { SampleSearchProvider } from "./context/SampleSearchProvider";

export default function App() {
  const Stack = createStackNavigator();
  const queryClient = new QueryClient({
    defaultOptions: {
      queries: {
        refetchOnWindowFocus: false,
        refetchOnmount: false,
      },
    },
  });

  return (
    <SampleSearchProvider>
      <QueryClientProvider client={queryClient}>
        <NavigationContainer>
          <Stack.Navigator>
            <Stack.Screen
              name="sample screen"
              component={TopComponent}
              options={{
                headerTitle: "サンプル",
                headerTitleAlign: "center",
              }}
            />
          </Stack.Navigator>
        </NavigationContainer>
      </QueryClientProvider>
    </SampleSearchProvider>
  );
}
```
2022/7/11主にITとかセキュリティの記事

読売新聞のサイトに不正アクセス　個人情報流出の可能性(7/8)
https://mainichi.jp/articles/20220708/k00/00m/040/351000c

有休記録削除目的で637回不正アクセスか　町職員を逮捕へ(7/9)
https://www.zaikei.co.jp/article/20220709/680359.html

悪意のあるnpmパッケージを用いたIconBurstサプライチェーン攻撃に注意(7/9)
https://news.mynavi.jp/techplus/article/20220709-2392604/

最強ハッカー・ロックビット「病院狙う」、闇サイトで予告…日本も警戒強める(7/8)
https://www.yomiuri.co.jp/national/20220708-OYT1T50231/

TikTokアカウント乗っ取り被害、防ぐための対策は--VTuberなどの被害が多発(7/9)
https://japan.cnet.com/article/35190057/

オフィス改革とクラウド活用で、職員同士の連携を強め生産性向上へ
https://www.jt-tsushin.jp/interview/jt40_cybozu/

日本郵便、不審なメールに注意を呼びかけ(7/9)
https://k-tai.watch.impress.co.jp/docs/news/1423580.html

ネットの新暗号にIBM方式が選定、NTT方式の世界標準化は夢のままに終わる!(7/9)
https://www.zaikei.co.jp/article/20220709/680334.html

中小企業のIT投資、必要性は感じているが課題の対策に手が回らない状況／デル調べ(7/9)
https://dxmagazine.jp/news/research/Ub2GN

暗証番号なぜ4桁？　英開発の現金支払機、6桁導入せず くらしの数字考(7/9)
https://www.nikkei.com/article/DGXZQOUD151ZM0V10C22A6000000/

「ポスト量子暗号イニシアチブ」発足、量子コンピュータによる脅威に対抗(7/8)
https://news.mynavi.jp/techplus/article/20220708-2392553/

最近よく見る「Cookie使用同意バナー」、実は無意味？　専門家が指摘するちぐはぐ対応(7/8)
https://news.infoseek.co.jp/article/itmedia_nlab_20220419179/?tpgnr=it

ブラジル、仮想通貨マネロンのゴールド採掘を摘発＝報道(7/9)
https://coinpost.jp/?p=366359
気象学における流線関数・速度ポテンシャルのCDOでの計算方法

# はじめに

以前の記事では、Python の [windspharm](https://github.com/ajdawson/windspharm) パッケージを用いた流線関数・速度ポテンシャルの計算方法を紹介した（なお、流線関数や速度ポテンシャル自体についての解説はこの記事では行わないので、リンク先の記事を参照してほしい）。

https://qiita.com/wm-ytakano/items/92570f11a0e39eac2a54

windspharm は Intel Mac では `conda` コマンドでインストールすることができるが、Apple Silicon向けにはインストールできない（最終更新が2018年とメンテナンスがなされていないようである）。
そこで[CDO](https://code.mpimet.mpg.de/projects/cdo)を用いた計算方法を調べたのでメモしておく。

なお、以下の記事を大きく参考にした。

https://code.mpimet.mpg.de/boards/1/topics/11291

実行環境は以下のとおりである
- Macbook Air (M1, 2020)
- macOS Monterey 12.4
- CDO version 2.0.5 (Homebrewでインストール)

# 計算方法
手元に東西風(ps_u.nc)と南北風(ps_v.nc)が含まれているファイルがあるとする。ファイルに1時刻、複数気圧面が含まれているとする。水平1度格子で、出力の流線関数と速度ポテンシャルも同じ格子で得たいとする。

サンプルコードを以下に示す。CDOのパイプラインの機能を使っており一つのコマンドが長くなるので適宜改行している。また、後で参照するときにわかりやすいように各行にコメントで番号を振っている。番号はパイプラインで処理される順番（右から）に対応している。

```bash
cdo -L \ # (0)
    sp2gp \ # (8)
    -dv2ps \ # (7)
    -uv2dv \ # (6)
    -remapbil,F90 \ # (5)
    -chname,ps_u,u,ps_v,v \ # (4)
    -setmisstoc,0 \ # (3)
    -sellevel,850 \ # (2)
    -merge ps_u.nc ps_v.nc \ # (1)
    tmp.nc # (9)
cdo -L remapbil,outgrid tmp.nc ps_sfvp200.nc # (10)
```


(0) `-L`は Lock I/O (sequential access) の意味。マルチスレッド環境で非スレッドセーフなNetCDF4/HDF5ライブラリを使うとエラーが起きうるとの警告が出たのでつけている。
```
cdo    sp2gp (Warning): Using a non-thread-safe NetCDF4/HDF5 library in a multi-threaded environment may lead to erroneous results!
cdo    sp2gp (Warning): Use a thread-safe NetCDF4/HDF5 library or the CDO option -L to avoid such errors.
```

(1) 東西風と南北風のファイルを一つに結合する。気圧面の切り出しをしてから結合したほうが効率的だが、その場合はパイプラインで繋ぐことができないため、東西風と南北風の一時ファイルを作成することになる。

(2) 複数気圧面を一度に処理できないため、一つの気圧面データを切り出す。ファイル内に複数時刻が含まれている場合は、`-seltimestep,1`のように特定時刻を切り出す必要があるかもしれない(未確認)。

(3) `uv2dv`をする際に、欠損値があると計算ができないため、欠損値を埋める。気圧面が地表面よりも下にある場合に欠損が生じるため、埋める値を0とすることで実用上問題ないだろう。

(4) `uv2dv`をする際に、変数名がu,vにする必要があるため、変数名の変更を行う。

(5) `uv2dv`をする際に、入力データはガウス格子にする必要があるため、等緯度経度格子からバイリニア補間で格子変換する。F90のFはFull regular Gaussian gridの意味。90は極から赤道までの格子数で、この場合は東西360x南北180格子となる。

(6) ガウス格子上の東西風と南北風から、発散と渦度の球面調和係数を計算する。

(7) 発散と渦度の球面調和係数から、流線関数と速度ポテンシャルの球面調和係数を計算する。

(8) 流線関数と速度ポテンシャルの球面調和係数から、ガウス格子上での流線関数と速度ポテンシャルの値を計算する。

(9) 中間ファイルに出力する。後続のガウス格子から等緯度傾度格子へと変換する部分もパイプラインにできるとよかったのだが、以下のようなエラーが出てしまう。

```
cdo    remapbil (Abort): Unsupported spectral coordinates (Variable: )!
```

(10) ガウス格子から等緯度傾度格子へと変換する。outgridは出力格子で、`remapbil,r360x180`とすれば、経度0度、南緯89.5度開始の1度格子となる。東経0.5度開始にしたい場合は、`outgrid`という名前のファイルに以下のように記述すればよい。

```outgrid
gridtype = latlon
xsize = 360
ysize = 180
xunits = 'degree'
yunits = 'degree'
xfirst = 0.5
xinc = 1.0
yfirst = -89.5
yinc = 1.0
```
Oracle Database Docker Image

Oracle DatabaseのDocker Imageは公開されていないらしく、自前でビルドする必要がある。  
そのための手順をメモ。（2022.07時点）

* 環境
    * MacBook Pro (2018)
        * MacOX monterey 12.4
    * Docker Desktop 4.10.1

2023.03.20  
sqlplus起動のコマンド間違えを修正。

## Oracle Docker-Imageリポジトリの入手（git clone）
Github [oracle/docker-images](https://github.com/oracle/docker-images)
```
$ cd ~/
$ git clone https://github.com/oracle/docker-images.git
```
## Oracle Database 21c Express Editionの入手

[Oracle Database Express Edition (XE) Download](https://www.oracle.com/database/technologies/xe-downloads.html)から`Oracle Database 21c Express Edition for Linux x64 ( OL8 )`をダウンロード。（OL7でも可）

## Docker Imageビルド

cloneしてきたリポジトリの以下のパスまで移動。
```
cd ~/docker-images/OracleDatabase/SingleInstance/dockerfiles
```
ダウンロードしたデータベースのバージョンと一致するディレクトリにコピーする。
```
$ mv ~/oracle-database-xe-21c-1.0-1.ol8.x86_64.rpm ./21.3.0/
```
シェルを実行。
```
$ ./buildContainerImage.sh -v 21.3.0 -x -i
```
しばらく待つと完成。
```
$ docker image ls
REPOSITORY                                TAG             IMAGE ID       CREATED         SIZE
oracle/database                           21.3.0-xe       9b207125183b   3 days ago      6.53GB
```

### おまけ：イメージの保存と読み込み
docker saveコマンドでローカル保存。
```
$ docker save oracle/database:21.3.0-xe | gzip > oracle-database-21.3.0-xe.tar.gz
```
docker loadコマンドで読み込み。
```
$ docker load < oracle-database-21.3.0-xe.tar.gz
```

## （コンテナで）Oracle　Database起動

GitのREADMEに書かれている「[Running Oracle Database 21c/18c Express Edition in a container](https://github.com/oracle/docker-images/blob/main/OracleDatabase/SingleInstance/README.md#running-oracle-database-21c18c-express-edition-in-a-container)」を参考。

```yaml
version: '3.8'
services:
  oraclexe:
    image: oracle/database:21.3.0-xe
    ports:
      - 1521:1521
    environment:
      - ORACLE_PWD=ora
      - ORACLE_CHARACTERSET=AL32UTF8
    volumes:
      - oradata:/opt/oracle/oradata
#     - ./oradata:/opt/oracle/oradata           # ホストにマウントする場合
#     - ./startup:/opt/oracle/scripts/startup   # 起動時実行スクリプトを配置
volumes:
  oradata:
```
インスタンスの起動に時間がかかる・・・。

### sqlplus

```sh
$ docker-compose exec oraclexe sqlplus sys/ora@//localhost:1521/XE as sysdba

SQL*Plus: Release 21.0.0.0.0 - Production on Sun Jul 10 16:07:30 2022
Version 21.3.0.0.0

Copyright (c) 1982, 2021, Oracle.  All rights reserved.


Connected to:
Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0

SQL> 
```
2022参院選候補者アンケートをスクレイピング

```python
import requests
import pandas as pd

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"
}


def get_json(url):

    r = requests.get(url, headers=headers)
    r.raise_for_status()

    return r.json()


def get_questions():

    url = (
        "https://www.nhk.or.jp/senkyo-data/database/sangiin/2022/survey/questions.json"
    )

    data = get_json(url)

    dfs = []

    for _, v in data.items():

        tmp = pd.json_normalize(v)
        dfs.append(tmp)

    df = pd.concat(dfs).set_index("id")

    df.drop(["type", "selects"], axis=1, inplace=True)

    return df


df_questions = get_questions()
df_questions


# 選挙区
def get_senkyoku():

    df_senkyoku = pd.read_csv(
        "https://www.nhk.or.jp/senkyo-data/database/sangiin/2022/00/search/sindex.csv",
        names=[
            "typeID",
            "senkyoID",
            "senkyo_name",
            "senkyokuID",
            "senkyoku_name",
            "todoufukenID",
        ],
        storage_options={"User-Agent": "Mozilla/5.0"},
        header=None,
    )

    dfs = []

    for _, row in df_senkyoku.iterrows():

        url = f'https://www.nhk.or.jp/senkyo-data/database/sangiin/2022/survey/{row["senkyokuID"]}.json'

        data = get_json(url)

        tmp = pd.json_normalize(
            data,
            meta=[
                "candidateID",
                "lastname",
                "firstname",
                "sex",
                "touha",
                "touha_name",
                "age",
                "senkyokuID",
                "senkyoku_name",
                "todoufukenID",
                "answerDatetime",
            ],
            record_path="qa",
        )

        dfs.append(tmp)

    df = pd.concat(dfs).reset_index(drop=True)

    return df


# 比例
def get_hirei():

    url = "https://www.nhk.or.jp/senkyo-data/database/sangiin/2022/survey/hirei.json"

    data = get_json(url)

    df = pd.json_normalize(
        data,
        meta=[
            "candidateID",
            "lastname",
            "firstname",
            "sex",
            "touha",
            "touha_name",
            "age",
            "senkyokuID",
            "senkyoku_name",
            "todoufukenID",
            "answerDatetime",
        ],
        record_path="qa",
    )

    return df


# 選挙区取得
df_senkyoku = get_senkyoku()
df_senkyoku

# 比例取得
df_hirei = get_hirei()
df_hirei

# 選挙区と比例結合
df_sangiin = pd.concat([df_senkyoku, df_hirei])

# アンケート結合
df0 = df_sangiin.join(df_questions, on="id")

df0["answers"] = df0["answers"].str[0]

df0

df1 = df0.pivot(
    index=["todoufukenID", "candidateID", "lastname", "firstname"],
    columns=["id", "question"],
    values="answers",
)

df1.to_csv("result.csv")
```
Snyk Vulnerability Database を使って脆弱性情報を検索する


## はじめに

この記事は、「Snyk を使って開発者セキュリティに関する記事を投稿しよう！」のイベント記事です

https://qiita.com/official-events/786b978e4a1a28fad312

脆弱性の情報を調べると検索によく引っかかる Snyk Vulnerability Database について記載します

## Snyk Vulnerability Database について

https://security.snyk.io/

Synk が提供する脆弱性データベース (と理解しています)
ライブラリやパッケージを設定しておくと、脆弱性の情報を確認することができますが、Vulnerability Database 単体でも利用することができます

![security.snyk.io_(Nest Hub).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55950/259aa7d7-bf17-2104-532c-0dda4b3a21cf.png)

同様のサービスとして、 "GitHub Advisory Database" が存在します

https://github.com/advisories

## 脆弱性に関する情報を調べる

Snyk Vulnerability Database を使って脆弱性に関する情報を調べてみます
今回調べるのは、Qiita で開発している [qiita-markdown](https://github.com/increments/qiita-markdown) で過去生じた Cross-site Scripting (XSS) / CVE-2021-28796 について調べてみます

https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-28796

### Snyk Vulnerability Database にアクセスする

https://security.snyk.io/ にアクセスし、調査したい `CVE-2021-28796` を入力し検索します

https://security.snyk.io/vuln/?search=CVE-2021-28796

![security.snyk.io_(Nest Hub) (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55950/d382f937-9801-1355-2dab-fa4ec244476e.png)

詳細ページへと進むと、 スコアや、脆弱性の情報および修正されているバージョンなどが記載されています
また、 XSS についての説明もあり普段から脆弱性の情報を収集している方は不要かもしれませんが、これから脆弱性の対応を始める人には参照しながら対応を行うと学びも多いのではないかと感じます

https://security.snyk.io/vuln/SNYK-RUBY-QIITAMARKDOWN-1087446

![security.snyk.io_vuln_SNYK-RUBY-QIITAMARKDOWN-1087446(Nest Hub).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55950/6bf0ca8f-06c5-8d85-9ae4-5ab871c84ee9.png)

### (参考) GitHub Advisory Database で脆弱性の情報をしらべる

https://github.com/advisories

GitHub Advisory Database Top にアクセスし `CVE-2021-28796` を入力します

https://github.com/advisories?query=CVE-2021-28796

![github.com_advisories_query=CVE-2021-28796(Nest Hub).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55950/5ae104ee-dca5-2432-ab84-2a84b8fe2091.png)

検索に引っかかった脆弱性の情報は詳細ページに進むと確認することができます

https://github.com/advisories/GHSA-f2c9-5jqw-3xh3

![github.com_advisories_query=CVE-2021-28796(Nest Hub) (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55950/52fe2936-d0b2-33d4-221a-b26caf31ef95.png)

Synk と違い 対象のバージョンと関連リンクが簡潔に記載されています
Snyk Vulnerability Database と GitHub Advisory Database どちらを利用するかは好みによって別れそうだという感想です

## 最後に

実は、 Snyk のサービスは脆弱性の情報を調べたときによく出てくるな程度しか知りませんでした。
今回記載した、「Snyk Vulnerability Database」は知らずに利用していたので今回記事にしました
脆弱性情報の調査や対応は難しそう、大変そうという声を聞いたことがあったので、進め方など知っていれば大変ではないので調査など小さく初めて見るとよいと思います

## Reference

https://security.snyk.io/vuln/SNYK-RUBY-QIITAMARKDOWN-1087446

https://www.cve.org/CVERecord?id=CVE-2021-28796
Rails エラー「Runtime Error Your version of SQLite (3.7.17) is too old. Active Record supports SQLite >= 3.8」の対処法

※バージョン情報が誤っていたので訂正しました…大変失礼いたしました。。。。

# 開発環境
Rails 6.1.4
ruby 2.6.3

# 目次
- エラー全文
- 対処法

## エラー全文
アプリケーション作成後、`rails s`でアプリケーションを起動。
サイトアクセス時、に下記エラーが発生。

![rails1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730324/74534efa-3a59-2d31-5c3c-3c47a9ce501e.png)

AmazonLinux2にはsqlite3のバージョン3.7がデフォルトでインストールされており、
これがyumで利用しているらしく、削除することはできません。
しかし、Rails6を動かすにはsqlite3のバージョン3.8以上が必要なので、
バージョンが古い！とエラーが出ている、、、というわけです。


## 対処法

既存のSQLiteはそのままで、3.8以上のSQLiteを別途インストールします。
sqliteの最新バージョンは[こちら](https://www.sqlite.org/download.html)で確認可能です。

```ruby:ターミナル
# アプリ用のユーザのホームディレクトリで作業（私は）
$ cd /home/appuser 
# 3.39.0をダウンロード
$ wget https://www.sqlite.org/2021/sqlite-autoconf-3360000.tar.gz
$ tar xzvf sqlite-autoconf-3360000.tar.gz
$ cd sqlite-autoconf-3360000/
# もとから入っているsqliteと競合しないように /opt/sqlite/sqlite3にインストールする
$ ./configure --prefix=/opt/sqlite/sqlite3
$ make
$ sudo make install
# バージョン確認
$ /opt/sqlite/sqlite3/bin/sqlite3 --version
3.36.0 2022-07-01 14:12:00 a26b6597e3ae272231b96f9982c3bcc17ddec2f2b6eb4df06a224b91089fed5b
```    

アプリで使用するSQLiteとして、今回インストールしたSQLiteをgemで指定する。

```ruby:ターミナル
# アプリ用のディレクトリに移動
$ cd /var/www/rails/web_app 
# gemで新しいSQLiteを指定
$ gem install sqlite3 -- --with-sqlite3-include=/opt/sqlite/sqlite3/include \
   --with-sqlite3-lib=/opt/sqlite/sqlite3/lib
# 指定が正しくできているか確認
$ irb
irb(main):001:0> require 'sqlite3'
=> true
irb(main):002:0> SQLite3::SQLITE_VERSION
=> "3.36.0"  # 成功
irb(main):003:0> exit
``` 


新しいSQLiteにパスを通す必要があるので以下作業実施。


```ruby:ターミナル
$ echo 'export LD_LIBRARY_PATH="/opt/sqlite/sqlite3/lib"' >> .bash_profile
$ source .bash_profile
``` 

これで再度アプリを起動すると、、、無事にエラー解消できました！

![6a459a54e624a5a2d3aa3de1866cc763.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730324/905e3fe1-c00a-23c8-cf0c-d093981d5aee.png)


お疲れ様でした！
あくまで備忘録なので足りない説明等多々あるかと思います。
行き詰まった際の助けになれば幸いです。
Vue.jsの書き方忘却録

# 背景
Vue.jsの基本的な書き方を忘却録として残す

# 開発環境

PC:macOS Monterey(Intel Macbook Pro 2020)
エディター：Visual Studio Code
Vue.js： 2系

# コード

```javascript:app.js
// Vueインスタンスの生成
var vm = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue！'
  }
})
```

```html:index.html
<div id="app">
  {{ message }}
</div>
```

```:出力
Hello Vue!
```

## 基本構文
new Vue()でVueインスタンスを生成する
インスタンスを生成することで、Vueアプリケーションが有効になる
VueはMVVMの影響を受けているので、Vueインスタンスの変数名にはvmがよく使われる

上記のapp.jsでインスタンスを生成する時の引数（オプションオブジェクト）は以下である

- el
Vueの有効範囲を指定する
elに書かれた要素配下でVue.jsの機能が有効になる
app.jsは「#app」と記述しているので、idがappのHTML要素、すなわち「```<div id=”app”></div>```」の中でVue.jsの機能が有効になる

- data
Vueの有効範囲内で利用できる変数を指定する
app.jsではmessageが変数、Hello Vue!が値になる
VUeインスタンスが作成されると、自身のdataオブジェクトの全てのプロパティをリアクティブシステムに追加される。値が変更すると、すぐに更新される。

リアクティブシステムについては[こちら](https://vuejs.org/guide/extras/reactivity-in-depth.html)を参照

リアクティブに変更しないようにするためには、Object.freeze()を使用する

```app.js
// 定義したdataオブジェクト
var data = { a: 1 }

// 追加することで、変更を防ぐ
Object.freeze(data)

var vm = new Vue({
  el: '#app',
  data: data
})
```

```index.html
<div id="app">
  <p>{{ a }}</p>
  <input v-model="a">
</div>
```

inputに値を入れても, {{ a }}は変化しない


## その他の設定オブジェクト
- methods
関数

- computed


- watch
あるデータが変更されたタイミングで何か処理をしたいときに使用する

オプション一覧は[こちら](https://vuejs.org/api/)を参照

## Vueのインスタンスプロパティとインスタンスメソッド

ユーザーが定義したプロパティと区別するため、$が付いている

```app.js
var data = { a: 1 }
var vm = new Vue({
  el: '#example',
  data: data
})

// インスタンスプロパティ($data, $el)
// $data： Vue インスタンスが監視しているデータオブジェクト
vm.$data === data // => true
// $el: Vue インスタンスが管理している ルートな DOM 要素
vm.$el === document.getElementById('example') // => true

// インスタンスメソッド
vm.$watch('a', function (newValue, oldValue) {
   // このコールバックは `vm.a` の値が変わる時に呼ばれる
})
```

インスタンスプロパティ、メソッドの一覧は[こちら](https://v2.vuejs.org/v2/api/#Instance-Properties)

## Vueのライフサイクル

続きはここから書く

<img src="https://v2.vuejs.org/images/lifecycle.png">

https://v2.vuejs.org/v2/guide/instance.html#Lifecycle-Diagram

# 参考記事

[Vue.js公式ドキュメント](https://vuejs.org/guide/introduction.html)
データソース追加をPower Query M式言語ソースから行う

# オープンデータはたまに変わる

更新されるオープンデータの取得を続けていると、たまにフォーマットが変わったり、取得先が変わったりなどすることに悩まされます。
修正に手間がかかりますが、そのための操作が「使い方の復習」になるので、変更が発生した場合はこれまで同様の振る舞いに戻すように直しています。
今回、そうした「使い方の復習」が発生したので、メモをしておくことにしました。
対象のオープンデータは「東京都 新型コロナウイルス陽性患者発表詳細」です。

https://catalog.data.metro.tokyo.lg.jp/dataset/t000010d0000000068

2022年の春頃から、以下のようにデータが分かれていました。

* 東京都_新型コロナウイルス陽性患者発表詳細（年別分割版_2020年）CSV
* 東京都_新型コロナウイルス陽性患者発表詳細（年別分割版_2021年）CSV
* 東京都_新型コロナウイルス陽性患者発表詳細（年別分割版_2022年その１）CSV
* 東京都_新型コロナウイルス陽性患者発表詳細（年別分割版_2022年その２）CSV
　（その1は2022年1月1日から4月20日まで）

「Power BI Desktop」を使っています。

# 期間別は「クエリの追加」

こうした期間別に分かれている場合、（列項目が同じなら）「クエリの追加」を使います。
「Power Query エディター」ホームタブ右側の「クエリの追加」です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/6e6972db-6c93-d5cc-ee4f-e94316a59800.png)

# データソース設置変更

取得先のURLが変わった場合は、「ホーム」→「データの変更」→「データソース設定」→「ソースの変更」で変更できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/b68b036f-476e-e846-ea03-f34fa529d4f2.png)


# 「ソース」のデータソース書き換え

今回CSVが複数に分かれたので、上述4種類のCSVデータをインポートする必要があります。
その際、通常の「データを取得」→「Web」を使わず、「Power Query エディター」のソースを利用しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/bcc85bbd-ab27-ac34-147e-4fd73d2a7b5b.png)

使用したのは以下です。
まず、通常通りインポートして生成されたクエリーを「複製」します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/b20c6452-099e-1224-e0a5-64b98ecf1ac3.png)

右パネル「ソース」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/6736b6ff-ee28-db46-38f7-35d457626e88.png)

URL部分を書き換えます。

~~~
= Csv.Document(
Web.Contents("https://stopcovid19.metro.tokyo.lg.jp/data/130001_tokyo_covid19_patients_2022.csv"),
[Delimiter=",", Encoding=65001, QuoteStyle=QuoteStyle.None])
~~~

上記の場合、「2022年」のCSVをインポートしているので、「130001_tokyo_covid19_patients_2021.csv"」と書き換えることで、「2021年」のCSVを取り込みます。

~~~
= Csv.Document(
Web.Contents("https://stopcovid19.metro.tokyo.lg.jp/data/130001_tokyo_covid19_patients_2021.csv"),
[Delimiter=",", Encoding=65001, QuoteStyle=QuoteStyle.None])
~~~

先述の「クエリの追加」で「2021年」と「2021年」のデータを結合します。
「2020年」のCSVも同様にクエリを複製し、「ソース」を書き換え、「クエリの追加」を実行しました。

# 2020年〜最新値まで集計

2020年1月24日以降の集計が可能になりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/d56feaf1-602d-07e1-657b-05c871589a11.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/0e606229-d383-24fe-cd17-c6a526efe15d.png)

**了**
USBシリアルモジュールを Ubuntu22.04 で使用する

# 問題

CP2102 USBシリアルモジュールを接続して、さあつかおうとしたところで

```

FATAL: cannot open /dev/ttyUSB0: No such file or directory
```

と出てすぐに使えなくなってしまう。

```

$ sudo dmesg -w

```
で見てみると、


```
[23429.336746] cp210x 3-2.3.4:1.0: cp210x converter detected
[23429.343098] usb 3-2.3.4: cp210x converter now attached to ttyUSB0
[23439.108740] usb 3-2.3.4: usbfs: interface 0 claimed by cp210x while 'brltty' sets config #1
[23439.112118] cp210x ttyUSB0: cp210x converter now disconnected from ttyUSB0
[23439.112156] cp210x 3-2.3.4:1.0: device disconnected

```
となっていて、10秒かそこいらで切断されている。

brltty って何だ?

調べてみると、点字ディスプレイのためのドライバらしい。
以下を見てみると、点字ディスプレイデバイスが汎用USBデバイス識別子を使っていることが問題なのかな?
https://bugs.launchpad.net/ubuntu/+source/brltty/+bug/1958224

点字ディスプレイを使うことがなければ brltty を削除すればOK.

```
$ sudo apt remove brltty
```

# dialout ユーザーになる

特に設定していないと /dev/ttyUSB0 などは一般ユーザで使えないので、以下のようにして再起動する。

```

$ sudo adduser $USER dialout
```
値オブジェクトでセキュアなアプリケーションを作ろう


セキュア・バイ・デザインを読み、DDDの値オブジェクト(value_object)を利用することで自然とセキュアなアプリケーションを作れることを学んだのでまとめます。
文字通りセキュリティに関する書籍なのですが、セキュリティエンジニアのような専門的な知識がなくとも、設計によって自然とセキュアなアプリケーションとなるように努めようという内容になります。

# セキュリティを心配事として捉える
例えば以下のようなアプリケーションのユーザーストーリーがあるとします。

`写真格納サービスのユーザーとして、私はログイン画面が欲しいです。そうすることで私は自身がアップロードした写真の一覧画面にアクセスできるようになります。`

この機能を満たすようにログイン画面を実装し、一覧画面から写真のダウンロードができるようになったとして、それだけで機能として大丈夫でしょうか？
もし、別のユーザーがそれらの写真をダウンロードするリンクを何らかの方法で入手することができれば、そのリンクを直接呼び出すことで写真がダウンロードできてしまいます。

上記は少し極端な例かもしれませんが、セキュリティを`機能`として見るのではなく、`心配事`として見ることでユーザーストーリーを改善することができます。

`写真格納サービスのユーザーとして、私は自身がアップロードした写真へのすべてのアクセスを認証によって保護したいです。それによって私がアップロードした写真の機密性が保護されます。`

写真の機密性を担保したいという心配事に関心を移したため、より抽象的かつユーザーの意図することを正確に表現できるようになりました。
たしかに、チケットを作成する際に機能要件しか記載していなかったため、直リンクの防止、不正な値のバリデーションといったセキュリティが満たされていないことは身に覚えがあります。

# ドメイン・プリミティブによるセキュリティ担保
読んでいる中で、一番費用対効果が大きく導入しやすいセキュリティ改善策として印象に残ったのがドメイン・プリミティブです。
DDDで言う値オブジェクトを拡張した概念であり、生成されるときに不変条件を確認し、存在自体が有効であることを保証されたものだそうです。
個人的には、値オブジェクトはそれ自体で正当性を保証できなければ意味がないと思うので、ほぼ同一の概念として読み進めました。(この記事でも同一のものとして扱います)

以下のようなUserクラスがあったとします。

```ruby:user.rb
class User

  attr_reader :id, :name

  def initialize id, name
    @id = id
    @name = name
  end
  
end
```

このUserクラスをインスタンス化する際に渡される`name`に
`<script>alert('hoge!!!')</script>`
のようなスクリプトが入力されるとどうなるでしょうか？
このようないたずら程度のスクリプトならどうにかなるかもしれませんが、Cookieの値を読み取って送信するような悪質なスクリプトだと深刻な問題に発展するかもしれません。

では以下のようにXSS対策を組み込んでみましょう。

```ruby:user.rb
class User

  attr_reader :id, :name

  def initialize id, name
    @id = id
    @name = validate_for_xss(name)
  end
  
end
```
たしかにこれでXSSへの対策は行えますが、以下のような問題が発生します。
* ビジネスロジックとセキュリティ、2つのことを常に考えなくてはならない
* すべての開発者がセキュリティ専門家と同レベルの知識を求められることになる
* 今後起こりうるすべての脆弱性を把握していることが前提となる
いずれも開発効率を悪化させますし、現実的な対策が困難です。

こういった問題に対しては、セキュリティよりも設計を中心に考え、ドメイン・プリミティブを利用することが有効です。
ドメイン分析を行い、ユーザー名について以下のような結論が出たとします。
* 半角英数字のみ使用可
* 長さは4〜40文字

Userクラスをドメイン・プリミティブを用いて再設計すると以下のようになります。

```ruby:user.rb
class User

  attr_reader :id, :name

  def initialize id, name
    @id = id
    # stringではなくドメイン・プリミティブであるUserNameクラスを利用する
    @name = UserName.new(name)
  end
  
end

class UserName

  attr_reader :value

  def initialize value
    # 半角英数字のみ含まれており、長さが4~40文字であることを確認する(実装は省略)
    validate(value)
    
    @value = value
  end
  
end
```
このように設計することで、仮にユーザー名に
`<script>alert('hoge!!!')</script>`
と入力されても有効な値でないためUserNameクラスが自動的にユーザー登録を防いでくれます。
注目すべきは、`セキュリティについて考えるまでもなく、自然とセキュアなアプリケーションとなっている`ことです。
先に挙げた問題点についても以下のように解決できています。
* ビジネスロジックの実装、セキュリティの保証を同時に行える
* セキュリティの専門家でなくても安全なコードを書けるようになる
* 気がつかないうちにセキュリティに関する多くのバグを取り除けるようになる

# まとめ
設計によってセキュリティを改善する手段がまとめられた良書でした。
セキュリティに関する専門知識がなくても読むことができ、DDDについての知識を拡充することができます。
なぜDDDなのか？というメリットも語られており、チームメンバーにそのメリットを紹介する際にも使えると思います。
値オブジェクトによるセキュリティ担保は比較的導入しやすい設計改善策なのでプロジェクトで実施していきます。
【Laravel】PHP Fatal error:  Maximum execution time of 60 seconds exceeded in vendor/symfony/polyfill-mbstring/Mbstring.php:635を対処する

問題なく動いているLaravelアプリが入っているEC2インスタンスをコピーして動かすと謎エラーが発生した。

```
PHP Fatal error:  Maximum execution time of 60 seconds exceeded in vendor/symfony/polyfill-mbstring/Mbstring.php:635
```

どうやらmbstringが動いていないらしい。。

# 修正方法その① mbstringを再インストールする
mbstringはもちろんインストール済みではあったがなぜかphpinfoすると`Multibyte decoding support using mbstring`がdisabledだったので再インストールした。

```
$ yum remove php-mbstring
$ yum install php-mbstring

// php-fpmの再起動
$ sudo service php-fpm restart

// Apacheの再起動
$ sudo service httpd restart
```

が、状況は変わりませんでした。。。

# 修正方法その② インスタンス再起動
AWSコンソールからEC2インスタンスを再起動したら状況が改善されて正常に動くようになった！

# まとめ
原因は謎ですがインスタンスを再起動したら直りました。
理由はわからないが、とりあえず動くのでこれでよしとしました、
WEBサーバー、APサーバーについて

#### はじめに

復習もとい備忘録にWEBサーバーとAPサーバーについてまとめてみました。

今回の記事では、WEBサーバーとAPサーバーの違い、役割についてまとめていきます。

#### そもそもWEBサーバーとAPサーバーって何？

![投稿記事用0710.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1928016/616a1347-7b99-b783-2f78-1a2dcf088fee.png)

簡単に画像で説明してみる。

**WEBサーバーはクライアントから投げられたHTTPリクエストを処理する層**
場合によっては、後続のAPサーバーに処理を受け渡す。

**AP（アプリケーション）サーバーはRubyやPythonなどを実行してデータを処理するもの。**
ローカルで作成したWEBアプリケーション(Flask,Django)を動かしているのはここの層。


#### APサーバーの役割


APサーバーに処理を投げる場合は動的にコンテンツを生成する場合。

**動的コンテンツというのは、ページによって値が変わったりする動的に値などが変化するコンテンツのこと。**

具体例を挙げるなら、訪問者数のカウンターの部分はアクセスの度に値が変わるので、動的なコンテンツになる。

動的コンテンツを生成した後の流れとして、APサーバーから受け取った処理をWEBサーバーを介して、クライアントに返却する。

場合によっては、APサーバーからDBサーバーに接続して、処理を行ったりする。


少し、話が脱線してしまいますが。。。
Flaskは組み込みサーバーを保有しており、ローカルではWEBサーバーの環境構築を行わずにWEBアプリケーションにアクセスできる。

#### WEBサーバーの役割

WEBサーバーはAPサーバーから受け取った値をWebブラウザに返す。
また、静的コンテンツへのリクエストの場合（HTML,CSSだけ）の場合はWEBサーバーがAPサーバーに問い合わせを行うことなく、クライアントに値を返したりもする。

昔はWEBサーバーにすべての処理を担わせていたらしい。（動的コンテンツの生成をWebサーバーで行っていた）

WEBサーバーとAPサーバーに分けられている理由として、

**サーバーへの負荷分散などが挙げられる。**

以前はWEBサーバーにアプリケーションの役割も持たせていたが、大量の処理などがきた場合にWEBサーバーへの負荷が大きくなってしまう。

そこでWEBサーバーとAPサーバーを分けることで、処理を分割してサーバーへの負荷を減らすといった対応を取った。

動的コンテンツを生成する場合はAPサーバーで処理を行い、静的ページを表示するだけの部分はWEBサーバーが処理を行うことで処理が分散される。

また、セキュリティの観点からも2つを分けておく方が情報漏洩のリスクが少なくなる。

現在、nginxが多くの場面で採用されているのは、大量アクセスへの負荷分散が優れているからだったりする。

#### まとめ

WEBサーバーとAPサーバーに分ける理由として、負荷の分散、セキュリティ面のケアが理由。


#### 参考にした記事

https://www.nginx.co.jp/resources/glossary/application-server-vs-web-server/

https://kitsune.blog/web-server-summary
【Git】git stashのメモ

### 一時退避させる
```Bash
# saveは省略可能
git stash save
git stash 

# 任意メッセージを加えてsaveする
git stash save "hoge"
```

### 未追跡のファイルも含めて全てスタッシュ
```Bash
git stash -u
```

### 保存されているスタッシュを一覧表示する
```Bash
git stash list
```

### N番目のスタッシュを適用し、残す
```Bash
# NはN番目
git stash apply stash@{N}
```

### N番目のスタッシュを削除
```Bash
# NはN番目
git stash drop stash@{N}
```

### N番目にスタッシュしたファイルを表示する
```Bash
# NはN番目
git stash show stash@{N}
```

### N番目にスタッシュしたファイルごとの変更内容を表示する
```Bash
# NはN番目
git stash show -p stash@{N}
```

### スタッシュを全削除する
```Bash
git stash clear
```
X.509 とは

## 勉強前イメージ

見たことあるかもしれんくらいのレベル

## 調査

### X.509 とは

エックスポイントゴーマルキューと呼ばれ
デジタル証明書また、証明書失効リストのデータ形式を定めた標準規格の一つになります。

PKIとは盗聴や改ざん、なりすましを防ぐために公開鍵暗号技術と電子署名を使用して、安全な通信を行うことが出来るようにするための環境のことです。
詳細は [こちら](https://qiita.com/miyuki_samitani/items/73adf345bd8ec5213431) に記載しております。
そのなりすましなどを防ぐためのPKIという仕様の規定になります。

元々はITU-TというところがX.500シリーズの標準の一環として策定したものです。
現在はv3が広く知られていますが、v1,v2もありました。

- X.509証明書

v3のが使用されており、公開鍵認証の標準のフォーマットになります。

- X.509証明書失効リスト

証明書の内容が変更になったり、秘密鍵が漏洩したりなどの理由で証明書を無効にするために使用されます。
恒久的な無効化と一時的な無効があり、一時的な無効は後から有効にすることもできます。

## 勉強後イメージ

フォーマットとかでも細かく標準って決められるのね

## 参考

- [X.509とは](https://atmarkit.itmedia.co.jp/ait/articles/0401/01/news098.html)
- [X.509](https://e-words.jp/w/X.509.html)
サイバーセキュリティお嬢様「しんせいせい...ってなんですの？」

### 前回までのあらすじ
[サイバーセキュリティお嬢様「CIAってなんですの？」](https://qiita.com/choco_py3/items/51c04bdc8bfe25fe84f3)

# ある日
サイバーセキュリティお嬢様（以下CSお嬢様）「おーほっほ！」
CSお嬢様「これで情報セキュリティの３要素、CIAは完璧でしてよ！」
CSお嬢様「これでサイバーセキュリティお嬢様を名乗っても恥ずかしくないですわー！」

じいや「**お嬢様！甘いですぞ！**」

CSお嬢様「じいや一体何事ですの」

じいや「実は情報セキュリティの要素は」
じいや「CIA以外にも4つ存在するのですぞ」

# CIAに付加されたセキュリティ要素
じいや「ISO/IEC 27001:2005という規格では、以下の4要素が追加されていますのじゃ」

:::note info
真正性（Authenticity）
責任追及性（Accountability）
否認防止（Non-repudiation）
信頼性（Reliability）
:::

CSお嬢様「ではこれも頭文字を取って、 **AANR** になりますわね！」

じいや「残念ながらお嬢様」
じいや「こちらの方はCIAのように略称は存在しないようですぞ」

CSお嬢様「あら〜そうなんですの？」
CSお嬢様「**覚えにくそうでいきなりめんどくさくなってきましたわ**」

じいや「やれやれ、これでは先が思いやられますな」
じいや「今回もじいやが分かりやすく説明して差し上げましょうぞ」

CSお嬢様「なるべく手短に、略して『**なる手**』でお願いいたしますわぁ〜」

## 真正性
CSお嬢様「しんしょうせい...ってなんですの？」

じいや「お嬢様、正しくは【しんせいせい】ですぞ」
じいや「真正性とは」
じいや「利用者や情報が主張通りであることですぞ」

CSお嬢様「**わたくし、じいやが何を言っているかさっぱりでしてよ**」

じいや「例えば」
じいや「なりすましを防止したり、データが改ざんされていないことを証明したりするのが真正性にあたるのですぞ」
じいや「多要素認証と呼ばれる方法や、ディジタル署名、ハッシュ値などで真正性を高めることができますのじゃ」

CSお嬢様「**やっぱり何を言っているのかさっぱりですわぁー！**」

じいや「お嬢様でも分かりやすいように説明すると」
じいや「ばあやがお嬢様になりすましてお嬢様の部屋に入ったり」
じいや「お嬢様がご学友に宛てた手紙をこっそり書き換えて送るなどされると」
じいや「真正性が脅かされた状態になっているわけですな」

CSお嬢様「**よく分かりましたけれど、ばあやがわたくしの変装をしている姿を想像してゾッとしましたわ**」

## 責任追及性
CSお嬢様「責任追及性、ってなんですの？」

じいや「責任追及性とは」
じいや「利用者や情報に対し」
じいや「ログなどを用いて、その動作内容を適切に追跡できることですじゃ」

じいや「お嬢様でも分かりやすいよう説明すると」
じいや「情報へのアクセス、動作ログを取得、保管しておくこと、」
じいや「例えばお屋敷の厨房に監視カメラを設置しておくことで」
じいや「お嬢様が夜中こっそり忍び込んでおやつを盗み食いしていることを証明できるわけですな」

CSお嬢様「**夜中の盗み食い、しっかりバレていましたわー！**」

## 否認防止
CSお嬢様「否認防止、ってなんですの？」
じいや「否認防止とは一言で言うと」

じいや「**後でなかったことにされないようにすること**、ですじゃ」
じいや「否認防止にはディジタル署名やタイムスタンプなどが有効ですぞ」

CSお嬢様「じいやが何を言っているのかさっp..」

じいや「**詳しくは別の機会に説明しますが**」
じいや「ディジタル署名は作成者を証明する、電子版の署名や押印のことで」
じいや「タイムスタンプはデータに付けられた日時の情報のことですぞい」

CSお嬢様「しっかり証拠を残しておくことで」
CSお嬢様「言った言わないを回避する、ということで合っていまして？」

じいや「お嬢様にしては冴えていますな」

CSお嬢様「**じいや、一言多いですわ**」

## 信頼性
CSお嬢様「信頼性、ってなんですの？」

じいや「信頼性とは」

じいや「システムの処理に矛盾がなく整合性が取れている状態ですぞ」
じいや「**システムの冗長化や、バグや脆弱性（ぜいじゃくせい）の素早い対応が信頼性の向上につながりますな**」

CSお嬢様「つまりどういうことでして？」

じいや「お嬢様にも分かりやすく説明すると」
じいや「お嬢様のお世話係はじいやの他にばあやがいますが」
じいや「じいやが風邪を引いてもばあやがいるのでお嬢様のお世話が遂行できますな」
じいや「これが冗長化です」

じいや「脆弱性などについてはまたの機会に説明しますが」
じいや「じいやもばあやも不調時にはお休みをいただいて、身体のメンテナンスをすることで」
じいや「お嬢様へのお世話の品質を維持しているのですぞ」

CSお嬢様「なんとなく分かりましてよー！」

# おわりに
じいや「どうでしたかな」

CSお嬢様「今回も分かりやすかったわ、ありがとうじいや」

じいや「これからも少しずつセキュリティの知識を身につけて」
じいや「**真のサイバーセキュリティお嬢様**を目指すのですぞ」

CSお嬢様「わたくし頑張りましてよー！」

# 参考文献
この一冊で全部わかる セキュリティの基本
情報処理教科書　情報処理安全確保支援士2022年版

# 次回以降
[サイバーセキュリティお嬢様「き...脆弱性ってなんですの？」](https://qiita.com/choco_py3/items/15479e37b011c34abf36)
[サイバーセキュリティお嬢様「マルウェア...？スキーウェアのお仲間ですの？」](https://qiita.com/choco_py3/items/00af04f6906de4135b48)]
[サイバーセキュリティお嬢様「クラッカー？何それ食べられますの？」](https://qiita.com/choco_py3/items/40fe5a27af3722daa654)
[サイバーセキュリティお嬢様「ハクティビストってなんですの？」](https://qiita.com/choco_py3/items/262df8fc893cf7fd303f)
[サイバーセキュリティお嬢様「F5攻撃（アタック）ってなんですの？」](https://qiita.com/choco_py3/items/f0164dedc7e4b761b25d)
[サイバーセキュリティお嬢様「SQLいんじぇくしょん...ってなんですの？」](https://qiita.com/choco_py3/items/4a597f25f0c3dbbea437)
[サイバーセキュリティお嬢様「クロスサイトスクリプティング？...美味しそうですわぁ！」](https://qiita.com/choco_py3/items/f3bb70ecf819bb55ad80)

# 宣伝
[技術書典13](https://techbookfest.org/event/tbf13)にサークル参加予定ですわ！
良かったら[Twitter](https://twitter.com/choco_py3)フォローしてくださいですわー！
Jenkinfilesからbashでコマンドを実行する

# TL;DR
Jenkinsfileでは `sh '''` 〜 `'''` で囲った複数行のシェルコマンドを実行することができる。この際、通常はOSの `sh` コマンドで実行されるが、開始行の `'''` の右に `#!/bin/bash` などのシェバンを追記すると、 `bash` などの指定したインタプリタでのコマンド実行が可能となる。

```groovy
pipeline {
    agent any
    stages {
        stage('Test') {
            steps {
                sh '''#!/bin/bash
                    python3 -m venv .venv
                    source .venv/bin/activate
                    echo "hoge"
                '''
            }
        }
    }
}
```


# 詳細
Jenkinsfileには、Jenkinsパイプライン上でシェルコマンドを実行するための `sh` というステップが用意されており、 `sh <command>` の一行形式か、 `sh '''` 〜 `'''` の複数行形式で記述できる。

```groovy
pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                sh 'echo "Hello World"'
                sh '''
                    echo "Multiline shell steps works too"
                    ls -lah
                '''
            }
        }
    }
}
```

ただし、この `sh` ステップはOSの `SHELL` 環境変数の値に関わらず `/bin/sh` インタプリタで実行される。このことにより、時折不都合が生じることがある。
例として、Ubuntu20.04の `sh` コマンドは `dash` へのシンボリックリンクとなっており、　dashには　`source` などの一部コマンドが存在しないため、bashと同じ感覚で以下の内容をパイプラインで実行させるとエラーが発生してしまう。

- 実行するパイプライン
```groovy
pipeline {
    agent any
    stages {
        stage('Test') {
            steps {
                sh '''
                    python3 -m venv .venv
                    source .venv/bin/activate
                    echo "hoge"
                '''
            }
        }
    }
}
```

- 発生するエラー

```
script.sh: 2: source: not found
```
　　
`source` であれば `.` に置き換えることで解消できるが、その他の理由で `dash` ではなく `bash` を使いたいといった場合、複数行コマンドの形式で `sh '''` の右に `#!/bin/bash` のシェバンを追記することで、 `bash` でのコマンド実行が可能となる。

```groovy
pipeline {
    agent any
    stages {
        stage('Test') {
            steps {
                sh '''#!/bin/bash
                    python3 -m venv .venv
                    source .venv/bin/activate
                    echo "hoge"
                '''
            }
        }
    }
}
```

このとき、 `'''` とシェバンはスペースを空けずに記述する必要がある点に注意。


# 参考
[jenkins.io - Running multiple steps](https://www.jenkins.io/doc/pipeline/tour/running-multiple-steps/)
[Bourne Shell(レガシー sh)とPOSIXシェル(sh, bash, etc)の違い - Qiita](https://qiita.com/ko1nksm/items/6b61b0e687d206be9cb0)
Rails7で画像の保存にActiveStorage使ってみよう(導入からリサイズまで)

## はじめに

Ruby on Railsには、クラウドストレージサービスへのファイルのアップロードを行う機能を提供するActive Storageがあります。

Rails5.2から登場したActive Storageですが、当初はできることが少なく、CarrierWaveを利用する方も多かったのではないでしょうか。
Rails7まででActive Storageには様々な機能が追加され、新規開発の際はActive Storageを選択することが多くなると思います。

今回はActive Storageの導入からよく使うであろう画像のリサイズの方法までをご紹介します。

ViewやControllerまわりについては説明していないので[Railsガイド](https://railsguides.jp/active_storage_overview.html)などで確認してください。

## 開発環境

[こちらの記事](https://qiita.com/croquette0212/items/7b99d9339fd773ddf20b)を参考にRails7 + MySQLの開発環境ができている前提で話を進めていきます。

## libvipsのインストール

Active Storageで取り扱いたいファイルの種類に応じて、必要なライブラリをインストールする必要があります。今回は画像を取り扱いため、libvipsをインストールします。(ImageMagickでも良いですがlibvipsの方が処理が高速なためそちらを選択)

Dockerfileにlibvipsインストールの記述を追加します。(`RUN bundle install`の前)

```Dockerfile:Dockerfile
RUN apt-get update && apt-get install -y libvips42
```

## image_processing gemのインストール

image_processing gemも必要なため、Gemfileのコメントアウトを外します。

```:Gemfile
# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
gem "image_processing", "~> 1.2"
```

この段階でbuildしておきます。

```sh
docker-compose build
```

## ActiveStorage用のmigrateファイルの作成

ActiveStoregeでは3つのDBテーブルが必要となります。

- `active_storage_blobs`: ファイルの実体(blob)を保存しておくテーブル
- `active_storage_attachments`: ActiveRecordと↑のファイルの実体(もとの画像)を紐づけるテーブル
- `active_storage_variant_records`: ActiveRecordと↑のファイルの実体(後述するvariantで作成された画像)を紐づけるテーブル

テーブルを作成するためのmigrateファイルは下記コマンドで作成することができます。

```sh
docker-compose run --rm web rails active_storage:install
```

## 利用するサービス(保存先)を設定する

ファイルの保存先はローカルやS3などいろいろ設定することができます。今回は開発環境でローカル利用するために必要な設定を行います。

サービスの定義を`config/storage.yml`に記述します。
ローカルはすでに定義されているため変更不要です。

```yaml:config/storage.yml
local:
  service: Disk
  root: <%= Rails.root.join("storage") %>
```

利用するサービスをActiveStorageに認識させるために`config/environments/development.rb`に下記を追加します。

```ruby:config/environments/development.rb
config.active_storage.service = :local
```

## ファイルをレコードに紐づける

Userモデルを作成します。アバター画像を紐づけたいので以下のジェネレーターコマンドを実行します。

```sh
docker-compose run --rm web rails generate model User name:string avatar:attachment
```

実行後に以下のようなモデルが作成されます。

```ruby:app/models/user.rb
class User < ApplicationRecord
  has_one_attached :avatar
end
```

`has_one_attached`でレコードとファイルの間に1対1の紐づけができます。

## variantを使って画像をリサイズする

variantを利用することで、もとの画像ファイルはそのままに、サイズ違いの画像を作成することができます。

```ruby:app/models/user.rb
class User < ApplicationRecord
  has_one_attached :avatar do |attachable|
    attachable.variant :thumb, resize_to_limit: [100, 100]
  end
end
```

上記では`thumb`というvariant名で、最大で幅100px高さ100pxの画像となるようにリサイズされた画像を利用できるようになります。その他の画像処理の指定方法などは[image_processingのREADME](https://github.com/janko/image_processing/blob/master/doc/vips.md#methods)を確認してください。

variantは`user.avatar.variant(:thumb)`のような形で呼び出すことができます。

初回の呼び出し時に画像を作成・保存し、次回以降は保存されたリサイズ済みの画像を取得するようになります。
【kotlin】viewの位置やサイズを動的に変更する【Android】

# はじめに
今回はviewをレイアウトではなく　コード上で動的に動かす、サイズを変更する方法を記事にします


# コード一覧表
|コード|説明|
|:---|:---|
|translationX|X座標位置を指定することで、指定した位置にViewオブジェクトが移動。（横方向に移動します）|
|translationY|Y座標位置を指定することで、指定した位置にViewオブジェクトが移動。（縦方向に移動します）|
|scaleX|指定したサイズにViewオブジェクトの横幅が変更されます。|
|scaleY|指定したサイズにViewオブジェクトの縦幅が変更されます。|
|rotationX|指定した角度にX軸回転します。|
|rotationY|指定した角度にY軸回転します。|
|rotation|指定した角度でViewオブジェクトの中心点を中心に回転します。|





# 実践
ここでは一例として　translationXを使ってHello World! のviewを横方向に移動させたものを　コードとスクショで置いておきます
![スクリーンショット 2022-07-10 21.59.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2394054/9eda3446-0689-22d1-6fba-feb2265ce450.png)



```
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val textView = findViewById<TextView>(R.id.text_view)
        textView.translationX = 300F
```
移動させたいTextViewに対して.translationXで移動してほしい位置を指定します
はじめの位置は０で、型はfloatです


![スクリーンショット 2022-07-10 21.59.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2394054/7af26397-a978-1009-cc9e-8996b80fd1a6.png)


# 終わりに
今回記事にしたやり方以外にも、layouytで使っているviewの種類で違う名前の同じ機能のものがあったり
違うアプローチの仕方があったり様々な方法でのやり方があると思います。
それらもまた別の機会に記事にできたらいいなと思います。
PL-300受験体験記

PL-300に受験し合格できたので、その勉強方法や感想を共有したいと思います。

# PL-300について
PL-300とは、Microsoft Power BI Data Analystのことで、Power BIの基本的機能やより良いモデルの作り方を学べる資格試験です。

[公式ページ](https://docs.microsoft.com/ja-jp/learn/certifications/exams/pl-300)

# 受験のきっかけ
仕事でPower BIのレポートを作ったりする際に、Power BIの機能を知ることが楽しく、きちんと体系的に勉強したいと思っていました。

また、Cloud Skills Challengも開催されていたので、無料で受験できたので、良い機会だと受験しました。

[Cloud Skills Challengについて](https://www.microsoft.com/ja-jp/cloudskillschallenge/build/registration/2022?wt.mc_id=build22_csc_webpage_esc)

※Cloud Skills Challengは半年に１度程度開催されています。対象試験は変わるので、定期的にチェックするとよいです。

# 勉強方法
セオリー通り、試験範囲のLearnを熟読しました。

Power BI Desktopの基本機能やDAXは触る機会が多かったですが、Power BIサービスやRLSは使ったことがなかったので、その部分のLearnの内容を時間をかけて試してみました。

勉強時間は20時間〜30時間くらいだったかと思います。

# 結果
自宅受験をし、結果は858点でした。

自信のない回答も多くあったので、バランスよく得点でき、予想以上の結果でした。

# 感想
無事合格できて、ひとまず良かったです。

また、[パフォーマンスの最適化](https://docs.microsoft.com/ja-jp/learn/modules/optimize-model-power-bi/)などで知らなかった手法があり、勉強になりました。

ただ、基本的な内容がメインで、この資格を取れば、素晴らしいレポート作りやモデリングができるかというとそうでないと思います。

この試験を通じて、Power BIに関する理解できてないこと、有益なことがまだまだあるたくさんあると知れたので、Docsや先人たちのQiita記事で勉強し続けていきたいです。