OmniAICreator/Qiita-1.07M huggingface dataset:
タイム インテリジェンス 関数を使う（SAMEPERIODLASTYEAR関数 ）

# はじめに

この記事は、[Microsoft Power BI Advent Calendar 2023](https://qiita.com/advent-calendar/2023/powerbi "Microsoft Power BI Advent Calendar 2023") の8日目の記事です。

https://qiita.com/advent-calendar/2023/powerbi

[^1]:「DAX Boot Camp」は、みんなで DAX の訓練(勉強)する勉強会です。通常は月に一度、土曜日の午後に実施されています。 

Power Pivot で[タイム インテリジェンス 関数](https://learn.microsoft.com/ja-jp/dax/time-intelligence-functions-dax "タイム インテリジェンス 関数")を使い時系列でのデータの集計や比較ができた時、「わー！すごく便利！」と、とても感激しました。

https://learn.microsoft.com/ja-jp/dax/time-intelligence-functions-dax

そこで、よく使ういくつかのタイム インテリジェンス 関数について、書きとめておきたいと思います。

まずは、本記事の **SAMEPERIODLASTYEAR関数** です。

# SAMEPERIODLASTYEAR関数 とは

https://learn.microsoft.com/ja-jp/dax/sameperiodlastyear-function-dax

>現在のコンテキストで、指定された dates 列の日付から 1 年前にシフトした日付の列を含むテーブルを返します。

# SAMEPERIODLASTYEAR関数 を使ってやりたいこと

ここでは、ある商品の売上データを合計し、前年の売上と比較したいと思います。

Excel の Power Pivot を使います。

👇こんな風に「売上合計」と「前年度売上合計」「売上前年対比」を並べて表示させたいと思います。

![001.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302412/6c465863-9c29-7ef8-a30c-4c8b1ef9a108.jpeg)

# 準備

■売上データ（ファクトテーブル）
2021年から2023年の売上データを用意します。
列「日付」と列「売上金額」のシンプルなデータです。

| 日付| 売上金額 |
|:-:|:-:|
| 2021/1/2 |61,500 |
| 2021/1/9  | 86,600|
|：|：|
|：|：|
|：|：|
</details>

■カレンダーテーブル
ファクトテーブルの売上データの日付に合わせてカレンダーテーブルは、2021年から2023年の3年間の日付で作成します。

| 日付| 年 | 月番号 | 月 | 年月 |
|:-:|:-:|:-:|:-:|:-:|
| 2021/01/01| 2021 | 1 | 1月 | 2021年1月 |
| 2021/01/02| 2021 | 1 | 1月 | 2021年1月 |
|：|：|：|：|：|
|：|：|：|：|：|
| 2023/12/31| 2023 | 12 | 12月 | 2023年12月 |

# データモデル

![003.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302412/ec157aac-c596-e38d-1fae-5eb661038fd8.jpeg)

:::note info
日付を**キー**にして、「カレンダーテーブル」と「売上テーブル」間に**1対多**のリレーションシップを作成します。
:::
# メジャーを作成する

## ■メジャー「売上合計」をつくる
まず、**SUM関数**を使ってメジャー「売上合計」を作ります。
```
合計金額:
=SUM([売上金額])
```
![003.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302412/ab8e184d-5e24-0d59-035e-349a7c904f45.jpeg)


## ■メジャー「前年度売上合計」をつくる
次に、**CALCULATE関数**と**SAMEPERIODLASTYEAR関数**を使ってメジャー「前年度売上合計」を作ります。
```
前年度売上合計
=CALCULATE(
  [売上合計],
  SAMEPERIODLASTYEAR('カレンダー'[日付])
  )
```
![004.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302412/deb42a04-0d99-9fc4-d4ca-c9caeda8c09b.jpeg)

## ■メージャー「売上前年対比」をつくる
最後に、メージャー「売上前年対比」を作ります。
「売上合計」を「前年度売上合計」で割れば「売上前年対比」が算出できるので、**DIVIDE関数**を使います。
```
売上前年対比
=DIVIDE([売上合計],[前年度売上合計])
```
![005.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302412/6db18b81-d1a1-1b20-5802-b27b1d501f91.jpeg)

# うまくいきました！

👇1年前の売上合計と前年度売上合計金額が同じであることが確認できます。
また、売上前年対比も正しく表示されています。

![006.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302412/c74e5e34-09fe-411a-f5ca-8add7aef3087.jpeg)

# ちなみに

メジャー「前年度売上合計」は**DATEADD関数**を使って作ることもできます。
```
前年度売上合計
=CALCULATE(
  [売上合計],
  DATEADD('カレンダー'[日付],-1,YEAR)
  )
```
次回は、**DATEADD関数**を使って2年前や1月前など任意の期間との比較をしてみたいと思います。

https://learn.microsoft.com/ja-jp/dax/dateadd-function-dax

# おわりに
[Power BI勉強会](https://powerbi.connpass.com/ "Power BI勉強会")のおかげで、2023年も楽しく学習を続けることができました。
いつも優しくアドバイスしてくださる勉強会の皆さん💕**本当にありがとうございます** :heart_exclamation:

https://powerbi.connpass.com/
アイデアの質が変わる！デザイン思考のHMW(HowMightWe)で課題解決を加速させよう


# ソフトウェア開発とデザイン思考

新しい取組を始める時、課題や問いに目を向けず、思いつきのアイデアから始めてしまうことはエンジニアであれば誰しも経験があるのではないかと思います。

ソフトウェア開発の現場では、たくさんの問題が発生します。問題に対して様々なアイデアを出し、ソフトウェアのコードに落とし込んで実装し解決しているはずです。このアイデアの質によって、大きく方向性が変わるということを何度も経験してきました。

そんな時、「デザイン思考」の一部「How Might We（HMW）」と出会いました。HMWは、UXデザイナーだけではなく、エンジニアが仮説検証のプロセスを効果的に進めるために役立つフレームワークなのではないかと考えています。そこで今回は「HMW」について説明しつつ、エンジニアとしてどのように取り入れられるかについて話をします。

### HMW(How Might We)とは

HMW（How Might We）とは、「どうすれば我々は〜できるか？」というフォーマットにあわせて解くべき問題を定義する方法です。IDEOが使い始めたのち、今では世界中の多くのデザインファームやデザイン教育機関で使われているそうです。

https://ddcph.hatenablog.com/entry/2016/05/21/203714

https://www.mof-mof.co.jp/blog/column/how-might-we

https://www.amazon.co.jp/dp/4802511779

## 例：遊園地のアトラクションにて待ち時間が長く、お客さんが退屈してしまう

![eefdb5d4-c335-4d5b-83f5-e5925653dd88.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149986/96ba780d-e73f-49cd-3909-043f7ae77e85.jpeg)

課題の例として、「遊園地のアトラクションにて待ち時間が長く、お客さんが退屈してしまう」という状況を考えてみましょう。
この問題を解決するために、HMW(How Might We)を活用してみます。「どうすれば我々は〜できるだろうか」のフォーマットに合わせて、この課題に対する問いを作成していきます。

### どうすれば我々はアトラクションの待ち時間を減らせるだろうか
よくあるHMWは「どうすれば我々はアトラクションの待ち時間を減らせるだろうか」というものです。これに対する具体的なアイデアとしては、アトラクションの稼働率を上げるなどが考えられます。

### どうすれば我々はアトラクションの待ち時間を楽しんでもらえるだろうか
別のHMWとして挙げられるのが「どうすれば我々はアトラクションの待ち時間を楽しんでもらえるだろうか」です。ここでは、待機列にエンターテイメント要素を追加することで解決策を考えます。例えば、壁に描かれたキャラクター探し（隠れミ●キー）などを提供することで、待ち時間そのものが楽しい時間に変わるかもしれません。

### どうすれば我々は待ち時間中にお客さんが他のアトラクションを楽しめるようにすることができるだろうか
他にも「どうすれば我々は待ち時間中にお客さんが他のアトラクションを楽しめるようにすることができるだろうか」というHMWが考えられます。この問題解決のためには、「待機列から離れて別アトラクションを楽しめるファストパス」などが考えられます。

このように課題に対して様々なHMWを出すことにより、解決策となるソリューションのアイデアを多数生み出すことができます。


## ソフトウェア開発現場のHMW

![785ecc0f-de66-4a90-a536-127a38604d8c.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149986/d4a02aa7-c060-bf11-1efd-dc09b6645a49.jpeg)

エンジニアリングチームでは日々生じる課題に対してふりかえりを行います。例えば、以下のような問題が起きたとします。
「初めて扱う新しい技術を使うことになり難しく計画していた作業が予定通り終わらなかった。次の計画では予定通り終わるように調整する必要がある。」
この時どのような解決策を考えるでしょうか？

HMWの力を借りてみましょう。
「デザインリサーチの教科書」で紹介されているいくつかのパターンで問題定義を考えてみます。

### 良い面を伸ばす

「どうすれば我々は、新しい技術を使いこなせるだろうか？」
書籍を買ったり、勉強会に参加するなどの施策が考えられます。

### 悪い面を除去する

「どうすれば我々は、作業の見積もりを改善することができるだろうか？」
「どうすれば我々は、計画する作業を減らせるだろうか？」
予定通り行くために計画を見直すアイデアです。

### 反対を探す

「どうすれば我々は、新しい技術を使わずに問題を解決できるだろうか？」
新しい技術を使わなくても解決できるのであれば無理に使わなくてもよいかもしれません。

### そもそもの質問

「どうすれば我々は、作業を計画せずに済むだろうか。」
計画することを諦めます。（いいのだろうか）

### 他のリソースを活用する

「どうすれば我々は、外のチームに相談して難しい作業を終わらせられるだろうか。」
外のチームに支援を求めるパターンです

これらの質問から派生するアイデアは、プロダクトを成功させるための具体的な行動へとつながるのではないでしょうか？

## アイデアを出す前に問題定義から考える

アイデアを出す前に、課題と問題定義から考えることで、様々な観点のアイデアを出せることを説明しました。私は、ふりかえりでTryを出す際にはよくこのようなHMWを考えてからアイデアを出すように心がけています。

アイデア出しをする前に今起きている課題とその問題定義から始めてみませんか？
【Linux】特定のフォルダのファイル総容量を確認する方法



## `du`コマンド

`du`コマンドを使用することでディレクトリ内のファイル容量を表示させることができます。

```terminal
$ du .
8328	./sample/example
280240	./sample
7670680	.
```

## オプション（一部）

### `-h`
次のように実行すると、適切な単位で表示します。

```terminal
$ du -h .
4.1M	./sample/example
137M	./sample
3.7G	.
```

### `-s`

次のように実行すると、指定したディレクトリの合計を表示します。

```terminal
$ du -s .
7670776	.
```

### `-d 深さ`

次のように実行すると、表示する深さを指定できます。

```terminal
$ du -d 1 .
7670680	./sample
7670776	.
```

## 容量が大きい順に表示する

以下のように実行すると容量が大きい順に表示されます。

```terminal
du -h . | sort -n -r
```
【Android】ログを出すためのライブラリなんて必要？という人(過去の私を含む)はいますぐ考えを改めよう。

## 最初に
皆さんロガーライブラリ使っていますか？
私は正直、社会人になって業務のアプリを開発するまで、標準出力で十分でしょ！！と思っていました。。。:sweat_smile:
この記事ではそんな考えの人間が考えを改めた経緯を記載したいと思います。
それでは行きましょう〜:writing_hand:

## そもそもログは必要？
大前提でこの疑問が出てくると思います。
私の個人的な考えですが、**ログは必要**だと思っています。
ログが必要なケースとしては以下が考えられます。
1. どこのフローを通ったのか開発中に確認したい時。
1. リリース後に出た不具合を解析する時。

ここで注目したいのは、最初の方です。

## 開発中のログ
これはプログラミングして開発しているとみんなが必ず一度はやる、プリントデバッグというやつになります。
どこの処理を通り、変数はどういった状態になっているかを一行ずつログとして出力する行為です。
地道ですが最終手段としては有効な方法の一つです。

ですがこの出力した情報は、あくまで開発中のみ必要な情報になります。
ですので、開発が終わったら消しておくべきです。

しかし、開発中有効にしておいてリリース時は消すなんてことを手作業でやることは現実的ではありませんよね？

そう。ここで登場してくるのが、**ロガーライブラリ**になります。
(Androidでは[Timber](https://github.com/JakeWharton/timber)というライブラリが有名ですね。)

これが登場するまでは、自前でログを管理する独自クラスなんてのもありました。(懐かしい。。。)
こういったライブラリを　使うことで、デバッグオプションで指定してあるログはリリース時にでなくなります。
(もちろん、人間がやらないのでミスもありません！)


## 最後に
今回はロガーライブラリについて記載してみました。
過去の私みたいに「このライブラリ必要なのかなぁ？」と思っていた人がもしいたら、
少しは考えを改めるキッカケになるのではないかと思います。

では、また明日〜〜
画面ロック時でも動くWinActorシナリオの作り方

## WinActorは画面に表示して使うツール

WinActorを画面ロックなど、ディスプレイに表示されていない状態で使いたいという相談を受け、可能かどうか調べた時のことを書きます。
WinActorは基本的に画面に表示をして使うツールです。

調べた結果、画面ロックされている状態でも使えるノード・ライブラリもありました！

まずは使えないライブラリから紹介します。

## 画面ロック時に使えないノード・ライブラリ

画像マッチング
エミュレーション
UIオートメーション
など。。
いわゆるプロパティに「ウィンドウ識別名」があるノード・ライブラリは画面ロック状態では使えません！！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636184/9a2be350-4d54-e580-1b1a-fc189d21669a.png)

あとはキャプチャ取得も動きませんでした。

## 画面ロック時でも使えたノード・ライブラリ

文字列比較
文字列操作
日付関連
Excel関連
ブラウザ関連
など。。

この辺は私が調べた限りですが、こちらは画面ロック状態でも動きました。

↓こんな感じのブラウザ操作するようなシナリオも動きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636184/f760dc91-a424-d2a3-7ddd-e25b628198a1.png)

これらのノード・ライブラリを使ってシナリオを作ればいいのです。

例えばWinDows10がインストールされているAzure Virtual MachinesのスタートアップにWinActorの起動ショートカットを入れておき、自動起動自動ログイン時にシナリオを動かす。。という運用も出来ました。

結論としては「ノード・ライブラリを限定すれば可能」でした。
ただし公式に謳われているわけではなく、あくまで私の調べた結果なので必ず検証してから実用してください。

以上、「画面ロック時でも動くWinActorシナリオの作り方」でした！
OpenAIのダリーさんに画像生成してもらーう（Python）

# はじめに
[がちもとさんアドベントカレンダー](https://qiita.com/advent-calendar/2023/gachimoto3)7日目の記事です。
今日は、ダリーさん（DALLE3）に画像生成してもらいました。

# 開発環境
- Windows 11 PC
- Python 3.11

# 導入

1．ライブラリのインストール
pip install openai
pip install requests

2．APIキーを発行

https://platform.openai.com/api-keys

3．プログラムを作成

~~~dalle3.py
from openai import OpenAI
import requests 
import os

client = OpenAI(api_key="<INSERT-YOUR-API-KEY>")
response = client.images.generate(
  model="dall-e-3",
  prompt="a white siamese cat",
  size="1024x1024",
  quality="standard", # "hd"
  n=1,
)

image_url = response.data[0].url

print(image_url)

url_parts = image_url.split('?')
file_name = url_parts[0].split('/')[-1]

response = requests.get(image_url)
if response.status_code == 200:
    with open(file_name, "wb") as f:
        f.write(response.content)
    print("画像をダウンロードして保存しました。")
else:
    print("画像のダウンロードに失敗しました。")
~~~

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

このコードは、OpenAIのDALL·Eモデルを使用して、指定したテキストプロンプトに基づいて画像を生成し、その画像をダウンロードして保存するPythonプログラムです。以下、コードの簡単な説明です。

1．OpenAIのAPIキーをセットアップします。

- api_keyには、OpenAIのAPIを使用するためのキーを指定します。

2．client.images.generateメソッドを使用して画像を生成します。

- modelには、使用するDALL·Eモデルの種類を指定します（ここでは"dall-e-3"を使用しています）。
- promptには、生成する画像に関するテキストのプロンプトを指定します（ここでは「a white siamese cat」を指定しています）。
- sizeには、生成される画像のサイズを指定します（ここでは1024x1024ピクセル）。
- qualityには、画像の品質を指定します（ここでは「standard」を使用していますが、「hd」も選択可能です）。
- nには、生成する画像の数を指定します（ここでは1つ）。

3．生成された画像のURLを取得します。

4．画像のURLからファイル名を取得します。

5．requests.getを使用して、生成された画像のURLから画像データをダウンロードします。

6．ダウンロードが成功した場合は、ファイルに保存します。

このコードを実行すると、指定したテキストプロンプトに基づいて生成された画像がダウンロードされ、保存されます。
</div></details>

|standard|hd|
|:--|:--|
|![img-z7y8oa7PdQs7gTx2mYFhl8HO.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/388572c0-eb41-d015-1ce8-af1dea5fea71.png)|![img-TVdb4tCIrkr0an03IFLOhZwD.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/20a5bb80-1ad6-0ed3-4bf5-973e1f3c3c31.png)|

https://x.com/sotongshi/status/1732770589700727101?s=20

お疲れさまでした。
君の町では肉、魚?さぁ調べてみよう年末年始のごちそう何食べる？

# TableauPublicでかんたんなVizを作ってみよう！

データはいつものこちら、e-statから家計調査のデータを取ってきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/bfbd7cb3-14e4-ccc4-fd66-7984e99146b4.png)

こんな感じでポチポチえらんで肉魚の食材データをとりますよ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/1e0a5a30-f6b4-45e9-0db9-8c5aa07910e6.png)

お正月といえばお刺身！とはいえ、最近おさかな消費量、減ってる？？

てなわけで、まずは魚介類と肉類をとってきてみます。

魚介類に対して、お肉の消費金額がどんなもんかを表計算機能で出しておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/5a4400e3-225e-e9b5-2477-cb16ebc013d5.png)

で、青が魚のほうが多い、赤がお肉の方が多いところ。
年と都市でクロス可視してみると、だんだん南の方からお肉の消費割合が増えてるのがわかりますね！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/ccbb681d-4c46-931f-30a3-763a5de1b1b2.png)

