OmniAICreator/Qiita-1.07M huggingface dataset:
【ルール説明・basic】key-order

こちらの記事は [Ansible lint Advent Calendar 2022 カレンダー2](https://qiita.com/advent-calendar/2022/ansible-lint) 7日目の記事になります。


今回はルール [key-order](https://ansible-lint.readthedocs.io/rules/key-order/) について説明します。

### key-order

[key-order](https://ansible-lint.readthedocs.io/rules/key-order/) はコードの保守を容易にし、エラーを少なくするために、Ansible コンテンツのキーの順序を変更することを推奨しています。[key-order](https://ansible-lint.readthedocs.io/rules/key-order/) に違反すると警告が出力されます。

以下は推奨される書き方です。

* play、task、handler では、name が常に最初のキーでなければならない
* タスクの場合、block、rescue、always のキーは最後のキーでなければならない

#### 問題のあるコード

```yaml
---
- hosts: localhost
  name: This is a playbook # <-- name キーが最初に記述されていない
  tasks:
    - name: A block
      block:
        - name: Display a message
          debug:
            msg: "Hello world!"
      when: true # <-- when キーは block キーの前に記述する
```

#### 修正されたコード

```yaml
---
- name: This is a playbook
  hosts: localhost
  tasks:
    - name: A block
      when: true
      block:
        - name: Display a message
          debug:
            msg: "Hello world!"
```

### 参考サイト

* [key-order — Ansible Lint Documentation](https://ansible-lint.readthedocs.io/rules/key-order/)
VueのOptionAPIで使われていないプロパティを検知するESlintルール

# 結論
**vue/no-unused-property** を使う
https://eslint.vuejs.org/rules/no-unused-properties.html

# 背景
ReactのJSX構文やVueのCompositionAPIでは、JavaScript的にPropsやメソッド、リアクティブな変数を定義できるため、no-unused-varルールで使われていないものを検知することができる。
VueのOptionAPIでは、Vue独自の構文でクラス的な記法でプロパティを定義するため、JavaScriptのルールでは使われていないものを検知することができない。

# 使用例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414330/20b6b5d1-ee20-477f-88cc-f254002eb658.png)


# 注意点
vueのステート管理ライブラリであるvuexのmapGettersでラップした場合はこのルールだけでは検知ができない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414330/576f024e-6ec4-2d46-31ff-03d63e38d323.png)
今年のadvent calenderまとめ〜togetterによるイベント履歴のすすめ

CIST (公立千歳科学技術大学) Advent Calendar 2022 今年分の総括(<-この用語はイヤン)を、みんなでしよう！みたいな...

- とりあえず、例年より、だいぶ埋まったじゃないか〜
- これを機に外へ打って出る人が増えると良いな〜

### まとめ

以下、いつものように togetterによるツィートまとめのつもりだったのですが、ほぼタイトルが並んでいるだけ＝カレンダー見るのと一緒なので、まとめの意味はないですね orz

https://togetter.com/li/1981524

### togetter推しの謎を語る

これだけだと何なので、なんで常にtogetter出動やねんというところを語っておきましょう。

>イベントのときは、リアルタイムに、どうでもいいことでもtweetしとけ

という教えですよと。この元ネタは日本NetBSDユーザグループ（というか、ほぼebijunさんがマメでエライという話）ですけれど、おかげで10年以上前の当時の様子もなんとなく分かるというもの。OSCのほぼすべてに参加しているebijunさんなので、昔のOSC NetBSDブースとか当時の話題も振返れるのです。振り返ると十年一日じゃないかとか言われるのかもしれませんが:-)

https://togetter.com/t/NetBSD

それはともかく、当時のリアルタイムの生々しさが読み取れるところが良いのではとおもいます。回想録ではいかんのですよ。回想録は、やはり事実関係や時間関係を正確に思い出せなかったり、美化したり、編集過程で取捨選択が行われますしね。回想録がどう歪められていくのか？の具体例は、E.H.Carr, "What is History?"を参照。この本、長年、岩波新書（青版,清水幾太郎訳）で親しまれてまいりましたが、とつぜん今年、新訳が出ました(もしかしてウクライナ情勢あわせ?)。まだ新版は買ってない=読んでないですけど

https://www.iwanami.co.jp/book/b267200.html

https://www.iwanami.co.jp/book/b605144.html


p.s.

では、みなさま、良いお年を

p.s.2

総括といえば連合赤軍がですね...（やめ）
CSSのfocus-visibleを使ってみる

[ひとりCSS Advent Calendar 2022](https://qiita.com/advent-calendar/2022/css-becolomochi) 25日目です。

focus-visible を使ってみます。

## focus-visible とは

https://developer.mozilla.org/ja/docs/Web/CSS/:focus-visible

- フォームのinput要素にフォーカスを当てるユーザーの行動
    - マウスでクリックする
    - キーボードのタブキーを押す
- このときのスタイルを調整できる

## サンプル

要素の隣に結果を書いてある。
挙動は[Codepen](https://codepen.io/becolomochi/pen/KKBpLBK)見てください。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41088/6f791068-2dee-d180-5109-40399be3a7f0.png)

### HTML

```html
  <input class="focus" value=":focus"> マウスあり・キーボードあり
</div>
<div>
  <button class="focus">:focus</button> マウスあり・キーボードあり
</div>
<div>
  <input class="focus-visible" value=":focus-visible"> マウスあり・キーボードあり
</div>
<div>
  <button class="focus-visible">:focus-visible</button> マウスなし・キーボードあり
</div>
```

### CSS（抜粋)

```css
:root {
  --color1: #edb658;
  --color2: #e7719b;
}

.focus:focus {
  outline: 4px dotted var(--color1);
}

.focus-visible:focus-visible {
  outline: 4px dotted var(--color2);
}
```

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="KKBpLBK" data-user="becolomochi" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/becolomochi/pen/KKBpLBK">
  accent-color</a> by Beco (<a href="https://codepen.io/becolomochi">@becolomochi</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## 感想

- :focus-visible は例えばフォームの送信ボタンで使うと良さそう
    - マウス操作時にはフォーカスは見えなくてもいいけど、キーボードではフォーカスは見えていてほしい場合

## 参考

- https://developer.mozilla.org/ja/docs/Web/CSS/:focus-visible
簡単Elixirシリーズ ~ シンタクッスシュガー ~

# 簡単Elixirシリーズ
## ~ シンタクッスシュガー ~

この記事は「[Elixir Advent Calendar 2022](https://qiita.com/advent-calendar/2022/elixir)」16日目の記事です
東京にいるけどfukuokaexのYOSUKEです。

簡単 Elixirシリーズでは小ネタをサクッと書いていこう。というコンセプトで作っていきます。

今回は、オプションの構文と書かれている公式ドキュメントについてサクッと見ていきます。

ちなみに、Elixirの学習を始めた頃、このドキュメントにたどり着く前にめっちゃハマり、
@zacky1972 さんに教えてもらい、シンタックスシュガーと言うんだよ。と教わったことを思い出しました。

https://elixir-lang.org/getting-started/optional-syntax.html

まずは、```()```はオプションで省略可能なもの

```elixir
iex(40)> length([1,2,3])
3
iex(41)> length [1,2,3] 
3
iex(42)> length([1,2,3]) === length [1,2,3]
true
````

なので、```()```を外しまくってこんな感じで書くこともできます。

```elixir
iex()> Enum.map [1,2,3], & &1*2
[2, 4, 6]
```
次に、 ```do``` - ```end``` は キーワードリスト である。
に関しては、以下のようにも書けます。

```elixir
iex()> if true do
...()> :hello
...()> else
...()> :world
...()> end
:hello
iex()> if true, do: :hello, else: :world
:hello
```

キーワードリストなので、 do: や else: はアトムです。なので、さらに詳しくすると以下のように書いても動きます。

```elixir
iex()> if true, [{:do, :hello}, {:else, :world}] 
:hello
```

Phoenix フレームワークの中ではこのシンタックスシュガーが至る所で絶妙に利用されているので初めてみると混乱するかも知れませんが、シンタックスシュガーを利用して 記述をコンパクトにわかりやすくしています。
Wkipediaの助けを借りながら確率変数をサイコロの例から理解する

確率変数がわからない。何がわからないかからわからない。
確率密度関数もどうしてそれが出てくるのか、重要なのかわからない。
でもサイコロをふって出る目とその確率はなんとなくわかる。
サイコロの例から理解を広げて、確率変数をわかったつもりになる記事。

:::note warn
数学の集合の記法出てきます。測度論から厳密に理解しようとすると余計にモヤモヤするので、Wikipediaと集合の概念を使う程度のふわっとアプローチ。
:::

Wikipediaから`試行`の記事を引用すると
>確率論において、試行（しこう、英: trial, experiment）とは、起こりうる結果がいくつかあり、そのどれか1つだけが偶然で起こる流れのことである。試行の結果全体の集合は標本空間（全事象）と呼ばれる。
（中略）
試行の結果のいくつかからなる集合で、起こる割合が決まっていると考えられるものを事象という。事象に対してそれの起こる割合を確率という。

またWikipediaから`根元事象`の記事を引用すると
>確率論において、根元事象（こんげんじしょう、英語: elementary event）とは、1つだけの結果からなる事象である。
原子事象（げんしじしょう、英語: atomic event）ともいう。集合論の観点では、根元事象は単集合である。

これを「サイコロをふって出る目」の例を添えて書き出してみると

|用語|定義|例|
|:--|:--|:--|
|試行|結果を1つだけ引き起こす流れ|サイコロを1回ふる|
|結果|（これは言葉のまま受け取る）|⚂が出る|
|事象|結果のいくつかからなる集合で、<br>起こる割合が決まっているもの[^1]|{偶数の目が出る}<br>起こる割合は1/2|
|確率|事象に対してそれの起こる割合<br>（言葉の言い換え）|{偶数の目が出る}の確率は1/2|
|全事象|結果の全体の集合|{⚀〜⚅のどれかが出る}<br>起こる割合（確率）は1|
|根元事象|1つだけの結果からなる事象|{⚂が出る}<br>起こる割合（確率）は1/6|

ここでポイントなのが、事象は「結果の集まり（集合）」であって、集合に対して確率という数値が定まっているところ。集合の大きさが定まっているような感じ。集合の要素（結果）に対して大きさが定まっているわけではない。
![diagram-20221117.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66591/95b2b987-ce3d-20a4-6e02-bb6af989f510.png)

次に`確率変数`のwikipediaの記事を引用すると
>確率変数（かくりつへんすう、英: random variable, aleatory variable, stochastic variable）とは、統計学の確率論において、起こりうることがらに割り当てている値（ふつうは実数や整数）を取る変数。
各事象は確率をもち、その比重に応じて確率変数はランダムに値をとる。

起こりうることがらとは結果のことなので、結果に値を割り当てようということ[^2]。サイコロの例で結果を並べて、数値（整数）を割り当ててみると
|結果|割り当てる値|
|:--|:--|
|⚀が出る|1|
|⚁が出る|2|
|⚂が出る|3|
|⚃が出る|4|
|⚄が出る|5|
|⚅が出る|6|

例えばこんな割り当て方をした場合、確率変数Xとは1〜6のどれか値を取る変数を意味するということ。
さらに確率変数はランダムに値をとるということで、確率は今整数のほうじゃなくてサイコロの世界にある話だから

|結果|割り当てる値|値を取る割合|
|:--|:--|:--|
|⚀が出る|1|値1を取るのは{⚀が出る}確率=1/6の割合|
|⚁が出る|2|値2を取るのは{⚁が出る}確率=1/6の割合|
|⚂が出る|3|値3を取るのは{⚂が出る}確率=1/6の割合|
|⚃が出る|4|値4を取るのは{⚃が出る}確率=1/6の割合|
|⚄が出る|5|値5を取るのは{⚄が出る}確率=1/6の割合|
|⚅が出る|6|値6を取るのは{⚅が出る}確率=1/6の割合|

1〜6のどの値を取るかは上記のように（元の世界の確率に応じて）ランダムということなので、英語名の通りランダム変数というほうがいい気がする。(結論出た)
この例の確率変数（ランダム変数）を使うとサイコロの世界の話を、整数の話におきかえることができている。毎回いちいち「⚀が出る」などと書かなくてよくなる。これが確率変数を考えるメリットということね。

ちなみに⚀は1、⚁は2に割り当てなくても確率変数の定義上は問題ない。例えばこんな割り当ての仕方をするのもあり。

|結果|割り当てる値|値を取る割合|
|:--|:--|:--|
|⚀が出る|0|値0を取るのは{⚀～⚄のどれかが出る}確率=5/6の割合|
|⚁が出る|0|値0を取るのは{⚀～⚄のどれかが出る}確率=5/6の割合|
|⚂が出る|0|値0を取るのは{⚀～⚄のどれかが出る}確率=5/6の割合|
|⚃が出る|0|値0を取るのは{⚀～⚄のどれかが出る}確率=5/6の割合|
|⚄が出る|0|値0を取るのは{⚀～⚄のどれかが出る}確率=5/6の割合|
|⚅が出る|1|値0を取るのは{⚅が出る}確率=1/6の割合|

この場合、確率変数Xとは1または0の値をランダムに取る変数となる。
ずいぶんと元のサイコロの世界の情報が失われてしまっているので、この例から確率変数は異なるものを異なる値に割り当てる（単射性）制約があったほうがよさそう。

なんとなくわかってきた。モヤモヤしてたのは元の世界の情報がなんとなく失われていないかという不安によるものだった。次は確率変数の和や積、連続の確率変数と確率密度関数を理解していきたいと思う。


[^1]:サイコロの例では出てこないが、結果の集合であっても割合が決まっていないもの（大きさの測れない集合）は事象ではない。という深い意味が込められている。
[^2]:別のWikipediaの記事を見ると根元事象に確率変数を割り当てるような記載があるが、たぶん結果と結果1つの集合を同一視してるとかそういう話なので無視。
正規表現を用いたPythonで動的に値を判定する方法

# 前提
ABC084-B問題での実装検討を端的にまとめる
> [ABC084_B問題](https://atcoder.jp/contests/abc084/tasks/abc084_b)

# 今回やりたいこと
* 正規表現を用いて変数の値を反映したい
* 毎回input値が変わるので動的に正規表現をかけて判定したい(今回動的に判定するのは文字数)

# 実装内容
```ABC_084_B.py
import re

a, b = map(int, input().split())
s = input()

# aとbの値を受け取る値毎に動的に変更して文字数を判定する
print("Yes" if re.search(fr'[0-9]{{{a}}}-[0-9]{{{b}}}', s) else "No")

```

* fr"hoge"とすることでfstring関数とrow関数を併用することが可能
* `{` と `}`は2つ重ねればエスケープすることが可能

```実行結果.py
# 下記結果の通り後は上記実装方法の様に、Noneなら"No", matchするなら"Yes"として完成
3 4
269-6650
<re.Match object; span=(0, 8), match='269-6650'>

1 1
---
None

1 2
7444
None
```

# 参考
> https://teratail.com/questions/336593
Github Actions にてコンテナを作成する

GitHub Actions でコンテナを作成し、GitHub Container Registry へ格納します。これまでも同様の処理はやっていたのですが、暫く関連するライブラリのバージョンを更新しておらず、古くなってしまっていたため、最新の記述方法を整理しました。

## やる事
* GitHub Actions でコンテナを作成する
* コンテナをGitHub Container Registry へ格納する
* 2022/12/24時点の最新の書き方に変更する

## Before

私がこれまで使っていたワークフローはこちらです。結構古くなってますね。

```yaml:build.yml
name: Publish Docker image
on:
  push:
    branches:
      - main
jobs:
  main:
    name: Push Docker image to Github Container Registry
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v1
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1
      - name: Login
        run: echo $CR_PAT | docker login ghcr.io -u ${OWNER,,} --password-stdin
        env:
          CR_PAT: ${{ secrets.GITHUB_TOKEN }}
          OWNER: ${{ github.repository_owner }}
      - name: Push to GitHub Container Registry
        uses: docker/build-push-action@v3
        with:
          push: true
          tags: ghcr.io/example/container_name:latest # ここは都度書き換え
```

## After

以下の通り書き換えました。コード数は少し長くなりましたが、これで一安心です。
途中でコンテナのバージョンを指定する為に package.json からバージョン情報を取得していますが、これは私がたまたま node.js プロジェクトでの開発が多いからそうているだけですので、ここはご自身のお好みの方法に変えていただければ幸いです。

```yaml:build.yml
name: Docker

on:
  workflow_dispatch:
  push:
    branches: ["master", "main"]
    tags: ["v*.*.*"]
  pull_request:
    branches: ["master", "main"]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
      id-token: write

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Setup Docker buildx
        uses: docker/setup-buildx-action@v2.2.1

      - name: Log into registry ${{ env.REGISTRY }}
        if: github.event_name != 'pull_request'
        uses: docker/login-action@v2.1.0
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      # 私は主にnode.jsで開発をしているのでpackage.jsonから取得していますが、ここは消しても問題ありません
      # 消した場合は最後の処理のバージョン取得方法を任意の方法へ書き換え下さい
      - name: Get version in package.json
        id: get-package-version
        run: echo VERSION=$(cat package.json | jq -r '.version') >> $GITHUB_OUTPUT

      - name: Build and push Docker image (latest)
        uses: docker/build-push-action@v3.2.0
        with:
          context: .
          push: ${{ github.event_name != 'pull_request' }}
          tags: 
            - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
            - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.get-package-version.outputs.VERSION }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
```
New words in this year (Since 2022/6/13)

# New words in this year (Since 2022/6/13)

I changed jobs this year when Jun 13 2022.
This year will finish in a few days.
So,summarized below in bullet points.

- Tools (A lot of new tools for me in Windows or web Application)
    - BackLog(task management)
    - Slack(chat tool between engineer)
        - API(notification error,notification deploy to prod server etc...)
    - WinSCP(Sync stg server, prod server)
    - RLogin(Connect stg server, prod server)
        - SSH config file
        - OpenSSH error
        - VS Code RemoteSSH WSL
    - Doc Base(markdown article in only self company)
    - A5SQL(watch Database)
        - show processlist
        - query parameter
    - Google
        - Calendar
        - Spread Sheet
        - Document (management task)
        - Chat (chat with colleague)
        - Analytics
        - reCAPTCHA
    - Send Grid (mail delivery service)
    - GMO API

- STG/PRD environment concept
    - Read/Write(Master or Readonly database)
- nginx/apach (web server)
- Linux (aws ec2 instance)
    - top (monitoring server)
    - rsync (sync server)
    - crontab (run regularly)
    - vim (edit in server)
- WSL2
- Docker
- Docker Compose V2
- Basic Authentication
- Python
    - Selenium
簡単Elixirシリーズ　~ マクロを理解しよう quoteとunquoteが必要な理由~

# 簡単Elixirシリーズ
## ~ マクロを理解しよう quoteとunquoteが必要な理由~

この記事は「[Elixir Advent Calendar 2022](https://qiita.com/advent-calendar/2022/elixir)」6日目の記事です
東京にいるけどfukuokaexのYOSUKEです。

簡単 Elixirシリーズでは小ネタをサクッと書いていこう。というコンセプトで作っていきます。

今回は、[Elixir School のメタプログラミング](https://elixirschool.com/ja/lessons/advanced/metaprogramming)の記事を見ていると、
quoteとunquoteを知ったらマクロを理解できる準びができた的な事が書かれていたので、
マクロって何？ を理解する。という小ネタ（そう、この記事はサクッとがコンセプトW）

https://qiita.com/Yoosuke/items/f82e80d764b051ab283e

https://qiita.com/Yoosuke/items/19ac169136b173feb2b6

で、マクロについて色々調べて見ると、@yasuhiro-okada-aktskさんが、すでに[Elixir: Macro入門](https://qiita.com/yasuhiro-okada-aktsk/items/742f266329960ca0ea20)Qiitaの記事にしてくれているようでしたので詳しい内容はこちらを見ていただくことにして、ここではマクロを作る上でquoteとunquoteを使う理由が気になったのでその点について調べてみました。

まず、最初に公式ドキュメントでもマクロのページで最初に言われているのでとても大事な事なのでしょう。を紹介しておきます。

> マクロは最後の手段としてのみ使用してください。明示的は暗黙的よりも優れていることに注意してください。明確なコードは簡潔なコードよりも優れています。

要するに多用するな！ 作るなら相当な責任と覚悟をしなさい。と言うことでしょう。断言しましょう。僕レベルでマクロを扱おうなんて、なんて烏滸がましい！と言われた気持ちですw

## マクロを理解しよう。

まず、マクロを理解する為に、Elixir Schoolに unless を利用した例が書かれていましたので、そちらを確認していきます。

unlessについてはこちらで記事にしてあるので詳しくない方はこちらもご覧ください。

https://qiita.com/Yoosuke/items/1975165016cfcb17271b

一旦、Elixirスクールで紹介されている通りに書いてみます。

```elixir
defmodule MyMacro do
  defmacro unless(expr, do: block) do
    quote do
      if !unquote(expr), do: unquote(block)
    end
  end
end

iex()> MyMacro.unless true, do: "Hello"
nil
iex()> MyMacro.unless false, do: "Hello"
"Hello"

```

ちなみに、以下でも動きます。なので quote と unquote が必要な理由が知りたいです。

```elixir
defmodule MyMacro do
  defmacro unless(expr, do: block) do
     if !(expr), do: block
  end
end

iex()> MyMacro.unless true, do: "Hello" 
nil
iex()> MyMacro.unless false, do: "Hello"
"Hello"
```

と言うことで、調べてみました。理由は簡単だったのですが、```quote```と```unquote```を利用しないバージョンで例えば以下のように ```flag``` に true や false を入れて利用したいとします。 要するに変数を使った利用です。

```elixir
iex()> flag = true
true
iex()> MyMacro.unless flag, do: "Hello" 
nil
iex()> flag = false
false
iex()> MyMacro.unless flag, do: "Hello" 
nil
```
このように、変数を入れても結果が変わりません。これはコンパイル時点で固定の値になってしまう為です。
と言うことで、コンパイル時にマクロはquoteを利用してASTで返すようにし、unquoteを利用してASTに、今回の場合であれば、引数の値が入るように作る必要があるということがわかりました。

## 参考

* [Elixir: Macro入門(Qiitaの記事)](https://qiita.com/yasuhiro-okada-aktsk/items/742f266329960ca0ea20)
* [Elixir.School マクロ](https://elixirschool.com/ja/lessons/advanced/metaprogramming)
* [Elixir 公式ドキュメント マクロ](https://elixir-lang.jp/getting-started/meta/macros.html)
非エンジニア非デザイナーがPMをやってみた話

### 本記事について
この記事は[プロダクトづくりのための挑戦とその成功・失敗談を綴るアドベントカレンダーpowered byプロダクト筋トレAdventCalendar2022](https://qiita.com/advent-calendar/2022/product-kintore-challenge) の24日目の記事です。
本日は非エンジニアかつ非デザイナーである私がPMを担当したプロジェクトについて書きます。
しくじりも踏まえて書いていますので、これからPMを始める方、初めて開発プロジェクトに関わる方の参考になればと思います。

### 誰のための記事?
「セールスやマーケターからPMになった方」
「これからPMを担当するけど何からやっていいかわからない方」
「PM何それ美味しいの？と思っている方」

### 自己紹介
靴の販売員から真逆のことに挑戦したいと思い、法人向けの営業支援会社へ転職。
コールセンターやMAツールなどの立ち上げに参賀した後、通販のデータサイエンス部署へ転職。
2022年3月より、UXリサーチャーとして流通小売業界の開発部門を担う会社へJOIN。
直近はWebやアプリの体験設計に携わる。

### 非エンジニア非デザイナーがPMをやってみた話
自己紹介にも記載しましたがお題の通り、私は非エンジニアかつ非デザイナーです。
少しだけプログラミングスクールでコードを書いたことがあるものの、実務ではSQLやpythonを使用する程度です。
そんな私がPMをやることになりました。PMをやってみて気づいたことや学んだことを書きます。

**1.背景や目的を詳しく聞いて言語化する**
依頼内容をそのまま受け取ってデザイナーがラフを作成したのですが、後から実はあーで、こーでと追加や修正が入りました。
デザイナーは「え？依頼通りなのになんで？」となったのですが、なんで？となった部分を深く掘り下げてい聞いていくと、
本当に実現したいこと、改善したいことは初めの依頼内容と真逆のことだったり、必要なことが抜けていたりしました。
受け身にならず、どういう背景や経緯か、誰の何のための改善なのか深く掘り下げて聞き、言語化し、
認識すり合わせに時間をかけてデザインのリテイクをなくす方が、確実に早くて良いものができます。
プロジェクトに関わる全員が共通認識を持たなくてはならないのだと再認識しました。

**2.mustとwantを切り分ける**
デザインもFIXし、開発に入るぞーと思ったの束の間、やっぱりこーしたい、あーしたいという要望が入ります。
ラフを教訓に、よくよくその改善要望を聞いてみると9割はあったらいいな、できたらいいなといった希望や夢でできていたりします。
依頼側も悪気はないのですが、要望を全て受け入れてデザイン修正していたら納期はどんどん遅延していきます。
実際にできればあったら良い機能を実装した時、どのくらいの改善インパクトがあるのか依頼側に確認したところ、
100件のうち1件しかない事象のための機能追加でした。今回は代替になる機能があったので、そちらで納得してもらいました。
mustなのか、wantなのか要望を切り分けて整理していくことが大切です。

**3.デザインと開発どちらで対応するのか切り分ける**
今回、デザイン修正をきめ細かく対応しすぎたことで、開発に渡すフェーズになってもデザインがFIXできず、スケジュールが遅延してしまいました。そんな折、シニアのデザイナーの方にアドバイス頂いたのは、
「開発スケジュール的に間に合わない時はデザインではなく開発のフェーズで対応してもらう」ということでした。
イラストは難しいですが、レイアウトやボタンの追加、テキストの追加はデザインがなくとも開発フェーズで対応可能です。
また、Webやアプリの場合、解決方法が平面的なデザインではなかったという場合もあります。
（レスポンス速度、モーダルの出し方、コンテンツ内容など）
もちろん開発側との交渉や調整は必要ですが、必ずしもデザインを完璧に！という頭でいなくても進められることを学びました。

**4.修正、変更によるデザインや開発への影響を考える**
依頼側の要望の中には、「このくらいだったらすぐできますよね」「いい感じにしてください」みたいな言われ方をされるものもあります。
そう言われた時、デザイナーやエンジニアの方は「技術的には可能です」と答えるかもしれません。しかし、心の声はきっとこうです。

・でもめっちゃお金かかるよ
・でもめっちゃ時間かかるよ
・でも作っても意味なくね？
・でも正直作りたくないです

こういった依頼は「ギリギリに要件が決まって」「〆切まで時間がなく」「要件があとから二転三転する」という、
地獄のようなコンボで攻めてくる確率が高いため、デザイナーやエンジニアは恐れています。
そんな時、PMは詳細な技術の知識はなくとも、大まかなデザイン・開発のフローやデータの流れを理解し、
その仕様や変更を行うと部分なのか全体なのかどこに影響しそうか、予測を立てることが重要だと考えています。
そして、依頼側にお金と時間が膨大にかかることやどこにどんな影響があるかなどを明確に伝え、依頼側を納得させる力が必要です。

### まとめ
PMは、ドキュメンテーション、問題解決、ファシリテーション、交渉・説得など色々なスキルが求められます。
非エンジニア・非デザイナーだからこその経験を活かし、依頼側のビジネスや業務課題を向き合い、
HowではなくWhyに着目し共有することで最短距離で良いものが作れるということも学びました。
今回の学びを次のプロジェクトにも活かしていきたいと思います。

プロダクト筋トレコミュニティでは
プロダクトを作るために必要な知識は技術だけではなく、事業、ユーザー体験、チームのマネジメント、ドメインの知識などと多岐に渡ります。
そして、そのすべてに長けている人はほとんどいません。
「何を学べば良いかわからない」状態から「自分のレベルがわかる」状態へ、そして「弱みや強みを強化していく」状態へ。
プロダクトづくりに関する知識や考える力をつけるための思考の筋トレをプロダクト筋トレと呼んでいます。
社外の仲間と勉強、議論をし、よりよいプロダクトをつくる筋肉を伸ばしていきましょう。(引用：プロダクト筋トレコミュニティサイトより）
興味を持ってくださった方のご参加お待ちしております。
ご参加はこちらから→https://www.productkintore.org/

最後までお読みいただきありがとうございました。
Githubでpush、アクセストークンを用いた方法

# Github　push方法のまとめ　
最近pushする時のシステムが変わり、ユーザー名とパスワードを入れる方式から、アクセストークンを用いるものに変更がありました。備忘録としてアクセストークンを用いる方法を簡単に記録しようと思います。
gitを始めようとしている、最近始めた人向けの記事です。


## 説明することしないこと　
すること
git init の手順に従い、新しくレポジトリ作成
->アクセストークンを用いてリモートレポジトリを設定(Pushできるようにする)

しないこと　
git の詳しい説明
アクセストークンの入手方法


## Githubでレポジトリを作る　
トップページから　
Repositories -> new
で新しいレポジトリを作成できる。　
　
レポジトリの名前を決定できるので、任意の名前を入力し決定。　
するとレポジトリのページにとび以下のコードが表示される。　

```
echo "# create_test" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/{username}/{repository name}.git
git push -u origin main
```

基本的にはこのコードをコピペすれば良いのだが、上述したように仕様が変わったためこのままだと　
pushした時にエラーが起きる。そのためアクセストークンを入手する。　

## アクセストークン入手
入手方法などは以下のサイトがわかりやすいので参考にされたい。　
https://rfs.jp/server/git/github/personal_access_tokens.html

アクセストークンを入手できればあとは簡単で上記のコードを少し変更すれば良い。(上記のコードはレポジトリのページにアクセスすればみることができる)

下から2行目のコマンドを変更し、"://"の後にアクセストークンをコピペし"@"を挿入する。

```
echo "# create_test" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin https://{access token}@github.com/{username}/{repository name}.git
git push -u origin main
```
これをすることでリモートリポジトリにpushすることが可能になった。

# Git をこれから始める人へ　
この作業で自分のアカウントのレポジトリに自分のコードをpushすることができるようになった。　
git の細かい仕様や使い方はさておきとりあえず使えるコマンド集を下に載せておく。　

・変更をpushしたい　
git add .
git commit . -m "変更箇所のコメント"
git push origin main

・今の状態を保存しつつ、テストしたり試してみたい　-> ブランチ操作

ブランチを新しく作りそこに移動　
git checkout -b "新しいブランチ名"

既存のブランチに移動　
git swich "ブランチ名"


ブランチの統合　変更箇所の共有　
git merge

などです。ひとまずpushするだけでもヒストリ機能が結構便利だと思います。　

## アクセストークンの更新　
アクセストークンには有効期限があり、それをすぎるとGithubからメールが届く。　
その時はメールに従い、アクセストークンを再取得し、　
```
git remote set-url origin https://{new access token}@github.com/{username}/{repository name}.git

```
とコマンドを実行することでアクセストークンを登録することができる。




# まとめ　
最近仕様の変わったアクセストークンの簡単な使い方一例でした。役にたてば幸いです。
【備忘録】docker compose で バージョンを指定してmigrate

```bash
##バックグラウンドでdocker compose up
docker compose up -d

##サービス名を確認
docker compose config --service

##マイレーションファイルを生成
docker compose exec サービス名 bundle exec rails g migration テーブル名

##マイグレーションファイルのバージョンを確認
docker compose exec サービス名 bundle exec rake db:migrate:status

##対象のマイグレーションファイルを編集後テーブルを作成
##VERSIONはマイグレーションファイルを指定する場合にマイグレーションファイルのバージョン名を指定する
docker compose exec サービス名 bundle exec rake db:migrate:up VERSION=20221224101010

##特定のマイグレーションファイルをrollbackする(特定のテーブルを削除する)場合
docker compose exec サービス名 bundle exec rake db:migrate:down VERSION=20221224101010
2022年のAmazon DevOps Guruについて調べてみる

今年に入り、Guruの新機能が発表されていたようです。
今できる事を改めて調べてみました。

ちなみにforRDSについては以前簡単にさわった事があります！

Amazon DevOps Guru for RDSを使ってみる
https://qiita.com/zenden/items/774be6c0b2f6f9802b5e

### ■Amazon DevOps Guruとは

Amazon DevOps Guru は機械学習 (ML) を活用したサービスで、アプリケーションのオペレーションパフォーマンスと可用性の改善を容易に実現できます。
具体的には、ホストリソースの過剰使用、データベースのボトルネック、SQL クエリの誤動作など、パフォーマンスに関連するさまざまなデータベースの問題を自動的に特定して分析します。
そして問題が検出されると、DevOps Guruはその結果を DevOps Guru コンソールに表示し、Amazon EventBridge またはAmazon Simple Notification Service (SNS) を使用して通知を送信します。これにより、デベロッパーは課題を自動的に管理し、リアルタイムでアクションを取ることができるというものになります。

料金は1インスタンスにつき $0.0042/h

### ■対応リソースについて
昨年はforRDSについて記事を書きましたが、色々と対応範囲となるサービスも増えているようです。
以下に列挙します。

- Lambda : 関数	 
- S3 : バケット
- API ゲートウェイ : API パス/ルート
- Kinesis : ストリーム
- ALB : LoadBalancer
- NATGateway (VPC) : NatGateway
- CloudFront : 配信
- NLB : LoadBalancer
- DynamoDB ストリーム : ストリーム
- RDS : DBInstance
- DynamoDB : テーブル
- Redshift : クラスター、ノード
- EC2(ASG): インスタンス*
- Route 53 : HostedZone
- ECS : サービス**
- SageMaker : InvocationEndpoint
- EKS : サービス**
- SNS : トピック
- Elastic Beanstalk : 環境
- SQS : キュー
- ElastiCache : ノード
- Step Functions : アクティビティ、StateMachine
- OpenSearch Service : ノード
- SWF : ワークフロー、タスク


### ■Amazon DevOps Guruの新機能
新機能についてですが、「Log Anomaly Detection and Recommendations」という名前で発表されました。
アプリ内の関連するログから異常を発見し、問題を解決するためのターゲットとなるレコメンデーションを得ることができる、という事で発見できるレベル感次第では運用に大きく役立つのではないかと考えられますね。

またその他には下記のような情報がありました。

・レイテンシーの増加、エラー率、リソースの制約などの異常を特定し、原因と解決のために実行可能な推奨事項をアラートとして通知する
・例外キーワード、数値異常、HTTPステータスコード、データフォーマット異常などを検出可能

### ■コンソール画面を見てみる

こちらはダッシュボードのトップになります。
現在はいずれのリソースも分析されていない状態になります

![ダッシュボードScreenshot 2022-12-24_09-18-39-066.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/f8997916-dff9-ba91-ba86-890e4097267e.png)

「分析されたリソースの編集」にてどのリソースをアナライズするのか選択可能です。
全リソースを選択する事もでき、タグにより選別する事も可能となっています。
なおタグには「Devops-Guru-」を含む必要があります！

![タグ登録前Screenshot 2022-12-24_09-15-10-448.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/d2657c1e-a35c-7bea-309c-fac11d3e2da8.png)

アナライズ後…

![アナライズ結果Screenshot 2022-12-24_10-51-11-863.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/aff9e060-b556-f7d6-7c97-5a24ee58a047.png)

前回はRDSのみでしたが、ELB、SNSが分析の対象として選択する事ができました。
今回はここまでで、また実際どのような検知が可能なのか検証を進めていきたいと思います。

### ■最後に
サーバー運用においてのトラブルシューティングでは、根本的な原因特定に辿り着くために長い時間や豊富な経験など、様々な要素が必要になっています。
実際の運用でもこのような要素は運用者にとって大きな負担になってしまう場合も少なくないと思われるので、GuruのようなAWSサービスを上手に用いて、運用改善を目指したいですね。
Reactのテストだけ動かなくてデバックした時に考えたこと

Reactのアプリをブラウザで確認した際にブラウザは思った通りの挙動をしたのですがテストだけ`FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory`と出てしまったときのデバック記録です。

結論から言いますとuseEffectの第二引数の[]をつけ忘れたことに起因するエラーでした。

# 試してみたこと１
Dockerのメモリを増やしてみました。

- なぜやったか

エラー文内に`heap out of memory`とあるので素直にメモリ不足と仮定してメモリを増やした。
今思うと、メモリが足りないではなくメモリをたくさん食いすぎてるロジックを仮定するべきであったと思う。

# 試してみたこと２

テストケースを減らして、一つ一つのテストケースでエラーを起こすか確認

- なぜやったか

どのテストケースが失敗の要因か確認するため

結果
1ケースの場合はどのケースでも成功する。複数ケースの場合は必ず上記のエラーになるとわかった。

# ここで改めて使っている関数のDocumentを読む

ここで、useEffectの引数は２つなのに一つしか指定していないことに気が付く。Reactの[公式DocumentのuseEffect](https://ja.reactjs.org/docs/hooks-reference.html#useeffect)では

> デフォルトでは副作用関数はレンダーが終了した後に毎回動作しますが、特定の値が変化した時のみ動作させるようにすることもできます。

とあります。つまり値が変化する度にuesEffect関数が呼び出される状態になっていたのです。
しかしながら、無限ループを抑制する機能（？）がブラウザにはついていたので一見ブラウザではうまく動いているように見えていたというわけです。


# こういうことが起きないためにすること

**Linterを入れましょう**
これにつきます。異論は認めすが「現代においてLinterを入れないのはただの怠慢でぶっちゃけダサいだけです。」

見たことがないエラーが出たら、変なSyntaxエラーであるケースが多いと思います。使ってる関数の引数の数が足りているかなどを重点的に確認していくといいでしょう。

あと、困ったときは人にペアプロやコードレビューを頼むと、違う視点からの意見をもらえ早く解決することができることが多い印象があります。
フロントエンドエンジニアがこれだけは知っておいて欲しい ~認証について~

## はじめに

ユーザー認証があるサービスが多いかと思います。
個人情報に直結するところなので、エンジニアが気を張り巡らせないといけないところですよね。

最近はバックエンドやブラウザ、サーバーの仕組みを知らなくてもサイトが作れちゃったりするので、**認証みたいな難しいことはちょっと苦手**、、と思っている方もいるかと思います。

でもやっぱり、認証処理ってフロントエンドも関わってくるのでフロントエンドエンジニアは知っておくべきだと思うんです。

なので今回は重要な部分に絞ってお話しできればと思います。

## トークンについて

認証に必要な**トークン**。
多くの場合`jwt`というものを用いてバックエンドとやり取りを行います。
でも、この`jwt`という正体がわからないんですね、、

フロントエンドエンジニアが知っておくべきなのは、以下のようなことかなと思います。

- `[ヘッダ].[ペイロード].[署名]`という情報がBase64でエンコードされている
- Base64というのはただのencodeなので、[jwt.io](https://jwt.io/)などで簡単にdecodeできる
- `ヘッダー`というところに暗号化方式などの情報が入っている
- `ペイロード`というところにユーザーの情報が入っている
- `署名`が秘密鍵で暗号化されたもので、キーを持たないと復号はできない
- `署名`の部分はフロントエンドでは、復号はできないものの、暗号化方式によっては、公開鍵があれば、値の検証はできる場合がある

一番下の、暗号化方式みたいな話は難しいかと思いますが、いちいちサーバーサイドにverifyTokenをしにいかなくても、公開鍵さえフロントエンドに持っていればユーザーの検証が行えるよ
というものですので、できれば知っておいて欲しいなと思います。

## 通信方法

トークンというものの正体がなんとなくわかれば、あとはどうやってバックエンドに渡すのかという話ですね。
jwtをHTTP通信のリクエストヘッダーに付与するのが一般的かと思います。

これはバックエンド側の要件によるのですが、多くのAPIでは

```
Authorization: Bearer <token>
```

のように付与することが多いかと思います。
tokenのところは先程のjwtを指定することが多いですね。

## 保存場所

いくつか保存場所はあるのですが、セキュリティ要件によって保存できる場所が違ったりします

- Indexed DB、Local Storage
- Session Storage
- On memory
- Cookie

一番おすすめなのは`httponly`なCookieに保存してしまうことです。

### httponlyなCookieとは？

Cookieというのはなんとなくわかるので割愛しますが、Cookieに値を格納する際、httponlyというオプションをつけることができます。
名前からはhttp通信で使えるのかなとか思ってしまいますが、これは**JavaScriptからのアクセスを禁じる**というオプションになります。

JavaScriptからのアクセスを禁じるということは、つまり、サーバーサイドでのみアクセスができるCookieということですね。
クライアントサイドではアクセスできなくなるため、XSS（クロスサイトスクリプティング）による攻撃をされてしまった場合の予防になるということです。

### JavaScript側でアクセスできないとなると、クライアントサイドでは認証情報を入手できないの？

SSRしている場合はサーバーサイドで認証を処理して、必要なものをクライアントサイドに渡す。
ということをする必要があります。

Next.jsなどを使っているのであれば、`getServerSideProps`などで処理して、propsとして渡します。

ただし、tokenを直接渡してしまうというのは、結果XSSなどによる抜き取りを許容しているのに近い状態になってしまうため、データフェッチなどはサーバーサイドで行い、必要なデータのみ渡すのが一番良いかなと思います。

## まとめ

今回はフロントエンドエンジニアが知っておいて欲しい認証の仕組みみたいなところを記事にしました。

フロントエンドからエンジニアになった人にはこの辺りは結構難しいと思いますが、ぜひ頑張ってチャレンジしてみてください
【備忘録】docker compose で rails c コマンド

```bash
##バックグラウンドでdockerを起動
docker compose up -d

##入りたいコンテナ名を確認
docker ps -a

##コンテナに入る
docker exec -it コンテナ名 /bin/bash

##shで入る場合
docker exec -it コンテナ名 sh

##railsコンソールを開く
rails c

##railsのコンソールが起動
irb(main):001:0>

##Modelのテスト(例)
モデル名.find(1)
25. FortLearnerを書いていて思ったこと

# FortLearnerを書いていて思ったこと
　FortLearnerを作成し始めてから思ったこと、今回アドベントカレンダーに初めて参加してみて思ったことなどを書こうと思います。ただの感想文（ポエム？）です。

# アドベントカレンダーに参加して
　一人ですべての記事を書くのはかなりきついですね。4月ごろに思い立ち、１日づつ何を題材に書こうかというのを決定しました。決定木の記事はすぐに着手して４月中にはほぼ下書きが終わっていた記憶しています。それ以降の記事については延び延びになって結局11月末に10記事程度しか作成できませんでした。それ以降は土日に記事を書いたりしていたのですが、12月19日には完全にストックが切れてしまい、毎日夜更かしして書いていました。

　記事を書くというのはやはり自分の中で論理の流れができていなければならないはずですが、個々のトピックだけがのこっている状態では自分が何を書いているのかがごちゃごちゃになってしまいました。とりあえず実装でき、既存実装と比較して同じような性能が出ていればいいやという気持ちでやっていたのがいけませんでした。1年後の自分は他人というのをもう一度思い出して、設計書とでもいうべきノートを今後は作成していきます。

　まともな記事を書くときには記憶だけを頼りに書くのではなく、現在の環境についても検証したり、そういえばきちんと確認していなかったなという部分もキチンと調査しなければならないのを改めて思いました。実装なしでもひと月に1本かければよいほうだと思うので（ただ実装しないと多分理解したつもりにもなれない）、2年分くらいのストックを使った今年と違い来年は多分一人でカレンダーを埋めきれないので参加しないつもりです。Fortranのカレンダーのほうで日程が空いていれば参加させていただこうと思います。


# FortLearnerを書いていて思ったこと
　1日目の記事でも書いたと思いますが、最初は機械学習アルゴリズムの動きを理解したいと思って始めました。初めて決定木のアルゴリズムを書いたときには計算量を考えることもまったく知りませんでした（各種ソートの計算量についても知りませんでした）。初めに実装してみて処理時間を測定してみると、Scikit-Learnと速度に全く歯が立たず、そもそもどこが遅いんだろうということもわからない状態でした。それからソート関数を調べるうえで、計算量という概念を知り、趣味でも仕事でも毎回計算量を考えるようにしました。そうすると一目見て、というわけにはいきませんが、どこが重そうかがなんとなくわかるようになった気がします（結局測定するわけですが）。

　遅いのであれば、高速化するためにどのようなアルゴリズムを用いればよいかも調べたり、メモリアクセスが良くないのかなども考えるようになりました。一番コードを考えるうえで成長したと思ったのは、同じ入出力のコードでもいくつもの方法を考えられるようになったことです。その時点ではもちろん時間もメモリ使用量もなにも考えていないため、とりあえず一番良さそうなのを実装しますが、手段が増えるのはいいことだと思います。

　簡単な例題からでも競技プログラミングからアルゴリズムを学びたいと思うようになりました。おそらく応用方法が浮かぶまでは長いですが、これも手段を増やすことになると考えているからです。アルゴリズムを学ぶ中でも、さらにこんな書き方があるのかと学べたらと思います。

# 今後の実装予定

* Classifier
    * 回帰用のアルゴリズムがほとんどなので、今後はもう少し分類用のアルゴリズムも実装していきます。特に決定木はRegressorのみです。SVMは回帰側の実装を調査中ですが、簡単に見た限りでは式変形も特に難しくなさそうです。
* AutoGradの3次元Tensorへの対応や、Layerの追加
    * 畳み込みニューラルネット用のConvolutional Layerは未実装なので追加したいです
    * 例えばPrametricReLUなど
    * RNN、GPUなど
* 速度＋精度検証用のスクリプト
    * 今回は一部のアルゴリズムしか速度検証として載せられませんでした。また、精度もほぼ乗せられていないので（以前検証した際にほぼSklearnと同じだったため保存していなかった）、それを比較できるようなスクリプトをきちんと作成したいです。
* 非深層学習系の時系列用のアルゴリズム
    * 状態空間モデル、自己回帰モデルなど基本的なものから進めたいと思っています。
    * クラスタリングではKshape
    * Change-point Detectionなど

以上です。これからも細々と機能を追加していきたいです。
Github Actions で、特定の文字列をファイルが含んでいる場合に CI を落とす

下記は console.log() , FIXME を含んでいたら CI を落とす例。

検索ワードやディでクトリは適宜書き換えてください。

```yaml
name: NG words

on: [push, pull_request]

jobs:
  check-console:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - run: |
          if grep -rE "console\.log\(" ./src; then
               exit 1
          else
              echo "All good"
          fi
  check-fixme:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - run: |
          if grep -rE "FIXME" ./src; then
               exit 1
          else
              echo "All good"
          fi

```
M5STACK BASIC タイマー割り込みの精度

計測的な用途で，タイマー割り込みを使ってみました。uiflowでプロトタイプし，thonnyで仕上げてM5に転送して使います。手軽でいいです。

```main（抜粋）.py
@timerSch.event('timer')
def ttimer():
  global s
  s=s+1

s=0
timerSch.run('timer', 1000, 0x00) # 変数sには経過時間（秒）が入るはず...
```

M5をWiFiに接続できない環境でしたので，これを選択したのですが，数分とか数時間使うとどうもずれているようでした。

WiFiに接続できる環境で，NTPと比較してみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/8a17179b-e5d0-8974-7ac3-5b5a780309ba.png)

経過時間 19611 秒，Timerでは442回カウント少なかったようです。2.3%ほど指定した1秒より長いようですね。

タイマーの時間を2.3%減らしてみました。

```main（抜粋）.py
a = 1000 * (1 - 442 / 19611)
timerSch.run('timer1', a, 0x00)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/d10fecf8-4bf7-b6a5-c3dd-924b42449eb9.png)

いい感じです。ただ，割り込みじゃないときの負荷によって，変わるのかもしれません。

さらに調べていくと，経過時間を知るだけなら `utime` モジュールが使えそうです。utimeとNTPで比較してみました。

```main（抜粋）.py
import utime
u0=utime.ticks_ms()/1000 # 最初の時を保存
# 中略
u=utime.ticks_ms()/1000-u0 # 経過時間
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/c4d0b3cb-d40e-ea14-49e1-97f54a6c004e.png)

はい。こちらのほうがいいですね。BASICはRTCを持ちませんので，WiFiを使えない場合はutimeを使うようにしてみます。

（補足）Core2も，タイマー割り込みは2.6%ほど遅くなっていました。「そういうもの」なのかもです。
Playwright(.NET)でテストコードの実現方法に困ったときに見返す

# 概要
最近Playwrightでテストコードを書くことが増えてきました。
API仕様から目的の操作を探すの大変、よく使うものはいつでも見直せるようにしたいと思い整理してみました。

こんなことないですか？
テストケースも決まりやりたいこともまとまっていて、目の前の画面に表示される要素をテストコードで操作したいだけなのにできない、なんでなん？と

手動では再現簡単なのに、テストコードとしてどう実現するか悩む時間が惜しい方に役立てばと思います。他にも実現手段はあると思いますが、あくまで一例です。

本記事は、APIをどう使うかに特化したものため、Playwrightを少し触ったことある人向けになります。

# よく使うメモ
### エレメントの指定方法
全体的に共通するのが目的のエレメントを指定する方法です。例えば、何らかのエレメントをクリックした場合の様々な指定方法

```C#
//class属性を指定する場合
await Page.ClickAsync(".hogehoge");
//Id属性を指定する場合
await Page.ClickAsync("#hogehoge");
//buttonタグのname属性を指定する場合
await Page.ClickAsync(@"button[name=""hogehoge""]");
//inputタグのid属性を指定する場合
await Page.ClickAsync(@"input[id=""hogehoge""]");
//複数存在するクラス名の1番目を指定する場合(※インデックスは1始まり)
await Page.ClickAsync(".hogehoge:nth-of-type(1)");
//特定の表示文字列をもつクラス名を指定する場合
await Page,ClickAsync($@".hogehoge:has-text(""部分一致もできます"")"))
```

### 基本操作
何かしたいときの基本操作
```C#
//何かをクリックしたいとき
await Page.ClickAsync("#hogehoge");
//何かを入力したいとき
await Page.FillAsync("#hogehoge", "test");
//何かをホバーしたいとき
await Page.HoverAsync("#hogehoge");
//何かをフォーカスしたいとき
await Page.FocusAsync("#hogehoge");
//何かをチェックしたい
await Page.CheckAsync("#hogehoge");
//何かをアンチェックしたい
await Page.UncheckAsync("#hogehoge");
//ファイルをアップロードしたい
await Page.SetInputFilesAsync("#hogehoge", "ファイルパス");
```

### あるエレメントの表示/非表示
あるエレメントが表示/非表示になるまで待ちたい
```C#
//何かを待ちたい
//(第2引数のオプションで、attached, detached, visible, hiddenが選べるので表示を待ちたいのか非表示になるのを待ちたいのか利用シーンに合わせて)
await Page.WaitForSelectorAsync("#hogehoge", new PageWaitForSelectorOptions { State = WaitForSelectorState.Visible }); 
```

### 画面表示情報の取得 
画面に表示される情報を取得したいときに使う
```C#
//チェックボックスのチェック状態を取得
await Page.IsCheckedAsync("#hogehoge")
//ある要素に表示されているテキストの取得
await Page.TextContentAsync("#hogehoge")
//入力したテキストの取得
await Page.InputValueAsync("#hogehoge");
//あるクラス名の要素を取得したい
await Page.QuerySelectorAsync("#hogehoge")
//あるクラス名の要素を一括取得したい
await Page.QuerySelectorAllAsync(".hogehoge")
//表示文字列から自身のエレメントのId属性を取得したい
await Page.GetByText("表示名称").GetAttributeAsync("id");
//ある要素のクラス名を取得したい
await Page.GetAttributeAsync("#hogehoge", "class");
```

### selectの操作
ドロップダウンで表示されるselectタグに対する操作
```C#
//選択肢を選ぶ(第２引数のオプションでlabel, value, indexが選べる、選びたい属性にあわせる)
await Page.SelectOptionAsync("#hogehoge", new SelectOptionValue { Label = "表示名" });
//選ばれている表示名を取得したい(第2引数のtextContentをvalueにすればvalueがとれる)
await Page.EvalOnSelectorAsync<string>("#hogehoge", "el =>el.options[el.options.selectedIndex].textContent");
```

### 画面遷移
画面遷移する
```C#
//現在のURLを取得する
Page.Url
//どこかのURLに遷移したい
await Page.GotoAsync("https://～～～～");
//何かをクリックして新しく開く別タブのウインドウを操作したい
var newPage =await BrowserContext.RunAndWaitForPageAsync(async () =>
{
	await Page.ClickAsync("#hogehoge");
});
```

# おわりに
普段使うものを挙げてみました。意外とたくさんある。
API仕様は大量に書いてあるので、自分のやりたいことがどれで実現できるのか探すのになかなか苦労するときもあります。
他にもAPIはたくさんあって、知れば効率よくテストコードもかけるんだろうなと思います。
今後もいろいろな使い方を勉強していきたいと思います。
潤さんの「コーディングインタビュー素数を判定するコードを実装しろ」を試してみました。

参照先：
https://www.youtube.com/watch?v=dgxEsRC6PNI

潤さん曰く、シリコンバレーのコーディングテストはこれよりもっと難しいらしいです。
私もコーディングテストを導入できない日本のＩＴ企業を憂いてます。



## 素数を判定するpythonコード

```main.py
"""
Input
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]

Prime number
[2,3,5,7,11,13,17,19]

Non Prime number
[1,4,6,8,9,12,14,15,16,18,20]

"""

# 素数を判定する関数(1以下の値は素数ではないのでfalseを返す)


def is_prime_v1(num: int) -> bool:
    if num <= 1:
        return False

    for i in range(2, num):
        if num % i == 0:
            return False

    return True


# 処理数を減らして速度を上げた素数判定関数
def is_prime_v2(num: int) -> bool:
    if num <= 1:
        return False

    for i in range(2, math.floor(math.sqrt(num) + 1)):
        if num % i == 0:
            return False

    return True
    # >>> print([i for i in range(2, math.floor(math.sqrt(37) + 1))])
    #[2, 3, 4, 5, 6]


# 本ファイル実行時に出力
if __name__ == '__main__':
    # print(is_prime_v1(10))
    import math
    import time
    import random
    numbers = [random.randint(0, 1000) for _ in range(10000)]

    start = time.time()
    for num in numbers:
        is_prime_v1(num)
    print('v1', time.time() - start)

    start = time.time()
    for num in numbers:
        is_prime_v2(num)
    print('v2', time.time() - start)


```


## unittestするpythonコード

```unittest.py

import unittest

# 多数の関数を作るので別名付与
from main import is_prime_v1 as is_prime


class primeTest(unittest.TestCase):
    # Prime numberでtrueを返さなかったら失敗
    def test_is_prime_ok(self):
        for i in [2,3,5,7,11,13,17,19]:
            self.assertTrue(is_prime(i))


    # Non Prime numberでFalseを返さなかったら失敗
    def test_is_prime_no(self):
        for i in [1,4,6,8,9,12,14,15,16,18,20]:
            self.assertTrue(is_prime(i))


    # マイナス値でFalseを返さなかったら失敗
    def test_is_prime_negative(self):
            self.assertTrue(is_prime(-1))


    # typeerrorをraise
    def test_is_prime_typeerror(self):
            with self.assertRaise(typeError):
                is_prime('string')


# 本ファイル実行時に出力
if __name__ == '__main__':
    unittest.main()
```
[Linux] Opencvをダウンロードし、ビルドするときのメモ

# 手順
※今回は、例として、opencv 3.4.6のダウンロード、および、ビルドを行う。
※Ubuntu 20.04を使用。ほかのバージョンのubuntuでも同じようにできるはず。

適当なカレントディレクトリで以下のコマンドを実行
```
wget https://github.com/opencv/opencv/archive/refs/tags/3.4.6.tar.gz
tar -zxvf 3.4.6.tar.gz
rm 3.4.6.tar.gz
cd opencv-3.4.6/
mkdir build
cd build
cmake .. -DBUILD_SHARED_LIBS=OFF
make
```
cmake .. 実行時の-Dオプションは、[こちら](https://atmarkit.itmedia.co.jp/ait/articles/1704/10/news134.html)が分かりやすい。
年間120本のブログ発信を実現した3つの工夫

## はじめに
本記事は[リンクアンドモチベーション Advent Calendar 2022](https://qiita.com/advent-calendar/2022/mcs)の25日目です🎄

リンクアンドモチベーションは2022年1月から[テックブログ](https://link-and-motivation.hatenablog.com/)をはじめました。
この1年、テックブログ運営を通じて以下のような成果を創出しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20310/90963f6c-d8bc-c199-fbbd-2b2969df1724.png)
本記事では、これらの成果創出にあたり工夫した点を3つに絞ってお伝えします。

## 1. 社内のアウトプット量を増やす
テックブログ立ち上げにあたり、社内のメンバーに「テックブログ書く上での一番の障壁は何か」をヒアリングをしたところ、「社外に発信するのはハードルが高い」という声が多く上がりました。そこで、「ハードルを思い切り下げて、アウトプットする習慣を体験してもらう」ことから取り組みました。

外部に公開されるテックブログにいきなり書くのはハードルが高いため、まずは社内でのアウトプット量を増やすことに注力しました。具体的には、Qiita Teamを導入して社内向けにアウトプットが出来る仕組みをつくりました。

Qiita Team導入を提案してくれたエンジニアの高い推進力もあり、「社内であればアウトプットしてみよう」というモメンタムをつくることができました。結果、開始4ヶ月（トライアル期間含む）でQiita Teamへの投稿数は200記事を超えました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20310/ad365a9c-be42-15a4-9198-c0867082448d.png)


社内のアウトプット量が増えたタイミングで、社内のQiita Teamに溜まった記事から「社内に留めておくのはもったいない記事」をピックし、執筆者に相談してテックブログへ転記するようにしました。これにより、「この記事でも外部に公開して良いのか」という基準が組織内で揃いました。結果、テックブログに書く心理的な障壁が下がり、徐々に「テックブログを書いてみようかな」という声が上がるようになりました。

Qiita Team導入の詳細に関しては宮田の記事をご確認ください。

https://link-and-motivation.hatenablog.com/entry/2022/08/05/172909

また、これらを取り組むにあたり、広木さんの記事を参考にさせていただきました。

https://newspicks.com/topics/dx/posts/26

## 2. アウトプットを社内に共有する
私たちはアウトプットがある度に、執筆者へのリスペクトを込めて社内のSlackで共有します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20310/339958dc-9609-a89c-0dc6-fc1eefe2ae57.png)
外部の方から反応(ブックマーク/SNS)を貰うよりも、社内の仲間が反応(スタンプ/コメント)することのほうがハードルは低いです。アウトプットしたものに反応があることで「また記事を書きたい」という執筆者の意欲に繋がります。

シンプルな取り組みですが、"全員アウトプット"の文化を支える大事な活動です。

## 3. "目的"を引き寄せる
アウトプットする目的は個々人で異なります。アウトプットする機会をつくるためには、自身に引き寄せて「なぜやるのか」を理解することが重要です。そこで、繰り返し"テックブログをなぜやるのか"を発信しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20310/522259ea-4418-e1ca-bc75-bc7c0daee2f1.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20310/30ee99f9-f273-1aaa-5272-aba4330fe39d.png)

組織(All)と個人(One)、それぞれで目的を言語化し、「組織のためでも個人のためでもどちらでも良い。自分なりの目的を持ってアウトプットして欲しい。」ということを繰り返し伝えました。他にも、1on1などで"なぜテックブログを書くのか"を思考してもらう機会をつくりました。

結果、以下のような目的を持ってくれるメンバーが増えました。

- 「採用やブランディングに貢献したい」
- 「チームの取り組みを発信することでメンバーに自信をつけてもらいたい」
- 「自身の市場価値を高めたい」
- 「登壇に向けてアウトプット力を磨きたい」
- 「アウトプットを通じて学びを深めたい」

アウトプットする目的を引き寄せたメンバーの執筆意欲は高く、組織に数人いるだけでアウトプットが加速することを体感しました。

## おわりに
いかがでしたでしょうか。
引き続き、テックブログにて私たちの取り組みを発信していきますのでぜひ登録をお願いします！

https://link-and-motivation.hatenablog.com/
ハングルのデジタル化の歴史

# 前書き
街中のハングルを見て「読めない何か」と思っているのではないでしょうか。また、電車の案内LCDに表示されているのを見て「ふーん」って思っているだけではないでしょうか。実は、その文字を表示するためにたくさんの人の努力してきました。本記事では、その人たちの努力について書いてみようと思います。

# そもそもハングルとは
## 歴史
ハングルは、1443年に李氏朝鮮の国王、世宗によって公布されたとされています。当時の正式名称は「訓民正音」でした。

## 構造
ハングルは子音ㄱㄴㄷㄹㅁㅂㅅㅇㅈㅊㅋㅌㅍㅎと母音ㅏㅑㅓㅕㅗㅛㅜㅠㅡㅣの組み合わせにより文字が構成されます。子音単体の組み合わせとしてㄲㄸㅃㅆㅉが存在し、母音単体の組み合わせとしてㅔㅐㅚㅙㅟㅞㅢが存在します。しかし、ハングルはアルファベットのように、これらを横に並べて書くものではありません。「一音節＝一文字」という原則があり、これらの要素を組み合わせて文字を構成します。

いくつか例を挙げてみます。
- ilbon ㅣㄹㅂㅗㄴ 일본
- hanguk ㅎㅏㄴㄱㅜㄱ 한국
- euisa ㅡㅣㅅㅏ 의사

ㅇは「子音入る場所だけど子音ないよ」との意味なので、発音しません。まぁ、パッチムに来ると違いますが...
こういう風に、文字の要素を組み合わせて文字を構成します。できるパターンとしては

- 子音＋母音（例：가）
- 子音＋母音＋子音（例：안）
- 子音＋母音＋子音＋子音（例：밝）

が存在します。ハングルのデジタル化が難しかったのはこれが原因でした。

# 組合型と完成型
## 二つの違い
組合型は言葉の通り要素ごとに情報を保持し、表示時にハングルを組み合わせる方式です。割り当てる文字コードが少なくて済む大きなメリットがありますが、ハングルのためだけに組み合わせて出力するロジックが必要となる大きな欠点があります。ハングルのような文字は世界的に見ても珍しいので、高々7000~8000万人が使うような文字（北朝鮮はインターネット世界であまりカウントする意味がないから実質5000~6000万人程度）のためにOSがそれに対応するのも難しい話でした。

完成型にこのような問題点はありません。組合型とは違い、あらかじめ組み合わせた文字に文字を割り振る方式です。文字コードが膨大になる欠点がありますが、他の文字と共通した実装ができる大きなメリットがあります。特殊な実装がいらないことから主流は完成型になりました。

## EUC-KRの悲劇
EUC-KRはEUC-JPと同様、２バイトからならエンコードシステムです。2バイトという限界もあり、ハングルの全ての組合せ（1万越え...）を表現するのは無理がありました。ハングルだけならまだしも、漢字まで含まれたエンコーディングなので、全ての組合せを表現するのは極めて難しく、「韓国語ではあり得ない」ハングルの組合せを排除した２０００種類あまりのハングルを採用しました。しかし、問題はまもないうちに現れます。

「涼宮ハルヒの憂鬱」という作品をご存知でしょうか。登場人物に「キョン」がいますが、「韓国語」ではあり得ない組み合わせだったため、排除されました。しかし、「キョン」は「キョン」なので表記する必要があり、別に発音できない文字でもなかったので、「쿈」と表示する必要があったのです。結局出版社は「？」のまま出版したり表現できた「쿄」に「ㄴ」を下に無理やり付け加えて表現していました。

まだこれだけだったらよかったかもしれません。外国の人名・地名を表記するのに難があり、それは韓国語話者が発音できないものでもなかったのです。涼宮ハルヒの憂鬱が出た時はUTF-8は存在したと思いますが、当時の出版社の事情によりPowerPCでしか動かない超古いソフト「Quark3.3K」で作業していたため、EUC-KRで作業するしかありませんでした。

余談ですが、EUC-KRでは漢字と仮名は表現できたものの新字体の漢字は表現できませんでした。当時の韓国のアニヲタはEUC-KRにしか対応してない字幕フォーマットを使っていたため、新字体を無理やり旧字体に変換する必要がありました（例：　体育→體育）

## Unicode時代、想定される組み合わせは表現できるようになる
EUC-KRは登場時から問題が多かったのですが、Unicodeの登場により文字の表現に３バイトを用いることになり、文字コード領域に余裕ができ、1万通り程度の組み合わせを無理なく表現できるようになりました。しかし、発音できない文字も多数含まれており、「뷁」がその一例です。

# 終わりに
本記事ではハングルのデジタル化の歴史について少し触れてみました。「情報量足りないな」と思うかもしれませんが大目に見てください。
ある人は「電車に出てくる迷惑な文字」と思うようですが、「少しでもいいから興味を持ってほしい」と思ってこの記事を作成しました。これでハングル及びその文字のデジタル的な表現方法について興味持ってくれたら嬉しいです。
今日のElixirSchoolメモ17「Erlangとの相互運用」

Elixir Schoolの学習メモです。

https://elixirschool.com/ja/lessons/intermediate/erlang

## 概要

Erlang VM(BEAM)の上で開発することによって得られる利点の1つに、既にある大量のライブラリが利用できるということが挙げられる。
相互運用できることで、そうしたライブラリはErlangの標準ライブラリをElixirコードから活用することができる。

## 標準ライブラリ

Erlangの豊富な標準ライブラリはアプリケーション内のどのElixirコードからもアクセスすることができる。
Erlangモジュールは`:os`や`:timer`のように小文字のアトムで表される。

```elixir
iex(1)> defmodule Example do
...(1)>   def timed(fun, args) do
...(1)>     {time, result} = :timer.tc(fun, args)
...(1)>     IO.puts("Time: #{time} μs")
...(1)>     IO.puts("Result: #{result}")
...(1)>   end
...(1)> end
{:module, Example,
 <<70, 79, 82, 49, 0, 0, 7, 104, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 243,
   0, 0, 0, 26, 14, 69, 108, 105, 120, 105, 114, 46, 69, 120, 97, 109, 112, 108,
   101, 8, 95, 95, 105, 110, 102, 111, 95, ...>>, {:timed, 2}}
iex(2)> Example.timed(fn (n) -> (n * n) * n end, [100])
Time: 5 μs
Result: 1000000
:ok
```

Erlangの利用可能なモジュールの一覧はErlang Reference Manualを参照する。

https://www.erlang.org/doc/apps/stdlib/

## Erlangパッケージ

Erlangライブラリも組み込むことができる。

```elixir
def deps do
  [{:png, github: "yuce/png"}]
end
```

## 注目すべき違い

### アトム

Elixir:

```elixir
:exmample
```

Erlang:

```erlang
example.
```

### 文字列

Elixirの文字列はUTF-8でエンコードされたバイナリを意味するが、
Erlangでもstringはダブルクォートを使って表すが、文字リストを指す。

古いErlangライブラリではバイナリに対応していないものも多いため、
Elixirの文字列は `to_charlist/1` 関数を用いて、文字リストに変換する必要がある。

### 変数

Erlangでは、変数は大文字で始まり、バインドし直すことができない。
do〜 系Junitについて

## はじめに
voidメソッドに対してmockを設定するにはどうすればいいのだろうか。
when return出来ないし〜と悩んだ際の調べた内容について記載します。

## こんな人に読んでほしい
voidメソッドのJunitいまいち書き方がわからん方。


## do〜の種類
結論、do〜のmockitoを使ってvoidメソッドのmockを設定することができます。

以下今回テストしたいvoidメソッド
```java
public class MyList extends AbstractList<String> {
 
    @Override
    public void add(int index, String element) {
        // ~~~
    }
}
```


### 1.`doNothing`
    - 文字通り何もしてほしくない時に使います。
    - doNothing（）は、voidメソッドに対するMockitoのデフォルトの動作になります。

基本的な書き方は以下です。
```java
doNothing().when(sampleService).methodA(any());
```

```java
@Test
public void whenAddCalledVerified() {
    MyList myList = mock(MyList.class);
    //指定してもしなくても動く
    doNothing().when(myList).add(isA(Integer.class), isA(String.class));
    
    // 呼出
    myList.add(0, "");
 
    // 検証
    verify(myList, times(1)).add(0, "");
}
```
voidメソッドについて何もしない（デフォルトの動作）をしてほしい時、上記のように設定できます。
ただ、最初に記載しているように、**doNothing()** は、voidメソッドに対するMockitoのデフォルトの動作ですので、
doNothing()を指定しなくてもデフォルトで動きます。


### 2. `doThrow`
    - エラーをvoidメソッドの中で投げて返してほしい時に使います。

基本的な書き方は以下です。
```java
doThrow(exception).when(sampleService).methodA(any());
```


```java
@Test(expected = Exception.class)
public void givenNull_AddThrows() {
    MyList myList = mock(MyList.class);
    doThrow(new RuntimeException()).when(myList).add(isA(Integer.class),isA(String.class));
 
    // 呼出
    Try{
        myList.add(0, null);
        fail();
    } catch() {
        // 検証
    }   
}
```
**doThrow** を使って、呼び出した時に、RuntimeException()を引き起こすような挙動は上記のように設定できます。




### 3.`doAnswer`
    - voidメソッドの中でやってほしいことがある場合に使います。
    - 例えば、引数で渡したものをvoidメソッドの中で更新したい時なんかに使います。
    

```java
@Test
void whenAddCalledAnswered() {
    MyList myList = mock(MyList.class);
    doAnswer(invocation -> {
        // 第1引数何かな？を取得
        Object arg0 = invocation.getArgument(0);
        
        // 第一引数を＋1 するように設定
        arg++;

        return null;
    }).when(myList).add(any(Integer.clas), any(String.class));
    int beforeNum = 5;
    myList.add(beforeNum, "answer me");
    // 検証
    ~~~
}
```
上記の書き方では、引数を **invocation.getArgument()**　で取得して、そいつを更新させるような設定をしてみました。
なかなか使う機会は少ないかもしれませんが。


## 1回目と2回目の挙動を変えたい時
`thenReturn()` は、1回目と2回目返すもの変えたい時以下のようにすれば、返却値を変更できまが、
```
when(sampleService.methodA(any())).thenReturn("1回目").thenReturn("2回目");
```
`do〜系` も呼ばれる度に挙動を変えることができます。  
今回の例で言うと、1回目、２回目は何もせず、3回目で例外を投げたい時、下記のようにかけます。
```
doNothing().doNothing().doThrow(new RuntimeException()).when(sampleService).methodA(any());
```



## 参考
https://qiita.com/fumu238/items/64c910bc36b051c6b976
https://www.baeldung.com/mockito-void-methods
ffmpegでwmvの音ズレを補正する

# この記事の内容

音声と映像に一定時間ずれのある（どんどんずれるのではない）wmvを、ffmpegを使用して補正する方法を記載しています。
    mp4の場合は、wma → aac、wmv → mp4 と読み替えれば行けるかも。

# 環境

- Windows10
- ffmpegをインストール済み

# 概略

1. 動画から音声と映像を分離する
2. 音声または映像の先頭を削る
3. 結合する

# 1. 音声と映像を分離する

以降の「ファイル名」は、拡張子を含めないものとする。

```bat
ffmpeg -i 入力動画のファイル名.wmv -vcodec copy -an 保存先とする映像ファイル名.wmv
ffmpeg -i 入力動画のファイル名.wmv -acodec copy -vn 保存先とする音声ファイル名.wma
```

※ffmpegは、指定した出力ファイルの拡張子で出力コーデックを判断しているようなので、拡張子が適切なものでないとエラーになる。

# 2. 音声または映像の先頭を削る

## 2-a. 音声が遅い場合

音声の先頭を削ることで、遅れを解消させる。

```bat
ffmpeg.exe -ss 取り込み開始時間 -i 音声ファイル名.wma -c copy 保存先とする補正後の音声ファイル名.wma
```

「取り込み開始時間」の単位は<b>秒</b>で、小数(0.1など)を指定可能。遅れ分の時間を指定すればよい。

## 2-b. 映像が遅い場合（※試してない）

音声の場合と同様。（拡張子だけが音声と異なる。）

```bat
ffmpeg.exe -ss 取り込み開始時間 -i 映像ファイル名.wmv -c copy 保存先とする補正後の映像ファイル名.wmv
```

# 3. 結合する

下記で結合できる。※補正後のファイルを入力として指定することを忘れずに。

```bat
ffmpeg -i 音声ファイル名.wma -i 映像ファイル名.wmv -vcodec copy -acodec copy 保存先とする結合後の動画ファイル名.wmv
```

音声と映像の引数に渡す順序は逆でもよい（はず）。

# 参考記事

 - [どんどん音がずれる動画の問題を無料で解消する！ - Qiita](https://qiita.com/yuki_shipcat/items/f8ae50990a7016f4114d)
すべてのエンジニアは『すずめの戸締まり』によって救済される

## 『すずめの戸締まり』が感動的なわけ

2022年11月11日に封切られた新海誠監督の最新作『[すずめの戸締まり](https://suzume-tojimari-movie.jp/)』。

大ヒットした『[君の名は。](http://www.kiminona.com/)』（2016）や『[天気の子](https://tenkinoko.com/)』（2019）に続き、今回の作品も100億円超えの記録的な興行収入が見込まれ、新海監督は国民的なアニメーション作家に位置したと言えるでしょう。

ただ、私自身としては、新海作品はすべて観ているものの、『君の名は』以降の作品は正直あまり好きではありません。多くの人に受け入れられる理由はわかりつつも、私個人の琴線に触れる内容ではなかったのです。

そのような経緯もあり、今回の『すずめの戸締まり』も、正直あまり期待せずに観に行きました。

しかし、エンドロールが流れ終わり、劇場に明かりがついたとき、自分でも意外なくらい感動していることに気づきました。実のところ、劇中のいくつかの場面では涙も流しています。

なぜ、ここまで心が動かされたのか、私自身もはじめはよくわかりませんでした。
その後、この理由の言語化を試みたところ、あるひとつの仮説にたどり着きました。

**『すずめの戸締まり』は、ソフトウェア開発の営みを描いている**

もちろん、この映画の核となるテーマは「災害」です。
ただ、改めてこの映画の内容を振り返ると、あたかもソフトウェア開発が構造的に抱える困難さについての物語のように読み取れてしまうのです。

というわけで、私と同じようにソフトウェア開発に従事されるみなさんと、この『すずめの戸締まり』の感動をわかち合いたく、Qiitaで映画の感想を書くという場違いなことを試みたいと思います。

*※以降は作品へのネタバレを一切配慮せず、鑑賞済であることを前提に詳細な説明を省くので、未鑑賞の方は先に映画館へ行くことをおすすめします。
また、新海監督の狙いとは意に介さない私見にすぎず、ましては映画の解釈を越えて現実の震災とソフトウェア開発を重ねるような意図がないこともご留意ください。*

## 私たちは負債と隣り合わせで生きている

『すずめの戸締まり』が描く「世界の構造」は、このようなものです。

    ・私たちが今生きている社会は、人々が忘れた歴史の上に成り立っている
    ・前者の社会は「現世=生の世界」、後者の歴史は「常世=死の世界」で、普段それらは違う時間軸に存在している
    ・この時の隔たりを「後ろ戸」がつないだとき、「生の世界」に「死の世界」が流れ込み、災害が起きる
    ・厄災は、誰かの命を犠牲にした「要石」で封じられるか、「閉じ師」によって未然に防がれる
    

つまり、私たちが満ち足りた生活を日々享受できているのは、ふだんは意識されなくても先人が犠牲を払いながら積み上げた過去のおかげであり、それと同時に私たちの日常というものは、忘れていた痛みをふと思い出すかのように、ある日突如としてその平穏が破壊されるリスクを常に抱えているものなのです。

人々で賑わう街の姿は、常に人々から忘れ去られた廃墟と隣合わせにあります。

もうおわかりのように、これはソフトウェア開発においてはついて離れない「技術的負債」の課題と、同じ構造と捉えることができます。

私たちがソフトウェアによって価値を享受できているのは、ふだんは意識されないが先人たちが積み上げてきたコードのおかげであり、それと同時にソフトウェアというものは、今では忘れ去られたさまざまな事情からトレードオフになった品質上の課題が、ある日突如として障害を引き起こすリスクを常に抱えているのです。

便利で素敵なソフトウェアは、常に忘れ去られた技術的負債と隣合わせにあります。

このように「ソフトウェア開発者が常々悩まされている困難」は、『すずめの戸締まり』では「日本人が無意識に抱いている不安」として描いているのです。

## 誰が障害を防いでいるのか

ソフトウェア開発の現場では日々エンジニアが「技術的負債」と戦っていますが、同じように『すずめの戸締まり』でも痛みや苦しみといった「死の世界」の象徴であるミミズと戦う「閉じ師」の姿が描かれています。

誰にも気づかれないなか、厄災を身を以て未然に防ぐ「閉じ師」。
社会を支えるあらゆるサービスの裏側で、バグと戦って障害を未然に防ぐ「ソフトウェアエンジニア」。
地味ながらも責務をまっとうする姿に、両者は重なって見えます。

また、『すずめの戸締まり』では、そもそもの「死の世界」の力を抑え込む「要石」という存在が登場します。
物語の序盤に「要石」は神様の化身であると説明されますが、話が展開するにつれ、自らの命を引き換えて戦う「閉じ師」たちの自己犠牲の果ての姿であることが示唆されます。

いささか大げさかもしれませんが、バグを潰しても潰してもコードが書き足されていく以上は根本的な解決はできず、負債化したレガシーコードそのものとの戦いに向きあわざるをえないエンジニアは、「かぎ師」と同じような宿命を背負った者たちのように思えるのです。


## そして救済される

このように『すずめの戸締まり』は、私たちの平穏な日常を脅かす存在に対し、人知れず戦っている使命を負った人々の姿を、ヒロイックに描いた物語とも言えるでしょう。

しかし、新海誠はこの物語の終わりに、さらなる仕掛けを用意しました。

主人公のすずめは日本列島を北上する旅を通し、現在と過去と2つの時間軸をつなぐ「後ろ戸」を閉じながら、そこで出会った「現在を生きる人々」に垣間見える「過去の痛み」と向き合うことで、人間的に成長していきます。

その最終局面で、すずめはいよいよ、自分が抱える過去の痛みを精算するため、自身の原風景かつトラウマの舞台に向かうことになります。

その地で、「現在のすずめ」は「過去のすずめ」に出会い、「過去のすずめ」が抱える痛みを癒やします。すると、同時に「現在のすずめ」も、これまで抱えてきた過去の痛みから開放されます。

ただ、そのとき、すずめは気がつくのです。ここまで過去の痛みに苦しんできた自分は、実は「未来」のすずめの声によって励まされ、すでに救われていたという事実に。

これにより、すずめが自身のあり方を、「過去の痛みにとらわれ、苦しんできた」ではなく、「未来を信じることで、痛みを乗り越えてきた」と捉え直したところで、物語は終結します。

新海監督が仕掛けたこのアクロバティックな反転に、私は心が救われたような気がしました。

ソフトウェア開発は、つねに技術的負債との戦いです。
孤独で、苦しく、先の見えない、忘れ去られた過去と戦いです。

ただ、負債は苦しむものではなく、乗り越えるべきものなのです。
未来へ継承されていくことを信じ、今までもこれからも価値を出し続けていく。
私たちは、過去にとらわれず、未来に励まされるべきだ。

そのように『すずめの戸締まり』を観たことで、私はくじけずにまた頑張ろうと思えたのです。