パっと見、人の嗜好が変わっていくところ、実は地域性がある？みたいなところが分かって面白かったです。

こういうVizは作ってて楽しいですね。

明日は、各都市でどんな魚を食べているかを見てみましょう！
Ubuntu on WSL with USB deviceをする

# はじめに
Ubuntu on WSLでUSBメモリを使いたいですか？使いたいですよね？教えます，使いましょう．
尚，レポートを保存するのに非常に便利ですが，バックアップは取りましょう．USBメモリは急に壊れます

# 結論
Dドライブならこうしましょう
他のドライブならd:及び/mnt/dを変更するとよいです
```bash
user:~$ sudo mount -t drvfs d: /mnt/d -o uid=$(id -u $USER),gid=$(id -g $USER),metadata
```

# USBマウントの方法
### 公式ドキュメント
[公式ドキュメント](https://learn.microsoft.com/ja-jp/windows/wsl/wsl2-mount-disk)には以下のようにすればよいと書かれてあります.
```bash
user:~$ sudo mount -t drvfs D: /mnt/d
```
:::note warn
マウント先のディレクトリを事前に作る必要があります. (/mnt/d)
:::
当然, これはマウントすることができます. 公式がそう言ってるんだもの.
### 何が問題なの❓
例えばマウントしたUSBデバイスになにかvirtual environmentでも作ってPythonで遊ぶぞ～～としたとき, なにをするでしょうか. 
```bash
user:/mnt/d$ pip install hogehoge
```
でしょう. うーん残念ながらこれはできないです. 管理者権限がいるといわれるでしょう. いつもはそんなこと言わないのに...
これはマウント時のコマンドがsudo, 管理者権限で実行されていることに起因します. 管理者(以下root)でマウントしたフォルダ及びその配下はroot所有となります. root所有のフォルダにアクセスするには管理者権限がいるわけですね.
ほなこれでええやろ！
```bash
user:/mnt/d$ sudo pip install hogehoge
```
こうするとなんとCドライブのUbuntu本体にインストールされるんですね～～〇すぞ～～～
sudoコマンドにて一時的にrootになったとき,インストール先はカレントディレクトリではなくrootを指します. こうなるとvirtual environmentの意味がないですね.
### 結論(解決策)
こうしましょう
```bash
user:~$ sudo mount -t drvfs d: /mnt/d -o uid=$(id -u $USER),gid=$(id -g $USER),metadata
```
だいたいカレントユーザでマウントしているだけです.

# おわりに
おわり
OneNoteをユースケースを交えて紹介

## 背景

学生時代にもっと利用していたメモのアプリケーションがOneNoteだと思う．
会社ではメモ・勉強よりも作業そのものが多いので，OneNoteを利用する機会が減ってしまった．
忘れないうちに"どのように"・"何の機能を使ったか"を記載しておく．

## OneNoteとは

Microsoftのノートアプリ. 
Microsoftアカウントさえあれば以下から無料でダウンロードできる．

https://www.onenote.com/download?omkt=ja-JP

ノートというと，テキストや画像くらいだと思い浮かぶが，
動画，音声，手書きメモなどのメディアに対応している．
スマホアプリ版のOneNoteもあるので合わせてダウンロードしておくと，すごく便利．

![学生自体のOneNote](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3600683/56f810e5-39d6-bde9-22e5-902903b0c814.jpeg)

自分は，研究室のことを一つのノートにまとめている．
それぞれ，ゼミや英語輪講，自分の研究と言った形で章立てして，
各章にページを追加してノートをとっていた．

## ユースケース

### 1. チーム内ミーティング

チーム内ミーティングは基本的にテキストのメモが多くなる．
以下は，データ収録を行う際のメモになる (黒色でつぶした部分はホワイトボードの写真をそのまま張り付けている)．
必要なものリストなどを青く囲っておいて，紙のノート同様に見やすくしている．
また，**ノートシール**という機能を追加して，検索でヒットするようにしている(後述)．

![Onenote2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3600683/f9e550b3-dc39-5581-adb5-994e17cc1dd2.jpeg)

#### 画像の添付

会議が終ったあと，ホワイトボードに書いた議論メモを残すようにしている．
その際スマホで写真を撮って，OneNoteに張り付ける．

張り付ける際，トリミングすることで，よこから撮った写真を正面から撮ったように加工して
OneNoteに張り付けることができる．

![sounyu.png](https://raw.githubusercontent.com/killinneko/2023advent/main/image/Onenote/sounyu.png)


#### ノートシール

ノートシールは，テキストに付与するタグのようなもの．

![noteseal.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3600683/c82c74c1-7409-9203-e16c-c58a4eedb6ee.jpeg)

「ノートシールを検索」を使うと，ノートシールで張った部分のテキスト一覧が表示される．
終了したタスクにはチェックボックスが付く．
検索の「ノートシールのグループ化」は，ノートシールのジャンル・ノート・日付ごとで表示することができる．

![noteseal_find.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3600683/a0a408a7-520c-032c-5ef3-67dafa6c9ab9.jpeg)

基本的にはタスク/重要/質問の3つのみを利用している．
タスクは，今週やらないといけないタスク一覧に付与している．終わったらチェックを付けるような使い方．
重要は，例で挙げた実験に必要なことや学会の投稿期限などに利用．検索機能で振り返るようにしてる．
質問は，全体の進捗会議や輪講で出た疑問部分に付与している．分からないことを分からないままにしない習慣がちょっとはついた．

### 2. 論文・ドキュメント読み

ドキュメントファイルをそのまま添付して，手書きでメモを書いていく形式．
大量に書き込まないといけない場合や参考リンクなどを張りたくなった際に困らない．

![memo.jpg](https://raw.githubusercontent.com/killinneko/2023advent/main/image/Onenote/memo.jpg)

#### ファイルの印刷イメージ

ファイルを添付する際，2パターン選べる．
「ファイルの印刷イメージ」を押すと，画像としてスライドやpdfファイルを表示することができる．
「添付ファイル」を押すと，OneDriveにアップロードして，アイコンのみをページに表示する．
添付ファイルは表形式の実験データなどを添付していて，ノートから参照しやすいようにしていた．


## 終わりに

OneNoteのよく使う3つ機能を，ユースケースを交えて紹介した．
画像の添付 / ノートシール /　ファイルの印刷イメージ は便利な機能なので，
3つさえ使いこなせれば，メモを取る・情報を参照する速度がとても速くなるので
効率的に作業できると思う．
データ競合

# データ競合とは
　データ競合(Data Race)とは，複数のスレッドやプロセスが同時に共有されたデータにアクセスし，かつ少なくとも一つのアクセスが書き込みである場合に発生する問題です．データ競合が発生すると，不正確な結果やアプリケーションのクラッシュなどの予測不可能な挙動が発生する可能性があります．C#では，マルチスレッドプログラミングや非同期処理を行う際に特に注意が必要です．

# 具体的な場面
### 1. 銀行口座残高の競合:
　複数のスレッドが同時に同じ銀行口座の残高を取得し，それぞれが残高を変更する場合．競合が発生すると，正確な残高が把握できなくなります．

### 2．カウンターの競合:
　複数のスレッドが同時に共有のカウンターをインクリメントする場合．競合が発生すると，正確な回数が数えられなくなります。

### 3. データベースの同時更新:
　複数のスレッドが同時にデータベース内の同じレコードを更新しようとする場合．競合が発生すると，データが破損する可能性があります．

# 再現コード
　本投稿では，共有変数に対する同時のインクリメント操作を行います．
```C#
// 外部の名前空間をインポート
using System;
using System.Threading;

// C#プログラムは通常1つ以上のクラスから構成される
class DataRaceExample
{
    // 共有変数として使用するためstatic宣言
    // 本課題では複数スレッドからのアクセスを想定
    static int sharedVariable = 0;

    // インスタンス作成
    // 共有変数と操作をインスタンスで共有するためstatic宣言
    static void IncrementSharedVariable()
    {
        // 100万回インクリメント
        for (int i = 0; i < 1000000; i++)
        {
            sharedVariable++;
        }
    }

    // インスタンスを作成せずに実行させるためstatic宣言
    static void Main()
    {
        // 2つのスレッドを作成
        // 同じメソッドIncrementSharedVariableを実行
        Thread thread1 = new Thread(IncrementSharedVariable);
        Thread thread2 = new Thread(IncrementSharedVariable);

        // メソッドIncrementSharedVariableを同時に実行
        thread1.Start();
        thread2.Start();

        // Mainメソッドの終了防止のためthread1とthread2の実行が終了するまで待機
        thread1.Join();
        thread2.Join();

        // 最終的なsharedVariableの値を表示(予測できない値になっている)
        Console.WriteLine("Final shared variable value: " + sharedVariable);
        
        // ウィンドウが閉じて値が見られなくなるのを防ぐため．文字入力まで待機
        Console.ReadKey();
    }
}

```

# 再現コードの結果
　値が1166963や1073519などとなり，予測不能な値が出力されました．

# 修正コード
　再現コードと同様，共有変数に対する同時のインクリメント操作を行います．具体的には，lockステートメントを使用することで競合を防ぐ処理を追加しました．
```C#
// 外部の名前空間をインポート
using System;
using System.Threading;

// C#プログラムは通常1つ以上のクラスから構成される
class DataRaceExample
{
    // 共有変数として使用するためstatic宣言
    // 本課題では複数スレッドからのアクセスを想定
    static int sharedVariable = 0;

    // 共有オブジェクトとして使用するためstatic宣言
    // 本オブジェクトはロックのために使用
    static object lockObject = new object();

    // インスタンス作成
    // 共有変数と操作をインスタンスで共有するためstatic宣言
    static void IncrementSharedVariable()
    {
        // 100万回インクリメント
        for (int i = 0; i < 1000000; i++)
        {
            // lockステートメントより同時アクセスを制御
            lock (lockObject)
            {
                sharedVariable++;
            }
        }
    }

    // インスタンスを作成せずに実行させるためstatic宣言
    static void Main()
    {
        // 2つのスレッドを作成
        // 同じメソッドIncrementSharedVariableを実行
        Thread thread1 = new Thread(IncrementSharedVariable);
        Thread thread2 = new Thread(IncrementSharedVariable);

        // メソッドIncrementSharedVariableを同時に実行
        thread1.Start();
        thread2.Start();

        // Mainメソッドの終了防止のためthread1とthread2の実行が終了するまで待機
        thread1.Join();
        thread2.Join();

        // 最終的なsharedVariableの値を表示(予測できない値になっている)
        Console.WriteLine("Final shared variable value: " + sharedVariable);
        
        // ウィンドウが閉じて値が見られなくなるのを防ぐため．文字入力まで待機
        Console.ReadKey();
    }
}
```

# 修正コードの結果
　値が2000000となりました．これは100万回インクリメント×2スレッドの値であり，正しい結果が得られました．
[TiDB?] Databaseを理解するためのリンク集

みなさん、DB Tech Showcase 楽しんでますかー？

いろいろなデータベースがあって、分散や性能や運用といった様々な課題に立ち向かう努力が感じられて、
データベースについてもっと学んでみたい、そんな気持ちが高まりますよね。

PingCAPで使ってる参考文献リストありますよ〜、っていう話をしたら興味あるという声をいくつか頂いたのでここで紹介します。
データベースの様々なトピック毎の参考文献がリストされているものです。

https://github.com/pingcap/awesome-database-learning

DB Tech Showcaseで聴講したScalar DBと劔の参考リンクも記載しておきます。

## Scalar DB
* デザインDoc: https://github.com/scalar-labs/scalardb/blob/master/docs/design.md
* https://dl.acm.org/doi/10.14778/3611540.3611563 VLDB, 2023
    * https://www.vldb.org/pvldb/vol16/p3768-yamada.pdf

## 劔
* Note (ノーチラス・テクノロジーズ） https://note.com/n_technologies
* 劔関連論文 https://www.tsurugidb.com/paper.html

それぞれのセッションの感想などはまた別途書きたいなと思っています。

## GridDB
ブースに立っている時間と重複して聴講できませんでしたが、国産のTime Series DBです。
* https://griddb.net/ja/
* https://github.com/griddb/griddb

## そのほか

* [自作DBやろうぜ！](https://ryogrid.github.io/dbms-jisaku/) さんに自作DBやるためのリンク集があります。
* [RustでSqlite再実装されてる記事](https://kawasin73.hatenablog.com/entry/2023/12/07/081734) も楽しく読んでいます。No Dependencyで全部実装されてるのすごい...


それでは最終日も楽しんで行きましょう！
Truncation = Trueを忘れたらエラーになった話


# TL; DR
`transformers`ライブラリでBERTを使って文書分類をやろうとしたら`data_collator`から`ValueError`を受け取った話。
原因は文書の長さをそろえていなかったこと。

# 背景
transformersライブラリを使ってlivedoorニュースコーパスのカテゴリ分類をやろうとした。

# 困ったこと
`DataCollatorWithPadding`を使ってデータをテンソル化しようとした際に`ValueError`が出る。

```python
samples = tokenized_train_dataset[:8]
[len(x) for x in samples["input_ids"]]

batch = data_collator(samples)
```
```
ValueError: Unable to create tensor, you should probably activate truncation and/or padding with 'padding=True' 'truncation=True' to have batched tensors with the same length. Perhaps your features (`token_type_ids` in this case) have excessive nesting (inputs type `list` where type `int` is expected).
```

# 原因

```python
def tokenize_function(example):
  category = example['category']
  example = tokenizer(example['content'])
  example['labels'] = category2num[category]

  return example
```

ここでtokenizerのオプションに`truncation=True`を入れてなかった。[公式ドキュメント](https://huggingface.co/docs/transformers/main_classes/tokenizer#transformers.PreTrainedTokenizer.encode.truncation)にはこれをすると各文書を`max_length`のトークン長に切りそろえてくれるとある。

今回使ったBERTの最大トークン長は512であるため、`max_length=512`も必要。

# 対応
`tokenizer`のオプションに`truncation=True`と`max_length~512`を追加。
```python
def tokenize_function(example):
  category = example['category']
  example = tokenizer(example['content'], truncation=True, max_length=512)
  example['labels'] = category2num[category]

  return example
```

これで解決。
軽深演習 #7 何もしない


### 軽深（かるしん　なんちゃって圏論） Advent Calendar 2023 7日目の記事です。

演習形式をとっているので、ぜひ　回答を試みてください。


### 前提知識　恒等射　なにもしない
圏は、射が重要です。その中でも、特に重要なのが、恒等射です。言葉を使った説明では、**何もしない**　とよく表現されます。これを知っただけでは、とても重要とは思えないでしょう。数学的には恒等射は逆射と関連があるので、極めて重要です。自然数で言えば、乗法の１が恒等射に相当します。行列だったら単位行列になります。
さて図式だと対象と射がひとつの場合です。

```mermaid
flowchart LR
A-->A
```

軽深（かるしん　なんちゃって圏論）なので、数学的厳密さは、無視して演習　**何もしない**　を提示します。

### 演習　いろいろ検討して何もしないと意思決定することは結構あります。どんな場合がそうでしょうか？　

CD、DVDの規格が決まるときは、関係ある企業はどうだったのでしょうか？　あたらしいソフトウェア導入のとき、ユーザー企業はどんな場合にどう行動するのでしょうか？
**何もしない** のは賢い選択ではないでしょうか？
既定の環境ルーティングの使いどころを考える（前編）

:::note info
この記事は、[Power Apps Advent Calendar 2023](https://qiita.com/advent-calendar/2023/powerapps) 12月9日担当分の記事です。
:::
こんにちは、[たな](https://twitter.com/dreams_panda) です。
Qiita Advent Calendarへの参加ということで、Qiitaで記事を書いていこうと思います。

2023/12/06 - 09 に開催された 「[Japan Power Platform Conference 2023](https://powerplatformconf.connpass.com/event/294851/)」にて、メインイベント初日 12/07に「[マネージド環境とは何か？Power Platform管理者が押さえておくべきポイント]( https://www.docswell.com/s/tanapandalove/KEN7EE-2023-12-07-174940)」というお話をさせていただきました。
その中で「既定の環境ルーティング」の機能のご説明しましたが、参加していただいたみなさんにも興味を持っていただけたようでした。

登壇資料はこちら↓↓↓です。

https://www.docswell.com/s/tanapandalove/KEN7EE-2023-12-07-174940

資料に記載していない点もお話しているので、参加できなかった方は、後日、[Japan Power Platform User Group のYouTube](https://www.youtube.com/@JapanPowerPlatformUserGroup)で動画公開されるのをお待ちいただければと思います。

# 既定の環境ルーティング
マネージド環境に「既定の環境ルーティング」という機能が追加されました。

:::note info
マネージド環境、既定の環境ルーティングについては、以下の公式ドキュメントをご確認ください。
[マネージド環境の概要 - Power Platform | Microsoft Learn](https://learn.microsoft.com/ja-jp/power-platform/admin/managed-environment-overview?WT.mc_id=DX-MVP-5005072)
[既定の環境ルーティング (プレビュー) - Power Platform | Microsoft Learn](https://learn.microsoft.com/ja-jp/power-platform/admin/default-environment-routing?WT.mc_id=DX-MVP-5005072)
:::

通常、初めてPower Appsにログインすると「既定の環境」が選択された状態でポータル画面が表示されます。
しかし、既定の環境ルーティングを設定すると、初回のPower Appsログイン時にユーザー専用の「開発者環境」が自動的に作成されて、その環境が選択された状態でポータル画面が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1382111/4d9fca8b-c747-42b0-6196-1972fbc45e85.png)
※ 登壇資料抜粋

「既定の環境」は使わせたくないという組織も多いと思います。
「開発者環境」は、2GBという制限はありますが、テナントにDataverseの空き容量がなくても作成できるという点がとても魅力的です。
（Dataverseの容量はなかなかのお値段が。。。

「開発者環境」については、[ふらり](https://twitter.com/flali_world)さんの記事が参考になります。

https://flali.hatenablog.com/entry/2023/01/28/210000

既定の環境ルーティングは、ユーザーがPower Appsに初めてアクセスするときに実行されます。
初めてアクセスするということは、初学者である可能性が非常に高いです。
初学者にはいきなり運用環境でアプリを作り始めるのではなく、個人環境でいろいろ学んでから運用環境を使って欲しいと思う管理者は多いと思います。
その要望を叶えてくれるのが「既定の環境ルーティング」の機能です。

# 既定の環境ルーティングを使うにあたって気になる点
とても魅力的な機能ですが、現在、プレビュー中ということもあり、気になる点がいくつかあります。
登壇時にはお話できなかった点を「[既定の環境ルーティングの使いどころを考える（後編）](https://tana-techlog.net/?p=1135)」に綴っていこうと思います。
~~上記記事については、公開までもう少々お待ちください~~
※ 公開しました<m(__)m> 
※ 後半の記事の方でも、よかったよ、役に立ったよという方は、こちらのQiitaの記事の方にいいね！をよろしくお願いします。
goでsql

アドベントカレンダー7日目です。
goでmysqlを扱います。

`docker-compose`にmysql関連の記述を追加します。
```yml
version: '3'
services:
  golang:
    build: .
    tty: true
    volumes:
      - ./:/app/
    ports:
      - "1323:1323"
  mysql:
    image: mariadb # mysqlと言いつつmariadb使っています
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: golang
      MYSQL_USER: golang
      MYSQL_PASSWORD: golang
    ports:
      - "3310:3306"
    volumes:
      - ./mysql:/var/lib/mysql

```

コンテナを起動します。
```bash
docker-compose up -d
```

ローカルから接続してみます。
```bash
$ mysql -ugolang -pgolang -P 3310
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 10
Server version: 10.9.3-MariaDB-1:10.9.3+maria~ubu2204 mariadb.org binary distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]>
```
コンテナが起動していることの確認ができました。
適当に`users`テーブルを作成しておきます。
```bash
MariaDB [(none)]> use golang;
Database changed
MariaDB [golang]> CREATE TABLE users (
    ->     id INT AUTO_INCREMENT PRIMARY KEY,
    ->     username VARCHAR(50) NOT NULL,
    ->     password VARCHAR(50) NOT NULL,
    ->     email VARCHAR(100),
    ->     created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    -> );
Query OK, 0 rows affected (0.042 sec)

MariaDB [golang]>
```

## goからアクセスする
ライブラリをインストールします。
```bash
docker-compose exec golang go get github.com/go-sql-driver/mysql
```


```go
package main

import (
	"database/sql"
	"fmt"

	_ "github.com/go-sql-driver/mysql"
)

func main() {
	// データベースの接続情報(ハードコーディング勘弁)
	db, err := sql.Open("mysql", "golang:golang@tcp(mysql:3306)/golang")
	if err != nil {
		fmt.Println("Failed to connect to the database:", err)
		return
	}
	defer db.Close()

    // データの作成
	_, err = db.Exec("insert into users (username, email, password, created_at) values (?, ?, ?, now())", "test", "test", "test")
	if err != nil {
		fmt.Println("Failed to insert data:", err)
		return
	}

	// データの取得
	rows, err := db.Query("select * from users")
	if err != nil {
		fmt.Println("Failed to select data:", err)
		return
	}
	defer rows.Close()
	for rows.Next() {
		var id int
		var username string
		var email string
		var password string
		var createdAt string
		err := rows.Scan(&id, &username, &email, &password, &createdAt)
		if err != nil {
			fmt.Println("Failed to scan data:", err)
			return
		}
		fmt.Println(id, username, email, password, createdAt)
	}
}
```

## 所感
結構標準ライブラリだけでsqlを扱うのは大変な気がします。
`gorm`なり、`sqlboiler`などの使用を検討したいところです。
Ruby芸160チャレンジ(#10)マッチ文字列の一部を使った置換

## この記事は何
[shellgei160を通じて言語習得 Advent Calendar 2023](https://qiita.com/advent-calendar/2023/learning-via-shellgei160)に参加しています。

書籍「シェル芸ワンライナー160本ノック」の例題をRubyで解いてみて、Rubyの学習に役立てようとするものです。

例題はこちらのリポジトリで公開されているものに限ります。
https://github.com/shellgei/shellgei160

## 実行環境など
- Docker image: ruby:3.0.2
- 上記リポジトリをクローンした上で、リポジトリのルートディレクトリ直下に`answer-ruby`ディレクトリを作り、その中に解答となるファイルを作成していきます。

## 今回のテーマ
https://github.com/shellgei/shellgei160/blob/master/answer/10.md

```bash
$ cat headings.md | sed -r 's/^## +(.*)/\1\n---/' | sed -r 's/^# +(.*)/\1\n===/'
```

以下のように文字列を置換する処理です。ポイントはマッチした文字列の一部を使って、置換後の文字列を作成する点です。

```
(変換前)
## subset

(変換後)
subset
---
```

## 解
```ruby
text = File.open('qdata/10/headings.md', 'r').read
text.gsub!(/^## +(.*)/, "\\1\n---")
text.gsub!(/^# +(.*)/, "\\1\n===")
puts text
```

## 所感・メモ
- `( )`で囲ったブロック(?)を置換後文字列の中で使うには`\1`（複数あれば`\2`, ...)を使う。`\n`を入れるので、置換後文字列はダブルクオーテーションにしておく。`\1`はエスケープが必要なので`\\1`。
mayaのプレイブラストをffmpegでmp4にしてみる1

mayaのプレイブラスト　mov標準でサポートされなくなったので、
とりあえず非圧縮aviで書き出す事が多いんですが

おっもーいので、色々不便。

追記
Qtコーデックを別途インストールすれば書き出せるようになるそうです
https://3dcg.comaroku.com/maya-playblast-mov/#toc2


mp4にしたい
-
何でもいいっちゃいいのですが、一旦mp4で。
色々調べると　ffmepgっていうので変換できるらしい
https://ffmpeg.org/

昔からあるよなーって思ってたけど2000年からなのかー
2000年が23年前っていう事実のほうがビックリ
https://ja.wikipedia.org/wiki/FFmpeg

流れを考える
-
ffmepgさんは動画・連番ファイル両方に対応してるので

- mayaでプレイブラストする
- 出力された動画をffmepgさんにmp4化してもらう

雑に考えるとこんな感じですかね

動画を変換してもらう
-
まずはffmepg単体でテスト
古いだけあって、割と先人たちの知恵がいっぱいありますね。
ffmpeg-pythonも併用して

参考
https://qiita.com/studio_haneya/items/a2a6664c155cfa90ddcf


```python
import ffmpeg

def inputMovie(inputFilePath,fileType,codec):    
    inputVideoInfo = ffmpeg.probe(inputFilePath)["streams"][0]    
    outFilePath = os.path.splitext(inputFilePath)[0] + "." + fileType
    
    width = int(inputVideoInfo["width"])
    height = int(inputVideoInfo["height"])
    
    stream = ffmpeg.input(inputFilePath)
    stream = ffmpeg.filter(stream,'scale', -1, height)
    stream = ffmpeg.output(stream, outFilePath,vcodec=codec, pix_fmt= "yuv420p")    
    ffmpeg.run(stream,overwrite_output =True)

inputFilePath = "C:/Users/kubo/Desktop/trail.avi"
fileType = "mp4"
codec = "h264"
inputMovie(inputFilePath,fileType,codec)

```

お、できましたわね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/fee8620a-3637-a2c3-2790-0aa55d40a040.png)


mayaで使えるようにする
-

参考
https://qiita.com/lie_871221/items/367437a711ee0acb67ce

ffmepgのインストールがなぁ・・・
と色々と考えた結果
環境変数に一時的に足してしまえば行けんじゃねぇ？という雑頭の発想

```python
import sys
import os

ffmpegPath = "C:/Users/kubo/Documents/ffmpeg/bin"

if ffmpegPath not in os.environ["PATH"]:
    os.environ["PATH"] += ffmpegPath + ";"

ffmpegPyPath = "C:/Users/kubo/Documents/ffmpeg-python"

if ffmpegPyPath not in sys.path:
    sys.path.append(ffmpegPyPath)


import ffmpeg

def inputMovie(inputFilePath,fileType,codec):    
    inputVideoInfo = ffmpeg.probe(inputFilePath)["streams"][0]    
    outFilePath = os.path.splitext(inputFilePath)[0] + "." + fileType
    
    width = int(inputVideoInfo["width"])
    height = int(inputVideoInfo["height"])
    
    stream = ffmpeg.input(inputFilePath)
    stream = ffmpeg.filter(stream,'scale', -1, height)
    stream = ffmpeg.output(stream, outFilePath,vcodec=codec, pix_fmt= "yuv420p")    
    ffmpeg.run(stream,overwrite_output =True)

inputFilePath = "C:/Users/kubo/Desktop/trail.avi"
fileType = "mp4"
codec = "h264"
inputMovie(inputFilePath,fileType,codec)
```

うん　できたけども、これはなんかモヤっとしたので、
mayaの起動batにて指定することにしました。

続きは次回へ
Markdownで文章書く時に使うHTMLタグまとめ

## はじめに
Markdown書く時にどうも体裁がうまく整えられないというときHTMLタグに頼るのですが、よくつかうな〜という実感あるものをまとめてみたいと思います。

## 個人的使用頻度順HTMLタグ紹介
### imgタグ
```html
<img src="./hogehoge/fugafuga.png" width="300">
```

画像の大きさ調整したいな〜という時に使います。
資料作成の際スクリーンショット画像を貼り付けがちなのですが、だいたいの場合画像が大きすぎるのでwidthで大きさを調整します。
％を指定しても画像拡大縮小してくれるのですが、HTMLの現在の書き方的にNGのようです。

https://stackoverflow.com/questions/3396475/specifying-width-and-height-as-percentages-without-skewing-photo-proportions-in

タグとあわせて使いたい属性は以下リンク参照ください。先程のwidthの指定の仕方についても言及があります。
私は非推奨と書かれていますがvspaceやhspace使っちゃいがちです。(フロントエンド書くために使うわけではないからいいかなという気持ち)

https://developer.mozilla.org/ja/docs/Web/HTML/Element/img

ちなみにQiitaではvspace・hspaceなどは使えません。

### divタグ
```html
<div align="center">
    <img src="./fugafuga.jpeg" width="100">
</div>
```

主に何かを中央揃えしたいな〜という時に使います。
画像貼り付けるときはだいたいこの構成で書きます。

https://developer.mozilla.org/ja/docs/Web/HTML/Element/div

が、alignはもう廃止機能なんですね...
Qiitaで書く際はalign動いてくれません。

また、改ページの際も以下のような感じでdivタグを使っています。
```html
<div style="page-break-before:always"></div>
```

Marpで書くときは`---`で済むので、書き方を忘れがちです。

### 説明リスト
```html
<dl>
  <dt>朝ご飯</dt>
  <dd>ごはん、納豆、味噌汁</dd>
  <dt>昼ごはん</dt>
  <dd>サラダ、パスタ</dd>
  <dt>晩ごはん</dt>
  <dd>ごはん、味噌汁、とんかつ、千切りキャベツ、トマト、冷奴</dd>
</dl>
```

<dl>
  <dt>朝ご飯</dt>
  <dd>ごはん、納豆、味噌汁</dd>
  <dt>昼ごはん</dt>
  <dd>サラダ、パスタ</dd>
  <dt>晩ごはん</dt>
  <dd>ごはん、味噌汁、とんかつ、千切りキャベツ、トマト、冷奴</dd>
</dl>

こんなかんじのものですね。
リストを入れ子にして済ませちゃうこともあるのですが、こちらの方が見やすい場合が多いです。

https://developer.mozilla.org/ja/docs/Web/HTML/Element/dl

### sタグ
```html

取り消し線

```

説明リスト使用する際にはmarkdownの ~~取り消し線~~ が使えないので、線を引きたいときはsタグを使います。

```html
 ~~ここはリストの外なので"〜"で囲むのがつかえる！~~ 

もちろんsタグでも良い


<dl>
  <dt>朝ご飯</dt>
  <dd> ~~ごはん、納豆、味噌汁~~ </dd>
  <dt>昼ごはん</dt>
  <dd>
サラダ、パスタ
</dd>
  <dt>晩ごはん</dt>
  <dd>ごはん、味噌汁、とんかつ、千切りキャベツ、トマト、冷奴</dd>
</dl>
```

 ~~ここはリストの外なので"〜"で囲むのがつかえる！~~ 

もちろんsタグでも良い


<dl>
  <dt>朝ご飯</dt>
  <dd> ~~ごはん、納豆、味噌汁~~ </dd>
  <dt>昼ごはん</dt>
  <dd>
サラダ、パスタ
</dd>
  <dt>晩ごはん</dt>
  <dd>ごはん、味噌汁、とんかつ、千切りキャベツ、トマト、冷奴</dd>
</dl>

https://developer.mozilla.org/ja/docs/Web/HTML/Element/s

何か訂正したいことが多いみたいです。

### Detailsタグ
```html
<Details>
    <summary>折り畳み</summary>
    ここの内容は見えなくなるよ！
</Details>
```

<Details>
    <summary>折り畳み</summary>
    ここの内容は見えなくなるよ！
</Details>

長々としたソースコードの例など折りたたむ時に使います。
主にQiitaで記事書く時に使っています。

https://developer.mozilla.org/ja/docs/Web/HTML/Element/details

## 参考リンク

わからないことがあるたびに見るやつ

https://qiita.com/Qiita/items/c686397e4a0f4f11683d#emphasis--strong-emphasis---%E5%BC%B7%E8%AA%BF%E5%BC%B7%E5%8B%A2

少し前の記事だけど、あれ、これQiitaでは動かんのか？となったときに参照したい記事

https://qiita.com/syu1404/items/f2212bee7f0b2c69228f

## おわりに
いつも行き当たりばったりに調べて書いているので、最新のHTMLの書き方・お作法などちゃんと情報追わなきゃなあと思っています。
【AWS】S3

# S3(Amazon Simple Strage Service)とは
オブジェクトストレージを提供するサービス。耐障害性・可用性・コスト面に優れる。
バケット内にキーとオブジェクトのペアがあり，それぞれにメタデータが付随しているイメージ。
新しいオブジェクトの書き込みや既存のオブジェクトの上書きリクエスト成功後，読み込みリクエストはオブジェクトの最新版を受け取る(**強力な整合性**)

:::note info
**バケット**
オブジェクトを保存する場所。バケット名はAWSアカウントの中で一意である必要がある。**プレフィックス**と呼ばれるS3上のディレクトリを追加できる。また1アカウントで最大100個まで作成可能で，増加リクエストができる。
:::

:::note info
**キー**
オブジェクトに割り当てる名前(ファイル名)。キーはバケット内で一意である必要がある。
:::

:::note info
**メタデータ**
アップロードしたオブジェクトの属性を記載したデータ。アップロード時のみメタデータの設定ができる。
:::

:::note info
**オブジェクト**
バケットに保存するデータそのもの。
:::

:::note info
**フォルダ**
オブジェクトを階層構造に見せることができる。(実際はフラット)
:::

:::note info
ログの記録
**AWS CloudTrail**と連携してAPIコールの記録が可能
:::


# メリット
* 耐久性・可用性
S3は複数のAZに保存され，耐久性は99.999999999%(イレブンナイン)を持つ。

* 容量
格納可能なデータの総量とオブジェクト数に制限がないため，データ容量を気にしなくて良い。ただし1オブジェクトは最大5TB。ユーザは保存したオブジェクトの分だけ利用料金を払う。

* セキュリティ
柔軟なセキュリティ機能を提供

# S3のアクセス制御
* アクセスコントロールポリシー(ACL)
他のAWSアカウントなどにバケットやオブジェクトへのアクセスを許可するもの。バケットまたはオブジェクト単位で設定。

* バケットポリシー
バケットに付与でき，特定のIPアドレスからのアクセスを許可，拒否するといった設定が可能。JSON形式で期日。

* IAMポリシー
EC2からS3にアクセスする場合は，EC2にS3へのアクセスを許可するIAMロールを付与する必要がある。

* パブリックアクセス設定
パブリックアクセスの可否を設定。バケットやアカウント単位で設定。

# ストレージクラス
* 標準
高耐久・高可用性なスタンダードなストレージ。

* 標準-低頻度アクセス
標準よりも安価だが，データ取り出し時に料金が発生。アクセス頻度の低いデータの格納向け。

* 1ゾーン・低頻度アクセス
1つのAZにしかデータを保存しない代わりに，標準-低頻度アクセスよりも安価。しかし可用性が低くなっている。アクセス頻度の低いデータの格納向け。

* Glacier
長期間のデータ保存に有効であり，標準の1/5の料金で利用可能。データ取り出しに時間と料金がかかる。

# ライフサイクル
バケット内のオブジェクトを削除したり，ストレージクラスを変更する機能のこと。オブジェクトの更新日をベースに，バケット全体またはプレフィックス単位で設定可能。

# 署名付きURL
AWS CLIやSDKを使って一時的にオブジェクトへのアクセスできるURLを発行できる。URL自体に有効期限が設けられるため，戻し忘れが発生しない。

# バージョニング
オブジェクトの更新をバージョン管理する機能。バージョニングを有効化することで，S3バケット内の更新/削除のイベントは1バージョンとして管理できる。

# クロスリージョンレプリケーション
S3は3つのAZでデータを複製して管理する。仮にリージョン全体で大規模障害が発生した場合に備え，**クロスリージョンレプリケーション**という設定がある。これによりリージョン間でのコピーが自動的に行われ，データロスなどに備えることができる。


# 参考
https://www.youtube.com/watch?v=J0FYcxWN9mU&list=PLPzcoMdqG5noLR7rAc552mvPADUmmdSt1&index=7
https://www.youtube.com/watch?v=wQ8ZDvoMSno
AWSの基本・仕組み・重要用語が全部わかる教科書
WebGLのオブジェクトの中身

## scene
animations:Array(0)
autoUpdate: true
background: null
castShadow: false
children: (2)
environment:null
fog: null
frustumCulled: true
layers: ge {mask: 1}
matrix: se {elements: Array(16)}
matrixAutoUpdate: true
matrixWorld: se {elements: Array(16)}
matrixWorldNeedsUpdate: false
name: ""
overrideMaterial: null
parent: null
position: Lt {x: 0, y: 0, z: 0}
quaternion: At {_x: 0, _y: 0, _z: 0, _w: 1, _onChangeCallback: ƒ
receiveShadow: false
renderOrder: 0
scale: Lt {x: 1, y: 1, z: 1}
type: "Scene"
up: Lt {x: 0, y: 1, z: 0}
userData: {}
uuid: "C4ABDA44-DE6C-4486-8FE2-F3E5E510F811"
visible: true

----

id: 5
modelViewMatrix: se {elements: Array(16)}
normalMatrix: yt {elements: Array(9)}
eulerOrder: (...)
useQuaternion: (...)
進捗表のパーセント表示が機能しないのでなんとかできないか




# 進捗表のパーセント表示が機能しないのでなんとかできないか
開発においてWBS、進捗管理表はだいたい存在していると思うのですが
進捗を０～１００％で表現するのはデメリットが多くないかなと思った

* デメリット
９０％で一生止まったままのタスクが続出
分かってる人は４０％あたりから１％ずつ増やして時間稼ぎしてくる
開発に興味の無い人間でも％表示だけを見て怒り散らすことが可能（”ほぼ無関係者”に怒られるイベントが発生する）
管理者がパーセンテージを増やすことが目的となり作業・状況を軽視する
　 
　 
* メリット
％表示で見れると安心感、納得感がある（※正しい進捗とは限らない）

開発メンバー全員が正確にタスクをすべて洗い出して、正確に時間単位で工数が見積もれるのなら問題無いと思うんですがそういう人は一人も見たことないです
自分の経験上８０％くらいまで問題なく進んで８０％から１００％まではそれまでの２倍も３倍もの期間を要するという事が多い
８０％からは毎日会議で言い訳する時間が増えるという良くない状況になります
そういう状況多数見てると状況説明と締切だけあれば良くない？という気持ちになり、なんとかならないかなと思って代替案を考えていました

# パーセント表示でない進捗

パーセント表示でなく段階ステータスで表示すればいいんじゃないのという案

||タスク|未着手|着手|内部完了|外部確認中|外部完了|進捗コメント等|
|-|-|-|-|-|-|-|-|
|1|しじみを拾う|2023/12/1|2023/12/2|2023/12/5|||たくさん拾った|
|2|栗を拾う|2023/12/1|2023/12/2|2023/12/10|2023/12/12|2023/12/13|確認用写真を送信済み|
|3|黒猫を撫でる|2023/12/6|2023/12/6||||黒猫が見つからない|

使い方
指示を出す → 未着手に日付が入る
着手する → 着手に日付が入る
内部完了 → 作業終わってリーダー等のレビューが終わった状態で日付を入れる
外部確認中 → 依頼主とか上位の存在のレビュー待ちに入ったら日付を入れる
外部完了 → 依頼主とか上位の存在のレビュー完了やリリース済みとなったら日付を入れる

作業者目線だとこういう表のほうがパーセント表示するよりかはマシなんじゃないのという感想です
一応段階的に状況は分かりやすいし、左から右に向かって進んでいることが分かりやすいとは思います
完了度合いを出したければ　着手　のステータスにだけ日付でなく数値％を記入するとか、ハイブリッド型でも良いかもしれないですね。
ただしこの表だと **進んでる感** を得ることができないため依頼主が満足しない事が容易に想像できます

# 関係者全員が納得する進捗管理ツールはあるか
傾向として依頼主（大手企業様とか）はパーセント表示を絶対正義のように求めてきて
現場レベルでは悪習と扱われていると自分は思っています
あくまで自分の経験上の話なので人間・環境によって様々だとは思いますが…
依頼主から作業者まで納得できるような進捗管理方法が欲しいですね
第一世代　モーション変更

「aibo ers-11x/210で遊ぶ Advent Calendar 2023」の10日目です。

:::note
業務外の個人的な検討活動です。
:::

:::note alert
警告
この記事について作者はいかなる責任も負いません。
置き換えるファイルはバックアップを取ることをお勧めします。
:::

9日目にまとめた内容を参考にして、モーションを変更したいときに用いるファイルが分かります。

今回は条件が分かりやすいYART 11xの場合に、アイドル状態でのモーションを変更を試みます。

#### YART 11xでモーション名を確認
Idleの欄を見るとRandom#3にP1I3のモーションが割り当てられていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/a9d0d53e-91bb-4b75-a4fc-6d7f06c1577c.png)

#### モーションの修正
今回はDogsBody & Ratchet's Domainさんが提供するskitterを使用しました。ありがとうございます。
https://www.dogsbodynet.com/

AIBO Data Wizardを使って展開したmode0の中にあったモーションファイルP1I3をskitterで開き、修正しました。
今回はぎりぎりの速さで足踏みをさせました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/1e4470a4-aa8b-ced0-bec3-141185d01961.png)

保存したら、再度AIBO Data Wizardに戻り、UPdate AIBO Dataをクリックしました。

#### 動作確認
アイドル状態のなかからRandom#3が選ばれたとき、設定した動作になりました。

https://youtu.be/iewL0t6qflg

あとは一つ一つモーションを好きな内容に変更していくだけです。
【Git】名前を付けてstash

# はじめに
gitを利用してシステム開発している際に、git stash -uで変更箇所を一時退避させ、git stash pop で退避した変更箇所を反映させる場面が頻繁にでてきて、この退避分は何の変更だっけ？と考える時がたまにありました。その時に、名前を付けてstashtできないかなと調査した内容を簡単にまとめてみます。なお、vscodeで開発しています。

# 名前を付けて退避する方法
~~~
git stash save "付けたい名前"
~~~
を実行する。"付けたい名前"はよしなに変更いただければと思います。
実際に上記を実行した結果、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3382528/94ae06b6-8afe-01b3-81fe-3557a2a3d776.png)
名前付きで退避できていることが確認できました。

# おわりに
今回の名前を付けて退避することにより、一瞬でどの変更分の退避だったか判別ができ僅かながらも開発効率向上へ繋がるのではないかと思います。

# 参考記事
https://qiita.com/dev63/items/590feb83f4066560db01
let, var, constの使い分け【JavaScript】

# **ゴール** 
それぞれの特徴を理解したうえで使い分けできる。



# **各変数の違いを理解** 
下記の特徴を確認する。






<table>
    <tr>
        <th></th>
        <th>let</th>
        <th>var</th>
        <th>const</th>
    </tr>
    <tr>
        <th>再宣言</th>
        <td>不可能</td>
        <td>可能</td>
        <td>不可能</td>
    </tr>
    <tr>
        <th>再代入</th>
        <td>可能</td>
        <td>可能</td>
        <td>不可能</td>
    </tr>
    <tr>
        <th>スコープ</th>
        <td>ブロックスコープ</td>
        <td>関数スコープ</td>
        <td>ブロックスコープ</td>
    </tr>
    <tr>
        <th>繰り返し構文</th>
        <td>可能</td>
        <td>可能</td>
        <td>不可能</td>
    </tr>
</table>

引用元：
>https://techplay.jp/column/1619



# **基本はconstで定義する**
再宣言と再代入ができないconstを使用するのが良い。
意図せず値を書き換えることを防ぐため。（あまりないと思うけど...）





# **let、varの使い道**
ブロックスコープである「let」は、繰り返し構文で使用する。
再代入ができ、再宣言ができないことからvarと比較して変数宣言時のエラーを起こしにくくなる。

varは再代入、再宣言が可能であるが、関数スコープのため影響範囲に注意し
て使用する。
個人的には関数内での使用が良いと思う。ifの条件分岐時に使用することで、スコープを気にせず値の利用が可能である。


以上、アウトプットでした。
万が一間違いや、これも合わせて覚えると良い、ということがありましたら是非コメントいただけると幸いです。
読んでいただきありがとうございました。
FlaskでWebSocket通信

# 記事概要
FlaskでWebSoket通信を利用して、簡易なチャットアプリのサンプルを作成する。

# スクリプト
Server
```python
from flask import Flask, request, render_template, send_from_directory
from flask_socketio import SocketIO, emit
from flask_cors import CORS

app = Flask(__name__, static_folder='static', static_url_path='/')
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app, cors_allowed_origins="*")
CORS(app, supports_credentials=True, responses={r"/*": {"origins": "*"}})

@app.route('/')
def index():
    # return send_from_directory('static', 'index.html') # staticフォルダのindex.html
    return render_template('index.html') # templateフォルダのindex.html


@app.route('/<path:filename>')
def serve_static(filename):
    return send_from_directory('static', filename)


@socketio.on('message', namespace='/demo')
def handle_message(message):
    emit('message', f'{request.sid} => {message}', namespace='/demo', broadcast=True)


if __name__ == '__main__':
    socketio.run(app, host='0.0.0.0', port=5002, debug=True)

```
Client
```html
<!DOCTYPE html>
<html>
<head>
    <title>WebSocket Chat</title>
</head>
<body>
    <input id="message_input" autocomplete="off" /><button id="send">Send</button>
    <ul id="messages"></ul>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
    <script type="text/javascript">
        const socket = io.connect('/demo')

        socket.on('message', (data) => {
            console.log('message', data)
            const li = document.createElement('li')
            li.appendChild(document.createTextNode(data))
            document.getElementById('messages').appendChild(li)
        })

        document.getElementById('send').addEventListener('click', (e) => {
            const message_input = document.getElementById('message_input')
            const message = message_input.value
            socket.emit('message', message)
            message_input.value = ''
        })

        document.getElementById('message_input').addEventListener('keydown', (e) => {
            if (e.keyCode === 13) {
                const message_input = document.getElementById('message_input')
                const message = message_input.value
                socket.emit('message', message)
                message_input.value = ''
            }
        })
    </script>
</body>
</html>
```

# 使い方
- 上記コードではポート5002で立ち上げて、別IPからもWebSoket通信が行えるように***CORS***を使っている。  
- 静的ファイルの置き場として、staticフォルダを指定している。  
- Clientはpythonファイルと同じ階層に```templates```フォルダを作成して、その中に```index.html```を作る。


```python
emit('message', f'{request.sid} => {message}', namespace='/demo', broadcast=True)
```
⇑このようにメッセージ送信を行っているが、ルームを指定することで、個別にMessageのやり取りをすることが出来る。
```python
emit('message', f'{request.sid} => {message}', namespace='/demo', broadcast=True, room='hoge')
```
<br><br><br><br><br>
特定文字のバックスラッシュエスケープinJS

# はじめに 🐢
お仕事で、コピペ入力文字列の特定文字をバックスラッシュで
エスケープしたいケースがありました。
面白そうなので、放課後に取り組んでみました。
JSです。

# １．やりたいこと
\ や ? や ! などをバックスラッシュでエスケープする。

# ２．困ったこと
入力文字列にはバックスラッシュが１コで存在している。
そのまま JS に渡すと、文字列のエスケープ扱いとなってしまう。

# ３．どうしたか
String.raw と テンプレートリテラル を用いる。
入力時のバックスラッシュが１コでも大丈夫。

``` js
String.raw`\?!`;                                                    // '\\?!'
```
https://stackoverflow.com/a/54178824/11634537

# ４．エスケープ
入力文字列を一文字ずつ分割して配列にし、それぞれに対して map でエスケープ入れる。
``` js
String.raw`\?!`.split('').map(x => '\\' + x);        // ['\\\\', '\\?', '\\!']
```
# ５．分岐
特定文字のみエスケープなので、分岐を入れる。
辞書を持たせて、indexOf でマッチした場合のみエスケープする。

```js
String.raw`h\o?g!e`.split('').map(x => (['\\','?','!'].includes(x))? '\\' + x : x);

                                  // ['h', '\\\\', 'o', '\\?', 'g', '\\!', 'e']
```

# ６．出力
最後に、最終出力では バックスラッシュ２つではなく、1つであって欲しいので 
console.log で囲ってあげます。
そうそう、join も入れて元の文字列っぽくしておきます。

```js
console.log(String.raw`h\o?g!e`.split('').map(x => (['\\','?','!'].includes(x))? '\\' + x : x).join(''));

                                                              //　h\\o\?g\!e
```
うまくいきました！
辞書の指定文字のみエスケープされています。


# おわりに
入力がテンプレートリテラルへのコピペなので、レアケースかと思います。
でも面白かったし、私の役には立つので大満足です。



おやすみなさい！
めんどくさいGitの認証をいろんな環境で楽にする

# これまでの苦労について
Gitでプライベートレポジトリからcloneしたり、プライベート・パブリック関係なくpush/pullするときには、基本的に認証が必要になると思います。
ただ、これを行うにはかなりめんどくさい手順をふまなければいけませんでした...
```
(もはやスタンダードになっている)Githubの例:
少し前にパスワード認証が廃止されてしまったので、トークンを発行するか、ssh認証が必要。
1. トークンの発行
アカウント設定→デベロッパ設定→アクセストークンで作る。大抵の場合repoスコープをつける。
(なお、これも途中で新たなトークンが生まれたため、ただレポジトリにアクセスしたいだけなのにいろいろと大変。特にトークンの期限管理などがDALL・E(問題発言))
2. ssh認証
ssh認証鍵(秘密鍵か公開鍵か忘れて見に行ったら公開鍵やん!ってなったとか言えない)をgithubに登録した上でgit@github.comにsshを飛ばす。このときssh_configをいじる必要もあってDALL・E(再び多方面に喧嘩を売る)
```

# そんな あ・な・た・に
ぴったりなものがあります。[git-credential-oauth](https://github.com/hickford/git-credential-oauth)です。

:::note warn
なんでや!GCM(Git-Credential-Manager)があるやろ!と思った方へ...
確かに、この場面でよく使われているものだと考えますが、GCMはMicrosoft様の.NETフレームワークが必要で、これをインストールする必要があって(↑のReadmeにもあると思いますが)あまりにもオーバーヘッドが大きいように思えたのでこちらを選択しました。ちなみに筆者のメイン環境はLinuxです。
:::

設定すると、push/pull/clone時にoauthの認証ページを自動的に(毎回ではなく一定期間ごとに)ブラウザで開き、それだけで認証が完了します。
これにより、そもそもの操作が減り、一定期間ごとに認証をブラウザの認証ページを通して行うので、2段階認証・他要素認証を利用することもでき、実質的にトークン管理の自動化が可能です。
サーバなどのブラウザがない環境では表示されるURLをクリックすることで認証を行えます(なお、現状ではGithubに限る)。

Github、Gitlabのほか姉妹プロジェクトでAzure、エンドポイントの設定を行うことでその他のOauthでの認証を提供するGitレポジトリマネージャ(セルフホストも可)において利用することができます。
そして、なんと言ってもGCMとの差はGoで書かれていることによる移植性の高さ、バイナリの小ささがあります。現状では主要な環境はすべてサポートしているようです。

# Get started
まず、[リリースページ](https://github.com/hickford/git-credential-oauth/releases/tag/v0.11.0)からgitコマンドのプラグイン?として動作するバイナリを入手します。そして、入手したバイナリをPATH内(説明省略)に置きます。

:::note info
ここではリリースページから手動でダウンロードという説明をしていますが、公式ページにある通り、パッケージマネージャにてインストールが可能な環境もあります。その場合はありがたく利用するのが良いと考えます(個人的意見)。
:::

次に、以下のコマンドで有効化します。

```bash
git credential-oauth configure
```

ただし、サーバなどで利用している場合は

```bash
git credential-oauth configure -device
```

を実行してください。
これでひとまず基本的な設定は完了しました。
実際にcloneなどを行ってみてください。

なお、Gitlabを利用している場合は以下の設定が必要です。
- gitlabでoauth applicationを作成(scope read_repository write_repository, redirect_url http://127.0.0.1)
- 以下のコマンドを実行してレポジトリを登録
CLIENTIDには前項で作成したOAuth client_idを、gitlab_hostにはgit.example.comのようなgitlabのホスト名を入れてください。
```bash
git config --global credential.https://<gitlab_host>.oauthClientId <CLIENTID>
git config --global credential.https://<gitlab_host>.oauthScopes read_repository write_repository
git config --global credential.https://<gitlab_host>.oauthAuthURL /oauth/authorize
git config --global credential.https://<gitlab_host>.oauthTokenURL /oauth/token
```
Github Actionsでデプロイに失敗する。

# はじめに
Github Actionsの備忘録
ディレクトリの場所がよくわからなくなりがちなのでメモする。

# 問題

Github Actionsを走らせると下記のような状態によくなる。
ビルドがうまく出来ているように見えるが、デプロイがうまくいっていない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283544/2c93e59a-beaf-7e0a-f8c9-15f82cd23522.png)

### エラーメッセージ
エラーメッセージを見ると下記の通りだった。

ビルド時にファイルをZip化することには成功しているものの、artifactのアップロードの際にパス指定がうまくいかなかったみたいだった。
結局なにもアップロードされないために、artifactがないよという状態だった。

ビルド時のウォーニング
```
Warning: No files were found with the provided path: release.zip
```

デプロイ時のエラー
```
Error: Unable to find any artifacts for the associated workflow
```

### コード


コードをよく見てみる。
今回のファイルはトップディレクトリではなくその下のbackendというディレクトリにてビルドを行っていた。
そのため、working-directoryとしてbackendというディレクトリを指定していたのだが、これに関連したミスをしていた。


```workflow.yml
（略）
build:
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: ./backend
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Setup Python version
        uses: actions/setup-python@v1
        with:
          python-version: ${{ env.PYTHON_VERSION }}

      - name: Create and start virtual environment
        run: |
          python -m venv venv
          source venv/bin/activate
      - name: Install dependencies
        run: pip install -r requirements.txt

      # Optional: Add step to run tests here

      - name: Zip artifact for deployment
        run: zip release.zip ./* -r

      - name: Upload artifact for deployment job
        uses: actions/upload-artifact@v3
        with:
          name: python-app
          path: |
            release.zip
            !venv/
  deploy:
    runs-on: ubuntu-latest
    needs: build
    environment:
      name: 'Production'
      url: ${{ steps.deploy-to-function.outputs.webapp-url }}

    steps:
      - name: Download artifact from build job
        uses: actions/download-artifact@v3
        with:
          name: python-app

      - name: Unzip artifact for deployment
        run: unzip release.zip
（略）
```

# 解決
artifactのアップロード部分について下記のように修正した。

Before
```yml
      - name: Upload artifact for deployment job
        uses: actions/upload-artifact@v3
        with:
          name: python-app
          path: |
            release.zip
            !venv/
```

After
```yml
      - name: Upload artifact for deployment job
        uses: actions/upload-artifact@v3
        with:
          name: python-app
          path: |
            ./backend/release.zip
            !venv/
```

Zip化したファイルに対してworking-directoryで指定したパスを付加した。


修正後ちゃんとデプロイまでうまくいった
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283544/ed587535-11ce-e564-3ebc-969d0d7c1a84.png)

ビルド時のデフォルトのworking-directoryを指定したので、ビルドのステップであればどんなときでもデフォルトのワーキングディレクトリで作業してもらっているのかと思いきや、落とし穴だった。
もっと精進する次第です(´；ω；｀)


以上でございました。